X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=0234fdfb76bf4c3d18d44a889dd8e2a4e9c44261;hp=cab744cf2c52b50bd166fe74d9379b430d9d736e;hb=09f884dd87cbb5b3da9e261d8c0841cdb9365c5b;hpb=52a9f0f4041932c38ef07c932aef189957f4164c diff --git a/gl_rmain.c b/gl_rmain.c index cab744cf..0234fdfb 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -76,6 +76,7 @@ cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygo cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"}; cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"}; cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"}; +cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"}; cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"}; cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"}; cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"}; @@ -315,22 +316,22 @@ static void R_BuildBlankTextures(void) data[1] = 128; // normal Y data[0] = 255; // normal Z data[3] = 128; // height - r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL); + r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL); data[0] = 255; data[1] = 255; data[2] = 255; data[3] = 255; - r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL); + r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL); data[0] = 128; data[1] = 128; data[2] = 128; data[3] = 255; - r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL); + r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL); data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 255; - r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL); + r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL); } static void R_BuildNoTexture(void) @@ -358,14 +359,14 @@ static void R_BuildNoTexture(void) } } } - r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL); + r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL); } static void R_BuildWhiteCube(void) { unsigned char data[6*1*1*4]; memset(data, 255, sizeof(data)); - r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL); + r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL); } static void R_BuildNormalizationCube(void) @@ -426,7 +427,7 @@ static void R_BuildNormalizationCube(void) } } } - r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL); + r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL); Mem_Free(data); } @@ -481,7 +482,7 @@ static void R_BuildFogTexture(void) } else { - r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL); + r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL); //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL); } } @@ -498,7 +499,7 @@ static void R_BuildFogHeightTexture(void) inpixels = NULL; strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename)); if (r_refdef.fogheighttexturename[0]) - inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false); + inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL); if (!inpixels) { r_refdef.fog_height_tablesize = 0; @@ -551,7 +552,7 @@ static void R_BuildFogHeightTexture(void) r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f); } } - r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL); + r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL); } //======================================================================================================================================================= @@ -728,7 +729,7 @@ static const char *builtinshaderstring = " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n" " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n" " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n" -" gl_FragColor.rgb = gl_FragColor.rgb * UserVec2.x + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n" +" gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n" "#endif\n" "\n" "#ifdef USESATURATION\n" @@ -4928,7 +4929,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, case RENDERPATH_GL20: if (gl_mesh_separatearrays.integer) { - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset); R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); @@ -4939,7 +4940,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else { - RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer); } R_SetupShader_SetPermutationGLSL(mode, permutation); @@ -5048,7 +5049,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture ); if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation ); if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white ); - if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap ); + if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , r_texture_blanknormalmap ); if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture ); if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white ); if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white ); @@ -5074,7 +5075,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, #ifdef SUPPORTCG if (gl_mesh_separatearrays.integer) { - RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset); R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); @@ -5085,7 +5086,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else { - RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); + RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist); R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer); } R_SetupShader_SetPermutationCG(mode, permutation); @@ -5506,6 +5507,7 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \ } +extern cvar_t gl_picmip; skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) { int j; @@ -5519,6 +5521,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole qboolean ddshasalpha = false; float ddsavgcolor[4]; char basename[MAX_QPATH]; + int miplevel = R_PicmipForFlags(textureflags); + int savemiplevel = miplevel; + int mymiplevel; if (cls.state == ca_dedicated) return NULL; @@ -5533,13 +5538,15 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole Image_StripImageExtension(name, basename, sizeof(basename)); // check for DDS texture file first - if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor))) + if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel))) { - basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer); + basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel); if (basepixels == NULL) return NULL; } + // FIXME handle miplevel + if (developer_loading.integer) Con_Printf("loading skin \"%s\"\n", name); @@ -5564,14 +5571,14 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole skinframe->hasalpha = ddshasalpha; VectorCopy(ddsavgcolor, skinframe->avgcolor); if (r_loadfog && skinframe->hasalpha) - skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL); + skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel); //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]); } else { basepixels_width = image_width; basepixels_height = image_height; - skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); if (textureflags & TEXF_ALPHA) { for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4) @@ -5593,7 +5600,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole pixels[j+2] = 255; pixels[j+3] = basepixels[j+3]; } - skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); Mem_Free(pixels); } } @@ -5607,30 +5614,32 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole if (r_loaddds) { + mymiplevel = savemiplevel; if (r_loadnormalmap) - skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL); - skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL); + skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, mymiplevel); + skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); if (r_loadgloss) - skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL); - skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL); - skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL); - skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL); + skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); } // _norm is the name used by tenebrae and has been adopted as standard if (r_loadnormalmap && skinframe->nmap == NULL) { - if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL) + mymiplevel = savemiplevel; + if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL) { - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); Mem_Free(pixels); pixels = NULL; } - else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL) + else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL) { pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); Mem_Free(pixels); Mem_Free(bumppixels); } @@ -5638,7 +5647,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); Mem_Free(pixels); } if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap) @@ -5647,44 +5656,49 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole // _luma is supported only for tenebrae compatibility // _glow is the preferred name - if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))) + mymiplevel = savemiplevel; + if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))) { - skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow) R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true); Mem_Free(pixels);pixels = NULL; } - if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))) + mymiplevel = savemiplevel; + if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))) { - skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss) R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true); Mem_Free(pixels); pixels = NULL; } - if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))) + mymiplevel = savemiplevel; + if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))) { - skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants) R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true); Mem_Free(pixels); pixels = NULL; } - if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))) + mymiplevel = savemiplevel; + if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))) { - skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt) R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true); Mem_Free(pixels); pixels = NULL; } - if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))) + mymiplevel = savemiplevel; + if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))) { - skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL); + skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect) R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true); Mem_Free(pixels); @@ -5736,10 +5750,10 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); temp2 = temp1 + width * height * 4; Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL); Mem_Free(temp1); } - skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL); + skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL); if (textureflags & TEXF_ALPHA) { for (i = 3;i < width * height * 4;i += 4) @@ -5756,7 +5770,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co memcpy(fogpixels, skindata, width * height * 4); for (i = 0;i < width * height * 4;i += 4) fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255; - skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL); + skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL); Mem_Free(fogpixels); } } @@ -5859,27 +5873,27 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo // use either a custom palette or the quake palette Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete); Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL); Mem_Free(temp1); } if (skinframe->qgenerateglow) { skinframe->qgenerateglow = false; - skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow + skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow } if (colormapped) { skinframe->qgeneratebase = false; - skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap); - skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite); - skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite); + skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap); + skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite); + skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite); } else { skinframe->qgeneratemerged = false; - skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete); + skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete); } if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase) @@ -5921,7 +5935,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co if (developer_loading.integer) Con_Printf("loading embedded 8bit image \"%s\"\n", name); - skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette); + skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette); if (textureflags & TEXF_ALPHA) { for (i = 0;i < width * height;i++) @@ -5933,7 +5947,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co } } if (r_loadfog && skinframe->hasalpha) - skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette); + skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, alphapalette); } R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]); @@ -6026,7 +6040,7 @@ rtexture_t *R_LoadCubemap(const char *basename) // generate an image name based on the base and and suffix dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix); // load it - if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer))) + if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL))) { // an image loaded, make sure width and height are equal if (image_width == image_height && (!cubemappixels || image_width == cubemapsize)) @@ -6055,7 +6069,7 @@ rtexture_t *R_LoadCubemap(const char *basename) if (developer_loading.integer) Con_Printf("loading cubemap \"%s\"\n", basename); - cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL); + cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); Mem_Free(cubemappixels); } else @@ -6296,7 +6310,6 @@ extern void CL_ParseEntityLump(char *entitystring); void gl_main_newmap(void) { // FIXME: move this code to client - int l; char *entities, entname[MAX_QPATH]; if (r_qwskincache) Mem_Free(r_qwskincache); @@ -6304,17 +6317,12 @@ void gl_main_newmap(void) r_qwskincache_size = 0; if (cl.worldmodel) { - strlcpy(entname, cl.worldmodel->name, sizeof(entname)); - l = (int)strlen(entname) - 4; - if (l >= 0 && !strcmp(entname + l, ".bsp")) + dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension); + if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL))) { - memcpy(entname + l, ".ent", 5); - if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL))) - { - CL_ParseEntityLump(entities); - Mem_Free(entities); - return; - } + CL_ParseEntityLump(entities); + Mem_Free(entities); + return; } if (cl.worldmodel->brush.entities) CL_ParseEntityLump(cl.worldmodel->brush.entities); @@ -6371,6 +6379,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_showdisabledepthtest); Cvar_RegisterVariable(&r_drawportals); Cvar_RegisterVariable(&r_drawentities); + Cvar_RegisterVariable(&r_drawworld); Cvar_RegisterVariable(&r_cullentities_trace); Cvar_RegisterVariable(&r_cullentities_trace_samples); Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples); @@ -7581,14 +7590,14 @@ static void R_Water_ProcessPlanes(void) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { if (!p->texture_refraction) - p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL); + p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_refraction) goto error; } else if (p->materialflags & MATERIALFLAG_CAMERA) { if (!p->texture_camera) - p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL); + p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, -1, NULL); if (!p->texture_camera) goto error; } @@ -7596,7 +7605,7 @@ static void R_Water_ProcessPlanes(void) if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { if (!p->texture_reflection) - p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL); + p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_reflection) goto error; } @@ -7693,7 +7702,7 @@ static void R_Water_ProcessPlanes(void) r_refdef.view.cullface_front = GL_FRONT; r_refdef.view.cullface_back = GL_BACK; // also reverse the view matrix - Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1); + Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round R_RenderView_UpdateViewVectors(); if(p->camera_entity) r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false); @@ -7787,7 +7796,7 @@ void R_Bloom_StartFrame(void) r_bloomstate.screentexturewidth = screentexturewidth; r_bloomstate.screentextureheight = screentextureheight; if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight) - r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL); + r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL); } if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight) { @@ -7797,7 +7806,7 @@ void R_Bloom_StartFrame(void) r_bloomstate.bloomtexturewidth = bloomtexturewidth; r_bloomstate.bloomtextureheight = bloomtextureheight; if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight) - r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL); + r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); } // when doing a reduced render (HDR) we want to use a smaller area @@ -8334,7 +8343,7 @@ void R_UpdateVariables(void) } else { - r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL); + r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL); } } } @@ -9113,12 +9122,22 @@ static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, layer->color[3] = a; } +static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms) +{ + if(parms[0] == 0 && parms[1] == 0) + return false; + if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set! + if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0) + return false; + return true; +} + static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) { double index, f; index = parms[2] + r_refdef.scene.time * parms[3]; index -= floor(index); - switch (func) + switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1)) { default: case Q3WAVEFUNC_NONE: @@ -9143,7 +9162,10 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) f = -(1 - f); break; } - return (float)(parms[0] + parms[1] * f); + f = parms[0] + parms[1] * f; + if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set! + f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)]; + return (float) f; } void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) @@ -9580,6 +9602,7 @@ void RSurf_ActiveWorldEntity(void) // return; rsurface.entity = r_refdef.scene.worldentity; rsurface.skeleton = NULL; + memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = 0; rsurface.ent_qwskin = -1; rsurface.ent_shadertime = 0; @@ -9694,6 +9717,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q // return; rsurface.entity = (entity_render_t *)ent; rsurface.skeleton = ent->skeleton; + memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = ent->skinnum; rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_shadertime = ent->shadertime; @@ -10133,6 +10157,9 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // may require regenerating vertexmesh or vertexposition arrays... needsupdate = 0; + // check if any dynamic vertex processing must occur + dynamicvertex = false; + if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo) needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS; for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++) @@ -10152,26 +10179,36 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const case Q3DEFORM_NONE: break; case Q3DEFORM_AUTOSPRITE: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR; break; case Q3DEFORM_AUTOSPRITE2: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR; break; case Q3DEFORM_NORMAL: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR; break; case Q3DEFORM_WAVE: - batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; + if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms)) + break; // if wavefunc is a nop, ignore this transform + dynamicvertex = true; + batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR; break; case Q3DEFORM_BULGE: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR; break; case Q3DEFORM_MOVE: + if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms)) + break; // if wavefunc is a nop, ignore this transform + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX; break; @@ -10183,27 +10220,28 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const case Q3TCGEN_TEXTURE: break; case Q3TCGEN_LIGHTMAP: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP; break; case Q3TCGEN_VECTOR: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; break; case Q3TCGEN_ENVIRONMENT: + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; break; } if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT) { + dynamicvertex = true; batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS; needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD; } - // check if any dynamic vertex processing must occur - dynamicvertex = false; - if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))) { dynamicvertex = true; @@ -10695,6 +10733,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const waveparms[1] = deform->waveparms[1]; waveparms[2] = deform->waveparms[2]; waveparms[3] = deform->waveparms[3]; + if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms)) + break; // if wavefunc is a nop, don't make a dynamic vertex array // this is how a divisor of vertex influence on deformation animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f; scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms); @@ -10747,6 +10787,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const break; case Q3DEFORM_MOVE: // deform vertex array + if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms)) + break; // if wavefunc is a nop, don't make a dynamic vertex array scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms); VectorScale(deform->parms, scale, waveparms); for (j = 0;j < rsurface.batchnumvertices;j++) @@ -10901,32 +10943,39 @@ static void RSurf_BindLightmapForBatch(void) } } -static void RSurf_BindReflectionForBatch(void) +static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface) { - // pick the closest matching water plane and bind textures - int planeindex, vertexindex; + // pick the closest matching water plane + int planeindex, vertexindex, bestplaneindex = -1; float d, bestd; vec3_t vert; const float *v; - r_waterstate_waterplane_t *p, *bestp; + r_waterstate_waterplane_t *p; bestd = 0; - bestp = NULL; for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) { if(p->camera_entity != rsurface.texture->camera_entity) continue; d = 0; + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface); for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3) { Matrix4x4_Transform(&rsurface.matrix, v, vert); d += fabs(PlaneDiff(vert, &p->plane)); } - if (bestd > d || !bestp) + if (bestd > d || bestplaneindex < 0) { bestd = d; - bestp = p; + bestplaneindex = planeindex; } } + return bestplaneindex; +} + +static void RSurf_BindReflectionForBatch(int planeindex) +{ + // pick the closest matching water plane and bind textures + r_waterstate_waterplane_t *bestp = planeindex >= 0 ? r_waterstate.waterplanes + planeindex : NULL; switch(vid.renderpath) { case RENDERPATH_CGGL: @@ -11257,33 +11306,55 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface GL_DepthMask(true); R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist); RSurf_DrawBatch(); + return; } - else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene) - { - // render water or distortion background, then blend surface on top - GL_DepthMask(true); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, texturenumsurfaces, texturesurfacelist); - RSurf_BindReflectionForBatch(); - if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); - GL_DepthMask(false); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist); - if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); - } - else + + // bind lightmap texture + + // water/refraction/reflection/camera surfaces have to be handled specially + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene) { - // render surface normally - GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist); - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) - RSurf_BindReflectionForBatch(); - if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) - RSurf_BindLightmapForBatch(); - RSurf_DrawBatch(); + int start, end, startplaneindex; + for (start = 0;start < texturenumsurfaces;start = end) + { + startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]); + for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++) + ; + // now that we have a batch using the same planeindex, render it + if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene) + { + // render water or distortion background + GL_DepthMask(true); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start); + RSurf_BindReflectionForBatch(startplaneindex); + if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) + RSurf_BindLightmapForBatch(); + RSurf_DrawBatch(); + // blend surface on top + GL_DepthMask(false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start); + RSurf_DrawBatch(); + } + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene) + { + // render surface with reflection texture as input + GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start); + RSurf_BindReflectionForBatch(startplaneindex); + if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) + RSurf_BindLightmapForBatch(); + RSurf_DrawBatch(); + } + } + return; } + + // render surface batch normally + GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist); + if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) + RSurf_BindLightmapForBatch(); + RSurf_DrawBatch(); } static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth) @@ -12155,13 +12226,92 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float extern cvar_t cl_decals_bias; extern cvar_t cl_decals_models; extern cvar_t cl_decals_newsystem_intensitymultiplier; +// baseparms, parms, temps +static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex) +{ + int cornerindex; + int index; + float v[9][3]; + const float *vertex3f; + int numpoints; + float points[2][9][3]; + float temp[3]; + float tc[9][2]; + float f; + float c[9][4]; + const int *e; + + e = rsurface.modelelement3i + 3*triangleindex; + + vertex3f = rsurface.modelvertex3f; + + for (cornerindex = 0;cornerindex < 3;cornerindex++) + { + index = 3*e[cornerindex]; + VectorCopy(vertex3f + index, v[cornerindex]); + } + // cull backfaces + //TriangleNormal(v[0], v[1], v[2], normal); + //if (DotProduct(normal, localnormal) < 0.0f) + // continue; + // clip by each of the box planes formed from the projection matrix + // if anything survives, we emit the decal + numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]); + if (numpoints < 3) + return; + // some part of the triangle survived, so we have to accept it... + if (dynamic) + { + // dynamic always uses the original triangle + numpoints = 3; + for (cornerindex = 0;cornerindex < 3;cornerindex++) + { + index = 3*e[cornerindex]; + VectorCopy(vertex3f + index, v[cornerindex]); + } + } + for (cornerindex = 0;cornerindex < numpoints;cornerindex++) + { + // convert vertex positions to texcoords + Matrix4x4_Transform(projection, v[cornerindex], temp); + tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1; + tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1; + // calculate distance fade from the projection origin + f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value; + f = bound(0.0f, f, 1.0f); + c[cornerindex][0] = r * f; + c[cornerindex][1] = g * f; + c[cornerindex][2] = b * f; + c[cornerindex][3] = 1.0f; + //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]); + } + if (dynamic) + R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence); + else + for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++) + R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence); +} static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence) { matrix4x4_t projection; decalsystem_t *decalsystem; qboolean dynamic; dp_model_t *model; - const float *vertex3f; const msurface_t *surface; const msurface_t *surfaces; const int *surfacelist; @@ -12171,24 +12321,18 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor int surfacelistindex; int surfaceindex; int triangleindex; - int cornerindex; - int index; - int numpoints; - const int *e; float localorigin[3]; float localnormal[3]; float localmins[3]; float localmaxs[3]; float localsize; - float v[9][3]; - float tc[9][2]; - float c[9][4]; //float normal[3]; float planes[6][4]; - float f; - float points[2][9][3]; float angles[3]; - float temp[3]; + bih_t *bih; + int bih_triangles_count; + int bih_triangles[256]; + int bih_surfaces[256]; decalsystem = &ent->decalsystem; model = ent->model; @@ -12267,86 +12411,57 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor #endif dynamic = model->surfmesh.isanimated; - vertex3f = rsurface.modelvertex3f; numsurfacelist = model->nummodelsurfaces; surfacelist = model->sortedmodelsurfaces; surfaces = model->data_surfaces; - for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + + bih = NULL; + bih_triangles_count = -1; + if(!dynamic) { - surfaceindex = surfacelist[surfacelistindex]; - surface = surfaces + surfaceindex; - // check cull box first because it rejects more than any other check - if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) - continue; - // skip transparent surfaces - texture = surface->texture; - if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) - continue; - if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) - continue; - numtriangles = surface->num_triangles; - for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3) + if(model->render_bih.numleafs) + bih = &model->render_bih; + else if(model->collision_bih.numleafs) + bih = &model->collision_bih; + } + if(bih) + bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs); + if(bih_triangles_count == 0) + return; + if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway + return; + if(bih_triangles_count > 0) + { + for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex) { - for (cornerindex = 0;cornerindex < 3;cornerindex++) - { - index = 3*e[cornerindex]; - VectorCopy(vertex3f + index, v[cornerindex]); - } - // cull backfaces - //TriangleNormal(v[0], v[1], v[2], normal); - //if (DotProduct(normal, localnormal) < 0.0f) - // continue; - // clip by each of the box planes formed from the projection matrix - // if anything survives, we emit the decal - numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) - continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); - if (numpoints < 3) + surfaceindex = bih_surfaces[triangleindex]; + surface = surfaces + surfaceindex; + texture = surface->texture; + if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) continue; - numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) + if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); - if (numpoints < 3) + R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex); + } + } + else + { + for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + { + surfaceindex = surfacelist[surfacelistindex]; + surface = surfaces + surfaceindex; + // check cull box first because it rejects more than any other check + if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) continue; - numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) + // skip transparent surfaces + texture = surface->texture; + if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]); - if (numpoints < 3) + if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) continue; - // some part of the triangle survived, so we have to accept it... - if (dynamic) - { - // dynamic always uses the original triangle - numpoints = 3; - for (cornerindex = 0;cornerindex < 3;cornerindex++) - { - index = 3*e[cornerindex]; - VectorCopy(vertex3f + index, v[cornerindex]); - } - } - for (cornerindex = 0;cornerindex < numpoints;cornerindex++) - { - // convert vertex positions to texcoords - Matrix4x4_Transform(&projection, v[cornerindex], temp); - tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1; - tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1; - // calculate distance fade from the projection origin - f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value; - f = bound(0.0f, f, 1.0f); - c[cornerindex][0] = r * f; - c[cornerindex][1] = g * f; - c[cornerindex][2] = b * f; - c[cornerindex][3] = 1.0f; - //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]); - } - if (dynamic) - R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence); - else - for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++) - R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence); + numtriangles = surface->num_triangles; + for (triangleindex = 0; triangleindex < numtriangles; triangleindex++) + R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex); } } }