cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
+cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
+
cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
Cvar_RegisterVariable(&r_bloom_blur);
Cvar_RegisterVariable(&r_bloom_resolution);
Cvar_RegisterVariable(&r_bloom_power);
+ Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
Cvar_RegisterVariable(&developer_texturelogging);
Cvar_RegisterVariable(&gl_lightmaps);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
rsurface_svector3f = varray_svector3f;
rsurface_tvector3f = varray_tvector3f;
rsurface_normal3f = varray_normal3f;
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
+ Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
// a single autosprite surface can contain multiple sprites...
VectorClear(forward);
rsurface_svector3f = varray_svector3f;
rsurface_tvector3f = varray_tvector3f;
rsurface_normal3f = varray_normal3f;
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
+ Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
if (rsurface_normal3f == NULL)
{
rsurface_normal3f = varray_normal3f;
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f);
+ Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
r = 1;
rsurface_svector3f = varray_svector3f;
rsurface_tvector3f = varray_tvector3f;
rsurface_normal3f = varray_normal3f;
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
+ Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
}
if (ent->colormap >= 0)
{
mesh->data_tvector3f = mesh->data_vertex3f + mesh->num_vertices * 6;
mesh->data_normal3f = mesh->data_vertex3f + mesh->num_vertices * 9;
Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_vertex3f);
- Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f);
+ Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f, true);
}
static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
}
// compile additional data about the surface geometry
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, surface->groupmesh->data_vertex3f, surface->groupmesh->data_texcoordtexture2f, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f);
+ Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, surface->groupmesh->data_vertex3f, surface->groupmesh->data_texcoordtexture2f, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, true);
BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex));
// generate surface extents information
Con_Print("\n");
}
// for per pixel lighting
- Mod_BuildTextureVectorsAndNormals(out->num_firstvertex, out->num_vertices, out->num_triangles, out->groupmesh->data_vertex3f, out->groupmesh->data_texcoordtexture2f, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_svector3f, out->groupmesh->data_tvector3f, out->groupmesh->data_normal3f);
+ Mod_BuildTextureVectorsAndNormals(out->num_firstvertex, out->num_vertices, out->num_triangles, out->groupmesh->data_vertex3f, out->groupmesh->data_texcoordtexture2f, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_svector3f, out->groupmesh->data_tvector3f, out->groupmesh->data_normal3f, true);
// calculate a bounding box
VectorClear(out->mins);
VectorClear(out->maxs);
}
// warning: this is an expensive function!
-void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f)
+void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting)
{
- int i;
+ int i, j;
const int *element;
float *vectorNormal;
+ float areaNormal[3];
// clear the vectors
memset(normal3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
// process each vertex of each triangle and accumulate the results
// use area-averaging, to make triangles with a big area have a bigger
// weighting on the vertex normal than triangles with a small area
// to do so, just add the 'normals' together (the bigger the area
- // the greater the length of the normal is
+ // the greater the length of the normal is
element = elements;
- for (i = 0; i < numtriangles; i++)
+ for (i = 0; i < numtriangles; i++, element += 3)
{
- float areaNormal[3];
-
TriangleNormal(
- vertex3f + element[0] * 3,
- vertex3f + element[1] * 3,
- vertex3f + element[2] * 3,
+ vertex3f + element[0] * 3,
+ vertex3f + element[1] * 3,
+ vertex3f + element[2] * 3,
areaNormal
);
-
- vectorNormal = normal3f + element[0] * 3;
- vectorNormal[0] += areaNormal[0];
- vectorNormal[1] += areaNormal[1];
- vectorNormal[2] += areaNormal[2];
-
- vectorNormal = normal3f + element[1] * 3;
- vectorNormal[0] += areaNormal[0];
- vectorNormal[1] += areaNormal[1];
- vectorNormal[2] += areaNormal[2];
-
- vectorNormal = normal3f + element[2] * 3;
- vectorNormal[0] += areaNormal[0];
- vectorNormal[1] += areaNormal[1];
- vectorNormal[2] += areaNormal[2];
-
- element += 3;
+
+ if (!areaweighting)
+ VectorNormalize(areaNormal);
+
+ for (j = 0;j < 3;j++)
+ {
+ vectorNormal = normal3f + element[j] * 3;
+ vectorNormal[0] += areaNormal[0];
+ vectorNormal[1] += areaNormal[1];
+ vectorNormal[2] += areaNormal[2];
+ }
}
// and just normalize the accumulated vertex normal in the end
vectorNormal = normal3f + 3 * firstvertex;
- for (i = 0; i < numvertices; i++) {
+ for (i = 0; i < numvertices; i++, vectorNormal += 3)
VectorNormalize(vectorNormal);
- vectorNormal += 3;
- }
}
void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
{
float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
- // 103 add/sub/negate/multiply (1 cycle), 3 divide (20 cycle), 3 sqrt (22 cycle), 4 compare (3 cycle?), total cycles not counting load/store/exchange roughly 241 cycles
- // 12 add, 28 subtract, 57 multiply, 3 divide, 3 sqrt, 4 compare, 50% chance of 6 negates
+ // 79 add/sub/negate/multiply (1 cycle), 1 compare (3 cycle?), total cycles not counting load/store/exchange roughly 82 cycles
+ // 6 add, 28 subtract, 39 multiply, 1 compare, 50% chance of 6 negates
// 6 multiply, 9 subtract
VectorSubtract(v1, v0, v10);
normal3f[0] = v10[1] * v20[2] - v10[2] * v20[1];
normal3f[1] = v10[2] * v20[0] - v10[0] * v20[2];
normal3f[2] = v10[0] * v20[1] - v10[1] * v20[0];
- // 1 sqrt, 1 divide, 6 multiply, 2 add, 1 compare
- VectorNormalize(normal3f);
// 12 multiply, 10 subtract
tc10[1] = tc1[1] - tc0[1];
tc20[1] = tc2[1] - tc0[1];
tvector3f[0] -= f * normal3f[0];
tvector3f[1] -= f * normal3f[1];
tvector3f[2] -= f * normal3f[2];
- // 2 sqrt, 2 divide, 12 multiply, 4 add, 2 compare
- VectorNormalize(svector3f);
- VectorNormalize(tvector3f);
// if texture is mapped the wrong way (counterclockwise), the tangents
// have to be flipped, this is detected by calculating a normal from the
// two tangents, and seeing if it is opposite the surface normal
}
// warning: this is a very expensive function!
-void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f)
+void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f, qboolean areaweighting)
{
int i, tnum;
float sdir[3], tdir[3], normal[3], *v;
for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
{
Mod_BuildBumpVectors(vertex3f + e[0] * 3, vertex3f + e[1] * 3, vertex3f + e[2] * 3, texcoord2f + e[0] * 2, texcoord2f + e[1] * 2, texcoord2f + e[2] * 2, sdir, tdir, normal);
- if (svector3f)
+ if (!areaweighting)
{
- for (i = 0;i < 3;i++)
- {
- svector3f[e[i]*3 ] += sdir[0];
- svector3f[e[i]*3+1] += sdir[1];
- svector3f[e[i]*3+2] += sdir[2];
- }
+ VectorNormalize(sdir);
+ VectorNormalize(tdir);
+ VectorNormalize(normal);
}
+ if (svector3f)
+ for (i = 0;i < 3;i++)
+ VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
if (tvector3f)
- {
for (i = 0;i < 3;i++)
- {
- tvector3f[e[i]*3 ] += tdir[0];
- tvector3f[e[i]*3+1] += tdir[1];
- tvector3f[e[i]*3+2] += tdir[2];
- }
- }
+ VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
if (normal3f)
- {
for (i = 0;i < 3;i++)
- {
- normal3f[e[i]*3 ] += normal[0];
- normal3f[e[i]*3+1] += normal[1];
- normal3f[e[i]*3+2] += normal[2];
- }
- }
+ VectorAdd(normal3f + e[i]*3, normal, normal3f + e[i]*3);
}
// now we could divide the vectors by the number of averaged values on
// each vertex... but instead normalize them
int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices);
void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles);
void Mod_ValidateElements(const int *elements, int numtriangles, int numverts, const char *filename, int fileline);
-void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f);
-void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals);
+void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting);
+void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals, qboolean areaweighting);
surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean detailtexcoords, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors);
extern cvar_t gl_polyblend;
extern cvar_t gl_dither;
+extern cvar_t r_smoothnormals_areaweighting;
+
#include "gl_backend.h"
#include "r_light.h"