diff options
author | chai <chaifix@163.com> | 2020-02-11 11:29:07 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2020-02-11 11:29:07 +0800 |
commit | 160e1299ef3d95f8e8c48706d7f61dd3dc6c6b60 (patch) | |
tree | abe5ae5242d9cc6caf6edf103e662c44e978fca0 /src/libjin/graphics/shaders | |
parent | e095043485d1d298571af6d9eca7f0db9009ea7a (diff) |
Diffstat (limited to 'src/libjin/graphics/shaders')
-rw-r--r-- | src/libjin/graphics/shaders/built-in/default.shader.h | 4 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/built-in/font.shader.h | 4 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/built-in/texture.shader.h | 4 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/jsl_compiler.cpp | 268 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/jsl_compiler.h | 78 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/shader.cpp | 592 | ||||
-rw-r--r-- | src/libjin/graphics/shaders/shader.h | 360 |
7 files changed, 655 insertions, 655 deletions
diff --git a/src/libjin/graphics/shaders/built-in/default.shader.h b/src/libjin/graphics/shaders/built-in/default.shader.h index 3f57c44..0a7267b 100644 --- a/src/libjin/graphics/shaders/built-in/default.shader.h +++ b/src/libjin/graphics/shaders/built-in/default.shader.h @@ -5,7 +5,7 @@ static const char* default_shader = R"( Vertex vert(Vertex v) { - return v; + return v; } #END_VERTEX_SHADER @@ -14,7 +14,7 @@ Vertex vert(Vertex v) Color frag(Color col, Texture tex, Vertex v) { - return col * texel(tex, v.uv); + return col * texel(tex, v.uv); } #END_FRAGMENT_SHADER diff --git a/src/libjin/graphics/shaders/built-in/font.shader.h b/src/libjin/graphics/shaders/built-in/font.shader.h index e04c225..9d15284 100644 --- a/src/libjin/graphics/shaders/built-in/font.shader.h +++ b/src/libjin/graphics/shaders/built-in/font.shader.h @@ -5,7 +5,7 @@ static const char* font_shader = R"( Vertex vert(Vertex v) { - return v; + return v; } #END_VERTEX_SHADER @@ -14,7 +14,7 @@ Vertex vert(Vertex v) Color frag(Color col, Texture tex, Vertex v) { - return Color(col.rgb, texel(tex, v.uv).a); + return Color(col.rgb, texel(tex, v.uv).a); } #END_FRAGMENT_SHADER diff --git a/src/libjin/graphics/shaders/built-in/texture.shader.h b/src/libjin/graphics/shaders/built-in/texture.shader.h index d1fc86f..9e4a545 100644 --- a/src/libjin/graphics/shaders/built-in/texture.shader.h +++ b/src/libjin/graphics/shaders/built-in/texture.shader.h @@ -5,7 +5,7 @@ static const char* texture_shader = R"( Vertex vert(Vertex v) { - return v; + return v; } #END_VERTEX_SHADER @@ -14,7 +14,7 @@ Vertex vert(Vertex v) Color frag(Color col, Texture tex, Vertex v) { - return col * texel(tex, v.uv); + return col * texel(tex, v.uv); } #END_FRAGMENT_SHADER diff --git a/src/libjin/graphics/shaders/jsl_compiler.cpp b/src/libjin/graphics/shaders/jsl_compiler.cpp index 44908e8..ea247c0 100644 --- a/src/libjin/graphics/shaders/jsl_compiler.cpp +++ b/src/libjin/graphics/shaders/jsl_compiler.cpp @@ -11,146 +11,146 @@ using namespace JinEngine::Filesystem; namespace JinEngine { - namespace Graphics - { - namespace Shaders - { + namespace Graphics + { + namespace Shaders + { - /// - /// Uniforms: - /// jin_ProjectionMatrix --+ - /// jin_ModelViewMatrix |- Uniforms - /// jin_MainTexture | - /// jin_RenderTargetSize | - /// jin_Time --+ - /// - /// Built-in variables in vertex shader: - /// jin_VertexCoords --+ - /// jin_TextureCoords |- Attributes - /// jin_VertexColor --+ - /// jin_Color ---- GLSL built in - /// - /// Built-in variables in fragment shader: - /// jin_Color --+ - /// jin_XY |- Inputs - /// jin_UV | - /// jin_COLOR --+ - /// + /// + /// Uniforms: + /// jin_ProjectionMatrix --+ + /// jin_ModelViewMatrix |- Uniforms + /// jin_MainTexture | + /// jin_RenderTargetSize | + /// jin_Time --+ + /// + /// Built-in variables in vertex shader: + /// jin_VertexCoords --+ + /// jin_TextureCoords |- Attributes + /// jin_VertexColor --+ + /// jin_Color ---- GLSL built in + /// + /// Built-in variables in fragment shader: + /// jin_Color --+ + /// jin_XY |- Inputs + /// jin_UV | + /// jin_COLOR --+ + /// - JinEngine::String SHADER_PROJECTION_MATRIX = "jin_ProjectionMatrix"; - JinEngine::String SHADER_MODELVIEW_MATRIX = "jin_ModelViewMatrix"; - JinEngine::String SHADER_MAIN_TEXTURE = "jin_MainTexture"; - JinEngine::String SHADER_VERTEX_COORDS = "jin_VertexCoords"; - JinEngine::String SHADER_TEXTURE_COORDS = "jin_TextureCoords"; - JinEngine::String SHADER_VERTEX_COLOR = "jin_VertexColor"; - JinEngine::String SHADER_TIME = "jin_Time"; - JinEngine::String SHADER_RENDERTARGET_SIZE = "jin_RenderTargetSize"; - JinEngine::String SHADER_VERSION = "#version 130 core \n"; - JinEngine::String SHADER_DEFINITIONS = - // Types - "#define Number float \n" - "#define Texture sampler2D \n" - "#define Canvas sampler2D \n" - "#define Color vec4 \n" - "#define Vec2 vec2 \n" - "#define Vec3 vec3 \n" - "#define Vec4 vec4 \n" - // Functions - "#define texel texture2D \n" - // Structs - "struct Vertex \n" - "{ \n" - " vec2 xy; \n" - " vec2 uv; \n" - " vec4 color; \n" - "}; \n" - "\n"; - JinEngine::String SHADER_UNIFORMS = - "uniform Texture " + SHADER_MAIN_TEXTURE + "; \n" // Main texture goes first. - "uniform mat4 " + SHADER_PROJECTION_MATRIX + "; \n" - "uniform mat4 " + SHADER_MODELVIEW_MATRIX + "; \n" - "uniform vec2 " + SHADER_TIME + "; \n" - "uniform vec2 " + SHADER_RENDERTARGET_SIZE + "; \n"; + JinEngine::String SHADER_PROJECTION_MATRIX = "jin_ProjectionMatrix"; + JinEngine::String SHADER_MODELVIEW_MATRIX = "jin_ModelViewMatrix"; + JinEngine::String SHADER_MAIN_TEXTURE = "jin_MainTexture"; + JinEngine::String SHADER_VERTEX_COORDS = "jin_VertexCoords"; + JinEngine::String SHADER_TEXTURE_COORDS = "jin_TextureCoords"; + JinEngine::String SHADER_VERTEX_COLOR = "jin_VertexColor"; + JinEngine::String SHADER_TIME = "jin_Time"; + JinEngine::String SHADER_RENDERTARGET_SIZE = "jin_RenderTargetSize"; + JinEngine::String SHADER_VERSION = "#version 130 core \n"; + JinEngine::String SHADER_DEFINITIONS = + // Types + "#define Number float \n" + "#define Texture sampler2D \n" + "#define Canvas sampler2D \n" + "#define Color vec4 \n" + "#define Vec2 vec2 \n" + "#define Vec3 vec3 \n" + "#define Vec4 vec4 \n" + // Functions + "#define texel texture2D \n" + // Structs + "struct Vertex \n" + "{ \n" + " vec2 xy; \n" + " vec2 uv; \n" + " vec4 color; \n" + "}; \n" + "\n"; + JinEngine::String SHADER_UNIFORMS = + "uniform Texture " + SHADER_MAIN_TEXTURE + "; \n" // Main texture goes first. + "uniform mat4 " + SHADER_PROJECTION_MATRIX + "; \n" + "uniform mat4 " + SHADER_MODELVIEW_MATRIX + "; \n" + "uniform vec2 " + SHADER_TIME + "; \n" + "uniform vec2 " + SHADER_RENDERTARGET_SIZE + "; \n"; - JinEngine::String JSLCompiler::formatVertexShader(const JinEngine::String& vert) - { - static JinEngine::String vert_part1 = - SHADER_VERSION + - SHADER_DEFINITIONS + - SHADER_UNIFORMS + - "in vec2 " + SHADER_VERTEX_COORDS + "; \n" - "in vec2 " + SHADER_TEXTURE_COORDS + "; \n" - "in vec4 " + SHADER_VERTEX_COLOR + "; \n"; // Color data in unsigned byte. - static JinEngine::String vert_part2 = - "\n" - "out vec4 jin_Color; \n" - "out vec2 jin_XY; \n" - "out vec2 jin_UV; \n" - "out vec4 jin_COLOR; \n" - "void main()\n" - "{\n" - " vec4 v = " + SHADER_MODELVIEW_MATRIX + " * vec4(" + SHADER_VERTEX_COORDS + ", 0, 1.0); \n" - " Vertex _v = vert(Vertex(v.xy, " + SHADER_TEXTURE_COORDS + ", " + SHADER_VERTEX_COLOR + ")); \n" - " gl_Position = " + SHADER_PROJECTION_MATRIX + " * vec4(_v.xy, 0, 1.0f); \n" - " jin_Color = gl_Color; \n" - " jin_XY = _v.xy; \n" - " jin_UV = _v.uv; \n" - " jin_COLOR = _v.color; \n" - "}"; - return vert_part1 + vert + vert_part2; - } + JinEngine::String JSLCompiler::formatVertexShader(const JinEngine::String& vert) + { + static JinEngine::String vert_part1 = + SHADER_VERSION + + SHADER_DEFINITIONS + + SHADER_UNIFORMS + + "in vec2 " + SHADER_VERTEX_COORDS + "; \n" + "in vec2 " + SHADER_TEXTURE_COORDS + "; \n" + "in vec4 " + SHADER_VERTEX_COLOR + "; \n"; // Color data in unsigned byte. + static JinEngine::String vert_part2 = + "\n" + "out vec4 jin_Color; \n" + "out vec2 jin_XY; \n" + "out vec2 jin_UV; \n" + "out vec4 jin_COLOR; \n" + "void main()\n" + "{\n" + " vec4 v = " + SHADER_MODELVIEW_MATRIX + " * vec4(" + SHADER_VERTEX_COORDS + ", 0, 1.0); \n" + " Vertex _v = vert(Vertex(v.xy, " + SHADER_TEXTURE_COORDS + ", " + SHADER_VERTEX_COLOR + ")); \n" + " gl_Position = " + SHADER_PROJECTION_MATRIX + " * vec4(_v.xy, 0, 1.0f); \n" + " jin_Color = gl_Color; \n" + " jin_XY = _v.xy; \n" + " jin_UV = _v.uv; \n" + " jin_COLOR = _v.color; \n" + "}"; + return vert_part1 + vert + vert_part2; + } - JinEngine::String JSLCompiler::formatFragmentShader(const JinEngine::String& frag) - { - static JinEngine::String frag_part1 = - SHADER_VERSION + - SHADER_DEFINITIONS + - SHADER_UNIFORMS + - "in vec4 jin_Color; \n" - "in vec2 jin_XY; \n" - "in vec2 jin_UV; \n" - "in vec4 jin_COLOR; \n"; - static JinEngine::String frag_part2 = - "\n" - "out vec4 jin_OutColor; \n" - "void main() \n" - "{ \n" - " jin_OutColor = frag(jin_Color, " + SHADER_MAIN_TEXTURE + ", Vertex(jin_XY, jin_UV, jin_COLOR)); \n" - "} \n"; - return frag_part1 + frag + frag_part2; - } + JinEngine::String JSLCompiler::formatFragmentShader(const JinEngine::String& frag) + { + static JinEngine::String frag_part1 = + SHADER_VERSION + + SHADER_DEFINITIONS + + SHADER_UNIFORMS + + "in vec4 jin_Color; \n" + "in vec2 jin_XY; \n" + "in vec2 jin_UV; \n" + "in vec4 jin_COLOR; \n"; + static JinEngine::String frag_part2 = + "\n" + "out vec4 jin_OutColor; \n" + "void main() \n" + "{ \n" + " jin_OutColor = frag(jin_Color, " + SHADER_MAIN_TEXTURE + ", Vertex(jin_XY, jin_UV, jin_COLOR)); \n" + "} \n"; + return frag_part1 + frag + frag_part2; + } - bool JSLCompiler::compile(const string& jsl, string* vertex_shader, string* fragment_shader) - { - // parse shader source, need some optimizations - int loc_VERTEX_SHADER = jsl.find("#VERTEX_SHADER"); - int loc_END_VERTEX_SHADER = jsl.find("#END_VERTEX_SHADER"); - int loc_FRAGMENT_SHADER = jsl.find("#FRAGMENT_SHADER"); - int loc_END_FRAGMENT_SHADER = jsl.find("#END_FRAGMENT_SHADER"); - if ( loc_VERTEX_SHADER == string::npos - || loc_END_VERTEX_SHADER == string::npos - || loc_FRAGMENT_SHADER == string::npos - || loc_END_FRAGMENT_SHADER == string::npos - ) - return false; - // Load vertex and fragment shader source into buffers. - { - // Compile JSL vertex program. - int start = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER"); - *vertex_shader = jsl.substr(start, loc_END_VERTEX_SHADER - start); - vertex_shader->assign(formatVertexShader(*vertex_shader)); - } - { - // Compile JSL fragment program. - int start = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER"); - *fragment_shader = jsl.substr(start, loc_END_FRAGMENT_SHADER - start); - fragment_shader->assign(formatFragmentShader(*fragment_shader)); - } - return true; - } + bool JSLCompiler::compile(const string& jsl, string* vertex_shader, string* fragment_shader) + { + // parse shader source, need some optimizations + int loc_VERTEX_SHADER = jsl.find("#VERTEX_SHADER"); + int loc_END_VERTEX_SHADER = jsl.find("#END_VERTEX_SHADER"); + int loc_FRAGMENT_SHADER = jsl.find("#FRAGMENT_SHADER"); + int loc_END_FRAGMENT_SHADER = jsl.find("#END_FRAGMENT_SHADER"); + if ( loc_VERTEX_SHADER == string::npos + || loc_END_VERTEX_SHADER == string::npos + || loc_FRAGMENT_SHADER == string::npos + || loc_END_FRAGMENT_SHADER == string::npos + ) + return false; + // Load vertex and fragment shader source into buffers. + { + // Compile JSL vertex program. + int start = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER"); + *vertex_shader = jsl.substr(start, loc_END_VERTEX_SHADER - start); + vertex_shader->assign(formatVertexShader(*vertex_shader)); + } + { + // Compile JSL fragment program. + int start = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER"); + *fragment_shader = jsl.substr(start, loc_END_FRAGMENT_SHADER - start); + fragment_shader->assign(formatFragmentShader(*fragment_shader)); + } + return true; + } - } // namespace Shaders - } // namespace Graphics + } // namespace Shaders + } // namespace Graphics } // namespace JinEngine #endif // (jin_graphics) && (jin_graphics & jin_graphics_shader)
\ No newline at end of file diff --git a/src/libjin/graphics/shaders/jsl_compiler.h b/src/libjin/graphics/shaders/jsl_compiler.h index ad3bdbb..f7aa48a 100644 --- a/src/libjin/graphics/shaders/jsl_compiler.h +++ b/src/libjin/graphics/shaders/jsl_compiler.h @@ -11,45 +11,45 @@ namespace JinEngine { - namespace Graphics - { - namespace Shaders - { - - extern JinEngine::String SHADER_PROJECTION_MATRIX; - extern JinEngine::String SHADER_MODELVIEW_MATRIX; - extern JinEngine::String SHADER_MAIN_TEXTURE; - extern JinEngine::String SHADER_VERTEX_COORDS; - extern JinEngine::String SHADER_TEXTURE_COORDS; - extern JinEngine::String SHADER_VERTEX_COLOR; - extern JinEngine::String SHADER_TIME; - extern JinEngine::String SHADER_RENDERTARGET_SIZE; - - /// - /// Compile JSL into GLSL. - /// - class JSLCompiler : public Singleton<JSLCompiler> - { - public: - /// - /// Compile JSL shader source into GLSL. - /// - /// @param jsl JSL shader source. - /// @param glsl_vertex Output of vertex glsl shader source. - /// @param glsl_fragment Output of fragment glsl shader source. - /// @return True if compile successful, otherwise return false. - /// - bool compile(const std::string& jsl, std::string* glsl_vertex, std::string* glsl_fragment); - - private: - JinEngine::String formatVertexShader(const JinEngine::String& vert); - - JinEngine::String formatFragmentShader(const JinEngine::String& frag); - - }; - - } // namespace Shaders - } // namespace Graphics + namespace Graphics + { + namespace Shaders + { + + extern JinEngine::String SHADER_PROJECTION_MATRIX; + extern JinEngine::String SHADER_MODELVIEW_MATRIX; + extern JinEngine::String SHADER_MAIN_TEXTURE; + extern JinEngine::String SHADER_VERTEX_COORDS; + extern JinEngine::String SHADER_TEXTURE_COORDS; + extern JinEngine::String SHADER_VERTEX_COLOR; + extern JinEngine::String SHADER_TIME; + extern JinEngine::String SHADER_RENDERTARGET_SIZE; + + /// + /// Compile JSL into GLSL. + /// + class JSLCompiler : public Singleton<JSLCompiler> + { + public: + /// + /// Compile JSL shader source into GLSL. + /// + /// @param jsl JSL shader source. + /// @param glsl_vertex Output of vertex glsl shader source. + /// @param glsl_fragment Output of fragment glsl shader source. + /// @return True if compile successful, otherwise return false. + /// + bool compile(const std::string& jsl, std::string* glsl_vertex, std::string* glsl_fragment); + + private: + JinEngine::String formatVertexShader(const JinEngine::String& vert); + + JinEngine::String formatFragmentShader(const JinEngine::String& frag); + + }; + + } // namespace Shaders + } // namespace Graphics } // namespace JinEngine #endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) 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 diff --git a/src/libjin/graphics/shaders/shader.h b/src/libjin/graphics/shaders/shader.h index e8756ac..c0e9086 100644 --- a/src/libjin/graphics/shaders/shader.h +++ b/src/libjin/graphics/shaders/shader.h @@ -17,186 +17,186 @@ namespace JinEngine { - namespace Graphics - { - namespace Shaders - { - - /// - /// Built in shader program. - /// - /// Built in shader program written with custom shading language called JSL (jin shading language). A - /// JSL program is compiled into glsl, so most glsl built in functions and structs are available in - /// JSL. - /// - class Shader : public Object - { - public: - /// - /// Shader constructor. - /// - Shader(const std::string& program); - - /// - /// Destructor of shader. - /// - virtual ~Shader(); - - /// - /// Prepare shader and set default uniforms. - /// - Shader& begin(); - - /// - /// End use shader. - /// - void end(); - - /// - /// Send float value to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param number Value of uniform variable to be sent. - /// - Shader& sendFloat(const char* name, float number); - - /// - /// Send texture to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param texture Texture to be sent. - /// - Shader& sendTexture(const char* name, const Texture* texture); - - /// - /// Send integer value to shader - /// - /// @param name Name of the uniform variable to be assigned. - /// @param value Value to be sent. - /// - Shader& sendInt(const char* name, int value); - - /// - /// Send 2D vector to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param x X value of the vector to be sent. - /// @param y Y value of the vector to be sent. - /// - Shader& sendVec2(const char* name, float x, float y); - - /// - /// Send 3D vector to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param x X value of the vector to be sent. - /// @param y Y value of the vector to be sent. - /// @param z Z value of the vector to be sent. - /// - Shader& sendVec3(const char* name, float x, float y, float z); - - /// - /// Send 4D vector to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param x X value of the vector to be sent. - /// @param y Y value of the vector to be sent. - /// @param z Z value of the vector to be sent. - /// @param w W value of the vector to be sent. - /// - Shader& sendVec4(const char* name, float x, float y, float z, float w); - - /// - /// Send canvas to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param canvas Canvas to be sent. - /// - Shader& sendCanvas(const char* name, const Canvas* canvas); - - /// - /// Send color to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param color Color to be sent. - /// - Shader& sendColor(const char* name, const Color* color); - - /// - /// Send 4 by 4 matrix to shader. - /// - /// @param name Name of the uniform variable to be assigned. - /// @param mat4 Matrix to be sent. - /// - Shader& sendMatrix4(const char* name, const Math::Matrix* mat4); - - /// - /// Set vertices value. - /// - /// @param n Number of vertices. - /// @param type Data type of each component in the array. - /// @param stride Byte offset between consecutive generic vertex attributes. - /// @param pointers Pointer to the first component of the first generic vertex attribute in the array. - /// - Shader& uploadVertices(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); - - /// - /// Set texture UV coordinates. - /// - /// @param n Number of vertices. - /// @param type Data type of each component in the array. - /// @param stride Byte offset between consecutive generic vertex attributes. - /// @param pointers Pointer to the first component of the first generic vertex attribute in the array. - /// - Shader& uploadUV(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); - - /// - /// Upload vertex color array. - /// - Shader& uploadColor(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); - - /// - /// Set attribute. - /// - Shader& uploadAttribute(const String& name, int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); - - /// - /// Program ID. - /// - inline GLuint getGLProgramID() { return mPID; }; - - protected: - /// - /// Get texture unit of the uniform texture. If not, assign one. - /// - /// @param name Name of the texture uniform variable. - /// @return Texture unit which texture variable be assigned. - /// - GLint claimTextureUnit(/*const std::string& name*/); - - GLint getUniformLocation(const char* uniforms); - - /// - /// Compile JSL program into GLSL source. - /// - /// @param program JSL source code. - /// @return Return true if compile successed, otherwise return false. - /// - bool compile(const std::string& program); - - //static GLint mTextureUnit; - static GLint mAttributeIndex; - - GLuint mPID; - //GLint mCurrentTextureUnit; - //std::map<std::string, GLint> mTextureUnits; - - std::map<std::string, GLint> mUniformsLocation; - - }; - - } // namespace Shaders - } // namespace Graphics + namespace Graphics + { + namespace Shaders + { + + /// + /// Built in shader program. + /// + /// Built in shader program written with custom shading language called JSL (jin shading language). A + /// JSL program is compiled into glsl, so most glsl built in functions and structs are available in + /// JSL. + /// + class Shader : public Object + { + public: + /// + /// Shader constructor. + /// + Shader(const std::string& program); + + /// + /// Destructor of shader. + /// + virtual ~Shader(); + + /// + /// Prepare shader and set default uniforms. + /// + Shader& begin(); + + /// + /// End use shader. + /// + void end(); + + /// + /// Send float value to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param number Value of uniform variable to be sent. + /// + Shader& sendFloat(const char* name, float number); + + /// + /// Send texture to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param texture Texture to be sent. + /// + Shader& sendTexture(const char* name, const Texture* texture); + + /// + /// Send integer value to shader + /// + /// @param name Name of the uniform variable to be assigned. + /// @param value Value to be sent. + /// + Shader& sendInt(const char* name, int value); + + /// + /// Send 2D vector to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param x X value of the vector to be sent. + /// @param y Y value of the vector to be sent. + /// + Shader& sendVec2(const char* name, float x, float y); + + /// + /// Send 3D vector to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param x X value of the vector to be sent. + /// @param y Y value of the vector to be sent. + /// @param z Z value of the vector to be sent. + /// + Shader& sendVec3(const char* name, float x, float y, float z); + + /// + /// Send 4D vector to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param x X value of the vector to be sent. + /// @param y Y value of the vector to be sent. + /// @param z Z value of the vector to be sent. + /// @param w W value of the vector to be sent. + /// + Shader& sendVec4(const char* name, float x, float y, float z, float w); + + /// + /// Send canvas to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param canvas Canvas to be sent. + /// + Shader& sendCanvas(const char* name, const Canvas* canvas); + + /// + /// Send color to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param color Color to be sent. + /// + Shader& sendColor(const char* name, const Color* color); + + /// + /// Send 4 by 4 matrix to shader. + /// + /// @param name Name of the uniform variable to be assigned. + /// @param mat4 Matrix to be sent. + /// + Shader& sendMatrix4(const char* name, const Math::Matrix* mat4); + + /// + /// Set vertices value. + /// + /// @param n Number of vertices. + /// @param type Data type of each component in the array. + /// @param stride Byte offset between consecutive generic vertex attributes. + /// @param pointers Pointer to the first component of the first generic vertex attribute in the array. + /// + Shader& uploadVertices(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); + + /// + /// Set texture UV coordinates. + /// + /// @param n Number of vertices. + /// @param type Data type of each component in the array. + /// @param stride Byte offset between consecutive generic vertex attributes. + /// @param pointers Pointer to the first component of the first generic vertex attribute in the array. + /// + Shader& uploadUV(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); + + /// + /// Upload vertex color array. + /// + Shader& uploadColor(int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); + + /// + /// Set attribute. + /// + Shader& uploadAttribute(const String& name, int n, GLenum type, GLsizei stride, const GLvoid * pointers, GLboolean normalized = GL_FALSE); + + /// + /// Program ID. + /// + inline GLuint getGLProgramID() { return mPID; }; + + protected: + /// + /// Get texture unit of the uniform texture. If not, assign one. + /// + /// @param name Name of the texture uniform variable. + /// @return Texture unit which texture variable be assigned. + /// + GLint claimTextureUnit(/*const std::string& name*/); + + GLint getUniformLocation(const char* uniforms); + + /// + /// Compile JSL program into GLSL source. + /// + /// @param program JSL source code. + /// @return Return true if compile successed, otherwise return false. + /// + bool compile(const std::string& program); + + //static GLint mTextureUnit; + static GLint mAttributeIndex; + + GLuint mPID; + //GLint mCurrentTextureUnit; + //std::map<std::string, GLint> mTextureUnits; + + std::map<std::string, GLint> mUniformsLocation; + + }; + + } // namespace Shaders + } // namespace Graphics } // namespace JinEngine #endif // (jin_graphics) && (jin_graphics & jin_graphics_shader) |