handle invalidate of rh cache for dynamic textures/models

master
Lee Salzman 2012-09-17 02:12:51 +03:00
parent 79911ce359
commit d876e8a24a
8 changed files with 158 additions and 27 deletions

View File

@ -288,6 +288,7 @@ shader 0 "nocolor" [
worldshader = [
stype = 1
if (>= (strstr $arg1 "env") 0) [stype = (+ $stype 2)]
if (>= (strstr $arg1 "pulse") 0) [stype = (+ $stype 0x10)]
loop i 3 [
variantshader (? (= $i 2) (+ $stype 4) $stype) $arg1 (- $i 1) [
@(if (>= $numargs 5) [result $arg5])
@ -373,7 +374,7 @@ defershader 1 "glowworld" [
] [] [uniform sampler2D glowmap;]
]
defershader 1 "pulseworld" [
defershader 0x11 "pulseworld" [
defuniformparam "pulsespeed" 1 // pulse frequency (Hz)
worldshader "pulseworld" [
pulse = abs(fract(millis.x * pulsespeed.x)*2.0 - 1.0);
@ -383,7 +384,7 @@ defershader 1 "pulseworld" [
] [] [uniform vec4 millis; varying float pulse;] [uniform sampler2D decal;]
]
defershader 1 "pulseglowworld" [
defershader 0x11 "pulseglowworld" [
defuniformparam "glowcolor" 1 1 1 // glow color
defuniformparam "pulseglowspeed" 1 // pulse frequency (Hz)
defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color
@ -447,6 +448,7 @@ bumpvariantshader = [
stype = (? (btopt "e") 3 1)
srow = -1
if (btopt "G") [
stype = (+ $stype 0x10)
defuniformparam "glowcolor" 1 1 1 // glow color
defuniformparam "pulseglowspeed" 1 // pulse frequency (Hz)
defuniformparam "pulseglowcolor" 0 0 0 // pulse glow color

View File

@ -432,6 +432,7 @@ extern void findshadowvas();
extern void findshadowmms();
extern void renderrsmgeom();
extern int dynamicshadowvabounds(int mask, vec &bbmin, vec &bbmax);
extern void rendershadowmapworld();
extern void batchshadowmapmodels();
@ -698,6 +699,7 @@ extern void clearbatchedmapmodels();
extern void preloadmodelshaders();
extern void preloadusedmapmodels(bool msg = false, bool bih = false);
extern int batcheddynamicmodels();
extern int batcheddynamicmodelbounds(int mask, vec &bbmin, vec &bbmax);
// renderparticles
extern void particleinit();

View File

@ -132,7 +132,7 @@ struct vtxarray
ushort minvert, maxvert; // DRE info
elementset *eslist; // List of element indices sets (range) per texture
materialsurface *matbuf; // buffer of material surfaces
int verts, tris, texs, blendtris, blends, alphabacktris, alphaback, alphafronttris, alphafront, refracttris, refract, texmask, sky, matsurfs, matmask, distance, rdistance;
int verts, tris, texs, blendtris, blends, alphabacktris, alphaback, alphafronttris, alphafront, refracttris, refract, texmask, sky, matsurfs, matmask, distance, rdistance, dyntexs;
ivec o;
int size; // location and size of cube.
ivec geommin, geommax; // BB of geom

View File

@ -426,9 +426,12 @@ struct vacollect : verthash
}
va->texmask = 0;
va->dyntexs = 0;
loopi(va->texs+va->blends+va->alphaback+va->alphafront+va->refract)
{
Slot &slot = *lookupvslot(va->eslist[i].texture, false).slot;
VSlot &vslot = lookupvslot(va->eslist[i].texture, false);
if(vslot.isdynamic()) va->dyntexs++;
Slot &slot = *vslot.slot;
loopvj(slot.sts) va->texmask |= 1<<slot.sts[j].type;
if(slot.shader->type&SHADER_ENVMAP) va->texmask |= 1<<TEX_ENVMAP;
}

View File

@ -3081,6 +3081,10 @@ struct radiancehints
void clearcache() { bounds = -1e16f; }
} splits[RH_MAXSPLITS];
vec dynmin, dynmax, prevdynmin, prevdynmax;
radiancehints() : dynmin(1e16f, 1e16f, 1e16f), dynmax(-1e16f, -1e16f, -1e16f), prevdynmin(1e16f, 1e16f, 1e16f), prevdynmax(-1e16f, -1e16f, -1e16f) {}
void setup();
void updatesplitdist();
void bindparams();
@ -4136,13 +4140,23 @@ void radiancehints::renderslices()
float cellradius = split.bounds/rhgrid, step = 2*cellradius;
GLOBALPARAM(rhspread, (cellradius));
vec cmin, cmax, bmin(1e16f, 1e16f, 1e16f), bmax(-1e16f, -1e16f, -1e16f);
vec cmin, cmax, bmin(1e16f, 1e16f, 1e16f), bmax(-1e16f, -1e16f, -1e16f), dmin(1e16f, 1e16f, 1e16f), dmax(-1e16f, -1e16f, -1e16f);
loopk(3)
{
cmin[k] = floor((worldmin[k] - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds;
cmax[k] = ceil((worldmax[k] - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds;
}
if(prevdynmin.z < prevdynmax.z) loopk(3)
{
dmin[k] = min(dmin[k], (float)floor((prevdynmin[k] - gidist - cellradius - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds);
dmax[k] = max(dmax[k], (float)ceil((prevdynmax[k] + gidist + cellradius - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds);
}
if(dynmin.z < dynmax.z) loopk(3)
{
dmin[k] = min(dmin[k], (float)floor((dynmin[k] - gidist - cellradius - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds);
dmax[k] = max(dmax[k], (float)ceil((dynmax[k] + gidist + cellradius - (split.center[k] - split.bounds))/step)*step + split.center[k] - split.bounds);
}
if(rhborder && i + 1 < rhsplits)
{
GLOBALPARAM(bordercenter, (0.5f, 0.5f, float(i+1 + 0.5f)/rhsplits));
@ -4273,6 +4287,53 @@ void radiancehints::renderslices()
glEnd();
}
if(z > dmin.z && z < dmax.z)
{
float dx1 = max(px1, dmin.x), dx2 = min(px2, dmax.x),
dy1 = max(py1, dmin.y), dy2 = min(py2, dmax.y);
if(dx1 < dx2 && dy1 < dy2)
{
float dvx1 = -1 + rhborder*2.0f/(rhgrid+2) + 2*rhgrid/float(rhgrid+2*rhborder)*(dx1 - x1)/(x2 - x1),
dvx2 = 1 - rhborder*2.0f/(rhgrid+2) + 2*rhgrid/float(rhgrid+2*rhborder)*(dx2 - x2)/(x2 - x1),
dvy1 = -1 + rhborder*2.0f/(rhgrid+2) + 2*rhgrid/float(rhgrid+2*rhborder)*(dy1 - y1)/(y2 - y1),
dvy2 = 1 - rhborder*2.0f/(rhgrid+2) + 2*rhgrid/float(rhgrid+2*rhborder)*(dy2 - y2)/(y2 - y1),
dtx1 = (dx1 + split.center.x - split.cached.x)*split.scale.x + split.offset.x,
dtx2 = (dx2 + split.center.x - split.cached.x)*split.scale.x + split.offset.x,
dty1 = (dy1 + split.center.y - split.cached.y)*split.scale.y + split.offset.y,
dty2 = (dy2 + split.center.y - split.cached.y)*split.scale.y + split.offset.y,
dz = (z + split.center.z - split.cached.z)*split.scale.z + split.offset.z;
if(dx1 != px1 || dx2 != px2 || dy1 != py1 || dy2 != py2)
{
SETSHADER(radiancehintscached);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord3f(dtx2, dty1, dz); glVertex2f(dvx2, dvy1);
glTexCoord3f(ptx2, pty1, pz); glVertex2f(pvx2, pvy1);
glTexCoord3f(dtx1, dty1, dz); glVertex2f(dvx1, dvy1);
glTexCoord3f(ptx1, pty1, pz); glVertex2f(pvx1, pvy1);
glTexCoord3f(dtx1, dty2, dz); glVertex2f(dvx1, dvy2);
glTexCoord3f(ptx1, pty2, pz); glVertex2f(pvx1, pvy2);
glTexCoord3f(dtx2, dty2, dz); glVertex2f(dvx2, dvy2);
glTexCoord3f(ptx2, pty2, pz); glVertex2f(pvx2, pvy2);
glTexCoord3f(dtx2, dty1, dz); glVertex2f(dvx2, dvy1);
glTexCoord3f(ptx2, pty1, pz); glVertex2f(pvx2, pvy1);
glEnd();
}
radiancehintsshader->set();
glBegin(GL_TRIANGLE_STRIP);
glTexCoord3f(dx2, dy1, z); glVertex2f(dvx2, dvy1);
glTexCoord3f(dx1, dy1, z); glVertex2f(dvx1, dvy1);
glTexCoord3f(dx2, dy2, z); glVertex2f(dvx2, dvy2);
glTexCoord3f(dx1, dy2, z); glVertex2f(dvx1, dvy2);
glEnd();
continue;
}
}
SETSHADER(radiancehintscached);
glBegin(GL_TRIANGLE_STRIP);
@ -4309,13 +4370,32 @@ void renderradiancehints()
if(!rhinoq) timer_begin(TIMER_RH);
rh.setup();
rsm.setup();
if(!rhcache || !rh.allcached())
shadowmapping = SM_REFLECT;
shadowside = 0;
shadoworigin = vec(0, 0, 0);
shadowdir = rsm.lightview;
shadowbias = rsm.lightview.project_bb(worldmin, worldmax);
shadowradius = fabs(rsm.lightview.project_bb(worldmax, worldmin));
findshadowvas();
findshadowmms();
shadowmaskbatchedmodels(false);
batchshadowmapmodels();
rh.prevdynmin = rh.dynmin;
rh.prevdynmax = rh.dynmax;
rh.dynmin = vec(1e16f, 1e16f, 1e16f);
rh.dynmax = vec(-1e16f, -1e16f, -1e16f);
dynamicshadowvabounds(1<<shadowside, rh.dynmin, rh.dynmax);
batcheddynamicmodelbounds(1<<shadowside, rh.dynmin, rh.dynmax);
if(!rhcache || rh.prevdynmin.z < rh.prevdynmax.z || rh.dynmin.z < rh.dynmax.z || !rh.allcached())
{
if(rhinoq) glFlush();
rsm.setup();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(rsm.proj.v);
@ -4325,33 +4405,15 @@ void renderradiancehints()
glBindFramebuffer_(GL_FRAMEBUFFER_EXT, rsmfbo);
shadowmapping = SM_REFLECT;
shadoworigin = vec(0, 0, 0);
shadowdir = rsm.lightview;
shadowbias = rsm.lightview.project_bb(worldmin, worldmax);
shadowradius = fabs(rsm.lightview.project_bb(worldmax, worldmin));
GLOBALPARAM(rsmdir, (-rsm.lightview.x, -rsm.lightview.y, -rsm.lightview.z));
findshadowvas();
findshadowmms();
shadowmaskbatchedmodels(false);
batchshadowmapmodels();
glViewport(0, 0, rsmsize, rsmsize);
glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
shadowside = 0;
renderrsmgeom();
rendermodelbatches();
clearbatchedmapmodels();
shadowmapping = 0;
rh.renderslices();
glMatrixMode(GL_PROJECTION);
@ -4366,6 +4428,10 @@ void renderradiancehints()
}
}
clearbatchedmapmodels();
shadowmapping = 0;
if(!rhinoq) timer_end(TIMER_RH);
}

View File

@ -636,6 +636,39 @@ int batcheddynamicmodels()
return visible;
}
int batcheddynamicmodelbounds(int mask, vec &bbmin, vec &bbmax)
{
int vis = 0;
loopv(batchedmodels)
{
batchedmodel &b = batchedmodels[i];
if(b.flags&MDL_MAPMODEL) break;
if(b.visible&mask)
{
bbmin.min(vec(b.center).sub(b.radius));
bbmax.max(vec(b.center).add(b.radius));
++vis;
}
}
loopv(batches)
{
modelbatch &b = batches[i];
if(!(b.flags&MDL_MAPMODEL) || b.batched < 0 || !b.m->animated()) continue;
for(int j = b.batched; j >= 0;)
{
batchedmodel &bm = batchedmodels[j];
j = bm.next;
if(bm.visible&mask)
{
bbmin.min(vec(bm.center).sub(bm.radius));
bbmax.max(vec(bm.center).add(bm.radius));
++vis;
}
}
}
return vis;
}
void rendermodelbatches()
{
loopv(batches)

View File

@ -1886,6 +1886,21 @@ void rendergeom()
}
}
int dynamicshadowvabounds(int mask, vec &bbmin, vec &bbmax)
{
int vis = 0;
for(vtxarray *va = shadowva; va; va = va->rnext)
{
if(va->shadowmask&mask && va->dyntexs)
{
bbmin.min(va->geommin.tovec());
bbmax.max(va->geommax.tovec());
vis++;
}
}
return vis;
}
void renderrsmgeom()
{
glEnableClientState(GL_VERTEX_ARRAY);

View File

@ -239,6 +239,7 @@ enum
SHADER_ENVMAP = 1<<1,
SHADER_REFRACT = 1<<2,
SHADER_OPTION = 1<<3,
SHADER_DYNAMIC = 1<<4,
SHADER_INVALID = 1<<8,
SHADER_DEFERRED = 1<<9
@ -315,6 +316,8 @@ struct Shader
return (detailshader->variants[row][0]->type&SHADER_OPTION)!=0;
}
bool isdynamic() const { return (type&SHADER_DYNAMIC)!=0; }
void setvariant_(int col, int row, Shader *fallbackshader)
{
Shader *s = fallbackshader;
@ -666,6 +669,8 @@ struct VSlot
{
linked = false;
}
bool isdynamic() const;
};
struct Slot
@ -727,6 +732,11 @@ inline void VSlot::addvariant(Slot *slot)
}
}
inline bool VSlot::isdynamic() const
{
return scrollS || scrollT || slot->shader->isdynamic();
}
struct MSlot : Slot, VSlot
{
MSlot() : VSlot(this) {}