cvar_t r_showoverdraw = {CF_CLIENT, "r_showoverdraw", "0", "shows overlapping geometry"};
cvar_t r_showbboxes = {CF_CLIENT, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
cvar_t r_showbboxes_client = {CF_CLIENT, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
-cvar_t r_showsurfaces = {CF_CLIENT, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
+cvar_t r_showsurfaces = {CF_CLIENT, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 3 shows an approximation to vertex or object color (for a very approximate view of the game)"};
cvar_t r_showtris = {CF_CLIENT, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
cvar_t r_shownormals = {CF_CLIENT, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
cvar_t r_showlighting = {CF_CLIENT, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
float c[4];
float f;
inpixels = NULL;
- strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
+ dp_strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
if (r_refdef.fogheighttexturename[0])
inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
if (!inpixels)
static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, uint64_t permutation)
{
- int i;
+ unsigned i;
int ubibind;
int sampler;
shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
permutationname[0] = 0;
sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
- strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
+ dp_strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
// we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
if(vid.support.glshaderversion >= 140)
vertstrings_list[vertstrings_count++] = modeinfo->pretext;
geomstrings_list[geomstrings_count++] = modeinfo->pretext;
fragstrings_list[fragstrings_count++] = modeinfo->pretext;
- strlcat(permutationname, modeinfo->name, sizeof(permutationname));
+ dp_strlcat(permutationname, modeinfo->name, sizeof(permutationname));
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
- strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
+ dp_strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
}
else
{
if (!r_glsl_permutation->program)
{
// remove features until we find a valid permutation
- int i;
+ unsigned i;
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
// reduce i more quickly whenever it would not remove any bits
static void R_GLSL_DumpShader_f(cmd_state_t *cmd)
{
- int i, language, mode, dupe;
+ unsigned i, language, mode, dupe;
char *text;
shadermodeinfo_t *modeinfo;
qfile_t *file;
if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
-
+
// additive passes are only darkened by fog, not tinted
if (r_glsl_permutation->loc_FogColor >= 0)
qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
return NULL;
item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
memset(item, 0, sizeof(*item));
- strlcpy(item->basename, basename, sizeof(item->basename));
+ dp_strlcpy(item->basename, basename, sizeof(item->basename));
item->textureflags = compareflags;
item->comparewidth = comparewidth;
item->compareheight = compareheight;
return r_texture_whitecube;
r_texture_numcubemaps++;
r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
- strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
+ dp_strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
return r_texture_cubemaps[i]->texture;
}
// if the resize did not give us enough memory, fail
if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
- Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
+ Sys_Abort("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
offset = (int)mem->current;
r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
- Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
+ Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
// note: this can fail if the buffer is at the grow limit
ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
r_refdef.view.usecustompvs = true;
r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
}
-
+
// camera needs no clipplane
r_refdef.view.useclipplane = false;
// TODO: is the camera origin always valid? if so we don't need to clear this
r_fb.rt_bloom = cur;
}
-static qbool R_BlendView_IsTrivial(int viewx, int viewy, int viewwidth, int viewheight, int x, int y, int width, int height)
+static qbool R_BlendView_IsTrivial(int viewwidth, int viewheight, int width, int height)
{
- // Shifting requested?
- // (It should be possible to work around this otherwise)
- if (viewx != x || viewy != y)
- return false;
// Scaling requested?
if (viewwidth != width || viewheight != height)
return false;
// Higher bit depth or explicit FBO requested?
if (r_viewfbo.integer)
return false;
- // Motion blur?
- if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || (r_damageblur.value > 0 && cl.cshifts[CSHIFT_DAMAGE].percent != 0)) && r_fb.ghosttexture)
- return false;
// Non-trivial postprocessing shader permutation?
if (r_fb.bloomwidth
|| r_refdef.viewblend[3] > 0
return true;
}
-static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
+static void R_MotionBlurView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
{
- uint64_t permutation;
- float uservecs[4][4];
- rtexture_t *viewtexture;
- rtexture_t *bloomtexture;
-
R_EntityMatrix(&identitymatrix);
if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || (r_damageblur.value > 0 && cl.cshifts[CSHIFT_DAMAGE].percent != 0)) && r_fb.ghosttexture)
{
// declare variables
float blur_factor, blur_mouseaccel, blur_velocity;
- static float blur_average;
+ static float blur_average;
static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
// set a goal for the factoring
- blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
+ blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
/ max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
- blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
+ blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
/ max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
- blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
+ blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
+ (blur_mouseaccel * r_motionblur_mousefactor.value));
// from the goal, pick an averaged value between goal and last value
cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
- // enforce minimum amount of blur
+ // enforce minimum amount of blur
blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
//Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
r_fb.ghosttexture_valid = true;
}
+}
+
+static void R_BlendView(rtexture_t *viewcolortexture, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
+{
+ uint64_t permutation;
+ float uservecs[4][4];
+ rtexture_t *viewtexture;
+ rtexture_t *bloomtexture;
+
+ R_EntityMatrix(&identitymatrix);
if (r_fb.bloomwidth)
{
if(r_fb.rt_bloom)
r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
- skipblend = R_BlendView_IsTrivial(0, 0, r_fb.rt_screen->texturewidth, r_fb.rt_screen->textureheight, x, y, width, height);
+ skipblend = R_BlendView_IsTrivial(r_fb.rt_screen->texturewidth, r_fb.rt_screen->textureheight, width, height);
if (skipblend)
{
// Render to the screen right away.
// test needs to be on
if (r_fb.rt_screen)
GL_ScissorTest(true);
- GL_Scissor(viewx, viewy, viewwidth, viewheight);
+ GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
r_fb.water.numwaterplanes = 0;
// postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
GL_ScissorTest(false);
+ R_MotionBlurView(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
if (!skipblend)
- R_BlendView(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, fbo, depthtexture, colortexture, x, y, width, height);
+ R_BlendView(viewcolortexture, fbo, depthtexture, colortexture, x, y, width, height);
if (r_timereport_active)
R_TimeReport("blendview");
};
#define BBOXEDGES 13
-static const float bboxedges[BBOXEDGES][6] =
+static const float bboxedges[BBOXEDGES][6] =
{
// whole box
{ 0, 0, 0, 1, 1, 1 },
char name[MAX_QPATH];
skinframe_t *skinframe;
unsigned char pixels[296*194];
- strlcpy(cache->name, skinname, sizeof(cache->name));
+ dp_strlcpy(cache->name, skinname, sizeof(cache->name));
dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
if (developer_loading.integer)
Con_Printf("loading %s\n", name);
if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
{
if (rsurface.modelsurfaces[j].texture != rsurface.texture)
- Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
+ Sys_Abort("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
break;
}
}
int k;
const msurface_t *surface;
float surfacecolor4f[4];
+ float c[4];
+ texture_t *t = rsurface.texture;
// R_Mesh_ResetTextureState();
R_SetupShader_Generic_NoTexture(false, false);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(writedepth);
- RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
- vi = 0;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ switch (r_showsurfaces.integer)
{
- surface = texturesurfacelist[texturesurfaceindex];
- k = (int)(((size_t)surface) / sizeof(msurface_t));
- Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
- for (j = 0;j < surface->num_vertices;j++)
- {
- Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
- vi++;
- }
+ case 1:
+ default:
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
+ vi = 0;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ k = (int)(((size_t)surface) / sizeof(msurface_t));
+ Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
+ for (j = 0;j < surface->num_vertices;j++)
+ {
+ Vector4Copy(surfacecolor4f, rsurface.batchlightmapcolor4f + 4 * vi);
+ vi++;
+ }
+ }
+ break;
+ case 3:
+ if(t && t->currentskinframe)
+ {
+ Vector4Copy(t->currentskinframe->avgcolor, c);
+ c[3] *= t->currentalpha;
+ }
+ else
+ {
+ Vector4Set(c, 1, 0, 1, 1);
+ }
+ if (t && (t->pantstexture || t->shirttexture))
+ {
+ VectorMAM(0.7, t->render_colormap_pants, 0.3, t->render_colormap_shirt, c);
+ }
+ VectorScale(c, 2 * r_refdef.view.colorscale, c);
+ if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
+ c[3] *= r_wateralpha.value;
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ALWAYSCOPY, texturenumsurfaces, texturesurfacelist);
+ vi = 0;
+ if (rsurface.modellightmapcolor4f)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ for (j = 0;j < surface->num_vertices;j++)
+ {
+ float *ptr = rsurface.batchlightmapcolor4f + 4 * vi;
+ Vector4Multiply(ptr, c, ptr);
+ vi++;
+ }
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ for (j = 0;j < surface->num_vertices;j++)
+ {
+ float *ptr = rsurface.batchlightmapcolor4f + 4 * vi;
+ Vector4Copy(c, ptr);
+ vi++;
+ }
+ }
+ }
+ break;
}
R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f);
RSurf_DrawBatch();
// Now check if update flags are set on any surfaces that are visible
if (r_q1bsp_lightmap_updates_hidden_surfaces.integer)
{
- /*
+ /*
* We can do less frequent texture uploads (approximately 10hz for animated
* lightstyles) by rebuilding lightmaps on surfaces that are not currently visible.
* For optimal efficiency, this includes the submodels of the worldmodel, so we