diff --git a/src/client/refresh/gl3/gl3_mesh.c b/src/client/refresh/gl3/gl3_mesh.c index 979ba6ef..ff6fc268 100644 --- a/src/client/refresh/gl3/gl3_mesh.c +++ b/src/client/refresh/gl3/gl3_mesh.c @@ -87,7 +87,6 @@ LerpVerts(int nverts, dtrivertx_t *v, dtrivertx_t *ov, static void DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) { - unsigned short total; GLenum type; float l; daliasframe_t *frame, *oldframe; @@ -101,6 +100,10 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) int i; int index_xyz; float *lerp; + // draw without texture? used for quad damage effect etc, I think + qboolean colorOnly = 0 != (currententity->flags & + (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | + RF_SHELL_HALF_DAM)); frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + currententity->frame * paliashdr->framesize); @@ -121,12 +124,13 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) alpha = 1.0; } - if (currententity->flags & - (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | - RF_SHELL_HALF_DAM)) + if (colorOnly) { - //glDisable(GL_TEXTURE_2D); - STUB_ONCE("TODO: OpenGL: use color-only shader!"); + GL3_UseProgram(gl3state.si3DaliasColor.shaderProgram); + } + else + { + GL3_UseProgram(gl3state.si3Dalias.shaderProgram); } frontlerp = 1.0 - backlerp; @@ -156,6 +160,14 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) LerpVerts(paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv); + typedef struct { + GLfloat pos[3]; + GLfloat texCoord[2]; + GLfloat color[4]; + } gl3_alias_vtx; + + assert(sizeof(gl3_alias_vtx) == 9*sizeof(GLfloat)); + while (1) { /* get the vertex count and primitive type */ @@ -177,82 +189,58 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp) type = GL_TRIANGLE_STRIP; } - total = count; - GLfloat vtx[3*total]; - GLfloat tex[2*total]; - GLfloat clr[4 * total]; - unsigned int index_vtx = 0; - unsigned int index_tex = 0; - unsigned int index_clr = 0; + gl3_alias_vtx buf[count]; - if (currententity->flags & - (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE)) + if (colorOnly) { - do + int i; + for(i=0; ipos[j] = s_lerped[index_xyz][j]; + cur->color[j] = shadelight[j]; + } + cur->color[3] = alpha; } - while (--count); } else { - do + int i; + for(i=0; itexCoord[0] = ((float *) order)[0]; + cur->texCoord[1] = ((float *) order)[1]; index_xyz = order[2]; + order += 3; /* normals and vertexes come from the frame list */ l = shadedots[verts[index_xyz].lightnormalindex]; - clr[index_clr++] = l * shadelight[0]; - clr[index_clr++] = l * shadelight[1]; - clr[index_clr++] = l * shadelight[2]; - clr[index_clr++] = alpha; - - vtx[index_vtx++] = s_lerped[index_xyz][0]; - vtx[index_vtx++] = s_lerped[index_xyz][1]; - vtx[index_vtx++] = s_lerped[index_xyz][2]; + for(j=0; j<3; ++j) + { + cur->pos[j] = s_lerped[index_xyz][j]; + cur->color[j] = l * shadelight[j]; + } + cur->color[3] = alpha; } - while (--count); } - STUB_ONCE("TODO: OpenGL!"); -#if 0 - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + GL3_BindVAO(gl3state.vaoAlias); + GL3_BindVBO(gl3state.vboAlias); - glVertexPointer(3, GL_FLOAT, 0, vtx); - glTexCoordPointer(2, GL_FLOAT, 0, tex); - glColorPointer(4, GL_FLOAT, 0, clr); - glDrawArrays(type, 0, total); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); -#endif // 0 - } - - if (currententity->flags & - (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | - RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM)) - { - STUB_ONCE("TODO: OpenGL: use textured shader!"); - //glEnable(GL_TEXTURE_2D); + glBufferData(GL_ARRAY_BUFFER, count*sizeof(gl3_alias_vtx), buf, GL_STREAM_DRAW); + glDrawArrays(type, 0, count); } } @@ -271,7 +259,7 @@ DrawAliasShadow(dmdl_t *paliashdr, int posenum) height = -lheight + 0.1f; /* stencilbuffer shadows */ - STUB_ONCE("TODO: OpenGL: stencil shadows!"); + STUB_ONCE("TODO: OpenGL: *proper* stencil shadows!"); #if 0 if (have_stencil && gl_stencilshadow->value) { @@ -655,6 +643,7 @@ GL3_DrawAliasModel(entity_t *e) shadelight[2] = 0.0; } + // TODO: maybe we could somehow store the non-rotated normal and do the dot in shader? shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; @@ -667,8 +656,8 @@ GL3_DrawAliasModel(entity_t *e) /* locate the proper data */ c_alias_polys += paliashdr->num_tris; - STUB_ONCE("TODO: OpenGL3 stuff!"); -#if 0 + + /* draw all the triangles */ if (currententity->flags & RF_DEPTHHACK) { @@ -676,6 +665,8 @@ GL3_DrawAliasModel(entity_t *e) glDepthRange(gl3depthmin, gl3depthmin + 0.3 * (gl3depthmax - gl3depthmin)); } + STUB_ONCE("TODO: Weapon model left hand (special case!)"); +#if 0 if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F)) { extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, @@ -692,12 +683,15 @@ GL3_DrawAliasModel(entity_t *e) glCullFace(GL_BACK); } +#endif // 0 + + //glPushMatrix(); + hmm_mat4 origMVmat = gl3state.uni3DData.transModelViewMat4; - glPushMatrix(); e->angles[PITCH] = -e->angles[PITCH]; GL3_RotateForEntity(e); e->angles[PITCH] = -e->angles[PITCH]; -#endif // 0 + /* select skin */ if (currententity->skin) @@ -728,18 +722,19 @@ GL3_DrawAliasModel(entity_t *e) GL3_Bind(skin->texnum); - STUB_ONCE("TODO: OpenGL3 stuff!"); + STUB_ONCE("TODO: OpenGL3 stuff (shade model, texenv)!"); #if 0 /* draw it */ glShadeModel(GL_SMOOTH); R_TexEnv(GL_MODULATE); +#endif // 0 if (currententity->flags & RF_TRANSLUCENT) { glEnable(GL_BLEND); } -#endif // 0 + if ((currententity->frame >= paliashdr->num_frames) || (currententity->frame < 0)) @@ -769,12 +764,16 @@ GL3_DrawAliasModel(entity_t *e) DrawAliasFrameLerp(paliashdr, currententity->backlerp); STUB_ONCE("TODO: even more OpenGL3 stuff!"); + + //R_TexEnv(GL_REPLACE); + //glShadeModel(GL_FLAT); + + //glPopMatrix(); + gl3state.uni3DData.transModelViewMat4 = origMVmat; + GL3_UpdateUBO3D(); + + #if 0 - R_TexEnv(GL_REPLACE); - glShadeModel(GL_FLAT); - - glPopMatrix(); - if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F)) { glMatrixMode(GL_PROJECTION); @@ -782,6 +781,8 @@ GL3_DrawAliasModel(entity_t *e) glMatrixMode(GL_MODELVIEW); glCullFace(GL_FRONT); } +#endif // 0 + if (currententity->flags & RF_TRANSLUCENT) { @@ -790,9 +791,10 @@ GL3_DrawAliasModel(entity_t *e) if (currententity->flags & RF_DEPTHHACK) { - glDepthRange(gldepthmin, gldepthmax); + glDepthRange(gl3depthmin, gl3depthmax); } +#if 0 if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW))) { diff --git a/src/client/refresh/gl3/gl3_shaders.c b/src/client/refresh/gl3/gl3_shaders.c index 89bf332e..bf5202a1 100644 --- a/src/client/refresh/gl3/gl3_shaders.c +++ b/src/client/refresh/gl3/gl3_shaders.c @@ -108,6 +108,7 @@ CreateShaderProgram(int numShaders, const GLuint* shaders) glBindAttribLocation(shaderProgram, GL3_ATTRIB_POSITION, "position"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_TEXCOORD, "texCoord"); glBindAttribLocation(shaderProgram, GL3_ATTRIB_LMTEXCOORD, "lmTexCoord"); + glBindAttribLocation(shaderProgram, GL3_ATTRIB_COLOR, "vertColor"); // the following line is not necessary/implicit (as there's only one output) // glBindFragDataLocation(shaderProgram, 0, "outColor"); XXX would this even be here? @@ -258,6 +259,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n in vec3 position; // GL3_ATTRIB_POSITION in vec2 texCoord; // GL3_ATTRIB_TEXCOORD in vec2 lmTexCoord; // GL3_ATTRIB_LMTEXCOORD + in vec4 vertColor; // GL3_ATTRIB_COLOR out vec2 passTexCoord; @@ -354,6 +356,62 @@ static const char* vertexSrc3Dflow = MULTILINE_STRING( } ); +static const char* vertexSrcAlias = MULTILINE_STRING( + + // it gets attributes and uniforms from vertexCommon3D + + out vec4 passColor; + + void main() + { + passColor = vertColor; + passTexCoord = texCoord; + gl_Position = transProj * transModelView * vec4(position, 1.0); + } +); + +static const char* fragmentSrcAlias = MULTILINE_STRING( + + // it gets attributes and uniforms from fragmentCommon3D + + uniform sampler2D tex; + + in vec4 passColor; + + void main() + { + vec4 texel = texture(tex, passTexCoord); + + // apply gamma correction and intensity + texel.rgb *= intensity; + texel.a *= alpha; // is alpha even used here? + + // TODO: is this really equivalent to GL_MODULATE's behavior of texture vs glColor()? + texel *= passColor; + + outColor.rgb = pow(texel.rgb, vec3(gamma)); + outColor.a = texel.a; // I think alpha shouldn't be modified by gamma and intensity + } +); + +static const char* fragmentSrcAliasColor = MULTILINE_STRING( + + // it gets attributes and uniforms from fragmentCommon3D + + in vec4 passColor; + + void main() + { + vec4 texel = passColor; + + // apply gamma correction and intensity + texel.rgb *= intensity; + texel.a *= alpha; // is alpha even used here? + outColor.rgb = pow(texel.rgb, vec3(gamma)); + outColor.a = texel.a; // I think alpha shouldn't be modified by gamma and intensity + } +); + #undef MULTILINE_STRING @@ -608,6 +666,18 @@ qboolean GL3_InitShaders(void) R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for scrolling textures 3D rendering!\n"); return false; } + if(!initShader3D(&gl3state.si3Dalias, vertexSrcAlias, fragmentSrcAlias)) + { + R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for rendering textured models!\n"); + return false; + } + if(!initShader3D(&gl3state.si3DaliasColor, vertexSrcAlias, fragmentSrcAliasColor)) + { + R_Printf(PRINT_ALL, "WARNING: Failed to create shader program for rendering flat-colored models!\n"); + return false; + } + + gl3state.currentShaderProgram = 0; return true; diff --git a/src/client/refresh/gl3/gl3_surf.c b/src/client/refresh/gl3/gl3_surf.c index 39f0fef1..49354fe4 100644 --- a/src/client/refresh/gl3/gl3_surf.c +++ b/src/client/refresh/gl3/gl3_surf.c @@ -59,6 +59,22 @@ void GL3_SurfInit(void) glEnableVertexAttribArray(GL3_ATTRIB_LMTEXCOORD); qglVertexAttribPointer(GL3_ATTRIB_LMTEXCOORD, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE*sizeof(GLfloat), 5*sizeof(GLfloat)); + + + glGenVertexArrays(1, &gl3state.vaoAlias); + GL3_BindVAO(gl3state.vaoAlias); + + glGenBuffers(1, &gl3state.vboAlias); + GL3_BindVBO(gl3state.vboAlias); + + glEnableVertexAttribArray(GL3_ATTRIB_POSITION); + qglVertexAttribPointer(GL3_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 0); + + glEnableVertexAttribArray(GL3_ATTRIB_TEXCOORD); + qglVertexAttribPointer(GL3_ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 3*sizeof(GLfloat)); + + glEnableVertexAttribArray(GL3_ATTRIB_COLOR); + qglVertexAttribPointer(GL3_ATTRIB_COLOR, 2, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), 5*sizeof(GLfloat)); } void GL3_SurfShutdown(void) @@ -67,6 +83,11 @@ void GL3_SurfShutdown(void) gl3state.vbo3D = 0; glDeleteVertexArrays(1, &gl3state.vao3D); gl3state.vao3D = 0; + + glDeleteBuffers(1, &gl3state.vboAlias); + gl3state.vboAlias = 0; + glDeleteVertexArrays(1, &gl3state.vaoAlias); + gl3state.vaoAlias = 0; } /* diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 91ae2ef0..818b9f83 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -69,6 +69,7 @@ enum { GL3_ATTRIB_POSITION = 0, GL3_ATTRIB_TEXCOORD = 1, // for normal texture GL3_ATTRIB_LMTEXCOORD = 2, // for lightmap + GL3_ATTRIB_COLOR = 3, // per-vertex color // TODO: more? maybe normal and color? }; @@ -105,11 +106,6 @@ typedef struct 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? - } gl3ShaderInfo_t; typedef struct @@ -171,8 +167,11 @@ typedef struct gl3ShaderInfo_t si3D; gl3ShaderInfo_t si3Dturb; // for water etc gl3ShaderInfo_t si3Dflow; // for flowing/scrolling things (conveyor, ..?) + gl3ShaderInfo_t si3Dalias; // for models + gl3ShaderInfo_t si3DaliasColor; // for models w/ flat colors GLuint vao3D, vbo3D; // for brushes etc, using 7 floats as vertex input (x,y,z, s,t, lms,lmt) + GLuint vaoAlias, vboAlias; // for models, using 9 floats as (x,y,z, s,t, r,g,b,a) // UBOs and their data gl3UniCommon_t uniCommonData;