gale/gale/resource/Program.h

314 lines
14 KiB
C++

/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#ifndef __OPEN_GL__PROGRAM_H__
#define __OPEN_GL__PROGRAM_H__
#include <etk/types.h>
#include <etk/math/Vector4D.h>
#include <gale/debug.h>
#include <gale/renderer/openGL/openGL.h>
#include <gale/resource/Resource.h>
#include <gale/resource/Shader.h>
#include <gale/resource/VirtualBufferObject.h>
#include <etk/Color.h>
namespace gale {
namespace resource {
/**
* @brief In a openGL program we need some data to communicate with them, we register all the name requested by the user in this structure:
* @note Register all requested element permit to abstract the fact that some element does not exist and remove control of existance from upper code.
* This is important to note when the Program is reloaded the elements availlable can change.
* @not-in-doc
*/
class progAttributeElement {
public :
std::string m_name; //!< Name of the element
GLint m_elementId; //!< openGl Id if this element == > can not exist ==> @ref m_isLinked
bool m_isAttribute; //!< true if it was an attribute element, otherwite it was an uniform
bool m_isLinked; //!< if this element does not exist this is false
};
//! @not-in-doc
std::ostream& operator <<(std::ostream& _os, const gale::resource::progAttributeElement& _obj);
//! @not-in-doc
std::ostream& operator <<(std::ostream& _os, const std::vector<gale::resource::progAttributeElement>& _obj);
/**
* @brief Program is a compilation of some fragment Shader and vertex Shader. This construct automaticly this assiciation
* The input file must have the form : "myFile.prog"
* The data is simple :
* <pre>
* # Comment line ... paid attention at the space at the end of lines, they are considered like a part of the file ...
* # The folder is automaticly get from the program file basic folder
* filename1.vert
* filename2.frag
* filename3.vert
* filename4.frag
* </pre>
*/
class Program : public gale::Resource {
private :
bool m_exist; //!< the file existed
GLuint m_program; //!< openGL id of the current program
std::vector<std::shared_ptr<gale::resource::Shader>> m_shaderList; //!< List of all the shader loaded
std::vector<gale::resource::progAttributeElement> m_elementList; //!< List of all the attribute requested by the user
bool m_hasTexture; //!< A texture has been set to the current shader
bool m_hasTexture1; //!< A texture has been set to the current shader
protected:
/**
* @brief Contructor of an opengl Program.
* @param[in] filename Standard file name format. see @ref etk::FSNode
*/
Program();
void init(const std::string& _filename);
public:
DECLARE_RESOURCE_NAMED_FACTORY(Program);
/**
* @brief Destructor, remove the current Program.
*/
virtual ~Program();
public:
/**
* @brief Check If an Id is valid in the shader or not (sometime the shader have not some attribute, then we need to display some error)
* @return _idElem Id of the Attribute that might be sended.
* @return true The id is valid, false otherwise
*/
bool checkIdValidity(int32_t _idElem);
/**
* @brief User request an attribute on this program.
* @note The attribute is send to the fragment shaders
* @param[in] _elementName Name of the requested attribute.
* @return An abstract ID of the current attribute (this value is all time availlable, even if the program will be reloaded)
*/
int32_t getAttribute(std::string _elementName);
/**
* @brief Send attribute table to the spefified ID attribure (not send if does not really exist in the openGL program).
* @param[in] _idElem Id of the Attribute that might be sended.
* @param[in] _nbElement Specifies the number of elements that are to be modified.
* @param[in] _pointer Pointer on the data that might be sended.
* @param[in] _jumpBetweenSample Number of byte to jump between 2 vertex (this permit to enterlace informations)
*/
void sendAttribute(int32_t _idElem,
int32_t _nbElement,
const void* _pointer,
int32_t _jumpBetweenSample=0);
void sendAttributePointer(int32_t _idElem,
const std::shared_ptr<gale::resource::VirtualBufferObject>& _vbo,
int32_t _index,
int32_t _jumpBetweenSample=0,
int32_t _offset=0);
inline void sendAttribute(int32_t _idElem, const std::vector<vec2>& _data) {
sendAttribute(_idElem, 2/*u,v / x,y*/, &_data[0]);
}
inline void sendAttribute(int32_t _idElem, const std::vector<vec3>& _data) {
sendAttribute(_idElem, 3/*x,y,z,unused*/, &_data[0], 4*sizeof(btScalar));
}
inline void sendAttribute(int32_t _idElem, const std::vector<etk::Color<float>>& _data) {
sendAttribute(_idElem, 4/*r,g,b,a*/, &_data[0]);
}
inline void sendAttribute(int32_t _idElem, const std::vector<float>& _data) {
sendAttribute(_idElem, 1, &_data[0]);
}
/**
* @brief User request an Uniform on this program.
* @note uniform value is availlable for all the fragment shader in the program (only one value for all)
* @param[in] _elementName Name of the requested uniform.
* @return An abstract ID of the current uniform (this value is all time availlable, even if the program will be reloaded)
*/
int32_t getUniform(std::string _elementName);
/**
* @brief Send a uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _matrix Matrix that might be sended.
* @param[in] _transpose Transpose the matrix (needed all the taime in the normal openGl access (only not done in the openGL-ES2 due to the fact we must done it ourself)
*/
void uniformMatrix(int32_t _idElem, const mat4& _matrix, bool _transpose=true);
inline void uniform(int32_t _idElem, const etk::Color<float>& _value) {
uniform4f(_idElem, _value.r(), _value.g(), _value.b(), _value.a());
}
/**
* @brief Send 1 float uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
*/
void uniform1f(int32_t _idElem, float _value1);
/**
* @brief Send 2 float uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
*/
void uniform2f(int32_t _idElem, float _value1, float _value2);
/**
* @brief Send 3 float uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
* @param[in] _value3 Value to send at the Uniform
*/
void uniform3f(int32_t _idElem, float _value1, float _value2, float _value3);
/**
* @brief Send 4 float uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
* @param[in] _value3 Value to send at the Uniform
* @param[in] _value4 Value to send at the Uniform
*/
void uniform4f(int32_t _idElem, float _value1, float _value2, float _value3, float _value4);
/**
* @brief Send 1 signed integer uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
*/
void uniform1i(int32_t _idElem, int32_t _value1);
/**
* @brief Send 2 signed integer uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
*/
void uniform2i(int32_t _idElem, int32_t _value1, int32_t _value2);
/**
* @brief Send 3 signed integer uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
* @param[in] _value3 Value to send at the Uniform
*/
void uniform3i(int32_t _idElem, int32_t _value1, int32_t _value2, int32_t _value3);
/**
* @brief Send 4 signed integer uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _value1 Value to send at the Uniform
* @param[in] _value2 Value to send at the Uniform
* @param[in] _value3 Value to send at the Uniform
* @param[in] _value4 Value to send at the Uniform
*/
void uniform4i(int32_t _idElem, int32_t _value1, int32_t _value2, int32_t _value3, int32_t _value4);
/**
* @brief Send "vec1" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform1fv(int32_t _idElem, int32_t _nbElement, const float *_value);
/**
* @brief Send "vec2" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform2fv(int32_t _idElem, int32_t _nbElement, const float *_value);
/**
* @brief Send "vec3" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform3fv(int32_t _idElem, int32_t _nbElement, const float *_value);
/**
* @brief Send "vec4" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform4fv(int32_t _idElem, int32_t _nbElement, const float *_value);
/**
* @brief Send "ivec1" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform1iv(int32_t _idElem, int32_t _nbElement, const int32_t *_value);
/**
* @brief Send "ivec2" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the Attribute that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform2iv(int32_t _idElem, int32_t _nbElement, const int32_t *_value);
/**
* @brief Send "ivec3" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform3iv(int32_t _idElem, int32_t _nbElement, const int32_t *_value);
/**
* @brief Send "ivec4" uniform element to the spefified ID (not send if does not really exist in the openGL program)
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _nbElement Number of element sended
* @param[in] _value Pointer on the data
*/
void uniform4iv(int32_t _idElem, int32_t _nbElement, const int32_t *_value);
inline void uniform2(int32_t _idElem, const vec2& _value) {
uniform2fv(_idElem, 1, &_value.m_floats[0]);
};
inline void uniform3(int32_t _idElem, const vec3& _value) {
uniform3fv(_idElem, 1, &_value.m_floats[0]);
};
inline void uniform4(int32_t _idElem, const vec4& _value) {
uniform4fv(_idElem, 1, &_value.m_floats[0]);
};
inline void uniform2(int32_t _idElem, const ivec2& _value) {
uniform2iv(_idElem, 1, &_value.m_floats[0]);
};
inline void uniform3(int32_t _idElem, const ivec3& _value) {
uniform3iv(_idElem, 1, &_value.m_floats[0]);
};
inline void uniform4(int32_t _idElem, const ivec4& _value) {
uniform4iv(_idElem, 1, &_value.m_floats[0]);
};
/**
* @brief Request the processing of this program
*/
void use();
/**
* @brief set the testure Id on the specify uniform element.
* @param[in] _idElem Id of the uniform that might be sended.
* @param[in] _textureOpenGlID Real openGL texture ID
*/
void setTexture0(int32_t _idElem, GLint _textureOpenGlID);
void setTexture1(int32_t _idElem, GLint _textureOpenGlID);
/**
* @brief Stop the processing of this program
*/
void unUse();
/**
* @brief This load/reload the data in the opengl context, needed when removed previously.
*/
void updateContext();
/**
* @brief remove the data from the opengl context.
*/
void removeContext();
/**
* @brief Special android spec! It inform us that all context is removed and after notify us...
*/
void removeContextToLate();
/**
* @brief Relode the shader from the file. used when a request of resouces reload is done.
* @note this is really usefull when we tested the new themes or shader developpements.
*/
void reload();
private:
void checkGlError(const char* _op, int32_t _localLine, int32_t _idElem=-2);
};
};
};
#endif