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;
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;
}
}
- // 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)
// 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;
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)
{
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;
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;
char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
unsigned long custsurfaceparms[256];
int numcustsurfaceparms;
+ qboolean dpshaderkill;
Mod_FreeQ3Shaders();
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;
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;
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"))
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))
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
{
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)
{
}
}
}
+ // 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)
{
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".
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;
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);
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])
{
if(cls.state == ca_dedicated)
{
texture->skinframes[0] = NULL;
+ success = false;
}
else
{
}
// 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;
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)
// 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;
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)
{
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;