diff --git a/src/client/refresh/gl3/gl3_draw.c b/src/client/refresh/gl3/gl3_draw.c index 4d69a619..6d39644d 100644 --- a/src/client/refresh/gl3/gl3_draw.c +++ b/src/client/refresh/gl3/gl3_draw.c @@ -266,11 +266,6 @@ GL3_Draw_Fill(int x, int y, int w, int h, int c) color.c = d_8to24table[c]; - for(i=0; i<3; ++i) - { - cf[i] = color.v[i] * (1.0f/255.0f); - } - GLfloat vBuf[8] = { // X, Y x, y+h, @@ -279,12 +274,16 @@ GL3_Draw_Fill(int x, int y, int w, int h, int c) x+w, y }; + for(i=0; i<3; ++i) + { + gl3state.uniCommonData.color[i] = color.v[i] * (1.0f/255.0f); + } + + GL3_UpdateUBOCommon(); + GL3_UseProgram(gl3state.si2Dcolor.shaderProgram); - GL3_BindVAO(vao2Dcolor); - glUniform4f(gl3state.si2Dcolor.uniColor, cf[0], cf[1], cf[2], 1.0f); - glBindBuffer(GL_ARRAY_BUFFER, vbo2D); glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); @@ -296,6 +295,7 @@ GL3_Draw_FadeScreen(void) { float w = vid.width; float h = vid.height; + int i=0; GLfloat vBuf[8] = { // X, Y @@ -307,13 +307,19 @@ GL3_Draw_FadeScreen(void) glEnable(GL_BLEND); + for(i=0; i<3; ++i) + { + gl3state.uniCommonData.color[i] = 0.0f; + } + gl3state.uniCommonData.color[3] = 0.6f; + + GL3_UpdateUBOCommon(); + GL3_UseProgram(gl3state.si2Dcolor.shaderProgram); GL3_BindVAO(vao2Dcolor); - glUniform4f(gl3state.si2Dcolor.uniColor, 0, 0, 0, 0.6f); - glBindBuffer(GL_ARRAY_BUFFER, vbo2D); glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 9c9e5151..0d11ed94 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -25,12 +25,13 @@ * ======================================================================= */ -#define HANDMADE_MATH_IMPLEMENTATION -#include "header/HandmadeMath.h" #include "../../header/ref.h" #include "header/local.h" +#define HANDMADE_MATH_IMPLEMENTATION +#include "header/HandmadeMath.h" + // TODO: put this in local.h ? #define REF_VERSION "Yamagi Quake II OpenGL3 Refresher" @@ -553,6 +554,8 @@ GL3_Init(void) GL3_Draw_InitLocal(); + GL3_SurfInit(); + R_Printf(PRINT_ALL, "\n"); return true; } @@ -567,6 +570,7 @@ GL3_Shutdown(void) GL3_Mod_FreeAll(); GL3_ShutdownImages(); + GL3_SurfShutdown(); GL3_Draw_ShutdownLocal(); GL3_ShutdownShaders(); @@ -829,10 +833,19 @@ GL3_SetGL2D(void) hmm_mat4 transMatr = HMM_Orthographic(0, vid.width, vid.height, 0, -99999, 99999); + /* glUseProgram(gl3state.si2Dcolor.shaderProgram); glUniformMatrix4fv(gl3state.si2Dcolor.uniProjMatrix , 1, GL_FALSE, transMatr.Elements[0]); glUseProgram(gl3state.si2D.shaderProgram); glUniformMatrix4fv(gl3state.si2D.uniProjMatrix , 1, GL_FALSE, transMatr.Elements[0]); + */ + + //memcpy(gl3state.uni2DData.transMat4, transMatr.Elements, 4*4*sizeof(GLfloat)); + for(int i=0; i<4; ++i) + for(int j=0; j<4; ++j) + gl3state.uni2DData.transMat4[i][j] = transMatr.Elements[i][j]; + + GL3_UpdateUBO2D(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); @@ -923,10 +936,6 @@ SetupGL(void) }}; // now rotate by view angles - /*hmm_mat4 rotMat = HMM_Rotate(-gl3_newrefdef.viewangles[2], HMM_Vec3(1, 0, 0)); - rotMat = HMM_MultiplyMat4( rotMat, HMM_Rotate(-gl3_newrefdef.viewangles[0], HMM_Vec3(0, 1, 0)) ); - rotMat = HMM_MultiplyMat4( rotMat, HMM_Rotate(-gl3_newrefdef.viewangles[1], HMM_Vec3(0, 0, 1)) ); - */ hmm_mat4 rotMat = rotAroundAxisXYZ(-gl3_newrefdef.viewangles[2], -gl3_newrefdef.viewangles[0], -gl3_newrefdef.viewangles[1]); viewMat = HMM_MultiplyMat4( viewMat, rotMat ); @@ -938,10 +947,12 @@ SetupGL(void) gl3_world_matrix = viewMat; } - // TODO: set matrices as uniforms in relevant shaders - glUseProgram(gl3state.si3D.shaderProgram); - glUniformMatrix4fv(gl3state.si3D.uniProjMatrix, 1, GL_FALSE, gl3_projectionMatrix.Elements[0]); - glUniformMatrix4fv(gl3state.si3D.uniModelViewMatrix, 1, GL_FALSE, gl3_world_matrix.Elements[0]); + memcpy(gl3state.uni3DData.transProjMat4, gl3_projectionMatrix.Elements, sizeof(gl3state.uni3DData.transProjMat4)); + memcpy(gl3state.uni3DData.transModelViewMat4, gl3_world_matrix.Elements, sizeof(gl3state.uni3DData.transProjMat4)); + + gl3state.uni3DData.time = gl3_newrefdef.time; + + GL3_UpdateUBO3D(); #if 0 glMatrixMode(GL_MODELVIEW); @@ -1134,9 +1145,9 @@ GL3_RenderView(refdef_t *fd) GL3_RenderDlights(); R_DrawParticles(); - - R_DrawAlphaSurfaces(); - +#endif // 0 + GL3_DrawAlphaSurfaces(); +#if 0 R_Flash(); if (gl_speeds->value) @@ -1316,7 +1327,9 @@ GL3_BeginFrame(float camera_separation) vid_gamma->modified = false; intensity->modified = false; - GL3_SetGammaAndIntensity(); + gl3state.uniCommonData.gamma = 1.0f/vid_gamma->value; + gl3state.uniCommonData.intensity = intensity->value; + GL3_UpdateUBOCommon(); } // Clamp overbrightbits diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index 85c9a050..9b556181 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -158,11 +158,18 @@ CreateShaderProgram(int numShaders, const GLuint* shaders) #define MULTILINE_STRING(...) #__VA_ARGS__ +// ############## shaders for 2D rendering (HUD, menus, console, videos, ..) ##################### + static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n + in vec2 position; // GL3_ATTRIB_POSITION in vec2 texCoord; // GL3_ATTRIB_TEXCOORD - uniform mat4 trans; + // for UBO shared between 2D shaders + layout (std140) uniform uni2D + { + mat4 trans; + }; out vec2 passTexCoord; @@ -174,11 +181,19 @@ static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n ); static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n + in vec2 passTexCoord; + // for UBO shared between all shaders (incl. 2D) + layout (std140) uniform uniCommon + { + float gamma; + float intensity; + + vec4 color; + }; + uniform sampler2D tex; - uniform float gamma; // this is 1.0/vid_gamma - uniform float intensity; out vec4 outColor; @@ -200,9 +215,14 @@ static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n // 2D color only rendering, GL3_Draw_Fill(), GL3_Draw_FadeScreen() static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n + in vec2 position; // GL3_ATTRIB_POSITION - uniform mat4 trans; + // for UBO shared between 2D shaders + layout (std140) uniform uni2D + { + mat4 trans; + }; void main() { @@ -212,9 +232,14 @@ static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n - uniform float gamma; // this is 1.0/vid_gamma - uniform float intensity; - uniform vec4 color; + // for UBO shared between all shaders (incl. 2D) + layout (std140) uniform uniCommon + { + float gamma; + float intensity; + + vec4 color; + }; out vec4 outColor; @@ -226,6 +251,8 @@ static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n } ); +// ############## shaders for 3D rendering ##################### + static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n in vec3 position; // GL3_ATTRIB_POSITION @@ -234,7 +261,14 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n out vec2 passTexCoord; - // TODO: uniform blocks + // for UBO shared between all 3D shaders + layout (std140) uniform uni3D + { + mat4 transProj; + mat4 transModelView; // TODO: or maybe transViewProj and transModel ?? + float scroll; // for SURF_FLOWING + float time; // or sth like this? + }; ); static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n @@ -243,13 +277,28 @@ static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n out vec4 outColor; - // TODO: uniform blocks + // for UBO shared between all shaders (incl. 2D) + layout (std140) uniform uniCommon + { + float gamma; // this is 1.0/vid_gamma + float intensity; + + vec4 color; // really? + + }; + // for UBO shared between all 3D shaders + layout (std140) uniform uni3D + { + mat4 transProj; + mat4 transModelView; // TODO: or maybe transViewProj and transModel ?? + float scroll; // for SURF_FLOWING + float time; // or sth like this? + }; ); static const char* vertexSrc3D = MULTILINE_STRING( - uniform mat4 transProj; - uniform mat4 transModelView; + // it gets attributes and uniforms from vertexCommon3D void main() { @@ -260,9 +309,9 @@ static const char* vertexSrc3D = MULTILINE_STRING( static const char* fragmentSrc3D = MULTILINE_STRING( + // it gets attributes and uniforms from fragmentCommon3D + uniform sampler2D tex; - uniform float gamma; // this is 1.0/vid_gamma - uniform float intensity; void main() { @@ -277,39 +326,73 @@ static const char* fragmentSrc3D = MULTILINE_STRING( } ); +/* + os = v [ 3 ]; + ot = v [ 4 ]; + + float TURBSCALE = (256.0 / (2 * M_PI)); + + s = os + gl3_turbsin [ (int) ( ( ot * 0.125 + rdt ) * TURBSCALE ) & 255 ]; + s += scroll; + tex[index_tex++] = s * ( 1.0 / 64 ); + + t = ot + gl3_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ]; + tex[index_tex++] = t * ( 1.0 / 64 ); + */ + +static const char* vertexSrc3Dwater = MULTILINE_STRING( + + // it gets attributes and uniforms from vertexCommon3D + void main() + { + vec2 tc = texCoord; + tc.s += sin( texCoord.t*0.125 + time ) * 4; + tc.s += scroll; + tc.t += sin( texCoord.s*0.125 + time ) * 4; + tc *= 1.0/64.0; // do this last + passTexCoord = tc; + + gl_Position = transProj * transModelView * vec4(position, 1.0); + } +); + +static const char* fragmentSrc3Dwater = MULTILINE_STRING( + + // it gets attributes and uniforms from fragmentCommon3D + + uniform sampler2D tex; + + const float PI = 3.141592653589793238462643383; // TODO: put in common + const float TURBSCALE = (256.0 / (2 * PI)); + + void main() + { + vec4 texel = texture(tex, passTexCoord); + + // TODO: something about GL_BLEND vs GL_ALPHATEST etc + + // apply gamma correction and intensity + texel.rgb *= intensity; + outColor.rgb = pow(texel.rgb, vec3(gamma)); + //outColor.a = texel.a; // I think alpha shouldn't be modified by gamma and intensity + outColor.a = 0.666; // FIXME: set alpha via uniform + } +); + #undef MULTILINE_STRING -/* TODO: UBOs -layout (std140) uniform common_data -{ - float gamma; - float intensity; - - vec4 color; // really? - +enum { + GL3_BINDINGPOINT_UNICOMMON, + GL3_BINDINGPOINT_UNI2D, + GL3_BINDINGPOINT_UNI3D }; -layout (std140) uniform for2D_data -{ - mat4 trans; -}; - -layout (std140) uniform for3D_data -{ - mat4 transProj; - mat4 transModelView; // TODO: or maybe transViewProj; and transModel; ?? - float scroll; // for SURF_FLOWING - float time; // or sth like this? -}; - */ - static qboolean initShader2D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragSrc) { GLuint shaders2D[2] = {0}; - GLint i = -1; GLuint prog = 0; if(shaderInfo->shaderProgram != 0) @@ -318,7 +401,7 @@ initShader2D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS glDeleteProgram(shaderInfo->shaderProgram); } - shaderInfo->uniColor = shaderInfo->uniProjMatrix = shaderInfo->uniModelViewMatrix = -1; + //shaderInfo->uniColor = shaderInfo->uniProjMatrix = shaderInfo->uniModelViewMatrix = -1; shaderInfo->shaderProgram = 0; shaders2D[0] = CompileShader(GL_VERTEX_SHADER, vertSrc, NULL); @@ -343,17 +426,75 @@ initShader2D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS } shaderInfo->shaderProgram = prog; - glUseProgram(prog); + GL3_UseProgram(prog); - shaderInfo->uniColor = glGetUniformLocation(prog, "color"); - - i = glGetUniformLocation(prog, "trans"); - if( i == -1) + // Bind the buffer object to the uniform blocks + GLuint blockIndex = glGetUniformBlockIndex(prog, "uniCommon"); + if(blockIndex != GL_INVALID_INDEX) { - R_Printf(PRINT_ALL, "WARNING: Couldn't get 'trans' uniform in shader\n"); + GLint blockSize; + glGetActiveUniformBlockiv(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize); + if(blockSize != sizeof(gl3state.uniCommonData)) + { + R_Printf(PRINT_ALL, "WARNING: OpenGL driver disagrees with us about UBO size of 'uniCommon': %i vs %i\n", + blockSize, (int)sizeof(gl3state.uniCommonData)); + + // TODO: clean up? + return false; + } + + const GLchar *names[] = { "gamma", "intensity", "color" }; + + GLuint indices[3]; + glGetUniformIndices(prog, 3, names, indices); + + GLint offset[3]; + glGetActiveUniformsiv(prog, 3, indices, GL_UNIFORM_OFFSET, offset); + + printf("## uniCommon offsets in shader:"); + for(int i=0; i<3; ++i) + { + printf(" offset of '%s' is %d", names[i], offset[i]); + } + printf("\n"); + + printf("## offsets in C: gamma: %zd intensity: %zd color: %zd\n", + offsetof(gl3UniCommon_t, gamma), + offsetof(gl3UniCommon_t, intensity), + offsetof(gl3UniCommon_t, color)); + + + + glUniformBlockBinding(prog, blockIndex, GL3_BINDINGPOINT_UNICOMMON); + + // TODO: something with glUniformBlockBinding() ! + } + else + { + R_Printf(PRINT_ALL, "WARNING: Couldn't find uniform block index 'uniCommon'\n"); + // TODO: clean up? + return false; + } + blockIndex = glGetUniformBlockIndex(prog, "uni2D"); + if(blockIndex != GL_INVALID_INDEX) + { + GLint blockSize; + glGetActiveUniformBlockiv(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize); + if(blockSize != sizeof(gl3state.uni2DData)) + { + R_Printf(PRINT_ALL, "WARNING: OpenGL driver disagrees with us about UBO size of 'uni2D'\n"); + // TODO: clean up? + return false; + } + + glUniformBlockBinding(prog, blockIndex, GL3_BINDINGPOINT_UNI2D); + } + else + { + R_Printf(PRINT_ALL, "WARNING: Couldn't find uniform block index 'uni2D'\n"); + // TODO: clean up? return false; } - shaderInfo->uniProjMatrix = i; return true; } @@ -362,7 +503,6 @@ static qboolean initShader3D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragSrc) { GLuint shaders3D[2] = {0}; - GLint i = -1; GLuint prog = 0; if(shaderInfo->shaderProgram != 0) @@ -371,7 +511,7 @@ initShader3D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS glDeleteProgram(shaderInfo->shaderProgram); } - shaderInfo->uniColor = shaderInfo->uniProjMatrix = shaderInfo->uniModelViewMatrix = -1; + //shaderInfo->uniColor = shaderInfo->uniProjMatrix = shaderInfo->uniModelViewMatrix = -1; shaderInfo->shaderProgram = 0; shaders3D[0] = CompileShader(GL_VERTEX_SHADER, vertexCommon3D, vertSrc); @@ -386,40 +526,109 @@ initShader3D(gl3ShaderInfo_t* shaderInfo, const char* vertSrc, const char* fragS prog = CreateShaderProgram(2, shaders3D); + if(prog == 0) + { + goto err_cleanup; + } + + GL3_UseProgram(prog); + + // Bind the buffer object to the uniform blocks + GLuint blockIndex = glGetUniformBlockIndex(prog, "uniCommon"); + if(blockIndex != GL_INVALID_INDEX) + { + GLint blockSize; + glGetActiveUniformBlockiv(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize); + if(blockSize != sizeof(gl3state.uniCommonData)) + { + R_Printf(PRINT_ALL, "WARNING: OpenGL driver disagrees with us about UBO size of 'uniCommon'\n"); + + goto err_cleanup; + } + + glUniformBlockBinding(prog, blockIndex, GL3_BINDINGPOINT_UNICOMMON); + } + else + { + R_Printf(PRINT_ALL, "WARNING: Couldn't find uniform block index 'uniCommon'\n"); + + goto err_cleanup; + } + blockIndex = glGetUniformBlockIndex(prog, "uni3D"); + if(blockIndex != GL_INVALID_INDEX) + { + GLint blockSize; + glGetActiveUniformBlockiv(prog, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize); + if(blockSize != sizeof(gl3state.uni3DData)) + { + R_Printf(PRINT_ALL, "WARNING: OpenGL driver disagrees with us about UBO size of 'uni3D'\n"); + + goto err_cleanup; + } + + glUniformBlockBinding(prog, blockIndex, GL3_BINDINGPOINT_UNI3D); + } + else + { + R_Printf(PRINT_ALL, "WARNING: Couldn't find uniform block index 'uni3D'\n"); + + goto err_cleanup; + } + + shaderInfo->shaderProgram = prog; + // I think the shaders aren't needed anymore once they're linked into the program glDeleteShader(shaders3D[0]); glDeleteShader(shaders3D[1]); - if(prog == 0) - { - return false; - } - - shaderInfo->shaderProgram = prog; - glUseProgram(prog); - - shaderInfo->uniColor = glGetUniformLocation(prog, "color"); - - i = glGetUniformLocation(prog, "transProj"); - if( i == -1) - { - R_Printf(PRINT_ALL, "WARNING: Couldn't get 'trans' uniform in shader\n"); - return false; - } - shaderInfo->uniProjMatrix = i; - i = glGetUniformLocation(prog, "transModelView"); - if( i == -1) - { - R_Printf(PRINT_ALL, "WARNING: Couldn't get 'trans' uniform in shader\n"); - return false; - } - shaderInfo->uniModelViewMatrix = i; - return true; + +err_cleanup: + + if(shaders3D[0] != 0) glDeleteShader(shaders3D[0]); + if(shaders3D[1] != 0) glDeleteShader(shaders3D[1]); + + if(prog != 0) glDeleteProgram(prog); + + return false; +} + +static void initUBOs(void) +{ + gl3state.uniCommonData.gamma = 1.0f/vid_gamma->value; + gl3state.uniCommonData.intensity = intensity->value; + GLfloat color[4] = {1, 1, 1, 1}; + memcpy(gl3state.uniCommonData.color, color, sizeof(color)); + + glGenBuffers(1, &gl3state.uniCommonUBO); + glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uniCommonUBO); + glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNICOMMON, gl3state.uniCommonUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uniCommonData), &gl3state.uniCommonData, GL_DYNAMIC_DRAW); + + // the matrix will be set to something more useful later, before being used + memset(gl3state.uni2DData.transMat4, 0, sizeof(gl3state.uni2DData.transMat4)); + + glGenBuffers(1, &gl3state.uni2DUBO); + glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uni2DUBO); + glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNI2D, gl3state.uni2DUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni2DData), &gl3state.uni2DData, GL_DYNAMIC_DRAW); + + + memset(&gl3state.uni3DData, 0, sizeof(gl3state.uni3DData)); + // the matrices will be set to something more useful later, before being used + gl3state.uni3DData.scroll = 0.0f; + gl3state.uni3DData.time = 0.0f; + + glGenBuffers(1, &gl3state.uni3DUBO); + glBindBuffer(GL_UNIFORM_BUFFER, gl3state.uni3DUBO); + glBindBufferBase(GL_UNIFORM_BUFFER, GL3_BINDINGPOINT_UNI3D, gl3state.uni3DUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni3DData), &gl3state.uni3DData, GL_DYNAMIC_DRAW); } qboolean GL3_InitShaders(void) { + initUBOs(); + if(!initShader2D(&gl3state.si2D, vertexSrc2D, fragmentSrc2D)) { R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 2D rendering!\n"); @@ -435,11 +644,13 @@ qboolean GL3_InitShaders(void) R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 3D rendering!\n"); return false; } + if(!initShader3D(&gl3state.si3Dturb, vertexSrc3Dwater, fragmentSrc3Dwater)) + { + R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for water rendering!\n"); + return false; + } gl3state.currentShaderProgram = 0; - - GL3_SetGammaAndIntensity(); - return true; } @@ -456,29 +667,25 @@ void GL3_ShutdownShaders(void) if(gl3state.si3D.shaderProgram != 0) glDeleteProgram(gl3state.si3D.shaderProgram); memset(&gl3state.si3D, 0, sizeof(gl3ShaderInfo_t)); + + glDeleteBuffers(3, &gl3state.uniCommonUBO); + gl3state.uniCommonUBO = gl3state.uni2DUBO = gl3state.uni3DUBO = 0; } -void GL3_SetGammaAndIntensity(void) +void GL3_UpdateUBOCommon(void) { - float gamma = 1.0f/vid_gamma->value; - float intens = intensity->value; - int i=0; - GLint progs[] = { gl3state.si2D.shaderProgram, gl3state.si2Dcolor.shaderProgram, - gl3state.si3D.shaderProgram }; - - for(i=0; iverts[0]; - - // v: blocks of 7 floats: (X, Y, Z) (S1, T1), (S2, T2) - // apparently (S2, T2) is not used here, probably for lightmap? - - STUB_ONCE("TODO: Implement!"); - - GL3_UseProgram(gl3state.si3D.shaderProgram); // TODO: needed each time?! - - static GLuint vao = 0, vbo = 0; // TODO!! - if(vao == 0) // FIXME: DON'T DO THIS! - { - glGenVertexArrays(1, &vao); - GL3_BindVAO(vao); - - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); // TODO ?? - - glEnableVertexAttribArray(GL3_ATTRIB_POSITION); - qglVertexAttribPointer(GL3_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 0); - - glEnableVertexAttribArray(GL3_ATTRIB_TEXCOORD); - qglVertexAttribPointer(GL3_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 3*sizeof(GLfloat)); - - glEnableVertexAttribArray(GL3_ATTRIB_LMTEXCOORD); - qglVertexAttribPointer(GL3_ATTRIB_LMTEXCOORD, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 5*sizeof(GLfloat)); - } + float* v = p->verts[0]; GL3_UseProgram(gl3state.si3D.shaderProgram); // TODO: needed each time?! maybe call this once in DrawTextureChains()? - GL3_BindVAO(vao); + GL3_BindVAO(gl3state.vao3D); - glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo3D); glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*p->numverts, v, GL_STREAM_DRAW); glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts); - -#if 0 - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v ); - glTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v+3 ); - glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 } void @@ -640,26 +629,29 @@ RenderBrushPoly(msurface_t *fa) void GL3_DrawAlphaSurfaces(void) { - STUB("TODO: implement!"); -#if 0 + STUB_ONCE("TODO: implement!"); + msurface_t *s; float intens; /* go back to the world matrix */ - glLoadMatrixf(r_world_matrix); + //glLoadMatrixf(r_world_matrix); + memcpy(gl3state.uni3DData.transModelViewMat4, gl3_world_matrix.Elements, 16*sizeof(float)); + GL3_UpdateUBO3D(); glEnable(GL_BLEND); - R_TexEnv(GL_MODULATE); + //R_TexEnv(GL_MODULATE); /* the textures are prescaled up for a better lighting range, so scale it back down */ - intens = gl_state.inverse_intensity; + //intens = gl_state.inverse_intensity; + STUB_ONCE("Something about inverse intensity"); - for (s = gl3_alpha_surfaces; s; s = s->texturechain) + for (s = gl3_alpha_surfaces; s != NULL; s = s->texturechain) { GL3_Bind(s->texinfo->image->texnum); c_brush_polys++; - +#if 0 if (s->texinfo->flags & SURF_TRANS33) { glColor4f(intens, intens, intens, 0.33); @@ -672,27 +664,27 @@ GL3_DrawAlphaSurfaces(void) { glColor4f(intens, intens, intens, 1); } +#endif // 0 if (s->flags & SURF_DRAWTURB) { - R_EmitWaterPolys(s); + GL3_EmitWaterPolys(s); } else if (s->texinfo->flags & SURF_FLOWING) { - R_DrawGLFlowingPoly(s); + GL3_DrawGLFlowingPoly(s); } else { - R_DrawGLPoly(s->polys); + GL3_DrawGLPoly(s->polys); } } - R_TexEnv(GL_REPLACE); - glColor4f(1, 1, 1, 1); + //R_TexEnv(GL_REPLACE); + //glColor4f(1, 1, 1, 1); glDisable(GL_BLEND); gl3_alpha_surfaces = NULL; -#endif // 0 } static void diff --git a/src/client/refresh/gl3/gl3_warp.c b/src/client/refresh/gl3/gl3_warp.c index 9d02d6f4..5527a52e 100644 --- a/src/client/refresh/gl3/gl3_warp.c +++ b/src/client/refresh/gl3/gl3_warp.c @@ -228,61 +228,30 @@ GL3_SubdivideSurface(msurface_t *fa, gl3model_t* loadmodel) void GL3_EmitWaterPolys(msurface_t *fa) { - glpoly_t *p, *bp; - float *v; - int i; - float s, t, os, ot; - float scroll; - float rdt = gl3_newrefdef.time; - - static const float TURBSCALE = (256.0 / (2 * M_PI)); + glpoly_t *bp; + float scroll = 0.0f; if (fa->texinfo->flags & SURF_FLOWING) { - scroll = -64 * ((gl3_newrefdef.time * 0.5) - (int)(gl3_newrefdef.time * 0.5)); - } - else - { - scroll = 0; + scroll = -64.0f * ((gl3_newrefdef.time * 0.5) - (int)(gl3_newrefdef.time * 0.5)); } - // TODO: do the scrolling/warping in shader - - for (bp = fa->polys; bp; bp = bp->next) + if(gl3state.uni3DData.scroll != scroll) { - p = bp; - int numverts = p->numverts; + gl3state.uni3DData.scroll = scroll; + GL3_UpdateUBO3D(); + } - GLfloat tex[2*numverts]; - unsigned int index_tex = 0; + GL3_UseProgram(gl3state.si3Dturb.shaderProgram); - for ( i = 0, v = p->verts [ 0 ]; i < numverts; i++, v += VERTEXSIZE ) - { - os = v [ 3 ]; - ot = v [ 4 ]; + GL3_BindVAO(gl3state.vao3D); + glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo3D); - s = os + gl3_turbsin [ (int) ( ( ot * 0.125 + gl3_newrefdef.time ) * TURBSCALE ) & 255 ]; - s += scroll; - tex[index_tex++] = s * ( 1.0 / 64 ); - - t = ot + gl3_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ]; - tex[index_tex++] = t * ( 1.0 / 64 ); - } - - v = p->verts [ 0 ]; - - STUB_ONCE("TODO: Implement OpenGL3 part!"); -#if 0 - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 + for (bp = fa->polys; bp != NULL; bp = bp->next) + { + int numverts = bp->numverts; + glBufferData(GL_ARRAY_BUFFER, VERTEXSIZE*sizeof(GLfloat)*numverts, bp->verts[0], GL_STREAM_DRAW); + glDrawArrays(GL_TRIANGLE_FAN, 0, numverts); } } diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 32c62fdf..1f8032c4 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -43,6 +43,8 @@ #include "../../ref_shared.h" +#include "HandmadeMath.h" + #define STUB(msg) \ R_Printf(PRINT_ALL, "STUB: %s() %s\n", __FUNCTION__, msg) @@ -64,8 +66,8 @@ qglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normaliz // attribute locations for vertex shaders enum { - GL3_ATTRIB_POSITION = 0, - GL3_ATTRIB_TEXCOORD = 1, // for normal texture + GL3_ATTRIB_POSITION = 0, + GL3_ATTRIB_TEXCOORD = 1, // for normal texture GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap // TODO: more? maybe normal and color? }; @@ -104,14 +106,40 @@ typedef struct { GLuint shaderProgram; - GLint uniColor; - GLint uniProjMatrix; // for 2D shaders this is the only one used - GLint uniModelViewMatrix; // TODO: or even pass as 2 matrices? - - // TODO: probably more uniforms, at least gamma and intensity + //GLint uniColor; + //GLint uniProjMatrix; // for 2D shaders this is the only one used + //GLint uniModelViewMatrix; // TODO: or even pass as 2 matrices? } gl3ShaderInfo_t; +typedef struct +{ + GLfloat gamma; + GLfloat intensity; + + // entries of std140 UBOs are aligned to multiples of their own size + // so we'll need to pad accordingly + GLfloat _padding[2]; + + GLfloat color[4]; +} gl3UniCommon_t; + +typedef struct +{ + GLfloat transMat4[4][4]; +} gl3Uni2D_t; + +typedef struct +{ + GLfloat transProjMat4[4][4]; + GLfloat transModelViewMat4[4][4]; + + GLfloat scroll; // for SURF_FLOWING + GLfloat time; // for warping surfaces like water & possibly other things + + GLfloat _padding[2]; // again, some padding to ensure this has right size +} gl3Uni3D_t; + typedef struct { // TODO: what of this do we need? @@ -138,8 +166,18 @@ typedef struct GLuint currentShaderProgram; gl3ShaderInfo_t si2D; // shader for rendering 2D with textures gl3ShaderInfo_t si2Dcolor; // shader for rendering 2D with flat colors - gl3ShaderInfo_t si3D; + gl3ShaderInfo_t si3Dturb; // for water etc + + GLuint vao3D, vbo3D; // for brushes etc, using 7 floats as vertex input (x,y,z, s,t, lms,lmt) + + // UBOs and their data + gl3UniCommon_t uniCommonData; + gl3Uni2D_t uni2DData; + gl3Uni3D_t uni3DData; + GLuint uniCommonUBO; + GLuint uni2DUBO; + GLuint uni3DUBO; } gl3state_t; @@ -215,6 +253,9 @@ extern cplane_t frustum[4]; extern vec3_t gl3_origin; +hmm_mat4 gl3_projectionMatrix; // eye cord -> clip coord +hmm_mat4 gl3_world_matrix; // the view matrix: world coord -> eye coord + extern gl3image_t *gl3_notexture; /* use for bad textures */ extern gl3image_t *gl3_particletexture; /* little dot for particles */ @@ -324,6 +365,8 @@ extern void GL3_AddSkySurface(msurface_t *fa); // gl3_surf.c +extern void GL3_SurfInit(void); +extern void GL3_SurfShutdown(void); extern void GL3_DrawGLPoly(glpoly_t *p); extern void GL3_DrawGLFlowingPoly(msurface_t *fa); extern void GL3_DrawTriangleOutlines(void); @@ -337,7 +380,9 @@ extern void GL3_MarkLeaves(void); extern qboolean GL3_InitShaders(void); extern void GL3_ShutdownShaders(void); -extern void GL3_SetGammaAndIntensity(void); +extern void GL3_UpdateUBOCommon(void); +extern void GL3_UpdateUBO2D(void); +extern void GL3_UpdateUBO3D(void); // ############ Cvars ###########