#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"};
Mod_AliasInit();
Mod_SpriteInit();
+ Cvar_RegisterVariable(&r_enableshadowvolumes);
Cvar_RegisterVariable(&r_mipskins);
Cvar_RegisterVariable(&r_mipnormalmaps);
Cvar_RegisterVariable(&mod_generatelightmaps_unitspersample);
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)
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;
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)
}
extern cvar_t mod_q3shader_default_offsetmapping;
+extern cvar_t mod_q3shader_default_polygonoffset;
+extern cvar_t mod_q3shader_default_polygonfactor;
void Mod_LoadQ3Shaders(void)
{
int j;
shader.offsetscale = 1;
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, "{"))
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;
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]);
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)
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->specularscalemod = shader->specularscalemod;
}
// 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;
}
}
- // 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;