aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/graphics/shaders/shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/graphics/shaders/shader.cpp')
-rw-r--r--src/libjin/graphics/shaders/shader.cpp592
1 files changed, 296 insertions, 296 deletions
diff --git a/src/libjin/graphics/shaders/shader.cpp b/src/libjin/graphics/shaders/shader.cpp
index 36f6603..44b2cb0 100644
--- a/src/libjin/graphics/shaders/shader.cpp
+++ b/src/libjin/graphics/shaders/shader.cpp
@@ -20,302 +20,302 @@ using namespace JinEngine::Time;
namespace JinEngine
{
- namespace Graphics
- {
- namespace Shaders
- {
-
- //
- // default_texture
- // base_shader
- // SHADER_FORMAT_SIZE
- // formatShader
- //
- #include "built-in/default.shader.h"
-
- //
- // https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value
- // The default value of a sampler variable is 0. From the GLSL 3.30 spec,
- // section "4.3.5 Uniforms":
- //
- // The link time initial value is either the value of the variable's
- // initializer, if present, or 0 if no initializer is present.Sampler
- // types cannot have initializers.
- //
- // Since a value of 0 means that it's sampling from texture unit 0, it will
- // work without ever setting the value as long as you bind your textures to
- // unit 0. This is well defined behavior.
- //
- // Since texture unit 0 is also the default until you call glActiveTexture()
- // with a value other than GL_TEXTURE0, it's very common to always use unit
- // 0 as long as shaders do not need more than one texture.Which means that
- // often times, setting the sampler uniforms is redundant for simple
- // applications.
- //
- // I would still prefer to always set the values.If nothing else, it makes
- // it clear to anybody reading your code that you really mean to sample from
- // texture unit 0, and did not just forget to set the value.
- //
- const int MAIN_TEXTURE_UNIT = 0;
-
- static GLint textureUnit = 0;
-
- GLint Shader::mAttributeIndex = 0;
-
- Shader::Shader(const string& program)
- {
- if (!compile(program))
- {
- jin_log_error("Compile jsl shader failed.");
- throw Exception("Compile jsl shader failed");
- }
- }
-
- Shader::~Shader()
- {
- if (gl.getShader() == this)
- gl.unuseShader();
- // Delete shader program.
- glDeleteShader(mPID);
- }
-
- Shader& Shader::begin()
- {
-
- textureUnit = MAIN_TEXTURE_UNIT;
-
- // Send uniforms.
- sendInt(SHADER_MAIN_TEXTURE, MAIN_TEXTURE_UNIT);
- sendVec2(SHADER_TIME, Time::getSecond(), Time::getDeltaTime());
- Canvas* rt = gl.getCanvas();
- if (rt == OpenGL::SCREEN)
- {
- sendVec2(SHADER_RENDERTARGET_SIZE, Window::get()->getW(), Window::get()->getH());
- }
- else if(rt != nullptr)
- {
- sendVec2(SHADER_RENDERTARGET_SIZE, rt->getWidth(), rt->getHeight());
- }
-
- gl.activeTextureUnit(MAIN_TEXTURE_UNIT);
-
- return *this;
- }
-
- void Shader::end()
- {
- // Reset attribute index.
- for (; mAttributeIndex > 0; --mAttributeIndex)
- glDisableVertexAttribArray(mAttributeIndex);
- }
-
- bool Shader::compile(const string& program)
- {
- string vertex_shader, fragment_shader;
- // Compile JSL shader source into GLSL shader source.
- JSLCompiler* compiler = JSLCompiler::get();
- if (!compiler->compile(program, &vertex_shader, &fragment_shader))
- {
- return false;
- }
-
- #define glsl(SHADER_MODE, SHADER, SRC) \
- do{ \
- const GLchar* src = SRC.c_str(); \
- glShaderSource(SHADER, 1, &src, NULL); \
- glCompileShader(SHADER); \
- GLint success; \
- glGetShaderiv(SHADER, GL_COMPILE_STATUS, &success); \
- if (success == GL_FALSE) \
- return false; \
- }while(0)
-
- // Compile vertex shader.
- GLuint vid = glCreateShader(GL_VERTEX_SHADER);
- glsl(GL_VERTEX_SHADER, vid, vertex_shader);
- // Compile fragment shader.
- GLuint fid = glCreateShader(GL_FRAGMENT_SHADER);
- glsl(GL_FRAGMENT_SHADER, fid, fragment_shader);
-
- #undef glsl
- // Create OpenGL shader program.
- mPID = glCreateProgram();
- glAttachShader(mPID, vid);
- glAttachShader(mPID, fid);
- glLinkProgram(mPID);
- GLint success;
- glGetProgramiv(mPID, GL_LINK_STATUS, &success);
- if (success == GL_FALSE)
- return false;
- }
-
- static inline GLint getMaxTextureUnits()
- {
- GLint maxTextureUnits = 0;
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
- return maxTextureUnits;
- }
-
- GLint Shader::claimTextureUnit(/*const std::string& name*/)
- {
- return textureUnit++;
- }
-
- GLint Shader::getUniformLocation(const char* uniform)
- {
- map<std::string, GLint>::iterator it = mUniformsLocation.find(uniform);
- if (it != mUniformsLocation.end())
- return it->second;
- GLint loc = glGetUniformLocation(mPID, uniform);
- mUniformsLocation.insert(pair<std::string, GLint>(uniform, loc));
- return loc;
- }
-
- #define check_jsl() \
- if (gl.getShader() != this) \
- return *this
-
- Shader & Shader::sendInt(const char* name, int value)
- {
- check_jsl();
- int loc = getUniformLocation(name);
- glUniform1i(loc, value);
- return *this;
- }
-
- Shader& Shader::sendFloat(const char* variable, float number)
- {
- check_jsl();
- int loc = getUniformLocation(variable);
- glUniform1f(loc, number);
- return *this;
- }
-
- //
- // https://www.douban.com/note/627332677/
- // struct TextureUnit
- // {
- // GLuint targetTexture1D;
- // GLuint targetTexture2D;
- // GLuint targetTexture3D;
- // GLuint targetTextureCube;
- // ...
- // };
- //
- // TextureUnit mTextureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
- // GLuint mCurrentTextureUnit = 0;
- //
- Shader& Shader::sendTexture(const char* variable, const Texture* tex)
- {
- check_jsl();
- GLint location = getUniformLocation(variable);
- if (location == -1)
- return *this;
- GLint unit = claimTextureUnit(/*variable*/);
- if (unit == 0)
- {
- // TODO: 쳣󶨵
- return *this;
- }
- gl.activeTextureUnit(unit);
- gl.bindTexture2D(tex->getGLTexture());
- glUniform1i(location, unit);
- gl.activeTextureUnit(MAIN_TEXTURE_UNIT);
- return *this;
- }
-
- Shader& Shader::sendCanvas(const char* variable, const Canvas* canvas)
- {
- check_jsl();
- GLint location = getUniformLocation(variable);
- if (location == -1)
- return *this;
- GLint unit = claimTextureUnit(/*variable*/);
- if (unit == 0)
- {
- // TODO: 쳣󶨵
- return *this;
- }
- glActiveTexture(GL_TEXTURE0 + unit);
- gl.bindTexture2D(canvas->getGLTexture());
- glUniform1i(location, unit);
-
- glActiveTexture(GL_TEXTURE0);
- return *this;
- }
-
- Shader& Shader::sendVec2(const char* name, float x, float y)
- {
- check_jsl();
- int loc = getUniformLocation(name);
- glUniform2f(loc, x, y);
- return *this;
- }
-
- Shader& Shader::sendVec3(const char* name, float x, float y, float z)
- {
- check_jsl();
- int loc = getUniformLocation(name);
- glUniform3f(loc, x, y, z);
- return *this;
- }
-
- Shader& Shader::sendVec4(const char* name, float x, float y, float z, float w)
- {
- check_jsl();
- int loc = getUniformLocation(name);
- glUniform4f(loc, x, y, z, w);
- return *this;
- }
-
- Shader& Shader::sendColor(const char* name, const Color* col)
- {
- check_jsl();
- int loc = getUniformLocation(name);
- glUniform4f(loc,
- col->r / 255.f,
- col->g / 255.f,
- col->b / 255.f,
- col->a / 255.f
- );
- return *this;
- }
-
- Shader& Shader::sendMatrix4(const char* name, const Math::Matrix* mat4)
- {
- int loc = getUniformLocation(name);
- glUniformMatrix4fv(loc, 1, GL_FALSE, mat4->getElements());
- return *this;
- }
-
- Shader& Shader::uploadVertices(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
- {
- uploadAttribute(SHADER_VERTEX_COORDS, n, type, stride, pointers, normalized);
- return *this;
- }
-
- Shader& Shader::uploadUV(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
- {
- uploadAttribute(SHADER_TEXTURE_COORDS, n, type, stride, pointers, normalized);
- return *this;
- }
-
- Shader& Shader::uploadColor(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
- {
- uploadAttribute(SHADER_VERTEX_COLOR, n, type, stride, pointers, normalized);
- return *this;
- }
-
- Shader& Shader::uploadAttribute(const String& name, int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
- {
- GLint loc = glGetAttribLocation(mPID, name);
- glEnableVertexAttribArray(mAttributeIndex++);
- glVertexAttribPointer(loc, n, type, normalized, stride, pointers);
- return *this;
- }
-
- } // namespace Shaders
- } // namespace Graphics
+ namespace Graphics
+ {
+ namespace Shaders
+ {
+
+ //
+ // default_texture
+ // base_shader
+ // SHADER_FORMAT_SIZE
+ // formatShader
+ //
+ #include "built-in/default.shader.h"
+
+ //
+ // https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value
+ // The default value of a sampler variable is 0. From the GLSL 3.30 spec,
+ // section "4.3.5 Uniforms":
+ //
+ // The link time initial value is either the value of the variable's
+ // initializer, if present, or 0 if no initializer is present.Sampler
+ // types cannot have initializers.
+ //
+ // Since a value of 0 means that it's sampling from texture unit 0, it will
+ // work without ever setting the value as long as you bind your textures to
+ // unit 0. This is well defined behavior.
+ //
+ // Since texture unit 0 is also the default until you call glActiveTexture()
+ // with a value other than GL_TEXTURE0, it's very common to always use unit
+ // 0 as long as shaders do not need more than one texture.Which means that
+ // often times, setting the sampler uniforms is redundant for simple
+ // applications.
+ //
+ // I would still prefer to always set the values.If nothing else, it makes
+ // it clear to anybody reading your code that you really mean to sample from
+ // texture unit 0, and did not just forget to set the value.
+ //
+ const int MAIN_TEXTURE_UNIT = 0;
+
+ static GLint textureUnit = 0;
+
+ GLint Shader::mAttributeIndex = 0;
+
+ Shader::Shader(const string& program)
+ {
+ if (!compile(program))
+ {
+ jin_log_error("Compile jsl shader failed.");
+ throw Exception("Compile jsl shader failed");
+ }
+ }
+
+ Shader::~Shader()
+ {
+ if (gl.getShader() == this)
+ gl.unuseShader();
+ // Delete shader program.
+ glDeleteShader(mPID);
+ }
+
+ Shader& Shader::begin()
+ {
+
+ textureUnit = MAIN_TEXTURE_UNIT;
+
+ // Send uniforms.
+ sendInt(SHADER_MAIN_TEXTURE, MAIN_TEXTURE_UNIT);
+ sendVec2(SHADER_TIME, Time::getSecond(), Time::getDeltaTime());
+ Canvas* rt = gl.getCanvas();
+ if (rt == OpenGL::SCREEN)
+ {
+ sendVec2(SHADER_RENDERTARGET_SIZE, Window::get()->getW(), Window::get()->getH());
+ }
+ else if(rt != nullptr)
+ {
+ sendVec2(SHADER_RENDERTARGET_SIZE, rt->getWidth(), rt->getHeight());
+ }
+
+ gl.activeTextureUnit(MAIN_TEXTURE_UNIT);
+
+ return *this;
+ }
+
+ void Shader::end()
+ {
+ // Reset attribute index.
+ for (; mAttributeIndex > 0; --mAttributeIndex)
+ glDisableVertexAttribArray(mAttributeIndex);
+ }
+
+ bool Shader::compile(const string& program)
+ {
+ string vertex_shader, fragment_shader;
+ // Compile JSL shader source into GLSL shader source.
+ JSLCompiler* compiler = JSLCompiler::get();
+ if (!compiler->compile(program, &vertex_shader, &fragment_shader))
+ {
+ return false;
+ }
+
+ #define glsl(SHADER_MODE, SHADER, SRC) \
+ do{ \
+ const GLchar* src = SRC.c_str(); \
+ glShaderSource(SHADER, 1, &src, NULL); \
+ glCompileShader(SHADER); \
+ GLint success; \
+ glGetShaderiv(SHADER, GL_COMPILE_STATUS, &success); \
+ if (success == GL_FALSE) \
+ return false; \
+ }while(0)
+
+ // Compile vertex shader.
+ GLuint vid = glCreateShader(GL_VERTEX_SHADER);
+ glsl(GL_VERTEX_SHADER, vid, vertex_shader);
+ // Compile fragment shader.
+ GLuint fid = glCreateShader(GL_FRAGMENT_SHADER);
+ glsl(GL_FRAGMENT_SHADER, fid, fragment_shader);
+
+ #undef glsl
+ // Create OpenGL shader program.
+ mPID = glCreateProgram();
+ glAttachShader(mPID, vid);
+ glAttachShader(mPID, fid);
+ glLinkProgram(mPID);
+ GLint success;
+ glGetProgramiv(mPID, GL_LINK_STATUS, &success);
+ if (success == GL_FALSE)
+ return false;
+ }
+
+ static inline GLint getMaxTextureUnits()
+ {
+ GLint maxTextureUnits = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ return maxTextureUnits;
+ }
+
+ GLint Shader::claimTextureUnit(/*const std::string& name*/)
+ {
+ return textureUnit++;
+ }
+
+ GLint Shader::getUniformLocation(const char* uniform)
+ {
+ map<std::string, GLint>::iterator it = mUniformsLocation.find(uniform);
+ if (it != mUniformsLocation.end())
+ return it->second;
+ GLint loc = glGetUniformLocation(mPID, uniform);
+ mUniformsLocation.insert(pair<std::string, GLint>(uniform, loc));
+ return loc;
+ }
+
+ #define check_jsl() \
+ if (gl.getShader() != this) \
+ return *this
+
+ Shader & Shader::sendInt(const char* name, int value)
+ {
+ check_jsl();
+ int loc = getUniformLocation(name);
+ glUniform1i(loc, value);
+ return *this;
+ }
+
+ Shader& Shader::sendFloat(const char* variable, float number)
+ {
+ check_jsl();
+ int loc = getUniformLocation(variable);
+ glUniform1f(loc, number);
+ return *this;
+ }
+
+ //
+ // https://www.douban.com/note/627332677/
+ // struct TextureUnit
+ // {
+ // GLuint targetTexture1D;
+ // GLuint targetTexture2D;
+ // GLuint targetTexture3D;
+ // GLuint targetTextureCube;
+ // ...
+ // };
+ //
+ // TextureUnit mTextureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]
+ // GLuint mCurrentTextureUnit = 0;
+ //
+ Shader& Shader::sendTexture(const char* variable, const Texture* tex)
+ {
+ check_jsl();
+ GLint location = getUniformLocation(variable);
+ if (location == -1)
+ return *this;
+ GLint unit = claimTextureUnit(/*variable*/);
+ if (unit == 0)
+ {
+ // TODO: 쳣󶨵
+ return *this;
+ }
+ gl.activeTextureUnit(unit);
+ gl.bindTexture2D(tex->getGLTexture());
+ glUniform1i(location, unit);
+ gl.activeTextureUnit(MAIN_TEXTURE_UNIT);
+ return *this;
+ }
+
+ Shader& Shader::sendCanvas(const char* variable, const Canvas* canvas)
+ {
+ check_jsl();
+ GLint location = getUniformLocation(variable);
+ if (location == -1)
+ return *this;
+ GLint unit = claimTextureUnit(/*variable*/);
+ if (unit == 0)
+ {
+ // TODO: 쳣󶨵
+ return *this;
+ }
+ glActiveTexture(GL_TEXTURE0 + unit);
+ gl.bindTexture2D(canvas->getGLTexture());
+ glUniform1i(location, unit);
+
+ glActiveTexture(GL_TEXTURE0);
+ return *this;
+ }
+
+ Shader& Shader::sendVec2(const char* name, float x, float y)
+ {
+ check_jsl();
+ int loc = getUniformLocation(name);
+ glUniform2f(loc, x, y);
+ return *this;
+ }
+
+ Shader& Shader::sendVec3(const char* name, float x, float y, float z)
+ {
+ check_jsl();
+ int loc = getUniformLocation(name);
+ glUniform3f(loc, x, y, z);
+ return *this;
+ }
+
+ Shader& Shader::sendVec4(const char* name, float x, float y, float z, float w)
+ {
+ check_jsl();
+ int loc = getUniformLocation(name);
+ glUniform4f(loc, x, y, z, w);
+ return *this;
+ }
+
+ Shader& Shader::sendColor(const char* name, const Color* col)
+ {
+ check_jsl();
+ int loc = getUniformLocation(name);
+ glUniform4f(loc,
+ col->r / 255.f,
+ col->g / 255.f,
+ col->b / 255.f,
+ col->a / 255.f
+ );
+ return *this;
+ }
+
+ Shader& Shader::sendMatrix4(const char* name, const Math::Matrix* mat4)
+ {
+ int loc = getUniformLocation(name);
+ glUniformMatrix4fv(loc, 1, GL_FALSE, mat4->getElements());
+ return *this;
+ }
+
+ Shader& Shader::uploadVertices(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
+ {
+ uploadAttribute(SHADER_VERTEX_COORDS, n, type, stride, pointers, normalized);
+ return *this;
+ }
+
+ Shader& Shader::uploadUV(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
+ {
+ uploadAttribute(SHADER_TEXTURE_COORDS, n, type, stride, pointers, normalized);
+ return *this;
+ }
+
+ Shader& Shader::uploadColor(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
+ {
+ uploadAttribute(SHADER_VERTEX_COLOR, n, type, stride, pointers, normalized);
+ return *this;
+ }
+
+ Shader& Shader::uploadAttribute(const String& name, int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized)
+ {
+ GLint loc = glGetAttribLocation(mPID, name);
+ glEnableVertexAttribArray(mAttributeIndex++);
+ glVertexAttribPointer(loc, n, type, normalized, stride, pointers);
+ return *this;
+ }
+
+ } // namespace Shaders
+ } // namespace Graphics
} // namespace JinEngine
#endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) \ No newline at end of file