summaryrefslogtreecommitdiff
path: root/src/engine/renderva.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/renderva.cpp')
-rw-r--r--src/engine/renderva.cpp2856
1 files changed, 1428 insertions, 1428 deletions
diff --git a/src/engine/renderva.cpp b/src/engine/renderva.cpp
index cef5ac5..dc3dca1 100644
--- a/src/engine/renderva.cpp
+++ b/src/engine/renderva.cpp
@@ -4,13 +4,13 @@
static inline void drawtris(GLsizei numindices, const GLvoid *indices, ushort minvert, ushort maxvert)
{
- glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, numindices, GL_UNSIGNED_SHORT, indices);
- glde++;
+ glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, numindices, GL_UNSIGNED_SHORT, indices);
+ glde++;
}
static inline void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices)
{
- drawtris(numindices, indices, va->minvert, va->maxvert);
+ drawtris(numindices, indices, va->minvert, va->maxvert);
}
///////// view frustrum culling ///////////////////////
@@ -23,65 +23,65 @@ vtxarray *visibleva;
bool isfoggedsphere(float rad, const vec &cv)
{
- loopi(4) if(vfcP[i].dist(cv) < -rad) return true;
- float dist = vfcP[4].dist(cv);
- return dist < -rad || dist > vfcDfog + rad;
+ loopi(4) if(vfcP[i].dist(cv) < -rad) return true;
+ float dist = vfcP[4].dist(cv);
+ return dist < -rad || dist > vfcDfog + rad;
}
int isvisiblesphere(float rad, const vec &cv)
{
- int v = VFC_FULL_VISIBLE;
- float dist;
+ int v = VFC_FULL_VISIBLE;
+ float dist;
- loopi(5)
- {
- dist = vfcP[i].dist(cv);
- if(dist < -rad) return VFC_NOT_VISIBLE;
- if(dist < rad) v = VFC_PART_VISIBLE;
- }
+ loopi(5)
+ {
+ dist = vfcP[i].dist(cv);
+ if(dist < -rad) return VFC_NOT_VISIBLE;
+ if(dist < rad) v = VFC_PART_VISIBLE;
+ }
- dist -= vfcDfog;
- if(dist > rad) return VFC_FOGGED; //VFC_NOT_VISIBLE; // culling when fog is closer than size of world results in HOM
- if(dist > -rad) v = VFC_PART_VISIBLE;
+ dist -= vfcDfog;
+ if(dist > rad) return VFC_FOGGED; //VFC_NOT_VISIBLE; // culling when fog is closer than size of world results in HOM
+ if(dist > -rad) v = VFC_PART_VISIBLE;
- return v;
+ return v;
}
static inline int ishiddencube(const ivec &o, int size)
{
- loopi(5) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true;
- return false;
+ loopi(5) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true;
+ return false;
}
static inline int isfoggedcube(const ivec &o, int size)
{
- loopi(4) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true;
- float dist = o.dist(vfcP[4]);
- return dist < -vfcDfar[4]*size || dist > vfcDfog - vfcDnear[4]*size;
+ loopi(4) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true;
+ float dist = o.dist(vfcP[4]);
+ return dist < -vfcDfar[4]*size || dist > vfcDfog - vfcDnear[4]*size;
}
int isvisiblecube(const ivec &o, int size)
{
- int v = VFC_FULL_VISIBLE;
- float dist;
+ int v = VFC_FULL_VISIBLE;
+ float dist;
- loopi(5)
- {
- dist = o.dist(vfcP[i]);
- if(dist < -vfcDfar[i]*size) return VFC_NOT_VISIBLE;
- if(dist < -vfcDnear[i]*size) v = VFC_PART_VISIBLE;
- }
+ loopi(5)
+ {
+ dist = o.dist(vfcP[i]);
+ if(dist < -vfcDfar[i]*size) return VFC_NOT_VISIBLE;
+ if(dist < -vfcDnear[i]*size) v = VFC_PART_VISIBLE;
+ }
- dist -= vfcDfog;
- if(dist > -vfcDnear[4]*size) return VFC_FOGGED;
- if(dist > -vfcDfar[4]*size) v = VFC_PART_VISIBLE;
+ dist -= vfcDfog;
+ if(dist > -vfcDnear[4]*size) return VFC_FOGGED;
+ if(dist > -vfcDfar[4]*size) v = VFC_PART_VISIBLE;
- return v;
+ return v;
}
float vadist(vtxarray *va, const vec &p)
{
- return p.dist_to_bb(va->bbmin, va->bbmax);
+ return p.dist_to_bb(va->bbmin, va->bbmax);
}
#define VASORTSIZE 64
@@ -90,128 +90,128 @@ static vtxarray *vasort[VASORTSIZE];
void addvisibleva(vtxarray *va)
{
- float dist = vadist(va, camera1->o);
- va->distance = int(dist); /*cv.dist(camera1->o) - va->size*SQRT3/2*/
+ float dist = vadist(va, camera1->o);
+ va->distance = int(dist); /*cv.dist(camera1->o) - va->size*SQRT3/2*/
- int hash = clamp(int(dist*VASORTSIZE/worldsize), 0, VASORTSIZE-1);
- vtxarray **prev = &vasort[hash], *cur = vasort[hash];
+ int hash = clamp(int(dist*VASORTSIZE/worldsize), 0, VASORTSIZE-1);
+ vtxarray **prev = &vasort[hash], *cur = vasort[hash];
- while(cur && va->distance >= cur->distance)
- {
- prev = &cur->next;
- cur = cur->next;
- }
+ while(cur && va->distance >= cur->distance)
+ {
+ prev = &cur->next;
+ cur = cur->next;
+ }
- va->next = *prev;
- *prev = va;
+ va->next = *prev;
+ *prev = va;
}
void sortvisiblevas()
{
- visibleva = NULL;
- vtxarray **last = &visibleva;
- loopi(VASORTSIZE) if(vasort[i])
- {
- vtxarray *va = vasort[i];
- *last = va;
- while(va->next) va = va->next;
- last = &va->next;
- }
+ visibleva = NULL;
+ vtxarray **last = &visibleva;
+ loopi(VASORTSIZE) if(vasort[i])
+ {
+ vtxarray *va = vasort[i];
+ *last = va;
+ while(va->next) va = va->next;
+ last = &va->next;
+ }
}
void findvisiblevas(vector<vtxarray *> &vas, bool resetocclude = false)
{
- loopv(vas)
- {
- vtxarray &v = *vas[i];
- int prevvfc = resetocclude ? (int) VFC_NOT_VISIBLE : (int) v.curvfc;
- v.curvfc = isvisiblecube(v.o, v.size);
- if(v.curvfc!=VFC_NOT_VISIBLE)
- {
- addvisibleva(&v);
- if(v.children.length()) findvisiblevas(v.children, prevvfc>=VFC_NOT_VISIBLE);
- if(prevvfc>=VFC_NOT_VISIBLE)
- {
- v.occluded = !v.texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING;
- v.query = NULL;
- }
- }
- }
+ loopv(vas)
+ {
+ vtxarray &v = *vas[i];
+ int prevvfc = resetocclude ? (int) VFC_NOT_VISIBLE : (int) v.curvfc;
+ v.curvfc = isvisiblecube(v.o, v.size);
+ if(v.curvfc!=VFC_NOT_VISIBLE)
+ {
+ addvisibleva(&v);
+ if(v.children.length()) findvisiblevas(v.children, prevvfc>=VFC_NOT_VISIBLE);
+ if(prevvfc>=VFC_NOT_VISIBLE)
+ {
+ v.occluded = !v.texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING;
+ v.query = NULL;
+ }
+ }
+ }
}
void calcvfcD()
{
- loopi(5)
- {
- plane &p = vfcP[i];
- vfcDnear[i] = vfcDfar[i] = 0;
- loopk(3) if(p[k] > 0) vfcDfar[i] += p[k];
- else vfcDnear[i] += p[k];
- }
+ loopi(5)
+ {
+ plane &p = vfcP[i];
+ vfcDnear[i] = vfcDfar[i] = 0;
+ loopk(3) if(p[k] > 0) vfcDfar[i] += p[k];
+ else vfcDnear[i] += p[k];
+ }
}
void setvfcP(float z, const vec &bbmin, const vec &bbmax)
{
- vec4 px = camprojmatrix.rowx(), py = camprojmatrix.rowy(), pz = camprojmatrix.rowz(), pw = camprojmatrix.roww();
- vfcP[0] = plane(vec4(pw).mul(-bbmin.x).add(px)).normalize(); // left plane
- vfcP[1] = plane(vec4(pw).mul(bbmax.x).sub(px)).normalize(); // right plane
- vfcP[2] = plane(vec4(pw).mul(-bbmin.y).add(py)).normalize(); // bottom plane
- vfcP[3] = plane(vec4(pw).mul(bbmax.y).sub(py)).normalize(); // top plane
- vfcP[4] = plane(vec4(pw).add(pz)).normalize(); // near/far planes
- if(z >= 0) loopi(5) vfcP[i].reflectz(z);
+ vec4 px = camprojmatrix.rowx(), py = camprojmatrix.rowy(), pz = camprojmatrix.rowz(), pw = camprojmatrix.roww();
+ vfcP[0] = plane(vec4(pw).mul(-bbmin.x).add(px)).normalize(); // left plane
+ vfcP[1] = plane(vec4(pw).mul(bbmax.x).sub(px)).normalize(); // right plane
+ vfcP[2] = plane(vec4(pw).mul(-bbmin.y).add(py)).normalize(); // bottom plane
+ vfcP[3] = plane(vec4(pw).mul(bbmax.y).sub(py)).normalize(); // top plane
+ vfcP[4] = plane(vec4(pw).add(pz)).normalize(); // near/far planes
+ if(z >= 0) loopi(5) vfcP[i].reflectz(z);
- vfcDfog = fog;
- calcvfcD();
+ vfcDfog = fog;
+ calcvfcD();
}
plane oldvfcP[5];
void savevfcP()
{
- memcpy(oldvfcP, vfcP, sizeof(vfcP));
+ memcpy(oldvfcP, vfcP, sizeof(vfcP));
}
void restorevfcP()
{
- memcpy(vfcP, oldvfcP, sizeof(vfcP));
- calcvfcD();
+ memcpy(vfcP, oldvfcP, sizeof(vfcP));
+ calcvfcD();
}
void visiblecubes(bool cull)
{
- memclear(vasort);
-
- if(cull)
- {
- setvfcP();
- findvisiblevas(varoot);
- sortvisiblevas();
- }
- else
- {
- memclear(vfcP);
- vfcDfog = 1000000;
- memclear(vfcDnear);
- memclear(vfcDfar);
- visibleva = NULL;
- loopv(valist)
- {
- vtxarray *va = valist[i];
- va->distance = 0;
- va->curvfc = VFC_FULL_VISIBLE;
- va->occluded = !va->texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING;
- va->query = NULL;
- va->next = visibleva;
- visibleva = va;
- }
- }
+ memclear(vasort);
+
+ if(cull)
+ {
+ setvfcP();
+ findvisiblevas(varoot);
+ sortvisiblevas();
+ }
+ else
+ {
+ memclear(vfcP);
+ vfcDfog = 1000000;
+ memclear(vfcDnear);
+ memclear(vfcDfar);
+ visibleva = NULL;
+ loopv(valist)
+ {
+ vtxarray *va = valist[i];
+ va->distance = 0;
+ va->curvfc = VFC_FULL_VISIBLE;
+ va->occluded = !va->texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING;
+ va->query = NULL;
+ va->next = visibleva;
+ visibleva = va;
+ }
+ }
}
static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2)
{
- int size = va->size + margin;
- return v.x>=va->o.x-margin && v.y>=va->o.y-margin && v.z>=va->o.z-margin &&
- v.x<=va->o.x+size && v.y<=va->o.y+size && v.z<=va->o.z+size;
+ int size = va->size + margin;
+ return v.x>=va->o.x-margin && v.y>=va->o.y-margin && v.z>=va->o.z-margin &&
+ v.x<=va->o.x+size && v.y<=va->o.y+size && v.z<=va->o.z+size;
}
///////// occlusion queries /////////////
@@ -221,37 +221,37 @@ static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2)
struct queryframe
{
- int cur, max;
- occludequery queries[MAXQUERY];
-
- queryframe() : cur(0), max(0) {}
-
- void flip() { loopi(cur) queries[i].owner = NULL; cur = 0; }
-
- occludequery *newquery(void *owner)
- {
- if(cur >= max)
- {
- if(max >= MAXQUERY) return NULL;
- glGenQueries_(1, &queries[max++].id);
- }
- occludequery *query = &queries[cur++];
- query->owner = owner;
- query->fragments = -1;
- return query;
- }
-
- void reset() { loopi(max) queries[i].owner = NULL; }
-
- void cleanup()
- {
- loopi(max)
- {
- glDeleteQueries_(1, &queries[i].id);
- queries[i].owner = NULL;
- }
- cur = max = 0;
- }
+ int cur, max;
+ occludequery queries[MAXQUERY];
+
+ queryframe() : cur(0), max(0) {}
+
+ void flip() { loopi(cur) queries[i].owner = NULL; cur = 0; }
+
+ occludequery *newquery(void *owner)
+ {
+ if(cur >= max)
+ {
+ if(max >= MAXQUERY) return NULL;
+ glGenQueries_(1, &queries[max++].id);
+ }
+ occludequery *query = &queries[cur++];
+ query->owner = owner;
+ query->fragments = -1;
+ return query;
+ }
+
+ void reset() { loopi(max) queries[i].owner = NULL; }
+
+ void cleanup()
+ {
+ loopi(max)
+ {
+ glDeleteQueries_(1, &queries[i].id);
+ queries[i].owner = NULL;
+ }
+ cur = max = 0;
+ }
};
static queryframe queryframes[MAXQUERYFRAMES];
@@ -259,28 +259,28 @@ static uint flipquery = 0;
int getnumqueries()
{
- return queryframes[flipquery].cur;
+ return queryframes[flipquery].cur;
}
void flipqueries()
{
- flipquery = (flipquery + 1) % MAXQUERYFRAMES;
- queryframes[flipquery].flip();
+ flipquery = (flipquery + 1) % MAXQUERYFRAMES;
+ queryframes[flipquery].flip();
}
occludequery *newquery(void *owner)
{
- return queryframes[flipquery].newquery(owner);
+ return queryframes[flipquery].newquery(owner);
}
void resetqueries()
{
- loopi(MAXQUERYFRAMES) queryframes[i].reset();
+ loopi(MAXQUERYFRAMES) queryframes[i].reset();
}
void clearqueries()
{
- loopi(MAXQUERYFRAMES) queryframes[i].cleanup();
+ loopi(MAXQUERYFRAMES) queryframes[i].cleanup();
}
VAR(oqfrags, 0, 8, 64);
@@ -288,107 +288,107 @@ VAR(oqwait, 0, 1, 1);
void startquery(occludequery *query)
{
- glBeginQuery_(GL_SAMPLES_PASSED, query->id);
+ glBeginQuery_(GL_SAMPLES_PASSED, query->id);
}
void endquery(occludequery *query)
{
- glEndQuery_(GL_SAMPLES_PASSED);
+ glEndQuery_(GL_SAMPLES_PASSED);
}
bool checkquery(occludequery *query, bool nowait)
{
- GLuint fragments;
- if(query->fragments >= 0) fragments = query->fragments;
- else
- {
- if(nowait || !oqwait)
- {
- GLint avail;
- glGetQueryObjectiv_(query->id, GL_QUERY_RESULT_AVAILABLE, &avail);
- if(!avail) return false;
- }
- glGetQueryObjectuiv_(query->id, GL_QUERY_RESULT, &fragments);
- query->fragments = fragments;
- }
- return fragments < uint(oqfrags);
+ GLuint fragments;
+ if(query->fragments >= 0) fragments = query->fragments;
+ else
+ {
+ if(nowait || !oqwait)
+ {
+ GLint avail;
+ glGetQueryObjectiv_(query->id, GL_QUERY_RESULT_AVAILABLE, &avail);
+ if(!avail) return false;
+ }
+ glGetQueryObjectuiv_(query->id, GL_QUERY_RESULT, &fragments);
+ query->fragments = fragments;
+ }
+ return fragments < uint(oqfrags);
}
static GLuint bbvbo = 0, bbebo = 0;
static void setupbb()
{
- if(!bbvbo)
- {
- glGenBuffers_(1, &bbvbo);
- gle::bindvbo(bbvbo);
- vec verts[8];
- loopi(8) verts[i] = vec(i&1, (i>>1)&1, (i>>2)&1);
- glBufferData_(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
- gle::clearvbo();
- }
- if(!bbebo)
- {
- glGenBuffers_(1, &bbebo);
- gle::bindebo(bbebo);
- GLushort tris[3*2*6];
- #define GENFACEORIENT(orient, v0, v1, v2, v3) do { \
- int offset = orient*3*2; \
- tris[offset + 0] = v0; \
- tris[offset + 1] = v1; \
- tris[offset + 2] = v2; \
- tris[offset + 3] = v0; \
- tris[offset + 4] = v2; \
- tris[offset + 5] = v3; \
- } while(0);
- #define GENFACEVERT(orient, vert, ox,oy,oz, rx,ry,rz) (ox | oy | oz)
- GENFACEVERTS(0, 1, 0, 2, 0, 4, , , , , , )
- #undef GENFACEORIENT
- #undef GENFACEVERT
- glBufferData_(GL_ELEMENT_ARRAY_BUFFER, sizeof(tris), tris, GL_STATIC_DRAW);
- gle::clearebo();
- }
+ if(!bbvbo)
+ {
+ glGenBuffers_(1, &bbvbo);
+ gle::bindvbo(bbvbo);
+ vec verts[8];
+ loopi(8) verts[i] = vec(i&1, (i>>1)&1, (i>>2)&1);
+ glBufferData_(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+ gle::clearvbo();
+ }
+ if(!bbebo)
+ {
+ glGenBuffers_(1, &bbebo);
+ gle::bindebo(bbebo);
+ GLushort tris[3*2*6];
+ #define GENFACEORIENT(orient, v0, v1, v2, v3) do { \
+ int offset = orient*3*2; \
+ tris[offset + 0] = v0; \
+ tris[offset + 1] = v1; \
+ tris[offset + 2] = v2; \
+ tris[offset + 3] = v0; \
+ tris[offset + 4] = v2; \
+ tris[offset + 5] = v3; \
+ } while(0);
+ #define GENFACEVERT(orient, vert, ox,oy,oz, rx,ry,rz) (ox | oy | oz)
+ GENFACEVERTS(0, 1, 0, 2, 0, 4, , , , , , )
+ #undef GENFACEORIENT
+ #undef GENFACEVERT
+ glBufferData_(GL_ELEMENT_ARRAY_BUFFER, sizeof(tris), tris, GL_STATIC_DRAW);
+ gle::clearebo();
+ }
}
static void cleanupbb()
{
- if(bbvbo) { glDeleteBuffers_(1, &bbvbo); bbvbo = 0; }
- if(bbebo) { glDeleteBuffers_(1, &bbebo); bbebo = 0; }
+ if(bbvbo) { glDeleteBuffers_(1, &bbvbo); bbvbo = 0; }
+ if(bbebo) { glDeleteBuffers_(1, &bbebo); bbebo = 0; }
}
void startbb(bool mask)
{
- setupbb();
- gle::bindvbo(bbvbo);
- gle::bindebo(bbebo);
- gle::vertexpointer(sizeof(vec), (const vec *)0);
- gle::enablevertex();
- SETSHADER(bbquery);
- if(mask)
- {
- glDepthMask(GL_FALSE);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- }
+ setupbb();
+ gle::bindvbo(bbvbo);
+ gle::bindebo(bbebo);
+ gle::vertexpointer(sizeof(vec), (const vec *)0);
+ gle::enablevertex();
+ SETSHADER(bbquery);
+ if(mask)
+ {
+ glDepthMask(GL_FALSE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
}
void endbb(bool mask)
{
- gle::disablevertex();
- gle::clearvbo();
- gle::clearebo();
- if(mask)
- {
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- }
+ gle::disablevertex();
+ gle::clearvbo();
+ gle::clearebo();
+ if(mask)
+ {
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
}
void drawbb(const ivec &bo, const ivec &br)
{
- LOCALPARAMF(bborigin, bo.x, bo.y, bo.z);
- LOCALPARAMF(bbsize, br.x, br.y, br.z);
- glDrawRangeElements_(GL_TRIANGLES, 0, 8-1, 3*2*6, GL_UNSIGNED_SHORT, (ushort *)0);
- xtraverts += 8;
+ LOCALPARAMF(bborigin, bo.x, bo.y, bo.z);
+ LOCALPARAMF(bbsize, br.x, br.y, br.z);
+ glDrawRangeElements_(GL_TRIANGLES, 0, 8-1, 3*2*6, GL_UNSIGNED_SHORT, (ushort *)0);
+ xtraverts += 8;
}
extern int octaentsize;
@@ -397,214 +397,214 @@ static octaentities *visiblemms, **lastvisiblemms;
static inline bool insideoe(const octaentities *oe, const vec &v, int margin = 1)
{
- return v.x>=oe->bbmin.x-margin && v.y>=oe->bbmin.y-margin && v.z>=oe->bbmin.z-margin &&
- v.x<=oe->bbmax.x+margin && v.y<=oe->bbmax.y+margin && v.z<=oe->bbmax.z+margin;
+ return v.x>=oe->bbmin.x-margin && v.y>=oe->bbmin.y-margin && v.z>=oe->bbmin.z-margin &&
+ v.x<=oe->bbmax.x+margin && v.y<=oe->bbmax.y+margin && v.z<=oe->bbmax.z+margin;
}
void findvisiblemms(const vector<extentity *> &ents, bool doquery)
{
- visiblemms = NULL;
- lastvisiblemms = &visiblemms;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(va->mapmodels.empty() || va->curvfc >= VFC_FOGGED || va->occluded >= OCCLUDE_BB) continue;
- loopv(va->mapmodels)
- {
- octaentities *oe = va->mapmodels[i];
- if(isfoggedcube(oe->o, oe->size)) continue;
-
- bool occluded = doquery && oe->query && oe->query->owner == oe && checkquery(oe->query);
- if(occluded)
- {
- oe->distance = -1;
-
- oe->next = NULL;
- *lastvisiblemms = oe;
- lastvisiblemms = &oe->next;
- }
- else
- {
- int visible = 0;
- loopv(oe->mapmodels)
- {
- extentity &e = *ents[oe->mapmodels[i]];
- if(e.flags&EF_NOVIS) continue;
- e.flags |= EF_RENDER;
- ++visible;
- }
- if(!visible) continue;
-
- oe->distance = int(camera1->o.dist_to_bb(oe->o, oe->size));
-
- octaentities **prev = &visiblemms, *cur = visiblemms;
- while(cur && cur->distance >= 0 && oe->distance > cur->distance)
- {
- prev = &cur->next;
- cur = cur->next;
- }
-
- if(*prev == NULL) lastvisiblemms = &oe->next;
- oe->next = *prev;
- *prev = oe;
- }
- }
- }
+ visiblemms = NULL;
+ lastvisiblemms = &visiblemms;
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(va->mapmodels.empty() || va->curvfc >= VFC_FOGGED || va->occluded >= OCCLUDE_BB) continue;
+ loopv(va->mapmodels)
+ {
+ octaentities *oe = va->mapmodels[i];
+ if(isfoggedcube(oe->o, oe->size)) continue;
+
+ bool occluded = doquery && oe->query && oe->query->owner == oe && checkquery(oe->query);
+ if(occluded)
+ {
+ oe->distance = -1;
+
+ oe->next = NULL;
+ *lastvisiblemms = oe;
+ lastvisiblemms = &oe->next;
+ }
+ else
+ {
+ int visible = 0;
+ loopv(oe->mapmodels)
+ {
+ extentity &e = *ents[oe->mapmodels[i]];
+ if(e.flags&EF_NOVIS) continue;
+ e.flags |= EF_RENDER;
+ ++visible;
+ }
+ if(!visible) continue;
+
+ oe->distance = int(camera1->o.dist_to_bb(oe->o, oe->size));
+
+ octaentities **prev = &visiblemms, *cur = visiblemms;
+ while(cur && cur->distance >= 0 && oe->distance > cur->distance)
+ {
+ prev = &cur->next;
+ cur = cur->next;
+ }
+
+ if(*prev == NULL) lastvisiblemms = &oe->next;
+ oe->next = *prev;
+ *prev = oe;
+ }
+ }
+ }
}
VAR(oqmm, 0, 4, 8);
void rendermapmodel(extentity &e)
{
- int anim = ANIM_MAPMODEL|ANIM_LOOP, basetime = 0;
- mapmodelinfo *mmi = getmminfo(e.attr2);
- if(mmi) rendermodel(&e.light, mmi->name, anim, e.o, e.attr1, 0, MDL_CULL_VFC | MDL_CULL_DIST | MDL_DYNLIGHT, NULL, NULL, basetime);
+ int anim = ANIM_MAPMODEL|ANIM_LOOP, basetime = 0;
+ mapmodelinfo *mmi = getmminfo(e.attr2);
+ if(mmi) rendermodel(&e.light, mmi->name, anim, e.o, e.attr1, 0, MDL_CULL_VFC | MDL_CULL_DIST | MDL_DYNLIGHT, NULL, NULL, basetime);
}
vtxarray *reflectedva;
void renderreflectedmapmodels()
{
- const vector<extentity *> &ents = entities::getents();
-
- octaentities *mms = visiblemms;
- if(reflecting)
- {
- octaentities **lastmms = &mms;
- for(vtxarray *va = reflectedva; va; va = va->rnext)
- {
- if(va->mapmodels.empty() || va->distance > reflectdist) continue;
- loopv(va->mapmodels)
- {
- octaentities *oe = va->mapmodels[i];
- *lastmms = oe;
- lastmms = &oe->rnext;
- }
- }
- *lastmms = NULL;
- }
- for(octaentities *oe = mms; oe; oe = reflecting ? oe->rnext : oe->next) if(reflecting || oe->distance >= 0)
- {
- if(reflecting || refracting>0 ? oe->bbmax.z <= reflectz : oe->bbmin.z >= reflectz) continue;
- if(isfoggedcube(oe->o, oe->size)) continue;
- loopv(oe->mapmodels)
- {
- extentity &e = *ents[oe->mapmodels[i]];
- if(e.flags&(EF_NOVIS | EF_RENDER)) continue;
- e.flags |= EF_RENDER;
- }
- }
- if(mms)
- {
- startmodelbatches();
- for(octaentities *oe = mms; oe; oe = reflecting ? oe->rnext : oe->next)
- {
- loopv(oe->mapmodels)
- {
- extentity &e = *ents[oe->mapmodels[i]];
- if(!(e.flags&EF_RENDER)) continue;
- rendermapmodel(e);
- e.flags &= ~EF_RENDER;
- }
- }
- endmodelbatches();
- }
+ const vector<extentity *> &ents = entities::getents();
+
+ octaentities *mms = visiblemms;
+ if(reflecting)
+ {
+ octaentities **lastmms = &mms;
+ for(vtxarray *va = reflectedva; va; va = va->rnext)
+ {
+ if(va->mapmodels.empty() || va->distance > reflectdist) continue;
+ loopv(va->mapmodels)
+ {
+ octaentities *oe = va->mapmodels[i];
+ *lastmms = oe;
+ lastmms = &oe->rnext;
+ }
+ }
+ *lastmms = NULL;
+ }
+ for(octaentities *oe = mms; oe; oe = reflecting ? oe->rnext : oe->next) if(reflecting || oe->distance >= 0)
+ {
+ if(reflecting || refracting>0 ? oe->bbmax.z <= reflectz : oe->bbmin.z >= reflectz) continue;
+ if(isfoggedcube(oe->o, oe->size)) continue;
+ loopv(oe->mapmodels)
+ {
+ extentity &e = *ents[oe->mapmodels[i]];
+ if(e.flags&(EF_NOVIS | EF_RENDER)) continue;
+ e.flags |= EF_RENDER;
+ }
+ }
+ if(mms)
+ {
+ startmodelbatches();
+ for(octaentities *oe = mms; oe; oe = reflecting ? oe->rnext : oe->next)
+ {
+ loopv(oe->mapmodels)
+ {
+ extentity &e = *ents[oe->mapmodels[i]];
+ if(!(e.flags&EF_RENDER)) continue;
+ rendermapmodel(e);
+ e.flags &= ~EF_RENDER;
+ }
+ }
+ endmodelbatches();
+ }
}
void rendermapmodels()
{
- static int skipoq = 0;
- bool doquery = !drawtex && oqfrags && oqmm;
- const vector<extentity *> &ents = entities::getents();
- findvisiblemms(ents, doquery);
-
- startmodelbatches();
- for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0)
- {
- bool rendered = false;
- loopv(oe->mapmodels)
- {
- extentity &e = *ents[oe->mapmodels[i]];
- if(!(e.flags&EF_RENDER)) continue;
- if(!rendered)
- {
- rendered = true;
- oe->query = doquery && oe->distance>0 && !(++skipoq%oqmm) ? newquery(oe) : NULL;
- if(oe->query) startmodelquery(oe->query);
- }
- rendermapmodel(e);
- e.flags &= ~EF_RENDER;
- }
- if(rendered && oe->query) endmodelquery();
- }
- endmodelbatches();
-
- bool queried = true;
- for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0)
- {
- oe->query = doquery && !insideoe(oe, camera1->o) ? newquery(oe) : NULL;
- if(!oe->query) continue;
- if(queried)
- {
- startbb();
- queried = false;
- }
- startquery(oe->query);
- drawbb(oe->bbmin, ivec(oe->bbmax).sub(oe->bbmin));
- endquery(oe->query);
- }
- if(!queried)
- {
- endbb();
- }
+ static int skipoq = 0;
+ bool doquery = !drawtex && oqfrags && oqmm;
+ const vector<extentity *> &ents = entities::getents();
+ findvisiblemms(ents, doquery);
+
+ startmodelbatches();
+ for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0)
+ {
+ bool rendered = false;
+ loopv(oe->mapmodels)
+ {
+ extentity &e = *ents[oe->mapmodels[i]];
+ if(!(e.flags&EF_RENDER)) continue;
+ if(!rendered)
+ {
+ rendered = true;
+ oe->query = doquery && oe->distance>0 && !(++skipoq%oqmm) ? newquery(oe) : NULL;
+ if(oe->query) startmodelquery(oe->query);
+ }
+ rendermapmodel(e);
+ e.flags &= ~EF_RENDER;
+ }
+ if(rendered && oe->query) endmodelquery();
+ }
+ endmodelbatches();
+
+ bool queried = true;
+ for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0)
+ {
+ oe->query = doquery && !insideoe(oe, camera1->o) ? newquery(oe) : NULL;
+ if(!oe->query) continue;
+ if(queried)
+ {
+ startbb();
+ queried = false;
+ }
+ startquery(oe->query);
+ drawbb(oe->bbmin, ivec(oe->bbmax).sub(oe->bbmin));
+ endquery(oe->query);
+ }
+ if(!queried)
+ {
+ endbb();
+ }
}
static inline bool bbinsideva(const ivec &bo, const ivec &br, vtxarray *va)
{
- return bo.x >= va->bbmin.x && bo.y >= va->bbmin.y && bo.z >= va->bbmin.z &&
- br.x <= va->bbmax.x && br.y <= va->bbmax.y && br.z <= va->bbmax.z;
+ return bo.x >= va->bbmin.x && bo.y >= va->bbmin.y && bo.z >= va->bbmin.z &&
+ br.x <= va->bbmax.x && br.y <= va->bbmax.y && br.z <= va->bbmax.z;
}
static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ivec &o, int size)
{
- loopoctabox(o, size, bo, br)
- {
- ivec co(i, o, size);
- if(c[i].ext && c[i].ext->va)
- {
- vtxarray *va = c[i].ext->va;
- if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) continue;
- }
- if(c[i].children && bboccluded(bo, br, c[i].children, co, size>>1)) continue;
- return false;
- }
- return true;
+ loopoctabox(o, size, bo, br)
+ {
+ ivec co(i, o, size);
+ if(c[i].ext && c[i].ext->va)
+ {
+ vtxarray *va = c[i].ext->va;
+ if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) continue;
+ }
+ if(c[i].children && bboccluded(bo, br, c[i].children, co, size>>1)) continue;
+ return false;
+ }
+ return true;
}
bool bboccluded(const ivec &bo, const ivec &br)
{
- int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z);
- if(diff&~((1<<worldscale)-1)) return false;
- int scale = worldscale-1;
- if(diff&(1<<scale)) return bboccluded(bo, br, worldroot, ivec(0, 0, 0), 1<<scale);
- cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)];
- if(c->ext && c->ext->va)
- {
- vtxarray *va = c->ext->va;
- if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) return true;
- }
- scale--;
- while(c->children && !(diff&(1<<scale)))
- {
- c = &c->children[octastep(bo.x, bo.y, bo.z, scale)];
- if(c->ext && c->ext->va)
- {
- vtxarray *va = c->ext->va;
- if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) return true;
- }
- scale--;
- }
- if(c->children) return bboccluded(bo, br, c->children, ivec(bo).mask(~((2<<scale)-1)), 1<<scale);
- return false;
+ int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z);
+ if(diff&~((1<<worldscale)-1)) return false;
+ int scale = worldscale-1;
+ if(diff&(1<<scale)) return bboccluded(bo, br, worldroot, ivec(0, 0, 0), 1<<scale);
+ cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)];
+ if(c->ext && c->ext->va)
+ {
+ vtxarray *va = c->ext->va;
+ if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) return true;
+ }
+ scale--;
+ while(c->children && !(diff&(1<<scale)))
+ {
+ c = &c->children[octastep(bo.x, bo.y, bo.z, scale)];
+ if(c->ext && c->ext->va)
+ {
+ vtxarray *va = c->ext->va;
+ if(va->curvfc >= VFC_FOGGED || (va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va))) return true;
+ }
+ scale--;
+ }
+ if(c->children) return bboccluded(bo, br, c->children, ivec(bo).mask(~((2<<scale)-1)), 1<<scale);
+ return false;
}
VAR(outline, 0, 0, 1);
@@ -613,213 +613,213 @@ VAR(dtoutline, 0, 1, 1);
void renderoutline()
{
- notextureshader->set();
+ notextureshader->set();
- gle::enablevertex();
+ gle::enablevertex();
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- gle::color(vec::hexcolor(outlinecolour));
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ gle::color(vec::hexcolor(outlinecolour));
- enablepolygonoffset(GL_POLYGON_OFFSET_LINE);
+ enablepolygonoffset(GL_POLYGON_OFFSET_LINE);
- if(!dtoutline) glDisable(GL_DEPTH_TEST);
+ if(!dtoutline) glDisable(GL_DEPTH_TEST);
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(va->occluded >= OCCLUDE_BB) continue;
- if(!va->alphaback && !va->alphafront && (!va->texs || va->occluded >= OCCLUDE_GEOM)) continue;
+ vtxarray *prev = NULL;
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(va->occluded >= OCCLUDE_BB) continue;
+ if(!va->alphaback && !va->alphafront && (!va->texs || va->occluded >= OCCLUDE_GEOM)) continue;
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
+ if(!prev || va->vbuf != prev->vbuf)
+ {
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->ebuf);
+ const vertex *ptr = 0;
+ gle::vertexpointer(sizeof(vertex), ptr->pos.v);
+ }
- if(va->texs && va->occluded < OCCLUDE_GEOM)
- {
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
- }
- if(va->alphatris)
- {
- drawvatris(va, 3*va->alphatris, &va->edata[3*(va->tris + va->blendtris)]);
- xtravertsva += 3*va->alphatris;
- }
+ if(va->texs && va->occluded < OCCLUDE_GEOM)
+ {
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
+ }
+ if(va->alphatris)
+ {
+ drawvatris(va, 3*va->alphatris, &va->edata[3*(va->tris + va->blendtris)]);
+ xtravertsva += 3*va->alphatris;
+ }
- prev = va;
- }
+ prev = va;
+ }
- if(!dtoutline) glEnable(GL_DEPTH_TEST);
+ if(!dtoutline) glEnable(GL_DEPTH_TEST);
- disablepolygonoffset(GL_POLYGON_OFFSET_LINE);
+ disablepolygonoffset(GL_POLYGON_OFFSET_LINE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
+ gle::clearvbo();
+ gle::clearebo();
+ gle::disablevertex();
}
HVAR(blendbrushcolor, 0, 0x0000C0, 0xFFFFFF);
void renderblendbrush(GLuint tex, float x, float y, float w, float h)
{
- SETSHADER(blendbrush);
+ SETSHADER(blendbrush);
- gle::enablevertex();
+ gle::enablevertex();
- glDepthFunc(GL_LEQUAL);
+ glDepthFunc(GL_LEQUAL);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glBindTexture(GL_TEXTURE_2D, tex);
- gle::color(vec::hexcolor(blendbrushcolor), 0.25f);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ gle::color(vec::hexcolor(blendbrushcolor), 0.25f);
- LOCALPARAMF(texgenS, 1.0f/w, 0, 0, -x/w);
- LOCALPARAMF(texgenT, 0, 1.0f/h, 0, -y/h);
+ LOCALPARAMF(texgenS, 1.0f/w, 0, 0, -x/w);
+ LOCALPARAMF(texgenT, 0, 1.0f/h, 0, -y/h);
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue;
- if(va->o.x + va->size <= x || va->o.y + va->size <= y || va->o.x >= x + w || va->o.y >= y + h) continue;
+ vtxarray *prev = NULL;
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue;
+ if(va->o.x + va->size <= x || va->o.y + va->size <= y || va->o.x >= x + w || va->o.y >= y + h) continue;
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
+ if(!prev || va->vbuf != prev->vbuf)
+ {
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->ebuf);
+ const vertex *ptr = 0;
+ gle::vertexpointer(sizeof(vertex), ptr->pos.v);
+ }
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
- prev = va;
- }
+ prev = va;
+ }
- glDisable(GL_BLEND);
+ glDisable(GL_BLEND);
- glDepthFunc(GL_LESS);
+ glDepthFunc(GL_LESS);
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
+ gle::clearvbo();
+ gle::clearebo();
+ gle::disablevertex();
}
void rendershadowmapreceivers()
{
- SETSHADER(shadowmapreceiver);
+ SETSHADER(shadowmapreceiver);
- gle::enablevertex();
+ gle::enablevertex();
- glCullFace(GL_FRONT);
- glDepthMask(GL_FALSE);
- glDepthFunc(GL_GREATER);
+ glCullFace(GL_FRONT);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_GREATER);
- extern int ati_minmax_bug;
- if(!ati_minmax_bug) glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
+ extern int ati_minmax_bug;
+ if(!ati_minmax_bug) glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
- glEnable(GL_BLEND);
- glBlendEquation_(GL_MAX);
- glBlendFunc(GL_ONE, GL_ONE);
+ glEnable(GL_BLEND);
+ glBlendEquation_(GL_MAX);
+ glBlendFunc(GL_ONE, GL_ONE);
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->curvfc >= VFC_FOGGED || !isshadowmapreceiver(va)) continue;
+ vtxarray *prev = NULL;
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(!va->texs || va->curvfc >= VFC_FOGGED || !isshadowmapreceiver(va)) continue;
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
+ if(!prev || va->vbuf != prev->vbuf)
+ {
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->ebuf);
+ const vertex *ptr = 0;
+ gle::vertexpointer(sizeof(vertex), ptr->pos.v);
+ }
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
- prev = va;
- }
+ prev = va;
+ }
- glDisable(GL_BLEND);
- glBlendEquation_(GL_FUNC_ADD);
+ glDisable(GL_BLEND);
+ glBlendEquation_(GL_FUNC_ADD);
- glCullFace(GL_BACK);
- glDepthMask(GL_TRUE);
- glDepthFunc(GL_LESS);
+ glCullFace(GL_BACK);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LESS);
- if(!ati_minmax_bug) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ if(!ati_minmax_bug) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
+ gle::clearvbo();
+ gle::clearebo();
+ gle::disablevertex();
}
void renderdepthobstacles(const vec &bbmin, const vec &bbmax, float scale, float *ranges, int numranges)
{
- float scales[4] = { 0, 0, 0, 0 }, offsets[4] = { 0, 0, 0, 0 };
- if(numranges < 0)
- {
- SETSHADER(depthfxsplitworld);
-
- loopi(-numranges)
- {
- if(!i) scales[i] = 1.0f/scale;
- else scales[i] = scales[i-1]*256;
- }
- }
- else
- {
- SETSHADER(depthfxworld);
-
- if(!numranges) loopi(4) scales[i] = 1.0f/scale;
- else loopi(numranges)
- {
- scales[i] = 1.0f/scale;
- offsets[i] = -ranges[i]/scale;
- }
- }
- LOCALPARAMF(depthscale, scales[0], scales[1], scales[2], scales[3]);
- LOCALPARAMF(depthoffsets, offsets[0], offsets[1], offsets[2], offsets[3]);
-
- gle::enablevertex();
-
- vtxarray *prev = NULL;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded >= OCCLUDE_GEOM ||
- va->o.x > bbmax.x || va->o.y > bbmax.y || va->o.z > bbmax.z ||
- va->o.x + va->size < bbmin.x || va->o.y + va->size < bbmin.y || va->o.z + va->size < bbmin.z)
- continue;
-
- if(!prev || va->vbuf != prev->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- }
-
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
- if(va->alphatris > 0)
- {
- drawvatris(va, 3*va->alphatris, va->edata + 3*(va->tris + va->blendtris));
- xtravertsva += 3*va->alphatris;
- }
-
- prev = va;
- }
-
- gle::clearvbo();
- gle::clearebo();
- gle::disablevertex();
+ float scales[4] = { 0, 0, 0, 0 }, offsets[4] = { 0, 0, 0, 0 };
+ if(numranges < 0)
+ {
+ SETSHADER(depthfxsplitworld);
+
+ loopi(-numranges)
+ {
+ if(!i) scales[i] = 1.0f/scale;
+ else scales[i] = scales[i-1]*256;
+ }
+ }
+ else
+ {
+ SETSHADER(depthfxworld);
+
+ if(!numranges) loopi(4) scales[i] = 1.0f/scale;
+ else loopi(numranges)
+ {
+ scales[i] = 1.0f/scale;
+ offsets[i] = -ranges[i]/scale;
+ }
+ }
+ LOCALPARAMF(depthscale, scales[0], scales[1], scales[2], scales[3]);
+ LOCALPARAMF(depthoffsets, offsets[0], offsets[1], offsets[2], offsets[3]);
+
+ gle::enablevertex();
+
+ vtxarray *prev = NULL;
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(!va->texs || va->occluded >= OCCLUDE_GEOM ||
+ va->o.x > bbmax.x || va->o.y > bbmax.y || va->o.z > bbmax.z ||
+ va->o.x + va->size < bbmin.x || va->o.y + va->size < bbmin.y || va->o.z + va->size < bbmin.z)
+ continue;
+
+ if(!prev || va->vbuf != prev->vbuf)
+ {
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->ebuf);
+ const vertex *ptr = 0;
+ gle::vertexpointer(sizeof(vertex), ptr->pos.v);
+ }
+
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
+ if(va->alphatris > 0)
+ {
+ drawvatris(va, 3*va->alphatris, va->edata + 3*(va->tris + va->blendtris));
+ xtravertsva += 3*va->alphatris;
+ }
+
+ prev = va;
+ }
+
+ gle::clearvbo();
+ gle::clearebo();
+ gle::disablevertex();
}
VAR(oqdist, 0, 256, 1024);
@@ -828,101 +828,101 @@ VAR(envpass, 0, 1, 1);
struct renderstate
{
- bool colormask, depthmask, blending;
- int alphaing;
- GLuint vbuf;
- bool vattribs, vquery;
- vec colorscale, lightcolor;
- float alphascale;
- GLuint textures[8];
- Slot *slot, *texgenslot;
- VSlot *vslot, *texgenvslot;
- vec2 texgenscroll;
- int texgendim;
- int visibledynlights;
- uint dynlightmask;
-
- renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0)
- {
- loopk(8) textures[k] = 0;
- }
+ bool colormask, depthmask, blending;
+ int alphaing;
+ GLuint vbuf;
+ bool vattribs, vquery;
+ vec colorscale, lightcolor;
+ float alphascale;
+ GLuint textures[8];
+ Slot *slot, *texgenslot;
+ VSlot *vslot, *texgenvslot;
+ vec2 texgenscroll;
+ int texgendim;
+ int visibledynlights;
+ uint dynlightmask;
+
+ renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0)
+ {
+ loopk(8) textures[k] = 0;
+ }
};
static inline void disablevbuf(renderstate &cur)
{
- gle::clearvbo();
- gle::clearebo();
- cur.vbuf = 0;
+ gle::clearvbo();
+ gle::clearebo();
+ cur.vbuf = 0;
}
static inline void enablevquery(renderstate &cur)
{
- if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); }
- if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
- startbb(false);
- cur.vquery = true;
+ if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); }
+ if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
+ startbb(false);
+ cur.vquery = true;
}
static inline void disablevquery(renderstate &cur)
{
- endbb(false);
- cur.vquery = false;
+ endbb(false);
+ cur.vquery = false;
}
static void renderquery(renderstate &cur, occludequery *query, vtxarray *va, bool full = true)
{
- if(!cur.vquery) enablevquery(cur);
+ if(!cur.vquery) enablevquery(cur);
- startquery(query);
+ startquery(query);
- if(full) drawbb(ivec(va->bbmin).sub(1), ivec(va->bbmax).sub(va->bbmin).add(2));
- else drawbb(va->geommin, ivec(va->geommax).sub(va->geommin));
+ if(full) drawbb(ivec(va->bbmin).sub(1), ivec(va->bbmax).sub(va->bbmin).add(2));
+ else drawbb(va->geommin, ivec(va->geommax).sub(va->geommin));
- endquery(query);
+ endquery(query);
}
enum
{
- RENDERPASS_LIGHTMAP = 0,
- RENDERPASS_Z,
- RENDERPASS_CAUSTICS,
- RENDERPASS_FOG,
- RENDERPASS_LIGHTMAP_BLEND
+ RENDERPASS_LIGHTMAP = 0,
+ RENDERPASS_Z,
+ RENDERPASS_CAUSTICS,
+ RENDERPASS_FOG,
+ RENDERPASS_LIGHTMAP_BLEND
};
struct geombatch
{
- const elementset &es;
- VSlot &vslot;
- ushort *edata;
- vtxarray *va;
- int next, batch;
-
- geombatch(const elementset &es, ushort *edata, vtxarray *va)
- : es(es), vslot(lookupvslot(es.texture)), edata(edata), va(va),
- next(-1), batch(-1)
- {}
-
- int compare(const geombatch &b) const
- {
- if(va->vbuf < b.va->vbuf) return -1;
- if(va->vbuf > b.va->vbuf) return 1;
- if(va->dynlightmask < b.va->dynlightmask) return -1;
- if(va->dynlightmask > b.va->dynlightmask) return 1;
- if(vslot.slot->shader < b.vslot.slot->shader) return -1;
- if(vslot.slot->shader > b.vslot.slot->shader) return 1;
- if(vslot.slot->params.length() < b.vslot.slot->params.length()) return -1;
- if(vslot.slot->params.length() > b.vslot.slot->params.length()) return 1;
- if(es.texture < b.es.texture) return -1;
- if(es.texture > b.es.texture) return 1;
- if(es.lmid < b.es.lmid) return -1;
- if(es.lmid > b.es.lmid) return 1;
- if(es.envmap < b.es.envmap) return -1;
- if(es.envmap > b.es.envmap) return 1;
- if(es.dim < b.es.dim) return -1;
- if(es.dim > b.es.dim) return 1;
- return 0;
- }
+ const elementset &es;
+ VSlot &vslot;
+ ushort *edata;
+ vtxarray *va;
+ int next, batch;
+
+ geombatch(const elementset &es, ushort *edata, vtxarray *va)
+ : es(es), vslot(lookupvslot(es.texture)), edata(edata), va(va),
+ next(-1), batch(-1)
+ {}
+
+ int compare(const geombatch &b) const
+ {
+ if(va->vbuf < b.va->vbuf) return -1;
+ if(va->vbuf > b.va->vbuf) return 1;
+ if(va->dynlightmask < b.va->dynlightmask) return -1;
+ if(va->dynlightmask > b.va->dynlightmask) return 1;
+ if(vslot.slot->shader < b.vslot.slot->shader) return -1;
+ if(vslot.slot->shader > b.vslot.slot->shader) return 1;
+ if(vslot.slot->params.length() < b.vslot.slot->params.length()) return -1;
+ if(vslot.slot->params.length() > b.vslot.slot->params.length()) return 1;
+ if(es.texture < b.es.texture) return -1;
+ if(es.texture > b.es.texture) return 1;
+ if(es.lmid < b.es.lmid) return -1;
+ if(es.lmid > b.es.lmid) return 1;
+ if(es.envmap < b.es.envmap) return -1;
+ if(es.envmap > b.es.envmap) return 1;
+ if(es.dim < b.es.dim) return -1;
+ if(es.dim > b.es.dim) return 1;
+ return 0;
+ }
};
static vector<geombatch> geombatches;
@@ -930,486 +930,486 @@ static int firstbatch = -1, numbatches = 0;
static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, int numtexs = 0, ushort *edata = NULL)
{
- if(!texs)
- {
- texs = va->eslist;
- numtexs = va->texs;
- edata = va->edata;
- if(cur.alphaing)
- {
- texs += va->texs + va->blends;
- edata += 3*(va->tris + va->blendtris);
- numtexs = va->alphaback;
- if(cur.alphaing > 1) numtexs += va->alphafront;
- }
- }
-
- if(firstbatch < 0)
- {
- firstbatch = geombatches.length();
- numbatches = numtexs;
- loopi(numtexs-1)
- {
- geombatches.add(geombatch(texs[i], edata, va)).next = i+1;
- edata += texs[i].length[1];
- }
- geombatches.add(geombatch(texs[numtexs-1], edata, va));
- return;
- }
-
- int prevbatch = -1, curbatch = firstbatch, curtex = 0;
- do
- {
- geombatch &b = geombatches.add(geombatch(texs[curtex], edata, va));
- edata += texs[curtex].length[1];
- int dir = -1;
- while(curbatch >= 0)
- {
- dir = b.compare(geombatches[curbatch]);
- if(dir <= 0) break;
- prevbatch = curbatch;
- curbatch = geombatches[curbatch].next;
- }
- if(!dir)
- {
- int last = curbatch, next;
- for(;;)
- {
- next = geombatches[last].batch;
- if(next < 0) break;
- last = next;
- }
- if(last==curbatch)
- {
- b.batch = curbatch;
- b.next = geombatches[curbatch].next;
- if(prevbatch < 0) firstbatch = geombatches.length()-1;
- else geombatches[prevbatch].next = geombatches.length()-1;
- curbatch = geombatches.length()-1;
- }
- else
- {
- b.batch = next;
- geombatches[last].batch = geombatches.length()-1;
- }
- }
- else
- {
- numbatches++;
- b.next = curbatch;
- if(prevbatch < 0) firstbatch = geombatches.length()-1;
- else geombatches[prevbatch].next = geombatches.length()-1;
- prevbatch = geombatches.length()-1;
- }
- }
- while(++curtex < numtexs);
+ if(!texs)
+ {
+ texs = va->eslist;
+ numtexs = va->texs;
+ edata = va->edata;
+ if(cur.alphaing)
+ {
+ texs += va->texs + va->blends;
+ edata += 3*(va->tris + va->blendtris);
+ numtexs = va->alphaback;
+ if(cur.alphaing > 1) numtexs += va->alphafront;
+ }
+ }
+
+ if(firstbatch < 0)
+ {
+ firstbatch = geombatches.length();
+ numbatches = numtexs;
+ loopi(numtexs-1)
+ {
+ geombatches.add(geombatch(texs[i], edata, va)).next = i+1;
+ edata += texs[i].length[1];
+ }
+ geombatches.add(geombatch(texs[numtexs-1], edata, va));
+ return;
+ }
+
+ int prevbatch = -1, curbatch = firstbatch, curtex = 0;
+ do
+ {
+ geombatch &b = geombatches.add(geombatch(texs[curtex], edata, va));
+ edata += texs[curtex].length[1];
+ int dir = -1;
+ while(curbatch >= 0)
+ {
+ dir = b.compare(geombatches[curbatch]);
+ if(dir <= 0) break;
+ prevbatch = curbatch;
+ curbatch = geombatches[curbatch].next;
+ }
+ if(!dir)
+ {
+ int last = curbatch, next;
+ for(;;)
+ {
+ next = geombatches[last].batch;
+ if(next < 0) break;
+ last = next;
+ }
+ if(last==curbatch)
+ {
+ b.batch = curbatch;
+ b.next = geombatches[curbatch].next;
+ if(prevbatch < 0) firstbatch = geombatches.length()-1;
+ else geombatches[prevbatch].next = geombatches.length()-1;
+ curbatch = geombatches.length()-1;
+ }
+ else
+ {
+ b.batch = next;
+ geombatches[last].batch = geombatches.length()-1;
+ }
+ }
+ else
+ {
+ numbatches++;
+ b.next = curbatch;
+ if(prevbatch < 0) firstbatch = geombatches.length()-1;
+ else geombatches[prevbatch].next = geombatches.length()-1;
+ prevbatch = geombatches.length()-1;
+ }
+ }
+ while(++curtex < numtexs);
}
static inline void enablevattribs(renderstate &cur, bool all = true)
{
- gle::enablevertex();
- if(all)
- {
- gle::enabletexcoord0();
- gle::enabletexcoord1();
- gle::enablenormal();
- gle::enabletangent();
- }
- cur.vattribs = true;
+ gle::enablevertex();
+ if(all)
+ {
+ gle::enabletexcoord0();
+ gle::enabletexcoord1();
+ gle::enablenormal();
+ gle::enabletangent();
+ }
+ cur.vattribs = true;
}
static inline void disablevattribs(renderstate &cur, bool all = true)
{
- gle::disablevertex();
- if(all)
- {
- gle::disabletexcoord0();
- gle::disabletexcoord1();
- gle::disablenormal();
- gle::disabletangent();
- }
- cur.vattribs = false;
+ gle::disablevertex();
+ if(all)
+ {
+ gle::disabletexcoord0();
+ gle::disabletexcoord1();
+ gle::disablenormal();
+ gle::disabletangent();
+ }
+ cur.vattribs = false;
}
static void changevbuf(renderstate &cur, int pass, vtxarray *va)
{
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->ebuf);
- cur.vbuf = va->vbuf;
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->ebuf);
+ cur.vbuf = va->vbuf;
- vertex *vdata = (vertex *)0;
- gle::vertexpointer(sizeof(vertex), vdata->pos.v);
+ vertex *vdata = (vertex *)0;
+ gle::vertexpointer(sizeof(vertex), vdata->pos.v);
- if(pass==RENDERPASS_LIGHTMAP)
- {
- gle::normalpointer(sizeof(vertex), vdata->norm.v, GL_BYTE);
- gle::texcoord0pointer(sizeof(vertex), vdata->tc.v);
- gle::texcoord1pointer(sizeof(vertex), vdata->lm.v, GL_SHORT);
- gle::tangentpointer(sizeof(vertex), vdata->tangent.v, GL_BYTE);
- }
+ if(pass==RENDERPASS_LIGHTMAP)
+ {
+ gle::normalpointer(sizeof(vertex), vdata->norm.v, GL_BYTE);
+ gle::texcoord0pointer(sizeof(vertex), vdata->tc.v);
+ gle::texcoord1pointer(sizeof(vertex), vdata->lm.v, GL_SHORT);
+ gle::tangentpointer(sizeof(vertex), vdata->tangent.v, GL_BYTE);
+ }
}
static void changebatchtmus(renderstate &cur, int pass, geombatch &b)
{
- bool changed = false;
- extern bool brightengeom;
- extern int fullbright;
- int lmid = brightengeom && (b.es.lmid < LMID_RESERVED || (fullbright && editmode)) ? (int) LMID_BRIGHT : (int) b.es.lmid;
- if(cur.textures[1]!=lightmaptexs[lmid].id)
- {
- glActiveTexture_(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, cur.textures[1] = lightmaptexs[lmid].id);
- changed = true;
- }
- int tmu = 2;
- if(b.vslot.slot->shader->type&SHADER_NORMALSLMS)
- {
- if(cur.textures[tmu]!=lightmaptexs[lmid+1].id)
- {
- glActiveTexture_(GL_TEXTURE0+tmu);
- glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = lightmaptexs[lmid+1].id);
- changed = true;
- }
- tmu++;
- }
- if(b.vslot.slot->shader->type&SHADER_ENVMAP && b.es.envmap!=EMID_CUSTOM)
- {
- GLuint emtex = lookupenvmap(b.es.envmap);
- if(cur.textures[tmu]!=emtex)
- {
- glActiveTexture_(GL_TEXTURE0+tmu);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[tmu] = emtex);
- changed = true;
- }
- }
- if(changed) glActiveTexture_(GL_TEXTURE0);
-
- if(cur.dynlightmask != b.va->dynlightmask)
- {
- cur.visibledynlights = setdynlights(b.va);
- cur.dynlightmask = b.va->dynlightmask;
- }
+ bool changed = false;
+ extern bool brightengeom;
+ extern int fullbright;
+ int lmid = brightengeom && (b.es.lmid < LMID_RESERVED || (fullbright && editmode)) ? (int) LMID_BRIGHT : (int) b.es.lmid;
+ if(cur.textures[1]!=lightmaptexs[lmid].id)
+ {
+ glActiveTexture_(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, cur.textures[1] = lightmaptexs[lmid].id);
+ changed = true;
+ }
+ int tmu = 2;
+ if(b.vslot.slot->shader->type&SHADER_NORMALSLMS)
+ {
+ if(cur.textures[tmu]!=lightmaptexs[lmid+1].id)
+ {
+ glActiveTexture_(GL_TEXTURE0+tmu);
+ glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = lightmaptexs[lmid+1].id);
+ changed = true;
+ }
+ tmu++;
+ }
+ if(b.vslot.slot->shader->type&SHADER_ENVMAP && b.es.envmap!=EMID_CUSTOM)
+ {
+ GLuint emtex = lookupenvmap(b.es.envmap);
+ if(cur.textures[tmu]!=emtex)
+ {
+ glActiveTexture_(GL_TEXTURE0+tmu);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[tmu] = emtex);
+ changed = true;
+ }
+ }
+ if(changed) glActiveTexture_(GL_TEXTURE0);
+
+ if(cur.dynlightmask != b.va->dynlightmask)
+ {
+ cur.visibledynlights = setdynlights(b.va);
+ cur.dynlightmask = b.va->dynlightmask;
+ }
}
static void changeslottmus(renderstate &cur, int pass, Slot &slot, VSlot &vslot)
{
- if(pass==RENDERPASS_LIGHTMAP)
- {
- GLuint diffusetex = slot.sts.empty() ? notexture->id : slot.sts[0].t->id;
- if(cur.textures[0]!=diffusetex)
- glBindTexture(GL_TEXTURE_2D, cur.textures[0] = diffusetex);
- }
-
- if(cur.alphaing)
- {
- float alpha = cur.alphaing > 1 ? vslot.alphafront : vslot.alphaback;
- if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha)
- {
- cur.colorscale = vslot.colorscale;
- cur.alphascale = alpha;
- GLOBALPARAMF(colorparams, 2*alpha*vslot.colorscale.x, 2*alpha*vslot.colorscale.y, 2*alpha*vslot.colorscale.z, alpha);
- setfogcolor(vec(curfogcolor).mul(alpha));
- }
- }
- else if(cur.colorscale != vslot.colorscale)
- {
- cur.colorscale = vslot.colorscale;
- GLOBALPARAMF(colorparams, 2*vslot.colorscale.x, 2*vslot.colorscale.y, 2*vslot.colorscale.z, 1);
- }
- int tmu = 2, envmaptmu = -1;
- if(slot.shader->type&SHADER_NORMALSLMS) tmu++;
- if(slot.shader->type&SHADER_ENVMAP) envmaptmu = tmu++;
- loopvj(slot.sts)
- {
- Slot::Tex &t = slot.sts[j];
- if(t.type==TEX_DIFFUSE || t.combined>=0) continue;
- if(t.type==TEX_ENVMAP)
- {
- if(envmaptmu>=0 && t.t && cur.textures[envmaptmu]!=t.t->id)
- {
- glActiveTexture_(GL_TEXTURE0+envmaptmu);
- glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[envmaptmu] = t.t->id);
- }
- }
- else
- {
- if(cur.textures[tmu]!=t.t->id)
- {
- glActiveTexture_(GL_TEXTURE0+tmu);
- glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id);
- }
- if(++tmu >= 8) break;
- }
- }
- glActiveTexture_(GL_TEXTURE0);
-
- cur.slot = &slot;
- cur.vslot = &vslot;
+ if(pass==RENDERPASS_LIGHTMAP)
+ {
+ GLuint diffusetex = slot.sts.empty() ? notexture->id : slot.sts[0].t->id;
+ if(cur.textures[0]!=diffusetex)
+ glBindTexture(GL_TEXTURE_2D, cur.textures[0] = diffusetex);
+ }
+
+ if(cur.alphaing)
+ {
+ float alpha = cur.alphaing > 1 ? vslot.alphafront : vslot.alphaback;
+ if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha)
+ {
+ cur.colorscale = vslot.colorscale;
+ cur.alphascale = alpha;
+ GLOBALPARAMF(colorparams, 2*alpha*vslot.colorscale.x, 2*alpha*vslot.colorscale.y, 2*alpha*vslot.colorscale.z, alpha);
+ setfogcolor(vec(curfogcolor).mul(alpha));
+ }
+ }
+ else if(cur.colorscale != vslot.colorscale)
+ {
+ cur.colorscale = vslot.colorscale;
+ GLOBALPARAMF(colorparams, 2*vslot.colorscale.x, 2*vslot.colorscale.y, 2*vslot.colorscale.z, 1);
+ }
+ int tmu = 2, envmaptmu = -1;
+ if(slot.shader->type&SHADER_NORMALSLMS) tmu++;
+ if(slot.shader->type&SHADER_ENVMAP) envmaptmu = tmu++;
+ loopvj(slot.sts)
+ {
+ Slot::Tex &t = slot.sts[j];
+ if(t.type==TEX_DIFFUSE || t.combined>=0) continue;
+ if(t.type==TEX_ENVMAP)
+ {
+ if(envmaptmu>=0 && t.t && cur.textures[envmaptmu]!=t.t->id)
+ {
+ glActiveTexture_(GL_TEXTURE0+envmaptmu);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, cur.textures[envmaptmu] = t.t->id);
+ }
+ }
+ else
+ {
+ if(cur.textures[tmu]!=t.t->id)
+ {
+ glActiveTexture_(GL_TEXTURE0+tmu);
+ glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id);
+ }
+ if(++tmu >= 8) break;
+ }
+ }
+ glActiveTexture_(GL_TEXTURE0);
+
+ cur.slot = &slot;
+ cur.vslot = &vslot;
}
static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed)
{
- if(glaring)
- {
- static Shader *noglareshader = NULL, *noglareblendshader = NULL, *noglarealphashader = NULL;
- Shader *fallback;
- if(cur.blending) { if(!noglareblendshader) noglareblendshader = lookupshaderbyname("noglareblendworld"); fallback = noglareblendshader; }
- else if(cur.alphaing) { if(!noglarealphashader) noglarealphashader = lookupshaderbyname("noglarealphaworld"); fallback = noglarealphashader; }
- else { if(!noglareshader) noglareshader = lookupshaderbyname("noglareworld"); fallback = noglareshader; }
- if(s->hasoption(4)) s->setvariant(cur.visibledynlights, 4, slot, vslot, fallback);
- else s->setvariant(cur.blending ? 1 : 0, 4, slot, vslot, fallback);
- }
- else if(fading && !cur.blending && !cur.alphaing)
- {
- if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot);
- else s->setvariant(cur.visibledynlights, 2, slot, vslot);
- }
- else if(shadowed) s->setvariant(cur.visibledynlights, 1, slot, vslot);
- else if(!cur.visibledynlights) s->set(slot, vslot);
- else s->setvariant(cur.visibledynlights-1, 0, slot, vslot);
+ if(glaring)
+ {
+ static Shader *noglareshader = NULL, *noglareblendshader = NULL, *noglarealphashader = NULL;
+ Shader *fallback;
+ if(cur.blending) { if(!noglareblendshader) noglareblendshader = lookupshaderbyname("noglareblendworld"); fallback = noglareblendshader; }
+ else if(cur.alphaing) { if(!noglarealphashader) noglarealphashader = lookupshaderbyname("noglarealphaworld"); fallback = noglarealphashader; }
+ else { if(!noglareshader) noglareshader = lookupshaderbyname("noglareworld"); fallback = noglareshader; }
+ if(s->hasoption(4)) s->setvariant(cur.visibledynlights, 4, slot, vslot, fallback);
+ else s->setvariant(cur.blending ? 1 : 0, 4, slot, vslot, fallback);
+ }
+ else if(fading && !cur.blending && !cur.alphaing)
+ {
+ if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot);
+ else s->setvariant(cur.visibledynlights, 2, slot, vslot);
+ }
+ else if(shadowed) s->setvariant(cur.visibledynlights, 1, slot, vslot);
+ else if(!cur.visibledynlights) s->set(slot, vslot);
+ else s->setvariant(cur.visibledynlights-1, 0, slot, vslot);
}
static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot)
{
- if(cur.texgenslot != &slot || cur.texgenvslot != &vslot)
- {
- Texture *curtex = !cur.texgenslot || cur.texgenslot->sts.empty() ? notexture : cur.texgenslot->sts[0].t,
- *tex = slot.sts.empty() ? notexture : slot.sts[0].t;
- if(!cur.texgenvslot || slot.sts.empty() ||
- (curtex->xs != tex->xs || curtex->ys != tex->ys ||
- cur.texgenvslot->rotation != vslot.rotation || cur.texgenvslot->scale != vslot.scale ||
- cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll))
- {
- const texrotation &r = texrotations[vslot.rotation];
- float xs = r.flipx ? -tex->xs : tex->xs,
- ys = r.flipy ? -tex->ys : tex->ys;
- vec2 scroll(vslot.scroll);
- if(r.swapxy) swap(scroll.x, scroll.y);
- scroll.x *= lastmillis*tex->xs/xs;
- scroll.y *= lastmillis*tex->ys/ys;
- if(cur.texgenscroll != scroll)
- {
- cur.texgenscroll = scroll;
- cur.texgendim = -1;
- }
- }
- cur.texgenslot = &slot;
- cur.texgenvslot = &vslot;
- }
-
- if(cur.texgendim == dim) return;
- GLOBALPARAM(texgenscroll, cur.texgenscroll);
- cur.texgendim = dim;
+ if(cur.texgenslot != &slot || cur.texgenvslot != &vslot)
+ {
+ Texture *curtex = !cur.texgenslot || cur.texgenslot->sts.empty() ? notexture : cur.texgenslot->sts[0].t,
+ *tex = slot.sts.empty() ? notexture : slot.sts[0].t;
+ if(!cur.texgenvslot || slot.sts.empty() ||
+ (curtex->xs != tex->xs || curtex->ys != tex->ys ||
+ cur.texgenvslot->rotation != vslot.rotation || cur.texgenvslot->scale != vslot.scale ||
+ cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll))
+ {
+ const texrotation &r = texrotations[vslot.rotation];
+ float xs = r.flipx ? -tex->xs : tex->xs,
+ ys = r.flipy ? -tex->ys : tex->ys;
+ vec2 scroll(vslot.scroll);
+ if(r.swapxy) swap(scroll.x, scroll.y);
+ scroll.x *= lastmillis*tex->xs/xs;
+ scroll.y *= lastmillis*tex->ys/ys;
+ if(cur.texgenscroll != scroll)
+ {
+ cur.texgenscroll = scroll;
+ cur.texgendim = -1;
+ }
+ }
+ cur.texgenslot = &slot;
+ cur.texgenvslot = &vslot;
+ }
+
+ if(cur.texgendim == dim) return;
+ GLOBALPARAM(texgenscroll, cur.texgenscroll);
+ cur.texgendim = dim;
}
static void renderbatch(renderstate &cur, int pass, geombatch &b)
{
- geombatch *shadowed = NULL;
- int rendered = -1;
- for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch])
- {
- ushort len = curbatch->es.length[curbatch->va->shadowed ? 0 : 1];
- if(len)
- {
- if(rendered < 0)
- {
- changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, false);
- rendered = 0;
- gbatches++;
- }
- ushort minvert = curbatch->es.minvert[0], maxvert = curbatch->es.maxvert[0];
- if(!curbatch->va->shadowed) { minvert = min(minvert, curbatch->es.minvert[1]); maxvert = max(maxvert, curbatch->es.maxvert[1]); }
- drawtris(len, curbatch->edata, minvert, maxvert);
- vtris += len/3;
- }
- if(curbatch->es.length[1] > len && !shadowed) shadowed = curbatch;
- if(curbatch->batch < 0) break;
- }
- if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch])
- {
- if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0])
- {
- if(rendered < 1)
- {
- changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, true);
- rendered = 1;
- gbatches++;
- }
- ushort len = curbatch->es.length[1] - curbatch->es.length[0];
- drawtris(len, curbatch->edata + curbatch->es.length[0], curbatch->es.minvert[1], curbatch->es.maxvert[1]);
- vtris += len/3;
- }
- if(curbatch->batch < 0) break;
- }
+ geombatch *shadowed = NULL;
+ int rendered = -1;
+ for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch])
+ {
+ ushort len = curbatch->es.length[curbatch->va->shadowed ? 0 : 1];
+ if(len)
+ {
+ if(rendered < 0)
+ {
+ changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, false);
+ rendered = 0;
+ gbatches++;
+ }
+ ushort minvert = curbatch->es.minvert[0], maxvert = curbatch->es.maxvert[0];
+ if(!curbatch->va->shadowed) { minvert = min(minvert, curbatch->es.minvert[1]); maxvert = max(maxvert, curbatch->es.maxvert[1]); }
+ drawtris(len, curbatch->edata, minvert, maxvert);
+ vtris += len/3;
+ }
+ if(curbatch->es.length[1] > len && !shadowed) shadowed = curbatch;
+ if(curbatch->batch < 0) break;
+ }
+ if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch])
+ {
+ if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0])
+ {
+ if(rendered < 1)
+ {
+ changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, true);
+ rendered = 1;
+ gbatches++;
+ }
+ ushort len = curbatch->es.length[1] - curbatch->es.length[0];
+ drawtris(len, curbatch->edata + curbatch->es.length[0], curbatch->es.minvert[1], curbatch->es.maxvert[1]);
+ vtris += len/3;
+ }
+ if(curbatch->batch < 0) break;
+ }
}
static void resetbatches()
{
- geombatches.setsize(0);
- firstbatch = -1;
- numbatches = 0;
+ geombatches.setsize(0);
+ firstbatch = -1;
+ numbatches = 0;
}
static void renderbatches(renderstate &cur, int pass)
{
- cur.slot = NULL;
- cur.vslot = NULL;
- int curbatch = firstbatch;
- if(curbatch >= 0)
- {
- if(cur.alphaing)
- {
- if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
- }
- else if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
- if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, cur.alphaing ? GL_FALSE : GL_TRUE); }
- if(!cur.vattribs)
- {
- if(cur.vquery) disablevquery(cur);
- enablevattribs(cur);
- }
- }
- while(curbatch >= 0)
- {
- geombatch &b = geombatches[curbatch];
- curbatch = b.next;
-
- if(cur.vbuf != b.va->vbuf) changevbuf(cur, pass, b.va);
- if(cur.vslot != &b.vslot)
- {
- changeslottmus(cur, pass, *b.vslot.slot, b.vslot);
- if(cur.texgendim != b.es.dim || (cur.texgendim <= 2 && cur.texgenvslot != &b.vslot)) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot);
- }
- else if(cur.texgendim != b.es.dim) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot);
- if(pass == RENDERPASS_LIGHTMAP) changebatchtmus(cur, pass, b);
-
- renderbatch(cur, pass, b);
- }
-
- resetbatches();
+ cur.slot = NULL;
+ cur.vslot = NULL;
+ int curbatch = firstbatch;
+ if(curbatch >= 0)
+ {
+ if(cur.alphaing)
+ {
+ if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
+ }
+ else if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
+ if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, cur.alphaing ? GL_FALSE : GL_TRUE); }
+ if(!cur.vattribs)
+ {
+ if(cur.vquery) disablevquery(cur);
+ enablevattribs(cur);
+ }
+ }
+ while(curbatch >= 0)
+ {
+ geombatch &b = geombatches[curbatch];
+ curbatch = b.next;
+
+ if(cur.vbuf != b.va->vbuf) changevbuf(cur, pass, b.va);
+ if(cur.vslot != &b.vslot)
+ {
+ changeslottmus(cur, pass, *b.vslot.slot, b.vslot);
+ if(cur.texgendim != b.es.dim || (cur.texgendim <= 2 && cur.texgenvslot != &b.vslot)) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot);
+ }
+ else if(cur.texgendim != b.es.dim) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot);
+ if(pass == RENDERPASS_LIGHTMAP) changebatchtmus(cur, pass, b);
+
+ renderbatch(cur, pass, b);
+ }
+
+ resetbatches();
}
void renderzpass(renderstate &cur, vtxarray *va)
{
- if(!cur.vattribs)
- {
- if(cur.vquery) disablevquery(cur);
- enablevattribs(cur, false);
- }
- if(cur.vbuf!=va->vbuf) changevbuf(cur, RENDERPASS_Z, va);
- if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
- if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); }
- int firsttex = 0, numtris = va->tris;
- ushort *edata = va->edata;
- if(cur.alphaing)
- {
- firsttex += va->texs + va->blends;
- edata += 3*(va->tris + va->blendtris);
- numtris = va->alphatris;
- xtravertsva += 3*numtris;
- }
- else xtravertsva += va->verts;
- nocolorshader->set();
- drawvatris(va, 3*numtris, edata);
+ if(!cur.vattribs)
+ {
+ if(cur.vquery) disablevquery(cur);
+ enablevattribs(cur, false);
+ }
+ if(cur.vbuf!=va->vbuf) changevbuf(cur, RENDERPASS_Z, va);
+ if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
+ if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); }
+ int firsttex = 0, numtris = va->tris;
+ ushort *edata = va->edata;
+ if(cur.alphaing)
+ {
+ firsttex += va->texs + va->blends;
+ edata += 3*(va->tris + va->blendtris);
+ numtris = va->alphatris;
+ xtravertsva += 3*numtris;
+ }
+ else xtravertsva += va->verts;
+ nocolorshader->set();
+ drawvatris(va, 3*numtris, edata);
}
vector<vtxarray *> foggedvas;
#define startvaquery(va, flush) \
- do { \
- if(va->query) \
- { \
- flush; \
- startquery(va->query); \
- } \
- } while(0)
+ do { \
+ if(va->query) \
+ { \
+ flush; \
+ startquery(va->query); \
+ } \
+ } while(0)
#define endvaquery(va, flush) \
- do { \
- if(va->query) \
- { \
- flush; \
- endquery(va->query); \
- } \
- } while(0)
+ do { \
+ if(va->query) \
+ { \
+ flush; \
+ endquery(va->query); \
+ } \
+ } while(0)
void renderfoggedvas(renderstate &cur, bool doquery = false)
{
- static Shader *fogshader = NULL;
- if(!fogshader) fogshader = lookupshaderbyname("fogworld");
- if(fading) fogshader->setvariant(0, 2);
- else fogshader->set();
+ static Shader *fogshader = NULL;
+ if(!fogshader) fogshader = lookupshaderbyname("fogworld");
+ if(fading) fogshader->setvariant(0, 2);
+ else fogshader->set();
- if(!cur.vattribs) enablevattribs(cur, false);
+ if(!cur.vattribs) enablevattribs(cur, false);
- loopv(foggedvas)
- {
- vtxarray *va = foggedvas[i];
- if(cur.vbuf!=va->vbuf) changevbuf(cur, RENDERPASS_FOG, va);
+ loopv(foggedvas)
+ {
+ vtxarray *va = foggedvas[i];
+ if(cur.vbuf!=va->vbuf) changevbuf(cur, RENDERPASS_FOG, va);
- if(doquery) startvaquery(va, );
- drawvatris(va, 3*va->tris, va->edata);
- vtris += va->tris;
- if(doquery) endvaquery(va, );
- }
+ if(doquery) startvaquery(va, );
+ drawvatris(va, 3*va->tris, va->edata);
+ vtris += va->tris;
+ if(doquery) endvaquery(va, );
+ }
- foggedvas.setsize(0);
+ foggedvas.setsize(0);
}
VAR(batchgeom, 0, 1, 1);
void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool fogpass = false, bool doquery = false)
{
- switch(pass)
- {
- case RENDERPASS_LIGHTMAP:
- if(!cur.alphaing) vverts += va->verts;
- va->shadowed = false;
- va->dynlightmask = 0;
- if(fogpass ? va->geommax.z<=reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED)
- {
- if(!cur.alphaing && !cur.blending) foggedvas.add(va);
- break;
- }
- if(!drawtex && !glaring && !cur.alphaing)
- {
- va->shadowed = isshadowmapreceiver(va);
- calcdynlightmask(va);
- }
- if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); });
- mergetexs(cur, va);
- if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); });
- else if(!batchgeom && geombatches.length()) renderbatches(cur, pass);
- break;
-
- case RENDERPASS_LIGHTMAP_BLEND:
- {
- if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); });
- mergetexs(cur, va, &va->eslist[va->texs], va->blends, va->edata + 3*va->tris);
- if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); });
- else if(!batchgeom && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
- break;
- }
-
- case RENDERPASS_FOG:
- if(cur.vbuf!=va->vbuf) changevbuf(cur, pass, va);
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
- break;
-
- case RENDERPASS_CAUSTICS:
- if(cur.vbuf!=va->vbuf) changevbuf(cur, pass, va);
- drawvatris(va, 3*va->tris, va->edata);
- xtravertsva += va->verts;
- break;
-
- case RENDERPASS_Z:
- if(doquery) startvaquery(va, );
- renderzpass(cur, va);
- if(doquery) endvaquery(va, );
- break;
- }
+ switch(pass)
+ {
+ case RENDERPASS_LIGHTMAP:
+ if(!cur.alphaing) vverts += va->verts;
+ va->shadowed = false;
+ va->dynlightmask = 0;
+ if(fogpass ? va->geommax.z<=reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED)
+ {
+ if(!cur.alphaing && !cur.blending) foggedvas.add(va);
+ break;
+ }
+ if(!drawtex && !glaring && !cur.alphaing)
+ {
+ va->shadowed = isshadowmapreceiver(va);
+ calcdynlightmask(va);
+ }
+ if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); });
+ mergetexs(cur, va);
+ if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); });
+ else if(!batchgeom && geombatches.length()) renderbatches(cur, pass);
+ break;
+
+ case RENDERPASS_LIGHTMAP_BLEND:
+ {
+ if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); });
+ mergetexs(cur, va, &va->eslist[va->texs], va->blends, va->edata + 3*va->tris);
+ if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); });
+ else if(!batchgeom && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+ break;
+ }
+
+ case RENDERPASS_FOG:
+ if(cur.vbuf!=va->vbuf) changevbuf(cur, pass, va);
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
+ break;
+
+ case RENDERPASS_CAUSTICS:
+ if(cur.vbuf!=va->vbuf) changevbuf(cur, pass, va);
+ drawvatris(va, 3*va->tris, va->edata);
+ xtravertsva += va->verts;
+ break;
+
+ case RENDERPASS_Z:
+ if(doquery) startvaquery(va, );
+ renderzpass(cur, va);
+ if(doquery) endvaquery(va, );
+ break;
+ }
}
#define NUMCAUSTICS 32
@@ -1418,24 +1418,24 @@ static Texture *caustictex[NUMCAUSTICS] = { NULL };
void loadcaustics(bool force)
{
- static bool needcaustics = false;
- if(force) needcaustics = true;
- if(!caustics || !needcaustics) return;
- useshaderbyname("caustic");
- if(caustictex[0]) return;
- loopi(NUMCAUSTICS)
- {
- defformatstring(name, "<grey><noswizzle>packages/caustics/caust%.2d.png", i);
- caustictex[i] = textureload(name);
- }
+ static bool needcaustics = false;
+ if(force) needcaustics = true;
+ if(!caustics || !needcaustics) return;
+ useshaderbyname("caustic");
+ if(caustictex[0]) return;
+ loopi(NUMCAUSTICS)
+ {
+ defformatstring(name, "<grey><noswizzle>packages/caustics/caust%.2d.png", i);
+ caustictex[i] = textureload(name);
+ }
}
void cleanupva()
{
- clearvas(worldroot);
- clearqueries();
- cleanupbb();
- loopi(NUMCAUSTICS) caustictex[i] = NULL;
+ clearvas(worldroot);
+ clearqueries();
+ cleanupbb();
+ loopi(NUMCAUSTICS) caustictex[i] = NULL;
}
VARR(causticscale, 0, 50, 10000);
@@ -1445,38 +1445,38 @@ VARFP(caustics, 0, 1, 1, loadcaustics());
void setupcaustics(float blend)
{
- if(!caustictex[0]) loadcaustics(true);
+ if(!caustictex[0]) loadcaustics(true);
- vec s = vec(0.011f, 0, 0.0066f).mul(100.0f/causticscale), t = vec(0, 0.011f, 0.0066f).mul(100.0f/causticscale);
- int tex = (lastmillis/causticmillis)%NUMCAUSTICS;
- float frac = float(lastmillis%causticmillis)/causticmillis;
- loopi(2)
- {
- glActiveTexture_(GL_TEXTURE0+i);
- glBindTexture(GL_TEXTURE_2D, caustictex[(tex+i)%NUMCAUSTICS]->id);
- }
- glActiveTexture_(GL_TEXTURE0);
- SETSHADER(caustic);
- LOCALPARAM(texgenS, s);
- LOCALPARAM(texgenT, t);
- blend *= causticcontrast;
- LOCALPARAMF(frameblend, blend*(1-frac), blend*frac, blend, 1 - blend);
+ vec s = vec(0.011f, 0, 0.0066f).mul(100.0f/causticscale), t = vec(0, 0.011f, 0.0066f).mul(100.0f/causticscale);
+ int tex = (lastmillis/causticmillis)%NUMCAUSTICS;
+ float frac = float(lastmillis%causticmillis)/causticmillis;
+ loopi(2)
+ {
+ glActiveTexture_(GL_TEXTURE0+i);
+ glBindTexture(GL_TEXTURE_2D, caustictex[(tex+i)%NUMCAUSTICS]->id);
+ }
+ glActiveTexture_(GL_TEXTURE0);
+ SETSHADER(caustic);
+ LOCALPARAM(texgenS, s);
+ LOCALPARAM(texgenT, t);
+ blend *= causticcontrast;
+ LOCALPARAMF(frameblend, blend*(1-frac), blend*frac, blend, 1 - blend);
}
void setupgeom(renderstate &cur)
{
- GLOBALPARAMF(colorparams, 2, 2, 2, 1);
- GLOBALPARAM(camera, camera1->o);
- GLOBALPARAMF(ambient, ambientcolor.x/255.0f, ambientcolor.y/255.0f, ambientcolor.z/255.0f);
- GLOBALPARAMF(millis, lastmillis/1000.0f);
+ GLOBALPARAMF(colorparams, 2, 2, 2, 1);
+ GLOBALPARAM(camera, camera1->o);
+ GLOBALPARAMF(ambient, ambientcolor.x/255.0f, ambientcolor.y/255.0f, ambientcolor.z/255.0f);
+ GLOBALPARAMF(millis, lastmillis/1000.0f);
- glActiveTexture_(GL_TEXTURE0);
+ glActiveTexture_(GL_TEXTURE0);
}
void cleanupgeom(renderstate &cur)
{
- if(cur.vattribs) disablevattribs(cur);
- if(cur.vbuf) disablevbuf(cur);
+ if(cur.vattribs) disablevattribs(cur);
+ if(cur.vbuf) disablevbuf(cur);
}
#define FIRSTVA (reflecting ? reflectedva : visibleva)
@@ -1484,398 +1484,398 @@ void cleanupgeom(renderstate &cur)
static void rendergeommultipass(renderstate &cur, int pass, bool fogpass)
{
- if(cur.vbuf) disablevbuf(cur);
- if(!cur.vattribs) enablevattribs(cur, false);
- cur.texgendim = -1;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
- {
- if(!va->texs) continue;
- if(refracting)
- {
- if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_GEOM) continue;
- if(ishiddencube(va->o, va->size)) continue;
- }
- else if(reflecting)
- {
- if(va->geommax.z <= reflectz) continue;
- }
- else if(va->occluded >= OCCLUDE_GEOM) continue;
- if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
- renderva(cur, va, pass, fogpass);
- }
- if(geombatches.length()) renderbatches(cur, pass);
+ if(cur.vbuf) disablevbuf(cur);
+ if(!cur.vattribs) enablevattribs(cur, false);
+ cur.texgendim = -1;
+ for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ {
+ if(!va->texs) continue;
+ if(refracting)
+ {
+ if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_GEOM) continue;
+ if(ishiddencube(va->o, va->size)) continue;
+ }
+ else if(reflecting)
+ {
+ if(va->geommax.z <= reflectz) continue;
+ }
+ else if(va->occluded >= OCCLUDE_GEOM) continue;
+ if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
+ renderva(cur, va, pass, fogpass);
+ }
+ if(geombatches.length()) renderbatches(cur, pass);
}
VAR(oqgeom, 0, 1, 1);
void rendergeom(float causticspass, bool fogpass)
{
- if(causticspass && (!causticscale || !causticmillis)) causticspass = 0;
-
- bool mainpass = !reflecting && !refracting && !drawtex && !glaring,
- doOQ = oqfrags && oqgeom && mainpass,
- doZP = doOQ && zpass,
- doSM = shadowmap && !drawtex && !glaring;
- renderstate cur;
- if(mainpass)
- {
- flipqueries();
- vtris = vverts = 0;
- }
- if(!doZP)
- {
- if(shadowmap && mainpass) rendershadowmap();
- setupgeom(cur);
- if(doSM) pushshadowmap();
- }
-
- finddynlights();
-
- resetbatches();
-
- int blends = 0;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
- {
- if(!va->texs) continue;
- if(refracting)
- {
- if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_GEOM) continue;
- if(ishiddencube(va->o, va->size)) continue;
- }
- else if(reflecting)
- {
- if(va->geommax.z <= reflectz) continue;
- }
- else if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o))
- {
- if(va->parent && va->parent->occluded >= OCCLUDE_BB)
- {
- va->query = NULL;
- va->occluded = OCCLUDE_PARENT;
- continue;
- }
- va->occluded = va->query && va->query->owner == va && checkquery(va->query) ? min(va->occluded+1, int(OCCLUDE_BB)) : OCCLUDE_NOTHING;
- va->query = newquery(va);
- if((!va->query && zpass) || !va->occluded)
- va->occluded = OCCLUDE_NOTHING;
- if(va->occluded >= OCCLUDE_GEOM)
- {
- if(va->query)
- {
- if(!zpass && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
- if(cur.vattribs) disablevattribs(cur, !doZP);
- if(cur.vbuf) disablevbuf(cur);
- renderquery(cur, va->query, va);
- }
- continue;
- }
- }
- else
- {
- va->query = NULL;
- va->occluded = OCCLUDE_NOTHING;
- }
-
- if(!doZP) blends += va->blends;
- renderva(cur, va, doZP ? RENDERPASS_Z : RENDERPASS_LIGHTMAP, fogpass, doOQ);
- }
-
- if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
-
- if(cur.vquery) disablevquery(cur);
- if(cur.vattribs) disablevattribs(cur, !doZP);
- if(cur.vbuf) disablevbuf(cur);
-
- if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
- if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
-
- bool multipassing = false;
-
- if(doZP)
- {
+ if(causticspass && (!causticscale || !causticmillis)) causticspass = 0;
+
+ bool mainpass = !reflecting && !refracting && !drawtex && !glaring,
+ doOQ = oqfrags && oqgeom && mainpass,
+ doZP = doOQ && zpass,
+ doSM = shadowmap && !drawtex && !glaring;
+ renderstate cur;
+ if(mainpass)
+ {
+ flipqueries();
+ vtris = vverts = 0;
+ }
+ if(!doZP)
+ {
+ if(shadowmap && mainpass) rendershadowmap();
+ setupgeom(cur);
+ if(doSM) pushshadowmap();
+ }
+
+ finddynlights();
+
+ resetbatches();
+
+ int blends = 0;
+ for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ {
+ if(!va->texs) continue;
+ if(refracting)
+ {
+ if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_GEOM) continue;
+ if(ishiddencube(va->o, va->size)) continue;
+ }
+ else if(reflecting)
+ {
+ if(va->geommax.z <= reflectz) continue;
+ }
+ else if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o))
+ {
+ if(va->parent && va->parent->occluded >= OCCLUDE_BB)
+ {
+ va->query = NULL;
+ va->occluded = OCCLUDE_PARENT;
+ continue;
+ }
+ va->occluded = va->query && va->query->owner == va && checkquery(va->query) ? min(va->occluded+1, int(OCCLUDE_BB)) : OCCLUDE_NOTHING;
+ va->query = newquery(va);
+ if((!va->query && zpass) || !va->occluded)
+ va->occluded = OCCLUDE_NOTHING;
+ if(va->occluded >= OCCLUDE_GEOM)
+ {
+ if(va->query)
+ {
+ if(!zpass && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+ if(cur.vattribs) disablevattribs(cur, !doZP);
+ if(cur.vbuf) disablevbuf(cur);
+ renderquery(cur, va->query, va);
+ }
+ continue;
+ }
+ }
+ else
+ {
+ va->query = NULL;
+ va->occluded = OCCLUDE_NOTHING;
+ }
+
+ if(!doZP) blends += va->blends;
+ renderva(cur, va, doZP ? RENDERPASS_Z : RENDERPASS_LIGHTMAP, fogpass, doOQ);
+ }
+
+ if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+
+ if(cur.vquery) disablevquery(cur);
+ if(cur.vattribs) disablevattribs(cur, !doZP);
+ if(cur.vbuf) disablevbuf(cur);
+
+ if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); }
+ if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
+
+ bool multipassing = false;
+
+ if(doZP)
+ {
glFlush();
- if(shadowmap && mainpass) rendershadowmap();
- setupgeom(cur);
- if(doSM) pushshadowmap();
-
- if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
- cur.texgendim = -1;
-
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue;
- blends += va->blends;
- renderva(cur, va, RENDERPASS_LIGHTMAP, fogpass);
- }
- if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->texs || va->occluded < OCCLUDE_GEOM) continue;
- else if((va->parent && va->parent->occluded >= OCCLUDE_BB) ||
- (va->query && checkquery(va->query)))
- {
- va->occluded = OCCLUDE_BB;
- continue;
- }
-
- blends += va->blends;
- renderva(cur, va, RENDERPASS_LIGHTMAP, fogpass);
- }
- if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
- }
-
- if(blends)
- {
- if(cur.vbuf) disablevbuf(cur);
-
- if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
- glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
-
- cur.texgendim = -1;
- cur.blending = true;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
- {
- if(!va->blends) continue;
- if(refracting)
- {
- if(refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) continue;
- if(ishiddencube(va->o, va->size)) continue;
- if(va->occluded >= OCCLUDE_GEOM) continue;
- }
- else if(reflecting)
- {
- if(va->geommax.z <= reflectz) continue;
- }
- else if(va->occluded >= OCCLUDE_GEOM) continue;
- if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
- renderva(cur, va, RENDERPASS_LIGHTMAP_BLEND, fogpass);
- }
- if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
- cur.blending = false;
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDisable(GL_BLEND);
- glDepthMask(GL_TRUE);
- }
-
- if(doSM) popshadowmap();
-
- if(cur.vattribs) disablevattribs(cur);
-
- if(foggedvas.length()) renderfoggedvas(cur, doOQ && !zpass);
-
- if(causticspass)
- {
- if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
- glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
-
- setupcaustics(causticspass);
- glBlendFunc(GL_ZERO, GL_SRC_COLOR);
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- rendergeommultipass(cur, RENDERPASS_CAUSTICS, fogpass);
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- glDisable(GL_BLEND);
- glDepthMask(GL_TRUE);
- }
-
- if(multipassing) glDepthFunc(GL_LESS);
-
- cleanupgeom(cur);
+ if(shadowmap && mainpass) rendershadowmap();
+ setupgeom(cur);
+ if(doSM) pushshadowmap();
+
+ if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
+ cur.texgendim = -1;
+
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue;
+ blends += va->blends;
+ renderva(cur, va, RENDERPASS_LIGHTMAP, fogpass);
+ }
+ if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+ for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if(!va->texs || va->occluded < OCCLUDE_GEOM) continue;
+ else if((va->parent && va->parent->occluded >= OCCLUDE_BB) ||
+ (va->query && checkquery(va->query)))
+ {
+ va->occluded = OCCLUDE_BB;
+ continue;
+ }
+
+ blends += va->blends;
+ renderva(cur, va, RENDERPASS_LIGHTMAP, fogpass);
+ }
+ if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+ }
+
+ if(blends)
+ {
+ if(cur.vbuf) disablevbuf(cur);
+
+ if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+ cur.texgendim = -1;
+ cur.blending = true;
+ for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ {
+ if(!va->blends) continue;
+ if(refracting)
+ {
+ if(refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) continue;
+ if(ishiddencube(va->o, va->size)) continue;
+ if(va->occluded >= OCCLUDE_GEOM) continue;
+ }
+ else if(reflecting)
+ {
+ if(va->geommax.z <= reflectz) continue;
+ }
+ else if(va->occluded >= OCCLUDE_GEOM) continue;
+ if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
+ renderva(cur, va, RENDERPASS_LIGHTMAP_BLEND, fogpass);
+ }
+ if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+ cur.blending = false;
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ }
+
+ if(doSM) popshadowmap();
+
+ if(cur.vattribs) disablevattribs(cur);
+
+ if(foggedvas.length()) renderfoggedvas(cur, doOQ && !zpass);
+
+ if(causticspass)
+ {
+ if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); }
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+
+ setupcaustics(causticspass);
+ glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+ if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+ rendergeommultipass(cur, RENDERPASS_CAUSTICS, fogpass);
+ if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ }
+
+ if(multipassing) glDepthFunc(GL_LESS);
+
+ cleanupgeom(cur);
}
void renderalphageom(bool fogpass)
{
- static vector<vtxarray *> alphavas;
- alphavas.setsize(0);
- bool hasback = false;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
- {
- if(!va->alphatris) continue;
- if(refracting)
- {
- if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_BB) continue;
- if(ishiddencube(va->o, va->size)) continue;
- }
- else if(reflecting)
- {
- if(va->geommax.z <= reflectz) continue;
- }
- else
- {
- if(va->occluded >= OCCLUDE_BB) continue;
- }
- if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
- alphavas.add(va);
- if(va->alphabacktris) hasback = true;
- }
- if(alphavas.empty()) return;
-
- resetbatches();
-
- renderstate cur;
- cur.alphaing = 1;
-
- loop(front, 2) if(front || hasback)
- {
- cur.alphaing = front+1;
- if(!front) glCullFace(GL_FRONT);
- cur.vbuf = 0;
- cur.texgendim = -1;
- loopv(alphavas) renderva(cur, alphavas[i], RENDERPASS_Z);
- if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
- cur.colormask = true;
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
-
- if(cur.vattribs) disablevattribs(cur, false);
- if(cur.vbuf) disablevbuf(cur);
-
- setupgeom(cur);
-
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- cur.vbuf = 0;
- cur.texgendim = -1;
- cur.colorscale = vec(1, 1, 1);
- cur.alphascale = -1;
- loopv(alphavas) if(front || alphavas[i]->alphabacktris) renderva(cur, alphavas[i], RENDERPASS_LIGHTMAP, fogpass);
- if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
-
- cleanupgeom(cur);
-
- resetfogcolor();
- if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
- glDisable(GL_BLEND);
- glDepthFunc(GL_LESS);
- if(!front) glCullFace(GL_BACK);
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, fading ? GL_FALSE : GL_TRUE);
+ static vector<vtxarray *> alphavas;
+ alphavas.setsize(0);
+ bool hasback = false;
+ for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ {
+ if(!va->alphatris) continue;
+ if(refracting)
+ {
+ if((refracting < 0 ? va->geommin.z > reflectz : va->geommax.z <= reflectz) || va->occluded >= OCCLUDE_BB) continue;
+ if(ishiddencube(va->o, va->size)) continue;
+ }
+ else if(reflecting)
+ {
+ if(va->geommax.z <= reflectz) continue;
+ }
+ else
+ {
+ if(va->occluded >= OCCLUDE_BB) continue;
+ }
+ if(fogpass ? va->geommax.z <= reflectz-refractfog || !refractfog : va->curvfc==VFC_FOGGED) continue;
+ alphavas.add(va);
+ if(va->alphabacktris) hasback = true;
+ }
+ if(alphavas.empty()) return;
+
+ resetbatches();
+
+ renderstate cur;
+ cur.alphaing = 1;
+
+ loop(front, 2) if(front || hasback)
+ {
+ cur.alphaing = front+1;
+ if(!front) glCullFace(GL_FRONT);
+ cur.vbuf = 0;
+ cur.texgendim = -1;
+ loopv(alphavas) renderva(cur, alphavas[i], RENDERPASS_Z);
+ if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); }
+ cur.colormask = true;
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+ if(cur.vattribs) disablevattribs(cur, false);
+ if(cur.vbuf) disablevbuf(cur);
+
+ setupgeom(cur);
+
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ cur.vbuf = 0;
+ cur.texgendim = -1;
+ cur.colorscale = vec(1, 1, 1);
+ cur.alphascale = -1;
+ loopv(alphavas) if(front || alphavas[i]->alphabacktris) renderva(cur, alphavas[i], RENDERPASS_LIGHTMAP, fogpass);
+ if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
+
+ cleanupgeom(cur);
+
+ resetfogcolor();
+ if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
+ glDisable(GL_BLEND);
+ glDepthFunc(GL_LESS);
+ if(!front) glCullFace(GL_BACK);
+ }
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, fading ? GL_FALSE : GL_TRUE);
}
void findreflectedvas(vector<vtxarray *> &vas, int prevvfc = VFC_PART_VISIBLE)
{
- loopv(vas)
- {
- vtxarray *va = vas[i];
- if(prevvfc >= VFC_NOT_VISIBLE) va->curvfc = prevvfc;
- if(va->curvfc == VFC_FOGGED || va->curvfc == PVS_FOGGED || va->o.z+va->size <= reflectz || isfoggedcube(va->o, va->size)) continue;
- bool render = true;
- if(va->curvfc == VFC_FULL_VISIBLE)
- {
- if(va->occluded >= OCCLUDE_BB) continue;
- if(va->occluded >= OCCLUDE_GEOM) render = false;
- }
- else if(va->curvfc == PVS_FULL_VISIBLE) continue;
- if(render)
- {
- if(va->curvfc >= VFC_NOT_VISIBLE) va->distance = (int)vadist(va, camera1->o);
- vtxarray **vprev = &reflectedva, *vcur = reflectedva;
- while(vcur && va->distance > vcur->distance)
- {
- vprev = &vcur->rnext;
- vcur = vcur->rnext;
- }
- va->rnext = *vprev;
- *vprev = va;
- }
- if(va->children.length()) findreflectedvas(va->children, va->curvfc);
- }
+ loopv(vas)
+ {
+ vtxarray *va = vas[i];
+ if(prevvfc >= VFC_NOT_VISIBLE) va->curvfc = prevvfc;
+ if(va->curvfc == VFC_FOGGED || va->curvfc == PVS_FOGGED || va->o.z+va->size <= reflectz || isfoggedcube(va->o, va->size)) continue;
+ bool render = true;
+ if(va->curvfc == VFC_FULL_VISIBLE)
+ {
+ if(va->occluded >= OCCLUDE_BB) continue;
+ if(va->occluded >= OCCLUDE_GEOM) render = false;
+ }
+ else if(va->curvfc == PVS_FULL_VISIBLE) continue;
+ if(render)
+ {
+ if(va->curvfc >= VFC_NOT_VISIBLE) va->distance = (int)vadist(va, camera1->o);
+ vtxarray **vprev = &reflectedva, *vcur = reflectedva;
+ while(vcur && va->distance > vcur->distance)
+ {
+ vprev = &vcur->rnext;
+ vcur = vcur->rnext;
+ }
+ va->rnext = *vprev;
+ *vprev = va;
+ }
+ if(va->children.length()) findreflectedvas(va->children, va->curvfc);
+ }
}
void renderreflectedgeom(bool causticspass, bool fogpass)
{
- if(reflecting)
- {
- reflectedva = NULL;
- findreflectedvas(varoot);
- rendergeom(causticspass ? 1 : 0, fogpass);
- }
- else rendergeom(causticspass ? 1 : 0, fogpass);
+ if(reflecting)
+ {
+ reflectedva = NULL;
+ findreflectedvas(varoot);
+ rendergeom(causticspass ? 1 : 0, fogpass);
+ }
+ else rendergeom(causticspass ? 1 : 0, fogpass);
}
static vtxarray *prevskyva = NULL;
void renderskyva(vtxarray *va, bool explicitonly = false)
{
- if(!prevskyva || va->vbuf != prevskyva->vbuf)
- {
- gle::bindvbo(va->vbuf);
- gle::bindebo(va->skybuf);
- const vertex *ptr = 0;
- gle::vertexpointer(sizeof(vertex), ptr->pos.v);
- if(!prevskyva) gle::enablevertex();
- }
+ if(!prevskyva || va->vbuf != prevskyva->vbuf)
+ {
+ gle::bindvbo(va->vbuf);
+ gle::bindebo(va->skybuf);
+ const vertex *ptr = 0;
+ gle::vertexpointer(sizeof(vertex), ptr->pos.v);
+ if(!prevskyva) gle::enablevertex();
+ }
- drawvatris(va, explicitonly ? va->explicitsky : va->sky+va->explicitsky, explicitonly ? va->skydata+va->sky : va->skydata);
+ drawvatris(va, explicitonly ? va->explicitsky : va->sky+va->explicitsky, explicitonly ? va->skydata+va->sky : va->skydata);
- if(!explicitonly) xtraverts += va->sky/3;
- xtraverts += va->explicitsky/3;
+ if(!explicitonly) xtraverts += va->sky/3;
+ xtraverts += va->explicitsky/3;
- prevskyva = va;
+ prevskyva = va;
}
int renderedsky = 0, renderedexplicitsky = 0, renderedskyfaces = 0, renderedskyclip = INT_MAX;
static inline void updateskystats(vtxarray *va)
{
- renderedsky += va->sky;
- renderedexplicitsky += va->explicitsky;
- renderedskyfaces |= va->skyfaces&0x3F;
- if(!(va->skyfaces&0x1F) || camera1->o.z < va->skyclip) renderedskyclip = min(renderedskyclip, va->skyclip);
- else renderedskyclip = 0;
+ renderedsky += va->sky;
+ renderedexplicitsky += va->explicitsky;
+ renderedskyfaces |= va->skyfaces&0x3F;
+ if(!(va->skyfaces&0x1F) || camera1->o.z < va->skyclip) renderedskyclip = min(renderedskyclip, va->skyclip);
+ else renderedskyclip = 0;
}
void renderreflectedskyvas(vector<vtxarray *> &vas, int prevvfc = VFC_PART_VISIBLE)
{
- loopv(vas)
- {
- vtxarray *va = vas[i];
- if(prevvfc >= VFC_NOT_VISIBLE) va->curvfc = prevvfc;
- if((va->curvfc == VFC_FULL_VISIBLE && va->occluded >= OCCLUDE_BB) || va->curvfc==PVS_FULL_VISIBLE) continue;
- if(va->o.z+va->size <= reflectz || ishiddencube(va->o, va->size)) continue;
- if(va->sky+va->explicitsky)
- {
- updateskystats(va);
- renderskyva(va);
- }
- if(va->children.length()) renderreflectedskyvas(va->children, va->curvfc);
- }
+ loopv(vas)
+ {
+ vtxarray *va = vas[i];
+ if(prevvfc >= VFC_NOT_VISIBLE) va->curvfc = prevvfc;
+ if((va->curvfc == VFC_FULL_VISIBLE && va->occluded >= OCCLUDE_BB) || va->curvfc==PVS_FULL_VISIBLE) continue;
+ if(va->o.z+va->size <= reflectz || ishiddencube(va->o, va->size)) continue;
+ if(va->sky+va->explicitsky)
+ {
+ updateskystats(va);
+ renderskyva(va);
+ }
+ if(va->children.length()) renderreflectedskyvas(va->children, va->curvfc);
+ }
}
bool rendersky(bool explicitonly)
{
- prevskyva = NULL;
- renderedsky = renderedexplicitsky = renderedskyfaces = 0;
- renderedskyclip = INT_MAX;
-
- if(reflecting)
- {
- renderreflectedskyvas(varoot);
- }
- else for(vtxarray *va = visibleva; va; va = va->next)
- {
- if((va->occluded >= OCCLUDE_BB && va->skyfaces&0x80) || !(va->sky+va->explicitsky)) continue;
-
- // count possibly visible sky even if not actually rendered
- updateskystats(va);
- if(explicitonly && !va->explicitsky) continue;
- renderskyva(va, explicitonly);
- }
-
- if(prevskyva)
- {
- gle::disablevertex();
- gle::clearvbo();
- gle::clearebo();
- }
-
- return renderedsky+renderedexplicitsky > 0;
+ prevskyva = NULL;
+ renderedsky = renderedexplicitsky = renderedskyfaces = 0;
+ renderedskyclip = INT_MAX;
+
+ if(reflecting)
+ {
+ renderreflectedskyvas(varoot);
+ }
+ else for(vtxarray *va = visibleva; va; va = va->next)
+ {
+ if((va->occluded >= OCCLUDE_BB && va->skyfaces&0x80) || !(va->sky+va->explicitsky)) continue;
+
+ // count possibly visible sky even if not actually rendered
+ updateskystats(va);
+ if(explicitonly && !va->explicitsky) continue;
+ renderskyva(va, explicitonly);
+ }
+
+ if(prevskyva)
+ {
+ gle::disablevertex();
+ gle::clearvbo();
+ gle::clearebo();
+ }
+
+ return renderedsky+renderedexplicitsky > 0;
}