diff --git a/ref/gl/gl_rsurf.c b/ref/gl/gl_rsurf.c index 3584ba88c..e8d9611b3 100644 --- a/ref/gl/gl_rsurf.c +++ b/ref/gl/gl_rsurf.c @@ -442,44 +442,6 @@ texture_t *R_TextureAnim( texture_t *b ) return base; } - -/* -=============== -R_TextureRandomTiling - -Returns the proper texture for a given surface without animation -=============== -*/ -texture_t *R_TextureRandomTiling( msurface_t *s ) -{ - texture_t *base = s->texinfo->texture; - int count, reletive; - - if( !base->anim_total ) - return base; - - if( base->name[0] == '-' ) - { - int tx = (int)((s->texturemins[0] + (base->width << 16)) / base->width) % MOD_FRAMES; - int ty = (int)((s->texturemins[1] + (base->height << 16)) / base->height) % MOD_FRAMES; - - reletive = rtable[tx][ty] % base->anim_total; - } - - count = 0; - - while( base->anim_min > reletive || base->anim_max <= reletive ) - { - base = base->anim_next; - - if( !base || ++count > MOD_FRAMES ) - return s->texinfo->texture; - } - - return base; -} - - /* =============== R_TextureAnimation @@ -1327,8 +1289,6 @@ void R_DrawTextureChains( void ) skychain = NULL; } - R_DrawVBO( !r_fullbright->value && !!WORLDMODEL->lightdata, true ); - for( i = 0; i < WORLDMODEL->numtextures; i++ ) { t = WORLDMODEL->textures[i]; @@ -1722,20 +1682,10 @@ typedef struct vbovertex_s #endif } vbovertex_t; -#ifndef UINT_INDEX -typedef unsigned short vboindex_t; -#define VBOINDEX_MAX USHRT_MAX -#define GL_VBOINDEX_TYPE GL_UNSIGNED_SHORT -#else -typedef unsigned int vboindex_t; -#define VBOINDEX_MAX UINT_MAX -#define GL_VBOINDEX_TYPE GL_UNSIGNED_INT -#endif - // store indexes for each texture typedef struct vbotexture_s { - vboindex_t *indexarray; // index array (generated instead of texture chains) + unsigned short *indexarray; // index array (generated instead of texture chains) uint curindex; // counter for index array uint len; // maximum index array length struct vbotexture_s *next; // if cannot fit into one array, allocate new one, as every array has own index space @@ -1792,7 +1742,7 @@ struct vbo_static_s vboarray_t *arraylist; // linked list // separate areay for dlights (build during draw) - vboindex_t *dlight_index; // array + unsigned short *dlight_index; // array vec2_t *dlight_tc; // array unsigned int dlight_vbo; vbovertex_t decal_dlight[MAX_RENDER_DECALS * DECAL_VERTS_MAX]; @@ -1823,40 +1773,6 @@ struct multitexturestate_s gl_texture_t *glt; // details scale } mtst; -enum array_state_e -{ - VBO_ARRAY_NONE, - VBO_ARRAY_STATIC, - VBO_ARRAY_DECAL, - VBO_ARRAY_DLIGHT, - VBO_ARRAY_DECAL_DLIGHT -}; - -enum texture_state_e -{ - VBO_TEXTURE_NONE, - VBO_TEXTURE_MAIN, - VBO_TEXTURE_DECAL -}; - -enum lightmap_state_e -{ - VBO_LIGHTMAP_NONE, - VBO_LIGHTMAP_STATIC, - VBO_LIGHTMAP_DYNAMIC -}; - - -static struct arraystate_s -{ - enum array_state_e astate; - enum texture_state_e tstate; - enum lightmap_state_e lstate; - int itexture; - qboolean decal_mode; -} vboarray; - - /* =================== R_GenerateVBO @@ -1866,10 +1782,7 @@ Allocate memory for arrays, fill it with vertex attribs and upload to GPU */ void R_GenerateVBO( void ) { - model_t *world = WORLDMODEL; - msurface_t *surfaces = world->surfaces; - int numsurfaces = world->numsurfaces; - int numtextures = world->numtextures; + int numtextures = WORLDMODEL->numtextures; int numlightmaps = gl_lms.current_lightmap_texture; int k, len = 0; vboarray_t *vbo; @@ -1915,20 +1828,20 @@ void R_GenerateVBO( void ) int i; vbotexture_t *vbotex = &vbos.textures[k * numtextures + j]; - for( i = 0; i < numsurfaces; i++ ) + for( i = 0; i < WORLDMODEL->numsurfaces; i++ ) { - msurface_t *surf = &surfaces[i]; + msurface_t *surf = &WORLDMODEL->surfaces[i]; - if( surf->lightmaptexturenum != k ) + if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) continue; - if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) + if( surf->lightmaptexturenum != k ) continue; - if( R_TextureAnimation( surf ) != world->textures[j] ) + if( R_TextureAnimation( surf ) != WORLDMODEL->textures[j] ) continue; - if( vbo->array_len + surf->polys->numverts > VBOINDEX_MAX ) + if( vbo->array_len + surf->polys->numverts > USHRT_MAX ) { // generate new array and new vbotexture node vbo->array = Mem_Calloc( vbos.mempool, sizeof( vbovertex_t ) * vbo->array_len ); @@ -1976,28 +1889,28 @@ void R_GenerateVBO( void ) vbotexture_t *vbotex = &vbos.textures[k * numtextures + j]; // preallocate index arrays - vbotex->indexarray = Mem_Calloc( vbos.mempool, sizeof( *vbotex->indexarray ) * 6 * vbotex->len ); + vbotex->indexarray = Mem_Calloc( vbos.mempool, sizeof( unsigned short ) * 6 * vbotex->len ); vbotex->lightmaptexturenum = k; if( maxindex < vbotex->len ) maxindex = vbotex->len; - for( i = 0; i < numsurfaces; i++ ) + for( i = 0; i < WORLDMODEL->numsurfaces; i++ ) { - msurface_t *surf = &surfaces[i]; + msurface_t *surf = &WORLDMODEL->surfaces[i]; int l; - if( surf->lightmaptexturenum != k ) + if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) continue; - if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) + if( surf->lightmaptexturenum != k ) continue; - if( R_TextureAnimation( surf ) != world->textures[j] ) + if( R_TextureAnimation( surf ) != WORLDMODEL->textures[j] ) continue; // switch to next array - if( len + surf->polys->numverts > VBOINDEX_MAX ) + if( len + surf->polys->numverts > USHRT_MAX ) { // upload last generated array pglGenBuffersARB( 1, &vbo->glindex ); @@ -2008,7 +1921,7 @@ void R_GenerateVBO( void ) vbo = vbo->next; vbotex = vbotex->next; - vbotex->indexarray = Mem_Calloc( vbos.mempool, sizeof( *vbotex->indexarray ) * 6 * vbotex->len ); + vbotex->indexarray = Mem_Calloc( vbos.mempool, sizeof( unsigned short ) * 6 * vbotex->len ); vbotex->lightmaptexturenum = k; // calculate limits for dlights @@ -2029,9 +1942,9 @@ void R_GenerateVBO( void ) vbo->array[len + l].lm_tc[0] = v[5]; vbo->array[len + l].lm_tc[1] = v[6]; #ifdef NO_TEXTURE_MATRIX - if( world->textures[j]->dt_texturenum ) + if( WORLDMODEL->textures[j]->dt_texturenum ) { - gl_texture_t *glt = R_GetTexture( world->textures[j]->gl_texturenum ); + gl_texture_t *glt = R_GetTexture( WORLDMODEL->textures[j]->gl_texturenum ); vbo->array[len + l].dt_tc[0] = v[3] * glt->xscale; vbo->array[len + l].dt_tc[1] = v[4] * glt->yscale; } @@ -2056,10 +1969,10 @@ void R_GenerateVBO( void ) pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbovertex_t ) * DECAL_VERTS_CUT * MAX_RENDER_DECALS, vbos.decaldata->decalarray, GL_DYNAMIC_DRAW_ARB ); // preallocate dlight arrays - vbos.dlight_index = Mem_Calloc( vbos.mempool, maxindex * sizeof( *vbos.dlight_index ) * 6 ); + vbos.dlight_index = Mem_Calloc( vbos.mempool, maxindex * sizeof( unsigned short ) * 6 ); // select maximum possible length for dlight - vbos.dlight_tc = Mem_Calloc( vbos.mempool, sizeof( vec2_t ) * (int)( vbos.arraylist->next ? VBOINDEX_MAX + 1 : vbos.arraylist->array_len + 1 )); + vbos.dlight_tc = Mem_Calloc( vbos.mempool, sizeof( vec2_t ) * (int)(vbos.arraylist->next?USHRT_MAX + 1:vbos.arraylist->array_len + 1) ); if( r_vbo_dlightmode.value ) { @@ -2224,14 +2137,11 @@ static void R_SetLightmap( void ) R_SetDecalMode When drawing decal, disable or restore bump and details +set tmu to lightmap when enabled ============== */ static void R_SetDecalMode( qboolean enable ) { - if( vboarray.decal_mode == enable ) - return; - vboarray.decal_mode = enable; - // order is important to correctly rearrange TMUs if( enable ) { @@ -2271,122 +2181,10 @@ static texture_t *R_SetupVBOTexture( texture_t *tex, int number ) else R_DisableDetail(); GL_Bind( mtst.tmu_gl, r_lightmap->value ?tr.whiteTexture:tex->gl_texturenum ); - if(number) - vboarray.itexture = number; return tex; } - -void R_SetupVBOArrayStatic( vboarray_t *vbo, qboolean drawlightmap, qboolean drawtextures ) -{ - if( vboarray.astate != VBO_ARRAY_STATIC ) - { - // bind array - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - // dlights use same vertex array - if( vboarray.astate != VBO_ARRAY_DLIGHT ) - { - - pglEnableClientState( GL_VERTEX_ARRAY ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t,pos) ); - } - - - // setup multitexture - if( drawtextures && vboarray.tstate != VBO_TEXTURE_MAIN ) - { - GL_SelectTexture( mtst.tmu_gl = XASH_TEXTURE0 ); - pglEnable( GL_TEXTURE_2D ); - pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); - vboarray.tstate = VBO_TEXTURE_MAIN; - } - - if( drawlightmap && (vboarray.lstate != VBO_LIGHTMAP_STATIC || vboarray.astate == VBO_ARRAY_DECAL ) ) - { - // set lightmap texenv - if( mtst.lm ) - GL_Bind( mtst.tmu_lm = XASH_TEXTURE1, mtst.lm ); - else - GL_SelectTexture( mtst.tmu_lm = XASH_TEXTURE1 ); - pglEnable( GL_TEXTURE_2D ); - pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - R_SetLightmap(); - vboarray.lstate = VBO_LIGHTMAP_STATIC; - } - vboarray.astate = VBO_ARRAY_STATIC; - R_SetDecalMode( false ); - } -} - - - -static void R_SetupVBOArrayDlight( vboarray_t *vbo, texture_t *texture ) -{ - - if( vboarray.astate != VBO_ARRAY_DLIGHT ) - { - if( vboarray.astate == VBO_ARRAY_DECAL_DLIGHT ) - { - // bind array - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - pglEnableClientState( GL_VERTEX_ARRAY ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t,pos) ); - } - if( vboarray.tstate != VBO_TEXTURE_MAIN || vboarray.astate == VBO_ARRAY_DECAL_DLIGHT ) - { - R_SetupVBOTexture( texture, vboarray.itexture ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); - vboarray.tstate = VBO_TEXTURE_MAIN; - } - GL_Bind( mtst.tmu_lm, tr.dlightTexture ); - vboarray.lstate = VBO_LIGHTMAP_DYNAMIC; - - // replace lightmap texcoord array by dlight array - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); - if( vbos.dlight_vbo ) - pglTexCoordPointer( 2, GL_FLOAT, sizeof( float ) * 2, 0 ); - else - pglTexCoordPointer( 2, GL_FLOAT, sizeof( float ) * 2, vbos.dlight_tc ); - - vboarray.astate = VBO_ARRAY_DLIGHT; - } -} - - - -static void R_SetupVBOArrayDecalDlight( void ) -{ - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decal_dlight_vbo ); - R_SetDecalMode( true ); - // hack: fix decal dlights on gl_vbo_details == 2 (wrong state??) - /*if( mtst.details_enabled && mtst.tmu_dt != -1 ) - { - GL_Bind( mtst.tmu_dt, tr.whiteTexture ); - }*/ - GL_SelectTexture( mtst.tmu_lm ); - if( vbos.decal_dlight_vbo ) - { - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof( vbovertex_t, lm_tc ) ); - GL_SelectTexture( mtst.tmu_gl ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof( vbovertex_t, gl_tc ) ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof( vbovertex_t, pos ) ); - } - else - { - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), &vbos.decal_dlight[0].lm_tc ); - GL_SelectTexture( mtst.tmu_gl ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), &vbos.decal_dlight[0].gl_tc ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), &vbos.decal_dlight[0].pos); - } - vboarray.astate = VBO_ARRAY_DECAL_DLIGHT; - vboarray.tstate = VBO_TEXTURE_DECAL; - vboarray.lstate = VBO_LIGHTMAP_DYNAMIC; -} - - /* =================== R_AdditionalPasses @@ -2394,7 +2192,7 @@ R_AdditionalPasses draw details when not enough tmus =================== */ -static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, texture_t *tex, qboolean resetvbo, size_t offset ) +static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, texture_t *tex, qboolean resetvbo ) { // draw details in additional pass if( r_detailtextures.value && mtst.tmu_dt == -1 && tex->dt_texturenum ) @@ -2414,7 +2212,7 @@ static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, if( resetvbo ) pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)(offset + offsetof( vbovertex_t, gl_tc ))); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof( vbovertex_t, gl_tc ) ); // apply scale pglMatrixMode( GL_TEXTURE ); @@ -2424,15 +2222,14 @@ static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, // draw #if !defined XASH_NANOGL || defined XASH_WES && XASH_EMSCRIPTEN // WebGL need to know array sizes if( pglDrawRangeElements ) - pglDrawRangeElements( GL_TRIANGLES, 0, vbo->array_len, indexlen, GL_VBOINDEX_TYPE, indexarray ); + pglDrawRangeElements( GL_TRIANGLES, 0, vbo->array_len, indexlen, GL_UNSIGNED_SHORT, indexarray ); else #endif - pglDrawElements( GL_TRIANGLES, indexlen, GL_VBOINDEX_TYPE, indexarray ); + pglDrawElements( GL_TRIANGLES, indexlen, GL_UNSIGNED_SHORT, indexarray ); // restore state pglLoadIdentity(); - /* pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglDisable( GL_BLEND ); GL_Bind( XASH_TEXTURE1, mtst.lm ); @@ -2440,14 +2237,8 @@ static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, GL_SelectTexture( XASH_TEXTURE1 ); pglEnable( GL_TEXTURE_2D ); - pglDisable( GL_BLEND ); - vboarray.astate = VBO_ARRAY_NONE; - vboarray.tstate = VBO_TEXTURE_NONE; - vboarray.lstate = VBO_LIGHTMAP_NONE; if( resetvbo ) - R_SetupVBOArrayDlight( vbo, tex ); - else - R_SetupVBOArrayStatic( vbo, true, true ); + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); } } @@ -2455,180 +2246,68 @@ static void R_AdditionalPasses( vboarray_t *vbo, int indexlen, void *indexarray, ===================== R_DrawLightmappedVBO - -static void R_DrawDlightedDecals( vboarray_t *vbo, msurface_t *newsurf, msurface_t *surf, int decalcount, texture_t *texture ) -{ - msurface_t *decalsurf; - decal_t *pdecal; - int decali = 0; - - pglDepthMask( GL_FALSE ); - pglEnable( GL_BLEND ); - pglEnable( GL_POLYGON_OFFSET_FILL ); - if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) - pglDisable( GL_ALPHA_TEST ); - - R_SetupVBOArrayDecalDlight(); - - for( decalsurf = newsurf; ( decali < decalcount ) && (!surf ||( decalsurf != surf )); decalsurf = decalsurf->info->lightmapchain ) - { - for( pdecal = decalsurf->pdecals; pdecal; pdecal = pdecal->pnext ) - { - gl_texture_t *glt; - - if( !pdecal->texture ) - continue; - - glt = R_GetTexture( pdecal->texture ); - - GL_Bind( mtst.tmu_gl, pdecal->texture ); - - // normal HL decal with alpha-channel - if( glt->flags & TF_HAS_ALPHA ) - { - // draw transparent decals with GL_MODULATE - if( glt->fogParams[3] > 230 ) - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - } - else - { - // color decal like detail texture. Base color is 127 127 127 - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ); - } - - pglDrawArrays( GL_TRIANGLE_FAN, decali * DECAL_VERTS_MAX, vbos.decal_numverts[decali] ); - decali++; - } - newsurf = surf; - - } - - if( vbos.decal_dlight_vbo ) - pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbos.decal_dlight ), NULL, GL_STREAM_DRAW_ARB ); - - // restore states pointers for next dynamic lightmap - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - pglDepthMask( GL_TRUE ); - pglDisable( GL_BLEND ); - pglDisable( GL_POLYGON_OFFSET_FILL ); - if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) - pglEnable( GL_ALPHA_TEST ); - R_SetDecalMode( false ); -} - -static void R_FlushDlights( vboarray_t *vbo, int min_index, int max_index, int dlightindex, vboindex_t *dlightarray ) +Draw array for given vbotexture_t. build and draw dynamic lightmaps if present +===================== +*/ +static void R_DrawLightmappedVBO( vboarray_t *vbo, vbotexture_t *vbotex, texture_t *texture, int lightmap, qboolean skiplighting ) { - if( max_index == 0 ) - return; - if( vbos.dlight_vbo ) - { -#ifndef MINIMIZE_UPLOAD - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); - pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vec2_t )* (max_index - min_index), vbos.dlight_tc + min_index, GL_STREAM_DRAW_ARB ); -#endif - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index* sizeof( vbovertex_t ) + offsetof(vbovertex_t,pos)) ); - GL_SelectTexture( mtst.tmu_gl ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index * sizeof( vbovertex_t ) + offsetof(vbovertex_t,gl_tc)) ); - if( mtst.details_enabled && mtst.tmu_dt != -1 ) - { - GL_SelectTexture( mtst.tmu_dt ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index * sizeof( vbovertex_t ) + offsetof(vbovertex_t,gl_tc)) ); - } - - } - //GL_SelectTexture( mtst.tmu_lm ); - GL_Bind( mtst.tmu_lm, tr.dlightTexture ); -#ifdef DISCARD_DLIGHTS - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_SIZE, BLOCK_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); -#endif - LM_UploadDynamicBlock(); #if !defined XASH_NANOGL || defined XASH_WES && XASH_EMSCRIPTEN // WebGL need to know array sizes if( pglDrawRangeElements ) - pglDrawRangeElements( GL_TRIANGLES, min_index, max_index, dlightindex, GL_VBOINDEX_TYPE, dlightarray ); + pglDrawRangeElements( GL_TRIANGLES, 0, vbo->array_len, vbotex->curindex, GL_UNSIGNED_SHORT, vbotex->indexarray ); else #endif - pglDrawElements( GL_TRIANGLES, dlightindex, GL_VBOINDEX_TYPE, dlightarray ); -} + pglDrawElements( GL_TRIANGLES, vbotex->curindex, GL_UNSIGNED_SHORT, vbotex->indexarray ); R_AdditionalPasses( vbo, vbotex->curindex, vbotex->indexarray, texture, false ); // draw debug lines if( gl_wireframe.value && !skiplighting ) { - int decalindex = pdecal - &gDecalPool[0]; - int numVerts = vbos.decaldata->decals[decalindex].numVerts; - int i; - - if( numVerts == -1 ) - { - // build decal array - float *v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &numVerts ); - - for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) - { - VectorCopy( v, vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].pos ); - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[0] = v[3]; - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[1] = v[4]; - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[0] = v[5] - ( surf->light_s - surf->info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ); - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[1] = v[6] - ( surf->light_t - surf->info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ); - } - } + R_SetDecalMode( true ); + pglDisable( GL_TEXTURE_2D ); + GL_SelectTexture( XASH_TEXTURE0 ); + pglDisable( GL_TEXTURE_2D ); + pglDisable( GL_DEPTH_TEST ); +#if !defined XASH_NANOGL || defined XASH_WES && XASH_EMSCRIPTEN // WebGL need to know array sizes + if( pglDrawRangeElements ) + pglDrawRangeElements( GL_LINES, 0, vbo->array_len, vbotex->curindex, GL_UNSIGNED_SHORT, vbotex->indexarray ); else - { - // copy from vbo - for( i = 0; i < numVerts; i++ ) - { - VectorCopy( vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].pos, vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].pos ); - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[0] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].gl_tc[0]; - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[1] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].gl_tc[1]; - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[0] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].lm_tc[0] - ( surf->light_s - surf->info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ); - vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[1] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].lm_tc[1] - ( surf->light_t - surf->info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ); - } - } - if( vbos.dlight_vbo ) - { - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decal_dlight_vbo ); - pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbovertex_t ) * decalcount * DECAL_VERTS_MAX, sizeof( vbovertex_t )* numVerts, vbos.decal_dlight + decalcount * DECAL_VERTS_MAX ); - } - - vbos.decal_numverts[decalcount] = numVerts; - decalcount++; +#endif + pglDrawElements( GL_LINES, vbotex->curindex, GL_UNSIGNED_SHORT, vbotex->indexarray ); + pglEnable( GL_DEPTH_TEST ); + pglEnable( GL_TEXTURE_2D ); + GL_SelectTexture( XASH_TEXTURE1 ); + pglEnable( GL_TEXTURE_2D ); + R_SetDecalMode( false ); + } + //Msg( "%d %d %d\n", vbo->array_len, vbotex->len, lightmap ); + if( skiplighting ) + { + vbotex->curindex = 0; + vbotex->dlightchain = NULL; + return; } - *pdecalcount = decalcount; -} - -static void R_DrawVBODlights( vboarray_t *vbo, vbotexture_t *vbotex, texture_t *texture, int lightmap ) -{ // draw dlights and dlighted decals if( vbotex->dlightchain ) { - vboindex_t *dlightarray = vbos.dlight_index; // preallocated array + unsigned short *dlightarray = vbos.dlight_index; // preallocated array unsigned int dlightindex = 0; msurface_t *surf, *newsurf; int decalcount = 0; - R_SetupVBOArrayDlight( vbo, texture ); - - // clear the block - LM_InitBlock(); + GL_Bind( mtst.tmu_lm, tr.dlightTexture ); - if( vbos.dlight_vbo ) - { - // calculate minimum indexbase - for( surf = newsurf = vbotex->dlightchain; surf; surf = surf->info->lightmapchain ) - if(min_index > vbos.surfdata[((char*)surf - (char*)WORLDMODEL->surfaces) / sizeof( *surf )].startindex ) - min_index = vbos.surfdata[((char*)surf - (char*)WORLDMODEL->surfaces) / sizeof( *surf )].startindex; - } + // replace lightmap texcoord array by dlight array + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); + if( vbos.dlight_vbo ) + pglTexCoordPointer( 2, GL_FLOAT, sizeof( float ) * 2, 0 ); else - { - min_index = 0; - } + pglTexCoordPointer( 2, GL_FLOAT, sizeof( float ) * 2, vbos.dlight_tc ); + + // clear the block + LM_InitBlock(); // accumulate indexes for every dlighted surface until dlight block full for( surf = newsurf = vbotex->dlightchain; surf; surf = surf->info->lightmapchain ) @@ -2657,24 +2336,8 @@ static void R_DrawVBODlights( vboarray_t *vbo, vbotexture_t *vbotex, texture_t * } else { - - // out of free block space. Draw all generated index array and clear it // upload already generated block - if( vbos.dlight_vbo ) - { - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); - pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vec2_t )* (max_index - min_index), vbos.dlight_tc + min_index, GL_STREAM_DRAW_ARB ); - - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index* sizeof( vbovertex_t ) + offsetof(vbovertex_t,pos)) ); - GL_SelectTexture( XASH_TEXTURE0 ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index * sizeof( vbovertex_t ) + offsetof(vbovertex_t,gl_tc)) ); - GL_SelectTexture( XASH_TEXTURE1 ); - } - - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_SIZE, BLOCK_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); - LM_UploadDynamicBlock(); #if !defined XASH_NANOGL || defined XASH_WES && XASH_EMSCRIPTEN // WebGL need to know array sizes if( pglDrawRangeElements ) @@ -2682,7 +2345,6 @@ static void R_DrawVBODlights( vboarray_t *vbo, vbotexture_t *vbotex, texture_t * else #endif pglDrawElements( GL_TRIANGLES, dlightindex, GL_UNSIGNED_SHORT, dlightarray ); - max_index = 0; // draw decals that lighted with this lightmap if( decalcount ) @@ -2800,31 +2462,62 @@ static void R_DrawVBODlights( vboarray_t *vbo, vbotexture_t *vbotex, texture_t * vbos.dlight_tc[index][1] = surf->polys->verts[index - indexbase][6] - ( surf->light_t - info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ); } - if( max_index < indexbase + surf->polys->numverts ) - max_index = indexbase + surf->polys->numverts; + if( vbos.dlight_vbo ) + { + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); + pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vec2_t ) * indexbase, sizeof( vec2_t )* surf->polys->numverts, vbos.dlight_tc + indexbase ); + } // if surface has decals, build decal array - R_AddSurfaceDecalsDlight( surf, &decalcount ); + for( pdecal = surf->pdecals; pdecal; pdecal = pdecal->pnext ) + { + int decalindex = pdecal - &gDecalPool[0]; + int numVerts = vbos.decaldata->decals[decalindex].numVerts; + int i; + + if( numVerts == -1 ) + { + // build decal array + float *v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &numVerts ); + + for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) + { + VectorCopy( v, vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].pos ); + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[0] = v[3]; + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[1] = v[4]; + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[0] = v[5] - ( surf->light_s - info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ); + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[1] = v[6] - ( surf->light_t - info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ); + } + } + else + { + // copy from vbo + for( i = 0; i < numVerts; i++ ) + { + VectorCopy( vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].pos, vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].pos ); + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[0] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].gl_tc[0]; + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].gl_tc[1] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].gl_tc[1]; + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[0] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].lm_tc[0] - ( surf->light_s - info->dlight_s ) * ( 1.0f / (float)BLOCK_SIZE ); + vbos.decal_dlight[decalcount * DECAL_VERTS_MAX + i].lm_tc[1] = vbos.decaldata->decalarray[decalindex * DECAL_VERTS_CUT + i].lm_tc[1] - ( surf->light_t - info->dlight_t ) * ( 1.0f / (float)BLOCK_SIZE ); + } + } + if( vbos.dlight_vbo ) + { + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decal_dlight_vbo ); + pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbovertex_t ) * decalcount * DECAL_VERTS_MAX, sizeof( vbovertex_t )* numVerts, vbos.decal_dlight + decalcount * DECAL_VERTS_MAX ); + } + + vbos.decal_numverts[decalcount] = numVerts; + decalcount++; + } //info->dlight_s = info->dlight_t = 0; } if( dlightindex ) { - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_SIZE, BLOCK_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); // update block LM_UploadDynamicBlock(); - if( vbos.dlight_vbo ) - { - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.dlight_vbo ); - pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vec2_t )* (max_index - min_index), vbos.dlight_tc + min_index, GL_STREAM_DRAW_ARB ); - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); - pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index * sizeof( vbovertex_t ) + offsetof(vbovertex_t,pos)) ); - GL_SelectTexture( XASH_TEXTURE0 ); - pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)(min_index * sizeof( vbovertex_t ) + offsetof(vbovertex_t,gl_tc)) ); - GL_SelectTexture( XASH_TEXTURE1 ); - } - // draw remaining array #if !defined XASH_NANOGL || defined XASH_WES && XASH_EMSCRIPTEN // WebGL need to know array sizes if( pglDrawRangeElements ) @@ -2923,7 +2616,6 @@ static void R_DrawVBODlights( vboarray_t *vbo, vbotexture_t *vbotex, texture_t * // prepare to next frame vbotex->dlightchain = NULL; } -} // prepare to next frame vbotex->curindex = 0; @@ -2946,8 +2638,6 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) if( !r_vbo.value ) return; - GL_SetupFogColorForSurfacesEx( 1, 0.5f ); - // bind array pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); pglEnableClientState( GL_VERTEX_ARRAY ); @@ -2992,6 +2682,7 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) for( k = vbos.minlightmap; k < vbos.maxlightmap; k++ ) { int j; + msurface_t *lightmapchain; if( drawlightmap ) { @@ -3024,9 +2715,6 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) vbotex = vbotex->next; vbo = vbo->next; - vboarray.astate = VBO_ARRAY_NONE; // invalidate - vboarray.tstate = VBO_TEXTURE_NONE; - vboarray.lstate = VBO_LIGHTMAP_NONE; // bind new vertex and index arrays pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); @@ -3035,7 +2723,7 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) // update texcoord pointers if( drawtextures ) { - tex = R_SetupVBOTexture( tex, j ); + tex = R_SetupVBOTexture( tex, 0 ); pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); } @@ -3048,20 +2736,146 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) // draw new array if( (vbotex->curindex || vbotex->dlightchain) ) R_DrawLightmappedVBO( vbo, vbotex, tex, k, !drawlightmap ); - vboarray.astate = VBO_ARRAY_NONE; // invalidate - vboarray.tstate = VBO_TEXTURE_NONE; } } if( drawtextures && drawlightmap && vbos.decaldata->lm[k] ) { - R_DrawStaticDecals( vbo, drawlightmap, k ); + // prepare for decal draw + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decaldata->decalvbo ); + pglDepthMask( GL_FALSE ); + pglEnable( GL_BLEND ); + pglEnable( GL_POLYGON_OFFSET_FILL ); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) + pglDisable( GL_ALPHA_TEST ); + + R_SetDecalMode( true ); + + // Set pointers to vbodecaldata->decalvbo + if( drawlightmap ) + { + GL_SelectTexture( mtst.tmu_lm ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, lm_tc ) ); + GL_SelectTexture( mtst.tmu_gl ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); + pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, pos ) ); + } + + // all surfaces having decals and this lightmap + for( lightmapchain = vbos.decaldata->lm[k]; lightmapchain; lightmapchain = lightmapchain->info->lightmapchain ) + { + decal_t *pdecal; + + // all decals of surface + for( pdecal = lightmapchain->pdecals; pdecal; pdecal = pdecal->pnext ) + { + gl_texture_t *glt; + int decalindex = pdecal - &gDecalPool[0]; + + if( !pdecal->texture ) + continue; + + glt = R_GetTexture( pdecal->texture ); + + GL_Bind( mtst.tmu_gl, pdecal->texture ); + + // normal HL decal with alpha-channel + if( glt->flags & TF_HAS_ALPHA ) + { + // draw transparent decals with GL_MODULATE + if( glt->fogParams[3] > 230 ) + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + } + else + { + // color decal like detail texture. Base color is 127 127 127 + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ); + } + + if( vbos.decaldata->decals[decalindex].numVerts == -1 ) + { + int numVerts; + float *v; + + v = R_DecalSetupVerts( pdecal, lightmapchain, pdecal->texture, &numVerts ); + + // to many verts to keep in sparse array, so build it now + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); + pglVertexPointer( 3, GL_FLOAT, VERTEXSIZE * 4, v ); + pglTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE * 4, v + 3 ); + if( drawlightmap ) + { + GL_SelectTexture( mtst.tmu_lm ); + pglTexCoordPointer( 2, GL_FLOAT, VERTEXSIZE * 4, v + 5 ); + } + + pglDrawArrays( GL_TRIANGLE_FAN, 0, numVerts ); + + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decaldata->decalvbo ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, lm_tc ) ); + GL_SelectTexture( mtst.tmu_gl ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); + pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, pos ) ); + } + else // just draw VBO + pglDrawArrays( GL_TRIANGLE_FAN, decalindex * DECAL_VERTS_CUT, vbos.decaldata->decals[decalindex].numVerts ); + } + } + + // prepare for next frame + vbos.decaldata->lm[k] = NULL; + + // prepare for next texture + pglDepthMask( GL_TRUE ); + pglDisable( GL_BLEND ); + pglDisable( GL_POLYGON_OFFSET_FILL ); + + // restore vbo + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbo->glindex ); + pglVertexPointer( 3, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t,pos) ); + + // restore bump if needed + R_SetDecalMode( false ); + + // restore texture + GL_SelectTexture( mtst.tmu_gl ); + pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, gl_tc ) ); + + // restore lightmap + GL_SelectTexture( mtst.tmu_lm ); + pglTexCoordPointer( 2, GL_FLOAT, sizeof( vbovertex_t ), (void*)offsetof(vbovertex_t, lm_tc ) ); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) + pglEnable( GL_ALPHA_TEST ); } if( !drawtextures || !drawlightmap ) vbos.decaldata->lm[k] = NULL; } // ASSERT( !vbo->next ); - R_ClearVBOState( drawlightmap, drawtextures ); + + // restore states + R_DisableDetail(); + + if( drawlightmap ) + { + // reset states + GL_SelectTexture( XASH_TEXTURE1 ); + pglDisableClientState( GL_TEXTURE_COORD_ARRAY ); + pglDisable( GL_TEXTURE_2D ); + if( drawtextures ) + { + GL_SelectTexture( XASH_TEXTURE0 ); + pglEnable( GL_TEXTURE_2D ); + } + } + + if( drawtextures ) + pglDisableClientState( GL_TEXTURE_COORD_ARRAY ); mtst.details_enabled = false; @@ -3069,6 +2883,9 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures ) vbos.maxlightmap = 0; vbos.mintexture = INT_MAX; vbos.maxtexture = 0; + + pglDisableClientState( GL_VERTEX_ARRAY ); + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); } /* @@ -3194,10 +3011,6 @@ qboolean R_AddSurfToVBO( msurface_t *surf, qboolean buildlightmap ) vbos.decaldata->lm[vbotex->lightmaptexturenum] = surf; } } - - // now this path does not draw wapred surfaces, so count it as one poly - r_stats.c_world_polys++; - return true; } return false; @@ -3529,6 +3342,7 @@ void R_DrawWorld( void ) r_stats.t_world_node = end - start; start = gEngfuncs.pfnTime(); + R_DrawVBO( !r_fullbright->value && !!WORLDMODEL->lightdata, true ); R_DrawTextureChains(); @@ -3826,4 +3640,4 @@ void GL_InitRandomTable( void ) } gEngfuncs.COM_SetRandomSeed( 0 ); -} +} \ No newline at end of file