#if SPECIAL #include "main.h" #endif #include "gl_calls.h" // TODO(fox): Combine into one after fixing Mac/Windows blend mode slowdown. const char *DefaultVertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 Point;\n" "layout (location = 1) in vec2 aTexCoord;\n" "out vec2 TexCoord;\n" "uniform int VertexMode;\n" "uniform vec2 CompDimensions;\n" "uniform vec2 LayerDimensions;\n" "uniform vec2 ScreenDimensions;\n" "uniform vec2 Pos;\n" "uniform vec2 UIOffset;\n" "uniform vec2 UIZoom;\n" "uniform vec2 Anchor;\n" "uniform float Rad;\n" "uniform float Scale;\n" "void main()\n" "{\n" " if (VertexMode == 0) {\n" " gl_Position = vec4(Point, 1.0);\n" "} else {\n" " vec2 XRotation = vec2(cos(Rad), sin(Rad));\n" " vec2 YRotation = vec2(sin(Rad), -cos(Rad));\n" " vec2 XAxis = (Point.x - (Anchor.x * LayerDimensions.x)) * Scale * XRotation;\n" " vec2 YAxis = (Point.y - (Anchor.y * LayerDimensions.y)) * -Scale * YRotation;\n" " vec2 CompPoint = Pos + vec2(XAxis + YAxis);\n" " vec2 CompUV = CompPoint / CompDimensions;\n" " vec2 ScreenPoint = UIOffset + (CompUV * UIZoom);\n" " vec2 ScreenUV = ScreenPoint / ScreenDimensions;\n" " vec2 GL_Space = ScreenUV * 2 - vec2(1.0f, 1.0f);\n" " gl_Position = vec4(vec2(GL_Space.x, -GL_Space.y), 0.0f, 1.0);\n" "}\n" " TexCoord = aTexCoord;\n" "}\0"; const char *DefaultFragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "in vec2 TexCoord;\n" "uniform sampler2D Texture;\n" "uniform sampler2D Texture1;\n" "uniform int FragmentMode;\n" "uniform vec3 InputCol;\n" "void main()\n" "{\n" "vec4 Col = texture(Texture, TexCoord);\n" " if (FragmentMode == 0) {\n" " FragColor = Col;\n" "} else if (FragmentMode == 1) {\n" " FragColor = vec4(InputCol, Col.a);\n" "} else if (FragmentMode == 2) {\n" " FragColor = Col;\n" "}\n" "}\0"; #if 1 const char *BlendVertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec2 Point;\n" "layout (location = 1) in vec2 aTexCoord;\n" "layout (location = 2) in vec2 aTexCoordBlend;\n" "out vec2 TexCoord;\n" "out vec2 TexCoordBlend;\n" "uniform vec2 CompDimensions;\n" "uniform vec2 ScreenDimensions;\n" "uniform vec2 UIOffset;\n" "uniform vec2 UIZoom;\n" "void main()\n" "{\n" " vec2 GL_Space = Point * 2 - vec2(1.0f, 1.0f);\n" " gl_Position = vec4(vec2(GL_Space.x, -GL_Space.y), 0.0f, 1.0);\n" " TexCoord = aTexCoord;\n" " TexCoordBlend = aTexCoordBlend;\n" "}\0"; #else const char *BlendVertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec2 Point;\n" "layout (location = 1) in vec2 aTexCoord;\n" "layout (location = 2) in vec2 aTexCoordBlend;\n" "out vec2 TexCoord;\n" "out vec2 TexCoordBlend;\n" "uniform vec2 CompDimensions;\n" "uniform vec2 LayerDimensions;\n" "uniform vec2 ScreenDimensions;\n" "uniform vec2 Pos;\n" "uniform vec2 UIOffset;\n" "uniform vec2 UIZoom;\n" "uniform vec2 Anchor;\n" "uniform float Rad;\n" "uniform float Scale;\n" "void main()\n" "{\n" " vec2 XRotation = vec2(cos(Rad), sin(Rad));\n" " vec2 YRotation = vec2(sin(Rad), -cos(Rad));\n" " vec2 XAxis = (Point.x - (Anchor.x * LayerDimensions.x)) * Scale * XRotation;\n" " vec2 YAxis = (Point.y - (Anchor.y * LayerDimensions.y)) * -Scale * YRotation;\n" " vec2 CompPoint = Pos + vec2(XAxis + YAxis);\n" " vec2 CompUV = CompPoint / CompDimensions;\n" " vec2 ScreenPoint = UIOffset + (CompUV * UIZoom);\n" " vec2 ScreenUV = ScreenPoint / ScreenDimensions;\n" " vec2 GL_Space = ScreenUV * 2 - vec2(1.0f, 1.0f);\n" " gl_Position = vec4(vec2(GL_Space.x, -GL_Space.y), 0.0f, 1.0);\n" " TexCoord = aTexCoord;\n" " TexCoordBlend = aTexCoordBlend;\n" "}\0"; #endif // NOTE(fox): Is this slower than using multiple fragment shaders with less source code? // TODO(fox): Multiply and add can be optimized without the texture copy. const char *BlendFragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "in vec2 TexCoord;\n" "in vec2 TexCoordBlend;\n" "uniform sampler2D Texture;\n" "uniform sampler2D Texture1;\n" "uniform int BlendMode;\n" "uniform vec3 InputCol;\n" "uniform vec2 ScreenDimensions;\n" "void main()\n" "{\n" " vec2 NewCoord = gl_FragCoord.xy / ScreenDimensions;\n" " vec4 Col = texture(Texture, TexCoord);\n" " vec4 Dest = texture(Texture1, NewCoord);\n" " vec4 Blend = Dest;\n" " FragColor.a = Dest.a;\n" " switch (BlendMode)\n" " {\n" " case 0:\n" " {\n" " FragColor.a = Col.a;\n" " } break;\n" " case 1:\n" " {\n" " Blend = Dest * Col;\n" " } break;\n" " case 2:\n" " {\n" " Blend = 1.0f - ((1.0f - Dest) / Col);\n" " } break;\n" " case 3:\n" " {\n" " Blend = (Dest + Col) - 1.0f;\n" " } break;\n" " case 4:\n" " {\n" " Blend = Dest + Col;\n" " } break;\n" " case 5:\n" " {\n" " Blend = 1.0f - ((1.0f - Dest) * (1.0f - Col));\n" " } break;\n" " case 6:\n" " {\n" " Blend = 2.0f * Dest * Col;\n" " vec4 BlendSecond = 1.0f - (2.0f * (1.0f - Dest) * (1.0f - Col));\n" " Blend = mix(BlendSecond, Blend, lessThan(Dest, vec4(0.5)));\n" " } break;\n" " case 7:\n" " {\n" " Blend = ((1.0f - Col * 2) * Dest * Dest) + (Col * 2 * Dest);\n" " } break;\n" " case 8:\n" " {\n" " Blend = 2.0f * Dest * Col;\n" " vec4 BlendSecond = 1.0f - (2.0f * (1.0f - Dest) * (1.0f - Col));\n" " Blend = mix(BlendSecond, Blend, greaterThan(Dest, vec4(0.5)));\n" " } break;\n" " case 9:\n" " {\n" " Blend = Dest - Col;\n" " } break;\n" " case 10:\n" " {\n" " Blend = Dest / (Col + 0.001f);\n" " } break;\n" " case 11:\n" " {\n" " Blend = Col - Dest;\n" " vec4 BlendSecond = Dest - Col;\n" " Blend = mix(BlendSecond, Blend, greaterThan(Col - Dest, vec4(0.0f)));\n" " } break;\n" " }\n" " FragColor.rgb = Blend.rgb ;\n" "}\0"; static void GL_InitDefaultShader(uint32 *VertexShader, const char *VertexShaderSource, uint32 *FragmentShader, const char *FragmentShaderSource, uint32 *ShaderProgram) { *VertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(*VertexShader, 1, &VertexShaderSource, NULL); glCompileShader(*VertexShader); int success; char infoLog[512]; glGetShaderiv(*VertexShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(*VertexShader, 512, NULL, infoLog); printf("Vertex shader fail:\n %s", infoLog); } *FragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(*FragmentShader, 1, &FragmentShaderSource, NULL); glCompileShader(*FragmentShader); glGetShaderiv(*FragmentShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(*FragmentShader, 512, NULL, infoLog); printf("Fragment shader fail:\n %s", infoLog); } // Shader programs link both types of shaders together. *ShaderProgram = glCreateProgram(); glAttachShader(*ShaderProgram, *VertexShader); glAttachShader(*ShaderProgram, *FragmentShader); glLinkProgram(*ShaderProgram); glGetProgramiv(*ShaderProgram, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(*ShaderProgram, 512, NULL, infoLog); printf("Shader linkage fail:\n %s", infoLog); } } static void GL_InitDefaultVerts() { unsigned int GLIndices[] = { 0, 1, 3, 1, 2, 3 }; glGenVertexArrays(1, &DefaultVerts.VertexArrayObject); glGenBuffers(1, &DefaultVerts.ElementBufferObject); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, DefaultVerts.ElementBufferObject); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLIndices), GLIndices, GL_STATIC_DRAW); glGenBuffers(1, &DefaultVerts.VertexBufferObject); glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); glGenVertexArrays(1, &ShapeVerts.VertexArrayObject); glGenBuffers(1, &ShapeVerts.VertexBufferObject); } void GL_GenAndBindTexture(GLuint *GLTexture, int Width, int Height, int BytesPerPixel, void *BufferAddress) { glGenTextures(1, GLTexture); glBindTexture(GL_TEXTURE_2D, *GLTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); int ByteFlag = (BytesPerPixel == 4) ? GL_RGBA : GL_RGBA16; int ByteFlag2 = (BytesPerPixel == 4) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; glTexImage2D(GL_TEXTURE_2D, 0, ByteFlag, Width, Height, 0, GL_RGBA, ByteFlag2, BufferAddress); } static void GL_BindDefaultVertexArrays() { glBindVertexArray(DefaultVerts.VertexArrayObject); // Switch to main buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, DefaultVerts.ElementBufferObject); glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // texture coordinate (note the last parameter's offset) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); } void GL_InitHWBuffer(gl_effect_layer *Test) { glGenFramebuffers(1, &Test->FramebufferObject); glGenTextures(1, &Test->Texture); glGenRenderbuffers(1, &Test->Color_Renderbuffer); glGenRenderbuffers(1, &Test->Stencil_Renderbuffer); Test->Initialized = true; } void GL_DeleteHWBuffer(gl_effect_layer *Test) { glDeleteFramebuffers(1, &Test->FramebufferObject); glDeleteTextures(1, &Test->Texture); glDeleteRenderbuffers(1, &Test->Color_Renderbuffer); glDeleteRenderbuffers(1, &Test->Stencil_Renderbuffer); Test->Initialized = true; } static void GL_BlitStencil(gl_effect_layer *TestM, void *StrokeData, void *FillData, uint32 StrokeCount, uint32 FillCount, layer_transforms T, int Width, int Height, int BytesPerPixel, int L_Width, int L_Height,v4 StrokeCol, v4 FillCol, int RenderMode, int Vector, ImVec2 ViewportSize, ImVec2 UIPos, ImVec2 UIZoom, int StencilLayer, int Mode) { int Uniform = 0; Uniform = glGetUniformLocation(DefaultShaderProgram, "CompDimensions"); glUniform2f(Uniform, Width, Height); Uniform = glGetUniformLocation(DefaultShaderProgram, "LayerDimensions"); glUniform2f(Uniform, L_Width, L_Height); Uniform = glGetUniformLocation(DefaultShaderProgram, "ScreenDimensions"); glUniform2f(Uniform, ViewportSize.x, ViewportSize.y); Uniform = glGetUniformLocation(DefaultShaderProgram, "UIOffset"); glUniform2f(Uniform, UIPos.x, UIPos.y); Uniform = glGetUniformLocation(DefaultShaderProgram, "UIZoom"); glUniform2f(Uniform, UIZoom.x, UIZoom.y); Uniform = glGetUniformLocation(DefaultShaderProgram, "Pos"); glUniform2f(Uniform, T.x, T.y); Uniform = glGetUniformLocation(DefaultShaderProgram, "Anchor"); glUniform2f(Uniform, T.ax, T.ay); real32 Rad = (T.rotation * (PI / 180)); Uniform = glGetUniformLocation(DefaultShaderProgram, "Rad"); glUniform1f(Uniform, Rad); Uniform = glGetUniformLocation(DefaultShaderProgram, "Scale"); glUniform1f(Uniform, T.scale); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "InputCol"); glUniform3f(Uniform, 0, 0, 0); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glBindVertexArray(ShapeVerts.VertexArrayObject); glStencilFunc(GL_EQUAL, StencilLayer, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, Mode); glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * 4 * FillCount, FillData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glDrawArrays(GL_TRIANGLE_FAN, 0, FillCount); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindVertexArray(0); } static void GL_RasterizeShape2(gl_effect_layer *TestM, gl_effect_layer *TestM2, void *StrokeData, void *FillData, uint32 StrokeCount, uint32 FillCount, layer_transforms T, int Width, int Height, int BytesPerPixel, void *Bitmap, int L_Width, int L_Height,v4 StrokeCol, v4 FillCol, blend_mode BlendMode, int RenderMode, int Vector, ImVec2 ViewportSize, ImVec2 UIPos, ImVec2 UIZoom, v2 BlendMin, v2 BlendMax, int StencilLayer) { int Uniform = 0; uint32 ShaderProgram = DefaultShaderProgram; if (RenderMode & gl_renderflag_blend) { ShaderProgram = BlendShaderProgram; glUseProgram(BlendShaderProgram); } Uniform = glGetUniformLocation(ShaderProgram, "CompDimensions"); glUniform2f(Uniform, Width, Height); Uniform = glGetUniformLocation(ShaderProgram, "ScreenDimensions"); glUniform2f(Uniform, ViewportSize.x, ViewportSize.y); Uniform = glGetUniformLocation(ShaderProgram, "UIOffset"); glUniform2f(Uniform, UIPos.x, UIPos.y); Uniform = glGetUniformLocation(ShaderProgram, "UIZoom"); glUniform2f(Uniform, UIZoom.x, UIZoom.y); Uniform = glGetUniformLocation(ShaderProgram, "LayerDimensions"); glUniform2f(Uniform, L_Width, L_Height); Uniform = glGetUniformLocation(ShaderProgram, "Pos"); glUniform2f(Uniform, T.x, T.y); Uniform = glGetUniformLocation(ShaderProgram, "Anchor"); glUniform2f(Uniform, T.ax, T.ay); real32 Rad = (T.rotation * (PI / 180)); Uniform = glGetUniformLocation(ShaderProgram, "Rad"); glUniform1f(Uniform, Rad); Uniform = glGetUniformLocation(ShaderProgram, "Scale"); glUniform1f(Uniform, T.scale); // Concave shapes are fairly more costly than convex: we have to write to // the stencil buffer, but since we also are using it to mask out precomps, // every shape has to be drawn a second time to "clean up" the buffer. if (RenderMode & gl_renderflag_fill && !(RenderMode & gl_renderflag_convex)) { // disable color component writing and allow stencil writing using the shape layer's vertices glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glBindVertexArray(ShapeVerts.VertexArrayObject); glStencilFunc(GL_ALWAYS, 0, 0xFF); glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); glBindVertexArray(ShapeVerts.VertexArrayObject); glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * 4 * FillCount, FillData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glDrawArrays(GL_TRIANGLE_FAN, 0, FillCount); // --- // allow color component writing glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindVertexArray(DefaultVerts.VertexArrayObject); glStencilFunc(GL_EQUAL, StencilLayer + 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 0); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "InputCol"); glUniform3f(Uniform, FillCol.r, FillCol.g, FillCol.b); glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); // --- // TODO(fox): If this is the final method, add this optimization: shapes with // no precomps below them don't have to be drawn twice and can instead // get cleaned by setting StencilOp to GL_DECR. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glBindVertexArray(DefaultVerts.VertexArrayObject); glStencilFunc(GL_ALWAYS, 0, 0xFF); glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP); glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); glBindVertexArray(ShapeVerts.VertexArrayObject); glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * 4 * FillCount, FillData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glDrawArrays(GL_TRIANGLE_FAN, 0, FillCount); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } else if (RenderMode & gl_renderflag_texture) { GLuint Texture; int InitialTex1 = 0; if (RenderMode & gl_renderflag_blend) { glGenTextures(1, &Texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, Texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Bitmap); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, TestM2->FramebufferObject); glBlitFramebuffer(0, 0, 3200, 1720, 0, 0, 3200, 1720, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_FRAMEBUFFER, TestM->FramebufferObject); glGetIntegerv(GL_TEXTURE_BINDING_2D, &InitialTex1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, TestM2->Texture); glUniform1i(glGetUniformLocation(BlendShaderProgram, "Texture"), 0); glUniform1i(glGetUniformLocation(BlendShaderProgram, "Texture1"), 1); glUniform1i(glGetUniformLocation(BlendShaderProgram, "BlendMode"), BlendMode); } else { glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_2D, Texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Bitmap); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindVertexArray(ShapeVerts.VertexArrayObject); glStencilFunc(GL_EQUAL, StencilLayer, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); int VertRowSize = 4; if (!(RenderMode & gl_renderflag_blend)) { Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 2); } else { VertRowSize = 6; } glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * VertRowSize * FillCount, FillData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, VertRowSize * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, VertRowSize * sizeof(float), (void*)(2 * sizeof(float))); glEnableVertexAttribArray(1); if (RenderMode & gl_renderflag_blend) { glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, VertRowSize * sizeof(float), (void*)(4 * sizeof(float))); glEnableVertexAttribArray(2); } glDrawArrays(GL_TRIANGLE_FAN, 0, FillCount); if (RenderMode & gl_renderflag_blend) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, InitialTex1); glUseProgram(DefaultShaderProgram); } glActiveTexture(GL_TEXTURE0); glDeleteTextures(1, &Texture); } else if (RenderMode & gl_renderflag_fill) { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindVertexArray(ShapeVerts.VertexArrayObject); glStencilFunc(GL_EQUAL, StencilLayer, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "InputCol"); glUniform3f(Uniform, FillCol.r, FillCol.g, FillCol.b); glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * 4 * FillCount, FillData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); // glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); glDrawArrays(GL_TRIANGLE_FAN, 0, FillCount); } else { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } glBindVertexArray(0); // stroke component if (RenderMode & gl_renderflag_stroke) { glBindVertexArray(ShapeVerts.VertexArrayObject); Uniform = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); glUniform1i(Uniform, 1); Uniform = glGetUniformLocation(DefaultShaderProgram, "InputCol"); glUniform3f(Uniform, StrokeCol.r, StrokeCol.g, StrokeCol.b); glBindBuffer(GL_ARRAY_BUFFER, ShapeVerts.VertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(real32) * 4 * StrokeCount, StrokeData, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLE_STRIP, 0, StrokeCount); } } void GL_UpdateTexture2(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, uint16 BytesPerPixel, bool32 Multisample) { glViewport(0, 0, Width, Height); // int err; // err = glGetError(); Assert(err == 0); if (!Test->Initialized) { GL_InitHWBuffer(Test); } GLenum Target = GL_TEXTURE_2D; if (Multisample) Target = GL_TEXTURE_2D_MULTISAMPLE; int Depth = 0, StencilDepth = 0; if (BytesPerPixel == 4) { Depth = GL_RGBA8; StencilDepth = GL_STENCIL_INDEX8; } else if (BytesPerPixel == 8) { Depth = GL_RGBA16; StencilDepth = GL_STENCIL_INDEX16; } glBindTexture(Target, Test->Texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data); glTexParameteri(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer ); glRenderbufferStorage(GL_RENDERBUFFER, StencilDepth, Width, Height); glBindFramebuffer(GL_FRAMEBUFFER, Test->FramebufferObject); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Test->Texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, Test->Stencil_Renderbuffer); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { printf("incomplete framebuffer"); Assert(0); } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, uint16 BytesPerPixel, bool32 Multisample) { glViewport(0, 0, Width, Height); // int err; // err = glGetError(); Assert(err == 0); if (!Test->Initialized) { GL_InitHWBuffer(Test); } GLenum Target = GL_TEXTURE_2D; if (Multisample) Target = GL_TEXTURE_2D_MULTISAMPLE; glBindTexture(Target, Test->Texture); int Depth = 0, StencilDepth = 0; if (BytesPerPixel == 4) { Depth = GL_RGBA8; StencilDepth = GL_STENCIL_INDEX8; } else if (BytesPerPixel == 8) { Depth = GL_RGBA16; StencilDepth = GL_STENCIL_INDEX16; } if (Multisample) { // glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, Width, Height, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, Depth, Width, Height); glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer ); glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, StencilDepth, Width, Height ); } else { glTexParameteri(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, // GL_UNSIGNED_BYTE, Data); glBindTexture(GL_TEXTURE_2D, 0); glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, Depth, Width, Height); glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer ); glRenderbufferStorage(GL_RENDERBUFFER, StencilDepth, Width, Height ); } // glBindTexture(GL_TEXTURE_2D, Test->Texture); // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, // GL_UNSIGNED_BYTE, Data); // glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, Test->FramebufferObject); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Test->Color_Renderbuffer); // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RGBA, Test->Texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, Test->Stencil_Renderbuffer); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { printf("incomplete framebuffer"); Assert(0); } glBindFramebuffer(GL_FRAMEBUFFER, 0); } static uint16 Effect_GL_InitShader(const char *FragmentShaderEffectSource) { glShaderSource(DefaultVertexShader, 1, &DefaultVertexShaderSource, NULL); glCompileShader(DefaultVertexShader); int success; char infoLog[512]; glGetShaderiv(DefaultVertexShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(DefaultVertexShader, 512, NULL, infoLog); printf("Vertex shader fail:\n %s", infoLog); } uint32 FragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(FragmentShader, 1, &FragmentShaderEffectSource, NULL); glCompileShader(FragmentShader); glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(FragmentShader, 512, NULL, infoLog); printf("Fragment shader fail:\n %s", infoLog); } uint16 ShaderProgram = glCreateProgram(); glAttachShader(ShaderProgram, DefaultVertexShader); glAttachShader(ShaderProgram, FragmentShader); glLinkProgram(ShaderProgram); glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(ShaderProgram, 512, NULL, infoLog); printf("Shader linkage fail:\n %s", infoLog); } glDeleteShader(FragmentShader); glUseProgram(ShaderProgram); return ShaderProgram; }