handle invalidate of rh cache for dynamic textures/models
parent
79911ce359
commit
d876e8a24a
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {}
|
||||
|
|
Loading…
Reference in New Issue