From 1a7ad9ddfb9cc57f86426a587979f94dd1a2274c Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 20 Jul 2018 23:40:39 -0500 Subject: [PATCH] OpenGL1: Use vertex arrays instead of glBegin This is loosely based on the OpenPandora OpenGL ES port by ptitSeb. Some of the changes were backported from the opengl2 renderer. It runs faster, at least on modern hardware, and is requires for OpenGL ES support. r_primatives cvar values 1 and 3 still use glBegin as they have to use it by definition. --- code/qcommon/q_shared.h | 5 +++ code/renderergl1/tr_backend.c | 80 ++++++++++++++++++++++++++--------- code/renderergl1/tr_local.h | 6 ++- code/renderergl1/tr_main.c | 33 +++++++++------ code/renderergl1/tr_shade.c | 52 +++++++++++++++++++---- code/renderergl1/tr_shadows.c | 72 +++++++++++++++++++++++-------- code/renderergl1/tr_sky.c | 71 +++++++++++++++++++++++++++---- code/renderergl1/tr_surface.c | 73 +++++++++++++++++++++++--------- code/renderergl2/tr_backend.c | 39 ++++++++--------- code/renderergl2/tr_local.h | 4 +- code/renderergl2/tr_main.c | 33 +++++++++------ code/renderergl2/tr_shadows.c | 75 +++++++++++++++++++++++--------- code/renderergl2/tr_sky.c | 39 ++++++++--------- 13 files changed, 418 insertions(+), 164 deletions(-) diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 86d9ac47c3..4b6d80f2a5 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -576,6 +576,11 @@ typedef struct { #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) + +#define Vector2Set(v, x, y) ((v)[0]=(x), (v)[1]=(y)) +#define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1]) + +#define Vector4Set(v, x, y, z, w) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z), (v)[3]=(w)) #define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) #define Byte4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) diff --git a/code/renderergl1/tr_backend.c b/code/renderergl1/tr_backend.c index 56cf37d12b..c7f73f8ee3 100644 --- a/code/renderergl1/tr_backend.c +++ b/code/renderergl1/tr_backend.c @@ -719,6 +719,45 @@ void RB_SetGL2D (void) { backEnd.refdef.floatTime = backEnd.refdef.time * 0.001; } +/* +================ +RB_InstantQuad2 +================ +*/ +void RB_InstantQuad2( vec4_t quadVerts[4], vec2_t texCoords[2] ) { + glIndex_t indexes[6]; + + qglDisableClientState( GL_COLOR_ARRAY ); + qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + + qglTexCoordPointer( 2, GL_FLOAT, 0, texCoords ); + qglVertexPointer( 3, GL_FLOAT, 16, quadVerts ); + + indexes[0] = 0; + indexes[1] = 1; + indexes[2] = 2; + indexes[3] = 0; + indexes[4] = 2; + indexes[5] = 3; + + R_DrawElements( 6, indexes ); +} + +/* +================ +RB_InstantQuad +===============- +*/ +void RB_InstantQuad( vec4_t quadVerts[4] ) { + vec2_t texCoords[4] = { + { 0, 0 }, + { 1, 0 }, + { 1, 1 }, + { 0, 1 } + }; + + RB_InstantQuad2( quadVerts, texCoords ); +} /* ============= @@ -732,6 +771,8 @@ Used for cinematics. void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { int i, j; int start, end; + vec4_t quadVerts[4]; + vec2_t texCoords[4]; if ( !tr.registered ) { return; @@ -771,16 +812,17 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); - qglBegin (GL_QUADS); - qglTexCoord2f ( 0.5f / cols, 0.5f / rows ); - qglVertex2f (x, y); - qglTexCoord2f ( ( cols - 0.5f ) / cols , 0.5f / rows ); - qglVertex2f (x+w, y); - qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows ); - qglVertex2f (x+w, y+h); - qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows ); - qglVertex2f (x, y+h); - qglEnd (); + Vector4Set( quadVerts[0], x, y, 0.0f, 1.0f ); + Vector4Set( quadVerts[1], x + w, y, 0.0f, 1.0f ); + Vector4Set( quadVerts[2], x + w, y + h, 0.0f, 1.0f ); + Vector4Set( quadVerts[3], x, y + h, 0.0f, 1.0f ); + + Vector2Set( texCoords[0], 0.5f / cols, 0.5f / rows ); + Vector2Set( texCoords[1], (cols - 0.5f) / cols, 0.5f / rows ); + Vector2Set( texCoords[2], (cols - 0.5f) / cols, (rows - 0.5f) / rows ); + Vector2Set( texCoords[3], 0.5f / cols, (rows - 0.5f) / rows ); + + RB_InstantQuad2( quadVerts, texCoords ); } void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { @@ -963,6 +1005,7 @@ void RB_ShowImages( void ) { image_t *image; float x, y, w, h; int start, end; + vec4_t quadVerts[4]; if ( !backEnd.projection2D ) { RB_SetGL2D(); @@ -989,16 +1032,13 @@ void RB_ShowImages( void ) { } GL_Bind( image ); - qglBegin (GL_QUADS); - qglTexCoord2f( 0, 0 ); - qglVertex2f( x, y ); - qglTexCoord2f( 1, 0 ); - qglVertex2f( x + w, y ); - qglTexCoord2f( 1, 1 ); - qglVertex2f( x + w, y + h ); - qglTexCoord2f( 0, 1 ); - qglVertex2f( x, y + h ); - qglEnd(); + + Vector4Set( quadVerts[0], x, y, 0, 1 ); + Vector4Set( quadVerts[1], x + w, y, 0, 1 ); + Vector4Set( quadVerts[2], x + w, y + h, 0, 1 ); + Vector4Set( quadVerts[3], x, y + h, 0, 1 ); + + RB_InstantQuad( quadVerts ); } qglFinish(); diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index e07f575bb6..8aac61fc17 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -1224,10 +1224,12 @@ typedef struct stageVars } stageVars_t; +// xyz index SHADER_MAX_VERTEXES-1 is used to check for overflow +// xyz index >= SHADER_MAX_VERTEXES are used for DrawNormals() and RB_ShadowTessEnd() typedef struct shaderCommands_s { glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16); - vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16); + vec4_t xyz[SHADER_MAX_VERTEXES*2] QALIGN(16); vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16); vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16); color4ub_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16); @@ -1266,6 +1268,8 @@ void RB_StageIteratorLightmappedMultitexture( void ); void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, byte *color ); void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, byte *color, float s1, float t1, float s2, float t2 ); +void RB_InstantQuad( vec4_t quadVerts[4] ); +void RB_InstantQuad2( vec4_t quadVerts[4], vec2_t texCoords[4] ); void RB_ShowImages( void ); diff --git a/code/renderergl1/tr_main.c b/code/renderergl1/tr_main.c index 09559a2e71..61e264a1f4 100644 --- a/code/renderergl1/tr_main.c +++ b/code/renderergl1/tr_main.c @@ -1299,29 +1299,36 @@ R_DebugPolygon ================ */ void R_DebugPolygon( int color, int numPoints, float *points ) { - int i; + if ( numPoints < 3 ) { + ri.Printf( PRINT_WARNING, "Debug polygon with color 0x%08X only has %d points (must have at least 3)\n", color, numPoints ); + return; + } GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + qglDisableClientState( GL_COLOR_ARRAY ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - // draw solid shade + qglVertexPointer( 3, GL_FLOAT, 0, points ); - qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); + if (qglLockArraysEXT) { + qglLockArraysEXT(0, numPoints); + GLimp_LogComment( "glLockArraysEXT\n" ); } - qglEnd(); + + // draw solid shade + qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); + qglDrawArrays( GL_TRIANGLE_FAN, 0, numPoints ); // draw wireframe outline - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); qglDepthRange( 0, 0 ); qglColor3f( 1, 1, 1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); - } - qglEnd(); + qglDrawArrays( GL_LINE_LOOP, 0, numPoints ); qglDepthRange( 0, 1 ); + + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } } /* diff --git a/code/renderergl1/tr_shade.c b/code/renderergl1/tr_shade.c index 7ea78d1302..2e78320fe6 100644 --- a/code/renderergl1/tr_shade.c +++ b/code/renderergl1/tr_shade.c @@ -254,15 +254,31 @@ Draws triangle outlines for debugging ================ */ static void DrawTris (shaderCommands_t *input) { + glIndex_t lineIndexes[SHADER_MAX_INDEXES*2]; + int i, numTris; + GL_Bind( tr.whiteImage ); qglColor3f (1,1,1); - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); + GL_State( GLS_DEPTHMASK_TRUE ); qglDepthRange( 0, 0 ); qglDisableClientState (GL_COLOR_ARRAY); qglDisableClientState (GL_TEXTURE_COORD_ARRAY); + // convert triangles to lines + numTris = tess.numIndexes / 3; + for (i = 0 ; i < numTris; i++) { + lineIndexes[i*6+0] = input->indexes[i*3+0]; + lineIndexes[i*6+1] = input->indexes[i*3+1]; + + lineIndexes[i*6+2] = input->indexes[i*3+1]; + lineIndexes[i*6+3] = input->indexes[i*3+2]; + + lineIndexes[i*6+4] = input->indexes[i*3+2]; + lineIndexes[i*6+5] = input->indexes[i*3+0]; + } + qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD if (qglLockArraysEXT) { @@ -270,7 +286,7 @@ static void DrawTris (shaderCommands_t *input) { GLimp_LogComment( "glLockArraysEXT\n" ); } - R_DrawElements( input->numIndexes, input->indexes ); + qglDrawElements( GL_LINES, numTris*6, GL_INDEX_TYPE, lineIndexes ); if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); @@ -288,23 +304,41 @@ Draws vertex normals for debugging ================ */ static void DrawNormals (shaderCommands_t *input) { + glIndex_t lineIndexes[SHADER_MAX_INDEXES*2]; int i; - vec3_t temp; GL_Bind( tr.whiteImage ); qglColor3f (1,1,1); qglDepthRange( 0, 0 ); // never occluded - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); + GL_State( GLS_DEPTHMASK_TRUE ); + + qglDisableClientState (GL_COLOR_ARRAY); + qglDisableClientState (GL_TEXTURE_COORD_ARRAY); - qglBegin (GL_LINES); for (i = 0 ; i < input->numVertexes ; i++) { - qglVertex3fv (input->xyz[i]); - VectorMA (input->xyz[i], 2, input->normal[i], temp); - qglVertex3fv (temp); + VectorMA( input->xyz[i], 2, input->normal[i], input->xyz[i + input->numVertexes] ); + + lineIndexes[i*2] = i; + lineIndexes[i*2+1] = i + input->numVertexes; + } + + qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD + + if (qglLockArraysEXT) { + qglLockArraysEXT(0, input->numVertexes * 2); + GLimp_LogComment( "glLockArraysEXT\n" ); } - qglEnd (); + qglDrawElements( GL_LINES, input->numVertexes * 2, GL_INDEX_TYPE, lineIndexes ); + + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } qglDepthRange( 0, 1 ); + + // FIXME: kind of ugly to have to clear this to avoid overflow detection. + memset( input->xyz[SHADER_MAX_VERTEXES-1], 0, sizeof ( input->xyz[0] ) ); } /* diff --git a/code/renderergl1/tr_shadows.c b/code/renderergl1/tr_shadows.c index 13fbfdf74e..89426d9a1b 100644 --- a/code/renderergl1/tr_shadows.c +++ b/code/renderergl1/tr_shadows.c @@ -44,7 +44,8 @@ typedef struct { static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; static int numEdgeDefs[SHADER_MAX_VERTEXES]; static int facing[SHADER_MAX_INDEXES/3]; -static vec3_t shadowXyz[SHADER_MAX_VERTEXES]; +static glIndex_t shadowIndexes[SHADER_MAX_VERTEXES*MAX_EDGE_DEFS*6]; +static int numShadowIndexes; void R_AddEdgeDef( int i1, int i2, int facing ) { int c; @@ -59,7 +60,7 @@ void R_AddEdgeDef( int i1, int i2, int facing ) { numEdgeDefs[ i1 ]++; } -void R_RenderShadowEdges( void ) { +void R_CalculateShadowEdges( void ) { int i; #if 0 @@ -68,6 +69,8 @@ void R_RenderShadowEdges( void ) { // dumb way -- render every triangle's edges numTris = tess.numIndexes / 3; + numShadowIndexes = 0; + for ( i = 0 ; i < numTris ; i++ ) { int i1, i2, i3; @@ -79,15 +82,16 @@ void R_RenderShadowEdges( void ) { i2 = tess.indexes[ i*3 + 1 ]; i3 = tess.indexes[ i*3 + 2 ]; + // FIXME: Convert to using shadowIndexes qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( shadowXyz[ i1 ] ); + qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( shadowXyz[ i2 ] ); + qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i3 ] ); - qglVertex3fv( shadowXyz[ i3 ] ); + qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( shadowXyz[ i1 ] ); + qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); qglEnd(); } #else @@ -97,6 +101,8 @@ void R_RenderShadowEdges( void ) { int c_edges, c_rejected; int hit[2]; + numShadowIndexes = 0; + // an edge is NOT a silhouette edge if its face doesn't face the light, // or if it has a reverse paired edge that also faces the light. // A well behaved polyhedron would have exactly two faces for each edge, @@ -123,14 +129,23 @@ void R_RenderShadowEdges( void ) { } // if it doesn't share the edge with another front facing - // triangle, it is a sil edge + // triangle, it is a silhouette edge if ( hit[ 1 ] == 0 ) { +/* qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i ] ); - qglVertex3fv( shadowXyz[ i ] ); + qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( shadowXyz[ i2 ] ); + qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); qglEnd(); +*/ + shadowIndexes[numShadowIndexes++] = i; + shadowIndexes[numShadowIndexes++] = i + tess.numVertexes; + shadowIndexes[numShadowIndexes++] = i2; + + shadowIndexes[numShadowIndexes++] = i2; + shadowIndexes[numShadowIndexes++] = i + tess.numVertexes; + shadowIndexes[numShadowIndexes++] = i2 + tess.numVertexes; c_edges++; } else { c_rejected++; @@ -166,7 +181,7 @@ void RB_ShadowTessEnd( void ) { // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { - VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] ); + VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i + tess.numVertexes] ); } // decide which triangles face the light @@ -204,12 +219,24 @@ void RB_ShadowTessEnd( void ) { R_AddEdgeDef( i3, i1, facing[ i ] ); } + R_CalculateShadowEdges(); + // draw the silhouette edges GL_Bind( tr.whiteImage ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor3f( 0.2f, 0.2f, 0.2f ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + qglDisableClientState( GL_COLOR_ARRAY ); + + qglVertexPointer( 3, GL_FLOAT, 16, tess.xyz ); // padded for SIMD + + if (qglLockArraysEXT) { + qglLockArraysEXT(0, tess.numVertexes*2); + GLimp_LogComment( "glLockArraysEXT\n" ); + } + // don't write to the color buffer qglGetBooleanv(GL_COLOR_WRITEMASK, rgba); qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); @@ -220,16 +247,23 @@ void RB_ShadowTessEnd( void ) { GL_Cull( CT_BACK_SIDED ); qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - R_RenderShadowEdges(); + R_DrawElements( numShadowIndexes, shadowIndexes ); GL_Cull( CT_FRONT_SIDED ); qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - R_RenderShadowEdges(); + R_DrawElements( numShadowIndexes, shadowIndexes ); + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } // reenable writing to the color buffer qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]); + + // FIXME: kind of ugly to have to clear this to avoid overflow detection. + memset( tess.xyz[SHADER_MAX_VERTEXES-1], 0, sizeof ( tess.xyz[0] ) ); } @@ -244,6 +278,8 @@ overlap and double darken. ================= */ void RB_ShadowFinish( void ) { + vec4_t quadVerts[4]; + if ( r_shadows->integer != 2 ) { return; } @@ -266,12 +302,12 @@ void RB_ShadowFinish( void ) { // qglColor3f( 1, 0, 0 ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - qglBegin( GL_QUADS ); - qglVertex3f( -100, 100, -10 ); - qglVertex3f( 100, 100, -10 ); - qglVertex3f( 100, -100, -10 ); - qglVertex3f( -100, -100, -10 ); - qglEnd (); + Vector4Set( quadVerts[0], -100, 100, -10, 0 ); + Vector4Set( quadVerts[1], 100, 100, -10, 0 ); + Vector4Set( quadVerts[2], 100, -100, -10, 0 ); + Vector4Set( quadVerts[3], -100, -100, -10, 0 ); + + RB_InstantQuad( quadVerts ); qglColor4f(1,1,1,1); qglDisable( GL_STENCIL_TEST ); diff --git a/code/renderergl1/tr_sky.c b/code/renderergl1/tr_sky.c index 1d12e924ec..63e6ce61fe 100644 --- a/code/renderergl1/tr_sky.c +++ b/code/renderergl1/tr_sky.c @@ -361,27 +361,82 @@ static int sky_texorder[6] = {0,2,1,3,4,5}; static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; +// NOTE: This reuses the tess structure out of convience but it doesn't use the shader system. static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t; + int vertexStart = tess.numVertexes; + int indexStart = tess.numIndexes; + int tHeight, sWidth; + + tHeight = maxs[1] - mins[1] + 1; + sWidth = maxs[0] - mins[0] + 1; GL_Bind( image ); - for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) + for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { - qglBegin( GL_TRIANGLE_STRIP ); - for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { - qglTexCoord2fv( s_skyTexCoords[t][s] ); - qglVertex3fv( s_skyPoints[t][s] ); + VectorCopy( s_skyPoints[t][s], tess.xyz[tess.numVertexes] ); + + tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; + tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; + + tess.numVertexes++; + + if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) + { + ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySide()" ); + } + } + } + + for ( t = 0; t < tHeight-1; t++ ) + { + for ( s = 0; s < sWidth-1; s++ ) + { + if ( tess.numIndexes + 6 >= SHADER_MAX_INDEXES ) + { + ri.Error( ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySide()" ); + } - qglTexCoord2fv( s_skyTexCoords[t+1][s] ); - qglVertex3fv( s_skyPoints[t+1][s] ); + tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); + tess.numIndexes++; + + tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth ); + tess.numIndexes++; + tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth ); + tess.numIndexes++; } + } + + qglDisableClientState( GL_COLOR_ARRAY ); + qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - qglEnd(); + qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); + qglVertexPointer( 3, GL_FLOAT, 16, tess.xyz ); + + if (qglLockArraysEXT) { + qglLockArraysEXT(0, tess.numIndexes); + GLimp_LogComment( "glLockArraysEXT\n" ); } + + R_DrawElements( tess.numIndexes - indexStart, tess.indexes + indexStart ); + + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } + + tess.numVertexes = vertexStart; + tess.numIndexes = indexStart; } static void DrawSkyBox( shader_t *shader ) diff --git a/code/renderergl1/tr_surface.c b/code/renderergl1/tr_surface.c index 41e72738d8..61bf9d033e 100644 --- a/code/renderergl1/tr_surface.c +++ b/code/renderergl1/tr_surface.c @@ -288,7 +288,8 @@ static void RB_SurfaceBeam( void ) int i; vec3_t perpvec; vec3_t direction, normalized_direction; - vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; + vec4_t vertexes[(NUM_BEAM_SEGS+1)*2] QALIGN(16); + float *start_point, *end_point; // pointers to vec4_t vec3_t oldorigin, origin; e = &backEnd.currentEntity->e; @@ -314,23 +315,40 @@ static void RB_SurfaceBeam( void ) for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) { - RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); -// VectorAdd( start_points[i], origin, start_points[i] ); - VectorAdd( start_points[i], direction, end_points[i] ); + start_point = vertexes[i*2]; + end_point = vertexes[i*2+1]; + + RotatePointAroundVector( start_point, normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); +// VectorAdd( start_point, origin, start_point ); + VectorAdd( start_point, direction, end_point ); } + // duplicate first start/end points + VectorCopy( vertexes[0], vertexes[NUM_BEAM_SEGS*2] ); + VectorCopy( vertexes[1], vertexes[NUM_BEAM_SEGS*2+1] ); + GL_Bind( tr.whiteImage ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); qglColor3f( 1, 0, 0 ); - qglBegin( GL_TRIANGLE_STRIP ); - for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { - qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] ); - qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + qglDisableClientState( GL_COLOR_ARRAY ); + + qglVertexPointer( 3, GL_FLOAT, 16, vertexes ); // padded for SIMD + + if (qglLockArraysEXT) { + qglLockArraysEXT(0, ARRAY_LEN(vertexes)); + GLimp_LogComment( "glLockArraysEXT\n" ); + } + + qglDrawArrays( GL_TRIANGLE_STRIP, 0, ARRAY_LEN(vertexes) ); + + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); } - qglEnd(); } //================================================================================ @@ -1026,20 +1044,35 @@ Draws x/y/z lines from the origin for orientation debugging =================== */ static void RB_SurfaceAxis( void ) { + vec4_t colors[6] = { + { 1,0,0,1 }, + { 1,0,0,1 }, + { 0,1,0,1 }, + { 0,1,0,1 }, + { 0,0,1,1 }, + { 0,0,1,1 } + }; + vec4_t vertexes[6] = { + { 0, 0, 0, 0 }, + { 16, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 16, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 16, 0 } + }; + GL_Bind( tr.whiteImage ); GL_State( GLS_DEFAULT ); qglLineWidth( 3 ); - qglBegin( GL_LINES ); - qglColor3f( 1,0,0 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 16,0,0 ); - qglColor3f( 0,1,0 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 0,16,0 ); - qglColor3f( 0,0,1 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 0,0,16 ); - qglEnd(); + + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + qglEnableClientState( GL_COLOR_ARRAY ); + + qglColorPointer( 4, GL_FLOAT, 0, colors ); + qglVertexPointer( 3, GL_FLOAT, 16, vertexes ); // padded for SIMD + + qglDrawArrays( GL_LINES, 0, 6 ); + qglLineWidth( 1 ); } diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index df54528b01..9ca32633aa 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -671,8 +671,8 @@ Used for cinematics. void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { int i, j; int start, end; - vec4_t quadVerts[4]; - vec2_t texCoords[4]; + vec4_t quadVerts[4]; + vec2_t texCoords[4]; if ( !tr.registered ) { return; @@ -716,22 +716,22 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * RB_SetGL2D(); - VectorSet4(quadVerts[0], x, y, 0.0f, 1.0f); - VectorSet4(quadVerts[1], x + w, y, 0.0f, 1.0f); - VectorSet4(quadVerts[2], x + w, y + h, 0.0f, 1.0f); - VectorSet4(quadVerts[3], x, y + h, 0.0f, 1.0f); + Vector4Set( quadVerts[0], x, y, 0.0f, 1.0f ); + Vector4Set( quadVerts[1], x + w, y, 0.0f, 1.0f ); + Vector4Set( quadVerts[2], x + w, y + h, 0.0f, 1.0f ); + Vector4Set( quadVerts[3], x, y + h, 0.0f, 1.0f ); - VectorSet2(texCoords[0], 0.5f / cols, 0.5f / rows); - VectorSet2(texCoords[1], (cols - 0.5f) / cols, 0.5f / rows); - VectorSet2(texCoords[2], (cols - 0.5f) / cols, (rows - 0.5f) / rows); - VectorSet2(texCoords[3], 0.5f / cols, (rows - 0.5f) / rows); + Vector2Set( texCoords[0], 0.5f / cols, 0.5f / rows ); + Vector2Set( texCoords[1], (cols - 0.5f) / cols, 0.5f / rows ); + Vector2Set( texCoords[2], (cols - 0.5f) / cols, (rows - 0.5f) / rows ); + Vector2Set( texCoords[3], 0.5f / cols, (rows - 0.5f) / rows ); GLSL_BindProgram(&tr.textureColorShader); GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite); - RB_InstantQuad2(quadVerts, texCoords); + RB_InstantQuad2( quadVerts, texCoords ); } void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { @@ -1221,6 +1221,7 @@ void RB_ShowImages( void ) { image_t *image; float x, y, w, h; int start, end; + vec4_t quadVerts[4]; RB_SetGL2D(); @@ -1244,18 +1245,14 @@ void RB_ShowImages( void ) { h *= image->uploadHeight / 512.0f; } - { - vec4_t quadVerts[4]; - - GL_BindToTMU(image, TB_COLORMAP); + GL_BindToTMU( image, TB_COLORMAP ); - VectorSet4(quadVerts[0], x, y, 0, 1); - VectorSet4(quadVerts[1], x + w, y, 0, 1); - VectorSet4(quadVerts[2], x + w, y + h, 0, 1); - VectorSet4(quadVerts[3], x, y + h, 0, 1); + Vector4Set( quadVerts[0], x, y, 0, 1 ); + Vector4Set( quadVerts[1], x + w, y, 0, 1 ); + Vector4Set( quadVerts[2], x + w, y + h, 0, 1 ); + Vector4Set( quadVerts[3], x, y + h, 0, 1 ); - RB_InstantQuad(quadVerts); - } + RB_InstantQuad( quadVerts ); } qglFinish(); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 39f6f7a2ba..0cf1f85ca3 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -2020,10 +2020,12 @@ typedef struct stageVars vec2_t texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES]; } stageVars_t; +// xyz index SHADER_MAX_VERTEXES-1 is used to check for overflow +// xyz index >= SHADER_MAX_VERTEXES are used for DrawNormals() and RB_ShadowTessEnd() typedef struct shaderCommands_s { glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16); - vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16); + vec4_t xyz[SHADER_MAX_VERTEXES*2] QALIGN(16); int16_t normal[SHADER_MAX_VERTEXES][4] QALIGN(16); int16_t tangent[SHADER_MAX_VERTEXES][4] QALIGN(16); vec2_t texCoords[SHADER_MAX_VERTEXES] QALIGN(16); diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 02f7d489fb..c0467d839c 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -1681,29 +1681,36 @@ R_DebugPolygon void R_DebugPolygon( int color, int numPoints, float *points ) { // FIXME: implement this #if 0 - int i; + if ( numPoints < 3 ) { + ri.Printf( PRINT_WARNING, "Debug polygon with color 0x%08X only has %d points (must have at least 3)\n", color, numPoints ); + return; + } GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + qglDisableClientState( GL_COLOR_ARRAY ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - // draw solid shade + qglVertexPointer( 3, GL_FLOAT, 0, points ); - qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); + if (qglLockArraysEXT) { + qglLockArraysEXT(0, numPoints); + GLimp_LogComment( "glLockArraysEXT\n" ); } - qglEnd(); + + // draw solid shade + qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); + qglDrawArrays( GL_TRIANGLE_FAN, 0, numPoints ); // draw wireframe outline - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); qglDepthRange( 0, 0 ); qglColor3f( 1, 1, 1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); - } - qglEnd(); + qglDrawArrays( GL_LINE_LOOP, 0, numPoints ); qglDepthRange( 0, 1 ); + + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } #endif } diff --git a/code/renderergl2/tr_shadows.c b/code/renderergl2/tr_shadows.c index 697800c137..0ec0acef98 100644 --- a/code/renderergl2/tr_shadows.c +++ b/code/renderergl2/tr_shadows.c @@ -44,7 +44,8 @@ typedef struct { static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; static int numEdgeDefs[SHADER_MAX_VERTEXES]; //static int facing[SHADER_MAX_INDEXES/3]; -//static vec3_t shadowXyz[SHADER_MAX_VERTEXES]; +static glIndex_t shadowIndexes[SHADER_MAX_VERTEXES*MAX_EDGE_DEFS*6]; +static int numShadowIndexes; void R_AddEdgeDef( int i1, int i2, int facing ) { int c; @@ -59,9 +60,7 @@ void R_AddEdgeDef( int i1, int i2, int facing ) { numEdgeDefs[ i1 ]++; } -void R_RenderShadowEdges( void ) { - // FIXME: implement this -#if 0 +void R_CalculateShadowEdges( void ) { int i; #if 0 @@ -70,6 +69,8 @@ void R_RenderShadowEdges( void ) { // dumb way -- render every triangle's edges numTris = tess.numIndexes / 3; + numShadowIndexes = 0; + for ( i = 0 ; i < numTris ; i++ ) { int i1, i2, i3; @@ -81,15 +82,16 @@ void R_RenderShadowEdges( void ) { i2 = tess.indexes[ i*3 + 1 ]; i3 = tess.indexes[ i*3 + 2 ]; + // FIXME: Convert to using shadowIndexes qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( shadowXyz[ i1 ] ); + qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( shadowXyz[ i2 ] ); + qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i3 ] ); - qglVertex3fv( shadowXyz[ i3 ] ); + qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( shadowXyz[ i1 ] ); + qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); qglEnd(); } #else @@ -99,6 +101,8 @@ void R_RenderShadowEdges( void ) { int c_edges, c_rejected; int hit[2]; + numShadowIndexes = 0; + // an edge is NOT a silhouette edge if its face doesn't face the light, // or if it has a reverse paired edge that also faces the light. // A well behaved polyhedron would have exactly two faces for each edge, @@ -125,14 +129,23 @@ void R_RenderShadowEdges( void ) { } // if it doesn't share the edge with another front facing - // triangle, it is a sil edge + // triangle, it is a silhouette edge if ( hit[ 1 ] == 0 ) { +/* qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i ] ); - qglVertex3fv( shadowXyz[ i ] ); + qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( shadowXyz[ i2 ] ); + qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); qglEnd(); +*/ + shadowIndexes[numShadowIndexes++] = i; + shadowIndexes[numShadowIndexes++] = i + tess.numVertexes; + shadowIndexes[numShadowIndexes++] = i2; + + shadowIndexes[numShadowIndexes++] = i2; + shadowIndexes[numShadowIndexes++] = i + tess.numVertexes; + shadowIndexes[numShadowIndexes++] = i2 + tess.numVertexes; c_edges++; } else { c_rejected++; @@ -140,7 +153,6 @@ void R_RenderShadowEdges( void ) { } } #endif -#endif } /* @@ -171,7 +183,7 @@ void RB_ShadowTessEnd( void ) { // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { - VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] ); + VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i + tess.numVertexes] ); } // decide which triangles face the light @@ -209,12 +221,24 @@ void RB_ShadowTessEnd( void ) { R_AddEdgeDef( i3, i1, facing[ i ] ); } + R_CalculateShadowEdges(); + // draw the silhouette edges GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor3f( 0.2f, 0.2f, 0.2f ); + qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + qglDisableClientState( GL_COLOR_ARRAY ); + + qglVertexPointer( 3, GL_FLOAT, 16, tess.xyz ); // padded for SIMD + + if (qglLockArraysEXT) { + qglLockArraysEXT(0, tess.numVertexes*2); + GLimp_LogComment( "glLockArraysEXT\n" ); + } + // don't write to the color buffer qglGetBooleanv(GL_COLOR_WRITEMASK, rgba); qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); @@ -225,16 +249,23 @@ void RB_ShadowTessEnd( void ) { GL_Cull( CT_BACK_SIDED ); qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - R_RenderShadowEdges(); + R_DrawElements( numShadowIndexes, shadowIndexes ); GL_Cull( CT_FRONT_SIDED ); qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - R_RenderShadowEdges(); + R_DrawElements( numShadowIndexes, shadowIndexes ); + if (qglUnlockArraysEXT) { + qglUnlockArraysEXT(); + GLimp_LogComment( "glUnlockArraysEXT\n" ); + } // reenable writing to the color buffer qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]); + + // FIXME: kind of ugly to have to clear this to avoid overflow detection. + memset( tess.xyz[SHADER_MAX_VERTEXES-1], 0, sizeof ( tess.xyz[0] ) ); #endif } @@ -252,6 +283,8 @@ overlap and double darken. void RB_ShadowFinish( void ) { // FIXME: implement this #if 0 + vec4_t quadVerts[4]; + if ( r_shadows->integer != 2 ) { return; } @@ -273,12 +306,12 @@ void RB_ShadowFinish( void ) { // qglColor3f( 1, 0, 0 ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - qglBegin( GL_QUADS ); - qglVertex3f( -100, 100, -10 ); - qglVertex3f( 100, 100, -10 ); - qglVertex3f( 100, -100, -10 ); - qglVertex3f( -100, -100, -10 ); - qglEnd (); + Vector4Set( quadVerts[0], -100, 100, -10, 0 ); + Vector4Set( quadVerts[1], 100, 100, -10, 0 ); + Vector4Set( quadVerts[2], 100, -100, -10, 0 ); + Vector4Set( quadVerts[3], -100, -100, -10, 0 ); + + RB_InstantQuad( quadVerts ); qglColor4f(1,1,1,1); qglDisable( GL_STENCIL_TEST ); diff --git a/code/renderergl2/tr_sky.c b/code/renderergl2/tr_sky.c index 94f68d26e6..c66400f0fc 100644 --- a/code/renderergl2/tr_sky.c +++ b/code/renderergl2/tr_sky.c @@ -361,57 +361,57 @@ static int sky_texorder[6] = {0,2,1,3,4,5}; static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; +// NOTE: This reuses the tess structure out of convience but it doesn't use the shader system. static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t; int firstVertex = tess.numVertexes; //int firstIndex = tess.numIndexes; - vec4_t color; + int tHeight, sWidth; + + tHeight = maxs[1] - mins[1] + 1; + sWidth = maxs[0] - mins[0] + 1; //tess.numVertexes = 0; //tess.numIndexes = 0; tess.firstIndex = tess.numIndexes; GL_BindToTMU( image, TB_COLORMAP ); - GL_Cull( CT_TWO_SIDED ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { - tess.xyz[tess.numVertexes][0] = s_skyPoints[t][s][0]; - tess.xyz[tess.numVertexes][1] = s_skyPoints[t][s][1]; - tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2]; - tess.xyz[tess.numVertexes][3] = 1.0; + VectorCopy( s_skyPoints[t][s], tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0] = s_skyTexCoords[t][s][0]; tess.texCoords[tess.numVertexes][1] = s_skyTexCoords[t][s][1]; tess.numVertexes++; - if(tess.numVertexes >= SHADER_MAX_VERTEXES) + if ( tess.numVertexes >= SHADER_MAX_VERTEXES ) { - ri.Error(ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySideVBO()"); + ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySide()" ); } } } - for ( t = 0; t < maxs[1] - mins[1]; t++ ) + for ( t = 0; t < tHeight-1; t++ ) { - for ( s = 0; s < maxs[0] - mins[0]; s++ ) + for ( s = 0; s < sWidth-1; s++ ) { - if (tess.numIndexes + 6 >= SHADER_MAX_INDEXES) + if ( tess.numIndexes + 6 >= SHADER_MAX_INDEXES ) { - ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()"); + ri.Error( ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySide()" ); } - tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; + tess.indexes[tess.numIndexes++] = s + t * sWidth + firstVertex; + tess.indexes[tess.numIndexes++] = s + (t + 1) * sWidth + firstVertex; + tess.indexes[tess.numIndexes++] = (s + 1) + t * sWidth + firstVertex; - tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; + tess.indexes[tess.numIndexes++] = (s + 1) + t * sWidth + firstVertex; + tess.indexes[tess.numIndexes++] = s + (t + 1) * sWidth + firstVertex; + tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * sWidth + firstVertex; } } @@ -420,6 +420,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max /* { shaderProgram_t *sp = &tr.textureColorShader; + vec4_t color; GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); GLSL_BindProgram(sp); @@ -435,7 +436,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max */ { shaderProgram_t *sp = &tr.lightallShader[0]; - vec4_t vector; + vec4_t color, vector; GLSL_BindProgram(sp);