data[2] = 128; // normal X
data[1] = 128; // normal Y
data[0] = 255; // normal Z
- data[3] = 128; // height
+ data[3] = 255; // height
r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
data[0] = 255;
data[1] = 255;
int loc_LightPosition;
int loc_OffsetMapping_ScaleSteps;
int loc_OffsetMapping_LodDistance;
+ int loc_OffsetMapping_Bias;
int loc_PixelSize;
int loc_ReflectColor;
int loc_ReflectFactor;
p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
+ p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
D3DPSREGISTER_NormalmapScrollBlend = 52,
D3DPSREGISTER_OffsetMapping_LodDistance = 53,
+ D3DPSREGISTER_OffsetMapping_Bias = 54,
// next at 54
}
D3DPSREGISTER_t;
if (vslog)
{
strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
- Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
+ Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
vslog->Release();
}
}
if (pslog)
{
strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
- Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
+ Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
pslog->Release();
}
}
Sys_UnloadLibrary(&d3dx9_dll);
}
else
- Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
+ Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
}
if (vsbin && psbin)
{
vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
if (FAILED(vsresult))
- Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
+ Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
if (FAILED(psresult))
- Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
+ Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
}
// free the shader data
vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
}
else
{
- if (r_glsl_offsetmapping.integer)
+ if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
{
switch(rsurface.texture->offsetmapping)
{
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
- hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
+ hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
);
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
+ DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
mymiplevel = savemiplevel;
if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
{
- skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
+ skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
#ifndef USE_GLES2
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
{
ent = r_refdef.scene.entities[i];
- // skip unseen models
- if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
+ // skip unseen models and models that updated by CSQC
+ if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
continue;
// skip bsp models
ent = r_refdef.scene.entities[i];
if (!(ent->flags & renderimask))
if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
- if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
+ if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
}
if (!r_refdef.viewcache.entityvisible[i])
continue;
ent = r_refdef.scene.entities[i];
- if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
+ if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
{
samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
if (samples < 0)
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
+ R_AnimCache_CacheVisibleEntities();
}
void R_View_Update(void)
R_View_WorldVisibility(r_refdef.view.useclipplane);
R_View_UpdateEntityVisible();
R_View_UpdateEntityLighting();
+ R_AnimCache_CacheVisibleEntities();
}
float viewscalefpsadjusted = 1.0f;
void R_Water_AddWaterPlane(msurface_t *surface, int entno)
{
- int triangleindex, planeindex;
- const int *e;
- vec3_t vert[3];
- vec3_t normal;
- vec3_t center;
+ int planeindex, bestplaneindex, vertexindex;
+ vec3_t mins, maxs, normal, center, v, n;
+ vec_t planescore, bestplanescore;
mplane_t plane;
r_waterstate_waterplane_t *p;
texture_t *t = R_GetCurrentTexture(surface->texture);
- // just use the first triangle with a valid normal for any decisions
- VectorClear(normal);
- for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
- {
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
- Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
- TriangleNormal(vert[0], vert[1], vert[2], normal);
- if (VectorLength2(normal) >= 0.001)
- break;
- }
+ rsurface.texture = t;
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
+ // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
+ if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
+ return;
+ // average the vertex normals, find the surface bounds (after deformvertexes)
+ Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
+ Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
+ VectorCopy(n, normal);
+ VectorCopy(v, mins);
+ VectorCopy(v, maxs);
+ for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
+ {
+ Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
+ Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
+ VectorAdd(normal, n, normal);
+ mins[0] = min(mins[0], v[0]);
+ mins[1] = min(mins[1], v[1]);
+ mins[2] = min(mins[2], v[2]);
+ maxs[0] = max(maxs[0], v[0]);
+ maxs[1] = max(maxs[1], v[1]);
+ maxs[2] = max(maxs[2], v[2]);
+ }
+ VectorNormalize(normal);
+ VectorMAM(0.5f, mins, 0.5f, maxs, center);
VectorCopy(normal, plane.normal);
VectorNormalize(plane.normal);
- plane.dist = DotProduct(vert[0], plane.normal);
+ plane.dist = DotProduct(center, plane.normal);
PlaneClassify(&plane);
if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
{
// skip backfaces (except if nocullface is set)
- if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
- return;
+// if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
+// return;
VectorNegate(plane.normal, plane.normal);
plane.dist *= -1;
PlaneClassify(&plane);
// find a matching plane if there is one
+ bestplaneindex = -1;
+ bestplanescore = 1048576.0f;
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ {
if(p->camera_entity == t->camera_entity)
- if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
- break;
- if (planeindex >= r_waterstate.maxwaterplanes)
- return; // nothing we can do, out of planes
+ {
+ planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
+ if (bestplaneindex < 0 || bestplanescore > planescore)
+ {
+ bestplaneindex = planeindex;
+ bestplanescore = planescore;
+ }
+ }
+ }
+ planeindex = bestplaneindex;
+ p = r_waterstate.waterplanes + planeindex;
- // if this triangle does not fit any known plane rendered this frame, add one
- if (planeindex >= r_waterstate.numwaterplanes)
+ // if this surface does not fit any known plane rendered this frame, add one
+ if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
{
// store the new plane
- r_waterstate.numwaterplanes++;
+ planeindex = r_waterstate.numwaterplanes++;
+ p = r_waterstate.waterplanes + planeindex;
p->plane = plane;
// clear materialflags and pvs
p->materialflags = 0;
p->pvsvalid = false;
p->camera_entity = t->camera_entity;
- VectorCopy(surface->mins, p->mins);
- VectorCopy(surface->maxs, p->maxs);
+ VectorCopy(mins, p->mins);
+ VectorCopy(maxs, p->maxs);
}
else
{
- // merge mins/maxs
- p->mins[0] = min(p->mins[0], surface->mins[0]);
- p->mins[1] = min(p->mins[1], surface->mins[1]);
- p->mins[2] = min(p->mins[2], surface->mins[2]);
- p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
- p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
- p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
+ // merge mins/maxs when we're adding this surface to the plane
+ p->mins[0] = min(p->mins[0], mins[0]);
+ p->mins[1] = min(p->mins[1], mins[1]);
+ p->mins[2] = min(p->mins[2], mins[2]);
+ p->maxs[0] = max(p->maxs[0], maxs[0]);
+ p->maxs[1] = max(p->maxs[1], maxs[1]);
+ p->maxs[2] = max(p->maxs[2], maxs[2]);
}
// merge this surface's materialflags into the waterplane
p->materialflags |= t->currentmaterialflags;
if(!(p->materialflags & MATERIALFLAG_CAMERA))
{
// merge this surface's PVS into the waterplane
- VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
&& r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
{
}
}
- R_AnimCache_CacheVisibleEntities();
- if (r_timereport_active)
- R_TimeReport("animation");
-
R_Shadow_PrepareLights();
if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
R_Shadow_PrepareModelShadows();
Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
break;
case Q3TCMOD_ROTATE:
+ f = tcmod->parms[0] * rsurface.shadertime;
Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
- Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
+ Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
break;
case Q3TCMOD_SCALE:
t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
else if (t->currentalpha < 1)
t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
+ // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
+ if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
+ t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
if (rsurface.ent_flags & RENDER_DOUBLESIDED)
t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))