X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_shared.c;h=47b4c58fabedfde42ed40f62707e0f17c9a13598;hb=853f7fe77fd4e7a79e682cf964e4ad863a1a60e7;hp=482cfe791b6a7b2bcacbdccf86564f9a1c1b65ed;hpb=c227b46e44bc1c37af4d9ef9b257c59fa396d043;p=xonotic%2Fdarkplaces.git diff --git a/model_shared.c b/model_shared.c index 482cfe79..47b4c58f 100644 --- a/model_shared.c +++ b/model_shared.c @@ -27,7 +27,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_shadow.h" #include "polygon.h" +cvar_t r_enableshadowvolumes = {CVAR_SAVE, "r_enableshadowvolumes", "1", "Enables use of Stencil Shadow Volume shadowing methods, saves some memory if turned off"}; cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0", "mipmaps model skins so they render faster in the distance and do not display noise artifacts, can cause discoloration of skins if they contain undesirable border colors"}; +cvar_t r_mipnormalmaps = {CVAR_SAVE, "r_mipnormalmaps", "1", "mipmaps normalmaps (turning it off looks sharper but may have aliasing)"}; cvar_t mod_generatelightmaps_unitspersample = {CVAR_SAVE, "mod_generatelightmaps_unitspersample", "8", "lightmap resolution"}; cvar_t mod_generatelightmaps_borderpixels = {CVAR_SAVE, "mod_generatelightmaps_borderpixels", "2", "extra space around polygons to prevent sampling artifacts"}; cvar_t mod_generatelightmaps_texturesize = {CVAR_SAVE, "mod_generatelightmaps_texturesize", "1024", "size of lightmap textures"}; @@ -159,7 +161,9 @@ void Mod_Init (void) Mod_AliasInit(); Mod_SpriteInit(); + Cvar_RegisterVariable(&r_enableshadowvolumes); Cvar_RegisterVariable(&r_mipskins); + Cvar_RegisterVariable(&r_mipnormalmaps); Cvar_RegisterVariable(&mod_generatelightmaps_unitspersample); Cvar_RegisterVariable(&mod_generatelightmaps_borderpixels); Cvar_RegisterVariable(&mod_generatelightmaps_texturesize); @@ -196,9 +200,9 @@ void Mod_UnloadModel (dp_model_t *mod) used = mod->used; if (mod->mempool) { - if (mod->surfmesh.vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexpositionbuffer); - mod->surfmesh.vertexpositionbuffer = NULL; + if (mod->surfmesh.vertex3fbuffer) + R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertex3fbuffer); + mod->surfmesh.vertex3fbuffer = NULL; if (mod->surfmesh.vertexmeshbuffer) R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexmeshbuffer); mod->surfmesh.vertexmeshbuffer = NULL; @@ -1191,8 +1195,8 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) return; // build r_vertexmesh_t array - // (compressed interleaved array for faster rendering) - if (!mesh->vertexmesh && mesh->texcoord2f) + // (compressed interleaved array for D3D) + if (!mesh->vertexmesh && mesh->texcoord2f && vid.useinterleavedarrays) { int vertexindex; int numvertices = mesh->numverts; @@ -1208,24 +1212,13 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) } } - // build r_vertexposition_t array - if (!mesh->vertexposition) - { - int vertexindex; - int numvertices = mesh->numverts; - r_vertexposition_t *vertexposition; - mesh->vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*mesh->vertexposition)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++) - VectorCopy(mesh->vertex3f + 3*vertexindex, vertexposition->vertex3f); - } - // upload r_vertexmesh_t array as a buffer if (mesh->vertexmesh && !mesh->vertexmeshbuffer) mesh->vertexmeshbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexmesh, mesh->numverts * sizeof(*mesh->vertexmesh), loadmodel->name, false, false, false); - // upload r_vertexposition_t array as a buffer - if (mesh->vertexposition && !mesh->vertexpositionbuffer) - mesh->vertexpositionbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexposition, mesh->numverts * sizeof(*mesh->vertexposition), loadmodel->name, false, false, false); + // upload vertex3f array as a buffer + if (mesh->vertex3f && !mesh->vertex3fbuffer) + mesh->vertex3fbuffer = R_Mesh_CreateMeshBuffer(mesh->vertex3f, mesh->numverts * sizeof(float[3]), loadmodel->name, false, false, false); // upload short indices as a buffer if (mesh->element3s && !mesh->element3s_indexbuffer) @@ -1240,7 +1233,7 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) // is this wise? the texcoordtexture2f array is used with dynamic // vertex/svector/tvector/normal when rendering animated models, on the // other hand animated models don't use a lot of vertices anyway... - if (!mesh->vbo_vertexbuffer) + if (!mesh->vbo_vertexbuffer && !vid.useinterleavedarrays) { size_t size; unsigned char *mem; @@ -1345,8 +1338,8 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) shadowmesh_t *nextmesh; for (;mesh;mesh = nextmesh) { - if (mesh->vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(mesh->vertexpositionbuffer); + if (mesh->vertex3fbuffer) + R_Mesh_DestroyMeshBuffer(mesh->vertex3fbuffer); if (mesh->vertexmeshbuffer) R_Mesh_DestroyMeshBuffer(mesh->vertexmeshbuffer); if (mesh->element3i_indexbuffer) @@ -1362,9 +1355,10 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) void Mod_CreateCollisionMesh(dp_model_t *mod) { - int k; - int numcollisionmeshtriangles; - const msurface_t *surface; + int k, numcollisionmeshtriangles; + qboolean usesinglecollisionmesh = false; + const msurface_t *surface = NULL; + mempool_t *mempool = mod->mempool; if (!mempool && mod->brush.parentmodel) mempool = mod->brush.parentmodel->mempool; @@ -1374,19 +1368,30 @@ void Mod_CreateCollisionMesh(dp_model_t *mod) for (k = 0;k < mod->nummodelsurfaces;k++) { surface = mod->data_surfaces + mod->firstmodelsurface + k; + if (!strcmp(surface->texture->name, "collision")) // found collision mesh + { + usesinglecollisionmesh = true; + numcollisionmeshtriangles = surface->num_triangles; + break; + } if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID)) continue; numcollisionmeshtriangles += surface->num_triangles; } mod->brush.collisionmesh = Mod_ShadowMesh_Begin(mempool, numcollisionmeshtriangles * 3, numcollisionmeshtriangles, NULL, NULL, NULL, false, false, true); - for (k = 0;k < mod->nummodelsurfaces;k++) - { - surface = mod->data_surfaces + mod->firstmodelsurface + k; - if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID)) - continue; + if (usesinglecollisionmesh) Mod_ShadowMesh_AddMesh(mempool, mod->brush.collisionmesh, NULL, NULL, NULL, mod->surfmesh.data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); + else + { + for (k = 0;k < mod->nummodelsurfaces;k++) + { + surface = mod->data_surfaces + mod->firstmodelsurface + k; + if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID)) + continue; + Mod_ShadowMesh_AddMesh(mempool, mod->brush.collisionmesh, NULL, NULL, NULL, mod->surfmesh.data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); + } } - mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, true, false); + mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, false, false); } void Mod_GetTerrainVertex3fTexCoord2fFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) @@ -1568,15 +1573,31 @@ static void Q3Shader_AddToHash (q3shaderinfo_t* shader) { if (strcasecmp (entry->shader.name, shader->name) == 0) { - unsigned char *start, *end, *start2; - start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START); - end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END); - start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START); - if(memcmp(start, start2, end - start)) - Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name); + // redeclaration + if(shader->dpshaderkill) + { + // killed shader is a redeclarion? we can safely ignore it + return; + } + else if(entry->shader.dpshaderkill) + { + // replace the old shader! + // this will skip the entry allocating part + // below and just replace the shader + break; + } else - Con_DPrintf("Shader '%s' already defined\n", shader->name); - return; + { + unsigned char *start, *end, *start2; + start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START); + end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END); + start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START); + if(memcmp(start, start2, end - start)) + Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name); + else + Con_DPrintf("Shader '%s' already defined\n", shader->name); + return; + } } lastEntry = entry; entry = entry->chain; @@ -1600,7 +1621,13 @@ static void Q3Shader_AddToHash (q3shaderinfo_t* shader) memcpy (&entry->shader, shader, sizeof (q3shaderinfo_t)); } +extern cvar_t mod_noshader_default_offsetmapping; extern cvar_t mod_q3shader_default_offsetmapping; +extern cvar_t mod_q3shader_default_offsetmapping_scale; +extern cvar_t mod_q3shader_default_offsetmapping_bias; +extern cvar_t mod_q3shader_default_polygonoffset; +extern cvar_t mod_q3shader_default_polygonfactor; +extern cvar_t mod_q3shader_force_addalpha; void Mod_LoadQ3Shaders(void) { int j; @@ -1615,6 +1642,7 @@ void Mod_LoadQ3Shaders(void) char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more unsigned long custsurfaceparms[256]; int numcustsurfaceparms; + qboolean dpshaderkill; Mod_FreeQ3Shaders(); @@ -1688,9 +1716,12 @@ void Mod_LoadQ3Shaders(void) Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1); shader.r_water_wateralpha = 1; shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF; - shader.offsetscale = 1; + shader.offsetscale = mod_q3shader_default_offsetmapping_scale.value; + shader.offsetbias = mod_q3shader_default_offsetmapping_bias.value; shader.specularscalemod = 1; shader.specularpowermod = 1; + shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value; + shader.biaspolygonfactor = mod_q3shader_default_polygonfactor.value; strlcpy(shader.name, com_token, sizeof(shader.name)); if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{")) @@ -1759,6 +1790,11 @@ void Mod_LoadQ3Shaders(void) layer->blendfunc[0] = GL_ONE; layer->blendfunc[1] = GL_ONE; } + else if (!strcasecmp(parameter[1], "addalpha")) + { + layer->blendfunc[0] = GL_SRC_ALPHA; + layer->blendfunc[1] = GL_ONE; + } else if (!strcasecmp(parameter[1], "filter")) { layer->blendfunc[0] = GL_DST_COLOR; @@ -1786,7 +1822,7 @@ void Mod_LoadQ3Shaders(void) else if (!strcasecmp(parameter[k+1], "GL_DST_COLOR")) layer->blendfunc[k] = GL_DST_COLOR; else if (!strcasecmp(parameter[k+1], "GL_DST_ALPHA")) - layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA; + layer->blendfunc[k] = GL_DST_ALPHA; else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_COLOR")) layer->blendfunc[k] = GL_ONE_MINUS_SRC_COLOR; else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_ALPHA")) @@ -1940,7 +1976,32 @@ void Mod_LoadQ3Shaders(void) shader.textureblendalpha = true; } } - layer->texflags = TEXF_ALPHA; + + if(mod_q3shader_force_addalpha.integer) + { + // for a long while, DP treated GL_ONE GL_ONE as GL_SRC_ALPHA GL_ONE + // this cvar brings back this behaviour + if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE) + layer->blendfunc[0] = GL_SRC_ALPHA; + } + + layer->texflags = 0; + if (layer->alphatest) + layer->texflags |= TEXF_ALPHA; + switch(layer->blendfunc[0]) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + layer->texflags |= TEXF_ALPHA; + break; + } + switch(layer->blendfunc[1]) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + layer->texflags |= TEXF_ALPHA; + break; + } if (!(shader.surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) layer->texflags |= TEXF_MIPMAP; if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP)) @@ -2063,10 +2124,64 @@ void Mod_LoadQ3Shaders(void) shader.dpshadow = true; else if (!strcasecmp(parameter[0], "dpnoshadow")) shader.dpnoshadow = true; + else if (!strcasecmp(parameter[0], "dpnortlight")) + shader.dpnortlight = true; else if (!strcasecmp(parameter[0], "dpreflectcube")) strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube)); else if (!strcasecmp(parameter[0], "dpmeshcollisions")) shader.dpmeshcollisions = true; + // this sets dpshaderkill to true if dpshaderkillifcvarzero was used, and to false if dpnoshaderkillifcvarzero was used + else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvarzero")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvarzero")) && numparameters >= 2) + { + if (Cvar_VariableValue(parameter[1]) == 0.0f) + shader.dpshaderkill = dpshaderkill; + } + // this sets dpshaderkill to true if dpshaderkillifcvar was used, and to false if dpnoshaderkillifcvar was used + else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvar")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvar")) && numparameters >= 2) + { + const char *op = NULL; + if (numparameters >= 3) + op = parameter[2]; + if(!op) + { + if (Cvar_VariableValue(parameter[1]) != 0.0f) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, "==")) + { + if (Cvar_VariableValue(parameter[1]) == atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, "!=")) + { + if (Cvar_VariableValue(parameter[1]) != atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, ">")) + { + if (Cvar_VariableValue(parameter[1]) > atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, "<")) + { + if (Cvar_VariableValue(parameter[1]) < atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, ">=")) + { + if (Cvar_VariableValue(parameter[1]) >= atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else if (numparameters >= 4 && !strcmp(op, "<=")) + { + if (Cvar_VariableValue(parameter[1]) <= atof(parameter[3])) + shader.dpshaderkill = dpshaderkill; + } + else + { + Con_DPrintf("%s parsing warning: unknown dpshaderkillifcvar op \"%s\", or not enough arguments\n", search->filenames[fileindex], op); + } + } else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2) { // some q3 skies don't have the sky parm set @@ -2091,6 +2206,18 @@ void Mod_LoadQ3Shaders(void) shader.textureflags |= Q3TEXTUREFLAG_NOPICMIP; else if (!strcasecmp(parameter[0], "polygonoffset")) shader.textureflags |= Q3TEXTUREFLAG_POLYGONOFFSET; + else if (!strcasecmp(parameter[0], "dppolygonoffset")) + { + shader.textureflags |= Q3TEXTUREFLAG_POLYGONOFFSET; + if(numparameters >= 2) + { + shader.biaspolygonfactor = atof(parameter[1]); + if(numparameters >= 3) + shader.biaspolygonoffset = atof(parameter[2]); + else + shader.biaspolygonoffset = 0; + } + } else if (!strcasecmp(parameter[0], "dprefract") && numparameters >= 5) { shader.textureflags |= Q3TEXTUREFLAG_REFRACTION; @@ -2118,6 +2245,11 @@ void Mod_LoadQ3Shaders(void) Vector4Set(shader.reflectcolor4f, atof(parameter[8]), atof(parameter[9]), atof(parameter[10]), 1); shader.r_water_wateralpha = atof(parameter[11]); } + else if (!strcasecmp(parameter[0], "dpwaterscroll") && numparameters >= 3) + { + shader.r_water_waterscroll[0] = 1/atof(parameter[1]); + shader.r_water_waterscroll[1] = 1/atof(parameter[2]); + } else if (!strcasecmp(parameter[0], "dpglossintensitymod") && numparameters >= 2) { shader.specularscalemod = atof(parameter[1]); @@ -2126,17 +2258,33 @@ void Mod_LoadQ3Shaders(void) { shader.specularpowermod = atof(parameter[1]); } - else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 3) + else if (!strcasecmp(parameter[0], "dprtlightambient") && numparameters >= 2) + { + shader.rtlightambient = atof(parameter[1]); + } + else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 2) { if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off")) shader.offsetmapping = OFFSETMAPPING_OFF; - else if (!strcasecmp(parameter[1], "default")) + else if (!strcasecmp(parameter[1], "default") || !strcasecmp(parameter[1], "normal")) shader.offsetmapping = OFFSETMAPPING_DEFAULT; else if (!strcasecmp(parameter[1], "linear")) shader.offsetmapping = OFFSETMAPPING_LINEAR; else if (!strcasecmp(parameter[1], "relief")) shader.offsetmapping = OFFSETMAPPING_RELIEF; - shader.offsetscale = atof(parameter[2]); + if (numparameters >= 3) + shader.offsetscale = atof(parameter[2]); + if (numparameters >= 5) + { + if(!strcasecmp(parameter[3], "bias")) + shader.offsetbias = atof(parameter[4]); + else if(!strcasecmp(parameter[3], "match")) + shader.offsetbias = 1.0f - atof(parameter[4]); + else if(!strcasecmp(parameter[3], "match8")) + shader.offsetbias = 1.0f - atof(parameter[4]) / 255.0f; + else if(!strcasecmp(parameter[3], "match16")) + shader.offsetbias = 1.0f - atof(parameter[4]) / 65535.0f; + } } else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2) { @@ -2178,6 +2326,9 @@ void Mod_LoadQ3Shaders(void) } } } + // hide this shader if a cvar said it should be killed + if (shader.dpshaderkill) + shader.numlayers = 0; // pick the primary layer to render with if (shader.numlayers) { @@ -2236,7 +2387,7 @@ q3shaderinfo_t *Mod_LookupQ3Shader(const char *name) qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags) { int j; - int texflagsmask; + int texflagsmask, texflagsor; qboolean success = true; q3shaderinfo_t *shader; if (!name) @@ -2249,11 +2400,18 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool texflagsmask &= ~TEXF_PICMIP; if(!(defaulttexflags & TEXF_COMPRESS)) texflagsmask &= ~TEXF_COMPRESS; + texflagsor = 0; + if(defaulttexflags & TEXF_ISWORLD) + texflagsor |= TEXF_ISWORLD; + if(defaulttexflags & TEXF_ISSPRITE) + texflagsor |= TEXF_ISSPRITE; // unless later loaded from the shader - texture->offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF; + texture->offsetmapping = (mod_noshader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF; texture->offsetscale = 1; + texture->offsetbias = 0; texture->specularscalemod = 1; texture->specularpowermod = 1; + texture->rtlightambient = 0; // WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE // HERE, AND Q1BSP LOADING // JUST GREP FOR "specularscalemod = 1". @@ -2265,7 +2423,7 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool texture->surfaceparms = shader->surfaceparms; // allow disabling of picmip or compression by defaulttexflags - texture->textureflags = shader->textureflags & texflagsmask; + texture->textureflags = (shader->textureflags & texflagsmask) | texflagsor; if (shader->surfaceparms & Q3SURFACEPARM_SKY) { @@ -2286,7 +2444,10 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool if (shader->textureflags & Q3TEXTUREFLAG_TWOSIDED) texture->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; if (shader->textureflags & Q3TEXTUREFLAG_POLYGONOFFSET) - texture->biaspolygonoffset -= 2; + { + texture->biaspolygonoffset += shader->biaspolygonoffset; + texture->biaspolygonfactor += shader->biaspolygonfactor; + } if (shader->textureflags & Q3TEXTUREFLAG_REFRACTION) texture->basematerialflags |= MATERIALFLAG_REFRACTION; if (shader->textureflags & Q3TEXTUREFLAG_REFLECTION) @@ -2353,7 +2514,7 @@ nothing GL_ZERO GL_ONE { texture->skinframes[j] = NULL; } - else if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], primarylayer->texflags & texflagsmask, false))) + else if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], (primarylayer->texflags & texflagsmask) | texflagsor, false))) { Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (frame %i) for shader ^2\"%s\"\n", loadmodel->name, primarylayer->texturename[j], j, texture->name); texture->skinframes[j] = R_SkinFrame_LoadMissing(); @@ -2374,7 +2535,7 @@ nothing GL_ZERO GL_ONE { texture->skinframes[j] = NULL; } - else if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], backgroundlayer->texflags & texflagsmask, false))) + else if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], (backgroundlayer->texflags & texflagsmask) | texflagsor, false))) { Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (background frame %i) for shader ^2\"%s\"\n", loadmodel->name, backgroundlayer->texturename[j], j, texture->name); texture->backgroundskinframes[j] = R_SkinFrame_LoadMissing(); @@ -2385,6 +2546,8 @@ nothing GL_ZERO GL_ONE texture->basematerialflags &= ~MATERIALFLAG_NOSHADOW; if (shader->dpnoshadow) texture->basematerialflags |= MATERIALFLAG_NOSHADOW; + if (shader->dpnortlight) + texture->basematerialflags |= MATERIALFLAG_NORTLIGHT; memcpy(texture->deforms, shader->deforms, sizeof(texture->deforms)); texture->reflectmin = shader->reflectmin; texture->reflectmax = shader->reflectmax; @@ -2393,10 +2556,13 @@ nothing GL_ZERO GL_ONE texture->reflectfactor = shader->reflectfactor; Vector4Copy(shader->reflectcolor4f, texture->reflectcolor4f); texture->r_water_wateralpha = shader->r_water_wateralpha; + Vector2Copy(shader->r_water_waterscroll, texture->r_water_waterscroll); texture->offsetmapping = shader->offsetmapping; texture->offsetscale = shader->offsetscale; + texture->offsetbias = shader->offsetbias; texture->specularscalemod = shader->specularscalemod; texture->specularpowermod = shader->specularpowermod; + texture->rtlightambient = shader->rtlightambient; if (shader->dpreflectcube[0]) texture->reflectcubetexture = R_GetCubemap(shader->dpreflectcube); @@ -2445,6 +2611,8 @@ nothing GL_ZERO GL_ONE if (shader->dpmeshcollisions) texture->basematerialflags |= MATERIALFLAG_MESHCOLLISIONS; + if (shader->dpshaderkill && developer_extra.integer) + Con_DPrintf("^1%s:^7 killing shader ^3\"%s\" because of cvar\n", loadmodel->name, name); } else if (!strcmp(texture->name, "noshader") || !texture->name[0]) { @@ -2485,6 +2653,7 @@ nothing GL_ZERO GL_ONE if(cls.state == ca_dedicated) { texture->skinframes[0] = NULL; + success = false; } else { @@ -2748,8 +2917,8 @@ void Mod_BuildVBOs(void) } // build r_vertexmesh_t array - // (compressed interleaved array for faster rendering) - if (!loadmodel->surfmesh.vertexmesh) + // (compressed interleaved array for D3D) + if (!loadmodel->surfmesh.vertexmesh && vid.useinterleavedarrays) { int vertexindex; int numvertices = loadmodel->surfmesh.num_vertices; @@ -2762,31 +2931,20 @@ void Mod_BuildVBOs(void) VectorScale(loadmodel->surfmesh.data_tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f); VectorScale(loadmodel->surfmesh.data_normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f); if (loadmodel->surfmesh.data_lightmapcolor4f) - Vector4Scale(loadmodel->surfmesh.data_lightmapcolor4f + 4*vertexindex, 255.0f, vertexmesh->color4ub); + Vector4Copy(loadmodel->surfmesh.data_lightmapcolor4f + 4*vertexindex, vertexmesh->color4f); Vector2Copy(loadmodel->surfmesh.data_texcoordtexture2f + 2*vertexindex, vertexmesh->texcoordtexture2f); if (loadmodel->surfmesh.data_texcoordlightmap2f) Vector2Scale(loadmodel->surfmesh.data_texcoordlightmap2f + 2*vertexindex, 1.0f, vertexmesh->texcoordlightmap2f); } } - // build r_vertexposition_t array - if (!loadmodel->surfmesh.vertexposition) - { - int vertexindex; - int numvertices = loadmodel->surfmesh.num_vertices; - r_vertexposition_t *vertexposition; - loadmodel->surfmesh.vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexposition)); - for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++) - VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexposition->vertex3f); - } - // upload r_vertexmesh_t array as a buffer if (loadmodel->surfmesh.vertexmesh && !loadmodel->surfmesh.vertexmeshbuffer) loadmodel->surfmesh.vertexmeshbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexmesh, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexmesh), loadmodel->name, false, false, false); - // upload r_vertexposition_t array as a buffer - if (loadmodel->surfmesh.vertexposition && !loadmodel->surfmesh.vertexpositionbuffer) - loadmodel->surfmesh.vertexpositionbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexposition, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexposition), loadmodel->name, false, false, false); + // upload vertex3f array as a buffer + if (loadmodel->surfmesh.data_vertex3f && !loadmodel->surfmesh.vertex3fbuffer) + loadmodel->surfmesh.vertex3fbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]), loadmodel->name, false, false, false); // upload short indices as a buffer if (loadmodel->surfmesh.data_element3s && !loadmodel->surfmesh.data_element3s_indexbuffer) @@ -2802,7 +2960,7 @@ void Mod_BuildVBOs(void) // is this wise? the texcoordtexture2f array is used with dynamic // vertex/svector/tvector/normal when rendering animated models, on the // other hand animated models don't use a lot of vertices anyway... - if (!loadmodel->surfmesh.vbo_vertexbuffer) + if (!loadmodel->surfmesh.vbo_vertexbuffer && !vid.useinterleavedarrays) { size_t size; unsigned char *mem; @@ -3404,8 +3562,8 @@ static void Mod_GenerateLightmaps_LightPoint(dp_model_t *model, const vec3_t pos continue; lightiradius = 1.0f / lightradius; dist = sqrt(dist2) * lightiradius; - intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0; - if (intensity <= 0) + intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist); + if (intensity <= 0.0f) continue; if (model && model->TraceLine) { @@ -3789,15 +3947,12 @@ static void Mod_GenerateLightmaps_UnweldTriangles(dp_model_t *model) if (model->surfmesh.num_vertices > 65536) model->surfmesh.data_element3s = NULL; - if (model->surfmesh.vertexposition) - Mem_Free(model->surfmesh.vertexposition); - model->surfmesh.vertexposition = NULL; if (model->surfmesh.vertexmesh) Mem_Free(model->surfmesh.vertexmesh); model->surfmesh.vertexmesh = NULL; - if (model->surfmesh.vertexpositionbuffer) - R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexpositionbuffer); - model->surfmesh.vertexpositionbuffer = NULL; + if (model->surfmesh.vertex3fbuffer) + R_Mesh_DestroyMeshBuffer(model->surfmesh.vertex3fbuffer); + model->surfmesh.vertex3fbuffer = NULL; if (model->surfmesh.vertexmeshbuffer) R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexmeshbuffer); model->surfmesh.vertexmeshbuffer = NULL;