memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
}
-void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, double zNear, double zFar)
+void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar)
{
double xmax, ymax;
GL_SetupView_Orientation_Identity();
}
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear)
+{
+ double nudge, m[16];
+
+ if (!r_render.integer)
+ return;
+
+ // set up viewpoint
+ qglMatrixMode(GL_PROJECTION);CHECKGLERROR
+ qglLoadIdentity ();CHECKGLERROR
+ // set view pyramid
+ nudge = 1.0 - 1.0 / (1<<23);
+ m[ 0] = 1.0 / tan(fovx * M_PI / 360.0);
+ m[ 1] = 0;
+ m[ 2] = 0;
+ m[ 3] = 0;
+ m[ 4] = 0;
+ m[ 5] = 1.0 / tan(fovy * M_PI / 360.0);
+ m[ 6] = 0;
+ m[ 7] = 0;
+ m[ 8] = 0;
+ m[ 9] = 0;
+ m[10] = -1 * nudge;
+ m[11] = -1 * nudge;
+ m[12] = 0;
+ m[13] = 0;
+ m[14] = -2 * zNear * nudge;
+ m[15] = 0;
+ qglLoadMatrixd(m);
+ qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+ GL_SetupView_Orientation_Identity();
+}
+
void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
{
if (!r_render.integer)
unsigned int t1d, t2d, t3d, tcubemap;
unsigned int arrayenabled;
float rgbscale;
+ int combinergb, combinealpha;
// FIXME: add more combine stuff
}
gltextureunit_t;
unit->t3d = 0;
unit->tcubemap = 0;
unit->rgbscale = 1;
+ unit->combinergb = GL_MODULATE;
+ unit->combinealpha = GL_MODULATE;
unit->arrayenabled = false;
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
if (gl_texture3d)
}
}
-void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, int *index)
+void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, const int *index)
{
int arraylocked = false;
c_meshs++;
arraylocked = true;
}
if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
- qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, (GLuint *) index);
+ qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, (const GLuint *) index);
else
- qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, (GLuint *) index);
+ qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, (const GLuint *) index);
CHECKGLERROR
if (arraylocked)
{
}
// renders the mesh
-void R_Mesh_Draw(int numverts, int numtriangles, int *elements)
+void R_Mesh_Draw(int numverts, int numtriangles, const int *elements)
{
BACKENDACTIVECHECK
void R_Mesh_TextureState(const rmeshstate_t *m)
{
- int i;
+ int i, combinergb, combinealpha;
float rgbscale;
gltextureunit_t *unit;
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
}
}
+ combinergb = m->texcombinergb[i];
+ combinealpha = m->texcombinealpha[i];
+ if (!combinergb)
+ combinergb = GL_MODULATE;
+ if (!combinealpha)
+ combinealpha = GL_MODULATE;
+ if (unit->combinergb != combinergb)
+ {
+ unit->combinergb = combinergb;
+ if (gl_combine.integer)
+ {
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
+ }
+ else
+ {
+ qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
+ }
+ }
+ if (unit->combinealpha != combinealpha)
+ {
+ unit->combinealpha = combinealpha;
+ if (gl_combine.integer)
+ {
+ qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
+ }
+ }
if (unit->t1d != m->tex1d[i])
{
if (m->tex1d[i])
#define POLYGONELEMENTS_MAXPOINTS 258
extern int polygonelements[768];
-void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, int *index);
+void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, const int *index);
void GL_SetupView_ViewPort (int x, int y, int width, int height);
void GL_SetupView_Orientation_Identity (void);
void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles);
-void GL_SetupView_Mode_Perspective (double aspect, double fovx, double fovy, double zNear, double zFar);
+void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar);
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear);
void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar);
void GL_UseColorArray(void);
void GL_Color(float cr, float cg, float cb, float ca);
int tex3d[MAX_TEXTUREUNITS];
int texcubemap[MAX_TEXTUREUNITS];
int texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present
+ int texcombinergb[MAX_TEXTUREUNITS]; // works with or without combine for some operations
+ int texcombinealpha[MAX_TEXTUREUNITS]; // does nothing without combine
}
rmeshstate_t;
void _R_Mesh_ResizeCheck(int numverts);
// renders the mesh in the varray_* buffers
-void R_Mesh_Draw(int numverts, int numtriangles, int *elements);
+void R_Mesh_Draw(int numverts, int numtriangles, const int *elements);
// saves a section of the rendered frame to a .tga file
qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height);
// LordHavoc: vertex arrays
-float *aliasvertbuf;
float *aliasvertcolorbuf;
-float *aliasvert; // this may point at aliasvertbuf or at vertex arrays in the mesh backend
float *aliasvertcolor; // this may point at aliasvertcolorbuf or at vertex arrays in the mesh backend
+float *aliasvert_svectors;
+float *aliasvert_tvectors;
+float *aliasvert_normals;
float *aliasvertcolor2;
-float *aliasvertnorm;
int *aliasvertusage;
zymbonematrix *zymbonepose;
{
// allocate vertex processing arrays
gl_models_mempool = Mem_AllocPool("GL_Models");
- aliasvert = aliasvertbuf = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
aliasvertcolor = aliasvertcolorbuf = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
- aliasvertnorm = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3]));
+ aliasvert_svectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
+ aliasvert_tvectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
+ aliasvert_normals = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
aliasvertcolor2 = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
aliasvertusage = Mem_Alloc(gl_models_mempool, sizeof(int[MD2MAX_VERTS]));
avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4;
avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4;
av += 4;
- avn += 3;
+ avn += 4;
verts1++;verts2++;verts3++;verts4++;
}
}
avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3;
avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3;
av += 4;
- avn += 3;
+ avn += 4;
verts1++;verts2++;verts3++;
}
}
avn[1] = n1[1] * lerp1 + n2[1] * lerp2;
avn[2] = n1[2] * lerp1 + n2[2] * lerp2;
av += 4;
- avn += 3;
+ avn += 4;
verts1++;verts2++;
}
}
avn[1] = n1[1] * lerp1;
avn[2] = n1[2] * lerp1;
av += 4;
- avn += 3;
+ avn += 4;
verts1++;
}
}
av[2] = verts1->v[2] * scale1[2] + translate[2];
VectorCopy(m_bytenormals[verts1->lightnormalindex], avn);
av += 4;
- avn += 3;
+ avn += 4;
verts1++;
}
}
blendfunc2 = GL_ZERO;
}
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
memcpy(varray_texcoord[0], model->mdlmd2data_texcoords, model->numverts * sizeof(float[4]));
if (!skinframe->base && !skinframe->pants && !skinframe->shirt && !skinframe->glow)
{
varray_texcoord[0][i + 0] *= 8.0f;
varray_texcoord[0][i + 1] *= 8.0f;
}
- R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, colorscale, colorscale, colorscale, false);
+ R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale, colorscale, colorscale, false);
GL_UseColorArray();
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
return;
else
{
GL_UseColorArray();
- R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false);
+ R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false);
}
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
c_alias_polys += model->numtris;
else
{
GL_UseColorArray();
- R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false);
+ R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false);
}
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
c_alias_polys += model->numtris;
else
{
GL_UseColorArray();
- R_LightModel(ent, model->numverts, varray_vertex, aliasvertnorm, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false);
+ R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false);
}
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
c_alias_polys += model->numtris;
{
model = ent->model;
R_Mesh_ResizeCheck(model->numverts * 2);
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
Matrix4x4_Transform(&ent->inversematrix, sl->origin, temp);
GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true);
GL_UseColorArray();
lightscale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f);
VectorScale(sl->light, lightscale, lightcolor);
- R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
+ R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
}
}
{
model = ent->model;
R_Mesh_ResizeCheck(model->numverts * 2);
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp);
GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
R_Shadow_Volume(model->numverts, model->numtris, varray_vertex, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
GL_UseColorArray();
- R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
+ R_Shadow_VertexLight(model->numverts, varray_vertex, aliasvert_normals, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
}
}
R_Mesh_State(&m);
c_alias_polys += model->numtris;
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
// put a light direction in the entity's coordinate space
Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
}
-void R_Model_Alias_DrawDepth(entity_render_t *ent)
+void R_Model_Alias_DrawBaseLighting(entity_render_t *ent)
{
+ R_Mesh_Matrix(&ent->matrix);
+ GL_Color(0, 0, 0, 1);
R_Mesh_ResizeCheck(ent->model->numverts);
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
}
projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
if (projectdistance > 0.1)
{
+ R_Mesh_Matrix(&ent->matrix);
R_Mesh_ResizeCheck(ent->model->numverts * 2);
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
}
}
-void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
{
+ skinframe_t *skinframe;
+ R_Mesh_Matrix(&ent->matrix);
+ skinframe = R_FetchSkinFrame(ent);
R_Mesh_ResizeCheck(ent->model->numverts);
- R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
- R_Shadow_Light(ent->model->numverts, aliasvertnorm, relativelightorigin, lightradius, lightdistbias, lightsubtract, lightcolor);
- GL_UseColorArray();
- R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
-}
-
-void R_Model_Alias_DrawOntoLight(entity_render_t *ent)
-{
- // FIXME
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
+ Mod_BuildTextureVectorsAndNormals(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_texcoords, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals);
+ R_Shadow_RenderLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, skinframe->base, r_notexture, NULL, NULL);
}
int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
R_Mesh_State(&mstate);
ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
ZymoticTransformVerts(numverts, varray_vertex, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
- ZymoticCalcNormals(numverts, varray_vertex, aliasvertnorm, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
+ ZymoticCalcNormals(numverts, varray_vertex, aliasvert_normals, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
memcpy(varray_texcoord[0], ent->model->zymdata_texcoords, ent->model->zymnum_verts * sizeof(float[4]));
GL_UseColorArray();
- R_LightModel(ent, numverts, varray_vertex, aliasvertnorm, varray_color, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
+ R_LightModel(ent, numverts, varray_vertex, aliasvert_normals, varray_color, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
R_Mesh_Draw(numverts, numtriangles, elements);
c_alias_polys += numtriangles;
}
void R_DrawNoModel(entity_render_t *ent);
-void R_DrawModels (void)
+void R_DrawModels (int baselighting)
{
int i;
entity_render_t *ent;
{
if (ent->model)
{
- if (ent->model->Draw)
+ if (baselighting && ent->model->DrawBaseLighting != NULL)
+ {
+ if (ent->model->DrawBaseLighting)
+ ent->model->DrawBaseLighting(ent);
+ }
+ else if (ent->model->Draw)
ent->model->Draw(ent);
}
else
#endif
{
Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius, visiblevolume);
}
}
{
if (d_lightstylevalue[sl->style] <= 0)
continue;
+ if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer)
+ continue;
/*
mins[0] = sl->origin[0] - sl->cullradius;
maxs[0] = sl->origin[0] + sl->cullradius;
if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
{
Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true);
}
*/
if (ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
{
Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
ent->model->DrawShadowVolume (ent, relativelightorigin, sl->cullradius, true);
}
*/
if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
{
Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true);
}
*/
if (ent != rd->ent && ent->model && ent->model->DrawShadowVolume && ent->maxs[0] >= mins[0] && ent->mins[0] <= maxs[0] && ent->maxs[1] >= mins[1] && ent->mins[1] <= maxs[1] && ent->maxs[2] >= mins[2] && ent->mins[2] <= maxs[2])
{
Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
ent->model->DrawShadowVolume (ent, relativelightorigin, rd->cullradius, true);
}
*/
vec3_t angles, angles2, angles3, angles4;
float verts[12];
shadowsphere = Mod_ShadowMesh_Begin(zonemempool);
- for (i = 0;i < SHADOWSPHERE_SEGMENTS;i++)
+ for (i = 0;i < SHADOWSPHERE_SEGMENTS / 2;i++)
{
for (j = 0;j < SHADOWSPHERE_SEGMENTS;j++)
{
- angles[0] = i * 360.0f / SHADOWSPHERE_SEGMENTS;
+ angles[0] = (i * 360.0f / SHADOWSPHERE_SEGMENTS) + 90.0f;
angles[1] = j * 360.0f / SHADOWSPHERE_SEGMENTS;
angles[2] = 0;
VectorCopy(angles, angles2);
AngleVectorsFLU(angles2, verts + 9, NULL, NULL);
AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
AngleVectorsFLU(angles4, verts + 3, NULL, NULL);
- VectorScale(&verts[0], 64.0f, &verts[0]);
- VectorScale(&verts[3], 64.0f, &verts[3]);
- VectorScale(&verts[6], 64.0f, &verts[6]);
- VectorScale(&verts[9], 64.0f, &verts[9]);
+ VectorScale(&verts[0], 1.0f, &verts[0]);
+ VectorScale(&verts[3], 1.0f, &verts[3]);
+ VectorScale(&verts[6], 1.0f, &verts[6]);
+ VectorScale(&verts[9], 1.0f, &verts[9]);
Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+ /*
AngleVectorsFLU(angles, verts, NULL, NULL);
AngleVectorsFLU(angles2, verts + 3, NULL, NULL);
AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
AngleVectorsFLU(angles4, verts + 9, NULL, NULL);
- VectorScale(&verts[0], 128.0f, &verts[0]);
- VectorScale(&verts[3], 128.0f, &verts[3]);
- VectorScale(&verts[6], 128.0f, &verts[6]);
- VectorScale(&verts[9], 128.0f, &verts[9]);
+ VectorScale(&verts[0], -4.0f, &verts[0]);
+ VectorScale(&verts[3], -4.0f, &verts[3]);
+ VectorScale(&verts[6], -4.0f, &verts[6]);
+ VectorScale(&verts[9], -4.0f, &verts[9]);
Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+ */
}
}
shadowsphere = Mod_ShadowMesh_Finish(zonemempool, shadowsphere);
}
-void R_DrawShadowSphere(vec3_t origin, float radius, int visiblevolume)
+void R_DrawShadowSphere(vec3_t origin, float cullradius, float lightradius, int visiblevolume)
{
- int i;
- float *v;
shadowmesh_t *mesh;
- //matrix4x4_t matrix;
+ matrix4x4_t matrix;
if (!shadowsphere)
R_CreateShadowSphere();
- //Matrix4x4_CreateTranslate(&matrix, origin[0], origin[1], origin[2]);
- //Matrix4x4_ConcatScale(&matrix, radius);
- //R_Mesh_Matrix(&matrix);
- R_Mesh_Matrix(&r_identitymatrix);
+ Matrix4x4_CreateScale(&matrix, lightradius);
+ Matrix4x4_ConcatTranslate(&matrix, origin[0], origin[1], origin[2]);
+ R_Mesh_Matrix(&matrix);
+ for (mesh = shadowsphere;mesh;mesh = mesh->next)
+ {
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
+ }
+ Matrix4x4_CreateScale(&matrix, -cullradius);
+ Matrix4x4_ConcatTranslate(&matrix, origin[0], origin[1], origin[2]);
+ R_Mesh_Matrix(&matrix);
for (mesh = shadowsphere;mesh;mesh = mesh->next)
{
memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- for (i = 0, v = varray_vertex;i < mesh->numverts;i++, v += 4)
- VectorMA(origin, radius, v, v);
R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
}
}
entity_render_t *ent;
int lnum;
float f;
- vec3_t mins, maxs, relativelightorigin, lightcolor;
+ vec3_t mins, maxs, relativelightorigin, relativeeyeorigin, lightcolor;
mlight_t *sl;
rdlight_t *rd;
- R_Shadow_Stage_Depth();
- ent = &cl_entities[0].render;
- if (ent->model && ent->model->DrawDepth)
- {
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawDepth(ent);
- }
- if (r_drawentities.integer)
- {
- for (i = 0;i < r_refdef.numentities;i++)
- {
- ent = r_refdef.entities[i];
- if (ent->visframe == r_framecount && ent->model && ent->model->DrawDepth)
- {
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawDepth(ent);
- }
- }
- }
-
+ R_Shadow_Stage_Begin();
for (lnum = 0, sl = cl.worldmodel->lights;lnum < cl.worldmodel->numlights;lnum++, sl++)
{
if (d_lightstylevalue[sl->style] <= 0)
continue;
+ if (r_light_debuglight.integer >= 0 && lnum != r_light_debuglight.integer)
+ continue;
VectorCopy(sl->mins, mins);
VectorCopy(sl->maxs, maxs);
- /*
- mins[0] = sl->origin[0] - sl->cullradius;
- maxs[0] = sl->origin[0] + sl->cullradius;
- mins[1] = sl->origin[1] - sl->cullradius;
- maxs[1] = sl->origin[1] + sl->cullradius;
- mins[2] = sl->origin[2] - sl->cullradius;
- maxs[2] = sl->origin[2] + sl->cullradius;
- if (R_CullBox(mins, maxs))
- continue;
- */
if (R_CullBox(mins, maxs))
continue;
VectorScale(sl->light, f, lightcolor);
R_Shadow_Stage_ShadowVolumes();
- R_DrawShadowSphere(sl->origin, 1.0f/*sl->cullradius - 16*/, false);
+ R_DrawShadowSphere(sl->origin, sl->cullradius, sl->lightradius * 2, false);
if (sl->shadowvolume && r_staticworldlights.integer)
R_DrawWorldLightShadowVolume(sl, false);
else
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
+ /*
if (ent->maxs[0] >= mins[0]
&& ent->mins[0] <= maxs[0]
&& ent->maxs[1] >= mins[1]
&& ent->mins[1] <= maxs[1]
&& ent->maxs[2] >= mins[2]
&& ent->mins[2] <= maxs[2])
+ */
R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, sl->cullradius, false);
}
}
if (ent->model && ent->model->DrawLight)
{
Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor);
}
if (r_drawentities.integer)
{
{
ent = r_refdef.entities[i];
if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+ /*
&& ent->maxs[0] >= mins[0]
&& ent->mins[0] <= maxs[0]
&& ent->maxs[1] >= mins[1]
&& ent->mins[1] <= maxs[1]
&& ent->maxs[2] >= mins[2]
- && ent->mins[2] <= maxs[2])
+ && ent->mins[2] <= maxs[2]*/)
{
Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, sl->lightradius, sl->distbias, sl->subtract, lightcolor);
}
}
}
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
+ /*
if (ent->maxs[0] >= mins[0]
&& ent->mins[0] <= maxs[0]
&& ent->maxs[1] >= mins[1]
&& ent->mins[1] <= maxs[1]
&& ent->maxs[2] >= mins[2]
&& ent->mins[2] <= maxs[2])
- R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false);
+ */
+ R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false);
}
}
if (ent->model && ent->model->DrawLight)
{
Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
}
if (r_drawentities.integer)
{
{
ent = r_refdef.entities[i];
if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+ /*
&& ent->maxs[0] >= mins[0]
&& ent->mins[0] <= maxs[0]
&& ent->maxs[1] >= mins[1]
&& ent->mins[1] <= maxs[1]
&& ent->maxs[2] >= mins[2]
- && ent->mins[2] <= maxs[2])
+ && ent->mins[2] <= maxs[2]*/)
{
Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
}
}
}
}
- R_Shadow_Stage_Textures();
- ent = &cl_entities[0].render;
- if (ent->model && ent->model->DrawOntoLight)
- {
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawOntoLight(ent);
- }
- if (r_drawentities.integer)
- {
- for (i = 0;i < r_refdef.numentities;i++)
- {
- ent = r_refdef.entities[i];
- if (ent->visframe == r_framecount && ent->model && ent->model->DrawOntoLight)
- {
- R_Mesh_Matrix(&ent->matrix);
- ent->model->DrawOntoLight(ent);
- }
- }
- }
-
R_Shadow_Stage_End();
}
R_TimeReport("markentity");
GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
- GL_SetupView_Mode_Perspective((double) r_refdef.height / r_refdef.width, r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
+ //GL_SetupView_Mode_Perspective(r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
+ GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.fov_x, r_refdef.fov_y, 1.0f);
GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
qglDepthFunc(GL_LEQUAL);
if (r_shadows.integer == 3)
{
- if (!gl_stencil)
+ if (!gl_texturecubemap)
{
- Con_Printf("Stencil not enabled, turning off r_shadows 3\n");
+ Con_Printf("Cubemap texture support not detected, turning off r_shadows 3\n");
Cvar_SetValueQuick(&r_shadows, 0);
}
- else if (!gl_texture3d)
+ else if (!gl_dot3arb)
{
- Con_Printf("3D texture support not detected, turning off r_shadows 3\n");
+ Con_Printf("Bumpmapping support not detected, turning off r_shadows 3\n");
Cvar_SetValueQuick(&r_shadows, 0);
}
- else if (!gl_texturecubemap)
+ else if (!gl_stencil)
{
- Con_Printf("Cubemap texture support not detected, turning off r_shadows 3\n");
+ Con_Printf("Stencil not enabled, turning off r_shadows 3, please type vid_stencil 1;vid_restart and try again\n");
Cvar_SetValueQuick(&r_shadows, 0);
}
- else if (!gl_dot3arb)
+ else if (!gl_combine.integer)
{
- Con_Printf("Bumpmapping support not detected, turning off r_shadows 3\n");
+ Con_Printf("Combine disabled, please turn on gl_combine, turning off r_shadows 3\n");
Cvar_SetValueQuick(&r_shadows, 0);
}
}
R_TimeReport("bmodelsky");
// must occur early because it can draw sky
- R_DrawWorld(world);
+ R_DrawWorld(world, r_shadows.integer == 3);
R_TimeReport("world");
// don't let sound skip if going slow
if (!intimerefresh && !r_speeds.integer)
S_ExtraUpdate ();
- R_DrawModels();
+ R_DrawModels(r_shadows.integer == 3);
R_TimeReport("models");
+ if (r_shadows.integer == 1)
+ {
+ R_DrawFakeShadows();
+ R_TimeReport("fakeshadows");
+ }
+
if (r_shadows.integer == 3)
R_ShadowVolumeLighting();
R_MeshQueue_Render();
R_MeshQueue_EndScene();
- if (r_shadows.integer == 1)
- {
- R_DrawFakeShadows();
- R_TimeReport("fakeshadows");
- }
if (r_shadows.integer == 2)
{
R_DrawShadowVolumes();
static int dlightdivtable[32768];
-// variables used by R_PVSUpdate
-int r_pvsframecount = 0;
-mleaf_t *r_pvsviewleaf = NULL;
-int r_pvsviewleafnovis = 0;
-
static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
{
int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract, k;
return false;
}
-static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
}
m.depthwrite = true;
R_Mesh_State(&m);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1);
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, 1);
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
qglColorMask(1,1,1,1);
}
}
-static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
vec3_t center;
if ((r_wateralpha.value < 1 && !(texture->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || texture->fogtexture)
{
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
- R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+ if (surf->visframe == r_framecount)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+ }
}
}
else
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
}
static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf)
}
}
-static void RSurfShader_Wall_Pass_BaseFullbright(const entity_render_t *ent, const msurface_t *surf)
-{
- const surfmesh_t *mesh;
- rmeshstate_t m;
- float modelorg[3];
- Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
- memset(&m, 0, sizeof(m));
- if (ent->effects & EF_ADDITIVE)
- {
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE;
- }
- else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
- {
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- }
- else
- {
- m.blendfunc1 = GL_ONE;
- m.blendfunc2 = GL_ZERO;
- }
- m.tex[0] = R_GetTexture(surf->currenttexture->texture);
- R_Mesh_State(&m);
- GL_UseColorArray();
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
- {
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- RSurf_FoggedColors(varray_vertex, varray_color, 1, 1, 1, ent->alpha, r_colorscale, mesh->numverts, modelorg);
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
- }
-}
-
static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf)
{
const surfmesh_t *mesh;
}
}
-static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.blendfunc1 = GL_ONE;
m.blendfunc2 = GL_ZERO;
m.tex[0] = R_GetTexture(texture->texture);
- m.tex[1] = R_GetTexture(texture->surfacechain->lightmaptexture);
+ m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
m.tex[2] = R_GetTexture(texture->detailtexture);
m.texrgbscale[0] = 1;
m.texrgbscale[1] = 4;
R_Mesh_State(&m);
cl = (float) (1 << r_lightmapscalebit) * r_colorscale;
GL_Color(cl, cl, cl, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
- if (m.tex[1] != lightmaptexturenum)
+ if (surf->visframe == r_framecount)
{
- m.tex[1] = lightmaptexturenum;
- R_Mesh_State(&m);
- }
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
- {
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[2], mesh->abc, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+ if (m.tex[1] != lightmaptexturenum)
+ {
+ m.tex[1] = lightmaptexturenum;
+ R_Mesh_State(&m);
+ }
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[2], mesh->abc, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.blendfunc1 = GL_ONE;
m.blendfunc2 = GL_ZERO;
m.tex[0] = R_GetTexture(texture->texture);
- m.tex[1] = R_GetTexture(texture->surfacechain->lightmaptexture);
+ m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
if (gl_combine.integer)
m.texrgbscale[1] = 4;
R_Mesh_State(&m);
GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
- if (m.tex[1] != lightmaptexturenum)
+ if (surf->visframe == r_framecount)
{
- m.tex[1] = lightmaptexturenum;
- R_Mesh_State(&m);
- }
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
- {
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+ if (m.tex[1] != lightmaptexturenum)
+ {
+ m.tex[1] = lightmaptexturenum;
+ R_Mesh_State(&m);
+ }
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[1], mesh->uvw, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.tex[0] = R_GetTexture(texture->texture);
R_Mesh_State(&m);
GL_Color(1, 1, 1, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
memset(&m, 0, sizeof(m));
m.blendfunc1 = GL_ZERO;
m.blendfunc2 = GL_SRC_COLOR;
- m.tex[0] = R_GetTexture(texture->surfacechain->lightmaptexture);
+ m.tex[0] = R_GetTexture(firstsurf->lightmaptexture);
if (gl_combine.integer)
m.texrgbscale[0] = 4;
R_Mesh_State(&m);
GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
- if (m.tex[0] != lightmaptexturenum)
- {
- m.tex[0] = lightmaptexturenum;
- R_Mesh_State(&m);
- }
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->uvw, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ lightmaptexturenum = R_GetTexture(surf->lightmaptexture);
+ if (m.tex[0] != lightmaptexturenum)
+ {
+ m.tex[0] = lightmaptexturenum;
+ R_Mesh_State(&m);
+ }
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->uvw, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
}
R_Mesh_State(&m);
GL_UseColorArray();
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- if (surf->dlightframe == r_framecount)
+ if (surf->visframe == r_framecount && surf->dlightframe == r_framecount)
{
for (mesh = surf->mesh;mesh;mesh = mesh->chain)
{
}
}
-static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
R_Mesh_State(&m);
GL_UseColorArray();
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- if (m.tex[0])
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg);
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ if (m.tex[0])
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ RSurf_FogPassColors(varray_vertex, varray_color, fogcolor[0], fogcolor[1], fogcolor[2], 1, r_colorscale, mesh->numverts, modelorg);
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.tex[0] = R_GetTexture(texture->detailtexture);
R_Mesh_State(&m);
GL_Color(1, 1, 1, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->abc, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->abc, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
const surfmesh_t *mesh;
m.tex[0] = R_GetTexture(texture->glowtexture);
R_Mesh_State(&m);
GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ if (surf->visframe == r_framecount)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
}
-static void RSurfShader_Wall_Fullbright_Callback(const void *calldata1, int calldata2)
-{
- const entity_render_t *ent = calldata1;
- const msurface_t *surf = ent->model->surfaces + calldata2;
- R_Mesh_Matrix(&ent->matrix);
- RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
- if (surf->currenttexture->glowtexture)
- RSurfShader_Wall_Pass_Glow(ent, surf);
- if (fogenabled)
- RSurfShader_Wall_Pass_Fog(ent, surf);
-}
-
-static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
- vec3_t center;
- if (ent->effects & EF_ADDITIVE || ent->alpha < 1 || texture->fogtexture != NULL)
+ const surfmesh_t *mesh;
+ rmeshstate_t m;
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ZERO;
+ m.tex[0] = R_GetTexture(texture->glowtexture);
+ R_Mesh_State(&m);
+ if (m.tex[0])
+ GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
+ else
+ GL_Color(0, 0, 0, 1);
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
{
- Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
- R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[0], mesh->str, mesh->numverts * sizeof(float[4]));
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ }
}
}
- else
- {
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
- if (texture->glowtexture)
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_Glow(ent, surf);
- if (fogenabled)
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_Fog(ent, surf);
- }
}
static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2)
RSurfShader_Wall_Pass_Fog(ent, surf);
}
-static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture)
+static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
{
const msurface_t *surf;
vec3_t center;
- if (ent->effects & EF_ADDITIVE || ent->alpha < 1 || texture->fogtexture != NULL)
+ if (texture->rendertype != SURFRENDER_OPAQUE)
{
// transparent vertex shaded from lightmap
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
{
- Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
- R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ if (surf->visframe == r_framecount)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
}
}
else if (r_vertexsurfaces.integer)
{
// opaque vertex shaded from lightmap
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Wall_Pass_BaseVertex(ent, surf);
if (texture->glowtexture)
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_Glow(ent, surf);
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
if (fogenabled)
- for (surf = texture->surfacechain;surf;surf = surf->texturechain)
- RSurfShader_Wall_Pass_Fog(ent, surf);
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
}
else
{
if (r_textureunits.integer >= 2)
{
if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
- RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture);
+ RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
else
{
- RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture);
+ RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
if (r_detailtextures.integer)
- RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture);
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
}
}
else
{
- RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture);
- RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture);
+ RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
+ RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
if (r_detailtextures.integer)
- RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture);
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
}
if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
- RSurfShader_OpaqueWall_Pass_Light(ent, texture);
+ RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
if (texture->glowtexture)
- RSurfShader_OpaqueWall_Pass_Glow(ent, texture);
+ RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
if (fogenabled)
- RSurfShader_OpaqueWall_Pass_Fog(ent, texture);
+ RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
}
}
-Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, SHADERFLAGS_NEEDLIGHTMAP};
-Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, 0};
-Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, 0};
-Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, 0};
+static void RSurfShader_Wall_Lightmap_BaseLighting(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+{
+ const msurface_t *surf;
+ if (cl.worldmodel->numlights)
+ RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
+ else if (r_vertexsurfaces.integer)
+ {
+ // opaque vertex shaded from lightmap
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ if (texture->glowtexture)
+ for (surf = firstsurf;surf;surf = surf->texturechain)
+ if (surf->visframe == r_framecount)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
+ }
+ else
+ {
+ // opaque lightmapped
+ if (r_textureunits.integer >= 2)
+ {
+ if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
+ RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
+ else
+ {
+ RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
+ if (r_detailtextures.integer)
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+ }
+ }
+ else
+ {
+ RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
+ RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
+ if (r_detailtextures.integer)
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+ }
+ if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
+ RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
+ if (texture->glowtexture)
+ RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
+ }
+}
-int Cshader_count = 4;
-Cshader_t *Cshaders[4] =
+Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Lightmap_BaseLighting}, SHADERFLAGS_NEEDLIGHTMAP};
+Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, 0};
+Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, 0};
+
+int Cshader_count = 3;
+Cshader_t *Cshaders[3] =
{
&Cshader_wall_lightmap,
- &Cshader_wall_fullbright,
&Cshader_water,
&Cshader_sky
};
-void R_DrawSurfaces(entity_render_t *ent, int sky, int normal)
+void R_PrepareSurfaces(entity_render_t *ent)
{
- int i, alttextures, texframe, framecount, numtextures, numsurfaces, *surfacevisframes;
- texture_t *t, *textures;
+ int i, texframe, numsurfaces, *surfacevisframes;
model_t *model;
msurface_t *surf, *surfaces;
+ texture_t *t;
vec3_t modelorg;
if (!ent->model)
return;
- // mark the surfaces touched by dynamic lights
- if (normal && r_dynamic.integer)
- R_MarkLights(ent);
-
- R_Mesh_Matrix(&ent->matrix);
-
model = ent->model;
- alttextures = ent->frame != 0;
- texframe = (int)(cl.time * 5.0f);
-
Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
-
- numtextures = model->numtextures;
- textures = model->textures;
numsurfaces = model->nummodelsurfaces;
surfaces = model->surfaces + model->firstmodelsurface;
surfacevisframes = model->surfacevisframes + model->firstmodelsurface;
- for (i = 0;i < numtextures;i++)
- textures[i].surfacechain = NULL;
+ texframe = (int)(cl.time * 5.0f);
+ for (i = 0;i < model->numtextures;i++)
+ {
+ t = model->textures + i;
+ if (ent->effects & EF_ADDITIVE)
+ t->rendertype = SURFRENDER_ADD;
+ else if (ent->alpha < 1 || t->flags & SURF_WATERALPHA || t->fogtexture != NULL)
+ t->rendertype = SURFRENDER_ALPHA;
+ else
+ t->rendertype = SURFRENDER_OPAQUE;
+ if (t->animated)
+ {
+ t->currentframe[0] = t->anim_frames[0][(t->anim_total[0] >= 2) ? (texframe % t->anim_total[0]) : 0];
+ t->currentframe[1] = t->anim_frames[1][(t->anim_total[1] >= 2) ? (texframe % t->anim_total[1]) : 0];
+ }
+ }
+
+ if (r_dynamic.integer)
+ R_MarkLights(ent);
for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
{
#endif
{
c_faces++;
- t = surf->texinfo->texture;
- if (t->animated)
- {
- framecount = t->anim_total[alttextures];
- if (framecount >= 2)
- t = t->anim_frames[alttextures][texframe % framecount];
- else
- t = t->anim_frames[alttextures][0];
- }
- surf->currenttexture = t;
- surf->texturechain = t->surfacechain;
- t->surfacechain = surf;
+ surf->visframe = r_framecount;
if (!r_vertexsurfaces.integer && surf->lightmaptexture != NULL)
{
if (surf->cached_dlight
- || surf->cached_ambient != r_ambient.value
- || surf->cached_lightmapscalebit != r_lightmapscalebit)
+ || surf->cached_ambient != r_ambient.value
+ || surf->cached_lightmapscalebit != r_lightmapscalebit)
R_BuildLightMap(ent, surf, false); // base lighting changed
else if (r_dynamic.integer)
{
if (surf->styles[0] != 255 && (d_lightstylevalue[surf->styles[0]] != surf->cached_light[0]
- || (surf->styles[1] != 255 && (d_lightstylevalue[surf->styles[1]] != surf->cached_light[1]
- || (surf->styles[2] != 255 && (d_lightstylevalue[surf->styles[2]] != surf->cached_light[2]
- || (surf->styles[3] != 255 && (d_lightstylevalue[surf->styles[3]] != surf->cached_light[3]))))))))
+ || (surf->styles[1] != 255 && (d_lightstylevalue[surf->styles[1]] != surf->cached_light[1]
+ || (surf->styles[2] != 255 && (d_lightstylevalue[surf->styles[2]] != surf->cached_light[2]
+ || (surf->styles[3] != 255 && (d_lightstylevalue[surf->styles[3]] != surf->cached_light[3]))))))))
R_BuildLightMap(ent, surf, false); // base lighting changed
else if (surf->dlightframe == r_framecount && r_dlightmap.integer)
R_BuildLightMap(ent, surf, true); // only dlights
}
}
}
+}
- if (sky)
- for (i = 0, t = textures;i < numtextures;i++, t++)
- if (t->surfacechain && t->shader->shaderfunc[SHADERSTAGE_SKY])
- t->shader->shaderfunc[SHADERSTAGE_SKY](ent, t);
-
- if (normal)
- for (i = 0, t = textures;i < numtextures;i++, t++)
- if (t->surfacechain && t->shader->shaderfunc[SHADERSTAGE_NORMAL])
- t->shader->shaderfunc[SHADERSTAGE_NORMAL](ent, t);
+void R_DrawSurfaces(entity_render_t *ent, int type)
+{
+ int i;
+ texture_t *t;
+ R_Mesh_Matrix(&ent->matrix);
+ for (i = 0, t = ent->model->textures;i < ent->model->numtextures;i++, t++)
+ if (t->shader->shaderfunc[type] && ent->model->texturesurfacechains[i])
+ t->shader->shaderfunc[type](ent, t, ent->model->texturesurfacechains[i]);
}
static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
{
- if (portal->here->pvsframe == r_pvsframecount || portal->past->pvsframe == r_pvsframecount)
+ if (portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount)
{
if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
{
}
}
-void R_DrawBrushModel(entity_render_t *ent, int sky, int normal)
+void R_PrepareBrushModel(entity_render_t *ent)
{
int i, numsurfaces, *surfacevisframes, *surfacepvsframes;
msurface_t *surf;
if ((surf->flags & SURF_PLANEBACK))
{
surfacevisframes[i] = r_framecount;
- surfacepvsframes[i] = r_pvsframecount;
+ surfacepvsframes[i] = model->pvsframecount;
}
}
else
if (!(surf->flags & SURF_PLANEBACK))
{
surfacevisframes[i] = r_framecount;
- surfacepvsframes[i] = r_pvsframecount;
+ surfacepvsframes[i] = model->pvsframecount;
}
}
#else
surfacevisframes[i] = r_framecount;
- surfacepvsframes[i] = r_pvsframecount;
+ surfacepvsframes[i] = model->pvsframecount;
#endif
surf->dlightframe = -1;
}
- R_DrawSurfaces(ent, sky, normal);
+ R_PrepareSurfaces(ent);
}
void R_SurfaceWorldNode (entity_render_t *ent)
for (i = 0, surf = surfaces;i < numsurfaces;i++, surf++)
{
- if (surfacepvsframes[i] == r_pvsframecount)
+ if (surfacepvsframes[i] == model->pvsframecount)
{
#if WORLDNODECULLBACKFACES
if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
{
leaf->worldnodeframe = r_framecount;
// FIXME: R_NotCulledBox is absolute, should be done relative
- if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+ if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
{
p->visframe = r_framecount;
pstack[portalstack++] = p;
{
leaf->worldnodeframe = r_framecount;
// FIXME: R_NotCulledBox is absolute, should be done relative
- if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+ if (leaf->pvsframe == ent->model->pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
leafstack[leafstackpos++] = leaf;
}
}
R_DrawPortals(ent);
}
-void R_PVSUpdate (mleaf_t *viewleaf)
+void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
{
int i, j, l, c, bits, *surfacepvsframes, *mark;
mleaf_t *leaf;
qbyte *vis;
+ model_t *model;
- if (r_pvsviewleaf == viewleaf && r_pvsviewleafnovis == r_novis.integer)
- return;
-
- r_pvsframecount++;
- r_pvsviewleaf = viewleaf;
- r_pvsviewleafnovis = r_novis.integer;
-
- if (viewleaf)
+ model = ent->model;
+ if (model && (model->pvsviewleaf != viewleaf || model->pvsviewleafnovis != r_novis.integer))
{
- surfacepvsframes = cl.worldmodel->surfacepvsframes;
- vis = Mod_LeafPVS (viewleaf, cl.worldmodel);
- for (j = 0;j < cl.worldmodel->numleafs;j += 8)
+ model->pvsframecount++;
+ model->pvsviewleaf = viewleaf;
+ model->pvsviewleafnovis = r_novis.integer;
+ if (viewleaf)
{
- bits = *vis++;
- if (bits)
+ surfacepvsframes = model->surfacepvsframes;
+ vis = Mod_LeafPVS (viewleaf, model);
+ for (j = 0;j < model->numleafs;j += 8)
{
- l = cl.worldmodel->numleafs - j;
- if (l > 8)
- l = 8;
- for (i = 0;i < l;i++)
+ bits = *vis++;
+ if (bits)
{
- if (bits & (1 << i))
+ l = model->numleafs - j;
+ if (l > 8)
+ l = 8;
+ for (i = 0;i < l;i++)
{
- leaf = &cl.worldmodel->leafs[j + i + 1];
- leaf->pvsframe = r_pvsframecount;
- // mark surfaces bounding this leaf as visible
- for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
- surfacepvsframes[*mark++] = r_pvsframecount;
+ if (bits & (1 << i))
+ {
+ leaf = &model->leafs[j + i + 1];
+ leaf->pvsframe = model->pvsframecount;
+ // mark surfaces bounding this leaf as visible
+ for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+ surfacepvsframes[*mark++] = model->pvsframecount;
+ }
}
}
}
R_DrawWorld
=============
*/
-void R_DrawWorld (entity_render_t *ent)
+void R_DrawWorld (entity_render_t *ent, int baselighting)
{
+ vec3_t modelorg;
mleaf_t *viewleaf;
- viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
- R_PVSUpdate(viewleaf);
+
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+ viewleaf = Mod_PointInLeaf (modelorg, ent->model);
+ R_PVSUpdate(ent, viewleaf);
+
if (!viewleaf)
return;
+
if (r_surfaceworldnode.integer || viewleaf->contents == CONTENTS_SOLID)
R_SurfaceWorldNode (ent);
else
R_PortalWorldNode (ent, viewleaf);
- R_DrawSurfaces(ent, true, true);
+ R_PrepareSurfaces(ent);
+ R_DrawSurfaces(ent, SHADERSTAGE_SKY);
+ if (baselighting)
+ R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
+ else
+ R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
}
void R_Model_Brush_DrawSky (entity_render_t *ent)
{
- R_DrawBrushModel(ent, true, false);
+ if (ent != &cl_entities[0].render)
+ R_PrepareBrushModel(ent);
+ R_DrawSurfaces(ent, SHADERSTAGE_SKY);
}
void R_Model_Brush_Draw (entity_render_t *ent)
{
c_bmodels++;
- R_DrawBrushModel(ent, false, true);
+ if (ent != &cl_entities[0].render)
+ R_PrepareBrushModel(ent);
+ R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
}
-void R_Model_Brush_DrawDepth (entity_render_t *ent)
+void R_Model_Brush_DrawBaseLighting (entity_render_t *ent)
{
+ c_bmodels++;
+ if (ent != &cl_entities[0].render)
+ R_PrepareBrushModel(ent);
+ R_DrawSurfaces(ent, SHADERSTAGE_BASELIGHTING);
+ /*
shadowmesh_t *mesh;
if (!cl.worldmodel->numlights)
GL_Color(0.3, 0.3, 0.3, 1);
}
if (!cl.worldmodel->numlights)
GL_Color(0, 0, 0, 1);
+ */
}
void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
{
-#if 0
+#if 1
float projectdistance, temp[3];
shadowmesh_t *mesh;
VectorSubtract(relativelightorigin, ent->model->shadowmesh_center, temp);
projectdistance = lightradius + ent->model->shadowmesh_radius - sqrt(DotProduct(temp, temp));
if (projectdistance >= 0.1)
{
+ R_Mesh_Matrix(&ent->matrix);
for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next)
{
R_Mesh_ResizeCheck(mesh->numverts * 2);
msurface_t *surf;
float projectdistance, f, temp[3], lightradius2;
surfmesh_t *mesh;
+ R_Mesh_Matrix(&ent->matrix);
lightradius2 = lightradius * lightradius;
for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
{
- if (surf->flags & SURF_SHADOWCAST)
+ if (surf->rendertype == SURFRENDER_OPAQUE && surf->flags & SURF_SHADOWCAST)
{
f = PlaneDiff(relativelightorigin, surf->plane);
if (surf->flags & SURF_PLANEBACK)
#endif
}
-void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
{
- int i;
+ int tnum;
msurface_t *surf;
+ texture_t *t;
float f, lightradius2;
surfmesh_t *mesh;
- vec3_t modelorg;
- Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+ R_Mesh_Matrix(&ent->matrix);
+ if (ent != &cl_entities[0].render)
+ R_PrepareBrushModel(ent);
lightradius2 = lightradius * lightradius;
- GL_UseColorArray();
- for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
+ for (tnum = 0;tnum < ent->model->numtextures;tnum++)
{
- if (surf->flags & SURF_SHADOWLIGHT)
+ t = ent->model->textures + tnum;
+ if (ent->model->texturesurfacechains[tnum] && t->rendertype == SURFRENDER_OPAQUE && t->flags & SURF_SHADOWLIGHT)
{
- f = PlaneDiff(relativelightorigin, surf->plane);
- if (surf->flags & SURF_PLANEBACK)
- f = -f;
- if (f >= -0.1 && f < lightradius)
+ t = t->currentframe[ent->frame != 0];
+ for (surf = ent->model->texturesurfacechains[tnum];surf;surf = surf->texturechain)
{
- f = PlaneDiff(modelorg, surf->plane);
- if (surf->flags & SURF_PLANEBACK)
- f = -f;
- if (f > 0)
+ if (surf->visframe == r_framecount)
{
- for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ f = PlaneDiff(relativelightorigin, surf->plane);
+ if (surf->flags & SURF_PLANEBACK)
+ f = -f;
+ if (f >= -0.1 && f < lightradius)
{
- R_Mesh_ResizeCheck(mesh->numverts);
- memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
- R_Shadow_Light(mesh->numverts, mesh->normals, relativelightorigin, lightradius, lightdistbias, lightsubtract, lightcolor);
- R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->texture, r_notexture, NULL, NULL);
+ }
}
}
}
}
}
-void R_Model_Brush_DrawOntoLight(entity_render_t *ent)
-{
- // FIXME
- c_bmodels++;
-}
-
/*
extern cvar_t r_shadows;
void R_DrawBrushModelFakeShadow (entity_render_t *ent)
static void gl_surf_newmap(void)
{
- // reset pvs visibility variables so it will update on first frame
- r_pvsframecount = 1;
- r_pvsviewleaf = NULL;
- r_pvsviewleafnovis = false;
}
void GL_Surf_Init(void)
#define GLTEXTURETYPE_3D 2
#define GLTEXTURETYPE_CUBEMAP 3
+static int gltexturetypeenums[4] = {GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB};
+static int gltexturetypedimensions[4] = {1, 2, 3, 2};
static int cubemapside[6] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
}
}
+static void GL_SetupTextureParameters(int flags, int texturetype)
+{
+ int textureenum = gltexturetypeenums[texturetype];
+ int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP : GL_REPEAT;
+
+ CHECKGLERROR
+
+ qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);
+ if (gltexturetypedimensions[texturetype] >= 2)
+ qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);
+ if (gltexturetypedimensions[texturetype] >= 3)
+ qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);
+
+ if (flags & TEXF_MIPMAP)
+ qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+ else
+ qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
+ qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
+
+ CHECKGLERROR
+}
+
static void R_Upload(gltexture_t *glt, qbyte *data)
{
int i, mip, width, height, depth, internalformat;
qbyte *prevbuffer;
prevbuffer = data;
+ CHECKGLERROR
+
glt->texnum = glt->image->texnum;
- switch(glt->image->texturetype)
- {
- case GLTEXTURETYPE_1D:
- qglBindTexture(GL_TEXTURE_1D, glt->image->texnum);
- CHECKGLERROR
- break;
- case GLTEXTURETYPE_2D:
- qglBindTexture(GL_TEXTURE_2D, glt->image->texnum);
- CHECKGLERROR
- break;
- case GLTEXTURETYPE_3D:
- qglBindTexture(GL_TEXTURE_3D, glt->image->texnum);
- CHECKGLERROR
- break;
- case GLTEXTURETYPE_CUBEMAP:
- qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, glt->image->texnum);
- CHECKGLERROR
- break;
- }
+ qglBindTexture(gltexturetypeenums[glt->image->texturetype], glt->image->texnum);
+ CHECKGLERROR
glt->flags &= ~GLTEXF_UPLOAD;
gl_backend_rebindtextures = true;
case GLTEXTURETYPE_1D:
qglTexImage1D(GL_TEXTURE_1D, 0, glt->image->glinternalformat, glt->image->width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
break;
case GLTEXTURETYPE_2D:
qglTexImage2D(GL_TEXTURE_2D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
break;
case GLTEXTURETYPE_3D:
qglTexImage3D(GL_TEXTURE_3D, 0, glt->image->glinternalformat, glt->image->width, glt->image->height, glt->image->depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, resizebuffer);
CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
break;
default:
Host_Error("R_Upload: fragment texture of type other than 1D, 2D, or 3D\n");
break;
}
+ GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
}
if (prevbuffer == NULL)
qglTexImage1D(GL_TEXTURE_1D, mip++, internalformat, width, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
CHECKGLERROR
}
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
- else
- {
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
}
break;
case GLTEXTURETYPE_2D:
qglTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
CHECKGLERROR
}
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
- else
- {
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
}
break;
case GLTEXTURETYPE_3D:
qglTexImage3D(GL_TEXTURE_3D, mip++, internalformat, width, height, depth, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
CHECKGLERROR
}
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
- else
- {
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
}
break;
case GLTEXTURETYPE_CUBEMAP:
qglTexImage2D(cubemapside[i], mip++, internalformat, width, height, 0, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
CHECKGLERROR
}
- qglTexParameteri(cubemapside[i], GL_TEXTURE_MIN_FILTER, gl_filter_min);
- CHECKGLERROR
- qglTexParameteri(cubemapside[i], GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
- }
- else
- {
- qglTexParameteri(cubemapside[i], GL_TEXTURE_MIN_FILTER, gl_filter_mag);
- CHECKGLERROR
- qglTexParameteri(cubemapside[i], GL_TEXTURE_MAG_FILTER, gl_filter_mag);
- CHECKGLERROR
}
}
break;
}
+ GL_SetupTextureParameters(glt->image->flags, glt->image->texturetype);
}
static void R_FindImageForTexture(gltexture_t *glt)
continue;
if (image->texturetype != glt->texturetype)
continue;
+ if ((image->flags ^ glt->flags) & (TEXF_MIPMAP | TEXF_ALPHA | TEXF_CLAMP))
+ continue;
if (image->glformat != texinfo->glformat || image->glinternalformat != texinfo->glinternalformat)
continue;
- if (glt->width > image->width || glt->height > image->height)
+ if (glt->width > image->width || glt->height > image->height || glt->depth > image->depth)
continue;
// got a fragments texture, find a place in it if we can
// make sure the created image is big enough for the fragment
for (image->width = block_size;image->width < glt->width;image->width <<= 1);
image->height = 1;
- if (glt->texturetype != GLTEXTURETYPE_1D)
+ if (gltexturetypedimensions[glt->texturetype] >= 2)
for (image->height = block_size;image->height < glt->height;image->height <<= 1);
image->depth = 1;
- if (glt->texturetype == GLTEXTURETYPE_3D)
+ if (gltexturetypedimensions[glt->texturetype] >= 3)
for (image->depth = block_size;image->depth < glt->depth;image->depth <<= 1);
image->blockallocation = Mem_Alloc(texturemempool, image->width * sizeof(short));
memset(image->blockallocation, 0, image->width * sizeof(short));
image->texturetype = glt->texturetype;
image->glinternalformat = texinfo->glinternalformat;
image->glformat = texinfo->glformat;
- image->flags = (glt->flags & (TEXF_MIPMAP | TEXF_ALPHA)) | GLTEXF_UPLOAD;
+ image->flags = (glt->flags & (TEXF_MIPMAP | TEXF_ALPHA | TEXF_CLAMP)) | GLTEXF_UPLOAD;
image->bytesperpixel = texinfo->internalbytesperpixel;
image->sides = image->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
// get a texture number to use
extern int gl_dot3arb;
#ifndef GL_DOT3_RGB_ARB
-#define DOT3_RGB_ARB 0x86AE
-#define DOT3_RGBA_ARB 0x86AF
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
#endif
/*
#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-#define VectorNormalize(v) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
-#define VectorNormalize2(v,dest) {float ilength = 1.0f / (float) sqrt(DotProduct(v,v));dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;}
-#define VectorNormalizeDouble(v) {double ilength = 1.0 / (float) sqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorNormalize(v) {float ilength = (float) sqrt(DotProduct(v,v));if (ilength) ilength = 1.0f / ilength;v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
+#define VectorNormalize2(v,dest) {float ilength = (float) sqrt(DotProduct(v,v));if (ilength) ilength = 1.0f / ilength;dest[0] = v[0] * ilength;dest[1] = v[1] * ilength;dest[2] = v[2] * ilength;}
+#define VectorNormalizeDouble(v) {double ilength = sqrt(DotProduct(v,v));if (ilength) ilength = 1.0 / ilength;v[0] *= ilength;v[1] *= ilength;v[2] *= ilength;}
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
#define VectorLength(a) sqrt(DotProduct(a, a))
#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
extern void R_Model_Alias_Draw(entity_render_t *ent);
extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Alias_DrawDepth(entity_render_t *ent);
+extern void R_Model_Alias_DrawBaseLighting(entity_render_t *ent);
extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Alias_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
int i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins;
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Alias_Draw;
loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
- loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+ loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting;
loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
loadmodel->DrawLight = R_Model_Alias_DrawLight;
- loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
loadmodel->numskins = LittleLong(pinmodel->numskins);
BOUNDI(loadmodel->numskins,0,256);
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Alias_Draw;
loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
- loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+ loadmodel->DrawBaseLighting = R_Model_Alias_DrawBaseLighting;
loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
loadmodel->DrawLight = R_Model_Alias_DrawLight;
- loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES)
Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
}
-static void zymswapintblock(int *m, int size)
-{
- size /= 4;
- while(size--)
- {
- *m = BigLong(*m);
- m++;
- }
-}
-
extern void R_Model_Zymotic_DrawSky(entity_render_t *ent);
extern void R_Model_Zymotic_Draw(entity_render_t *ent);
extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Zymotic_DrawDepth(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawBaseLighting(entity_render_t *ent);
extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
void Mod_LoadZymoticModel(model_t *mod, void *buffer)
{
zymtype1header_t *pinmodel, *pheader;
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Zymotic_Draw;
loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
- loadmodel->DrawDepth = NULL;//R_Model_Zymotic_DrawDepth;
+ loadmodel->DrawBaseLighting = NULL;//R_Model_Zymotic_DrawBaseLighting;
loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
- loadmodel->DrawOntoLight = NULL;//R_Model_Zymotic_DrawOntoLight;
// byteswap header
pheader = pinmodel;
|| !strncmp(tx->name,"*teleport",9)
|| !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
tx->flags |= SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA;
+ else
+ tx->flags |= SURF_WATERALPHA;
tx->shader = &Cshader_water;
}
else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y')
}
tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
+ // start out with no animation
+ tx->currentframe[0] = tx;
+ tx->currentframe[1] = tx;
}
// sequence the animations
memcpy(poly->verts, verts, numverts * sizeof(float[3]));
}
+void Mod_ShadowBrush_AddPolygonI(mempool_t *mempool, svbrush_t *brush, int numverts, float *verts)
+{
+ int i;
+ float normal[3], dist, dir0[3], dir1[3], *v0, *v1, *v2;
+ svpolygon_t *poly;
+ for (i = 0, v0 = verts + (numverts - 2) * 3, v1 = verts + (numverts - 1) * 3, v2 = verts;i < numverts;i++, v0 = v1, v1 = v2, v2 += 3)
+ {
+ VectorSubtract(v0, v1, dir0);
+ VectorSubtract(v2, v1, dir1);
+ CrossProduct(dir0, dir1, normal);
+ if (DotProduct(normal, normal) >= 0.1)
+ break;
+ }
+ if (i == numverts)
+ return;
+ VectorNormalize(normal);
+ dist = DotProduct(verts, normal);
+ VectorNegate(normal, normal);
+ dist = -dist;
+
+ poly = Mem_Alloc(mempool, sizeof(svpolygon_t) + numverts * sizeof(float[3]));
+ poly->numverts = numverts;
+ poly->verts = (float *)(poly + 1);
+ VectorCopy(normal, poly->normal);
+ poly->dist = dist;
+ poly->next = brush->polygons;
+ brush->polygons = poly;
+ for (i = 0, v0 = verts + (numverts - 1) * 3, v1 = poly->verts;i < numverts;i++, v0 -= 3, v1 += 3)
+ VectorCopy(v0, v1);
+}
+
void Mod_ShadowBrush_EndBrush(svworld_t *world, svbrush_t *brush)
{
int i;
e->cullradius2 = DotProduct(e->light, e->light) / (e->falloff * e->falloff * 8192.0f * 8192.0f);// + 4096.0f;
if (e->cullradius2 > 4096.0f * 4096.0f)
e->cullradius2 = 4096.0f * 4096.0f;
- e->cullradius = sqrt(e->cullradius2);
+ e->cullradius = e->lightradius = sqrt(e->cullradius2);
leaf = Mod_PointInLeaf(e->origin, loadmodel);
if (leaf->compressed_vis)
pvs = Mod_DecompressVis (leaf->compressed_vis, loadmodel);
if (loadmodel->surfacevisframes[j] == -2)
e->surfaces[e->numsurfaces++] = loadmodel->surfaces + j;
}
+#if 1
{
// find bounding box and sphere of lit surfaces
// (these will be used for creating a shape to clip the light)
radius2 = dist;
}
}
- /*
if (e->cullradius2 > radius2)
{
e->cullradius2 = radius2;
e->cullradius = sqrt(e->cullradius2);
}
- */
}
+#endif
+#if 1
+ e->mins[0] = e->origin[0] - e->cullradius;
+ e->maxs[0] = e->origin[0] + e->cullradius;
+ e->mins[1] = e->origin[1] - e->cullradius;
+ e->maxs[1] = e->origin[1] + e->cullradius;
+ e->mins[2] = e->origin[2] - e->cullradius;
+ e->maxs[2] = e->origin[2] + e->cullradius;
+#endif
#if 1
// clip shadow volumes against eachother to remove unnecessary
// polygons (and sections of polygons)
{
- vec3_t temp, outermins, outermaxs, innermins, innermaxs;
+ vec3_t temp;
+ //vec3_t polymins, polymaxs;
int maxverts = 4;
float *verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
float f, *v0, *v1, projectdistance;
svworld_t *svworld;
svbrush_t *svbrush;
+ svworld = Mod_ShadowBrush_NewWorld(loadmodel->mempool);
+#if 0
+ {
+ vec3_t outermins, outermaxs, innermins, innermaxs;
innermins[0] = e->mins[0] - 1;
innermins[1] = e->mins[1] - 1;
innermins[2] = e->mins[2] - 1;
outermaxs[0] = loadmodel->normalmaxs[0] + 1;
outermaxs[1] = loadmodel->normalmaxs[1] + 1;
outermaxs[2] = loadmodel->normalmaxs[2] + 1;
- svworld = Mod_ShadowBrush_NewWorld(loadmodel->mempool);
- for (j = 0, surf = loadmodel->surfaces + loadmodel->firstmodelsurface;j < loadmodel->nummodelsurfaces;j++, surf++)
- {
- if (!(surf->flags & SURF_SHADOWCAST))
- continue;
- f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
- if (surf->flags & SURF_PLANEBACK)
- f = -f;
- projectdistance = e->cullradius + f;
- if (projectdistance < 0.1 || projectdistance > e->cullradius)
- continue;
- VectorSubtract(e->origin, surf->poly_center, temp);
- if (DotProduct(temp, temp) > (surf->poly_radius2 + e->cullradius2))
- continue;
- if (maxverts < surf->poly_numverts)
- {
- maxverts = surf->poly_numverts;
- if (verts)
- Mem_Free(verts);
- verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- }
- svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
- // copy the original polygon, reversed, for the front cap of the volume
- for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
- VectorCopy(v0, v1);
- Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
- // project the original polygon, for the back cap of the volume
- for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
- {
- VectorSubtract(v0, e->origin, temp);
- VectorNormalize(temp);
- VectorMA(v0, projectdistance, temp, v1);
- }
- Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
- // project the shadow volume sides
- for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
- {
- VectorCopy(v0, &verts[0]);
- VectorCopy(v1, &verts[3]);
- VectorCopy(v1, &verts[6]);
- VectorCopy(v0, &verts[9]);
- VectorSubtract(&verts[6], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[6], projectdistance, temp, &verts[6]);
- VectorSubtract(&verts[9], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[9], projectdistance, temp, &verts[9]);
- Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
- }
- Mod_ShadowBrush_EndBrush(svworld, svbrush);
- }
// add bounding box around the whole shadow volume set,
// facing inward to limit light area, with an outer bounding box
// facing outward (this is needed by the shadow rendering method)
verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermins[2];
Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
Mod_ShadowBrush_EndBrush(svworld, svbrush);
+ }
+#endif
+#define SHADOWCASTFRONT 1
+#if SHADOWCASTFRONT
+ for (j = 0;j < e->numsurfaces;j++)
+ {
+ surf = e->surfaces[j];
+#else
+ for (j = 0, surf = loadmodel->surfaces + loadmodel->firstmodelsurface;j < loadmodel->nummodelsurfaces;j++, surf++)
+ {
+#endif
+ if (!(surf->flags & SURF_CLIPSOLID))
+ continue;
+ f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
+ if (surf->flags & SURF_PLANEBACK)
+ f = -f;
+#if SHADOWCASTFRONT
+ projectdistance = e->cullradius - f;
+#else
+ projectdistance = e->cullradius + f;
+#endif
+ if (projectdistance < 0.1 || projectdistance > e->cullradius)
+ continue;
+ VectorSubtract(e->origin, surf->poly_center, temp);
+ if (DotProduct(temp, temp) > (surf->poly_radius2 + e->cullradius2))
+ continue;
+ /*
+ VectorCopy(surf->poly_verts, polymins);
+ VectorCopy(surf->poly_verts, polymaxs);
+ for (k = 0, v0 = surf->poly_verts;k < surf->poly_numverts;k++, v0 += 3)
+ {
+ if (polymins[0] > v0[0]) polymins[0] = v0[0];if (polymaxs[0] < v0[0]) polymaxs[0] = v0[0];
+ if (polymins[1] > v0[1]) polymins[1] = v0[1];if (polymaxs[1] < v0[1]) polymaxs[1] = v0[1];
+ if (polymins[2] > v0[2]) polymins[2] = v0[2];if (polymaxs[2] < v0[2]) polymaxs[2] = v0[2];
+ }
+ if (polymins[0] > e->maxs[0] || polymaxs[0] < e->mins[0]
+ || polymins[1] > e->maxs[1] || polymaxs[1] < e->mins[1]
+ || polymins[2] > e->maxs[2] || polymaxs[2] < e->mins[2])
+ continue;
+ */
+ if (maxverts < surf->poly_numverts)
+ {
+ maxverts = surf->poly_numverts;
+ if (verts)
+ Mem_Free(verts);
+ verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
+ }
+ svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+#if SHADOWCASTFRONT
+ // copy the original polygon, for the front cap of the volume
+ for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
+ VectorCopy(v0, v1);
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+ // project the original polygon, reversed, for the back cap of the volume
+ for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
+ {
+ VectorSubtract(v0, e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(v0, projectdistance, temp, v1);
+ }
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+ // project the shadow volume sides
+ for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
+ {
+ VectorCopy(v1, &verts[0]);
+ VectorCopy(v0, &verts[3]);
+ VectorCopy(v0, &verts[6]);
+ VectorCopy(v1, &verts[9]);
+ VectorSubtract(&verts[6], e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(&verts[6], projectdistance, temp, &verts[6]);
+ VectorSubtract(&verts[9], e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(&verts[9], projectdistance, temp, &verts[9]);
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+ }
+#else
+ // copy the original polygon, reversed, for the front cap of the volume
+ for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
+ VectorCopy(v0, v1);
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+ // project the original polygon, for the back cap of the volume
+ for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
+ {
+ VectorSubtract(v0, e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(v0, projectdistance, temp, v1);
+ }
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, surf->poly_numverts, verts);
+ // project the shadow volume sides
+ for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;k++, v0 = v1, v1 += 3)
+ {
+ VectorCopy(v0, &verts[0]);
+ VectorCopy(v1, &verts[3]);
+ VectorCopy(v1, &verts[6]);
+ VectorCopy(v0, &verts[9]);
+ VectorSubtract(&verts[6], e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(&verts[6], projectdistance, temp, &verts[6]);
+ VectorSubtract(&verts[9], e->origin, temp);
+ VectorNormalize(temp);
+ VectorMA(&verts[9], projectdistance, temp, &verts[9]);
+ Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+ }
+#endif
+ Mod_ShadowBrush_EndBrush(svworld, svbrush);
+ }
// clip away hidden polygons
Mod_ShadowBrush_ProcessWorld(loadmodel->mempool, svworld);
// build the triangle mesh
}
#endif
+surfmesh_t *Mod_AllocSurfMesh(int numverts, int numtriangles)
+{
+ surfmesh_t *mesh;
+ mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + numtriangles * sizeof(int[6]) + numverts * (4 + 4 + 4 + 4 + 4 + 4 + 4 + 1) * sizeof(float));
+ mesh->numverts = numverts;
+ mesh->numtriangles = numtriangles;
+ mesh->verts = (float *)(mesh + 1);
+ mesh->str = mesh->verts + mesh->numverts * 4;
+ mesh->uvw = mesh->str + mesh->numverts * 4;
+ mesh->abc = mesh->uvw + mesh->numverts * 4;
+ mesh->svectors = (float *)(mesh->abc + mesh->numverts * 4);
+ mesh->tvectors = mesh->svectors + mesh->numverts * 4;
+ mesh->normals = mesh->tvectors + mesh->numverts * 4;
+ mesh->lightmapoffsets = (int *)(mesh->normals + mesh->numverts * 4);
+ mesh->index = mesh->lightmapoffsets + mesh->numverts;
+ mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+ return mesh;
+}
+
void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
{
int i, iu, iv, *index, smax, tmax;
vscale = (vscale - vbase) * 16.0 / ((surf->extents[1] & ~15) + 16);
}
- surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 4 + 4 + 4 + 1 + 3) * sizeof(float));
- mesh->numverts = surf->poly_numverts;
- mesh->numtriangles = surf->poly_numverts - 2;
- mesh->verts = (float *)(mesh + 1);
- mesh->str = mesh->verts + mesh->numverts * 4;
- mesh->uvw = mesh->str + mesh->numverts * 4;
- mesh->abc = mesh->uvw + mesh->numverts * 4;
- mesh->lightmapoffsets = (int *)(mesh->abc + mesh->numverts * 4);
- mesh->index = mesh->lightmapoffsets + mesh->numverts;
- mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
- mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
+ surf->mesh = mesh = Mod_AllocSurfMesh(surf->poly_numverts, surf->poly_numverts - 2);
index = mesh->index;
for (i = 0;i < mesh->numtriangles;i++)
mesh->abc[i * 4 + 0] = s * (1.0f / 16.0f);
mesh->abc[i * 4 + 1] = t * (1.0f / 16.0f);
mesh->lightmapoffsets[i] = ((iv * (smax+1) + iu) * 3);
- mesh->normals[i * 3 + 0] = normal[0];
- mesh->normals[i * 3 + 1] = normal[1];
- mesh->normals[i * 3 + 2] = normal[2];
}
+ Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
}
void Mod_GenerateVertexMesh (msurface_t *surf)
surf->lightmaptexturestride = 0;
surf->lightmaptexture = NULL;
- surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 4 + 4 + 3) * sizeof(float));
- mesh->numverts = surf->poly_numverts;
- mesh->numtriangles = surf->poly_numverts - 2;
- mesh->verts = (float *)(mesh + 1);
- mesh->str = mesh->verts + mesh->numverts * 4;
- mesh->abc = mesh->str + mesh->numverts * 4;
- mesh->index = (int *)(mesh->abc + mesh->numverts * 4);
- mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
- mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
+ surf->mesh = mesh = Mod_AllocSurfMesh(surf->poly_numverts, surf->poly_numverts - 2);
index = mesh->index;
for (i = 0;i < mesh->numtriangles;i++)
mesh->verts[i * 4 + 2] = in[2];
mesh->str[i * 4 + 0] = s / surf->texinfo->texture->width;
mesh->str[i * 4 + 1] = t / surf->texinfo->texture->height;
+ mesh->uvw[i * 4 + 0] = 0;
+ mesh->uvw[i * 4 + 1] = 0;
mesh->abc[i * 4 + 0] = s * (1.0f / 16.0f);
mesh->abc[i * 4 + 1] = t * (1.0f / 16.0f);
- mesh->normals[i * 3 + 0] = normal[0];
- mesh->normals[i * 3 + 1] = normal[1];
- mesh->normals[i * 3 + 2] = normal[2];
}
+ Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
}
void Mod_GenerateSurfacePolygon (msurface_t *surf)
Mod_FinalizePortals();
}
+static void Mod_BuildSurfaceNeighbors (msurface_t *surfaces, int numsurfaces, mempool_t *mempool)
+{
+ #if 0
+ int surfnum, vertnum, snum, vnum;
+ msurface_t *surf, *s;
+ float *v0, *v1, *v2, *v3;
+ for (surf = surfaces, surfnum = 0;surfnum < numsurfaces;surf++, surfnum++)
+ {
+ surf->neighborsurfaces = Mem_Alloc(mempool, surf->poly_numverts * sizeof(msurface_t *));
+ for (vertnum = 0;vertnum < surf->poly_numverts;vertnum++)
+ {
+ v0 = surf->poly_verts + ((vertnum + 1) % surf->poly_numverts) * 3;
+ v1 = surf->poly_verts + vertnum * 3;
+ surf->neighborsurfaces[vertnum] = NULL;
+ for (s = surfaces, snum = 0;snum < numsurfaces;s++, snum++)
+ {
+ if (s == surf)
+ continue;
+ for (vnum = 0, v2 = s->poly_verts + (s->poly_numverts - 1) * 3, v3 = s->poly_verts;vnum < s->poly_numverts;vnum++, v2 = v3, v3 += 3)
+ {
+ if (v0[0] == v2[0] && v0[1] == v2[1] && v0[2] == v2[2] && v1[0] == v3[0] && v1[1] == v3[1] && v1[2] == v3[2])
+ {
+ surf->neighborsurfaces[vertnum] = s;
+ break;
+ }
+ }
+ if (vnum < s->poly_numverts)
+ break;
+ }
+ }
+ }
+ #endif
+}
+
/*
=================
Mod_LoadBrushModel
extern void R_Model_Brush_DrawSky(entity_render_t *ent);
extern void R_Model_Brush_Draw(entity_render_t *ent);
//extern void R_Model_Brush_DrawFakeShadow(entity_render_t *ent);
-extern void R_Model_Brush_DrawDepth(entity_render_t *ent);
+extern void R_Model_Brush_DrawBaseLighting(entity_render_t *ent);
extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
-extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
-extern void R_Model_Brush_DrawOntoLight(entity_render_t *ent);
+extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
void Mod_LoadBrushModel (model_t *mod, void *buffer)
{
int i, j;
mod->DrawSky = NULL;
mod->Draw = R_Model_Brush_Draw;
mod->DrawFakeShadow = NULL;
- mod->DrawDepth = R_Model_Brush_DrawDepth;
+ mod->DrawBaseLighting = R_Model_Brush_DrawBaseLighting;
mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
mod->DrawLight = R_Model_Brush_DrawLight;
- mod->DrawOntoLight = R_Model_Brush_DrawOntoLight;
+ mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
if (mod->nummodelsurfaces)
{
// LordHavoc: calculate bmodel bounding box rather than trusting what it says
// we only need to have a drawsky function if it is used (usually only on world model)
if (surf->texinfo->texture->shader == &Cshader_sky)
mod->DrawSky = R_Model_Brush_DrawSky;
+ // link into texture chain
+ surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
+ mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
+ // calculate bounding shapes
for (k = 0;k < surf->numedges;k++)
{
l = mod->surfedges[k + surf->firstedge];
mod->radius2 = 0;
mod->shadowmesh = NULL;
}
+ Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);
mod->numleafs = bm->visleafs;
#define SHADERSTAGE_SKY 0
#define SHADERSTAGE_NORMAL 1
-#define SHADERSTAGE_COUNT 2
+#define SHADERSTAGE_BASELIGHTING 2
+#define SHADERSTAGE_COUNT 3
#define SHADERFLAGS_NEEDLIGHTMAP 1
+#define SURF_PLANEBACK 2
+#define SURF_DRAWSKY 4
+#define SURF_DRAWTURB 0x10
+#define SURF_LIGHTMAP 0x20
+#define SURF_DRAWNOALPHA 0x100
+#define SURF_DRAWFULLBRIGHT 0x200
+#define SURF_LIGHTBOTHSIDES 0x400
+#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons
+#define SURF_SHADOWCAST 0x1000 // this polygon can cast stencil shadows
+#define SURF_SHADOWLIGHT 0x2000 // this polygon can be lit by stencil shadowing
+#define SURF_WATERALPHA 0x4000 // this polygon's alpha is modulated by r_wateralpha
+
+#define SURFRENDER_OPAQUE 0
+#define SURFRENDER_ALPHA 1
+#define SURFRENDER_ADD 2
+
struct entity_render_s;
struct texture_s;
+struct msurface_s;
// change this stuff when real shaders are added
typedef struct Cshader_s
{
- void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture);
+ void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, const struct msurface_s *firstsurf);
int flags;
}
Cshader_t;
extern Cshader_t Cshader_wall_lightmap;
-extern Cshader_t Cshader_wall_fullbright;
extern Cshader_t Cshader_water;
extern Cshader_t Cshader_sky;
// SURF_ flags
unsigned int flags;
+ // type of rendering (SURFRENDER_ value)
+ int rendertype;
+
// base texture without fullbrights, never NULL
rtexture_t *texture;
// fullbrights texture, NULL if no fullbrights used
// shader to use for this texture
Cshader_t *shader;
- // list of surfaces to render using this texture
- struct msurface_s *surfacechain;
-
// total frames in sequence and alternate sequence
int anim_total[2];
// direct pointers to each of the frames in the sequences
// set if animated or there is an alternate frame set
// (this is an optimization in the renderer)
int animated;
+ // the current texture frames in animation
+ // (index with entity frame != 0)
+ struct texture_s *currentframe[2];
}
texture_t;
-
-#define SURF_PLANEBACK 2
-#define SURF_DRAWSKY 4
-#define SURF_DRAWTURB 0x10
-#define SURF_LIGHTMAP 0x20
-#define SURF_DRAWNOALPHA 0x100
-#define SURF_DRAWFULLBRIGHT 0x200
-#define SURF_LIGHTBOTHSIDES 0x400
-#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons
-#define SURF_SHADOWCAST 0x1000 // this polygon can cast stencil shadows
-#define SURF_SHADOWLIGHT 0x2000 // this polygon can be lit by stencil shadowing
-
typedef struct
{
unsigned short v[2];
int numverts;
int numtriangles;
float *verts;
+ float *svectors;
+ float *tvectors;
float *normals;
int *lightmapoffsets;
float *str;
{
// surface number, to avoid having to do a divide to find the number of a surface from it's address
int number;
- // should be drawn if visframe == r_framecount (set by WorldNode functions)
- //int visframe;
+ // should be drawn if visframe == r_framecount (set by PrepareSurfaces)
+ int visframe;
// should be drawn if onscreen and not a backface (used for setting visframe)
//int pvsframe;
// chain of surfaces marked visible by pvs
// bounding sphere radius (around poly_center)
float poly_radius, poly_radius2;
+ // neighboring surfaces (one per poly_numverts)
+ struct msurface_s **neighborsurfaces;
+
// these are regenerated every frame
// lighting info
int dlightframe;
float distbias;
// light style controlling this light
int style;
- // maximum extent of the light for various purposes
+ // maximum extent of the light for shading purposes
+ float lightradius;
+ // maximum extent of the light for culling purposes
float cullradius;
float cullradius2;
// surfaces this shines on
Mod_LoadModels();
}
-int Mod_FindTriangleWithEdge(int *elements, int numtriangles, int start, int end)
+int Mod_FindTriangleWithEdge(const int *elements, int numtriangles, int start, int end)
{
int i;
for (i = 0;i < numtriangles;i++, elements += 3)
return -1;
}
-void Mod_BuildTriangleNeighbors(int *neighbors, int *elements, int numtriangles)
+void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles)
{
- int i, *e, *n;
+ int i, *n;
+ const int *e;
for (i = 0, e = elements, n = neighbors;i < numtriangles;i++, e += 3, n += 3)
{
n[0] = Mod_FindTriangleWithEdge(elements, numtriangles, e[1], e[0]);
}
}
+void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals)
+{
+ int i, tnum, voffset;
+ float vert[3][4], vec[3][4], sdir[3], tdir[3], normal[3], f, *v;
+ const int *e;
+ // clear the vectors
+ memset(svectors, 0, numverts * sizeof(float[4]));
+ memset(tvectors, 0, numverts * sizeof(float[4]));
+ memset(normals, 0, numverts * sizeof(float[4]));
+ // process each vertex of each triangle and accumulate the results
+ for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
+ {
+ // calculate texture matrix for triangle
+ voffset = e[0] * 4;
+ vert[0][0] = vertex[voffset+0];
+ vert[0][1] = vertex[voffset+1];
+ vert[0][2] = vertex[voffset+2];
+ vert[0][3] = texcoord[voffset];
+ voffset = e[1] * 4;
+ vert[1][0] = vertex[voffset+0];
+ vert[1][1] = vertex[voffset+1];
+ vert[1][2] = vertex[voffset+2];
+ vert[1][3] = texcoord[voffset];
+ voffset = e[2] * 4;
+ vert[2][0] = vertex[voffset+0];
+ vert[2][1] = vertex[voffset+1];
+ vert[2][2] = vertex[voffset+2];
+ vert[2][3] = texcoord[voffset];
+ VectorSubtract(vert[1], vert[0], vec[0]);
+ VectorSubtract(vert[2], vert[0], vec[1]);
+ CrossProduct(vec[0], vec[1], normal);
+ if (DotProduct(normal, normal) >= 0.001)
+ {
+ VectorNormalize(normal);
+ sdir[0] = (vert[1][3] - vert[0][3]) * (vert[2][0] - vert[0][0]) - (vert[2][3] - vert[0][3]) * (vert[1][0] - vert[0][0]);
+ sdir[1] = (vert[1][3] - vert[0][3]) * (vert[2][1] - vert[0][1]) - (vert[2][3] - vert[0][3]) * (vert[1][1] - vert[0][1]);
+ sdir[2] = (vert[1][3] - vert[0][3]) * (vert[2][2] - vert[0][2]) - (vert[2][3] - vert[0][3]) * (vert[1][2] - vert[0][2]);
+ VectorNormalize(sdir);
+ f = -DotProduct(sdir, normal);
+ VectorMA(sdir, f, normal, sdir);
+ VectorNormalize(sdir);
+ CrossProduct(sdir, normal, tdir);
+ // this is probably not necessary
+ VectorNormalize(tdir);
+ // accumulate matrix onto verts used by triangle
+ for (i = 0;i < 3;i++)
+ {
+ voffset = e[i] * 4;
+ svectors[voffset ] += sdir[0];
+ svectors[voffset + 1] += sdir[1];
+ svectors[voffset + 2] += sdir[2];
+ tvectors[voffset ] += tdir[0];
+ tvectors[voffset + 1] += tdir[1];
+ tvectors[voffset + 2] += tdir[2];
+ normals[voffset ] += normal[0];
+ normals[voffset + 1] += normal[1];
+ normals[voffset + 2] += normal[2];
+ }
+ }
+ }
+ // now we could divide the vectors by the number of averaged values on
+ // each vertex... but instead normalize them
+ for (i = 0, v = svectors;i < numverts;i++, v += 4)
+ VectorNormalize(v);
+ for (i = 0, v = tvectors;i < numverts;i++, v += 4)
+ VectorNormalize(v);
+ for (i = 0, v = normals;i < numverts;i++, v += 4)
+ VectorNormalize(v);
+}
+
shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts)
{
shadowmesh_t *mesh;
while (numverts + mesh->numverts > mesh->maxverts || (numverts - 2) + mesh->numtriangles > mesh->maxtriangles)
{
if (mesh->next == NULL)
- mesh->next = Mod_ShadowMesh_Alloc(mempool, max(1000, numverts));
+ mesh->next = Mod_ShadowMesh_Alloc(mempool, max(4096, numverts));
mesh = mesh->next;
}
i1 = Mod_ShadowMesh_AddVertex(mesh, verts);
shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool)
{
- return Mod_ShadowMesh_Alloc(mempool, 1000);
+ return Mod_ShadowMesh_Alloc(mempool, 4096);
}
shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
int numtextures;
texture_t *textures;
+ msurface_t **texturesurfacechains;
+
qbyte *visdata;
qbyte *lightdata;
char *entities;
vec3_t shadowmesh_mins, shadowmesh_maxs, shadowmesh_center;
float shadowmesh_radius;
+ // pvs visibility marking
+ mleaf_t *pvsviewleaf;
+ int pvsviewleafnovis;
+ int pvsframecount;
+
// skin animation info
animscene_t *skinscenes; // [numskins]
// skin frame info
void(*DrawFakeShadow)(struct entity_render_s *ent);
// functions used only in shadow volume rendering mode
- void(*DrawDepth)(struct entity_render_s *ent);
+ // draw the base lighting for the model (glowing areas, etc)
+ void(*DrawBaseLighting)(struct entity_render_s *ent);
// draw a shadow volume for the model based on light source
void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
// draw the lighting on a model (through stencil)
- void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
- // draw the model with lighting already in framebuffer
- void(*DrawOntoLight)(struct entity_render_s *ent);
+ void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
// memory pool for allocations
mempool_t *mempool;
extern model_t *loadmodel;
extern char loadname[32]; // for hunk tags
-int Mod_FindTriangleWithEdge(int *elements, int numtriangles, int start, int end);
-void Mod_BuildTriangleNeighbors(int *neighbors, int *elements, int numtriangles);
+int Mod_FindTriangleWithEdge(const int *elements, int numtriangles, int start, int end);
+void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles);
+void Mod_BuildTextureVectorsAndNormals(int numverts, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals);
shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts);
shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh);
loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Sprite_Draw;
loadmodel->DrawFakeShadow = NULL;
- loadmodel->DrawDepth = NULL;
+ loadmodel->DrawBaseLighting = NULL;
loadmodel->DrawShadowVolume = NULL;
loadmodel->DrawLight = NULL;
- loadmodel->DrawOntoLight = NULL;
version = LittleLong(((dsprite_t *)buffer)->version);
if (version == SPRITE_VERSION || SPRITE32_VERSION)
R_MarkLights
=============
*/
-extern int r_pvsframecount;
static void R_OldMarkLights (entity_render_t *ent, vec3_t lightorigin, rdlight_t *rd, int bit, int bitindex, mnode_t *node)
{
float ndist, maxdist;
surf = ent->model->surfaces + node->firstsurface;
for (i = 0;i < node->numsurfaces;i++, surf++)
{
- if (surfacepvsframes[surf->number] != r_pvsframecount)
+ if (surfacepvsframes[surf->number] != ent->model->pvsframecount)
continue;
dist = ndist;
if (surf->flags & SURF_PLANEBACK)
if (surf->lightframe == lightframe)
continue;
surf->lightframe = lightframe;
- if (surfacepvsframes[surf->number] != r_pvsframecount)
+ if (surfacepvsframes[surf->number] != model->pvsframecount)
continue;
dist = PlaneDiff(lightorigin, surf->plane);
if (surf->flags & SURF_PLANEBACK)
avc[3] = a;
avc += 4;
av += 4;
- avn += 3;
+ avn += 4;
}
}
else
qbyte *trianglefacinglight;
rtexturepool_t *r_shadow_texturepool;
-rtexture_t *r_shadow_attenuationtexture;
+rtexture_t *r_shadow_normalsattenuationtexture;
+rtexture_t *r_shadow_normalscubetexture;
+rtexture_t *r_shadow_attenuation2dtexture;
+rtexture_t *r_shadow_blankbumptexture;
cvar_t r_shadow1 = {0, "r_shadow1", "16"};
-cvar_t r_shadow2 = {0, "r_shadow2", "4"};
+cvar_t r_shadow2 = {0, "r_shadow2", "2"};
cvar_t r_shadow3 = {0, "r_shadow3", "65536"};
cvar_t r_shadow4 = {0, "r_shadow4", "1"};
cvar_t r_shadow5 = {0, "r_shadow5", "0"};
cvar_t r_shadow6 = {0, "r_shadow6", "1"};
+cvar_t r_light_realtime = {0, "r_light_realtime", "0"};
+cvar_t r_light_quality = {0, "r_light_quality", "1"};
+cvar_t r_light_gloss = {0, "r_light_gloss", "0"};
+cvar_t r_light_debuglight = {0, "r_light_debuglight", "-1"};
void r_shadow_start(void)
{
shadowelements = NULL;
maxtrianglefacinglight = 0;
trianglefacinglight = NULL;
- r_shadow_attenuationtexture = NULL;
+ r_shadow_normalsattenuationtexture = NULL;
+ r_shadow_normalscubetexture = NULL;
+ r_shadow_attenuation2dtexture = NULL;
+ r_shadow_blankbumptexture = NULL;
r_shadow_texturepool = NULL;
}
void r_shadow_shutdown(void)
{
- r_shadow_attenuationtexture = NULL;
+ r_shadow_normalsattenuationtexture = NULL;
+ r_shadow_normalscubetexture = NULL;
+ r_shadow_attenuation2dtexture = NULL;
+ r_shadow_blankbumptexture = NULL;
R_FreeTexturePool(&r_shadow_texturepool);
maxshadowelements = 0;
shadowelements = NULL;
Cvar_RegisterVariable(&r_shadow4);
Cvar_RegisterVariable(&r_shadow5);
Cvar_RegisterVariable(&r_shadow6);
+ Cvar_RegisterVariable(&r_light_realtime);
+ Cvar_RegisterVariable(&r_light_quality);
+ Cvar_RegisterVariable(&r_light_gloss);
+ Cvar_RegisterVariable(&r_light_debuglight);
R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
}
// the unprojected vertices and these projected vertices
for (i = 0, v0 = vertex, v1 = vertex + numverts * 4;i < numverts;i++, v0 += 4, v1 += 4)
{
+#if 1
+ v1[0] = v0[0] + 50.0f * (v0[0] - relativelightorigin[0]);
+ v1[1] = v0[1] + 50.0f * (v0[1] - relativelightorigin[1]);
+ v1[2] = v0[2] + 50.0f * (v0[2] - relativelightorigin[2]);
+#elif 0
VectorSubtract(v0, relativelightorigin, temp);
-#if 0
f = lightradius / sqrt(DotProduct(temp,temp));
if (f < 1)
f = 1;
VectorMA(relativelightorigin, f, temp, v1);
#else
+ VectorSubtract(v0, relativelightorigin, temp);
f = projectdistance / sqrt(DotProduct(temp,temp));
VectorMA(v0, f, temp, v1);
#endif
// of the comparison use it, therefore they are both multiplied the
// same amount... furthermore the subtract can be done on the
// vectors, saving a little bit of math in the dotproducts
-#if 1
+#if 0
// fast version
// subtracts v1 from v0 and v2, combined into a crossproduct,
// combined with a dotproduct of the light location relative to the
// I.E. flat, so all points give the same answer)
// the normal is not normalized because it is used on both sides of
// the comparison, so it's magnitude does not matter
- trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+ //trianglefacinglight[i] = DotProduct(relativelightorigin, temp) >= DotProduct(v0, temp);
+ f = DotProduct(relativelightorigin, temp) - DotProduct(v0, temp);
+ trianglefacinglight[i] = f > 0 && f < lightradius * sqrt(DotProduct(temp, temp));
+ }
#endif
}
out[5] = e[2] + numverts;
out += 6;
tris += 2;
-#else
+#else if 1
// rear cap
out[0] = e[0] + numverts;
out[1] = e[1] + numverts;
// draw the volume
if (visiblevolume)
{
- qglDisable(GL_CULL_FACE);
+ //qglDisable(GL_CULL_FACE);
R_Mesh_Draw(numverts, numtris, elements);
- qglEnable(GL_CULL_FACE);
+ //qglEnable(GL_CULL_FACE);
}
else
{
}
float r_shadow_atten1, r_shadow_atten2, r_shadow_atten5;
-static void R_Shadow_MakeTextures(void)
+#define ATTEN3DSIZE 64
+static void R_Shadow_Make3DTextures(void)
{
int x, y, z, d;
- float v[3];
- qbyte data[32][32][32][4];
+ float v[3], intensity, ilen, length;
+ qbyte data[ATTEN3DSIZE][ATTEN3DSIZE][ATTEN3DSIZE][4];
+ if (r_light_quality.integer != 1 || !gl_texture3d)
+ return;
+ for (z = 0;z < ATTEN3DSIZE;z++)
+ {
+ for (y = 0;y < ATTEN3DSIZE;y++)
+ {
+ for (x = 0;x < ATTEN3DSIZE;x++)
+ {
+ v[0] = (x + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+ v[1] = (y + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+ v[2] = (z + 0.5f) * (2.0f / (float) ATTEN3DSIZE) - 1.0f;
+ length = sqrt(DotProduct(v, v));
+ if (DotProduct(v, v) < 1)
+ intensity = (((r_shadow_atten1 / (length*length + r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f;
+ else
+ intensity = 0;
+ ilen = 127.0f * bound(0, intensity, 1) / length;
+ data[z][y][x][0] = 128.0f + ilen * v[0];
+ data[z][y][x][1] = 128.0f + ilen * v[1];
+ data[z][y][x][2] = 128.0f + ilen * v[2];
+ data[z][y][x][3] = 255;
+ }
+ }
+ }
+ r_shadow_normalsattenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "normalsattenuation", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+}
+
+static void R_Shadow_MakeTextures(void)
+{
+ int x, y, z, d, side;
+ float v[3], s, t, intensity;
+ qbyte data[6][128][128][4];
R_FreeTexturePool(&r_shadow_texturepool);
r_shadow_texturepool = R_AllocTexturePool();
r_shadow_atten1 = r_shadow1.value;
r_shadow_atten2 = r_shadow2.value;
r_shadow_atten5 = r_shadow5.value;
- for (z = 0;z < 32;z++)
+ for (y = 0;y < 128;y++)
{
- for (y = 0;y < 32;y++)
+ for (x = 0;x < 128;x++)
{
- for (x = 0;x < 32;x++)
+ data[0][y][x][0] = 128;
+ data[0][y][x][1] = 128;
+ data[0][y][x][2] = 255;
+ data[0][y][x][3] = 255;
+ }
+ }
+ r_shadow_blankbumptexture = R_LoadTexture(r_shadow_texturepool, "blankbump", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE);
+ for (side = 0;side < 6;side++)
+ {
+ for (y = 0;y < 128;y++)
+ {
+ for (x = 0;x < 128;x++)
{
- v[0] = (x / 32.0f) - 0.5f;
- v[1] = (y / 32.0f) - 0.5f;
- v[2] = (z / 32.0f) - 0.5f;
- d = (int) (((r_shadow_atten1 / (DotProduct(v, v)+r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2)));
- d = bound(0, d, 255);
- data[z][y][x][0] = data[z][y][x][1] = data[z][y][x][2] = data[z][y][x][3] = d;
+ s = (x + 0.5f) * (2.0f / 128.0f) - 1.0f;
+ t = (y + 0.5f) * (2.0f / 128.0f) - 1.0f;
+ switch(side)
+ {
+ case 0:
+ v[0] = 1;
+ v[1] = -t;
+ v[2] = -s;
+ break;
+ case 1:
+ v[0] = -1;
+ v[1] = -t;
+ v[2] = s;
+ break;
+ case 2:
+ v[0] = s;
+ v[1] = 1;
+ v[2] = t;
+ break;
+ case 3:
+ v[0] = s;
+ v[1] = -1;
+ v[2] = -t;
+ break;
+ case 4:
+ v[0] = s;
+ v[1] = -t;
+ v[2] = 1;
+ break;
+ case 5:
+ v[0] = -s;
+ v[1] = -t;
+ v[2] = -1;
+ break;
+ }
+ intensity = 127.0f / sqrt(DotProduct(v, v));
+ data[side][y][x][0] = 128.0f + intensity * v[0];
+ data[side][y][x][1] = 128.0f + intensity * v[1];
+ data[side][y][x][2] = 128.0f + intensity * v[2];
+ data[side][y][x][3] = 255;
}
}
}
- r_shadow_attenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation", 32, 32, 32, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_ALPHA);
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- qglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
+ r_shadow_normalscubetexture = R_LoadTextureCubeMap(r_shadow_texturepool, "normalscube", 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+ for (y = 0;y < 128;y++)
+ {
+ for (x = 0;x < 128;x++)
+ {
+ v[0] = (x + 0.5f) * (2.0f / 128.0f) - 1.0f;
+ v[1] = (y + 0.5f) * (2.0f / 128.0f) - 1.0f;
+ v[2] = 0;
+ if (DotProduct(v, v) < 1)
+ intensity = (((r_shadow_atten1 / (DotProduct(v, v)+r_shadow_atten5)) - (r_shadow_atten1 * r_shadow_atten2))) / 256.0f;
+ else
+ intensity = 0;
+ d = bound(0, intensity, 255) / sqrt(DotProduct(v, v));
+ data[0][y][x][0] = d;
+ data[0][y][x][1] = d;
+ data[0][y][x][2] = d;
+ data[0][y][x][3] = 255;
+ }
+ }
+ r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+ R_Shadow_Make3DTextures();
}
-void R_Shadow_Stage_Depth(void)
+void R_Shadow_Stage_Begin(void)
{
rmeshstate_t m;
+ if (r_light_quality.integer == 1 && !gl_texture3d)
+ {
+ Con_Printf("3D texture support not detected, falling back on slower 2D + 1D + normalization lighting\n");
+ Cvar_SetValueQuick(&r_light_quality, 0);
+ }
//cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1);
- if (!r_shadow_attenuationtexture || r_shadow1.value != r_shadow_atten1 || r_shadow2.value != r_shadow_atten2 || r_shadow5.value != r_shadow_atten5)
+ if (!r_shadow_attenuation2dtexture
+ || (r_light_quality.integer == 1 && !r_shadow_normalsattenuationtexture)
+ || r_shadow1.value != r_shadow_atten1
+ || r_shadow2.value != r_shadow_atten2
+ || r_shadow5.value != r_shadow_atten5)
R_Shadow_MakeTextures();
memset(&m, 0, sizeof(m));
{
rmeshstate_t m;
memset(&m, 0, sizeof(m));
- if (r_shadow6.integer)
- m.tex3d[0] = R_GetTexture(r_shadow_attenuationtexture);
R_Mesh_TextureState(&m);
+ qglActiveTexture(GL_TEXTURE0_ARB);
+
qglEnable(GL_BLEND);
qglBlendFunc(GL_ONE, GL_ONE);
GL_Color(1, 1, 1, 1);
qglStencilFunc(GL_EQUAL, 0, 0xFF);
}
-void R_Shadow_Stage_Textures(void)
+void R_Shadow_Stage_End(void)
{
rmeshstate_t m;
// attempt to restore state to what Mesh_State thinks it is
qglDisable(GL_BLEND);
qglBlendFunc(GL_ONE, GL_ZERO);
qglDepthMask(1);
-
- // now change to a more useful state
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_DST_COLOR;
- m.blendfunc2 = GL_SRC_COLOR;
- R_Mesh_State(&m);
-
- // now hack some more
- GL_Color(1, 1, 1, 1);
- qglColorMask(1, 1, 1, 1);
- qglDepthFunc(GL_EQUAL);
- qglEnable(GL_STENCIL_TEST);
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- // only draw in lit areas
- qglStencilFunc(GL_EQUAL, 0, 0xFF);
-}
-
-void R_Shadow_Stage_End(void)
-{
- rmeshstate_t m;
+ // now restore the rest of the state to normal
GL_Color(1, 1, 1, 1);
qglColorMask(1, 1, 1, 1);
qglDepthFunc(GL_LEQUAL);
qglDisable(GL_STENCIL_TEST);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+}
- // now change to a more useful state
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_ONE;
- m.blendfunc2 = GL_ZERO;
- R_Mesh_State(&m);
+void R_Shadow_GenTexCoords_Attenuation2D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const vec3_t relativelightorigin, float lightradius)
+{
+ int i;
+ float lightvec[3], iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightvec);
+ out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
+ out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
+ }
+}
+
+void R_Shadow_GenTexCoords_Attenuation1D(float *out, int numverts, const float *vertex, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+ int i;
+ float lightvec[3], iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, normals += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightvec);
+ out[0] = 0.5f + DotProduct(normals, lightvec) * iradius;
+ out[1] = 0.5f;
+ }
+}
+
+void R_Shadow_GenTexCoords_Diffuse_Attenuation3D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+ int i;
+ float lightvec[3], iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightvec);
+ out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
+ out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
+ out[2] = 0.5f + DotProduct(normals, lightvec) * iradius;
+ }
+}
+
+void R_Shadow_GenTexCoords_Diffuse_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, float lightradius)
+{
+ int i;
+ float lightdir[3], iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightdir);
+ // the cubemap normalizes this for us
+ out[0] = DotProduct(svectors, lightdir);
+ out[1] = DotProduct(tvectors, lightdir);
+ out[2] = DotProduct(normals, lightdir);
+ }
+}
+
+void R_Shadow_GenTexCoords_Specular_Attenuation3D(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin, float lightradius)
+{
+ int i;
+ float lightdir[3], eyedir[3], halfdir[3], lightdirlen, ilen, iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightdir);
+ // this is used later to make the attenuation correct
+ lightdirlen = sqrt(DotProduct(lightdir, lightdir)) * iradius;
+ VectorNormalizeFast(lightdir);
+ VectorSubtract(vertex, relativeeyeorigin, eyedir);
+ VectorNormalizeFast(eyedir);
+ VectorAdd(lightdir, eyedir, halfdir);
+ VectorNormalizeFast(halfdir);
+ out[0] = 0.5f + DotProduct(svectors, halfdir) * lightdirlen;
+ out[1] = 0.5f + DotProduct(tvectors, halfdir) * lightdirlen;
+ out[2] = 0.5f + DotProduct(normals, halfdir) * lightdirlen;
+ }
+}
+
+void R_Shadow_GenTexCoords_Specular_NormalCubeMap(float *out, int numverts, const float *vertex, const float *svectors, const float *tvectors, const float *normals, const vec3_t relativelightorigin, const vec3_t relativeeyeorigin, float lightradius)
+{
+ int i;
+ float lightdir[3], eyedir[3], halfdir[3], lightdirlen, ilen, iradius;
+ iradius = 0.5f / lightradius;
+ for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
+ {
+ VectorSubtract(vertex, relativelightorigin, lightdir);
+ VectorNormalizeFast(lightdir);
+ VectorSubtract(vertex, relativeeyeorigin, eyedir);
+ VectorNormalizeFast(eyedir);
+ VectorAdd(lightdir, eyedir, halfdir);
+ // the cubemap normalizes this for us
+ out[0] = DotProduct(svectors, halfdir);
+ out[1] = DotProduct(tvectors, halfdir);
+ out[2] = DotProduct(normals, halfdir);
+ }
+}
+
+void R_Shadow_GenTexCoords_LightCubeMap(float *out, int numverts, const float *vertex, const vec3_t relativelightorigin)
+{
+ int i;
+ for (i = 0;i < numverts;i++, vertex += 4, out += 4)
+ VectorSubtract(vertex, relativelightorigin, out);
}
-void R_Shadow_Light(int numverts, float *normals, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
{
- if (!r_shadow6.integer)
+ float f;
+ rmeshstate_t m;
+ memset(&m, 0, sizeof(m));
+ if (!bumptexture)
+ bumptexture = r_shadow_blankbumptexture;
+ f = 1.0f / r_shadow3.value;
+ if (r_light_quality.integer == 1)
{
- int i;
- float *n, *v, *c, f, dist, temp[3], light[3], lightradius2;
- VectorCopy(lightcolor, light);
- lightradius2 = lightradius * lightradius;
- for (i = 0, v = varray_vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
+ // 4 texture 3D path, two pass
+ GL_Color(1,1,1,1);
+ //lightcolor[0] * f, lightcolor[1] * f, lightcolor[2] * f, 1);
+ memcpy(varray_texcoord[0], texcoords, numverts * sizeof(float[4]));
+ memcpy(varray_texcoord[2], texcoords, numverts * sizeof(float[4]));
+ if (r_light_gloss.integer != 2)
{
- VectorSubtract(relativelightorigin, v, temp);
- c[0] = 0;
- c[1] = 0;
- c[2] = 0;
- c[3] = 1;
- f = DotProduct(n, temp);
- if (f > 0)
- {
- dist = DotProduct(temp, temp);
- if (dist < lightradius2)
- {
- f = ((1.0f / (dist + lightdistbias)) - lightsubtract) * (f / sqrt(dist));
- c[0] = f * light[0];
- c[1] = f * light[1];
- c[2] = f * light[2];
- }
- }
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture);
+ m.tex[2] = R_GetTexture(basetexture);
+ m.texcubemap[3] = R_GetTexture(lightcubemap);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.texcombinergb[1] = GL_DOT3_RGB_ARB;
+ m.texcombinergb[2] = GL_MODULATE;
+ m.texcombinergb[3] = GL_MODULATE;
+ R_Mesh_TextureState(&m);
+ R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius);
+ if (m.texcubemap[3])
+ R_Shadow_GenTexCoords_LightCubeMap(varray_texcoord[3], numverts, varray_vertex, relativelightorigin);
+ R_Mesh_Draw(numverts, numtriangles, elements);
+ }
+ if (r_light_gloss.integer && glosstexture)
+ {
+ m.tex[0] = R_GetTexture(bumptexture);
+ m.tex3d[1] = R_GetTexture(r_shadow_normalsattenuationtexture);
+ m.tex[2] = R_GetTexture(glosstexture);
+ m.texcubemap[3] = R_GetTexture(lightcubemap);
+ m.texcombinergb[0] = GL_REPLACE;
+ m.texcombinergb[1] = GL_DOT3_RGB_ARB;
+ m.texcombinergb[2] = GL_MODULATE;
+ m.texcombinergb[3] = GL_MODULATE;
+ R_Mesh_TextureState(&m);
+ R_Shadow_GenTexCoords_Specular_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, relativeeyeorigin, lightradius);
+ R_Mesh_Draw(numverts, numtriangles, elements);
}
}
else
{
- int i;
- float *n, *v, *c, *t, f, temp[3], light[3], iradius, attentexbase[3];
- VectorScale(lightcolor, (1.0f / r_shadow3.value), light);
- iradius = 0.5f / lightradius;
- attentexbase[0] = 0.5f;
- attentexbase[1] = 0.5f;
- attentexbase[2] = 0.5f;
- for (i = 0, v = varray_vertex, c = varray_color, n = normals, t = varray_texcoord[0];i < numverts;i++, v += 4, c += 4, n += 3, t += 4)
- {
- VectorSubtract(v, relativelightorigin, temp);
- VectorMA(attentexbase, iradius, temp, t);
- c[0] = 0;
- c[1] = 0;
- c[2] = 0;
- c[3] = 1;
- f = DotProduct(n, temp);
- if (f < 0)
- {
- f /= -sqrt(DotProduct(temp, temp));
- c[0] = f * light[0];
- c[1] = f * light[1];
- c[2] = f * light[2];
- }
- }
+ //R_Mesh_TextureState(&m);
}
}
+
#ifndef R_SHADOW_H
#define R_SHADOW_H
+extern cvar_t r_light_realtime;
+extern cvar_t r_light_quality;
+extern cvar_t r_light_gloss;
+extern cvar_t r_light_debuglight;
+
void R_Shadow_Init(void);
void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance, int visiblevolume);
-void R_Shadow_Light(int numverts, float *normals, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
-void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
+void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements, const float *svectors, const float *tvectors, const float *normals, const float *texcoords, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, rtexture_t *basetexture, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap);
void R_Shadow_ClearStencil(void);
void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume);
-void R_Shadow_Stage_Depth(void);
+void R_Shadow_Stage_Begin(void);
void R_Shadow_Stage_ShadowVolumes(void);
void R_Shadow_Stage_Light(void);
-void R_Shadow_Stage_Textures(void);
void R_Shadow_Stage_End(void);
#endif
// allocated as a fragment in a larger texture, mipmap is not allowed with
// this, mostly used for lightmaps
#define TEXF_FRAGMENT 0x00000010
+// indicates texture coordinates should be clamped rather than wrapping
+#define TEXF_CLAMP 0x00000020
// used for checking if textures mismatch
-#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_FRAGMENT)
+#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_FRAGMENT | TEXF_CLAMP)
// 8bit quake paletted
#define TEXTYPE_QPALETTE 1
void R_NewMap (void);
-void R_DrawWorld(entity_render_t *ent);
+void R_DrawWorld(entity_render_t *ent, int baselighting);
void R_DrawParticles(void);
void R_DrawExplosions(void);