From 43e108fb9b3c5f3e3ac4d800c01a5945dae66bf8 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Mon, 23 Jan 2017 00:28:38 +0100 Subject: [PATCH] GL3_Draw_* is done, menu, console, videos work --- src/client/refresh/gl3/gl3_draw.c | 282 +++++++++----------------- src/client/refresh/gl3/gl3_main.c | 8 + src/client/refresh/gl3/gl3_shaders.c | 144 ++++++++----- src/client/refresh/gl3/header/local.h | 4 +- 4 files changed, 193 insertions(+), 245 deletions(-) diff --git a/src/client/refresh/gl3/gl3_draw.c b/src/client/refresh/gl3/gl3_draw.c index 933544b7..73513004 100644 --- a/src/client/refresh/gl3/gl3_draw.c +++ b/src/client/refresh/gl3/gl3_draw.c @@ -56,6 +56,43 @@ GL3_Draw_ShutdownLocal(void) gl3state.vao2D = 0; } +// bind the texture before calling this +static void +drawTexturedRectangle(float x, float y, float w, float h, + float sl, float tl, float sh, float th) +{ + /* + * x,y+h x+w,y+h + * sl,th--------sh,th + * | | + * | | + * | | + * sl,tl--------sh,tl + * x,y x+w,y + */ + + GLfloat vBuf[16] = { + // X, Y, S, T + x, y+h, sl, th, + x, y, sl, tl, + x+w, y+h, sh, th, + x+w, y, sh, tl + }; + + glBindVertexArray(gl3state.vao2D); + + glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D); + glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); + + glEnableVertexAttribArray(gl3state.si2D.attribPosition); + qglVertexAttribPointer(gl3state.si2D.attribPosition, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0); + + glEnableVertexAttribArray(gl3state.si2D.attribTexCoord); + qglVertexAttribPointer(gl3state.si2D.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 2*sizeof(float)); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + /* * Draws one 8*8 graphics character with 0 being transparent. * It can be clipped to the top of the screen to allow the console to be @@ -64,11 +101,8 @@ GL3_Draw_ShutdownLocal(void) void GL3_Draw_CharScaled(int x, int y, int num, float scale) { - STUB_ONCE("TODO: Implement!"); -#if 0 int row, col; float frow, fcol, size, scaledSize; - num &= 255; if ((num & 127) == 32) @@ -90,32 +124,8 @@ GL3_Draw_CharScaled(int x, int y, int num, float scale) scaledSize = 8*scale; - R_Bind(draw_chars->texnum); - - GLfloat vtx[] = { - x, y, - x + scaledSize, y, - x + scaledSize, y + scaledSize, - x, y + scaledSize - }; - - GLfloat tex[] = { - fcol, frow, - fcol + size, frow, - fcol + size, frow + size, - fcol, frow + size - }; - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 + GL3_Bind(draw_chars->texnum); + drawTexturedRectangle(x, y, scaledSize, scaledSize, fcol, frow, fcol+size, frow+size); } gl3image_t * @@ -157,11 +167,7 @@ GL3_Draw_GetPicSize(int *w, int *h, char *pic) void GL3_Draw_StretchPic(int x, int y, int w, int h, char *pic) { - STUB_ONCE("TODO: Implement!"); -#if 0 - image_t *gl; - - gl = RDraw_FindPic(pic); + gl3image_t *gl = GL3_Draw_FindPic(pic); if (!gl) { @@ -169,85 +175,24 @@ GL3_Draw_StretchPic(int x, int y, int w, int h, char *pic) return; } - if (scrap_dirty) - { - Scrap_Upload(); - } + GL3_Bind(gl->texnum); - R_Bind(gl->texnum); - - GLfloat vtx[] = { - x, y, - x + w, y, - x + w, y + h, - x, y + h - }; - - GLfloat tex[] = { - gl->sl, gl->tl, - gl->sh, gl->tl, - gl->sh, gl->th, - gl->sl, gl->th - }; - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 + drawTexturedRectangle(x, y, w, h, gl->sl, gl->tl, gl->sh, gl->th); } void GL3_Draw_PicScaled(int x, int y, char *pic, float factor) { - STUB_ONCE("TODO: Implement!"); -#if 0 - image_t *gl; - - gl = RDraw_FindPic(pic); - + gl3image_t *gl = GL3_Draw_FindPic(pic); if (!gl) { R_Printf(PRINT_ALL, "Can't find pic: %s\n", pic); return; } - if (scrap_dirty) - { - Scrap_Upload(); - } + GL3_Bind(gl->texnum); - R_Bind(gl->texnum); - - GLfloat vtx[] = { - x, y, - x + gl->width * factor, y, - x + gl->width * factor, y + gl->height * factor, - x, y + gl->height * factor - }; - - GLfloat tex[] = { - gl->sl, gl->tl, - gl->sh, gl->tl, - gl->sh, gl->th, - gl->sl, gl->th - }; - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 + drawTexturedRectangle(x, y, gl->width*factor, gl->height*factor, gl->sl, gl->tl, gl->sh, gl->th); } /* @@ -258,44 +203,16 @@ GL3_Draw_PicScaled(int x, int y, char *pic, float factor) void GL3_Draw_TileClear(int x, int y, int w, int h, char *pic) { - STUB_ONCE("TODO: Implement!"); -#if 0 - image_t *image; - - image = RDraw_FindPic(pic); - + gl3image_t *image = GL3_Draw_FindPic(pic); if (!image) { R_Printf(PRINT_ALL, "Can't find pic: %s\n", pic); return; } - R_Bind(image->texnum); + GL3_Bind(image->texnum); - GLfloat vtx[] = { - x, y, - x + w, y, - x + w, y + h, - x, y + h - }; - - GLfloat tex[] = { - x / 64.0, y / 64.0, - ( x + w ) / 64.0, y / 64.0, - ( x + w ) / 64.0, ( y + h ) / 64.0, - x / 64.0, ( y + h ) / 64.0 - }; - - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); - - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); -#endif // 0 + drawTexturedRectangle(x, y, w, h, x/64.0f, y/64.0f, (x+w)/64.0f, (y+h)/64.0f); } /* @@ -304,71 +221,80 @@ GL3_Draw_TileClear(int x, int y, int w, int h, char *pic) void GL3_Draw_Fill(int x, int y, int w, int h, int c) { - STUB_ONCE("TODO: Implement!"); -#if 0 union { unsigned c; byte v[4]; } color; + int i; + float cf[3]; if ((unsigned)c > 255) { ri.Sys_Error(ERR_FATAL, "Draw_Fill: bad color"); } - glDisable(GL_TEXTURE_2D); - color.c = d_8to24table[c]; - glColor4f(color.v [ 0 ] / 255.0, color.v [ 1 ] / 255.0, - color.v [ 2 ] / 255.0, 1); - GLfloat vtx[] = { - x, y, - x + w, y, - x + w, y + h, - x, y + h + for(i=0; i<3; ++i) + { + cf[i] = color.v[i] * (1.0f/255.0f); + } + + GLfloat vBuf[24] = { + // X, Y, R, G, B, A + x, y+h, cf[0], cf[1], cf[2], 1.0f, + x, y, cf[0], cf[1], cf[2], 1.0f, + x+w, y+h, cf[0], cf[1], cf[2], 1.0f, + x+w, y, cf[0], cf[1], cf[2], 1.0f }; - glEnableClientState( GL_VERTEX_ARRAY ); + glUseProgram(gl3state.si2Dcolor.shaderProgram); - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); + glBindVertexArray(gl3state.vao2D); - glDisableClientState( GL_VERTEX_ARRAY ); + glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D); + glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); - glColor4f( 1, 1, 1, 1 ); - glEnable(GL_TEXTURE_2D); -#endif // 0 + glEnableVertexAttribArray(gl3state.si2Dcolor.attribPosition); + qglVertexAttribPointer(gl3state.si2Dcolor.attribPosition, 2, GL_FLOAT, GL_FALSE, 6*sizeof(float), 0); + + glEnableVertexAttribArray(gl3state.si2Dcolor.attribColor); + qglVertexAttribPointer(gl3state.si2Dcolor.attribColor, 2, GL_FLOAT, GL_FALSE, 6*sizeof(float), 2*sizeof(float)); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glUseProgram(gl3state.si2D.shaderProgram); } void GL3_Draw_FadeScreen(void) { - STUB_ONCE("TODO: Implement!"); -#if 0 - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glColor4f(0, 0, 0, 0.8); + float w = vid.width; + float h = vid.height; - GLfloat vtx[] = { - 0, 0, - vid.width, 0, - vid.width, vid.height, - 0, vid.height + GLfloat vBuf[24] = { + // X, Y, R, G, B, A + 0, h, 0.0f, 0.0f, 0.0f, 0.8f, + 0, 0, 0.0f, 0.0f, 0.0f, 0.8f, + w, h, 0.0f, 0.0f, 0.0f, 0.8f, + w, 0, 0.0f, 0.0f, 0.0f, 0.8f }; - glEnableClientState( GL_VERTEX_ARRAY ); + glUseProgram(gl3state.si2Dcolor.shaderProgram); - glVertexPointer( 2, GL_FLOAT, 0, vtx ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); + glBindVertexArray(gl3state.vao2D); - glDisableClientState( GL_VERTEX_ARRAY ); + glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D); + glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); - glColor4f(1, 1, 1, 1); - glEnable(GL_TEXTURE_2D); - glDisable(GL_BLEND); -#endif // 0 + glEnableVertexAttribArray(gl3state.si2Dcolor.attribPosition); + qglVertexAttribPointer(gl3state.si2Dcolor.attribPosition, 2, GL_FLOAT, GL_FALSE, 6*sizeof(float), 0); + + glEnableVertexAttribArray(gl3state.si2Dcolor.attribColor); + qglVertexAttribPointer(gl3state.si2Dcolor.attribColor, 2, GL_FLOAT, GL_FALSE, 6*sizeof(float), 2*sizeof(float)); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glUseProgram(gl3state.si2D.shaderProgram); } void @@ -380,14 +306,6 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data) int i, j, trows; int row; - GLfloat vBuf[] = { - // posX, posY, texS, texT - x, y + h, 0.0f, 1.0f, - x, y, 0.0f, 0.0f, - x + w, y + h, 1.0f, 1.0f, - x + w, y, 1.0f, 0.0f, - }; - GL3_Bind(0); unsigned image32[320*240]; /* was 256 * 256, but we want a bit more space */ @@ -426,19 +344,7 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glBindVertexArray(gl3state.vao2D); - - glBindBuffer(GL_ARRAY_BUFFER, gl3state.vbo2D); - glBufferData(GL_ARRAY_BUFFER, sizeof(vBuf), vBuf, GL_STREAM_DRAW); - - glEnableVertexAttribArray(gl3state.si2D.attribPosition); - qglVertexAttribPointer(gl3state.si2D.attribPosition, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0); - - glEnableVertexAttribArray(gl3state.si2D.attribTexCoord); - qglVertexAttribPointer(gl3state.si2D.attribTexCoord, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), sizeof(float)*2); - - glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); + drawTexturedRectangle(x, y, w, h, 0.0f, 0.0f, 1.0f, 1.0f); glDeleteTextures(1, &glTex); GL3_Bind(0); diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index d39834f6..4cd0a674 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -422,6 +422,8 @@ GL3_Shutdown(void) GL3_Mod_FreeAll(); GL3_ShutdownImages(); + GL3_Draw_ShutdownLocal(); + GL3_ShutdownShaders(); /* shutdown OS specific OpenGL stuff like contexts, etc. */ GL3_ShutdownWindow(false); @@ -476,6 +478,7 @@ GL3_SetGL2D(void) glDisable(GL_BLEND); // glEnable(GL_ALPHA_TEST); TODO: do in shader https://www.khronos.org/opengl/wiki/Transparency_Sorting#Alpha_test // glColor4f(1, 1, 1, 1); + } /* @@ -744,6 +747,11 @@ void GL3_BeginFrame(float camera_separation) { STUB_ONCE("TODO: Implement!"); + + glClearColor(0, 0, 0, 0); // FIXME: not sure this should stay + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(1, 0, 0.5, 0.5); + GL3_SetGL2D(); #if 0 gl_state.camera_separation = camera_separation; diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index 8d6ec88a..9e1488af 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -200,17 +200,21 @@ static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n in vec2 passTexCoord; - out vec4 outColor; - uniform sampler2D tex; + out vec4 outColor; + void main() { // TODO: gamma, intensity - outColor = texture(tex, passTexCoord); + vec4 texel = texture(tex, passTexCoord); + if(texel.a < 0.666) + discard; + outColor = texel; } ); +// 2D color only rendering, GL3_Draw_Fill(), GL3_Draw_FadeScreen() static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n in vec4 color; in vec2 position; @@ -229,79 +233,107 @@ static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n in vec4 passColor; - out vec4 outColor; - uniform sampler2D tex; + out vec4 outColor; + void main() { - // TODO: gamma, intensity + // TODO: gamma, intensity? (not sure we need that here) outColor = passColor; } ); #undef MULTILINE_STRING -qboolean GL3_InitShaders(void) +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) { - GLuint shaders2D[2] = {0}; - shaders2D[0] = CompileShader(GL_VERTEX_SHADER, vertexSrc2D); - if(shaders2D[0] == 0) return false; - shaders2D[1] = CompileShader(GL_FRAGMENT_SHADER, fragmentSrc2D); - if(shaders2D[1] == 0) - { - glDeleteShader(shaders2D[0]); - return false; - } - - gl3state.si2D.shaderProgram = CreateShaderProgram(2, shaders2D); - - // I think the shaders aren't needed anymore once they're linked into the program - glDeleteShader(shaders2D[0]); - glDeleteShader(shaders2D[1]); - - if(gl3state.si2D.shaderProgram != 0) - { - glUseProgram(gl3state.si2D.shaderProgram); - gl3state.si2D.attribTexCoord = glGetAttribLocation(gl3state.si2D.shaderProgram, "texCoord"); - gl3state.si2D.attribPosition = glGetAttribLocation(gl3state.si2D.shaderProgram, "position"); - gl3state.si2D.attribColor = -1; - - gl3state.si2D.uniTransMatrix = glGetUniformLocation(gl3state.si2D.shaderProgram, "trans"); - } - else - { - return false; - } + R_Printf(PRINT_ALL, "WARNING: calling initShader2D for gl3ShaderInfo_t that already has a shaderProgram!\n"); + glDeleteProgram(shaderInfo->shaderProgram); } + shaderInfo->attribColor = shaderInfo->attribPosition = shaderInfo->attribTexCoord = -1; + shaderInfo->uniTransMatrix = -1; + shaderInfo->shaderProgram = 0; + + shaders2D[0] = CompileShader(GL_VERTEX_SHADER, vertSrc); + if(shaders2D[0] == 0) return false; + + shaders2D[1] = CompileShader(GL_FRAGMENT_SHADER, fragSrc); + if(shaders2D[1] == 0) { - GLuint shaders2Dcol[2] = {0}; + glDeleteShader(shaders2D[0]); + return false; + } - shaders2Dcol[0] = CompileShader(GL_VERTEX_SHADER, vertexSrc2Dcolor); - shaders2Dcol[1] = CompileShader(GL_FRAGMENT_SHADER, fragmentSrc2Dcolor); - // TODO: error handling! - gl3state.si2Dcolor.shaderProgram = CreateShaderProgram(2, shaders2Dcol); + prog = CreateShaderProgram(2, shaders2D); - // I think the shaders aren't needed anymore once they're linked into the program - glDeleteShader(shaders2Dcol[0]); - glDeleteShader(shaders2Dcol[1]); + // I think the shaders aren't needed anymore once they're linked into the program + glDeleteShader(shaders2D[0]); + glDeleteShader(shaders2D[1]); - if(gl3state.si2Dcolor.shaderProgram != 0) - { - glUseProgram(gl3state.si2Dcolor.shaderProgram); - gl3state.si2Dcolor.attribColor = glGetAttribLocation(gl3state.si2Dcolor.shaderProgram, "color"); - gl3state.si2Dcolor.attribPosition = glGetAttribLocation(gl3state.si2Dcolor.shaderProgram, "position"); - gl3state.si2Dcolor.attribTexCoord = -1; + if(prog == 0) + { + return false; + } - gl3state.si2Dcolor.uniTransMatrix = glGetUniformLocation(gl3state.si2Dcolor.shaderProgram, "trans"); - } - else - { - // TODO: error handling! - } + shaderInfo->shaderProgram = prog; + glUseProgram(prog); + + i = glGetAttribLocation(prog, "position"); + if( i == -1) + { + R_Printf(PRINT_ALL, "WARNING: Couldn't get 'position' attribute in shader\n"); + return false; + } + shaderInfo->attribPosition = i; + + // the following line will set it to -1 for the textured case, that's ok. + shaderInfo->attribColor = glGetAttribLocation(prog, "color"); + // the following line will set it to -1 for the color-only case, that's ok. + shaderInfo->attribTexCoord = glGetAttribLocation(prog, "texCoord"); + + i = glGetUniformLocation(prog, "trans"); + if( i == -1) + { + R_Printf(PRINT_ALL, "WARNING: Couldn't get 'trans' uniform in shader\n"); + return false; + } + shaderInfo->uniTransMatrix = i; + + return true; +} + +qboolean GL3_InitShaders(void) +{ + if(!initShader2D(&gl3state.si2D, vertexSrc2D, fragmentSrc2D)) + { + R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for textured 2D rendering!\n"); + return false; + } + if(!initShader2D(&gl3state.si2Dcolor, vertexSrc2Dcolor, fragmentSrc2Dcolor)) + { + R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for color-only 2D rendering!\n"); + return false; } return true; } + +void GL3_ShutdownShaders(void) +{ + if(gl3state.si2D.shaderProgram != 0) + glDeleteProgram(gl3state.si2D.shaderProgram); + memset(&gl3state.si2D, 0, sizeof(gl3ShaderInfo_t)); + + if(gl3state.si2Dcolor.shaderProgram != 0) + glDeleteProgram(gl3state.si2Dcolor.shaderProgram); + memset(&gl3state.si2Dcolor, 0, sizeof(gl3ShaderInfo_t)); +} diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 71b6acb3..c1f7c1b6 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -92,7 +92,8 @@ typedef struct float max_anisotropy; } gl3config_t; -typedef struct { +typedef struct +{ GLuint shaderProgram; GLint attribPosition; @@ -226,6 +227,7 @@ extern void GL3_SetSky(char *name, float rotate, vec3_t axis); // gl3_shaders.c extern qboolean GL3_InitShaders(void); +extern void GL3_ShutdownShaders(void); // ############ Cvars ###########