From d876e8a24ae2727b8de01e7b5560124a6f5e607b Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Mon, 17 Sep 2012 02:12:51 +0300 Subject: [PATCH] handle invalidate of rh cache for dynamic textures/models --- data/glsl.cfg | 6 +- src/engine/engine.h | 2 + src/engine/octa.h | 2 +- src/engine/octarender.cpp | 5 +- src/engine/rendergl.cpp | 112 +++++++++++++++++++++++++++++-------- src/engine/rendermodel.cpp | 33 +++++++++++ src/engine/renderva.cpp | 15 +++++ src/engine/texture.h | 10 ++++ 8 files changed, 158 insertions(+), 27 deletions(-) diff --git a/data/glsl.cfg b/data/glsl.cfg index 6938554..c50350d 100644 --- a/data/glsl.cfg +++ b/data/glsl.cfg @@ -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 diff --git a/src/engine/engine.h b/src/engine/engine.h index 420c389..8df0e6b 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -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(); diff --git a/src/engine/octa.h b/src/engine/octa.h index c7de963..0598ecc 100644 --- a/src/engine/octa.h +++ b/src/engine/octa.h @@ -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 diff --git a/src/engine/octarender.cpp b/src/engine/octarender.cpp index a4cfb28..9bf75b8 100644 --- a/src/engine/octarender.cpp +++ b/src/engine/octarender.cpp @@ -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<type&SHADER_ENVMAP) va->texmask |= 1< 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<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) diff --git a/src/engine/renderva.cpp b/src/engine/renderva.cpp index 97c7ba9..05c67a7 100644 --- a/src/engine/renderva.cpp +++ b/src/engine/renderva.cpp @@ -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); diff --git a/src/engine/texture.h b/src/engine/texture.h index 1c8e76c..54d4ebf 100644 --- a/src/engine/texture.h +++ b/src/engine/texture.h @@ -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) {}