Window(void) : SYS::GLWindow(0, TEXT("Normalmapping"), 800, 800) { _angle = 0.0f; R_Init(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); R_CreateShader(&_vertexShader, GL_VERTEX_SHADER, "vertexshader.txt"); R_CreateShader(&_pixelShader, GL_FRAGMENT_SHADER, "pixelshader.txt"); _program = glx.CreateProgram(); glx.AttachShader(_program, _vertexShader.shader); glx.AttachShader(_program, _pixelShader.shader); R_LinkProgram(_program); glx.UseProgram(_program); FS::Dump& dump = FS::Dump::Instance(); /* R_LoadModelMD5(&_model, "hunter/hunter.md5mesh"); _model.meshes[0].texDiffuse = R_GetTexture(dump, TYPE_TGA, "hunter/hunterbody.tga"); _model.meshes[0].texNormal = R_GetTexture(dump, TYPE_TGA, "hunter/highres/hunterbody_local.tga"); _model.meshes[0].texAdd = R_GetTexture(dump, TYPE_TGA, "hunter/hunterbody_add.tga"); _model.meshes[0].texSpec = R_GetTexture(dump, TYPE_TGA, "hunter/hunterbody_s.tga"); _model.meshes[1].texDiffuse = R_GetTexture(dump, TYPE_TGA, "hunter/hunterhead.tga"); _model.meshes[1].texNormal = R_GetTexture(dump, TYPE_TGA, "hunter/hunterhead_local.tga"); _model.meshes[1].texAdd = R_GetTexture(dump, TYPE_TGA, "hunter/hunterhead_add.tga"); _model.meshes[1].texSpec = R_GetTexture(dump, TYPE_TGA, "hunter/hunterhead_s.tga"); _model.meshes[2].texDiffuse = R_GetTexture(dump, TYPE_TGA, "rifle/rifle.tga"); _model.meshes[2].texNormal = R_GetTexture(dump, TYPE_TGA, "rifle/rifle_local.tga"); _model.meshes[2].texAdd = R_GetTexture(dump, TYPE_TGA, "rifle/rifle_add.tga"); _model.meshes[2].texSpec = R_GetTexture(dump, TYPE_TGA, "rifle/rifle_s.tga"); */ R_LoadModelMD5(&_model, "hellknight/hellknight.md5mesh"); _model.meshes[0].texDiffuse = R_GetTexture(dump, TYPE_TGA, "hellknight/hellknight.tga"); _model.meshes[0].texNormal = R_GetTexture(dump, TYPE_TGA, "hellknight/hellknight_local.tga"); _model.meshes[0].texSpec = R_GetTexture(dump, TYPE_TGA, "hellknight/hellknight_s.tga"); GLuint sampler; sampler = glx.GetUniformLocation(_program, "texDiffuse"); glx.Uniform1i(sampler, 0); sampler = glx.GetUniformLocation(_program, "texNormal"); glx.Uniform1i(sampler, 1); sampler = glx.GetUniformLocation(_program, "texAdd"); glx.Uniform1i(sampler, 2); sampler = glx.GetUniformLocation(_program, "texSpec"); glx.Uniform1i(sampler, 3); _lightPos = M::Vector3(-200.0f, 200.0f, 0.0f); }
static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) { gltexture_t *glt = R_GetTexture( texture ); if( xScale ) *xScale = glt->xscale; if( yScale ) *yScale = glt->yscale; }
/* ============= R_GetImageParms ============= */ void R_GetTextureParms( int *w, int *h, int texnum ) { gltexture_t *glt; glt = R_GetTexture( texnum ); if( w ) *w = glt->srcWidth; if( h ) *h = glt->srcHeight; }
const byte *GL_TextureData( unsigned int texnum ) { rgbdata_t *pic = R_GetTexture( texnum )->original; if( pic != NULL ) return pic->buffer; return NULL; }
static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) { gltexture_t *glt = R_GetTexture( texture ); if( red ) *red = glt->fogParams[0]; if( green ) *green = glt->fogParams[1]; if( blue ) *blue = glt->fogParams[2]; if( density ) *density = glt->fogParams[3]; }
static int GL_RenderGetParm( int parm, int arg ) { gltexture_t *glt; switch( parm ) { case PARM_TEX_WIDTH: glt = R_GetTexture( arg ); return glt->width; case PARM_TEX_HEIGHT: glt = R_GetTexture( arg ); return glt->height; case PARM_TEX_SRC_WIDTH: glt = R_GetTexture( arg ); return glt->srcWidth; case PARM_TEX_SRC_HEIGHT: glt = R_GetTexture( arg ); return glt->srcHeight; case PARM_TEX_SKYBOX: ASSERT( arg >= 0 && arg < 6 ); return tr.skyboxTextures[arg]; case PARM_TEX_SKYTEXNUM: return tr.skytexturenum; case PARM_TEX_LIGHTMAP: ASSERT( arg >= 0 && arg < MAX_LIGHTMAPS ); return tr.lightmapTextures[arg]; case PARM_SKY_SPHERE: return world.sky_sphere; case PARM_WORLD_VERSION: return world.version; case PARM_WIDESCREEN: return glState.wideScreen; case PARM_FULLSCREEN: return glState.fullScreen; case PARM_SCREEN_WIDTH: return glState.width; case PARM_SCREEN_HEIGHT: return glState.height; case PARM_MAP_HAS_MIRRORS: return world.has_mirrors; case PARM_CLIENT_INGAME: return CL_IsInGame(); case PARM_MAX_ENTITIES: return clgame.maxEntities; case PARM_TEX_TARGET: glt = R_GetTexture( arg ); return glt->target; case PARM_TEX_TEXNUM: glt = R_GetTexture( arg ); return glt->texnum; case PARM_TEX_FLAGS: glt = R_GetTexture( arg ); return glt->flags; case PARM_FEATURES: return host.features; } return 0; }
/* ==================== CL_UpdateTexture Update texture top and bottom colors ==================== */ void CL_UpdateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { gltexture_t *glt; rgbdata_t *pic; texture_t *tx = NULL; char texname[128], name[128], mdlname[128]; int i, index; size_t size; byte paletteBackup[768]; byte *raw, *pal; // save of the real texture index glt = R_GetTexture( ptexture->index ); // build name of original texture Q_strncpy( mdlname, RI.currentmodel->name, sizeof( mdlname )); FS_FileBase( ptexture->name, name ); FS_StripExtension( mdlname ); Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name ); index = GL_FindTexture( texname ); if( !index ) return; // couldn't find texture // search for pixels for( i = 0; i < RI.currentmodel->numtextures; i++ ) { tx = RI.currentmodel->textures[i]; if( tx->gl_texturenum == index ) break; // found } ASSERT( tx != NULL ); // backup original palette pal = (byte *)(tx + 1) + (tx->width * tx->height); Q_memcpy( paletteBackup, pal, 768 ); raw = CL_CreateRawTextureFromPixels( tx, &size, topcolor, bottomcolor ); pic = FS_LoadImage( glt->name, raw, size ); if( !pic ) { MsgDev( D_ERROR, "Couldn't update texture %s\n", glt->name ); return; } index = GL_LoadTextureInternal( glt->name, pic, 0, true ); FS_FreeImage( pic ); // restore original palette Q_memcpy( pal, paletteBackup, 768 ); ASSERT( index == ptexture->index ); }
/* ================ VGUI_GetTextureSizes returns wide and tall for currently binded texture ================ */ void VGUI_GetTextureSizes( int *width, int *height ) { gltexture_t *glt; int texnum; if( g_iBoundTexture ) texnum = g_textures[g_iBoundTexture]; else texnum = tr.defaultTexture; glt = R_GetTexture( texnum ); if( width ) *width = glt->srcWidth; if( height ) *height = glt->srcHeight; }
//----------------------------------------------------------------------------- // Purpose: Called by CSaveRestore::SaveClientState // Input : *pList - // Output : int //----------------------------------------------------------------------------- int R_CreateDecalList( decallist_t *pList, qboolean changelevel ) { int total = 0; int i, depth; if( cl.worldmodel ) { for( i = 0; i < MAX_RENDER_DECALS; i++ ) { decal_t *decal = &gDecalPool[i]; decal_t *pdecals; // decal is in use and is not a custom decal if( decal->psurface == NULL || ( decal->flags & FDECAL_DONTSAVE )) continue; // compute depth depth = 0; pdecals = decal->psurface->pdecals; while( pdecals && pdecals != decal ) { depth++; pdecals = pdecals->pnext; } pList[total].depth = depth; pList[total].flags = decal->flags; pList[total].scale = decal->scale; R_DecalUnProject( decal, &pList[total] ); FS_FileBase( R_GetTexture( decal->texture )->name, pList[total].name ); // check to see if the decal should be added total = DecalListAdd( pList, total ); } if( clgame.drawFuncs.R_CreateStudioDecalList ) { total += clgame.drawFuncs.R_CreateStudioDecalList( pList, total, changelevel ); } } // sort the decals lowest depth first, so they can be re-applied in order qsort( pList, total, sizeof( decallist_t ), DecalDepthCompare ); return total; }
/* ============= R_UploadStretchRaw ============= */ void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) { byte *raw = NULL; gltexture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { // check the dimensions width = NearestPOW( width, true ); height = NearestPOW( height, false ); } else { width = bound( 128, width, glConfig.max_2d_texture_size ); height = bound( 128, height, glConfig.max_2d_texture_size ); } if( cols != width || rows != height ) { raw = GL_ResampleTexture( data, cols, rows, width, height, false ); cols = width; rows = height; } else { raw = (byte *)data; } if( cols > glConfig.max_2d_texture_size ) Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", cols ); if( rows > glConfig.max_2d_texture_size ) Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", rows ); tex = R_GetTexture( texture ); GL_Bind( GL_TEXTURE0, texture ); tex->width = cols; tex->height = rows; pglTexImage2D( GL_TEXTURE_2D, 0, tex->format, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw ); GL_TexFilter( tex, false ); }
/* ============= Draw_TileClear This repeats a 64*64 tile graphic to fill the screen around a sized down refresh window. ============= */ void R_DrawTileClear( int x, int y, int w, int h ) { float tw, th; gltexture_t *glt; GL_SetRenderMode( kRenderNormal ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Bind( GL_TEXTURE0, cls.tileImage ); glt = R_GetTexture( cls.tileImage ); tw = glt->srcWidth; th = glt->srcHeight; pglBegin( GL_QUADS ); pglTexCoord2f( x / tw, y / th ); pglVertex2f( x, y ); pglTexCoord2f((x + w) / tw, y / th ); pglVertex2f( x + w, y ); pglTexCoord2f((x + w) / tw, (y + h) / th ); pglVertex2f( x + w, y + h ); pglTexCoord2f( x / tw, (y + h) / th ); pglVertex2f( x, y + h ); pglEnd (); }
/* ==================== CL_DuplicateTexture Dupliacte texture with remap pixels ==================== */ void CL_DuplicateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { gltexture_t *glt; texture_t *tx = NULL; char texname[128]; int i, index; size_t size; byte paletteBackup[768]; byte *raw, *pal; // save off the real texture index index = ptexture->index; glt = R_GetTexture( index ); Q_snprintf( texname, sizeof( texname ), "#%i_%s", RI.currententity->curstate.number, glt->name + 1 ); // search for pixels for( i = 0; i < RI.currentmodel->numtextures; i++ ) { tx = RI.currentmodel->textures[i]; if( tx->gl_texturenum == index ) break; // found } ASSERT( tx != NULL ); // backup original palette pal = (byte *)(tx + 1) + (tx->width * tx->height); Q_memcpy( paletteBackup, pal, 768 ); raw = CL_CreateRawTextureFromPixels( tx, &size, topcolor, bottomcolor ); ptexture->index = GL_LoadTexture( texname, raw, size, TF_FORCE_COLOR, NULL ); // do copy GL_SetTextureType( ptexture->index, TEX_REMAP ); // restore original palette Q_memcpy( pal, paletteBackup, 768 ); }
static const char *GL_TextureName( unsigned int texnum ) { return R_GetTexture( texnum )->name; }
void DrawSurfaceDecals( msurface_t *fa ) { decal_t *p; cl_entity_t *e; if( !fa->pdecals ) return; e = RI.currententity; ASSERT( e != NULL ); if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) { pglDepthMask( GL_FALSE ); pglEnable( GL_BLEND ); if( e->curstate.rendermode == kRenderTransAlpha ) pglDisable( GL_ALPHA_TEST ); } if( e->curstate.rendermode == kRenderTransColor ) pglEnable( GL_TEXTURE_2D ); if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) GL_Cull( GL_NONE ); pglEnable( GL_POLYGON_OFFSET_FILL ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( fa->flags & SURF_TRANSPARENT && glState.stencilEnabled ) { mtexinfo_t *tex = fa->texinfo; for( p = fa->pdecals; p; p = p->pnext ) { if( p->texture ) { float *o, *v; int i, numVerts; o = R_DecalSetupVerts( p, fa, p->texture, &numVerts ); pglEnable( GL_STENCIL_TEST ); pglStencilFunc( GL_ALWAYS, 1, 0xFFFFFFFF ); pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); pglStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); pglBegin( GL_POLYGON ); for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) { v[5] = ( DotProduct( v, tex->vecs[0] ) + tex->vecs[0][3] ) / tex->texture->width; v[6] = ( DotProduct( v, tex->vecs[1] ) + tex->vecs[1][3] ) / tex->texture->height; pglTexCoord2f( v[5], v[6] ); pglVertex3fv( v ); } pglEnd(); pglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); pglEnable( GL_ALPHA_TEST ); pglBegin( GL_POLYGON ); for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) { pglTexCoord2f( v[5], v[6] ); pglVertex3fv( v ); } pglEnd(); pglDisable( GL_ALPHA_TEST ); pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); pglStencilFunc( GL_EQUAL, 0, 0xFFFFFFFF ); pglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); } } } for( p = fa->pdecals; p; p = p->pnext ) { if( p->texture ) { gltexture_t *glt = R_GetTexture( p->texture ); // normal HL decal with alpha-channel if( glt->flags & TF_HAS_ALPHA ) { // draw transparent decals with GL_MODULATE if( glt->fogParams[3] > DECAL_TRANSPARENT_THRESHOLD ) 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 ); } DrawSingleDecal( p, fa ); } } if( fa->flags & SURF_TRANSPARENT && glState.stencilEnabled ) pglDisable( GL_STENCIL_TEST ); if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) { pglDepthMask( GL_TRUE ); pglDisable( GL_BLEND ); if( e->curstate.rendermode == kRenderTransAlpha ) pglEnable( GL_ALPHA_TEST ); } pglDisable( GL_POLYGON_OFFSET_FILL ); if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) GL_Cull( GL_FRONT ); if( e->curstate.rendermode == kRenderTransColor ) pglDisable( GL_TEXTURE_2D ); // restore blendfunc here if( e->curstate.rendermode == kRenderTransAdd || e->curstate.rendermode == kRenderGlow ) pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); }
/* =============== R_ShowTextures Draw all the images to the screen, on top of whatever was there. This is used to test for texture thrashing. =============== */ void R_ShowTextures( void ) { gltexture_t *image; float x, y, w, h; int i, j, k, base_w, base_h; int total, start, end; rgba_t color = { 192, 192, 192, 255 }; int charHeight, numTries = 0; static qboolean showHelp = true; string shortname; if( !gl_showtextures->integer ) return; if( showHelp ) { CL_CenterPrint( "use '<-' and '->' keys to view all the textures", 0.25f ); showHelp = false; } pglClear( GL_COLOR_BUFFER_BIT ); pglFinish(); base_w = 8; base_h = 6; rebuild_page: total = base_w * base_h; start = total * (gl_showtextures->integer - 1); end = total * gl_showtextures->integer; if( end > MAX_TEXTURES ) end = MAX_TEXTURES; w = glState.width / (float)base_w; h = glState.height / (float)base_h; Con_DrawStringLen( NULL, NULL, &charHeight ); for( i = j = 0; i < MAX_TEXTURES; i++ ) { image = R_GetTexture( i ); if( j == start ) break; // found start if( pglIsTexture( image->texnum )) j++; } if( i == MAX_TEXTURES && gl_showtextures->integer != 1 ) { // bad case, rewind to one and try again Cvar_SetFloat( "r_showtextures", max( 1, gl_showtextures->integer - 1 )); if( ++numTries < 2 ) goto rebuild_page; // to prevent infinite loop } for( k = 0; i < MAX_TEXTURES; i++ ) { if( j == end ) break; // page is full image = R_GetTexture( i ); if( !pglIsTexture( image->texnum )) continue; x = k % base_w * w; y = k / base_w * h; pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE )) pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); pglBegin( GL_QUADS ); pglTexCoord2f( 0, 0 ); pglVertex2f( x, y ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( image->width, 0 ); else pglTexCoord2f( 1, 0 ); pglVertex2f( x + w, y ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( image->width, image->height ); else pglTexCoord2f( 1, 1 ); pglVertex2f( x + w, y + h ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( 0, image->height ); else pglTexCoord2f( 0, 1 ); pglVertex2f( x, y + h ); pglEnd(); if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE )) pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); FS_FileBase( image->name, shortname ); if( Q_strlen( shortname ) > 18 ) { // cutoff too long names, it looks ugly shortname[16] = '.'; shortname[17] = '.'; shortname[18] = '\0'; } Con_DrawString( x + 1, y + h - charHeight, shortname, color ); j++, k++; } CL_DrawCenterPrint (); pglFinish(); }
/* ============= R_DrawStretchRaw ============= */ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) { byte *raw = NULL; gltexture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { int width = 1, height = 1; // check the dimensions width = NearestPOW( cols, true ); height = NearestPOW( rows, false ); if( cols != width || rows != height ) { raw = GL_ResampleTexture( data, cols, rows, width, height, false ); cols = width; rows = height; } } else { raw = (byte *)data; } if( cols > glConfig.max_2d_texture_size ) Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", cols ); if( rows > glConfig.max_2d_texture_size ) Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows ); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); tex = R_GetTexture( tr.cinTexture ); GL_Bind( GL_TEXTURE0, tr.cinTexture ); if( cols == tex->width && rows == tex->height ) { if( dirty ) { pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw ); } } else { tex->width = cols; tex->height = rows; if( dirty ) { pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw ); } } pglBegin( GL_QUADS ); pglTexCoord2f( 0, 0 ); pglVertex2f( x, y ); pglTexCoord2f( 1, 0 ); pglVertex2f( x + w, y ); pglTexCoord2f( 1, 1 ); pglVertex2f( x + w, y + h ); pglTexCoord2f( 0, 1 ); pglVertex2f( x, y + h ); pglEnd(); }
static int GL_RenderGetParm( int parm, int arg ) { gltexture_t *glt; switch( parm ) { case PARM_TEX_WIDTH: glt = R_GetTexture( arg ); return glt->width; case PARM_TEX_HEIGHT: glt = R_GetTexture( arg ); return glt->height; case PARM_TEX_SRC_WIDTH: glt = R_GetTexture( arg ); return glt->srcWidth; case PARM_TEX_SRC_HEIGHT: glt = R_GetTexture( arg ); return glt->srcHeight; case PARM_TEX_GLFORMAT: glt = R_GetTexture( arg ); return glt->format; case PARM_TEX_ENCODE: glt = R_GetTexture( arg ); return glt->encode; case PARM_TEX_SKYBOX: ASSERT( arg >= 0 && arg < 6 ); return tr.skyboxTextures[arg]; case PARM_TEX_SKYTEXNUM: return tr.skytexturenum; case PARM_TEX_LIGHTMAP: ASSERT( arg >= 0 && arg < MAX_LIGHTMAPS ); return tr.lightmapTextures[arg]; case PARM_SKY_SPHERE: return world.sky_sphere; case PARM_WORLD_VERSION: if( cls.state != ca_active ) return bmodel_version; return world.version; case PARM_WIDESCREEN: return glState.wideScreen; case PARM_FULLSCREEN: return glState.fullScreen; case PARM_SCREEN_WIDTH: return glState.width; case PARM_SCREEN_HEIGHT: return glState.height; case PARM_MAP_HAS_MIRRORS: return world.has_mirrors; case PARM_CLIENT_INGAME: return CL_IsInGame(); case PARM_MAX_ENTITIES: return clgame.maxEntities; case PARM_TEX_TARGET: glt = R_GetTexture( arg ); return glt->target; case PARM_TEX_TEXNUM: glt = R_GetTexture( arg ); return glt->texnum; case PARM_TEX_FLAGS: glt = R_GetTexture( arg ); return glt->flags; case PARM_FEATURES: return host.features; case PARM_ACTIVE_TMU: return glState.activeTMU; case PARM_TEX_CACHEFRAME: glt = R_GetTexture( arg ); return glt->cacheframe; case PARM_MAP_HAS_DELUXE: return (world.deluxedata != NULL); case PARM_TEX_TYPE: glt = R_GetTexture( arg ); return glt->texType; case PARM_CACHEFRAME: return world.load_sequence; case PARM_MAX_IMAGE_UNITS: return GL_MaxTextureUnits(); case PARM_CLIENT_ACTIVE: return (cls.state == ca_active); case PARM_REBUILD_GAMMA: return glConfig.softwareGammaUpdate; } return 0; }
static void GL_TextureUpdateCache( unsigned int texture ) { gltexture_t *glt = R_GetTexture( texture ); if( !glt || !glt->texnum ) return; glt->cacheframe = world.load_sequence; }
/* ============= R_CheckFog check for underwater fog Using backward recursion to find waterline leaf from underwater leaf (idea: XaeroX) ============= */ static void R_CheckFog( void ) { cl_entity_t *ent; gltexture_t *tex; int i, cnt, count; RI.fogEnabled = false; if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !r_viewleaf ) return; ent = CL_GetWaterEntity( RI.vieworg ); if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 ) cnt = ent->curstate.skin; else cnt = r_viewleaf->contents; if( IsLiquidContents( RI.cached_contents ) && !IsLiquidContents( cnt )) { RI.cached_contents = CONTENTS_EMPTY; return; } if( RI.refdef.waterlevel < 3 ) return; if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt )) { tex = NULL; // check for water texture if( ent && ent->model && ent->model->type == mod_brush ) { msurface_t *surf; count = ent->model->nummodelsurfaces; for( i = 0, surf = &ent->model->surfaces[ent->model->firstmodelsurface]; i < count; i++, surf++ ) { if( surf->flags & SURF_DRAWTURB && surf->texinfo && surf->texinfo->texture ) { tex = R_GetTexture( surf->texinfo->texture->gl_texturenum ); RI.cached_contents = ent->curstate.skin; break; } } } else { tex = R_RecursiveFindWaterTexture( r_viewleaf->parent, NULL, false ); if( tex ) RI.cached_contents = r_viewleaf->contents; } if( !tex ) return; // no valid fogs // copy fog params RI.fogColor[0] = tex->fogParams[0] / 255.0f; RI.fogColor[1] = tex->fogParams[1] / 255.0f; RI.fogColor[2] = tex->fogParams[2] / 255.0f; RI.fogDensity = tex->fogParams[3] * 0.000025f; RI.fogStart = RI.fogEnd = 0.0f; RI.fogCustom = false; RI.fogEnabled = true; } else { RI.fogCustom = false; RI.fogEnabled = true; } }
/* ============= R_RecursiveFindWaterTexture using to find source waterleaf with watertexture to grab fog values from it ============= */ static gltexture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) { gltexture_t *tex = NULL; // assure the initial node is not null // we could check it here, but we would rather check it // outside the call to get rid of one additional recursion level ASSERT( node != NULL ); // ignore solid nodes if( node->contents == CONTENTS_SOLID ) return NULL; if( node->contents < 0 ) { mleaf_t *pleaf; msurface_t **mark; int i, c; // ignore non-liquid leaves if( node->contents != CONTENTS_WATER && node->contents != CONTENTS_LAVA && node->contents != CONTENTS_SLIME ) return NULL; // find texture pleaf = (mleaf_t *)node; mark = pleaf->firstmarksurface; c = pleaf->nummarksurfaces; for( i = 0; i < c; i++, mark++ ) { if( (*mark)->flags & SURF_DRAWTURB && (*mark)->texinfo && (*mark)->texinfo->texture ) return R_GetTexture( (*mark)->texinfo->texture->gl_texturenum ); } // texture not found return NULL; } // this is a regular node // traverse children if( node->children[0] && ( node->children[0] != ignore )) { tex = R_RecursiveFindWaterTexture( node->children[0], node, true ); if( tex ) return tex; } if( node->children[1] && ( node->children[1] != ignore )) { tex = R_RecursiveFindWaterTexture( node->children[1], node, true ); if( tex ) return tex; } // for down recursion, return immediately if( down ) return NULL; // texture not found, step up if any if( node->parent ) return R_RecursiveFindWaterTexture( node->parent, node, false ); // top-level node, bail out return NULL; }
void R_ParseDetailTextures( const char *filename ) { char *afile, *pfile; string token, texname, detail_texname; float xScale, yScale; texture_t *tex; int i; if( r_detailtextures->integer >= 2 && !FS_FileExists( filename, false )) { // use built-in generator for detail textures R_CreateDetailTexturesList( filename ); } afile = FS_LoadFile( filename, NULL, false ); if( !afile ) return; pfile = afile; // format: 'texturename' 'detailtexture' 'xScale' 'yScale' while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { texname[0] = '\0'; // read texname if( token[0] == '{' ) { // NOTE: COM_ParseFile handled some symbols seperately // this code will be fix it pfile = COM_ParseFile( pfile, token ); Q_strncat( texname, "{", sizeof( texname )); Q_strncat( texname, token, sizeof( texname )); } else Q_strncpy( texname, token, sizeof( texname )); // read detailtexture name pfile = COM_ParseFile( pfile, token ); Q_snprintf( detail_texname, sizeof( detail_texname ), "gfx/%s.tga", token ); // read scales pfile = COM_ParseFile( pfile, token ); xScale = Q_atof( token ); pfile = COM_ParseFile( pfile, token ); yScale = Q_atof( token ); if( xScale <= 0.0f || yScale <= 0.0f ) continue; // search for existing texture and uploading detail texture for( i = 0; i < cl.worldmodel->numtextures; i++ ) { tex = cl.worldmodel->textures[i]; if( Q_stricmp( tex->name, texname )) continue; tex->dt_texturenum = GL_LoadTexture( detail_texname, NULL, 0, TF_FORCE_COLOR ); // texture is loaded if( tex->dt_texturenum ) { gltexture_t *glt; GL_SetTextureType( tex->dt_texturenum, TEX_DETAIL ); glt = R_GetTexture( tex->gl_texturenum ); glt->xscale = xScale; glt->yscale = yScale; } break; } } Mem_Free( afile ); }