diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index f2a42e5..585771f 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -31,6 +31,7 @@ + diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index f336d63..a26ea52 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -86,6 +86,9 @@ Header Files + + Header Files + diff --git a/inc/opengl.h b/inc/opengl.h index 5549a44..f3f19ba 100644 --- a/inc/opengl.h +++ b/inc/opengl.h @@ -54,6 +54,9 @@ extern PFNGLBINDBUFFERPROC glBindBuffer; extern PFNGLBUFFERDATAPROC glBufferData; extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; +extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; extern PFNGLACTIVETEXTUREPROC glActiveTexture; diff --git a/inc/paletteshader.h b/inc/paletteshader.h new file mode 100644 index 0000000..47076c5 --- /dev/null +++ b/inc/paletteshader.h @@ -0,0 +1,99 @@ +// old + +const GLchar *PassthroughVertShader110Src = + "#version 110\n" + "varying vec2 TexCoord0; \n" + "\n" + "void main(void)\n" + "{\n" + " gl_Position = ftransform(); \n" + " TexCoord0 = gl_MultiTexCoord0.xy; \n" + "}\n"; + +const GLchar *PaletteFragShader110Src = + "#version 110\n" + "uniform sampler2D PaletteTex; \n" + "uniform sampler2D SurfaceTex; \n" + "varying vec2 TexCoord0; \n" + "\n" + "void main()\n" + "{\n" + " vec4 index = texture2D(SurfaceTex, TexCoord0); \n" + " vec4 texel = texture2D(PaletteTex, index.xy); \n" + " gl_FragColor = texel;\n" + "}\n"; + + +// new + +const GLchar *PassthroughVertShaderSrc = + "#if __VERSION__ >= 130\n" + "#define COMPAT_VARYING out\n" + "#define COMPAT_ATTRIBUTE in\n" + "#define COMPAT_TEXTURE texture\n" + "#else\n" + "#define COMPAT_VARYING varying \n" + "#define COMPAT_ATTRIBUTE attribute \n" + "#define COMPAT_TEXTURE texture2D\n" + "#endif\n" + "\n" + "#ifdef GL_ES\n" + "#define COMPAT_PRECISION mediump\n" + "#else\n" + "#define COMPAT_PRECISION\n" + "#endif\n" + "\n" + "COMPAT_ATTRIBUTE vec4 VertexCoord;\n" + "COMPAT_ATTRIBUTE vec4 COLOR;\n" + "COMPAT_ATTRIBUTE vec4 TexCoord;\n" + "COMPAT_VARYING vec4 COL0;\n" + "COMPAT_VARYING vec4 TEX0;\n" + "\n" + "vec4 _oPosition1; \n" + "uniform mat4 MVPMatrix;\n" + "\n" + "void main()\n" + "{\n" + " vec4 _oColor;\n" + " vec2 _otexCoord;\n" + " gl_Position = VertexCoord.x * MVPMatrix[0] + VertexCoord.y * MVPMatrix[1] + VertexCoord.z * MVPMatrix[2] + VertexCoord.w * MVPMatrix[3];\n" + " _oPosition1 = gl_Position;\n" + " _oColor = COLOR;\n" + " _otexCoord = TexCoord.xy;\n" + " COL0 = COLOR;\n" + " TEX0.xy = TexCoord.xy;\n" + "}\n"; + + +const GLchar *PaletteFragShaderSrc = + "#if __VERSION__ >= 130\n" + "#define COMPAT_VARYING in\n" + "#define COMPAT_TEXTURE texture\n" + "out vec4 FragColor;\n" + "#else\n" + "#define COMPAT_VARYING varying\n" + "#define FragColor gl_FragColor\n" + "#define COMPAT_TEXTURE texture2D\n" + "#endif\n" + "\n" + "#ifdef GL_ES\n" + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "precision highp float;\n" + "#else\n" + "precision mediump float;\n" + "#endif\n" + "#define COMPAT_PRECISION mediump\n" + "#else\n" + "#define COMPAT_PRECISION\n" + "#endif\n" + "\n" + "uniform sampler2D PaletteTex;\n" + "uniform sampler2D SurfaceTex;\n" + "COMPAT_VARYING vec4 TEX0;\n" + "\n" + "void main()\n" + "{\n" + " vec4 index = COMPAT_TEXTURE(SurfaceTex, TEX0.xy);\n" + " vec4 texel = COMPAT_TEXTURE(PaletteTex, index.xy);\n" + " FragColor = texel;\n" + "}\n"; diff --git a/src/opengl.c b/src/opengl.c index 308be31..1c60fdb 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -49,6 +49,9 @@ PFNGLBINDBUFFERPROC glBindBuffer = NULL; PFNGLBUFFERDATAPROC glBufferData = NULL; PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL; PFNGLDELETEBUFFERSPROC glDeleteBuffers = NULL; +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL; PFNGLACTIVETEXTUREPROC glActiveTexture = NULL; @@ -105,6 +108,9 @@ void OpenGL_Init() glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData"); glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer"); glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers"); + glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays"); + glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray"); + glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)wglGetProcAddress("glDeleteVertexArrays"); glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture"); diff --git a/src/render.c b/src/render.c index b7722f7..f52a6c5 100644 --- a/src/render.c +++ b/src/render.c @@ -20,29 +20,7 @@ #include "opengl.h" #include "main.h" #include "surface.h" - -const GLchar *PassthroughVertShaderSrc = - "#version 110\n" - "varying vec2 TexCoord0; \n" - "\n" - "void main(void)\n" - "{\n" - " gl_Position = ftransform(); \n" - " TexCoord0 = gl_MultiTexCoord0.xy; \n" - "}\n"; - -const GLchar *PaletteFragShaderSrc = - "#version 110\n" - "uniform sampler2D PaletteTex; \n" - "uniform sampler2D SurfaceTex; \n" - "varying vec2 TexCoord0; \n" - "\n" - "void main()\n" - "{\n" - " vec4 index = texture2D(SurfaceTex, TexCoord0); \n" - " vec4 texel = texture2D(PaletteTex, index.xy); \n" - " gl_FragColor = texel;\n" - "}\n"; +#include "paletteshader.h" BOOL detect_cutscene(); @@ -108,15 +86,21 @@ DWORD WINAPI render_main(void) int tex_size = tex_width * tex_height * sizeof(int); int *tex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tex_size); - GLuint paletteConvProgram = 0; - if (glGetUniformLocation && glActiveTexture && glUniform1i) - paletteConvProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc); - - GLuint scaleProgram = 0; - if (glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glDrawBuffers && + BOOL got30 = glGenFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glDrawBuffers && glCheckFramebufferStatus && glUniform4f && glActiveTexture && glUniform1i && glGetAttribLocation && glGenBuffers && glBindBuffer && glBufferData && glVertexAttribPointer && - glEnableVertexAttribArray && glUniform2fv && glUniformMatrix4fv) + glEnableVertexAttribArray && glUniform2fv && glUniformMatrix4fv && glGenVertexArrays && glBindVertexArray; + + BOOL got20 = glGetUniformLocation && glActiveTexture && glUniform1i; + + GLuint paletteConvProgram = 0; + if (got30) + paletteConvProgram = OpenGL_BuildProgram(PassthroughVertShaderSrc, PaletteFragShaderSrc); + else if (got20) + paletteConvProgram = OpenGL_BuildProgram(PassthroughVertShader110Src, PaletteFragShader110Src); + + GLuint scaleProgram = 0; + if (got30) scaleProgram = OpenGL_BuildProgramFromFile(ddraw->shader); // primary surface texture @@ -158,30 +142,96 @@ DWORD WINAPI render_main(void) ddraw->render.viewport.x, ddraw->render.viewport.y, ddraw->render.viewport.width, ddraw->render.viewport.height); - GLint surfaceUniLoc = -1, paletteUniLoc = -1; + + GLint surfaceUniLoc = -1, paletteUniLoc = -1, mainTexCoordAttrLoc = -1; + GLuint mainVbos[3], mainVao; if (paletteConvProgram) { surfaceUniLoc = glGetUniformLocation(paletteConvProgram, "SurfaceTex"); paletteUniLoc = glGetUniformLocation(paletteConvProgram, "PaletteTex"); + + if (got30) + { + glUseProgram(paletteConvProgram); + + GLint vertexCoordAttrLoc = glGetAttribLocation(paletteConvProgram, "VertexCoord"); + mainTexCoordAttrLoc = glGetAttribLocation(paletteConvProgram, "TexCoord"); + + glGenBuffers(3, mainVbos); + + glBindBuffer(GL_ARRAY_BUFFER, mainVbos[0]); + if (scaleProgram) + { + glBindBuffer(GL_ARRAY_BUFFER, mainVbos[0]); + static const GLfloat vertexCoordPal[] = { + -1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordPal), vertexCoordPal, GL_STATIC_DRAW); + } + else + { + static const GLfloat vertexCoord[] = { + -1.0f, 1.0f, + 1.0f, 1.0f, + 1.0f,-1.0f, + -1.0f,-1.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &mainVao); + glBindVertexArray(mainVao); + + glBindBuffer(GL_ARRAY_BUFFER, mainVbos[0]); + glVertexAttribPointer(vertexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(vertexCoordAttrLoc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mainVbos[2]); + static const GLushort indices[] = + { + 0, 1, 2, + 0, 2, 3, + }; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glUniform4f(glGetAttribLocation(paletteConvProgram, "Color"), 1, 1, 1, 1); + + const float mvpMatrix[16] = { + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1, + }; + glUniformMatrix4fv(glGetUniformLocation(paletteConvProgram, "MVPMatrix"), 1, GL_FALSE, mvpMatrix); + + } } - GLint textureUniLoc = -1, texCoordAttrLoc = -1, frameCountUniLoc = -1; + GLint textureUniLoc = -1, scaleTexCoordAttrLoc = -1, frameCountUniLoc = -1; GLuint frameBufferId = 0; GLuint frameBufferTexId = 0; - GLuint vboBuffers[3]; + GLuint scaleVbos[3], scaleVao; if (scaleProgram) { glUseProgram(scaleProgram); GLint vertexCoordAttrLoc = glGetAttribLocation(scaleProgram, "VertexCoord"); - texCoordAttrLoc = glGetAttribLocation(scaleProgram, "TexCoord"); + scaleTexCoordAttrLoc = glGetAttribLocation(scaleProgram, "TexCoord"); textureUniLoc = glGetUniformLocation(scaleProgram, "Texture"); frameCountUniLoc = glGetUniformLocation(scaleProgram, "FrameCount"); - glGenBuffers(3, vboBuffers); + glGenBuffers(3, scaleVbos); - glBindBuffer(GL_ARRAY_BUFFER, vboBuffers[0]); + glBindBuffer(GL_ARRAY_BUFFER, scaleVbos[0]); static const GLfloat vertexCoord[] = { -1.0f, 1.0f, 1.0f, 1.0f, @@ -189,10 +239,17 @@ DWORD WINAPI render_main(void) -1.0f,-1.0f, }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoord), vertexCoord, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &scaleVao); + glBindVertexArray(scaleVao); + + glBindBuffer(GL_ARRAY_BUFFER, scaleVbos[0]); glVertexAttribPointer(vertexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(vertexCoordAttrLoc); + glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboBuffers[2]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scaleVbos[2]); static const GLushort indices[] = { 0, 1, 2, @@ -200,7 +257,7 @@ DWORD WINAPI render_main(void) }; glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); float inputSize[2], outputSize[2], textureSize[2]; @@ -254,7 +311,10 @@ DWORD WINAPI render_main(void) scaleProgram = 0; if (glDeleteBuffers) - glDeleteBuffers(3, vboBuffers); + glDeleteBuffers(3, scaleVbos); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &scaleVao); } glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -356,48 +416,63 @@ DWORD WINAPI render_main(void) glActiveTexture(GL_TEXTURE0); } - if (scaleProgram) + if (scaleProgram && paletteConvProgram) { // draw surface into framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); - - glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, ddraw->width, ddraw->height); - glBegin(GL_TRIANGLE_FAN); - glTexCoord2f(0, 0); glVertex2f(-1, -1); - glTexCoord2f(0, scale_h); glVertex2f(-1, 1); - glTexCoord2f(scale_w, scale_h); glVertex2f(1, 1); - glTexCoord2f(scale_w, 0); glVertex2f(1, -1); - glEnd(); + glBindVertexArray(mainVao); + + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId); + + glBindBuffer(GL_ARRAY_BUFFER, mainVbos[1]); + + GLfloat texCoordPal[] = { + 0.0f, 0.0f, + 0.0f, scale_h, + scale_w, scale_h, + scale_w, 0.0f, + }; + glBufferData(GL_ARRAY_BUFFER, sizeof(texCoordPal), texCoordPal, GL_STATIC_DRAW); + glVertexAttribPointer(mainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(mainTexCoordAttrLoc); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glPopAttrib(); + glBindVertexArray(0); + + glViewport( + ddraw->render.viewport.x, ddraw->render.viewport.y, + ddraw->render.viewport.width, ddraw->render.viewport.height); + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); // apply filter - glBindBuffer(GL_ARRAY_BUFFER, vboBuffers[1]); + glUseProgram(scaleProgram); + + glBindVertexArray(scaleVao); + + glBindBuffer(GL_ARRAY_BUFFER, scaleVbos[1]); GLfloat texCoord[] = { 0.0f, 0.0f, scale_w, 0.0f, scale_w, scale_h, - 0, scale_h, + 0.0f, scale_h, }; - glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); - glVertexAttribPointer(texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); - glEnableVertexAttribArray(texCoordAttrLoc); + glVertexAttribPointer(scaleTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(scaleTexCoordAttrLoc); glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboBuffers[2]); - - glUseProgram(scaleProgram); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, frameBufferTexId); @@ -409,7 +484,30 @@ DWORD WINAPI render_main(void) glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + else if (got30 && paletteConvProgram) + { + glBindVertexArray(mainVao); + + glBindBuffer(GL_ARRAY_BUFFER, mainVbos[1]); + + GLfloat texCoord[] = { + 0.0f, 0.0f, + scale_w, 0.0f, + scale_w, scale_h, + 0.0f, scale_h, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(texCoord), texCoord, GL_STATIC_DRAW); + glVertexAttribPointer(mainTexCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(mainTexCoordAttrLoc); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + + glBindVertexArray(0); } else { @@ -449,10 +547,13 @@ DWORD WINAPI render_main(void) glDeleteTextures(1, &frameBufferTexId); if (glDeleteBuffers) - glDeleteBuffers(3, vboBuffers); + glDeleteBuffers(3, scaleVbos); if (glDeleteFramebuffers) glDeleteFramebuffers(1, &frameBufferId); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &scaleVao); } if (glDeleteProgram) @@ -463,6 +564,18 @@ DWORD WINAPI render_main(void) if (scaleProgram) glDeleteProgram(scaleProgram); } + + if (got30) + { + if (paletteConvProgram) + { + if (glDeleteBuffers) + glDeleteBuffers(3, mainVbos); + + if (glDeleteVertexArrays) + glDeleteVertexArrays(1, &mainVao); + } + } wglMakeCurrent(NULL, NULL); wglDeleteContext(hRC);