engine/console.o \
engine/decal.o \
engine/dynlight.o \
- engine/glare.o \
engine/lightmap.o \
engine/main.o \
engine/material.o \
engine/rendergl.o \
engine/rendermodel.o \
engine/renderparticles.o \
- engine/rendersky.o \
engine/rendertext.o \
engine/renderva.o \
engine/server.o \
engine/shadowmap.o \
engine/sound.o \
engine/texture.o \
- engine/water.o \
engine/world.o \
engine/worldio.o \
fpsgame/ai.o \
engine/dynlight.o: shared/glemu.h shared/iengine.h shared/igame.h
engine/dynlight.o: engine/world.h engine/octa.h engine/lightmap.h
engine/dynlight.o: engine/bih.h engine/texture.h engine/model.h
-engine/glare.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
-engine/glare.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
-engine/glare.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
-engine/glare.o: engine/lightmap.h engine/bih.h engine/texture.h
-engine/glare.o: engine/model.h engine/rendertarget.h
engine/lightmap.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
engine/lightmap.o: shared/ents.h shared/command.h shared/glexts.h
engine/lightmap.o: shared/glemu.h shared/iengine.h shared/igame.h
engine/renderparticles.o: engine/lightmap.h engine/bih.h engine/texture.h
engine/renderparticles.o: engine/model.h engine/rendertarget.h
engine/renderparticles.o: engine/depthfx.h engine/explosion.h engine/lightning.h
-engine/rendersky.o: engine/engine.h shared/cube.h shared/tools.h
-engine/rendersky.o: shared/geom.h shared/ents.h shared/command.h
-engine/rendersky.o: shared/glexts.h shared/glemu.h shared/iengine.h
-engine/rendersky.o: shared/igame.h engine/world.h engine/octa.h
-engine/rendersky.o: engine/lightmap.h engine/bih.h engine/texture.h
-engine/rendersky.o: engine/model.h
engine/rendertext.o: engine/engine.h shared/cube.h shared/tools.h
engine/rendertext.o: shared/geom.h shared/ents.h shared/command.h
engine/rendertext.o: shared/glexts.h shared/glemu.h shared/iengine.h
engine/texture.o: shared/glemu.h shared/iengine.h shared/igame.h
engine/texture.o: engine/world.h engine/octa.h engine/lightmap.h engine/bih.h
engine/texture.o: engine/texture.h engine/model.h
-engine/water.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
-engine/water.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
-engine/water.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
-engine/water.o: engine/lightmap.h engine/bih.h engine/texture.h
-engine/water.o: engine/model.h
engine/world.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
engine/world.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
engine/world.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
-VARFP(envmapmodels, 0, 1, 1, preloadmodelshaders(true));
VARFP(bumpmodels, 0, 1, 1, preloadmodelshaders(true));
VARP(fullbrightmodels, 0, 0, 200);
struct shaderparams
{
- float spec, ambient, glow, glowdelta, glowpulse, specglare, glowglare, fullbright, envmapmin, envmapmax, scrollu, scrollv, alphatest;
+ float spec, ambient, fullbright, envmapmin, envmapmax, scrollu, scrollv, alphatest;
- shaderparams() : spec(1.0f), ambient(0.3f), glow(3.0f), glowdelta(0), glowpulse(0), specglare(1), glowglare(1), fullbright(0), envmapmin(0), envmapmax(0), scrollu(0), scrollv(0), alphatest(0.9f) {}
+ shaderparams() : spec(1.0f), ambient(0.3f), fullbright(0), envmapmin(0), envmapmax(0), scrollu(0), scrollv(0), alphatest(0.9f) {}
};
struct shaderparamskey
curpulse -= floor(curpulse);
curglow += glowdelta*2*fabs(curpulse - 0.5f);
}
- LOCALPARAMF(maskscale, 0.5f*spec, 0.5f*curglow, 16*specglare, 4*glowglare);
LOCALPARAMF(texscroll, scrollu*lastmillis/1000.0f, scrollv*lastmillis/1000.0f);
if(envmapped()) LOCALPARAMF(envmapscale, envmapmin-envmapmax, envmapmax);
}
{
if(alphablend)
{
- if(!enablealphablend && !reflecting && !refracting)
+ if(!enablealphablend)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].ambient = ambient;
}
- void setglow(float glow, float delta, float pulse)
- {
- if(parts.empty()) loaddefaultparts();
- loopv(parts) loopvj(parts[i]->skins)
- {
- skin &s = parts[i]->skins[j];
- s.glow = glow;
- s.glowdelta = delta;
- s.glowpulse = pulse;
- }
- }
-
- void setglare(float specglare, float glowglare)
- {
- if(parts.empty()) loaddefaultparts();
- loopv(parts) loopvj(parts[i]->skins)
- {
- skin &s = parts[i]->skins[j];
- s.specglare = specglare;
- s.glowglare = glowglare;
- }
- }
-
void setalphatest(float alphatest)
{
if(parts.empty()) loaddefaultparts();
loopskins(meshname, s, s.ambient = ambient);
}
- static void setglow(char *meshname, int *percent, int *delta, float *pulse)
- {
- float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
- if(*percent>0) glow = *percent/100.0f;
- else if(*percent<0) glow = 0.0f;
- glowdelta -= glow;
- loopskins(meshname, s, { s.glow = glow; s.glowdelta = glowdelta; s.glowpulse = glowpulse; });
- }
-
- static void setglare(char *meshname, float *specglare, float *glowglare)
- {
- loopskins(meshname, s, { s.specglare = *specglare; s.glowglare = *glowglare; });
- }
-
static void setalphatest(char *meshname, float *cutoff)
{
loopskins(meshname, s, s.alphatest = max(0.0f, min(1.0f, *cutoff)));
loopskins(meshname, s, s.cullface = *cullface!=0);
}
- static void setenvmap(char *meshname, char *envmap)
- {
- Texture *tex = cubemapload(envmap);
- loopskins(meshname, s, s.envmap = tex);
- }
-
static void setbumpmap(char *meshname, char *normalmapfile)
{
Texture *normalmaptex = textureload(makerelpath(MDL::dir, normalmapfile), 0, true, false);
modelcommand(setskin, "skin", "sssff");
modelcommand(setspec, "spec", "si");
modelcommand(setambient, "ambient", "si");
- modelcommand(setglow, "glow", "siif");
- modelcommand(setglare, "glare", "sff");
modelcommand(setalphatest, "alphatest", "sf");
modelcommand(setalphablend, "alphablend", "si");
modelcommand(setcullface, "cullface", "si");
- modelcommand(setenvmap, "envmap", "ss");
modelcommand(setbumpmap, "bumpmap", "ss");
modelcommand(setfullbright, "fullbright", "sf");
modelcommand(setshader, "shader", "ss");
}
else
{
- if(flags&DF_INVMOD) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); zerofogcolor(); }
- else if(flags&DF_ADD) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); zerofogcolor(); }
+ if(flags&DF_INVMOD) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); }
+ else if(flags&DF_ADD) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); }
else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if(flags&DF_SATURATE) SETSHADER(saturatedecal);
- else foggedshader->set();
}
glBindTexture(GL_TEXTURE_2D, tex->id);
glDrawArrays(GL_TRIANGLES, 0, count);
xtravertsva += count;
- if(flags&(DF_ADD|DF_INVMOD)) resetfogcolor();
-
extern int intel_vertexarray_bug;
if(intel_vertexarray_bug) glFlush();
}
loopi(matsurfs)
{
materialsurface &m = matbuf[i];
- if(!isclipped(m.material&MATF_VOLUME)) { i += m.skip; continue; }
+ if(1) { i += m.skip; continue; }
int dim = dimension(m.orient), dc = dimcoord(m.orient);
if(dc ? decalnormal[dim] <= 0 : decalnormal[dim] >= 0) { i += m.skip; continue; }
int c = C[dim], r = R[dim];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
depthfxing = true;
- refracting = -1;
extern void renderdepthobstacles(const vec &bbmin, const vec &bbmax, float scale, float *ranges, int numranges);
float scale = depthfxscale;
}
renderdepthobstacles(depthfxmin, depthfxmax, scale, ranges, numranges);
- refracting = 0;
depthfxing = false;
return numdepthfxranges > 0;
bool binddepthfxtex()
{
- if(!reflecting && !refracting && depthfx && depthfxtex.rendertex && numdepthfxranges>0)
+ if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
{
glActiveTexture_(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, depthfxtex.rendertex);
void binddepthfxparams(float blend, float minblend = 0, bool allow = true, void *owner = NULL)
{
- if(!reflecting && !refracting && depthfx && depthfxtex.rendertex && numdepthfxranges>0)
+ if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
{
float scale = 0, offset = -1, texscale = 0;
if(!depthfxtex.highprecision())
dynlight &d = dynlights[j];
if(d.curradius <= 0) continue;
d.dist = camera1->o.dist(d.o) - d.curradius;
- if(d.dist > dynlightdist || isfoggedsphere(d.curradius, d.o))
+ if(d.dist > dynlightdist)
continue;
- if(reflecting || refracting > 0)
- {
- if(d.o.z + d.curradius < reflectz) continue;
- }
- else if(refracting < 0 && d.o.z - d.curradius > reflectz) continue;
e.o = d.o;
e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = d.curradius;
if(!collide(&e, vec(0, 0, 0), 0, false)) continue;
extern void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component = GL_RGB, GLenum target = GL_TEXTURE_2D, int pw = 0, int ph = 0, int pitch = 0, bool resize = true, GLenum format = GL_FALSE, bool swizzle = false);
extern void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin = 0);
extern void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin = 0);
-extern void renderpostfx();
-extern void initenvmaps();
-extern void genenvmaps();
-extern ushort closestenvmap(const vec &o);
-extern ushort closestenvmap(int orient, const ivec &co, int size);
-extern GLuint lookupenvmap(ushort emid);
-extern GLuint lookupenvmap(Slot &slot);
extern bool reloadtexture(Texture &tex);
extern bool reloadtexture(const char *name);
extern void setuptexcompress();
extern bool renderedgame;
extern const matrix4 viewmatrix;
extern matrix4 cammatrix, projmatrix, camprojmatrix, invcammatrix, invcamprojmatrix;
-extern bvec fogcolor;
-extern vec curfogcolor;
-extern int fog;
-extern float curfogstart, curfogend;
extern void gl_checkextensions();
extern void gl_init();
extern void screenquadoffset(float x, float y, float w, float h);
extern void screenquadoffset(float x, float y, float w, float h, float x2, float y2, float w2, float h2);
extern void hudquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1);
-extern void setfogcolor(const vec &v);
-extern void zerofogcolor();
-extern void resetfogcolor();
-extern void setfogdist(float start, float end);
-extern void clearfogdist();
-extern void resetfogdist();
extern void writecrosshairs(stream *f);
namespace modelpreview
extern void updatevabbs(bool force = false);
// renderva
-extern vtxarray *visibleva, *reflectedva;
+extern vtxarray *visibleva;
extern void visiblecubes(bool cull = true);
extern void setvfcP(float z = -1, const vec &bbmin = vec(-1, -1, -1), const vec &bbmax = vec(1, 1, 1));
extern void savevfcP();
extern void restorevfcP();
-extern void rendergeom(float causticspass = 0, bool fogpass = false);
+extern void rendergeom(bool fogpass = false);
extern void renderalphageom(bool fogpass = false);
extern void rendermapmodels();
-extern void renderreflectedgeom(bool causticspass = false, bool fogpass = false);
-extern void renderreflectedmapmodels();
extern void renderoutline();
extern bool rendersky(bool explicitonly = false);
-extern bool isfoggedsphere(float rad, const vec &cv);
extern int isvisiblesphere(float rad, const vec &cv);
extern bool bboccluded(const ivec &bo, const ivec &br);
extern occludequery *newquery(void *owner);
extern void rendermaterials();
extern int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask = MATF_VOLUME);
-// water
-extern int refracting, refractfog;
-extern bool reflecting, fading, fogging;
-extern float reflectz;
-extern int reflectdist, vertwater, waterrefract, waterreflect, waterfade, caustics, waterfallrefract;
-
-#define GETMATIDXVAR(name, var, type) \
- type get##name##var(int mat) \
- { \
- switch(mat&MATF_INDEX) \
- { \
- default: case 0: return name##var; \
- case 1: return name##2##var; \
- case 2: return name##3##var; \
- case 3: return name##4##var; \
- } \
- }
-
-extern const bvec &getwatercolor(int mat);
-extern const bvec &getwaterfallcolor(int mat);
-extern int getwaterfog(int mat);
-extern const bvec &getlavacolor(int mat);
-extern int getlavafog(int mat);
-extern const bvec &getglasscolor(int mat);
-
-extern void cleanreflections();
-extern void queryreflections();
-extern void drawreflections();
-extern void renderwater();
-extern void setuplava(Texture *tex, float scale);
-extern void renderlava(const materialsurface &m);
-extern void flushlava();
-extern void loadcaustics(bool force = false);
-extern void preloadwatershaders(bool force = false);
-
-// glare
-extern bool glaring;
-
-extern void drawglaretex();
-extern void addglare();
-
// depthfx
extern bool depthfxing;
extern void cleardecals();
extern void renderdecals(bool mainpass = false);
-// rendersky
-extern int explicitsky;
-extern double skyarea;
-extern char *skybox;
-
-extern void setupsky();
-extern void drawskybox(int farplane, bool limited, bool force = false);
-extern bool limitsky();
-extern bool shouldrenderskyenvmap();
-extern bool shouldclearskyboxglare();
-
// 3dgui
extern void g3d_render();
extern void g3d_render2d();
void startrender()
{
- if(glaring) SETSHADER(explosionglare);
- else if(!reflecting && !refracting && depthfx && depthfxtex.rendertex && numdepthfxranges>0)
+ if(depthfx && depthfxtex.rendertex && numdepthfxranges>0)
{
if(!depthfxtex.highprecision()) SETSHADER(explosionsoft8);
else SETSHADER(explosionsoft);
size = p->fade ? float(ts)/p->fade : 1,
psize = (p->size + pmax * size)*WOBBLE;
if(2*(p->size + pmax)*WOBBLE < depthfxblend ||
- (!depthfxtex.highprecision() && !depthfxtex.emulatehighprecision() && psize > depthfxscale - depthfxbias) ||
- isfoggedsphere(psize, p->o)) continue;
+ (!depthfxtex.highprecision() && !depthfxtex.emulatehighprecision() && psize > depthfxscale - depthfxbias) || ) continue;
e.o = p->o;
e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = psize;
void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts)
{
- float pmax = p->val,
- size = p->fade ? float(ts)/p->fade : 1,
- psize = p->size + pmax * size;
-
- if(isfoggedsphere(psize*WOBBLE, p->o)) return;
+ float pmax = p->val, size = p->fade ? float(ts)/p->fade : 1, psize = p->size + pmax * size;
vec dir = vec(o).sub(camera1->o), s, t;
float dist = dir.magnitude();
}
else
{
- if(reflecting) { dir.z = o.z - reflectz; dist = dir.magnitude(); }
float mag2 = dir.magnitude2();
dir.x /= mag2;
dir.y /= mag2;
LOCALPARAMF(blendparams, inside ? 0.5f : 4, inside ? 0.25f : 0);
binddepthfxparams(depthfxblend, inside ? blend/(2*255.0f) : 0, 2*(p->size + pmax)*WOBBLE >= depthfxblend, p);
- int passes = !reflecting && !refracting && inside ? 2 : 1;
+ int passes = inside ? 2 : 1;
loopi(passes)
{
gle::color(p->color, i ? blend/2 : blend);
+++ /dev/null
-#include "engine.h"
-#include "rendertarget.h"
-
-static struct glaretexture : rendertarget
-{
- bool dorender()
- {
- extern void drawglare();
- drawglare();
- return true;
- }
-} glaretex;
-
-void cleanupglare()
-{
- glaretex.cleanup(true);
-}
-
-VARFP(glaresize, 6, 8, 10, cleanupglare());
-VARP(glare, 0, 0, 1);
-VARP(blurglare, 0, 4, 7);
-VARP(blurglareaspect, 0, 1, 1);
-VARP(blurglaresigma, 1, 50, 200);
-
-bool glaring = false;
-
-void drawglaretex()
-{
- if(!glare) return;
-
- int w = 1<<glaresize, h = 1<<glaresize, blury = blurglare;
- if(blurglare && blurglareaspect)
- {
- while(h > (1<<5) && (screenw*h)/w >= (screenh*4)/3) h /= 2;
- blury = ((1 + 4*blurglare)*(screenw*h)/w + screenh*2)/(screenh*4);
- blury = clamp(blury, 1, MAXBLURRADIUS);
- }
-
- glaretex.render(w, h, blurglare, blurglaresigma/100.0f, blury);
-}
-
-FVAR(glaremod, 0.5f, 0.75f, 1);
-FVARP(glarescale, 0, 1, 8);
-
-void addglare()
-{
- if(!glare) return;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
-
- SETSHADER(screenrect);
-
- glBindTexture(GL_TEXTURE_2D, glaretex.rendertex);
-
- float g = glarescale*glaremod;
- gle::colorf(g, g, g);
-
- screenquad(1, 1);
-
- glDisable(GL_BLEND);
-}
-
VARR(lighterror, 1, 8, 16);
VARR(bumperror, 1, 3, 16);
VARR(lightlod, 0, 0, 10);
-bvec ambientcolor(0x19, 0x19, 0x19), skylightcolor(0, 0, 0);
+bvec ambientcolor(36, 24, 12);
HVARFR(ambient, 1, 0x191919, 0xFFFFFF,
{
if(ambient <= 255) ambient |= (ambient<<8) | (ambient<<16);
ambientcolor = bvec((ambient>>16)&0xFF, (ambient>>8)&0xFF, ambient&0xFF);
});
-HVARFR(skylight, 0, 0, 0xFFFFFF,
-{
- if(skylight <= 255) skylight |= (skylight<<8) | (skylight<<16);
- skylightcolor = bvec((skylight>>16)&0xFF, (skylight>>8)&0xFF, skylight&0xFF);
-});
-
-extern void setupsunlight();
-bvec sunlightcolor(0, 0, 0);
-HVARFR(sunlight, 0, 0, 0xFFFFFF,
-{
- if(sunlight <= 255) sunlight |= (sunlight<<8) | (sunlight<<16);
- sunlightcolor = bvec((sunlight>>16)&0xFF, (sunlight>>8)&0xFF, sunlight&0xFF);
- setupsunlight();
-});
-FVARFR(sunlightscale, 0, 1, 16, setupsunlight());
-vec sunlightdir(0, 0, 1);
-extern void setsunlightdir();
-VARFR(sunlightyaw, 0, 0, 360, setsunlightdir());
-VARFR(sunlightpitch, -90, 90, 90, setsunlightdir());
-
-void setsunlightdir()
-{
- sunlightdir = vec(sunlightyaw*RAD, sunlightpitch*RAD);
- loopk(3) if(fabs(sunlightdir[k]) < 1e-5f) sunlightdir[k] = 0;
- sunlightdir.normalize();
- setupsunlight();
-}
-
-entity sunlightent;
-void setupsunlight()
-{
- memclear(sunlightent);
- sunlightent.type = ET_LIGHT;
- sunlightent.attr1 = 0;
- sunlightent.attr2 = int(sunlightcolor.x*sunlightscale);
- sunlightent.attr3 = int(sunlightcolor.y*sunlightscale);
- sunlightent.attr4 = int(sunlightcolor.z*sunlightscale);
- float dist = min(min(sunlightdir.x ? 1/fabs(sunlightdir.x) : 1e16f, sunlightdir.y ? 1/fabs(sunlightdir.y) : 1e16f), sunlightdir.z ? 1/fabs(sunlightdir.z) : 1e16f);
- sunlightent.o = vec(sunlightdir).mul(dist*worldsize).add(vec(worldsize/2, worldsize/2, worldsize/2));
-}
-
-VARR(skytexturelight, 0, 1, 1);
-extern int useskytexture;
static const surfaceinfo brightsurfaces[6] =
{
g += intensity * float(light.attr3);
b += intensity * float(light.attr4);
}
- if(sunlight)
- {
- float angle = sunlightdir.dot(normal);
- if(angle > 0 &&
- (!lmshadows ||
- shadowray(w->shadowraycache, vec(sunlightdir).mul(tolerance).add(target), sunlightdir, 1e16f, RAY_SHADOW | (lmshadows > 1 ? RAY_ALPHAPOLY : 0) | (skytexturelight ? RAY_SKIPSKY | (useskytexture ? RAY_SKYTEX : 0) : 0)) > 1e15f))
- {
- float intensity;
- switch(w->type&LM_TYPE)
- {
- case LM_BUMPMAP0:
- intensity = 1;
- avgray.add(sunlightdir);
- break;
- default:
- intensity = angle;
- break;
- }
- r += intensity * (sunlightcolor.x*sunlightscale);
- g += intensity * (sunlightcolor.y*sunlightscale);
- b += intensity * (sunlightcolor.z*sunlightscale);
- }
- }
switch(w->type&LM_TYPE)
{
case LM_BUMPMAP0:
return false;
}
-static void calcskylight(lightmapworker *w, const vec &o, const vec &normal, float tolerance, uchar *skylight, int flags = RAY_ALPHAPOLY, extentity *t = NULL)
-{
- static const vec rays[17] =
- {
- vec(cosf(21*RAD)*cosf(50*RAD), sinf(21*RAD)*cosf(50*RAD), sinf(50*RAD)),
- vec(cosf(111*RAD)*cosf(50*RAD), sinf(111*RAD)*cosf(50*RAD), sinf(50*RAD)),
- vec(cosf(201*RAD)*cosf(50*RAD), sinf(201*RAD)*cosf(50*RAD), sinf(50*RAD)),
- vec(cosf(291*RAD)*cosf(50*RAD), sinf(291*RAD)*cosf(50*RAD), sinf(50*RAD)),
-
- vec(cosf(66*RAD)*cosf(70*RAD), sinf(66*RAD)*cosf(70*RAD), sinf(70*RAD)),
- vec(cosf(156*RAD)*cosf(70*RAD), sinf(156*RAD)*cosf(70*RAD), sinf(70*RAD)),
- vec(cosf(246*RAD)*cosf(70*RAD), sinf(246*RAD)*cosf(70*RAD), sinf(70*RAD)),
- vec(cosf(336*RAD)*cosf(70*RAD), sinf(336*RAD)*cosf(70*RAD), sinf(70*RAD)),
-
- vec(0, 0, 1),
-
- vec(cosf(43*RAD)*cosf(60*RAD), sinf(43*RAD)*cosf(60*RAD), sinf(60*RAD)),
- vec(cosf(133*RAD)*cosf(60*RAD), sinf(133*RAD)*cosf(60*RAD), sinf(60*RAD)),
- vec(cosf(223*RAD)*cosf(60*RAD), sinf(223*RAD)*cosf(60*RAD), sinf(60*RAD)),
- vec(cosf(313*RAD)*cosf(60*RAD), sinf(313*RAD)*cosf(60*RAD), sinf(60*RAD)),
-
- vec(cosf(88*RAD)*cosf(80*RAD), sinf(88*RAD)*cosf(80*RAD), sinf(80*RAD)),
- vec(cosf(178*RAD)*cosf(80*RAD), sinf(178*RAD)*cosf(80*RAD), sinf(80*RAD)),
- vec(cosf(268*RAD)*cosf(80*RAD), sinf(268*RAD)*cosf(80*RAD), sinf(80*RAD)),
- vec(cosf(358*RAD)*cosf(80*RAD), sinf(358*RAD)*cosf(80*RAD), sinf(80*RAD)),
-
- };
- flags |= RAY_SHADOW;
- if(skytexturelight) flags |= RAY_SKIPSKY | (useskytexture ? RAY_SKYTEX : 0);
- int hit = 0;
- if(w) loopi(17)
- {
- if(normal.dot(rays[i])>=0 && shadowray(w->shadowraycache, vec(rays[i]).mul(tolerance).add(o), rays[i], 1e16f, flags, t)>1e15f) hit++;
- }
- else loopi(17)
- {
- if(normal.dot(rays[i])>=0 && shadowray(vec(rays[i]).mul(tolerance).add(o), rays[i], 1e16f, flags, t)>1e15f) hit++;
- }
-
- loopk(3) skylight[k] = uchar(ambientcolor[k] + (max(skylightcolor[k], ambientcolor[k]) - ambientcolor[k])*hit/17.0f);
-}
-
-static inline bool hasskylight()
-{
- return skylightcolor[0]>ambientcolor[0] || skylightcolor[1]>ambientcolor[1] || skylightcolor[2]>ambientcolor[2];
-}
-
-VARR(blurlms, 0, 0, 2);
-VARR(blurskylight, 0, 0, 2);
-
static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha)
{
alpha = lookupblendmap(w->blendmapcache, pos);
float t = EDGE_TOLERANCE(x, y) * tolerance;
vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2);
lightused |= generatelumel(w, t, 0, w->lights, u, vec(normal).normalize(), *sample, x, y);
- if(hasskylight())
- {
- if((w->type&LM_TYPE)==LM_BUMPMAP0 || !adaptivesample || sample->x<skylightcolor[0] || sample->y<skylightcolor[1] || sample->z<skylightcolor[2])
- calcskylight(w, u, normal, t, skylight, lmshadows > 1 ? RAY_ALPHAPOLY : 0);
- else loopk(3) skylight[k] = max(skylightcolor[k], ambientcolor[k]);
- }
- else loopk(3) skylight[k] = ambientcolor[k];
- if(w->type&LM_ALPHA) generatealpha(w, t, u, skylight[3]);
sample += aasample;
}
sample += aasample;
static int finishlightmap(lightmapworker *w)
{
- if(hasskylight() && blurskylight && (w->w>1 || w->h>1))
- {
- blurtexture(blurskylight, w->bpp, w->w, w->h, w->blur, w->ambient);
- swap(w->blur, w->ambient);
- }
vec *sample = w->colordata;
int aasample = min(1 << lmaa, 4), stride = aasample*(w->w+1);
float weight = 1.0f / (1.0f + 4.0f*lmaa),
cweight = weight * (lmaa == 3 ? 5.0f : 1.0f);
- uchar *skylight = w->ambient;
vec *ray = w->raydata;
uchar *dstcolor = blurlms && (w->w > 1 || w->h > 1) ? w->blur : w->colorbuf;
uchar mincolor[4] = { 255, 255, 255, 255 }, maxcolor[4] = { 0, 0, 0, 0 };
int r = int(center.x*cweight + l.x*weight),
g = int(center.y*cweight + l.y*weight),
b = int(center.z*cweight + l.z*weight),
- ar = skylight[0], ag = skylight[1], ab = skylight[2];
+ ar = w->ambient[0], ag = w->ambient[1], ab = w->ambient[2];
dstcolor[0] = max(ar, r);
dstcolor[1] = max(ag, g);
dstcolor[2] = max(ab, b);
}
if(w->type&LM_ALPHA)
{
- dstcolor[3] = skylight[3];
+ dstcolor[3] = ambientcolor[3];
mincolor[3] = min(mincolor[3], dstcolor[3]);
maxcolor[3] = max(maxcolor[3], dstcolor[3]);
}
if(ray->iszero()) dstray[0] = bvec(128, 128, 255);
else
{
- // bias the normals towards the amount of ambient/skylight in the lumel
- // this is necessary to prevent the light values in shaders from dropping too far below the skylight (to the ambient) if N.L is small
ray->normalize();
int l = max(r, max(g, b)), a = max(ar, max(ag, ab));
ray->mul(max(l-a, 0));
dstray++;
}
dstcolor += w->bpp;
- skylight += w->bpp;
}
sample += aasample;
}
}
}
if(vslot.layer && (setblendmaporigin(w->blendmapcache, ivec(cx, cy, cz), size) || slot.layermask)) return true;
- return w->lights.length() || hasskylight() || sunlight;
+ return w->lights.length();
}
static int packlightmaps(lightmapworker *w = NULL)
shouldlightents = true;
}
-static inline void fastskylight(const vec &o, float tolerance, uchar *skylight, int flags = RAY_ALPHAPOLY, extentity *t = NULL, bool fast = false)
-{
- flags |= RAY_SHADOW;
- if(skytexturelight) flags |= RAY_SKIPSKY | (useskytexture ? RAY_SKYTEX : 0);
- if(fast)
- {
- static const vec ray(0, 0, 1);
- if(shadowray(vec(ray).mul(tolerance).add(o), ray, 1e16f, flags, t)>1e15f)
- memcpy(skylight, skylightcolor.v, 3);
- else memcpy(skylight, ambientcolor.v, 3);
- }
- else
- {
- static const vec rays[5] =
- {
- vec(cosf(66*RAD)*cosf(65*RAD), sinf(66*RAD)*cosf(65*RAD), sinf(65*RAD)),
- vec(cosf(156*RAD)*cosf(65*RAD), sinf(156*RAD)*cosf(65*RAD), sinf(65*RAD)),
- vec(cosf(246*RAD)*cosf(65*RAD), sinf(246*RAD)*cosf(65*RAD), sinf(65*RAD)),
- vec(cosf(336*RAD)*cosf(65*RAD), sinf(336*RAD)*cosf(65*RAD), sinf(65*RAD)),
- vec(0, 0, 1),
- };
- int hit = 0;
- loopi(5) if(shadowray(vec(rays[i]).mul(tolerance).add(o), rays[i], 1e16f, flags, t)>1e15f) hit++;
- loopk(3) skylight[k] = uchar(ambientcolor[k] + (max(skylightcolor[k], ambientcolor[k]) - ambientcolor[k])*hit/5.0f);
- }
-}
-
void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity *t, float ambient)
{
if((fullbright && editmode) || lightmaps.empty())
intensity *= spotatten;
}
- //if(target==player->o)
- //{
- // conoutf(CON_DEBUG, "%d - %f %f", i, intensity, mag);
- //}
-
vec lightcol = vec(e.attr2, e.attr3, e.attr4).mul(1.0f/255);
color.add(vec(lightcol).mul(intensity));
dir.add(vec(ray).mul(-intensity*lightcol.x*lightcol.y*lightcol.z));
}
- if(sunlight && shadowray(target, sunlightdir, 1e16f, RAY_SHADOW | RAY_POLY | (skytexturelight ? RAY_SKIPSKY | (useskytexture ? RAY_SKYTEX : 0) : 0), t) > 1e15f)
- {
- vec lightcol = vec(sunlightcolor.x, sunlightcolor.y, sunlightcolor.z).mul(sunlightscale/255);
- color.add(lightcol);
- dir.add(vec(sunlightdir).mul(lightcol.x*lightcol.y*lightcol.z));
- }
- if(hasskylight())
- {
- uchar skylight[3];
- if(t) calcskylight(NULL, target, vec(0, 0, 0), 0.5f, skylight, RAY_POLY, t);
- else fastskylight(target, 0.5f, skylight, RAY_POLY, t, fast);
- loopk(3) color[k] = min(1.5f, max(max(skylight[k]/255.0f, ambient), color[k]));
- }
- else loopk(3) color[k] = min(1.5f, max(max(ambientcolor[k]/255.0f, ambient), color[k]));
+ loopk(3) color[k] = min(1.5f, max(max(ambientcolor[k]/255.0f, ambient), color[k]));
if(dir.iszero()) dir = vec(0, 0, 1);
else dir.normalize();
}
entity *brightestlight(const vec &target, const vec &dir)
{
- if(sunlight && sunlightdir.dot(dir) > 0 && shadowray(target, sunlightdir, 1e16f, RAY_SHADOW | RAY_POLY | (skytexturelight ? RAY_SKIPSKY | (useskytexture ? RAY_SKYTEX : 0) : 0)) > 1e15f)
- return &sunlightent;
const vector<extentity *> &ents = entities::getents();
const vector<int> &lights = checklightcache(int(target.x), int(target.y));
extentity *brightest = NULL;
extern vector<LightMapTexture> lightmaptexs;
-extern bvec ambientcolor, skylightcolor, sunlightcolor;
-extern float sunlightscale;
-extern vec sunlightdir;
+extern bvec ambientcolor;
extern void clearlights();
extern void initlights();
extern void cleanuplightmaps();
extern void cleanupblendmap();
extern void cleanshadowmap();
- extern void cleanreflections();
- extern void cleanupglare();
extern void cleanupdepthfx();
cleanupva();
cleanupparticles();
cleanuplightmaps();
cleanupblendmap();
cleanshadowmap();
- cleanreflections();
- cleanupglare();
cleanupdepthfx();
cleanupshaders();
cleanupgl();
bvec4(0, 0, 0x7F)
};
-static void renderwaterfall(const materialsurface &m, float offset)
-{
- if(gle::attribbuf.empty())
- {
- gle::defvertex();
- gle::defnormal(4, GL_BYTE);
- gle::begin(GL_QUADS);
- }
- float x = m.o.x, y = m.o.y, zmin = m.o.z, zmax = zmin;
- if(m.ends&1) zmin += -WATER_OFFSET-WATER_AMPLITUDE;
- if(m.ends&2) zmax += wfwave;
- int csize = m.csize, rsize = m.rsize;
- switch(m.orient)
- {
- #define GENFACEORIENT(orient, v0, v1, v2, v3) \
- case orient: v0 v1 v2 v3 break;
- #define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) \
- { \
- gle::attribf(mx sx, my sy, mz sz); \
- gle::attrib(matnormals[orient]); \
- }
- GENFACEVERTSXY(x, x, y, y, zmin, zmax, /**/, + csize, /**/, + rsize, + offset, - offset)
- #undef GENFACEORIENT
- #undef GENFACEVERT
- }
-}
-
static void drawmaterial(const materialsurface &m, float offset, const bvec4 &color)
{
if(gle::attribbuf.empty())
cur->visible == start->visible &&
cur->o[dim] == start->o[dim])
++cur;
- if(!isliquid(start->material&MATF_VOLUME) || start->orient != O_TOP || !vertwater)
+ if(start->orient != O_TOP || !vertwater)
{
if(start!=matbuf) memmove(matbuf, start, (cur-start)*sizeof(materialsurface));
matbuf += mergemats(matbuf, cur-start);
return matsurfs - (end-matbuf);
}
-struct waterinfo
-{
- materialsurface *m;
- double depth, area;
-};
-
void setupmaterials(int start, int len)
{
int hasmat = 0;
- vector<waterinfo> water;
unionfind uf;
if(!len) len = valist.length();
for(int i = start; i < len; i++)
{
materialsurface &m = va->matbuf[j];
int matvol = m.material&MATF_VOLUME;
- if(matvol==MAT_WATER && m.orient==O_TOP)
- {
- m.index = water.length();
- loopvk(water)
- {
- materialsurface &n = *water[k].m;
- if(m.material!=n.material || m.o.z!=n.o.z) continue;
- if(n.o.x+n.rsize==m.o.x || m.o.x+m.rsize==n.o.x)
- {
- if(n.o.y+n.csize>m.o.y && n.o.y<m.o.y+m.csize) uf.unite(m.index, n.index);
- }
- else if(n.o.y+n.csize==m.o.y || m.o.y+m.csize==n.o.y)
- {
- if(n.o.x+n.rsize>m.o.x && n.o.x<m.o.x+m.rsize) uf.unite(m.index, n.index);
- }
- }
- waterinfo &wi = water.add();
- wi.m = &m;
- vec center(m.o.x+m.rsize/2, m.o.y+m.csize/2, m.o.z-WATER_OFFSET);
- m.light = brightestlight(center, vec(0, 0, 1));
- float depth = raycube(center, vec(0, 0, -1), 10000);
- wi.depth = double(depth)*m.rsize*m.csize;
- wi.area = m.rsize*m.csize;
- }
- else if(isliquid(matvol) && m.orient!=O_BOTTOM && m.orient!=O_TOP)
- {
- m.ends = 0;
- int dim = dimension(m.orient), coord = dimcoord(m.orient);
- ivec o(m.o);
- o.z -= 1;
- o[dim] += coord ? 1 : -1;
- int minc = o[dim^1], maxc = minc + (C[dim]==2 ? m.rsize : m.csize);
- ivec co;
- int csize;
- while(o[dim^1] < maxc)
- {
- cube &c = lookupcube(o, 0, co, csize);
- if(isliquid(c.material&MATF_VOLUME)) { m.ends |= 1; break; }
- o[dim^1] += csize;
- }
- o[dim^1] = minc;
- o.z += R[dim]==2 ? m.rsize : m.csize;
- o[dim] -= coord ? 2 : -2;
- while(o[dim^1] < maxc)
- {
- cube &c = lookupcube(o, 0, co, csize);
- if(visiblematerial(c, O_TOP, co, csize)) { m.ends |= 2; break; }
- o[dim^1] += csize;
- }
- }
- else if(matvol==MAT_GLASS)
- {
- int dim = dimension(m.orient);
- vec center(m.o);
- center[R[dim]] += m.rsize/2;
- center[C[dim]] += m.csize/2;
- m.envmap = closestenvmap(center);
- }
if(matvol) hasmat |= 1<<m.material;
m.skip = 0;
if(skip && m.material == skip->material && m.orient == skip->orient && skip->skip < 0xFFFF)
skip = &m;
}
}
- loopv(water)
- {
- int root = uf.find(i);
- if(i==root) continue;
- materialsurface &m = *water[i].m, &n = *water[root].m;
- if(m.light && (!m.light->attr1 || !n.light || (n.light->attr1 && m.light->attr1 > n.light->attr1))) n.light = m.light;
- water[root].depth += water[i].depth;
- water[root].area += water[i].area;
- }
- loopv(water)
- {
- int root = uf.find(i);
- water[i].m->light = water[root].m->light;
- water[i].m->depth = (short)(water[root].depth/water[root].area);
- }
- if(hasmat&(0xF<<MAT_WATER))
- {
- loadcaustics(true);
- preloadwatershaders(true);
- loopi(4) if(hasmat&(1<<(MAT_WATER+i))) lookupmaterialslot(MAT_WATER+i);
- }
- if(hasmat&(0xF<<MAT_LAVA))
- {
- useshaderbyname("lava");
- useshaderbyname("lavaglare");
- loopi(4) if(hasmat&(1<<(MAT_LAVA+i))) lookupmaterialslot(MAT_LAVA+i);
- }
- if(hasmat&(0xF<<MAT_GLASS)) useshaderbyname("glass");
}
VARP(showmat, 0, 1, 1);
void sortmaterials(vector<materialsurface *> &vismats)
{
sortorigin = ivec(camera1->o);
- if(reflecting) sortorigin.z = int(reflectz - (camera1->o.z - reflectz));
vec dir;
- vecfromyawpitch(camera1->yaw, reflecting ? -camera1->pitch : camera1->pitch, 1, 0, dir);
+ vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir);
loopi(3) { dir[i] = fabs(dir[i]); sortdim[i] = i; }
if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]);
if(dir[sortdim[1]] > dir[sortdim[0]]) swap(sortdim[1], sortdim[0]);
if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]);
- for(vtxarray *va = reflecting ? reflectedva : visibleva; va; va = reflecting ? va->rnext : va->next)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
if(!va->matsurfs || va->occluded >= OCCLUDE_BB) continue;
- if(reflecting || refracting>0 ? va->o.z+va->size <= reflectz : va->o.z >= reflectz) continue;
loopi(va->matsurfs)
{
materialsurface &m = va->matbuf[i];
if(!editmode || !showmat || drawtex)
{
int matvol = m.material&MATF_VOLUME;
- if(matvol==MAT_WATER && (m.orient==O_TOP || (refracting<0 && reflectz>worldsize))) { i += m.skip; continue; }
if(m.visible == MATSURF_EDIT_ONLY) { i += m.skip; continue; }
if(glaring && matvol!=MAT_LAVA) { i += m.skip; continue; }
}
}
}
-VARFP(waterfallenv, 0, 1, 1, preloadwatershaders());
-
static inline void changematerial(int mat, int orient)
{
switch(mat&~MATF_INDEX)
glDisable(GL_CULL_FACE);
MSlot *mslot = NULL;
- int lastorient = -1, lastmat = -1, usedwaterfall = -1;
+ int lastorient = -1, lastmat = -1;
bool depth = true, blended = false;
ushort envmapped = EMID_NONE;
GLOBALPARAM(camera, camera1->o);
- int lastfogtype = 1;
if(editmode && showmat && !drawtex)
{
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
glEnable(GL_BLEND); blended = true;
- foggednotextureshader->set();
- zerofogcolor(); lastfogtype = 0;
bvec4 color(0, 0, 0, 0);
loopv(vismats)
{
}
xtraverts += gle::end();
}
- else loopv(vismats)
- {
- const materialsurface &m = *vismats[i];
- int matvol = m.material&~MATF_INDEX;
- if(lastmat!=m.material || lastorient!=m.orient || (matvol==MAT_GLASS && envmapped && m.envmap != envmapped))
- {
- int fogtype = lastfogtype;
- switch(matvol)
- {
- case MAT_WATER:
- if(m.orient == O_TOP) continue;
- if(lastmat == m.material) break;
- mslot = &lookupmaterialslot(m.material, false);
- if(!mslot->loaded || !mslot->sts.inrange(1)) continue;
- else
- {
- changematerial(lastmat, lastorient);
- glBindTexture(GL_TEXTURE_2D, mslot->sts[1].t->id);
-
- bvec wfcol = getwaterfallcolor(m.material);
- if(wfcol.iszero()) wfcol = getwatercolor(m.material);
- gle::color(wfcol, 192);
-
- int wfog = getwaterfog(m.material);
- if(!wfog && !waterfallenv)
- {
- foggednotextureshader->set();
- fogtype = 1;
- if(blended) { glDisable(GL_BLEND); blended = false; }
- if(!depth) { glDepthMask(GL_TRUE); depth = true; }
- }
- else if((!waterfallrefract || reflecting || refracting) && !waterfallenv)
- {
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
- SETSHADER(waterfall);
- fogtype = 0;
- if(!blended) { glEnable(GL_BLEND); blended = true; }
- if(depth) { glDepthMask(GL_FALSE); depth = false; }
- }
- else
- {
- fogtype = 1;
-
- if(waterfallrefract && wfog && !reflecting && !refracting)
- {
- if(waterfallenv) SETSHADER(waterfallenvrefract);
- else SETSHADER(waterfallrefract);
- if(blended) { glDisable(GL_BLEND); blended = false; }
- if(!depth) { glDepthMask(GL_TRUE); depth = true; }
- }
- else
- {
- SETSHADER(waterfallenv);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if(wfog)
- {
- if(!blended) { glEnable(GL_BLEND); blended = true; }
- if(depth) { glDepthMask(GL_FALSE); depth = false; }
- }
- else
- {
- if(blended) { glDisable(GL_BLEND); blended = false; }
- if(!depth) { glDepthMask(GL_TRUE); depth = true; }
- }
- }
-
- if(usedwaterfall != m.material)
- {
- Texture *dudv = mslot->sts.inrange(5) ? mslot->sts[5].t : notexture;
- float scale = TEX_SCALE/(dudv->ys*mslot->scale);
- LOCALPARAMF(dudvoffset, 0, scale*16*lastmillis/1000.0f);
-
- glActiveTexture_(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, mslot->sts.inrange(4) ? mslot->sts[4].t->id : notexture->id);
- glActiveTexture_(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, mslot->sts.inrange(5) ? mslot->sts[5].t->id : notexture->id);
- if(waterfallenv)
- {
- glActiveTexture_(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_CUBE_MAP, lookupenvmap(*mslot));
- }
- if(waterfallrefract && (!reflecting || !refracting) && usedwaterfall < 0)
- {
- glActiveTexture_(GL_TEXTURE4);
- extern void setupwaterfallrefract();
- setupwaterfallrefract();
- }
- glActiveTexture_(GL_TEXTURE0);
-
- usedwaterfall = m.material;
- }
- }
- float angle = fmod(float(lastmillis/600.0f/(2*M_PI)), 1.0f),
- s = angle - int(angle) - 0.5f;
- s *= 8 - fabs(s)*16;
- wfwave = vertwater ? WATER_AMPLITUDE*s-WATER_OFFSET : -WATER_OFFSET;
- float scroll = 16.0f*lastmillis/1000.0f;
- float xscale = TEX_SCALE/(mslot->sts[1].t->xs*mslot->scale);
- float yscale = -TEX_SCALE/(mslot->sts[1].t->ys*mslot->scale);
- LOCALPARAMF(waterfalltexgen, xscale, yscale, 0.0f, scroll);
- }
- break;
-
- case MAT_LAVA:
- if(lastmat==m.material && lastorient!=O_TOP && m.orient!=O_TOP) break;
- mslot = &lookupmaterialslot(m.material, false);
- if(!mslot->loaded) continue;
- else
- {
- int subslot = m.orient==O_TOP ? 0 : 1;
- if(!mslot->sts.inrange(subslot)) continue;
- changematerial(lastmat, lastorient);
- glBindTexture(GL_TEXTURE_2D, mslot->sts[subslot].t->id);
- }
- if(lastmat!=m.material)
- {
- if(!depth) { glDepthMask(GL_TRUE); depth = true; }
- if(blended) { glDisable(GL_BLEND); blended = false; }
- float t = lastmillis/2000.0f;
- t -= floor(t);
- t = 1.0f - 2*fabs(t-0.5f);
- extern int glare;
- if(glare) t = 0.625f + 0.075f*t;
- else t = 0.5f + 0.5f*t;
- gle::colorf(t, t, t);
- if(glaring) SETSHADER(lavaglare); else SETSHADER(lava);
- fogtype = 1;
- }
- if(m.orient!=O_TOP)
- {
- float angle = fmod(float(lastmillis/2000.0f/(2*M_PI)), 1.0f),
- s = angle - int(angle) - 0.5f;
- s *= 8 - fabs(s)*16;
- wfwave = vertwater ? WATER_AMPLITUDE*s-WATER_OFFSET : -WATER_OFFSET;
- float scroll = 16.0f*lastmillis/3000.0f;
- float xscale = TEX_SCALE/(mslot->sts[1].t->xs*mslot->scale);
- float yscale = -TEX_SCALE/(mslot->sts[1].t->ys*mslot->scale);
- LOCALPARAMF(lavatexgen, xscale, yscale, 0.0f, scroll);
- }
- else setuplava(mslot->sts[0].t, mslot->scale);
- break;
-
- case MAT_GLASS:
- if((m.envmap==EMID_NONE || !glassenv || envmapped==m.envmap) && lastmat==m.material) break;
- changematerial(lastmat, lastorient);
- if(m.envmap!=EMID_NONE && glassenv && envmapped!=m.envmap)
- {
- glBindTexture(GL_TEXTURE_CUBE_MAP, lookupenvmap(m.envmap));
- envmapped = m.envmap;
- }
- if(lastmat!=m.material)
- {
- if(!blended) { glEnable(GL_BLEND); blended = true; }
- if(depth) { glDepthMask(GL_FALSE); depth = false; }
- const bvec &gcol = getglasscolor(m.material);
- if(m.envmap!=EMID_NONE && glassenv)
- {
- glBlendFunc(GL_ONE, GL_SRC_ALPHA);
- gle::color(gcol);
- SETSHADER(glass);
- }
- else
- {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gle::color(gcol, 40);
- foggednotextureshader->set();
- fogtype = 1;
- }
- }
- break;
-
- default: continue;
- }
- lastmat = m.material;
- lastorient = m.orient;
- if(fogtype!=lastfogtype)
- {
- if(fogtype) resetfogcolor();
- else zerofogcolor();
- lastfogtype = fogtype;
- }
- }
- switch(matvol)
- {
- case MAT_WATER:
- renderwaterfall(m, 0.1f);
- break;
-
- case MAT_LAVA:
- if(m.orient==O_TOP) renderlava(m);
- else renderwaterfall(m, 0.1f);
- break;
-
- case MAT_GLASS:
- drawglass(m, 0.1f);
- break;
- }
- }
if(lastorient >= 0) changematerial(lastmat, lastorient);
if(!depth) glDepthMask(GL_TRUE);
if(blended) glDisable(GL_BLEND);
- if(!lastfogtype) resetfogcolor();
extern int wireframe;
if(editmode && showmat && !drawtex && !wireframe)
{
- foggednotextureshader->set();
rendermatgrid(vismats);
}
virtual void setenvmap(float envmapmin, float envmapmax, Texture *envmap) {}
virtual void setspec(float spec) {}
virtual void setambient(float ambient) {}
- virtual void setglow(float glow, float glowdelta, float glowpulse) {}
- virtual void setglare(float specglare, float glowglare) {}
virtual void setalphatest(float alpha) {}
virtual void setalphablend(bool blend) {}
virtual void setfullbright(float fullbright) {}
return clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, nf) < 3;
}
if(isentirelysolid(c)) return true;
- if(vmat != MAT_AIR && ((c.material&matmask) == vmat || (isliquid(vmat) && isclipped(c.material&MATF_VOLUME)))) return true;
+ if(vmat != MAT_AIR && ((c.material&matmask) == vmat)) return true;
if(touchingface(c, orient) && faceedges(c, orient) == F_SOLID) return true;
ivec2 cf[8];
int numc = clipfacevecs(vf, numv, o[C[dim]], o[R[dim]], size, cf);
{
if(nmat != MAT_AIR && (o.material&matmask) == nmat) return true;
if(isentirelysolid(o)) return false;
- if(mat != MAT_AIR && ((o.material&matmask) == mat || (isliquid(mat) && (o.material&MATF_VOLUME) == MAT_GLASS))) return false;
+ if(mat != MAT_AIR && ((o.material&matmask) == mat || ((o.material&MATF_VOLUME) == MAT_GLASS))) return false;
if(isempty(o) || notouchingface(o, opp)) return true;
if(touchingface(o, opp) && faceedges(o, opp) == F_SOLID) return false;
{
matid = 0;
matmask = filtermask;
- if(isclipped(filtermat&MATF_VOLUME)) matmask &= ~MATF_CLIP;
- if(isdeadly(filtermat&MATF_VOLUME)) matmask &= ~MAT_DEATH;
}
else
{
matmask = matid&(MATF_VOLUME|MATF_INDEX) ? 0 : (matid&MATF_CLIP ? ~MATF_CLIP : ~matid);
- if(isclipped(matid&MATF_VOLUME)) matid |= MAT_CLIP;
- if(isdeadly(matid&MATF_VOLUME)) matid |= MAT_DEATH;
}
loopselxyz(setmat(c, matid, matmask, filtermat, filtermask, filtergeom));
}
if(load)
{
setupsky();
- initenvmaps();
}
guessshadowdir();
entitiesinoctanodes();
cube &c = *lc;
if((dist>0 || !(mode&RAY_SKIPFIRST)) &&
- (((mode&RAY_CLIPMAT) && isclipped(c.material&MATF_VOLUME)) ||
- ((mode&RAY_EDITMAT) && c.material != MAT_AIR) ||
+ (((mode&RAY_EDITMAT) && c.material != MAT_AIR) ||
(!(mode&RAY_PASS) && lsize==size && !isempty(c)) ||
isentirelysolid(c) ||
dent < dist))
{
case MAT_NOCLIP: continue;
case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break;
- case MAT_CLIP: if(isclipped(c[i].material&MATF_VOLUME) || d->type<ENT_CAMERA) solid = true; break;
+ case MAT_CLIP: if(d->type<ENT_CAMERA) solid = true; break;
}
if(!solid && isempty(c[i])) continue;
if(cubecollide(d, dir, cutoff, c[i], o, size, solid)) return true;
{
case MAT_NOCLIP: return false;
case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break;
- case MAT_CLIP: if(isclipped(c->material&MATF_VOLUME) || d->type<ENT_CAMERA) solid = true; break;
+ case MAT_CLIP: if(d->type<ENT_CAMERA) solid = true; break;
}
if(!solid && isempty(*c)) return false;
int csize = 2<<scale, cmask = ~(csize-1);
{
// make sure bouncers don't start inside geometry
if(d->physstate!=PHYS_BOUNCE && collide(d, vec(0, 0, 0), 0, false)) return true;
- int mat = lookupmaterial(vec(d->o.x, d->o.y, d->o.z + (d->aboveeye - d->eyeheight)/2));
- bool water = isliquid(mat);
- if(water)
- {
- d->vel.z -= grav*GRAVITY/16*secs;
- d->vel.mul(max(1.0f - secs/waterfric, 0.0f));
- }
- else d->vel.z -= grav*GRAVITY*secs;
+ d->vel.z -= grav*GRAVITY*secs;
vec old(d->o);
loopi(2)
{
float fric = water ? 2.0f : 6.0f,
c = water ? 1.0f : clamp((pl->floor.z - SLOPEZ)/(FLOORZ-SLOPEZ), 0.0f, 1.0f);
pl->falling.mul(pow(1 - c/fric, curtime/20.0f));
-// old fps friction
-// float friction = water ? 2.0f : 6.0f,
-// fpsfric = friction/curtime*20.0f,
-// c = water ? 1.0f : clamp((pl->floor.z - SLOPEZ)/(FLOORZ-SLOPEZ), 0.0f, 1.0f);
-// pl->falling.mul(1 - c/fpsfric);
}
}
bool moveplayer(physent *pl, int moveres, bool local, int curtime)
{
int material = lookupmaterial(vec(pl->o.x, pl->o.y, pl->o.z + (3*pl->aboveeye - pl->eyeheight)/4));
- bool water = isliquid(material&MATF_VOLUME);
bool floating = pl->type==ENT_PLAYER && (pl->state==CS_EDITING || pl->state==CS_SPECTATOR);
float secs = curtime/1000.f;
if(pl->strafe && maxroll) pl->roll = clamp(pl->roll - pow(clamp(1.0f + pl->strafe*pl->roll/maxroll, 0.0f, 1.0f), 0.33f)*pl->strafe*curtime*straferoll, -maxroll, maxroll);
else pl->roll *= curtime == PHYSFRAMETIME ? faderoll : pow(faderoll, curtime/float(PHYSFRAMETIME));
- // play sounds on water transitions
-
- if(pl->inwater && !water)
- {
- material = lookupmaterial(vec(pl->o.x, pl->o.y, pl->o.z + (pl->aboveeye - pl->eyeheight)/2));
- water = isliquid(material&MATF_VOLUME);
- }
- if(!pl->inwater && water) game::physicstrigger(pl, local, 0, -1, material&MATF_VOLUME);
- else if(pl->inwater && !water) game::physicstrigger(pl, local, 0, 1, pl->inwater);
+ if(pl->inwater) game::physicstrigger(pl, local, 0, 1, pl->inwater);
pl->inwater = water ? material&MATF_VOLUME : MAT_AIR;
if(pl->state==CS_ALIVE && (pl->o.z < 0 || material&MAT_DEATH)) game::suicide(pl);
FVAR(ragdollbodyfric, 0, 0.95f, 1);
FVAR(ragdollbodyfricscale, 0, 2, 10);
-FVAR(ragdollwaterfric, 0, 0.85f, 1);
FVAR(ragdollgroundfric, 0, 0.8f, 1);
FVAR(ragdollairfric, 0, 0.996f, 1);
FVAR(ragdollunstick, 0, 10, 1e3f);
VAR(ragdollexpireoffset, 0, 1500, 30000);
-VAR(ragdollwaterexpireoffset, 0, 3000, 30000);
void ragdolldata::move(dynent *pl, float ts)
{
if(collidemillis && lastmillis > collidemillis) return;
int material = lookupmaterial(vec(center.x, center.y, center.z + radius/2));
- bool water = isliquid(material&MATF_VOLUME);
- if(!pl->inwater && water) game::physicstrigger(pl, true, 0, -1, material&MATF_VOLUME);
- else if(pl->inwater && !water)
- {
- material = lookupmaterial(center);
- water = isliquid(material&MATF_VOLUME);
- if(!water) game::physicstrigger(pl, true, 0, 1, pl->inwater);
- }
- pl->inwater = water ? material&MATF_VOLUME : MAT_AIR;
+ pl->inwater = MAT_AIR;
calcrotfriction();
float tsfric = timestep ? ts/timestep : 1,
vert &v = verts[i];
vec dpos = vec(v.pos).sub(v.oldpos);
dpos.z -= GRAVITY*ts*ts;
- if(water) dpos.z += 0.25f*sinf(detrnd(size_t(this)+i, 360)*RAD + lastmillis/10000.0f*M_PI)*ts;
- dpos.mul(pow((water ? ragdollwaterfric : 1.0f) * (v.collided ? ragdollgroundfric : airfric), ts*1000.0f/ragdolltimestepmin)*tsfric);
+ dpos.mul(pow(1.0f * (v.collided ? ragdollgroundfric : airfric), ts*1000.0f/ragdolltimestepmin)*tsfric);
v.oldpos = v.pos;
v.pos.add(dpos);
}
if(collisions)
{
floating = 0;
- if(!collidemillis) collidemillis = lastmillis + (water ? ragdollwaterexpireoffset : ragdollexpireoffset);
+ if(!collidemillis) collidemillis = lastmillis + ragdollexpireoffset;
}
else if(++floating > 1 && lastmillis < collidemillis) collidemillis = 0;
if(glversion >= 300 || hasext("GL_EXT_gpu_shader4"))
{
// on DX10 or above class cards (i.e. GF8 or RadeonHD) enable expensive features
- extern int glare, maxdynlights, depthfxsize, blurdepthfx, texcompress;
- waterfallrefract = 1;
- glare = 1;
+ extern int maxdynlights, depthfxsize, blurdepthfx, texcompress;
maxdynlights = MAXDYNLIGHTS;
depthfxsize = 10;
blurdepthfx = 0;
GLOBALPARAM(camprojmatrix, camprojmatrix);
- if(fogging)
- {
- vec fogplane(cammatrix.c);
- fogplane.x /= projmatrix.a.x;
- fogplane.y /= projmatrix.b.y;
- fogplane.z /= projmatrix.c.w;
- GLOBALPARAMF(fogplane, fogplane.x, fogplane.y, 0, fogplane.z);
- }
- else
- {
- vec2 lineardepthscale = projmatrix.lineardepthscale();
- GLOBALPARAMF(fogplane, 0, 0, lineardepthscale.x, lineardepthscale.y);
- }
+ vec2 lineardepthscale = projmatrix.lineardepthscale();
if(flush && Shader::lastshader) Shader::lastshader->flushparams();
}
FVAR(thirdpersonside, -25, 0, 25);
physent *camera1 = NULL;
bool detachedcamera = false;
-bool isthirdperson() { return player!=camera1 || detachedcamera || reflecting; }
+bool isthirdperson() { return player!=camera1 || detachedcamera; }
void fixcamerarange()
{
return dir.add(camera1->o);
}
-VAR(reflectclip, 0, 6, 64);
-VAR(reflectclipavatar, -64, 0, 64);
-
matrix4 clipmatrix, noclipmatrix;
void renderavatar()
return;
}
- bool clipped = reflectz < 1e15f && reflectclip;
+ bool clipped = false;
nooffsetmatrix = projmatrix;
projmatrix.d.z += depthoffset * (clipped ? noclipmatrix.c.z : projmatrix.c.z);
void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, float &sx2, float &sy2)
{
vec worldpos(center), e;
- if(reflecting) worldpos.z = 2*reflectz - worldpos.z;
cammatrix.transform(worldpos, e);
if(e.z > 2*size) { sx1 = sy1 = 1; sx2 = sy2 = -1; return; }
float zzrr = e.z*e.z - size*size,
HUDQUAD(x, y, x+w, y+h, tx, ty, tx+tw, ty+th);
}
-VARR(fog, 16, 4000, 1000024);
-bvec fogcolor(0x80, 0x99, 0xB3);
-HVARFR(fogcolour, 0, 0x8099B3, 0xFFFFFF,
-{
- fogcolor = bvec((fogcolour>>16)&0xFF, (fogcolour>>8)&0xFF, fogcolour&0xFF);
-});
-
static float findsurface(int fogmat, const vec &v, int &abovemat)
{
- fogmat &= MATF_VOLUME;
ivec o(v), co;
int csize;
do
{
cube &c = lookupcube(o, 0, co, csize);
int mat = c.material&MATF_VOLUME;
- if(mat != fogmat)
- {
- abovemat = isliquid(mat) ? (int) c.material : (int) MAT_AIR;
+ abovemat = (int) MAT_AIR;
return o.z;
- }
o.z = co.z + csize;
}
while(o.z < worldsize);
return worldsize;
}
-static void blendfog(int fogmat, float blend, float logblend, float &start, float &end, vec &fogc)
-{
- switch(fogmat&MATF_VOLUME)
- {
- case MAT_WATER:
- {
- const bvec &wcol = getwatercolor(fogmat);
- int wfog = getwaterfog(fogmat);
- fogc.madd(wcol.tocolor(), blend);
- end += logblend*min(fog, max(wfog*4, 32));
- break;
- }
-
- case MAT_LAVA:
- {
- const bvec &lcol = getlavacolor(fogmat);
- int lfog = getlavafog(fogmat);
- fogc.madd(lcol.tocolor(), blend);
- end += logblend*min(fog, max(lfog*4, 32));
- break;
- }
-
- default:
- fogc.madd(fogcolor.tocolor(), blend);
- start += logblend*(fog+64)/8;
- end += logblend*fog;
- break;
- }
-}
-
-vec oldfogcolor(0, 0, 0), curfogcolor(0, 0, 0);
-float oldfogstart = 0, oldfogend = 1000000, curfogstart = 0, curfogend = 1000000;
-
-void setfogcolor(const vec &v)
-{
- GLOBALPARAM(fogcolor, v);
-}
-
-void zerofogcolor()
-{
- setfogcolor(vec(0, 0, 0));
-}
-
-void resetfogcolor()
-{
- setfogcolor(curfogcolor);
-}
-
-void pushfogcolor(const vec &v)
-{
- oldfogcolor = curfogcolor;
- curfogcolor = v;
- resetfogcolor();
-}
-
-void popfogcolor()
-{
- curfogcolor = oldfogcolor;
- resetfogcolor();
-}
-
-void setfogdist(float start, float end)
-{
- GLOBALPARAMF(fogparams, 1/(end - start), end/(end - start));
-}
-
-void clearfogdist()
-{
- setfogdist(0, 1000000);
-}
-
-void resetfogdist()
-{
- setfogdist(curfogstart, curfogend);
-}
-
-void pushfogdist(float start, float end)
-{
- oldfogstart = curfogstart;
- oldfogend = curfogend;
- curfogstart = start;
- curfogend = end;
- resetfogdist();
-}
-
-void popfogdist()
-{
- curfogstart = oldfogstart;
- curfogend = oldfogend;
- resetfogdist();
-}
-
-static void resetfog()
-{
- resetfogcolor();
- resetfogdist();
-
- glClearColor(curfogcolor.r, curfogcolor.g, curfogcolor.b, 1.0f);
-}
-
-static void setfog(int fogmat, float below = 1, int abovemat = MAT_AIR)
-{
- float logscale = 256, logblend = log(1 + (logscale - 1)*below) / log(logscale);
-
- curfogstart = curfogend = 0;
- curfogcolor = vec(0, 0, 0);
- blendfog(fogmat, below, logblend, curfogstart, curfogend, curfogcolor);
- if(below < 1) blendfog(abovemat, 1-below, 1-logblend, curfogstart, curfogend, curfogcolor);
-
- resetfog();
-}
-
-static void blendfogoverlay(int fogmat, float blend, vec &overlay)
-{
- float maxc;
- switch(fogmat&MATF_VOLUME)
- {
- case MAT_WATER:
- {
- const bvec &wcol = getwatercolor(fogmat);
- maxc = max(wcol.r, max(wcol.g, wcol.b));
- overlay.madd(vec(wcol.r, wcol.g, wcol.b).div(min(32.0f + maxc*7.0f/8.0f, 255.0f)).max(0.4f), blend);
- break;
- }
-
- case MAT_LAVA:
- {
- const bvec &lcol = getlavacolor(fogmat);
- maxc = max(lcol.r, max(lcol.g, lcol.b));
- overlay.madd(vec(lcol.r, lcol.g, lcol.b).div(min(32.0f + maxc*7.0f/8.0f, 255.0f)).max(0.4f), blend);
- break;
- }
-
- default:
- overlay.add(blend);
- break;
- }
-}
-
-void drawfogoverlay(int fogmat, float fogblend, int abovemat)
-{
- SETSHADER(fogoverlay);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_ZERO, GL_SRC_COLOR);
- vec overlay(0, 0, 0);
- blendfogoverlay(fogmat, fogblend, overlay);
- blendfogoverlay(abovemat, 1-fogblend, overlay);
-
- gle::color(overlay);
- screenquad();
-
- glDisable(GL_BLEND);
-}
-
bool renderedgame = false;
void rendergame(bool mainpass)
if(!shadowmapping) renderedgame = true;
}
-VARP(skyboxglare, 0, 1, 1);
-
-void drawglare()
-{
- glaring = true;
- refracting = -1;
-
- pushfogcolor(vec(0, 0, 0));
-
- glClearColor(0, 0, 0, 1);
- glClear((skyboxglare && !shouldclearskyboxglare() ? 0 : GL_COLOR_BUFFER_BIT) | GL_DEPTH_BUFFER_BIT);
-
- rendergeom();
-
- if(skyboxglare) drawskybox(farplane, false);
-
- renderreflectedmapmodels();
- rendergame();
- renderavatar();
-
- renderwater();
- rendermaterials();
- renderalphageom();
- renderparticles();
-
- popfogcolor();
-
- refracting = 0;
- glaring = false;
-}
-
-VARP(reflectmms, 0, 1, 1);
-VARR(refractsky, 0, 0, 1);
-
-matrix4 noreflectmatrix;
-
-void drawreflection(float z, bool refract, int fogdepth, const bvec &col)
-{
- reflectz = z < 0 ? 1e16f : z;
- reflecting = !refract;
- refracting = refract ? (z < 0 || camera1->o.z >= z ? -1 : 1) : 0;
- fading = waterrefract && waterfade && z>=0;
- fogging = refracting<0 && z>=0;
- refractfog = fogdepth;
-
- if(fogging)
- {
- pushfogdist(camera1->o.z - z, camera1->o.z - (z - max(refractfog, 1)));
- pushfogcolor(col.tocolor());
- }
- else
- {
- vec color(0, 0, 0);
- float start = 0, end = 0;
- blendfog(MAT_AIR, 1, 1, start, end, color);
- pushfogdist(start, end);
- pushfogcolor(color);
- }
-
- if(fading)
- {
- float scale = fogging ? -0.25f : 0.25f, offset = 2*fabs(scale) - scale*z;
- GLOBALPARAMF(waterfadeparams, scale, offset, -scale, offset + camera1->o.z*scale);
- }
-
- if(reflecting)
- {
- noreflectmatrix = cammatrix;
- cammatrix.reflectz(z);
-
- glFrontFace(GL_CCW);
- }
-
- if(reflectclip && z>=0)
- {
- float zoffset = reflectclip/4.0f, zclip;
- if(refracting<0)
- {
- zclip = z+zoffset;
- if(camera1->o.z<=zclip) zclip = z;
- }
- else
- {
- zclip = z-zoffset;
- if(camera1->o.z>=zclip && camera1->o.z<=z+4.0f) zclip = z;
- if(reflecting) zclip = 2*z - zclip;
- }
- plane clipplane;
- invcammatrix.transposedtransform(plane(0, 0, refracting>0 ? 1 : -1, refracting>0 ? -zclip : zclip), clipplane);
- clipmatrix.clip(clipplane, projmatrix);
- noclipmatrix = projmatrix;
- projmatrix = clipmatrix;
- }
-
- setcamprojmatrix(false, true);
-
- renderreflectedgeom(refracting<0 && z>=0 && caustics, fogging);
-
- if(reflecting || refracting>0 || (refracting<0 && refractsky) || z<0)
- {
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- if(reflectclip && z>=0)
- {
- projmatrix = noclipmatrix;
- setcamprojmatrix(false, true);
- }
- drawskybox(farplane, false);
- if(reflectclip && z>=0)
- {
- projmatrix = clipmatrix;
- setcamprojmatrix(false, true);
- }
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- }
- else if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
-
- renderdecals();
-
- if(reflectmms) renderreflectedmapmodels();
- rendergame();
-
- if(refracting && z>=0 && !isthirdperson() && fabs(camera1->o.z-z) <= 0.5f*(player->eyeheight + player->aboveeye))
- {
- matrix4 oldprojmatrix = projmatrix, avatarproj;
- avatarproj.perspective(curavatarfov, aspect, nearplane, farplane);
- if(reflectclip)
- {
- matrix4 avatarclip;
- plane clipplane;
- invcammatrix.transposedtransform(plane(0, 0, refracting, reflectclipavatar/4.0f - refracting*z), clipplane);
- avatarclip.clip(clipplane, avatarproj);
- projmatrix = avatarclip;
- }
- else projmatrix = avatarproj;
- setcamprojmatrix(false, true);
- game::renderavatar();
- projmatrix = oldprojmatrix;
- setcamprojmatrix(false, true);
- }
-
- rendermaterials();
- renderalphageom(fogging);
- renderparticles();
-
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- if(reflectclip && z>=0) projmatrix = noclipmatrix;
-
- if(reflecting)
- {
- cammatrix = noreflectmatrix;
-
- glFrontFace(GL_CW);
- }
-
- popfogdist();
- popfogcolor();
-
- reflectz = 1e16f;
- refracting = 0;
- reflecting = fading = fogging = false;
-
- setcamprojmatrix(false, true);
-}
-
int drawtex = 0;
void drawcubemap(int size, const vec &o, float yaw, float pitch, const cubemapside &side, bool onlysky)
cmcamera.roll = 0;
camera1 = &cmcamera;
- int fogmat = lookupmaterial(o)&(MATF_VOLUME|MATF_INDEX);
-
- setfog(fogmat);
-
int farplane = worldsize*2;
projmatrix.perspective(90.0f, 1.0f, nearplane, farplane);
if(!limitsky()) drawskybox(farplane, false);
-// queryreflections();
-
rendermapmodels();
renderalphageom();
-// drawreflections();
-
-// renderwater();
-// rendermaterials();
-
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
curfov = 2*atan2(tan(fovy/2*RAD), 1/aspect)/RAD;
farplane = 1024;
- clearfogdist();
- zerofogcolor();
glClearColor(0, 0, 0, 1);
glClear((background ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
- resetfogdist();
- resetfogcolor();
- glClearColor(curfogcolor.r, curfogcolor.g, curfogcolor.b, 1);
-
aspect = oldaspect;
fovy = oldfovy;
curfov = oldfov;
aspect = forceaspect ? forceaspect : w/float(h);
fovy = 2*atan2(tan(curfov/2*RAD), aspect)/RAD;
- int fogmat = lookupmaterial(camera1->o)&(MATF_VOLUME|MATF_INDEX), abovemat = MAT_AIR;
- float fogblend = 1.0f, causticspass = 0.0f;
- if(isliquid(fogmat&MATF_VOLUME))
- {
- float z = findsurface(fogmat, camera1->o, abovemat) - WATER_OFFSET;
- if(camera1->o.z < z + 1) fogblend = min(z + 1 - camera1->o.z, 1.0f);
- else fogmat = abovemat;
- if(caustics && (fogmat&MATF_VOLUME)==MAT_WATER && camera1->o.z < z)
- causticspass = min(z - camera1->o.z, 1.0f);
- }
- else fogmat = MAT_AIR;
- setfog(fogmat, fogblend, abovemat);
- if(fogmat!=MAT_AIR)
- {
- float blend = abovemat==MAT_AIR ? fogblend : 1.0f;
- fovy += blend*sinf(lastmillis/1000.0)*2.0f;
- aspect += blend*sinf(lastmillis/1000.0+M_PI)*0.1f;
- }
-
farplane = worldsize*2;
projmatrix.perspective(fovy, aspect, nearplane, farplane);
if(limitsky()) drawskybox(farplane, true);
- rendergeom(causticspass);
+ rendergeom();
extern int outline;
if(!wireframe && editmode && outline) renderoutline();
- queryreflections();
-
if(!limitsky()) drawskybox(farplane, false);
renderdecals(true);
if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- drawglaretex();
drawdepthfxtex();
- drawreflections();
if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- renderwater();
-
rendermaterials();
renderalphageom();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
- addglare();
- if(isliquid(fogmat&MATF_VOLUME)) drawfogoverlay(fogmat, fogblend, abovemat);
- renderpostfx();
-
gl_drawhud();
renderedgame = false;
void gl_drawmainmenu()
{
xtravertsva = xtraverts = glde = gbatches = 0;
-
renderbackground(NULL, NULL, NULL, NULL, true, true);
- renderpostfx();
-
gl_drawhud();
}
COMMAND(mdldepthoffset, "i");
-void mdlglow(int *percent, int *delta, float *pulse)
-{
- checkmdl;
- float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
- if(*percent>0) glow = *percent/100.0f;
- else if(*percent<0) glow = 0.0f;
- glowdelta -= glow;
- loadingmodel->setglow(glow, glowdelta, glowpulse);
-}
-
-COMMAND(mdlglow, "iif");
-
-void mdlglare(float *specglare, float *glowglare)
-{
- checkmdl;
- loadingmodel->setglare(*specglare, *glowglare);
-}
-
-COMMAND(mdlglare, "ff");
-
void mdlenvmap(float *envmapmax, float *envmapmin, char *envmap)
{
checkmdl;
if(flags&MDL_CULL_DIST && center.dist(camera1->o)/radius>maxmodelradiusdistance) return MDL_CULL_DIST;
if(flags&MDL_CULL_VFC)
{
- if(reflecting || refracting)
- {
- if(reflecting || refracting>0)
- {
- if(center.z+radius<=reflectz) return MDL_CULL_VFC;
- }
- else
- {
- if(fogging && center.z+radius<reflectz-refractfog) return MDL_CULL_VFC;
- if(!shadow && center.z-radius>=reflectz) return MDL_CULL_VFC;
- }
- if(center.dist(camera1->o)-radius>reflectdist) return MDL_CULL_VFC;
- }
- if(isfoggedsphere(radius, center)) return MDL_CULL_VFC;
if(shadowmapping && !isshadowmapcaster(center, radius)) return MDL_CULL_VFC;
}
if(shadowmapping)
}
else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius))
{
- if(!reflecting && !refracting && d) d->occluded = OCCLUDE_PARENT;
+ if(d) d->occluded = OCCLUDE_PARENT;
return MDL_CULL_OCCLUDED;
}
else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query))
{
- if(!reflecting && !refracting && d->occluded<OCCLUDE_BB) d->occluded++;
+ if(d->occluded<OCCLUDE_BB) d->occluded++;
return MDL_CULL_QUERY;
}
return 0;
int culled = cullmodel(m, center, radius, flags, d, shadow);
if(culled)
{
- if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY && !reflecting && !refracting)
+ if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY)
{
enablecullmodelquery();
rendercullmodelquery(m, d, center, radius);
return;
}
- if(reflecting || refracting || shadowmapping) flags &= ~MDL_CULL_QUERY;
+ if(shadowmapping) flags &= ~MDL_CULL_QUERY;
}
if(flags&MDL_NORENDER) anim |= ANIM_NORENDER;
- else if(showboundingbox && !shadowmapping && !reflecting && !refracting && editmode)
+ else if(showboundingbox && !shadowmapping && editmode)
{
notextureshader->set();
if(d && showboundingbox==1)
vec pos = o;
if(d)
{
- if(!reflecting && !refracting) d->occluded = OCCLUDE_NOTHING;
+ d->occluded = OCCLUDE_NOTHING;
if(!light) light = &d->light;
if(flags&MDL_LIGHT && light->millis!=lastmillis)
{
b.basetime2 = basetime2;
b.transparent = trans;
b.flags = flags & ~(MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
- if(!shadow || reflecting || refracting>0)
+ if(!shadow)
{
b.flags &= ~(MDL_SHADOW|MDL_DYNSHADOW);
- if((flags&MDL_CULL_VFC) && refracting<0 && center.z-radius>=reflectz) b.flags |= MDL_CULL_VFC;
+ if(flags&MDL_CULL_VFC) b.flags |= MDL_CULL_VFC;
}
mb.flags |= b.flags;
b.d = d;
VARP(particlesize, 20, 100, 500);
-// Check canemitparticles() to limit the rate that paricles can be emitted for models/sparklies
-// Automatically stops particles being emitted when paused or in reflective drawing
VARP(emitmillis, 1, 17, 1000);
static int lastemitframe = 0, emitoffset = 0;
static bool canemit = false, regenemitters = false, canstep = false;
static bool canemitparticles()
{
- if(reflecting || refracting) return false;
return canemit || emitoffset;
}
vec o, d;
int blend, ts;
calc(&p, blend, ts, o, d, false);
- if(!isfoggedsphere(radius, p.o) && (depthfxscissor!=2 || depthfxtex.addscissorbox(p.o, radius)))
+ if((depthfxscissor!=2 || depthfxtex.addscissorbox(p.o, radius)))
{
numsoft++;
loopk(3)
loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->resettracked(owner);
}
-VARP(particleglare, 0, 2, 100);
-
void renderparticles(bool mainpass)
{
canstep = mainpass;
- if(glaring && !particleglare) return;
-
loopi(sizeof(parts)/sizeof(parts[0]))
{
if(glaring && !(parts[i]->type&PT_GLARE)) continue;
loopi(sizeof(parts)/sizeof(parts[0]))
{
partrenderer *p = parts[i];
- if(glaring && !(p->type&PT_GLARE)) continue;
+ if(!(p->type&PT_GLARE)) continue;
if(!p->haswork()) continue;
if(!rendered)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if(glaring) GLOBALPARAMF(colorscale, particleglare, particleglare, particleglare, 1);
- else GLOBALPARAMF(colorscale, 1, 1, 1, 1);
+ GLOBALPARAMF(colorscale, 1, 1, 1, 1);
}
uint flags = p->type & flagmask, changedbits = (flags ^ lastflags);
if(changedbits)
{
- if(changedbits&PT_LERP)
- {
- if(flags&PT_LERP) resetfogcolor();
- else zerofogcolor();
- }
if(changedbits&(PT_LERP|PT_MOD))
{
if(flags&PT_LERP) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if(rendered)
{
if(lastflags&(PT_LERP|PT_MOD)) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- if(!(lastflags&PT_LERP)) resetfogcolor();
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
}
else
{
int mat = MAT_WATER + clamp(-e.attr3, 0, 3);
- const bvec &wfcol = getwaterfallcolor(mat);
+ const bvec &wfcol = { 0 };
color = (int(wfcol[0])<<16) | (int(wfcol[1])<<8) | int(wfcol[2]);
if(!color)
{
- const bvec &wcol = getwatercolor(mat);
+ const bvec &wcol = { 0 };
color = (int(wcol[0])<<16) | (int(wcol[1])<<8) | int(wcol[2]);
}
}
particleemitter &pe = emitters[i];
extentity &e = *pe.ent;
if(e.o.dist(camera1->o) > maxparticledistance) { pe.lastemit = lastmillis; continue; }
- if(cullparticles && pe.maxfade >= 0)
- {
- if(isfoggedsphere(pe.radius, pe.center)) { pe.lastcull = lastmillis; continue; }
- }
makeparticles(e);
emitted++;
if(replayparticles && pe.maxfade > 5 && pe.lastcull > pe.lastemit)
+++ /dev/null
-#include "engine.h"
-
-Texture *sky[6] = { 0, 0, 0, 0, 0, 0 }, *clouds[6] = { 0, 0, 0, 0, 0, 0 };
-
-void loadsky(const char *basename, Texture *texs[6])
-{
- const char *wildcard = strchr(basename, '*');
- loopi(6)
- {
- const char *side = cubemapsides[i].name;
- string name;
- copystring(name, makerelpath("packages", basename));
- if(wildcard)
- {
- char *chop = strchr(name, '*');
- if(chop) { *chop = '\0'; concatstring(name, side); concatstring(name, wildcard+1); }
- texs[i] = textureload(name, 3, true, false);
- }
- else
- {
- defformatstring(ext, "_%s.jpg", side);
- concatstring(name, ext);
- if((texs[i] = textureload(name, 3, true, false))==notexture)
- {
- strcpy(name+strlen(name)-3, "png");
- texs[i] = textureload(name, 3, true, false);
- }
- }
- if(texs[i]==notexture) conoutf(CON_ERROR, "could not load side %s of sky texture %s", side, basename);
- }
-}
-
-Texture *cloudoverlay = NULL;
-
-Texture *loadskyoverlay(const char *basename)
-{
- const char *ext = strrchr(basename, '.');
- string name;
- copystring(name, makerelpath("packages", basename));
- Texture *t = notexture;
- if(ext) t = textureload(name, 0, true, false);
- else
- {
- concatstring(name, ".jpg");
- if((t = textureload(name, 0, true, false)) == notexture)
- {
- strcpy(name+strlen(name)-3, "png");
- t = textureload(name, 0, true, false);
- }
- }
- if(t==notexture) conoutf(CON_ERROR, "could not load sky overlay texture %s", basename);
- return t;
-}
-
-SVARFR(skybox, "", { if(skybox[0]) loadsky(skybox, sky); });
-HVARR(skyboxcolour, 0, 0xFFFFFF, 0xFFFFFF);
-FVARR(spinsky, -720, 0, 720);
-VARR(yawsky, 0, 0, 360);
-SVARFR(cloudbox, "", { if(cloudbox[0]) loadsky(cloudbox, clouds); });
-HVARR(cloudboxcolour, 0, 0xFFFFFF, 0xFFFFFF);
-FVARR(cloudboxalpha, 0, 1, 1);
-FVARR(spinclouds, -720, 0, 720);
-VARR(yawclouds, 0, 0, 360);
-FVARR(cloudclip, 0, 0.5f, 1);
-SVARFR(cloudlayer, "", { if(cloudlayer[0]) cloudoverlay = loadskyoverlay(cloudlayer); });
-FVARR(cloudoffsetx, 0, 0, 1);
-FVARR(cloudoffsety, 0, 0, 1);
-FVARR(cloudscrollx, -16, 0, 16);
-FVARR(cloudscrolly, -16, 0, 16);
-FVARR(cloudscale, 0.001, 1, 64);
-FVARR(spincloudlayer, -720, 0, 720);
-VARR(yawcloudlayer, 0, 0, 360);
-FVARR(cloudheight, -1, 0.2f, 1);
-FVARR(cloudfade, 0, 0.2f, 1);
-FVARR(cloudalpha, 0, 1, 1);
-VARR(cloudsubdiv, 4, 16, 64);
-HVARR(cloudcolour, 0, 0xFFFFFF, 0xFFFFFF);
-
-void drawenvboxface(float s0, float t0, int x0, int y0, int z0,
- float s1, float t1, int x1, int y1, int z1,
- float s2, float t2, int x2, int y2, int z2,
- float s3, float t3, int x3, int y3, int z3,
- Texture *tex)
-{
- glBindTexture(GL_TEXTURE_2D, (tex ? tex : notexture)->id);
- gle::begin(GL_TRIANGLE_STRIP);
- gle::attribf(x3, y3, z3); gle::attribf(s3, t3);
- gle::attribf(x2, y2, z2); gle::attribf(s2, t2);
- gle::attribf(x0, y0, z0); gle::attribf(s0, t0);
- gle::attribf(x1, y1, z1); gle::attribf(s1, t1);
- xtraverts += gle::end();
-}
-
-void drawenvbox(int w, float z1clip = 0.0f, float z2clip = 1.0f, int faces = 0x3F, Texture **sky = NULL)
-{
- if(z1clip >= z2clip) return;
-
- float v1 = 1-z1clip, v2 = 1-z2clip;
- int z1 = int(ceil(2*w*(z1clip-0.5f))), z2 = int(ceil(2*w*(z2clip-0.5f)));
-
- gle::defvertex();
- gle::deftexcoord0();
-
- if(faces&0x01)
- drawenvboxface(0.0f, v2, -w, -w, z2,
- 1.0f, v2, -w, w, z2,
- 1.0f, v1, -w, w, z1,
- 0.0f, v1, -w, -w, z1, sky[0]);
-
- if(faces&0x02)
- drawenvboxface(1.0f, v1, w, -w, z1,
- 0.0f, v1, w, w, z1,
- 0.0f, v2, w, w, z2,
- 1.0f, v2, w, -w, z2, sky[1]);
-
- if(faces&0x04)
- drawenvboxface(1.0f, v1, -w, -w, z1,
- 0.0f, v1, w, -w, z1,
- 0.0f, v2, w, -w, z2,
- 1.0f, v2, -w, -w, z2, sky[2]);
-
- if(faces&0x08)
- drawenvboxface(1.0f, v1, w, w, z1,
- 0.0f, v1, -w, w, z1,
- 0.0f, v2, -w, w, z2,
- 1.0f, v2, w, w, z2, sky[3]);
-
- if(z1clip <= 0 && faces&0x10)
- drawenvboxface(0.0f, 1.0f, -w, w, -w,
- 0.0f, 0.0f, w, w, -w,
- 1.0f, 0.0f, w, -w, -w,
- 1.0f, 1.0f, -w, -w, -w, sky[4]);
-
- if(z2clip >= 1 && faces&0x20)
- drawenvboxface(0.0f, 1.0f, w, w, w,
- 0.0f, 0.0f, -w, w, w,
- 1.0f, 0.0f, -w, -w, w,
- 1.0f, 1.0f, w, -w, w, sky[5]);
-}
-
-void drawenvoverlay(int w, Texture *overlay = NULL, float tx = 0, float ty = 0)
-{
- float z = w*cloudheight, tsz = 0.5f*(1-cloudfade)/cloudscale, psz = w*(1-cloudfade);
- glBindTexture(GL_TEXTURE_2D, overlay ? overlay->id : notexture->id);
- vec color = vec::hexcolor(cloudcolour);
- gle::color(color, cloudalpha);
- gle::defvertex();
- gle::deftexcoord0();
- gle::begin(GL_TRIANGLE_FAN);
- loopi(cloudsubdiv+1)
- {
- vec p(1, 1, 0);
- p.rotate_around_z((-2.0f*M_PI*i)/cloudsubdiv);
- gle::attribf(p.x*psz, p.y*psz, z);
- gle::attribf(tx + p.x*tsz, ty + p.y*tsz);
- }
- xtraverts += gle::end();
- float tsz2 = 0.5f/cloudscale;
- gle::defvertex();
- gle::deftexcoord0();
- gle::defcolor(4);
- gle::begin(GL_TRIANGLE_STRIP);
- loopi(cloudsubdiv+1)
- {
- vec p(1, 1, 0);
- p.rotate_around_z((-2.0f*M_PI*i)/cloudsubdiv);
- gle::attribf(p.x*psz, p.y*psz, z);
- gle::attribf(tx + p.x*tsz, ty + p.y*tsz);
- gle::attrib(color, cloudalpha);
- gle::attribf(p.x*w, p.y*w, z);
- gle::attribf(tx + p.x*tsz2, ty + p.y*tsz2);
- gle::attrib(color, 0.0f);
- }
- xtraverts += gle::end();
-}
-
-FVARR(fogdomeheight, -1, -0.5f, 1);
-FVARR(fogdomemin, 0, 0, 1);
-FVARR(fogdomemax, 0, 0, 1);
-VARR(fogdomecap, 0, 1, 1);
-FVARR(fogdomeclip, 0, 1, 1);
-bvec fogdomecolor(0, 0, 0);
-HVARFR(fogdomecolour, 0, 0, 0xFFFFFF,
-{
- fogdomecolor = bvec((fogdomecolour>>16)&0xFF, (fogdomecolour>>8)&0xFF, fogdomecolour&0xFF);
-});
-VARR(fogdomeclouds, 0, 1, 1);
-
-namespace fogdome
-{
- struct vert
- {
- vec pos;
- bvec4 color;
-
- vert() {}
- vert(const vec &pos, const bvec &fcolor, float alpha) : pos(pos), color(fcolor, uchar(alpha*255))
- {
- }
- vert(const vert &v0, const vert &v1) : pos(vec(v0.pos).add(v1.pos).normalize()), color(v0.color)
- {
- if(v0.pos.z != v1.pos.z) color.a += uchar((v1.color.a - v0.color.a) * (pos.z - v0.pos.z) / (v1.pos.z - v0.pos.z));
- }
- } *verts = NULL;
- GLushort *indices = NULL;
- int numverts = 0, numindices = 0, capindices = 0;
- GLuint vbuf = 0, ebuf = 0;
- bvec lastcolor(0, 0, 0);
- float lastminalpha = 0, lastmaxalpha = 0, lastcapsize = -1, lastclipz = 1;
-
- void subdivide(int depth, int face);
-
- void genface(int depth, int i1, int i2, int i3)
- {
- int face = numindices; numindices += 3;
- indices[face] = i3;
- indices[face+1] = i2;
- indices[face+2] = i1;
- subdivide(depth, face);
- }
-
- void subdivide(int depth, int face)
- {
- if(depth-- <= 0) return;
- int idx[6];
- loopi(3) idx[i] = indices[face+2-i];
- loopi(3)
- {
- int curvert = numverts++;
- verts[curvert] = vert(verts[idx[i]], verts[idx[(i+1)%3]]); //push on to unit sphere
- idx[3+i] = curvert;
- indices[face+2-i] = curvert;
- }
- subdivide(depth, face);
- loopi(3) genface(depth, idx[i], idx[3+i], idx[3+(i+2)%3]);
- }
-
- int sortcap(GLushort x, GLushort y)
- {
- const vec &xv = verts[x].pos, &yv = verts[y].pos;
- return xv.y < 0 ? yv.y >= 0 || xv.x < yv.x : yv.y >= 0 && xv.x > yv.x;
- }
-
- void init(const bvec &color, float minalpha = 0.0f, float maxalpha = 1.0f, float capsize = -1, float clipz = 1, int hres = 16, int depth = 2)
- {
- const int tris = hres << (2*depth);
- numverts = numindices = capindices = 0;
- verts = new vert[tris+1 + (capsize >= 0 ? 1 : 0)];
- indices = new GLushort[(tris + (capsize >= 0 ? hres<<depth : 0))*3];
- if(clipz >= 1)
- {
- verts[numverts++] = vert(vec(0.0f, 0.0f, 1.0f), color, minalpha); //build initial 'hres' sided pyramid
- loopi(hres) verts[numverts++] = vert(vec(sincos360[(360*i)/hres], 0.0f), color, maxalpha);
- loopi(hres) genface(depth, 0, i+1, 1+(i+1)%hres);
- }
- else if(clipz <= 0)
- {
- loopi(hres<<depth) verts[numverts++] = vert(vec(sincos360[(360*i)/(hres<<depth)], 0.0f), color, maxalpha);
- }
- else
- {
- float clipxy = sqrtf(1 - clipz*clipz);
- const vec2 &scm = sincos360[180/hres];
- loopi(hres)
- {
- const vec2 &sc = sincos360[(360*i)/hres];
- verts[numverts++] = vert(vec(sc.x*clipxy, sc.y*clipxy, clipz), color, minalpha);
- verts[numverts++] = vert(vec(sc.x, sc.y, 0.0f), color, maxalpha);
- verts[numverts++] = vert(vec(sc.x*scm.x - sc.y*scm.y, sc.y*scm.x + sc.x*scm.y, 0.0f), color, maxalpha);
- }
- loopi(hres)
- {
- genface(depth-1, 3*i, 3*i+1, 3*i+2);
- genface(depth-1, 3*i, 3*i+2, 3*((i+1)%hres));
- genface(depth-1, 3*i+2, 3*((i+1)%hres)+1, 3*((i+1)%hres));
- }
- }
-
- if(capsize >= 0)
- {
- GLushort *cap = &indices[numindices];
- int capverts = 0;
- loopi(numverts) if(!verts[i].pos.z) cap[capverts++] = i;
- verts[numverts++] = vert(vec(0.0f, 0.0f, -capsize), color, maxalpha);
- quicksort(cap, capverts, sortcap);
- loopi(capverts)
- {
- int n = capverts-1-i;
- cap[n*3] = cap[n];
- cap[n*3+1] = cap[(n+1)%capverts];
- cap[n*3+2] = numverts-1;
- capindices += 3;
- }
- }
-
- if(!vbuf) glGenBuffers_(1, &vbuf);
- gle::bindvbo(vbuf);
- glBufferData_(GL_ARRAY_BUFFER, numverts*sizeof(vert), verts, GL_STATIC_DRAW);
- DELETEA(verts);
-
- if(!ebuf) glGenBuffers_(1, &ebuf);
- gle::bindebo(ebuf);
- glBufferData_(GL_ELEMENT_ARRAY_BUFFER, (numindices + capindices)*sizeof(GLushort), indices, GL_STATIC_DRAW);
- DELETEA(indices);
- }
-
- void cleanup()
- {
- numverts = numindices = 0;
- if(vbuf) { glDeleteBuffers_(1, &vbuf); vbuf = 0; }
- if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; }
- }
-
- void draw()
- {
- float capsize = fogdomecap && fogdomeheight < 1 ? (1 + fogdomeheight) / (1 - fogdomeheight) : -1;
- bvec color = fogdomecolour ? fogdomecolor : fogcolor;
- if(!numverts || lastcolor != color || lastminalpha != fogdomemin || lastmaxalpha != fogdomemax || lastcapsize != capsize || lastclipz != fogdomeclip)
- {
- init(color, min(fogdomemin, fogdomemax), fogdomemax, capsize, fogdomeclip);
- lastcolor = color;
- lastminalpha = fogdomemin;
- lastmaxalpha = fogdomemax;
- lastcapsize = capsize;
- lastclipz = fogdomeclip;
- }
-
- gle::bindvbo(vbuf);
- gle::bindebo(ebuf);
-
- gle::vertexpointer(sizeof(vert), &verts->pos);
- gle::colorpointer(sizeof(vert), &verts->color);
- gle::enablevertex();
- gle::enablecolor();
-
- glDrawRangeElements_(GL_TRIANGLES, 0, numverts-1, numindices + fogdomecap*capindices, GL_UNSIGNED_SHORT, indices);
- xtraverts += numverts;
- glde++;
-
- gle::disablevertex();
- gle::disablecolor();
-
- gle::clearvbo();
- gle::clearebo();
- }
-}
-
-static void drawfogdome(int farplane)
-{
- SETSHADER(skyfog);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- matrix4 skymatrix = cammatrix, skyprojmatrix;
- skymatrix.settranslation(vec(cammatrix.c).mul(farplane*fogdomeheight*0.5f));
- skymatrix.scale(farplane/2, farplane/2, farplane*(0.5f - fogdomeheight*0.5f));
- skyprojmatrix.mul(projmatrix, skymatrix);
- LOCALPARAM(skymatrix, skyprojmatrix);
-
- fogdome::draw();
-
- glDisable(GL_BLEND);
-}
-
-void cleanupsky()
-{
- fogdome::cleanup();
-}
-
-extern int atmo;
-
-void preloadatmoshaders(bool force = false)
-{
- static bool needatmo = false;
- if(force) needatmo = true;
- if(!atmo || !needatmo) return;
-
- useshaderbyname("atmosphere");
- useshaderbyname("atmosphereglare");
-}
-
-void setupsky()
-{
- preloadatmoshaders(true);
-}
-
-VARFR(atmo, 0, 0, 1, preloadatmoshaders());
-FVARR(atmoplanetsize, 1e-3f, 1, 1e3f);
-FVARR(atmoheight, 1e-3f, 1, 1e3f);
-FVARR(atmobright, 0, 1, 16);
-bvec atmosunlightcolor(0, 0, 0);
-HVARFR(atmosunlight, 0, 0, 0xFFFFFF,
-{
- if(atmosunlight <= 255) atmosunlight |= (atmosunlight<<8) | (atmosunlight<<16);
- atmosunlightcolor = bvec((atmosunlight>>16)&0xFF, (atmosunlight>>8)&0xFF, atmosunlight&0xFF);
-});
-FVARR(atmosunlightscale, 0, 1, 16);
-bvec atmosundiskcolor(0, 0, 0);
-HVARFR(atmosundisk, 0, 0, 0xFFFFFF,
-{
- if(atmosundisk <= 255) atmosundisk |= (atmosundisk<<8) | (atmosundisk<<16);
- atmosundiskcolor = bvec((atmosundisk>>16)&0xFF, (atmosundisk>>8)&0xFF, atmosundisk&0xFF);
-});
-FVARR(atmosundisksize, 0, 12, 90);
-FVARR(atmosundiskcorona, 0, 0.4f, 1);
-FVARR(atmosundiskbright, 0, 1, 16);
-FVARR(atmohaze, 0, 0.1f, 16);
-FVARR(atmodensity, 0, 1, 16);
-FVARR(atmoozone, 0, 1, 16);
-FVARR(atmoalpha, 0, 1, 1);
-
-static void drawatmosphere(int w, float z1clip = 0.0f, float z2clip = 1.0f, int faces = 0x3F)
-{
- if(z1clip >= z2clip) return;
-
- if(glaring) SETSHADER(atmosphereglare);
- else SETSHADER(atmosphere);
-
- matrix4 skymatrix = cammatrix, skyprojmatrix;
- skymatrix.settranslation(0, 0, 0);
- skyprojmatrix.mul(projmatrix, skymatrix);
- LOCALPARAM(skymatrix, skyprojmatrix);
-
- // optical depth scales for 3 different shells of atmosphere - air, haze, ozone
- const float earthradius = 6371e3f, earthairheight = 8.4e3f, earthhazeheight = 1.25e3f, earthozoneheight = 50e3f;
- float planetradius = earthradius*atmoplanetsize;
- vec atmoshells = vec(earthairheight, earthhazeheight, earthozoneheight).mul(atmoheight).add(planetradius).square().sub(planetradius*planetradius);
- LOCALPARAM(opticaldepthparams, vec4(atmoshells, planetradius));
-
- // Henyey-Greenstein approximation, 1/(4pi) * (1 - g^2)/(1 + g^2 - 2gcos)]^1.5
- // Hoffman-Preetham variation uses (1-g)^2 instead of 1-g^2 which avoids excessive glare
- // clamp values near 0 angle to avoid spotlight artifact inside sundisk
- float gm = max(0.95f - 0.2f*atmohaze, 0.65f), miescale = pow((1-gm)*(1-gm)/(4*M_PI), -2.0f/3.0f);
- LOCALPARAMF(mieparams, miescale*(1 + gm*gm), miescale*-2*gm, 1 - (1 - cosf(0.5f*atmosundisksize*(1 - atmosundiskcorona)*RAD)));
-
- static const vec lambda(680e-9f, 550e-9f, 450e-9f),
- k(0.686f, 0.678f, 0.666f),
- ozone(3.426f, 8.298f, 0.356f);
- vec betar = vec(lambda).square().square().recip().mul(1.241e-30f/M_LN2 * atmodensity),
- betam = vec(lambda).recip().square().mul(k).mul(9.072e-17f/M_LN2 * atmohaze),
- betao = vec(ozone).mul(1.5e-7f/M_LN2 * atmoozone);
- LOCALPARAM(betarayleigh, betar);
- LOCALPARAM(betamie, betam);
- LOCALPARAM(betaozone, betao);
-
- // extinction in direction of sun
- float sunoffset = sunlightdir.z*planetradius;
- vec sundepth = vec(atmoshells).add(sunoffset*sunoffset).sqrt().sub(sunoffset);
- vec sunweight = vec(betar).mul(sundepth.x).madd(betam, sundepth.y).madd(betao, sundepth.z - sundepth.x);
- vec sunextinction = vec(sunweight).neg().exp2();
- vec suncolor = atmosunlight ? atmosunlightcolor.tocolor().mul(atmosunlightscale) : sunlightcolor.tocolor().mul(sunlightscale);
- // assume sunlight color is gamma encoded, so decode to linear light, then apply extinction
- vec sunscale = vec(suncolor).square().mul(atmobright * 16).mul(sunextinction);
- float maxsunweight = max(max(sunweight.x, sunweight.y), sunweight.z);
- if(maxsunweight > 127) sunweight.mul(127/maxsunweight);
- sunweight.add(1e-4f);
- LOCALPARAM(sunweight, sunweight);
- LOCALPARAM(sunlight, vec4(sunscale, atmoalpha));
- LOCALPARAM(sundir, sunlightdir);
-
- // invert extinction at zenith to get an approximation of how bright the sun disk should be
- vec zenithdepth = vec(atmoshells).add(planetradius*planetradius).sqrt().sub(planetradius);
- vec zenithweight = vec(betar).mul(zenithdepth.x).madd(betam, zenithdepth.y).madd(betao, zenithdepth.z - zenithdepth.x);
- vec zenithextinction = vec(zenithweight).sub(sunweight).exp2();
- vec diskcolor = (atmosundisk ? atmosundiskcolor.tocolor() : suncolor).square().mul(zenithextinction).mul(atmosundiskbright * (glaring ? 1 : 1.5f)).min(1);
- LOCALPARAM(sundiskcolor, diskcolor);
-
- // convert from view cosine into mu^2 for limb darkening, where mu = sqrt(1 - sin^2) and sin^2 = 1 - cos^2, thus mu^2 = 1 - (1 - cos^2*scale)
- // convert corona offset into scale for mu^2, where sin = (1-corona) and thus mu^2 = 1 - (1-corona^2)
- float sundiskscale = sinf(0.5f*atmosundisksize*RAD);
- float coronamu = 1 - (1-atmosundiskcorona)*(1-atmosundiskcorona);
- if(sundiskscale > 0) LOCALPARAMF(sundiskparams, 1.0f/(sundiskscale*sundiskscale), 1.0f/max(coronamu, 1e-3f));
- else LOCALPARAMF(sundiskparams, 0, 0);
-
- float z1 = 2*w*(z1clip-0.5f), z2 = ceil(2*w*(z2clip-0.5f));
-
- gle::defvertex();
-
- if(glaring)
- {
- if(sundiskscale > 0 && sunlightdir.z*w + sundiskscale > z1 && sunlightdir.z*w - sundiskscale < z2)
- {
- gle::begin(GL_TRIANGLE_FAN);
- vec spoke;
- spoke.orthogonal(sunlightdir);
- spoke.rescale(2*sundiskscale);
- loopi(4) gle::attrib(vec(spoke).rotate(-2*M_PI*i/4.0f, sunlightdir).add(sunlightdir).mul(w));
- xtraverts += gle::end();
- }
- return;
- }
-
- gle::begin(GL_QUADS);
-
- if(faces&0x01)
- {
- gle::attribf(-w, -w, z1);
- gle::attribf(-w, w, z1);
- gle::attribf(-w, w, z2);
- gle::attribf(-w, -w, z2);
- }
-
- if(faces&0x02)
- {
- gle::attribf(w, -w, z2);
- gle::attribf(w, w, z2);
- gle::attribf(w, w, z1);
- gle::attribf(w, -w, z1);
- }
-
- if(faces&0x04)
- {
- gle::attribf(-w, -w, z2);
- gle::attribf( w, -w, z2);
- gle::attribf( w, -w, z1);
- gle::attribf(-w, -w, z1);
- }
-
- if(faces&0x08)
- {
- gle::attribf( w, w, z2);
- gle::attribf(-w, w, z2);
- gle::attribf(-w, w, z1);
- gle::attribf( w, w, z1);
- }
-
- if(z1clip <= 0 && faces&0x10)
- {
- gle::attribf(-w, -w, -w);
- gle::attribf( w, -w, -w);
- gle::attribf( w, w, -w);
- gle::attribf(-w, w, -w);
- }
-
- if(z2clip >= 1 && faces&0x20)
- {
- gle::attribf( w, -w, w);
- gle::attribf(-w, -w, w);
- gle::attribf(-w, w, w);
- gle::attribf( w, w, w);
- }
-
- xtraverts += gle::end();
-}
-
-VARP(sparklyfix, 0, 0, 1);
-VAR(showsky, 0, 1, 1);
-VAR(clipsky, 0, 1, 1);
-
-bool drawskylimits(bool explicitonly)
-{
- nocolorshader->set();
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- bool rendered = rendersky(explicitonly);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- return rendered;
-}
-
-void drawskyoutline()
-{
- notextureshader->set();
-
- glDepthMask(GL_FALSE);
- extern int wireframe;
- if(!wireframe)
- {
- enablepolygonoffset(GL_POLYGON_OFFSET_LINE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
- gle::colorf(0.5f, 0.0f, 0.5f);
- rendersky(true);
- if(!wireframe)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- disablepolygonoffset(GL_POLYGON_OFFSET_LINE);
- }
- glDepthMask(GL_TRUE);
-}
-
-VAR(clampsky, 0, 1, 1);
-
-static int yawskyfaces(int faces, int yaw, float spin = 0)
-{
- if(spin || yaw%90) return faces&0x0F ? faces | 0x0F : faces;
- static const int faceidxs[3][4] =
- {
- { 3, 2, 0, 1 },
- { 1, 0, 3, 2 },
- { 2, 3, 1, 0 }
- };
- yaw /= 90;
- if(yaw < 1 || yaw > 3) return faces;
- const int *idxs = faceidxs[yaw - 1];
- return (faces & ~0x0F) | (((faces>>idxs[0])&1)<<0) | (((faces>>idxs[1])&1)<<1) | (((faces>>idxs[2])&1)<<2) | (((faces>>idxs[3])&1)<<3);
-}
-
-void drawskybox(int farplane, bool limited, bool force)
-{
- extern int renderedskyfaces, renderedskyclip; // , renderedsky, renderedexplicitsky;
- bool alwaysrender = editmode || !insideworld(camera1->o) || reflecting || force,
- explicitonly = false;
- if(limited)
- {
- explicitonly = alwaysrender || !sparklyfix || refracting;
- if(!drawskylimits(explicitonly) && !alwaysrender) return;
- extern int ati_skybox_bug;
- if(!alwaysrender && !renderedskyfaces && !ati_skybox_bug) explicitonly = false;
- }
- else if(!alwaysrender)
- {
- renderedskyfaces = 0;
- renderedskyclip = INT_MAX;
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(va->occluded >= OCCLUDE_BB && va->skyfaces&0x80) continue;
- renderedskyfaces |= va->skyfaces&0x3F;
- if(!(va->skyfaces&0x1F) || camera1->o.z < va->skyclip) renderedskyclip = min(renderedskyclip, va->skyclip);
- else renderedskyclip = 0;
- }
- if(!renderedskyfaces) return;
- }
-
- if(alwaysrender)
- {
- renderedskyfaces = 0x3F;
- renderedskyclip = 0;
- }
-
- float skyclip = clipsky ? max(renderedskyclip-1, 0) : 0, topclip = 1;
- if(reflectz<worldsize)
- {
- if(refracting<0) topclip = 0.5f + 0.5f*(reflectz-camera1->o.z)/float(worldsize);
- else if(reflectz>skyclip) skyclip = reflectz;
- }
- if(skyclip) skyclip = 0.5f + 0.5f*(skyclip-camera1->o.z)/float(worldsize);
-
- if(limited)
- {
- if(explicitonly) glDisable(GL_DEPTH_TEST);
- else glDepthFunc(GL_GEQUAL);
- }
- else glDepthFunc(GL_LEQUAL);
-
- glDepthMask(GL_FALSE);
-
- if(clampsky) glDepthRange(1, 1);
-
- if(!atmo || (skybox[0] && atmoalpha < 1))
- {
- if(glaring) SETSHADER(skyboxglare);
- else SETSHADER(skybox);
-
- gle::color(vec::hexcolor(skyboxcolour));
-
- matrix4 skymatrix = cammatrix, skyprojmatrix;
- skymatrix.settranslation(0, 0, 0);
- skymatrix.rotate_around_z((spinsky*lastmillis/1000.0f+yawsky)*-RAD);
- skyprojmatrix.mul(projmatrix, skymatrix);
- LOCALPARAM(skymatrix, skyprojmatrix);
-
- drawenvbox(farplane/2, skyclip, topclip, yawskyfaces(renderedskyfaces, yawsky, spinsky), sky);
- }
-
- if(atmo)
- {
- if(atmoalpha < 1)
- {
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- drawatmosphere(farplane/2, skyclip, topclip, renderedskyfaces);
-
- if(atmoalpha < 1) glDisable(GL_BLEND);
- }
-
- if(!glaring)
- {
- if(fogdomemax && !fogdomeclouds)
- {
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- drawfogdome(farplane);
- }
-
- if(cloudbox[0])
- {
- SETSHADER(skybox);
-
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- gle::color(vec::hexcolor(cloudboxcolour), cloudboxalpha);
-
- matrix4 skymatrix = cammatrix, skyprojmatrix;
- skymatrix.settranslation(0, 0, 0);
- skymatrix.rotate_around_z((spinclouds*lastmillis/1000.0f+yawclouds)*-RAD);
- skyprojmatrix.mul(projmatrix, skymatrix);
- LOCALPARAM(skymatrix, skyprojmatrix);
-
- drawenvbox(farplane/2, skyclip ? skyclip : cloudclip, topclip, yawskyfaces(renderedskyfaces, yawclouds, spinclouds), clouds);
-
- glDisable(GL_BLEND);
- }
-
- if(cloudlayer[0] && cloudheight && renderedskyfaces&(cloudheight < 0 ? 0x1F : 0x2F))
- {
- SETSHADER(skybox);
-
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
-
- glDisable(GL_CULL_FACE);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- matrix4 skymatrix = cammatrix, skyprojmatrix;
- skymatrix.settranslation(0, 0, 0);
- skymatrix.rotate_around_z((spincloudlayer*lastmillis/1000.0f+yawcloudlayer)*-RAD);
- skyprojmatrix.mul(projmatrix, skymatrix);
- LOCALPARAM(skymatrix, skyprojmatrix);
-
- drawenvoverlay(farplane/2, cloudoverlay, cloudoffsetx + cloudscrollx * lastmillis/1000.0f, cloudoffsety + cloudscrolly * lastmillis/1000.0f);
-
- glDisable(GL_BLEND);
-
- glEnable(GL_CULL_FACE);
- }
-
- if(fogdomemax && fogdomeclouds)
- {
- if(fading) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
- drawfogdome(farplane);
- }
- }
-
- if(clampsky) glDepthRange(0, 1);
-
- glDepthMask(GL_TRUE);
-
- if(limited)
- {
- if(explicitonly) glEnable(GL_DEPTH_TEST);
- else glDepthFunc(GL_LESS);
- if(!reflecting && !refracting && !drawtex && editmode && showsky) drawskyoutline();
- }
- else glDepthFunc(GL_LESS);
-}
-
-VARNR(skytexture, useskytexture, 0, 1, 1);
-
-int explicitsky = 0;
-double skyarea = 0;
-
-bool limitsky()
-{
- return (explicitsky && (useskytexture || editmode)) || (sparklyfix && skyarea / (double(worldsize)*double(worldsize)*6) < 0.9);
-}
-
-bool shouldrenderskyenvmap()
-{
- return atmo != 0;
-}
-
-bool shouldclearskyboxglare()
-{
- return atmo && (!skybox[0] || atmoalpha >= 1);
-}
-
///////// view frustrum culling ///////////////////////
plane vfcP[5]; // perpindictular vectors to view frustrum bounding planes
-float vfcDfog; // far plane culling distance (fog limit).
float vfcDnear[5], vfcDfar[5];
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;
-}
-
int isvisiblesphere(float rad, const vec &cv)
{
int v = VFC_FULL_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;
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;
-}
-
int isvisiblecube(const ivec &o, int size)
{
int v = VFC_FULL_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;
vfcP[4] = plane(vec4(pw).add(pz)).normalize(); // near/far planes
if(z >= 0) loopi(5) vfcP[i].reflectz(z);
- vfcDfog = fog;
calcvfcD();
}
else
{
memclear(vfcP);
- vfcDfog = 1000000;
memclear(vfcDnear);
memclear(vfcDfar);
visibleva = NULL;
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)
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();
- }
-}
-
void rendermapmodels()
{
static int skipoq = 0;
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)
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(fading && !cur.blending && !cur.alphaing)
{
if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot);
else s->setvariant(cur.visibledynlights, 2, slot, vslot);
drawvatris(va, 3*numtris, edata);
}
-vector<vtxarray *> foggedvas;
-
#define startvaquery(va, flush) \
do { \
if(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();
-
- if(!cur.vattribs) enablevattribs(cur, false);
-
- 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, );
- }
-
- foggedvas.setsize(0);
-}
-
VAR(batchgeom, 0, 1, 1);
void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool fogpass = false, bool doquery = false)
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);
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);
}
}
-#define NUMCAUSTICS 32
-
-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);
- }
-}
-
void cleanupva()
{
clearvas(worldroot);
clearqueries();
cleanupbb();
- loopi(NUMCAUSTICS) caustictex[i] = NULL;
-}
-
-VARR(causticscale, 0, 50, 10000);
-VARR(causticmillis, 0, 75, 1000);
-FVARR(causticcontrast, 0, 0.6f, 1);
-VARFP(caustics, 0, 1, 1, loadcaustics());
-
-void setupcaustics(float blend)
-{
- 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);
}
void setupgeom(renderstate &cur)
if(cur.vbuf) disablevbuf(cur);
}
-#define FIRSTVA (reflecting ? reflectedva : visibleva)
-#define NEXTVA (reflecting ? va->rnext : va->next)
-
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)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
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;
+ if(va->occluded >= OCCLUDE_GEOM) continue;
renderva(cur, va, pass, fogpass);
}
if(geombatches.length()) renderbatches(cur, pass);
VAR(oqgeom, 0, 1, 1);
-void rendergeom(float causticspass, bool fogpass)
+void rendergeom(bool fogpass)
{
- if(causticspass && (!causticscale || !causticmillis)) causticspass = 0;
-
- bool mainpass = !reflecting && !refracting && !drawtex && !glaring,
+ bool mainpass = !drawtex && !glaring,
doOQ = oqfrags && oqgeom && mainpass,
doZP = doOQ && zpass,
doSM = shadowmap && !drawtex && !glaring;
resetbatches();
int blends = 0;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
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(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o))
{
if(va->parent && va->parent->occluded >= OCCLUDE_BB)
{
cur.texgendim = -1;
cur.blending = true;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
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;
+ if(va->occluded >= OCCLUDE_GEOM) continue;
renderva(cur, va, RENDERPASS_LIGHTMAP_BLEND, fogpass);
}
if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP);
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);
static vector<vtxarray *> alphavas;
alphavas.setsize(0);
bool hasback = false;
- for(vtxarray *va = FIRSTVA; va; va = NEXTVA)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
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;
+ if(va->occluded >= OCCLUDE_BB) continue;
alphavas.add(va);
if(va->alphabacktris) hasback = true;
}
cleanupgeom(cur);
- resetfogcolor();
if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); }
glDisable(GL_BLEND);
glDepthFunc(GL_LESS);
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);
- }
-}
-
-void renderreflectedgeom(bool causticspass, bool 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)
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);
- }
-}
-
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)
+ for(vtxarray *va = visibleva; va; va = va->next)
{
if((va->occluded >= OCCLUDE_BB && va->skyfaces&0x80) || !(va->sky+va->explicitsky)) continue;
Shader *Shader::lastshader = NULL;
-Shader *nullshader = NULL, *hudshader = NULL, *hudnotextureshader = NULL, *textureshader = NULL, *notextureshader = NULL, *nocolorshader = NULL, *foggedshader = NULL, *foggednotextureshader = NULL, *stdworldshader = NULL;
+Shader *nullshader = NULL, *hudshader = NULL, *hudnotextureshader = NULL, *textureshader = NULL, *notextureshader = NULL, *nocolorshader = NULL, *stdworldshader = NULL;
static hashnameset<GlobalShaderParamState> globalparams(256);
static hashtable<const char *, int> localparams(256);
textureshader = lookupshaderbyname("texture");
notextureshader = lookupshaderbyname("notexture");
nocolorshader = lookupshaderbyname("nocolor");
- foggedshader = lookupshaderbyname("fogged");
- foggednotextureshader = lookupshaderbyname("foggednotexture");
nullshader->set();
tmu++;
}
else UNIFORMTEX("lightmap", 1);
- if(type & SHADER_ENVMAP) UNIFORMTEX("envmap", tmu++);
UNIFORMTEX("shadowmap", 7);
int stex = 0;
loopv(slot->sts)
newshader(s.type, varname, vschanged ? vsv.getbuf() : reuse, pschanged ? psv.getbuf() : reuse, &s, row);
}
-static bool genwatervariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 2)
-{
- if(!strstr(vs, "//:water") && !strstr(ps, "//:water")) return false;
-
- vector<char> vsw, psw;
-
- const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
- if(!vsmain || !vsend) return false;
- vsw.put(vs, vsmain - vs);
- const char *fadeparams = "\nuniform vec4 waterfadeparams;\nvarying float fadedepth;\n";
- vsw.put(fadeparams, strlen(fadeparams));
- vsw.put(vsmain, vsend - vsmain);
- const char *fadedef = "\nfadedepth = vvertex.z*waterfadeparams.x + waterfadeparams.y;\n";
- vsw.put(fadedef, strlen(fadedef));
- vsw.put(vsend, strlen(vsend)+1);
-
- const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
- if(!psmain || !psend) return false;
- psw.put(ps, psmain - ps);
- const char *fadeinterp = "\nvarying float fadedepth;\n";
- psw.put(fadeinterp, strlen(fadeinterp));
- psw.put(psmain, psend - psmain);
- const char *fade = "\ngl_FragColor.a = fadedepth;\n";
- psw.put(fade, strlen(fade));
- psw.put(psend, strlen(psend)+1);
-
- defformatstring(name, "<water>%s", sname);
- Shader *variant = newshader(s.type, name, vsw.getbuf(), psw.getbuf(), &s, row);
- return variant!=NULL;
-}
-
bool minimizedynlighttcusage() { return glversion < 300 && maxvaryings < 48; }
static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0)
defformatstring(name, "<dynlight %d>%s", i+1, sname);
Shader *variant = newshader(s.type, name, vsdl.getbuf(), psdl.getbuf(), &s, row);
if(!variant) return;
- if(row < 4) genwatervariant(s, name, vsdl.getbuf(), psdl.getbuf(), row+2);
}
}
defformatstring(name, "<shadowmap>%s", sname);
Shader *variant = newshader(s.type, name, vssm.getbuf(), pssm.getbuf(), &s, row);
if(!variant) return;
- genwatervariant(s, name, vssm.getbuf(), pssm.getbuf(), row+2);
if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row);
}
-static void genfogshader(vector<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps)
-{
- const char *vspragma = strstr(vs, "//:fog"), *pspragma = strstr(ps, "//:fog");
- if(!vspragma && !pspragma) return;
- static const int pragmalen = strlen("//:fog");
- const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
- if(vsmain && vsend)
- {
- vsbuf.put(vs, vsmain - vs);
- const char *fogparams = "\nuniform vec4 fogplane;\nvarying float fogcoord;\n";
- vsbuf.put(fogparams, strlen(fogparams));
- vsbuf.put(vsmain, vsend - vsmain);
- const char *vsfog = "\nfogcoord = dot(fogplane, gl_Position);\n";
- vsbuf.put(vsfog, strlen(vsfog));
- vsbuf.put(vsend, strlen(vsend)+1);
- }
- const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
- if(psmain && psend)
- {
- psbuf.put(ps, psmain - ps);
- const char *fogparams =
- "\nuniform vec3 fogcolor;\n"
- "uniform vec2 fogparams;\n"
- "varying float fogcoord;\n";
- psbuf.put(fogparams, strlen(fogparams));
- psbuf.put(psmain, psend - psmain);
- const char *psdef = "\n#define FOG_COLOR ";
- const char *psfog =
- pspragma && !strncmp(pspragma+pragmalen, "rgba", 4) ?
- "\ngl_FragColor = mix((FOG_COLOR), gl_FragColor, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n" :
- "\ngl_FragColor.rgb = mix((FOG_COLOR).rgb, gl_FragColor.rgb, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n";
- int clen = 0;
- if(pspragma)
- {
- pspragma += pragmalen;
- while(iscubealpha(*pspragma)) pspragma++;
- while(*pspragma && !iscubespace(*pspragma)) pspragma++;
- pspragma += strspn(pspragma, " \t\v\f");
- clen = strcspn(pspragma, "\r\n");
- }
- if(clen <= 0) { pspragma = "fogcolor"; clen = strlen(pspragma); }
- psbuf.put(psdef, strlen(psdef));
- psbuf.put(pspragma, clen);
- psbuf.put(psfog, strlen(psfog));
- psbuf.put(psend, strlen(psend)+1);
- }
-}
-
static void genuniformdefs(vector<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps, Shader *variant = NULL)
{
if(variant ? variant->defaultparams.empty() : slotparams.empty()) return;
if(psbuf.length()) ps = psbuf.getbuf(); \
}
GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps));
- GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
Shader *s = newshader(*type, name, vs, ps);
if(s)
{
- if(strstr(vs, "//:water")) genwatervariant(*s, s->name, vs, ps);
if(strstr(vs, "//:shadowmap")) genshadowmapvariant(*s, s->name, vs, ps);
if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, s->name, vs, ps);
}
//renderprogress(loadprogress, info);
vector<char> vsbuf, psbuf, vsbak, psbak;
GENSHADER(s->defaultparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps, s));
- GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
Shader *v = newshader(*type, varname, vs, ps, s, *row);
if(v)
{
ICOMMAND(setshaderparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w));
ICOMMAND(defuniformparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w));
-#define NUMPOSTFXBINDS 10
-
-struct postfxtex
-{
- GLuint id;
- int scale, used;
-
- postfxtex() : id(0), scale(0), used(-1) {}
-};
-vector<postfxtex> postfxtexs;
-int postfxbinds[NUMPOSTFXBINDS];
-GLuint postfxfb = 0;
-int postfxw = 0, postfxh = 0;
-
-struct postfxpass
-{
- Shader *shader;
- vec4 params;
- uint inputs, freeinputs;
- int outputbind, outputscale;
-
- postfxpass() : shader(NULL), inputs(1), freeinputs(1), outputbind(0), outputscale(0) {}
-};
-vector<postfxpass> postfxpasses;
-
-static int allocatepostfxtex(int scale)
-{
- loopv(postfxtexs)
- {
- postfxtex &t = postfxtexs[i];
- if(t.scale==scale && t.used < 0) return i;
- }
- postfxtex &t = postfxtexs.add();
- t.scale = scale;
- glGenTextures(1, &t.id);
- createtexture(t.id, max(screenw>>scale, 1), max(screenh>>scale, 1), NULL, 3, 1, GL_RGB);
- return postfxtexs.length()-1;
-}
-
-void cleanuppostfx(bool fullclean)
-{
- if(fullclean && postfxfb)
- {
- glDeleteFramebuffers_(1, &postfxfb);
- postfxfb = 0;
- }
-
- loopv(postfxtexs) glDeleteTextures(1, &postfxtexs[i].id);
- postfxtexs.shrink(0);
-
- postfxw = 0;
- postfxh = 0;
-}
-
-void renderpostfx()
-{
- if(postfxpasses.empty()) return;
-
- if(postfxw != screenw || postfxh != screenh)
- {
- cleanuppostfx(false);
- postfxw = screenw;
- postfxh = screenh;
- }
-
- int binds[NUMPOSTFXBINDS];
- loopi(NUMPOSTFXBINDS) binds[i] = -1;
- loopv(postfxtexs) postfxtexs[i].used = -1;
-
- binds[0] = allocatepostfxtex(0);
- postfxtexs[binds[0]].used = 0;
- glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[0]].id);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenw, screenh);
-
- if(postfxpasses.length() > 1)
- {
- if(!postfxfb) glGenFramebuffers_(1, &postfxfb);
- glBindFramebuffer_(GL_FRAMEBUFFER, postfxfb);
- }
-
- GLOBALPARAMF(millis, lastmillis/1000.0f);
-
- loopv(postfxpasses)
- {
- postfxpass &p = postfxpasses[i];
-
- int tex = -1;
- if(!postfxpasses.inrange(i+1))
- {
- if(postfxpasses.length() > 1) glBindFramebuffer_(GL_FRAMEBUFFER, 0);
- }
- else
- {
- tex = allocatepostfxtex(p.outputscale);
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, postfxtexs[tex].id, 0);
- }
-
- int w = tex >= 0 ? max(screenw>>postfxtexs[tex].scale, 1) : screenw,
- h = tex >= 0 ? max(screenh>>postfxtexs[tex].scale, 1) : screenh;
- glViewport(0, 0, w, h);
- p.shader->set();
- LOCALPARAM(params, p.params);
- int tw = w, th = h, tmu = 0;
- loopj(NUMPOSTFXBINDS) if(p.inputs&(1<<j) && binds[j] >= 0)
- {
- if(!tmu)
- {
- tw = max(screenw>>postfxtexs[binds[j]].scale, 1);
- th = max(screenh>>postfxtexs[binds[j]].scale, 1);
- }
- else glActiveTexture_(GL_TEXTURE0 + tmu);
- glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[j]].id);
- ++tmu;
- }
- if(tmu) glActiveTexture_(GL_TEXTURE0);
- LOCALPARAMF(postfxscale, 1.0f/tw, 1.0f/th);
- screenquad(1, 1);
-
- loopj(NUMPOSTFXBINDS) if(p.freeinputs&(1<<j) && binds[j] >= 0)
- {
- postfxtexs[binds[j]].used = -1;
- binds[j] = -1;
- }
- if(tex >= 0)
- {
- if(binds[p.outputbind] >= 0) postfxtexs[binds[p.outputbind]].used = -1;
- binds[p.outputbind] = tex;
- postfxtexs[tex].used = p.outputbind;
- }
- }
-}
-
-static bool addpostfx(const char *name, int outputbind, int outputscale, uint inputs, uint freeinputs, const vec4 ¶ms)
-{
- if(!*name) return false;
- Shader *s = useshaderbyname(name);
- if(!s)
- {
- conoutf(CON_ERROR, "no such postfx shader: %s", name);
- return false;
- }
- postfxpass &p = postfxpasses.add();
- p.shader = s;
- p.outputbind = outputbind;
- p.outputscale = outputscale;
- p.inputs = inputs;
- p.freeinputs = freeinputs;
- p.params = params;
- return true;
-}
-
-void clearpostfx()
-{
- postfxpasses.shrink(0);
- cleanuppostfx(false);
-}
-
-COMMAND(clearpostfx, "");
-
-ICOMMAND(addpostfx, "siisffff", (char *name, int *bind, int *scale, char *inputs, float *x, float *y, float *z, float *w),
-{
- int inputmask = inputs[0] ? 0 : 1;
- int freemask = inputs[0] ? 0 : 1;
- bool freeinputs = true;
- for(; *inputs; inputs++) if(isdigit(*inputs))
- {
- inputmask |= 1<<(*inputs-'0');
- if(freeinputs) freemask |= 1<<(*inputs-'0');
- }
- else if(*inputs=='+') freeinputs = false;
- else if(*inputs=='-') freeinputs = true;
- inputmask &= (1<<NUMPOSTFXBINDS)-1;
- freemask &= (1<<NUMPOSTFXBINDS)-1;
- addpostfx(name, clamp(*bind, 0, NUMPOSTFXBINDS-1), max(*scale, 0), inputmask, freemask, vec4(*x, *y, *z, *w));
-});
-
-ICOMMAND(setpostfx, "sffff", (char *name, float *x, float *y, float *z, float *w),
-{
- clearpostfx();
- if(name[0]) addpostfx(name, 0, 0, 1, 1, vec4(*x, *y, *z, *w));
-});
-
void cleanupshaders()
{
- cleanuppostfx(true);
-
loadedshaders = false;
- nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = foggedshader = foggednotextureshader = stdworldshader = NULL;
+ nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = stdworldshader = NULL;
enumerate(shaders, Shader, s, s.cleanup());
Shader::lastshader = NULL;
glUseProgram_(0);
{
if(shadowmapangle) return;
vec dir;
- if(!sunlightcolor.iszero()) dir = sunlightdir;
- else
{
vec lightpos(0, 0, 0), casterpos(0, 0, 0);
int numlights = 0, numcasters = 0;
float r, g, b;
if(!shadowmapambient)
{
- if(skylightcolor[0] || skylightcolor[1] || skylightcolor[2])
- {
- r = max(25.0f, 0.4f*ambientcolor[0] + 0.6f*max(ambientcolor[0], skylightcolor[0]));
- g = max(25.0f, 0.4f*ambientcolor[1] + 0.6f*max(ambientcolor[1], skylightcolor[1]));
- b = max(25.0f, 0.4f*ambientcolor[2] + 0.6f*max(ambientcolor[2], skylightcolor[2]));
- }
- else
- {
- r = max(25.0f, 2.0f*ambientcolor[0]);
- g = max(25.0f, 2.0f*ambientcolor[1]);
- b = max(25.0f, 2.0f*ambientcolor[2]);
- }
+ r = max(25.0f, 2.0f*ambientcolor[0]);
+ g = max(25.0f, 2.0f*ambientcolor[1]);
+ b = max(25.0f, 2.0f*ambientcolor[2]);
}
else { r = shadowmapambientcolor[0]; g = shadowmapambientcolor[1]; b = shadowmapambientcolor[2]; }
GLOBALPARAMF(shadowmapambient, r/255.0f, g/255.0f, b/255.0f);
}
}
-// environment mapped reflections
-
-void forcecubemapload(GLuint tex)
-{
- extern int ati_cubemap_bug;
- if(!ati_cubemap_bug || !tex) return;
-
- SETSHADER(cubemap);
- GLenum depthtest = glIsEnabled(GL_DEPTH_TEST), blend = glIsEnabled(GL_BLEND);
- if(depthtest) glDisable(GL_DEPTH_TEST);
- glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
- if(!blend) glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gle::defvertex(2);
- gle::deftexcoord0(3);
- gle::defcolor(4);
- gle::begin(GL_LINES);
- loopi(2)
- {
- gle::attribf(i*1e-3f, 0);
- gle::attribf(0, 0, 1);
- gle::attribf(1, 1, 1, 0);
- }
- gle::end();
- if(!blend) glDisable(GL_BLEND);
- if(depthtest) glEnable(GL_DEPTH_TEST);
-}
-
-extern const cubemapside cubemapsides[6] =
-{
- { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, "lf", true, true, true },
- { GL_TEXTURE_CUBE_MAP_POSITIVE_X, "rt", false, false, true },
- { GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, "ft", true, false, false },
- { GL_TEXTURE_CUBE_MAP_POSITIVE_Y, "bk", false, true, false },
- { GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, "dn", false, false, true },
- { GL_TEXTURE_CUBE_MAP_POSITIVE_Z, "up", false, false, true },
-};
-
-VARFP(envmapsize, 4, 7, 10, setupmaterials());
-
-Texture *cubemaploadwildcard(Texture *t, const char *name, bool mipit, bool msg, bool transient = false)
-{
- string tname;
- if(!name) copystring(tname, t->name);
- else
- {
- copystring(tname, name);
- t = textures.access(path(tname));
- if(t)
- {
- if(!transient && t->type&Texture::TRANSIENT) t->type &= ~Texture::TRANSIENT;
- return t;
- }
- }
- char *wildcard = strchr(tname, '*');
- ImageData surface[6];
- string sname;
- if(!wildcard) copystring(sname, tname);
- int tsize = 0, compress = 0;
- loopi(6)
- {
- if(wildcard)
- {
- copystring(sname, stringslice(tname, wildcard));
- concatstring(sname, cubemapsides[i].name);
- concatstring(sname, wildcard+1);
- }
- ImageData &s = surface[i];
- texturedata(s, sname, NULL, msg, &compress);
- if(!s.data) return NULL;
- if(s.w != s.h)
- {
- if(msg) conoutf(CON_ERROR, "cubemap texture %s does not have square size", sname);
- return NULL;
- }
- if(s.compressed ? s.compressed!=surface[0].compressed || s.w!=surface[0].w || s.h!=surface[0].h || s.levels!=surface[0].levels : surface[0].compressed || s.bpp!=surface[0].bpp)
- {
- if(msg) conoutf(CON_ERROR, "cubemap texture %s doesn't match other sides' format", sname);
- return NULL;
- }
- tsize = max(tsize, max(s.w, s.h));
- }
- if(name)
- {
- char *key = newstring(tname);
- t = &textures[key];
- t->name = key;
- }
- t->type = Texture::CUBEMAP;
- if(transient) t->type |= Texture::TRANSIENT;
- GLenum format;
- if(surface[0].compressed)
- {
- format = uncompressedformat(surface[0].compressed);
- t->bpp = formatsize(format);
- t->type |= Texture::COMPRESSED;
- }
- else
- {
- format = texformat(surface[0].bpp, true);
- t->bpp = surface[0].bpp;
- if(hasTRG && !hasTSW && swizzlemask(format))
- {
- loopi(6) swizzleimage(surface[i]);
- format = texformat(surface[0].bpp, true);
- t->bpp = surface[0].bpp;
- }
- }
- if(alphaformat(format)) t->type |= Texture::ALPHA;
- t->mipmap = mipit;
- t->clamp = 3;
- t->xs = t->ys = tsize;
- t->w = t->h = min(1<<envmapsize, tsize);
- resizetexture(t->w, t->h, mipit, false, GL_TEXTURE_CUBE_MAP, compress, t->w, t->h);
- GLenum component = format;
- if(!surface[0].compressed)
- {
- component = compressedformat(format, t->w, t->h, compress);
- switch(component)
- {
- case GL_RGB: component = GL_RGB5; break;
- }
- }
- glGenTextures(1, &t->id);
- loopi(6)
- {
- ImageData &s = surface[i];
- const cubemapside &side = cubemapsides[i];
- texreorient(s, side.flipx, side.flipy, side.swapxy);
- if(s.compressed)
- {
- int w = s.w, h = s.h, levels = s.levels, level = 0;
- uchar *data = s.data;
- while(levels > 1 && (w > t->w || h > t->h))
- {
- data += s.calclevelsize(level++);
- levels--;
- if(w > 1) w /= 2;
- if(h > 1) h /= 2;
- }
- createcompressedtexture(t->id, w, h, data, s.align, s.bpp, levels, i ? -1 : 3, mipit ? 2 : 1, s.compressed, side.target, true);
- }
- else
- {
- createtexture(t->id, t->w, t->h, s.data, i ? -1 : 3, mipit ? 2 : 1, component, side.target, s.w, s.h, s.pitch, false, format, true);
- }
- }
- forcecubemapload(t->id);
- return t;
-}
-
-Texture *cubemapload(const char *name, bool mipit, bool msg, bool transient)
-{
- string pname;
- copystring(pname, makerelpath("packages", name));
- path(pname);
- Texture *t = NULL;
- if(!strchr(pname, '*'))
- {
- defformatstring(jpgname, "%s_*.jpg", pname);
- t = cubemaploadwildcard(NULL, jpgname, mipit, false, transient);
- if(!t)
- {
- defformatstring(pngname, "%s_*.png", pname);
- t = cubemaploadwildcard(NULL, pngname, mipit, false, transient);
- if(!t && msg) conoutf(CON_ERROR, "could not load envmap %s", name);
- }
- }
- else t = cubemaploadwildcard(NULL, pname, mipit, msg, transient);
- return t;
-}
-
-VARR(envmapradius, 0, 128, 10000);
-VARR(envmapbb, 0, 0, 1);
-
-struct envmap
-{
- int radius, size, blur;
- vec o;
- GLuint tex;
-
- envmap() : radius(-1), size(0), blur(0), o(0, 0, 0), tex(0) {}
-
- void clear()
- {
- if(tex) { glDeleteTextures(1, &tex); tex = 0; }
- }
-};
-
-static vector<envmap> envmaps;
-static Texture *skyenvmap = NULL;
-
-void clearenvmaps()
-{
- if(skyenvmap)
- {
- if(skyenvmap->type&Texture::TRANSIENT) cleanuptexture(skyenvmap);
- skyenvmap = NULL;
- }
- loopv(envmaps) envmaps[i].clear();
- envmaps.shrink(0);
-}
-
-VAR(aaenvmap, 0, 2, 4);
-
-GLuint genenvmap(const vec &o, int envmapsize, int blur, bool onlysky)
-{
- int rendersize = 1<<(envmapsize+aaenvmap), sizelimit = min(hwcubetexsize, min(screenw, screenh));
- if(maxtexsize) sizelimit = min(sizelimit, maxtexsize);
- while(rendersize > sizelimit) rendersize /= 2;
- int texsize = min(rendersize, 1<<envmapsize);
- if(!aaenvmap) rendersize = texsize;
- GLuint tex;
- glGenTextures(1, &tex);
- glViewport(0, 0, rendersize, rendersize);
- float yaw = 0, pitch = 0;
- uchar *pixels = new uchar[3*rendersize*rendersize*2];
- glPixelStorei(GL_PACK_ALIGNMENT, texalign(pixels, rendersize, 3));
- loopi(6)
- {
- const cubemapside &side = cubemapsides[i];
- switch(side.target)
- {
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: // lf
- yaw = 90; pitch = 0; break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X: // rt
- yaw = 270; pitch = 0; break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: // ft
- yaw = 180; pitch = 0; break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: // bk
- yaw = 0; pitch = 0; break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: // dn
- yaw = 270; pitch = -90; break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: // up
- yaw = 270; pitch = 90; break;
- }
- glFrontFace((side.flipx==side.flipy)!=side.swapxy ? GL_CW : GL_CCW);
- drawcubemap(rendersize, o, yaw, pitch, side, onlysky);
- uchar *src = pixels, *dst = &pixels[3*rendersize*rendersize];
- glReadPixels(0, 0, rendersize, rendersize, GL_RGB, GL_UNSIGNED_BYTE, src);
- if(rendersize > texsize)
- {
- scaletexture(src, rendersize, rendersize, 3, 3*rendersize, dst, texsize, texsize);
- swap(src, dst);
- }
- if(blur > 0)
- {
- blurtexture(blur, 3, texsize, texsize, dst, src);
- swap(src, dst);
- }
- createtexture(tex, texsize, texsize, src, 3, 2, GL_RGB5, side.target);
- }
- glFrontFace(GL_CW);
- delete[] pixels;
- glViewport(0, 0, screenw, screenh);
- clientkeepalive();
- forcecubemapload(tex);
- return tex;
-}
-
-void initenvmaps()
-{
- clearenvmaps();
- skyenvmap = NULL;
- if(shouldrenderskyenvmap()) envmaps.add().size = 1;
- else if(skybox[0]) skyenvmap = cubemapload(skybox, true, false, true);
- const vector<extentity *> &ents = entities::getents();
- loopv(ents)
- {
- const extentity &ent = *ents[i];
- if(ent.type != ET_ENVMAP) continue;
- envmap &em = envmaps.add();
- em.radius = ent.attr1 ? clamp(int(ent.attr1), 0, 10000) : envmapradius;
- em.size = ent.attr2 ? clamp(int(ent.attr2), 4, 9) : 0;
- em.blur = ent.attr3 ? clamp(int(ent.attr3), 1, 2) : 0;
- em.o = ent.o;
- }
-}
-
-void genenvmaps()
-{
- if(envmaps.empty()) return;
- renderprogress(0, "generating environment maps...");
- int lastprogress = SDL_GetTicks();
- loopv(envmaps)
- {
- envmap &em = envmaps[i];
- em.tex = genenvmap(em.o, em.size ? min(em.size, envmapsize) : envmapsize, em.blur, em.radius < 0);
- if(renderedframe) continue;
- int millis = SDL_GetTicks();
- if(millis - lastprogress >= 250)
- {
- renderprogress(float(i+1)/envmaps.length(), "generating environment maps...", 0, true);
- lastprogress = millis;
- }
- }
-}
-
-ushort closestenvmap(const vec &o)
-{
- ushort minemid = EMID_SKY;
- float mindist = 1e16f;
- loopv(envmaps)
- {
- envmap &em = envmaps[i];
- float dist;
- if(envmapbb)
- {
- if(!o.insidebb(vec(em.o).sub(em.radius), vec(em.o).add(em.radius))) continue;
- dist = em.o.dist(o);
- }
- else
- {
- dist = em.o.dist(o);
- if(dist > em.radius) continue;
- }
- if(dist < mindist)
- {
- minemid = EMID_RESERVED + i;
- mindist = dist;
- }
- }
- return minemid;
-}
-
-ushort closestenvmap(int orient, const ivec &co, int size)
-{
- vec loc(co);
- int dim = dimension(orient);
- if(dimcoord(orient)) loc[dim] += size;
- loc[R[dim]] += size/2;
- loc[C[dim]] += size/2;
- return closestenvmap(loc);
-}
-
-static inline GLuint lookupskyenvmap()
-{
- return envmaps.length() && envmaps[0].radius < 0 ? envmaps[0].tex : (skyenvmap ? skyenvmap->id : 0);
-}
-
-GLuint lookupenvmap(Slot &slot)
-{
- loopv(slot.sts) if(slot.sts[i].type==TEX_ENVMAP && slot.sts[i].t) return slot.sts[i].t->id;
- return lookupskyenvmap();
-}
-
-GLuint lookupenvmap(ushort emid)
-{
- if(emid==EMID_SKY || emid==EMID_CUSTOM) return skyenvmap ? skyenvmap->id : 0;
- if(emid==EMID_NONE || !envmaps.inrange(emid-EMID_RESERVED)) return 0;
- GLuint tex = envmaps[emid-EMID_RESERVED].tex;
- return tex ? tex : lookupskyenvmap();
-}
-
void cleanuptexture(Texture *t)
{
DELETEA(t->alphamask);
void cleanuptextures()
{
- clearenvmaps();
loopv(slots) slots[i]->cleanup();
loopv(vslots) vslots[i]->cleanup();
loopi((MATF_VOLUME|MATF_INDEX)+1) materialslots[i].cleanup();
extern const texrotation texrotations[8];
extern const cubemapside cubemapsides[6];
extern Texture *notexture;
-extern Shader *nullshader, *hudshader, *hudnotextureshader, *textureshader, *notextureshader, *nocolorshader, *foggedshader, *foggednotextureshader, *stdworldshader;
+extern Shader *nullshader, *hudshader, *hudnotextureshader, *textureshader, *notextureshader, *nocolorshader, *stdworldshader;
extern int reservevpparams, maxvsuniforms, maxfsuniforms;
extern Shader *lookupshaderbyname(const char *name);
+++ /dev/null
-#include "engine.h"
-
-VARFP(waterreflect, 0, 1, 1, { cleanreflections(); preloadwatershaders(); });
-VARFP(waterrefract, 0, 1, 1, { cleanreflections(); preloadwatershaders(); });
-VARFP(waterenvmap, 0, 1, 1, { cleanreflections(); preloadwatershaders(); });
-VARFP(waterfallrefract, 0, 0, 1, { cleanreflections(); preloadwatershaders(); });
-
-/* vertex water */
-VARP(watersubdiv, 0, 2, 3);
-VARP(waterlod, 0, 1, 3);
-
-static int wx1, wy1, wx2, wy2, wz, wsize, wsubdiv;
-static float whoffset, whphase;
-
-static inline float vertwangle(int v1, int v2)
-{
- static const float whscale = 59.0f/23.0f/(2*M_PI);
- v1 &= wsize-1;
- v2 &= wsize-1;
- return v1*v2*whscale+whoffset;
-}
-
-static inline float vertwphase(float angle)
-{
- float s = angle - int(angle) - 0.5f;
- s *= 8 - fabs(s)*16;
- return WATER_AMPLITUDE*s-WATER_OFFSET;
-}
-
-static inline void vertw(int v1, int v2, int v3)
-{
- float h = vertwphase(vertwangle(v1, v2));
- gle::attribf(v1, v2, v3+h);
-}
-
-static inline void vertwq(float v1, float v2, float v3)
-{
- gle::attribf(v1, v2, v3+whphase);
-}
-
-static inline void vertwn(float v1, float v2, float v3)
-{
- float h = -WATER_OFFSET;
- gle::attribf(v1, v2, v3+h);
-}
-
-struct waterstrip
-{
- int x1, y1, x2, y2, z;
- ushort size, subdiv;
-
- int numverts() const { return 2*((y2-y1)/subdiv + 1)*((x2-x1)/subdiv); }
-
- void save()
- {
- x1 = wx1;
- y1 = wy1;
- x2 = wx2;
- y2 = wy2;
- z = wz;
- size = wsize;
- subdiv = wsubdiv;
- }
-
- void restore()
- {
- wx1 = x1;
- wy1 = y1;
- wx2 = x2;
- wy2 = y2;
- wz = z;
- wsize = size;
- wsubdiv = subdiv;
- }
-};
-vector<waterstrip> waterstrips;
-
-void flushwaterstrips()
-{
- if(gle::attribbuf.length()) xtraverts += gle::end();
- gle::defvertex();
- int numverts = 0;
- loopv(waterstrips) numverts += waterstrips[i].numverts();
- gle::begin(GL_TRIANGLE_STRIP, numverts);
- loopv(waterstrips)
- {
- waterstrips[i].restore();
- for(int x = wx1; x < wx2; x += wsubdiv)
- {
- for(int y = wy1; y <= wy2; y += wsubdiv)
- {
- vertw(x, y, wz);
- vertw(x+wsubdiv, y, wz);
- }
- x += wsubdiv;
- if(x >= wx2) break;
- for(int y = wy2; y >= wy1; y -= wsubdiv)
- {
- vertw(x, y, wz);
- vertw(x+wsubdiv, y, wz);
- }
- }
- gle::multidraw();
- }
- waterstrips.setsize(0);
- wsize = 0;
- xtraverts += gle::end();
-}
-
-void flushwater(int mat = MAT_WATER, bool force = true)
-{
- if(wsize)
- {
- if(wsubdiv >= wsize)
- {
- if(gle::attribbuf.empty()) { gle::defvertex(); gle::begin(GL_QUADS); }
- vertwq(wx1, wy1, wz);
- vertwq(wx2, wy1, wz);
- vertwq(wx2, wy2, wz);
- vertwq(wx1, wy2, wz);
- }
- else waterstrips.add().save();
- wsize = 0;
- }
-
- if(force)
- {
- if(gle::attribbuf.length()) xtraverts += gle::end();
- if(waterstrips.length()) flushwaterstrips();
- }
-}
-
-void rendervertwater(int subdiv, int xo, int yo, int z, int size, int mat)
-{
- if(wsize == size && wsubdiv == subdiv && wz == z)
- {
- if(wx2 == xo)
- {
- if(wy1 == yo && wy2 == yo + size) { wx2 += size; return; }
- }
- else if(wy2 == yo && wx1 == xo && wx2 == xo + size) { wy2 += size; return; }
- }
-
- flushwater(mat, false);
-
- wx1 = xo;
- wy1 = yo;
- wx2 = xo + size,
- wy2 = yo + size;
- wz = z;
- wsize = size;
- wsubdiv = subdiv;
-
- ASSERT((wx1 & (subdiv - 1)) == 0);
- ASSERT((wy1 & (subdiv - 1)) == 0);
-}
-
-int calcwatersubdiv(int x, int y, int z, int size)
-{
- float dist;
- if(camera1->o.x >= x && camera1->o.x < x + size &&
- camera1->o.y >= y && camera1->o.y < y + size)
- dist = fabs(camera1->o.z - float(z));
- else
- dist = vec(x + size/2, y + size/2, z + size/2).dist(camera1->o) - size*1.42f/2;
- int subdiv = watersubdiv + int(dist) / (32 << waterlod);
- return subdiv >= 31 ? INT_MAX : 1<<subdiv;
-}
-
-int renderwaterlod(int x, int y, int z, int size, int mat)
-{
- if(size <= (32 << waterlod))
- {
- int subdiv = calcwatersubdiv(x, y, z, size);
- if(subdiv < size * 2) rendervertwater(min(subdiv, size), x, y, z, size, mat);
- return subdiv;
- }
- else
- {
- int subdiv = calcwatersubdiv(x, y, z, size);
- if(subdiv >= size)
- {
- if(subdiv < size * 2) rendervertwater(size, x, y, z, size, mat);
- return subdiv;
- }
- int childsize = size / 2,
- subdiv1 = renderwaterlod(x, y, z, childsize, mat),
- subdiv2 = renderwaterlod(x + childsize, y, z, childsize, mat),
- subdiv3 = renderwaterlod(x + childsize, y + childsize, z, childsize, mat),
- subdiv4 = renderwaterlod(x, y + childsize, z, childsize, mat),
- minsubdiv = subdiv1;
- minsubdiv = min(minsubdiv, subdiv2);
- minsubdiv = min(minsubdiv, subdiv3);
- minsubdiv = min(minsubdiv, subdiv4);
- if(minsubdiv < size * 2)
- {
- if(minsubdiv >= size) rendervertwater(size, x, y, z, size, mat);
- else
- {
- if(subdiv1 >= size) rendervertwater(childsize, x, y, z, childsize, mat);
- if(subdiv2 >= size) rendervertwater(childsize, x + childsize, y, z, childsize, mat);
- if(subdiv3 >= size) rendervertwater(childsize, x + childsize, y + childsize, z, childsize, mat);
- if(subdiv4 >= size) rendervertwater(childsize, x, y + childsize, z, childsize, mat);
- }
- }
- return minsubdiv;
- }
-}
-
-void renderflatwater(int x, int y, int z, int rsize, int csize, int mat)
-{
- if(gle::attribbuf.empty()) { gle::defvertex(); gle::begin(GL_QUADS); }
- vertwn(x, y, z);
- vertwn(x+rsize, y, z);
- vertwn(x+rsize, y+csize, z);
- vertwn(x, y+csize, z);
-}
-
-VARFP(vertwater, 0, 1, 1, allchanged());
-
-static inline void renderwater(const materialsurface &m, int mat = MAT_WATER)
-{
- if(!vertwater || drawtex == DRAWTEX_MINIMAP) renderflatwater(m.o.x, m.o.y, m.o.z, m.rsize, m.csize, mat);
- else if(renderwaterlod(m.o.x, m.o.y, m.o.z, m.csize, mat) >= int(m.csize) * 2)
- rendervertwater(m.csize, m.o.x, m.o.y, m.o.z, m.csize, mat);
-}
-
-void setuplava(Texture *tex, float scale)
-{
- float xk = TEX_SCALE/(tex->xs*scale);
- float yk = TEX_SCALE/(tex->ys*scale);
- float scroll = lastmillis/1000.0f;
- LOCALPARAMF(lavatexgen, xk, yk, scroll, scroll);
- gle::normal(vec(0, 0, 1));
- whoffset = fmod(float(lastmillis/2000.0f/(2*M_PI)), 1.0f);
- whphase = vertwphase(whoffset);
-}
-
-void renderlava(const materialsurface &m)
-{
- renderwater(m, MAT_LAVA);
-}
-
-void flushlava()
-{
- flushwater(MAT_LAVA);
-}
-
-/* reflective/refractive water */
-
-#define MAXREFLECTIONS 16
-
-struct Reflection
-{
- GLuint tex, refracttex;
- int material, height, depth, age;
- bool init;
- matrix4 projmat;
- occludequery *query, *prevquery;
- vector<materialsurface *> matsurfs;
-
- Reflection() : tex(0), refracttex(0), material(-1), height(-1), depth(0), age(0), init(false), query(NULL), prevquery(NULL)
- {}
-};
-
-VARP(reflectdist, 0, 2000, 10000);
-
-#define WATERVARS(name) \
- bvec name##color(0x14, 0x46, 0x50), name##fallcolor(0, 0, 0); \
- HVARFR(name##colour, 0, 0x144650, 0xFFFFFF, \
- { \
- if(!name##colour) name##colour = 0x144650; \
- name##color = bvec((name##colour>>16)&0xFF, (name##colour>>8)&0xFF, name##colour&0xFF); \
- }); \
- VARR(name##fog, 0, 150, 10000); \
- VARR(name##spec, 0, 150, 1000); \
- HVARFR(name##fallcolour, 0, 0, 0xFFFFFF, \
- { \
- name##fallcolor = bvec((name##fallcolour>>16)&0xFF, (name##fallcolour>>8)&0xFF, name##fallcolour&0xFF); \
- });
-
-WATERVARS(water)
-WATERVARS(water2)
-WATERVARS(water3)
-WATERVARS(water4)
-
-GETMATIDXVAR(water, colour, int)
-GETMATIDXVAR(water, color, const bvec &)
-GETMATIDXVAR(water, fallcolour, int)
-GETMATIDXVAR(water, fallcolor, const bvec &)
-GETMATIDXVAR(water, fog, int)
-GETMATIDXVAR(water, spec, int)
-
-#define LAVAVARS(name) \
- bvec name##color(0xFF, 0x40, 0x00); \
- HVARFR(name##colour, 0, 0xFF4000, 0xFFFFFF, \
- { \
- if(!name##colour) name##colour = 0xFF4000; \
- name##color = bvec((name##colour>>16)&0xFF, (name##colour>>8)&0xFF, name##colour&0xFF); \
- }); \
- VARR(name##fog, 0, 50, 10000);
-
-LAVAVARS(lava)
-LAVAVARS(lava2)
-LAVAVARS(lava3)
-LAVAVARS(lava4)
-
-GETMATIDXVAR(lava, colour, int)
-GETMATIDXVAR(lava, color, const bvec &)
-GETMATIDXVAR(lava, fog, int)
-
-void setprojtexmatrix(Reflection &ref)
-{
- if(ref.init)
- {
- ref.init = false;
- (ref.projmat = camprojmatrix).projective();
- }
-
- LOCALPARAM(watermatrix, ref.projmat);
-}
-
-Reflection reflections[MAXREFLECTIONS];
-Reflection waterfallrefraction;
-GLuint reflectionfb = 0, reflectiondb = 0;
-
-GLuint getwaterfalltex() { return waterfallrefraction.refracttex ? waterfallrefraction.refracttex : notexture->id; }
-
-VAR(oqwater, 0, 2, 2);
-VARFP(waterfade, 0, 1, 1, { cleanreflections(); preloadwatershaders(); });
-
-void preloadwatershaders(bool force)
-{
- static bool needwater = false;
- if(force) needwater = true;
- if(!needwater) return;
-
- useshaderbyname("waterglare");
-
- if(waterenvmap && !waterreflect)
- useshaderbyname(waterrefract ? (waterfade ? "waterenvfade" : "waterenvrefract") : "waterenv");
- else useshaderbyname(waterrefract ? (waterfade ? "waterfade" : "waterrefract") : (waterreflect ? "waterreflect" : "water"));
-
- useshaderbyname(waterrefract ? (waterfade ? "underwaterfade" : "underwaterrefract") : "underwater");
-
- extern int waterfallenv;
- useshaderbyname(waterfallenv ? "waterfallenv" : "waterfall");
- if(waterfallrefract) useshaderbyname(waterfallenv ? "waterfallenvrefract" : "waterfallrefract");
-}
-
-void renderwater()
-{
- if(editmode && showmat && !drawtex) return;
- if(!rplanes) return;
-
- glDisable(GL_CULL_FACE);
-
- if(!glaring && drawtex != DRAWTEX_MINIMAP)
- {
- if(waterrefract)
- {
- if(waterfade)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- }
- else
- {
- glDepthMask(GL_FALSE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_SRC_ALPHA);
- }
- }
-
- GLOBALPARAM(camera, camera1->o);
- GLOBALPARAMF(millis, lastmillis/1000.0f);
-
- #define SETWATERSHADER(which, name) \
- do { \
- static Shader *name##shader = NULL; \
- if(!name##shader) name##shader = lookupshaderbyname(#name); \
- which##shader = name##shader; \
- } while(0)
-
- Shader *aboveshader = NULL;
- if(glaring) SETWATERSHADER(above, waterglare);
- else if(drawtex == DRAWTEX_MINIMAP) aboveshader = notextureshader;
- else if(waterenvmap && !waterreflect)
- {
- if(waterrefract)
- {
- if(waterfade) SETWATERSHADER(above, waterenvfade);
- else SETWATERSHADER(above, waterenvrefract);
- }
- else SETWATERSHADER(above, waterenv);
- }
- else if(waterrefract)
- {
- if(waterfade) SETWATERSHADER(above, waterfade);
- else SETWATERSHADER(above, waterrefract);
- }
- else if(waterreflect) SETWATERSHADER(above, waterreflect);
- else SETWATERSHADER(above, water);
-
- Shader *belowshader = NULL;
- if(!glaring && drawtex != DRAWTEX_MINIMAP)
- {
- if(waterrefract)
- {
- if(waterfade) SETWATERSHADER(below, underwaterfade);
- else SETWATERSHADER(below, underwaterrefract);
- }
- else SETWATERSHADER(below, underwater);
- }
-
- vec ambient(max(skylightcolor[0], ambientcolor[0]), max(skylightcolor[1], ambientcolor[1]), max(skylightcolor[2], ambientcolor[2]));
- float offset = -WATER_OFFSET;
- loopi(MAXREFLECTIONS)
- {
- Reflection &ref = reflections[i];
- if(ref.height<0 || ref.age || ref.matsurfs.empty()) continue;
- if(!glaring && oqfrags && oqwater && ref.query && ref.query->owner==&ref)
- {
- if(!ref.prevquery || ref.prevquery->owner!=&ref || checkquery(ref.prevquery))
- {
- if(checkquery(ref.query)) continue;
- }
- }
-
- bool below = camera1->o.z < ref.height+offset;
- if(below)
- {
- if(!belowshader) continue;
- belowshader->set();
- }
- else aboveshader->set();
-
- if(!glaring && drawtex != DRAWTEX_MINIMAP)
- {
- if(waterreflect || waterrefract)
- {
- if(waterreflect || !waterenvmap) glBindTexture(GL_TEXTURE_2D, waterreflect ? ref.tex : ref.refracttex);
- setprojtexmatrix(ref);
- }
-
- if(waterrefract)
- {
- glActiveTexture_(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, ref.refracttex);
- if(waterfade)
- {
- float fadeheight = ref.height+offset+(below ? -2 : 2);
- LOCALPARAMF(waterheight, fadeheight);
- }
- }
- }
-
- MSlot &mslot = lookupmaterialslot(ref.material);
- glActiveTexture_(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, mslot.sts.inrange(2) ? mslot.sts[2].t->id : notexture->id);
- glActiveTexture_(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, mslot.sts.inrange(3) ? mslot.sts[3].t->id : notexture->id);
- glActiveTexture_(GL_TEXTURE0);
- if(!glaring && waterenvmap && !waterreflect && drawtex != DRAWTEX_MINIMAP)
- {
- glBindTexture(GL_TEXTURE_CUBE_MAP, lookupenvmap(mslot));
- }
-
- whoffset = fmod(float(lastmillis/600.0f/(2*M_PI)), 1.0f);
- whphase = vertwphase(whoffset);
-
- gle::color(getwatercolor(ref.material));
- int wfog = getwaterfog(ref.material), wspec = getwaterspec(ref.material);
-
- const entity *lastlight = (const entity *)-1;
- int lastdepth = -1;
- loopvj(ref.matsurfs)
- {
- materialsurface &m = *ref.matsurfs[j];
-
- entity *light = (m.light && m.light->type==ET_LIGHT ? m.light : NULL);
- if(light!=lastlight)
- {
- flushwater();
- vec lightpos = light ? light->o : vec(worldsize/2, worldsize/2, worldsize);
- float lightrad = light && light->attr1 ? light->attr1 : worldsize*8.0f;
- vec lightcol = (light ? vec(light->attr2, light->attr3, light->attr4) : vec(ambient)).div(255.0f).mul(wspec/100.0f);
- LOCALPARAM(lightpos, lightpos);
- LOCALPARAM(lightcolor, lightcol);
- LOCALPARAMF(lightradius, lightrad);
- lastlight = light;
- }
-
- if(!glaring && !waterrefract && m.depth!=lastdepth)
- {
- flushwater();
- float depth = !wfog ? 1.0f : min(0.75f*m.depth/wfog, 0.95f);
- depth = max(depth, !below && (waterreflect || waterenvmap) ? 0.3f : 0.6f);
- LOCALPARAMF(depth, depth, 1.0f-depth);
- lastdepth = m.depth;
- }
-
- renderwater(m);
- }
- flushwater();
- }
-
- if(!glaring && drawtex != DRAWTEX_MINIMAP)
- {
- if(waterrefract)
- {
- if(waterfade) glDisable(GL_BLEND);
- }
- else
- {
- glDepthMask(GL_TRUE);
- glDisable(GL_BLEND);
- }
- }
-
- glEnable(GL_CULL_FACE);
-}
-
-void setupwaterfallrefract()
-{
- glBindTexture(GL_TEXTURE_2D, waterfallrefraction.refracttex ? waterfallrefraction.refracttex : notexture->id);
- setprojtexmatrix(waterfallrefraction);
-}
-
-void cleanreflection(Reflection &ref)
-{
- ref.material = -1;
- ref.height = -1;
- ref.init = false;
- ref.query = ref.prevquery = NULL;
- ref.matsurfs.setsize(0);
- if(ref.tex)
- {
- glDeleteTextures(1, &ref.tex);
- ref.tex = 0;
- }
- if(ref.refracttex)
- {
- glDeleteTextures(1, &ref.refracttex);
- ref.refracttex = 0;
- }
-}
-
-void cleanreflections()
-{
- loopi(MAXREFLECTIONS) cleanreflection(reflections[i]);
- cleanreflection(waterfallrefraction);
- if(reflectionfb)
- {
- glDeleteFramebuffers_(1, &reflectionfb);
- reflectionfb = 0;
- }
- if(reflectiondb)
- {
- glDeleteRenderbuffers_(1, &reflectiondb);
- reflectiondb = 0;
- }
-}
-
-VARFP(reflectsize, 6, 8, 11, cleanreflections());
-
-void genwatertex(GLuint &tex, GLuint &fb, GLuint &db, bool refract = false)
-{
- static const GLenum colorfmts[] = { GL_RGBA, GL_RGBA8, GL_RGB, GL_RGB8, GL_FALSE },
- depthfmts[] = { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_FALSE };
- static GLenum reflectfmt = GL_FALSE, refractfmt = GL_FALSE, depthfmt = GL_FALSE;
- static bool usingalpha = false;
- bool needsalpha = refract && waterrefract && waterfade;
- if(refract && usingalpha!=needsalpha)
- {
- usingalpha = needsalpha;
- refractfmt = GL_FALSE;
- }
- int size = 1<<reflectsize;
- while(size>hwtexsize) size /= 2;
-
- glGenTextures(1, &tex);
- char *buf = new char[size*size*4];
- memset(buf, 0, size*size*4);
-
- GLenum &colorfmt = refract ? refractfmt : reflectfmt;
- if(colorfmt && fb && db)
- {
- createtexture(tex, size, size, buf, 3, 1, colorfmt);
- delete[] buf;
- return;
- }
-
- if(!fb) glGenFramebuffers_(1, &fb);
- int find = needsalpha ? 0 : 2;
- do
- {
- createtexture(tex, size, size, buf, 3, 1, colorfmt ? colorfmt : colorfmts[find]);
- glBindFramebuffer_(GL_FRAMEBUFFER, fb);
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
- if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break;
- }
- while(!colorfmt && colorfmts[++find]);
- if(!colorfmt) colorfmt = colorfmts[find];
-
- delete[] buf;
-
- if(!db) { glGenRenderbuffers_(1, &db); depthfmt = GL_FALSE; }
- if(!depthfmt) glBindRenderbuffer_(GL_RENDERBUFFER, db);
- find = 0;
- do
- {
- if(!depthfmt) glRenderbufferStorage_(GL_RENDERBUFFER, depthfmts[find], size, size);
- glFramebufferRenderbuffer_(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, db);
- if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break;
- }
- while(!depthfmt && depthfmts[++find]);
- if(!depthfmt)
- {
- glBindRenderbuffer_(GL_RENDERBUFFER, 0);
- depthfmt = depthfmts[find];
- }
-
- glBindFramebuffer_(GL_FRAMEBUFFER, 0);
-}
-
-void addwaterfallrefraction(materialsurface &m)
-{
- Reflection &ref = waterfallrefraction;
- if(ref.age>=0)
- {
- ref.age = -1;
- ref.init = false;
- ref.matsurfs.setsize(0);
- ref.material = MAT_WATER;
- ref.height = INT_MAX;
- }
- ref.matsurfs.add(&m);
-
- if(!ref.refracttex) genwatertex(ref.refracttex, reflectionfb, reflectiondb);
-}
-
-void addreflection(materialsurface &m)
-{
- int mat = m.material, height = m.o.z;
- Reflection *ref = NULL, *oldest = NULL;
- loopi(MAXREFLECTIONS)
- {
- Reflection &r = reflections[i];
- if(r.height<0)
- {
- if(!ref) ref = &r;
- }
- else if(r.height==height && r.material==mat)
- {
- r.matsurfs.add(&m);
- r.depth = max(r.depth, int(m.depth));
- if(r.age<0) return;
- ref = &r;
- break;
- }
- else if(!oldest || r.age>oldest->age) oldest = &r;
- }
- if(!ref)
- {
- if(!oldest || oldest->age<0) return;
- ref = oldest;
- }
- if(ref->height!=height || ref->material!=mat)
- {
- ref->material = mat;
- ref->height = height;
- ref->prevquery = NULL;
- }
- rplanes++;
- ref->age = -1;
- ref->init = false;
- ref->matsurfs.setsize(0);
- ref->matsurfs.add(&m);
- ref->depth = m.depth;
- if(drawtex == DRAWTEX_MINIMAP) return;
-
- if(waterreflect && !ref->tex) genwatertex(ref->tex, reflectionfb, reflectiondb);
- if(waterrefract && !ref->refracttex) genwatertex(ref->refracttex, reflectionfb, reflectiondb, true);
-}
-
-static void drawmaterialquery(const materialsurface &m, float offset, float border = 0, float reflect = -1)
-{
- if(gle::attribbuf.empty())
- {
- gle::defvertex();
- gle::begin(GL_QUADS);
- }
- float x = m.o.x, y = m.o.y, z = m.o.z, csize = m.csize + border, rsize = m.rsize + border;
- if(reflect >= 0) z = 2*reflect - z;
- switch(m.orient)
- {
-#define GENFACEORIENT(orient, v0, v1, v2, v3) \
- case orient: v0 v1 v2 v3 break;
-#define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) \
- gle::attribf(mx sx, my sy, mz sz);
- GENFACEVERTS(x, x, y, y, z, z, - border, + csize, - border, + rsize, + offset, - offset)
-#undef GENFACEORIENT
-#undef GENFACEVERT
- }
-}
-
-extern void drawreflection(float z, bool refract, int fogdepth = -1, const bvec &col = bvec(0, 0, 0));
-
-int rplanes = 0;
-
-void queryreflection(Reflection &ref, bool init)
-{
- if(init)
- {
- nocolorshader->set();
- glDepthMask(GL_FALSE);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glDisable(GL_CULL_FACE);
- }
- startquery(ref.query);
- loopvj(ref.matsurfs)
- {
- materialsurface &m = *ref.matsurfs[j];
- float offset = 0.1f;
- if(m.orient==O_TOP)
- {
- offset = WATER_OFFSET +
- (vertwater ? WATER_AMPLITUDE*(camera1->pitch > 0 || m.depth < WATER_AMPLITUDE+0.5f ? -1 : 1) : 0);
- if(fabs(m.o.z-offset - camera1->o.z) < 0.5f && m.depth > WATER_AMPLITUDE+1.5f)
- offset += camera1->pitch > 0 ? -1 : 1;
- }
- drawmaterialquery(m, offset);
- }
- xtraverts += gle::end();
- endquery(ref.query);
-}
-
-void queryreflections()
-{
- rplanes = 0;
-
- static int lastsize = 0;
- int size = 1<<reflectsize;
- while(size>hwtexsize) size /= 2;
- if(size!=lastsize) { if(lastsize) cleanreflections(); lastsize = size; }
-
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(!va->matsurfs || va->occluded >= OCCLUDE_BB || va->curvfc >= VFC_FOGGED) continue;
- int lastmat = -1;
- loopi(va->matsurfs)
- {
- materialsurface &m = va->matbuf[i];
- if(m.material != lastmat)
- {
- if((m.material&MATF_VOLUME) != MAT_WATER || m.orient == O_BOTTOM) { i += m.skip; continue; }
- if(m.orient != O_TOP)
- {
- if(!waterfallrefract || !getwaterfog(m.material)) { i += m.skip; continue; }
- }
- lastmat = m.material;
- }
- if(m.orient==O_TOP) addreflection(m);
- else addwaterfallrefraction(m);
- }
- }
-
- loopi(MAXREFLECTIONS)
- {
- Reflection &ref = reflections[i];
- ++ref.age;
- }
- if(waterfallrefract)
- {
- Reflection &ref = waterfallrefraction;
- ++ref.age;
- }
-
- if((editmode && showmat && !drawtex) || !oqfrags || !oqwater || drawtex == DRAWTEX_MINIMAP) return;
-
- int refs = 0;
- if(waterreflect || waterrefract) loopi(MAXREFLECTIONS)
- {
- Reflection &ref = reflections[i];
- ref.prevquery = oqwater > 1 ? ref.query : NULL;
- ref.query = ref.height>=0 && !ref.age && ref.matsurfs.length() ? newquery(&ref) : NULL;
- if(ref.query) queryreflection(ref, !refs++);
- }
- if(waterfallrefract)
- {
- Reflection &ref = waterfallrefraction;
- ref.prevquery = oqwater > 1 ? ref.query : NULL;
- ref.query = ref.height>=0 && !ref.age && ref.matsurfs.length() ? newquery(&ref) : NULL;
- if(ref.query) queryreflection(ref, !refs++);
- }
-
- if(refs)
- {
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_CULL_FACE);
- }
-
- glFlush();
-}
-
-VARP(maxreflect, 1, 2, 8);
-
-int refracting = 0, refractfog = 0;
-bvec refractcolor(0, 0, 0);
-bool reflecting = false, fading = false, fogging = false;
-float reflectz = 1e16f;
-
-VAR(maskreflect, 0, 2, 16);
-
-void maskreflection(Reflection &ref, float offset, bool reflect, bool clear = false)
-{
- const bvec &wcol = getwatercolor(ref.material);
- vec color = wcol.tocolor();
- if(!maskreflect)
- {
- if(clear) glClearColor(color.r, color.g, color.b, 1);
- glClear(GL_DEPTH_BUFFER_BIT | (clear ? GL_COLOR_BUFFER_BIT : 0));
- return;
- }
- glClearDepth(0);
- glClear(GL_DEPTH_BUFFER_BIT);
- glClearDepth(1);
- glDepthRange(1, 1);
- glDepthFunc(GL_ALWAYS);
- glDisable(GL_CULL_FACE);
- if(clear)
- {
- notextureshader->set();
- gle::color(color);
- }
- else
- {
- nocolorshader->set();
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- }
- float reflectheight = reflect ? ref.height + offset : -1;
- loopv(ref.matsurfs)
- {
- materialsurface &m = *ref.matsurfs[i];
- drawmaterialquery(m, -offset, maskreflect, reflectheight);
- }
- xtraverts += gle::end();
- if(!clear) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_CULL_FACE);
- glDepthFunc(GL_LESS);
- glDepthRange(0, 1);
-}
-
-VAR(reflectscissor, 0, 1, 1);
-VAR(reflectvfc, 0, 1, 1);
-
-static bool calcscissorbox(Reflection &ref, int size, vec &clipmin, vec &clipmax, int &sx, int &sy, int &sw, int &sh)
-{
- materialsurface &m0 = *ref.matsurfs[0];
- int dim = dimension(m0.orient), r = R[dim], c = C[dim];
- ivec bbmin = m0.o, bbmax = bbmin;
- bbmax[r] += m0.rsize;
- bbmax[c] += m0.csize;
- loopvj(ref.matsurfs)
- {
- materialsurface &m = *ref.matsurfs[j];
- bbmin[r] = min(bbmin[r], m.o[r]);
- bbmin[c] = min(bbmin[c], m.o[c]);
- bbmax[r] = max(bbmax[r], m.o[r] + m.rsize);
- bbmax[c] = max(bbmax[c], m.o[c] + m.csize);
- bbmin[dim] = min(bbmin[dim], m.o[dim]);
- bbmax[dim] = max(bbmax[dim], m.o[dim]);
- }
-
- vec4 v[8];
- float sx1 = 1, sy1 = 1, sx2 = -1, sy2 = -1;
- loopi(8)
- {
- vec4 &p = v[i];
- camprojmatrix.transform(vec(i&1 ? bbmax.x : bbmin.x, i&2 ? bbmax.y : bbmin.y, (i&4 ? bbmax.z + WATER_AMPLITUDE : bbmin.z - WATER_AMPLITUDE) - WATER_OFFSET), p);
- if(p.z >= -p.w)
- {
- float x = p.x / p.w, y = p.y / p.w;
- sx1 = min(sx1, x);
- sy1 = min(sy1, y);
- sx2 = max(sx2, x);
- sy2 = max(sy2, y);
- }
- }
- if(sx1 >= sx2 || sy1 >= sy2) return false;
- loopi(8)
- {
- const vec4 &p = v[i];
- if(p.z >= -p.w) continue;
- loopj(3)
- {
- const vec4 &o = v[i^(1<<j)];
- if(o.z <= -o.w) continue;
- float t = (p.z + p.w)/(p.z + p.w - o.z - o.w),
- w = p.w + t*(o.w - p.w),
- x = (p.x + t*(o.x - p.x))/w,
- y = (p.y + t*(o.y - p.y))/w;
- sx1 = min(sx1, x);
- sy1 = min(sy1, y);
- sx2 = max(sx2, x);
- sy2 = max(sy2, y);
- }
- }
- if(sx1 <= -1 && sy1 <= -1 && sx2 >= 1 && sy2 >= 1) return false;
- sx1 = max(sx1, -1.0f);
- sy1 = max(sy1, -1.0f);
- sx2 = min(sx2, 1.0f);
- sy2 = min(sy2, 1.0f);
- if(reflectvfc)
- {
- clipmin.x = clamp(clipmin.x, sx1, sx2);
- clipmin.y = clamp(clipmin.y, sy1, sy2);
- clipmax.x = clamp(clipmax.x, sx1, sx2);
- clipmax.y = clamp(clipmax.y, sy1, sy2);
- }
- sx = int(floor((sx1+1)*0.5f*size));
- sy = int(floor((sy1+1)*0.5f*size));
- sw = max(int(ceil((sx2+1)*0.5f*size)) - sx, 0);
- sh = max(int(ceil((sy2+1)*0.5f*size)) - sy, 0);
- return true;
-}
-
-VARR(refractclear, 0, 0, 1);
-
-void drawreflections()
-{
- if((editmode && showmat && !drawtex) || drawtex == DRAWTEX_MINIMAP) return;
-
- static int lastdrawn = 0;
- int refs = 0, n = lastdrawn;
- float offset = -WATER_OFFSET;
- int size = 1<<reflectsize;
- while(size>hwtexsize) size /= 2;
-
- if(waterreflect || waterrefract) loopi(MAXREFLECTIONS)
- {
- Reflection &ref = reflections[++n%MAXREFLECTIONS];
- if(ref.height<0 || ref.age || ref.matsurfs.empty()) continue;
- if(oqfrags && oqwater && ref.query && ref.query->owner==&ref)
- {
- if(!ref.prevquery || ref.prevquery->owner!=&ref || checkquery(ref.prevquery))
- {
- if(checkquery(ref.query)) continue;
- }
- }
-
- if(!refs)
- {
- glViewport(0, 0, size, size);
- glBindFramebuffer_(GL_FRAMEBUFFER, reflectionfb);
- }
- refs++;
- ref.init = true;
- lastdrawn = n;
-
- vec clipmin(-1, -1, -1), clipmax(1, 1, 1);
- int sx, sy, sw, sh;
- bool scissor = reflectscissor && calcscissorbox(ref, size, clipmin, clipmax, sx, sy, sw, sh);
- if(scissor) glScissor(sx, sy, sw, sh);
- else
- {
- sx = sy = 0;
- sw = sh = size;
- }
-
- const bvec &wcol = getwatercolor(ref.material);
- int wfog = getwaterfog(ref.material);
-
- if(waterreflect && ref.tex && camera1->o.z >= ref.height+offset)
- {
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ref.tex, 0);
- if(scissor) glEnable(GL_SCISSOR_TEST);
- maskreflection(ref, offset, true);
- savevfcP();
- setvfcP(ref.height+offset, clipmin, clipmax);
- drawreflection(ref.height+offset, false);
- restorevfcP();
- if(scissor) glDisable(GL_SCISSOR_TEST);
- }
-
- if(waterrefract && ref.refracttex)
- {
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ref.refracttex, 0);
- if(scissor) glEnable(GL_SCISSOR_TEST);
- maskreflection(ref, offset, false, refractclear || !wfog || (ref.depth>=10000 && camera1->o.z >= ref.height + offset));
- if(wfog || waterfade)
- {
- savevfcP();
- setvfcP(-1, clipmin, clipmax);
- drawreflection(ref.height+offset, true, wfog, wcol);
- restorevfcP();
- }
- if(scissor) glDisable(GL_SCISSOR_TEST);
- }
-
- if(refs>=maxreflect) break;
- }
-
- if(waterfallrefract && waterfallrefraction.refracttex)
- {
- Reflection &ref = waterfallrefraction;
-
- if(ref.height<0 || ref.age || ref.matsurfs.empty()) goto nowaterfall;
- if(oqfrags && oqwater && ref.query && ref.query->owner==&ref)
- {
- if(!ref.prevquery || ref.prevquery->owner!=&ref || checkquery(ref.prevquery))
- {
- if(checkquery(ref.query)) goto nowaterfall;
- }
- }
-
- if(!refs)
- {
- glViewport(0, 0, size, size);
- glBindFramebuffer_(GL_FRAMEBUFFER, reflectionfb);
- }
- refs++;
- ref.init = true;
-
- vec clipmin(-1, -1, -1), clipmax(1, 1, 1);
- int sx, sy, sw, sh;
- bool scissor = reflectscissor && calcscissorbox(ref, size, clipmin, clipmax, sx, sy, sw, sh);
- if(scissor) glScissor(sx, sy, sw, sh);
- else
- {
- sx = sy = 0;
- sw = sh = size;
- }
-
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ref.refracttex, 0);
- if(scissor) glEnable(GL_SCISSOR_TEST);
- maskreflection(ref, -0.1f, false);
- savevfcP();
- setvfcP(-1, clipmin, clipmax);
- drawreflection(-1, true);
- restorevfcP();
- if(scissor) glDisable(GL_SCISSOR_TEST);
- }
-nowaterfall:
-
- if(!refs) return;
- glViewport(0, 0, screenw, screenh);
- glBindFramebuffer_(GL_FRAMEBUFFER, 0);
-}
-
renderentsphere(e, e.attr2);
break;
- case ET_ENVMAP:
- {
- extern int envmapradius;
- if(color) gle::colorf(0, 1, 1);
- renderentsphere(e, e.attr1 ? max(0, min(10000, int(e.attr1))) : envmapradius);
+ case ET_NOENVMAP:
break;
- }
case ET_MAPMODEL:
case ET_PLAYERSTART:
{
clearoverrides();
clearmapsounds();
- cleanreflections();
resetblendmap();
resetlightmaps();
clearslots();
int lightmaps;
int lightprecision, lighterror, lightlod;
uchar ambient;
- uchar watercolour[3];
uchar blendmap;
uchar lerpangle, lerpsubdiv, lerpsubdivsize;
uchar bumperror;
- uchar skylight[3];
- uchar lavacolour[3];
- uchar waterfallcolour[3];
uchar reserved[10];
char maptitle[128];
};
validmapname(mapname, fname, strpbrk(fname, "/\\") ? NULL : "maps/");
}
-static void fixent(entity &e, int version)
-{
- if(version <= 10 && e.type >= 7) e.type++;
- if(version <= 12 && e.type >= 8) e.type++;
- if(version <= 14 && e.type >= ET_MAPMODEL && e.type <= 16)
- {
- if(e.type == 16) e.type = ET_MAPMODEL;
- else e.type++;
- }
- if(version <= 20 && e.type >= ET_ENVMAP) e.type++;
- if(version <= 21 && e.type >= ET_PARTICLES) e.type++;
- if(version <= 22 && e.type >= ET_SOUND) e.type++;
- if(version <= 23 && e.type >= ET_SPOTLIGHT) e.type++;
- if(version <= 30 && (e.type == ET_MAPMODEL || e.type == ET_PLAYERSTART)) e.attr1 = (int(e.attr1)+180)%360;
- if(version <= 31 && e.type == ET_MAPMODEL) { int yaw = (int(e.attr1)%360 + 360)%360 + 7; e.attr1 = yaw - yaw%15; }
-}
-
bool loadents(const char *fname, vector<entity> &ents, uint *crc)
{
string pakname, mapname, mcfgname, ogzname;
if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; }
compatheader chdr;
- if(hdr.version <= 28)
- {
- if(f->read(&chdr.lightprecision, sizeof(chdr) - 7*sizeof(int)) != sizeof(chdr) - 7*sizeof(int)) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
- }
- else
- {
- int extra = 0;
- if(hdr.version <= 29) extra++;
- if(f->read(&hdr.blendmap, sizeof(hdr) - (7+extra)*sizeof(int)) != sizeof(hdr) - (7+extra)*sizeof(int)) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
+ if(f->read(&hdr.blendmap, sizeof(hdr) - 7*sizeof(int)) != sizeof(hdr) - 7*sizeof(int)) {
+ conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false;
}
- if(hdr.version <= 28)
- {
- lilswap(&chdr.lightprecision, 3);
- hdr.blendmap = chdr.blendmap;
- hdr.numvars = 0;
- hdr.numvslots = 0;
- }
- else
- {
- lilswap(&hdr.blendmap, 2);
- if(hdr.version <= 29) hdr.numvslots = 0;
- else lilswap(&hdr.numvslots, 1);
- }
+ lilswap(&hdr.blendmap, 2);
+ lilswap(&hdr.numvslots, 1);
loopi(hdr.numvars)
{
copystring(gametype, "fps");
bool samegame = true;
int eif = 0;
- if(hdr.version>=16)
{
int len = f->getchar();
f->read(gametype, len+1);
samegame = false;
conoutf(CON_WARN, "WARNING: loading map from %s game, ignoring entities except for lights/mapmodels", gametype);
}
- if(hdr.version>=16)
{
eif = f->getlil<ushort>();
int extrasize = f->getlil<ushort>();
f->seek(extrasize, SEEK_CUR);
}
- if(hdr.version<14)
- {
- f->seek(256, SEEK_CUR);
- }
- else
- {
- ushort nummru = f->getlil<ushort>();
- f->seek(nummru*sizeof(ushort), SEEK_CUR);
- }
+ ushort nummru = f->getlil<ushort>();
+ f->seek(nummru*sizeof(ushort), SEEK_CUR);
loopi(min(hdr.numents, MAXENTS))
{
f->read(&e, sizeof(entity));
lilswap(&e.o.x, 3);
lilswap(&e.attr1, 5);
- fixent(e, hdr.version);
if(eif > 0) f->seek(eif, SEEK_CUR);
- if(samegame)
- {
- entities::readent(e, NULL, hdr.version);
- }
- else if(e.type>=ET_GAMESPECIFIC || hdr.version<=14)
+ if(e.type>=ET_GAMESPECIFIC)
{
ents.pop();
continue;
cube *loadchildren(stream *f, const ivec &co, int size, bool &failed);
-void convertoldsurfaces(cube &c, const ivec &co, int size, surfacecompat *srcsurfs, int hassurfs, normalscompat *normals, int hasnorms, mergecompat *merges, int hasmerges)
-{
- surfaceinfo dstsurfs[6];
- vertinfo verts[6*2*MAXFACEVERTS];
- int totalverts = 0, numsurfs = 6;
- memset(dstsurfs, 0, sizeof(dstsurfs));
- loopi(6) if((hassurfs|hasnorms|hasmerges)&(1<<i))
- {
- surfaceinfo &dst = dstsurfs[i];
- vertinfo *curverts = NULL;
- int numverts = 0;
- surfacecompat *src = NULL, *blend = NULL;
- if(hassurfs&(1<<i))
- {
- src = &srcsurfs[i];
- if(src->layer&2)
- {
- blend = &srcsurfs[numsurfs++];
- dst.lmid[0] = src->lmid;
- dst.lmid[1] = blend->lmid;
- dst.numverts |= LAYER_BLEND;
- if(blend->lmid >= LMID_RESERVED && (src->x != blend->x || src->y != blend->y || src->w != blend->w || src->h != blend->h || memcmp(src->texcoords, blend->texcoords, sizeof(src->texcoords))))
- dst.numverts |= LAYER_DUP;
- }
- else if(src->layer == 1) { dst.lmid[1] = src->lmid; dst.numverts |= LAYER_BOTTOM; }
- else { dst.lmid[0] = src->lmid; dst.numverts |= LAYER_TOP; }
- }
- else dst.numverts |= LAYER_TOP;
- bool uselms = hassurfs&(1<<i) && (dst.lmid[0] >= LMID_RESERVED || dst.lmid[1] >= LMID_RESERVED || dst.numverts&~LAYER_TOP),
- usemerges = hasmerges&(1<<i) && merges[i].u1 < merges[i].u2 && merges[i].v1 < merges[i].v2,
- usenorms = hasnorms&(1<<i) && normals[i].normals[0] != bvec(128, 128, 128);
- if(uselms || usemerges || usenorms)
- {
- ivec v[4], pos[4], e1, e2, e3, n, vo = ivec(co).mask(0xFFF).shl(3);
- genfaceverts(c, i, v);
- n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0]));
- if(usemerges)
- {
- const mergecompat &m = merges[i];
- int offset = -n.dot(v[0].mul(size).add(vo)),
- dim = dimension(i), vc = C[dim], vr = R[dim];
- loopk(4)
- {
- const ivec &coords = facecoords[i][k];
- int cc = coords[vc] ? m.u2 : m.u1,
- rc = coords[vr] ? m.v2 : m.v1,
- dc = n[dim] ? -(offset + n[vc]*cc + n[vr]*rc)/n[dim] : vo[dim];
- ivec &mv = pos[k];
- mv[vc] = cc;
- mv[vr] = rc;
- mv[dim] = dc;
- }
- }
- else
- {
- int convex = (e3 = v[0]).sub(v[3]).dot(n), vis = 3;
- if(!convex)
- {
- if(ivec().cross(e3, e2).iszero()) { if(!n.iszero()) vis = 1; }
- else if(n.iszero()) vis = 2;
- }
- int order = convex < 0 ? 1 : 0;
- pos[0] = v[order].mul(size).add(vo);
- pos[1] = vis&1 ? v[order+1].mul(size).add(vo) : pos[0];
- pos[2] = v[order+2].mul(size).add(vo);
- pos[3] = vis&2 ? v[(order+3)&3].mul(size).add(vo) : pos[0];
- }
- curverts = verts + totalverts;
- loopk(4)
- {
- if(k > 0 && (pos[k] == pos[0] || pos[k] == pos[k-1])) continue;
- vertinfo &dv = curverts[numverts++];
- dv.setxyz(pos[k]);
- if(uselms)
- {
- float u = src->x + (src->texcoords[k*2] / 255.0f) * (src->w - 1),
- v = src->y + (src->texcoords[k*2+1] / 255.0f) * (src->h - 1);
- dv.u = ushort(floor(clamp((u) * float(USHRT_MAX+1)/LM_PACKW + 0.5f, 0.0f, float(USHRT_MAX))));
- dv.v = ushort(floor(clamp((v) * float(USHRT_MAX+1)/LM_PACKH + 0.5f, 0.0f, float(USHRT_MAX))));
- }
- else dv.u = dv.v = 0;
- dv.norm = usenorms && normals[i].normals[k] != bvec(128, 128, 128) ? encodenormal(normals[i].normals[k].tonormal().normalize()) : 0;
- }
- dst.verts = totalverts;
- dst.numverts |= numverts;
- totalverts += numverts;
- if(dst.numverts&LAYER_DUP) loopk(4)
- {
- if(k > 0 && (pos[k] == pos[0] || pos[k] == pos[k-1])) continue;
- vertinfo &bv = verts[totalverts++];
- bv.setxyz(pos[k]);
- bv.u = ushort(floor(clamp((blend->x + (blend->texcoords[k*2] / 255.0f) * (blend->w - 1)) * float(USHRT_MAX+1)/LM_PACKW, 0.0f, float(USHRT_MAX))));
- bv.v = ushort(floor(clamp((blend->y + (blend->texcoords[k*2+1] / 255.0f) * (blend->h - 1)) * float(USHRT_MAX+1)/LM_PACKH, 0.0f, float(USHRT_MAX))));
- bv.norm = usenorms && normals[i].normals[k] != bvec(128, 128, 128) ? encodenormal(normals[i].normals[k].tonormal().normalize()) : 0;
- }
- }
- }
- setsurfaces(c, dstsurfs, verts, totalverts);
-}
-
-static inline int convertoldmaterial(int mat)
-{
- return ((mat&7)<<MATF_VOLUME_SHIFT) | (((mat>>3)&3)<<MATF_CLIP_SHIFT) | (((mat>>5)&7)<<MATF_FLAG_SHIFT);
-}
-
void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed)
{
bool haschildren = false;
default: failed = true; return;
}
loopi(6) c.texture[i] = mapversion<14 ? f->getchar() : f->getlil<ushort>();
- if(mapversion < 7) f->seek(3, SEEK_CUR);
- else if(mapversion <= 31)
- {
- uchar mask = f->getchar();
- if(mask & 0x80)
- {
- int mat = f->getchar();
- if(mapversion < 27)
- {
- static const ushort matconv[] = { MAT_AIR, MAT_WATER, MAT_CLIP, MAT_GLASS|MAT_CLIP, MAT_NOCLIP, MAT_LAVA|MAT_DEATH, MAT_GAMECLIP, MAT_DEATH };
- c.material = size_t(mat) < sizeof(matconv)/sizeof(matconv[0]) ? (int) matconv[mat] : (int) MAT_AIR;
- }
- else c.material = convertoldmaterial(mat);
- }
- surfacecompat surfaces[12];
- normalscompat normals[6];
- mergecompat merges[6];
- int hassurfs = 0, hasnorms = 0, hasmerges = 0;
- if(mask & 0x3F)
- {
- int numsurfs = 6;
- loopi(numsurfs)
- {
- if(i >= 6 || mask & (1 << i))
- {
- f->read(&surfaces[i], sizeof(surfacecompat));
- lilswap(&surfaces[i].x, 2);
- if(mapversion < 10) ++surfaces[i].lmid;
- if(mapversion < 18)
- {
- if(surfaces[i].lmid >= LMID_AMBIENT1) ++surfaces[i].lmid;
- if(surfaces[i].lmid >= LMID_BRIGHT1) ++surfaces[i].lmid;
- }
- if(mapversion < 19)
- {
- if(surfaces[i].lmid >= LMID_DARK) surfaces[i].lmid += 2;
- }
- if(i < 6)
- {
- if(mask & 0x40) { hasnorms |= 1<<i; f->read(&normals[i], sizeof(normalscompat)); }
- if(surfaces[i].layer != 0 || surfaces[i].lmid != LMID_AMBIENT)
- hassurfs |= 1<<i;
- if(surfaces[i].layer&2) numsurfs++;
- }
- }
- }
- }
- if(mapversion <= 8) edgespan2vectorcube(c);
- if(mapversion <= 11)
- {
- swap(c.faces[0], c.faces[2]);
- swap(c.texture[0], c.texture[4]);
- swap(c.texture[1], c.texture[5]);
- if(hassurfs&0x33)
- {
- swap(surfaces[0], surfaces[4]);
- swap(surfaces[1], surfaces[5]);
- hassurfs = (hassurfs&~0x33) | ((hassurfs&0x30)>>4) | ((hassurfs&0x03)<<4);
- }
- }
- if(mapversion >= 20)
- {
- if(octsav&0x80)
- {
- int merged = f->getchar();
- c.merged = merged&0x3F;
- if(merged&0x80)
- {
- int mask = f->getchar();
- if(mask)
- {
- hasmerges = mask&0x3F;
- loopi(6) if(mask&(1<<i))
- {
- mergecompat *m = &merges[i];
- f->read(m, sizeof(mergecompat));
- lilswap(&m->u1, 4);
- if(mapversion <= 25)
- {
- int uorigin = m->u1 & 0xE000, vorigin = m->v1 & 0xE000;
- m->u1 = (m->u1 - uorigin) << 2;
- m->u2 = (m->u2 - uorigin) << 2;
- m->v1 = (m->v1 - vorigin) << 2;
- m->v2 = (m->v2 - vorigin) << 2;
- }
- }
- }
- }
- }
- }
- if(hassurfs || hasnorms || hasmerges)
- convertoldsurfaces(c, co, size, surfaces, hassurfs, normals, hasnorms, merges, hasmerges);
- }
- else
+
{
- if(octsav&0x40)
- {
- if(mapversion <= 32)
- {
- int mat = f->getchar();
- c.material = convertoldmaterial(mat);
- }
- else c.material = f->getlil<ushort>();
- }
+ if(octsav&0x40) c.material = f->getlil<ushort>();
if(octsav&0x80) c.merged = f->getchar();
if(octsav&0x20)
{
lilswap(&tmp.o.x, 3);
lilswap(&tmp.attr1, 5);
f->write(&tmp, sizeof(entity));
- entities::writeent(*ents[i], ebuf);
if(entities::extraentinfosize()) f->write(ebuf, entities::extraentinfosize());
}
}
if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; }
compatheader chdr;
- if(hdr.version <= 28)
- {
- if(f->read(&chdr.lightprecision, sizeof(chdr) - 7*sizeof(int)) != sizeof(chdr) - 7*sizeof(int)) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
- }
- else
- {
- int extra = 0;
- if(hdr.version <= 29) extra++;
- if(f->read(&hdr.blendmap, sizeof(hdr) - (7+extra)*sizeof(int)) != sizeof(hdr) - (7+extra)*sizeof(int)) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; }
+ if(f->read(&hdr.blendmap, sizeof(hdr) - 7*sizeof(int)) != sizeof(hdr) - 7*sizeof(int)) {
+ conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false;
}
resetmap();
setvar("mapversion", hdr.version, true, false);
- if(hdr.version <= 28)
- {
- lilswap(&chdr.lightprecision, 3);
- if(chdr.lightprecision) setvar("lightprecision", chdr.lightprecision);
- if(chdr.lighterror) setvar("lighterror", chdr.lighterror);
- if(chdr.bumperror) setvar("bumperror", chdr.bumperror);
- setvar("lightlod", chdr.lightlod);
- if(chdr.ambient) setvar("ambient", chdr.ambient);
- setvar("skylight", (int(chdr.skylight[0])<<16) | (int(chdr.skylight[1])<<8) | int(chdr.skylight[2]));
- setvar("watercolour", (int(chdr.watercolour[0])<<16) | (int(chdr.watercolour[1])<<8) | int(chdr.watercolour[2]), true);
- setvar("waterfallcolour", (int(chdr.waterfallcolour[0])<<16) | (int(chdr.waterfallcolour[1])<<8) | int(chdr.waterfallcolour[2]));
- setvar("lavacolour", (int(chdr.lavacolour[0])<<16) | (int(chdr.lavacolour[1])<<8) | int(chdr.lavacolour[2]));
- setvar("fullbright", 0, true);
- if(chdr.lerpsubdivsize || chdr.lerpangle) setvar("lerpangle", chdr.lerpangle);
- if(chdr.lerpsubdivsize)
- {
- setvar("lerpsubdiv", chdr.lerpsubdiv);
- setvar("lerpsubdivsize", chdr.lerpsubdivsize);
- }
- setsvar("maptitle", chdr.maptitle);
- hdr.blendmap = chdr.blendmap;
- hdr.numvars = 0;
- hdr.numvslots = 0;
- }
- else
- {
- lilswap(&hdr.blendmap, 2);
- if(hdr.version <= 29) hdr.numvslots = 0;
- else lilswap(&hdr.numvslots, 1);
- }
+ lilswap(&hdr.blendmap, 2);
+ lilswap(&hdr.numvslots, 1);
renderprogress(0, "clearing world...");
copystring(gametype, "fps");
bool samegame = true;
int eif = 0;
- if(hdr.version>=16)
{
int len = f->getchar();
f->read(gametype, len+1);
samegame = false;
conoutf(CON_WARN, "WARNING: loading map from %s game, ignoring entities except for lights/mapmodels", gametype);
}
- if(hdr.version>=16)
{
eif = f->getlil<ushort>();
int extrasize = f->getlil<ushort>();
}
texmru.shrink(0);
- if(hdr.version<14)
- {
- uchar oldtl[256];
- f->read(oldtl, sizeof(oldtl));
- loopi(256) texmru.add(oldtl[i]);
- }
- else
- {
- ushort nummru = f->getlil<ushort>();
- loopi(nummru) texmru.add(f->getlil<ushort>());
- }
+ ushort nummru = f->getlil<ushort>();
+ loopi(nummru) texmru.add(f->getlil<ushort>());
renderprogress(0, "loading entities...");
f->read(&e, sizeof(entity));
lilswap(&e.o.x, 3);
lilswap(&e.attr1, 5);
- fixent(e, hdr.version);
if(samegame)
{
if(einfosize > 0) f->read(ebuf, einfosize);
- entities::readent(e, ebuf, mapversion);
}
else
{
if(eif > 0) f->seek(eif, SEEK_CUR);
- if(e.type>=ET_GAMESPECIFIC || hdr.version<=14)
+ if(e.type>=ET_GAMESPECIFIC)
{
entities::deleteentity(ents.pop());
continue;
conoutf(CON_WARN, "warning: ent outside of world: enttype[%s] index %d (%f, %f, %f)", entities::entname(e.type), i, e.o.x, e.o.y, e.o.z);
}
}
- if(hdr.version <= 14 && e.type == ET_MAPMODEL)
- {
- e.o.z += e.attr3;
- if(e.attr4) conoutf(CON_WARN, "warning: mapmodel ent (index %d) uses texture slot %d", i, e.attr4);
- e.attr3 = e.attr4 = 0;
- }
}
if(ebuf) delete[] ebuf;
if(!failed)
{
- if(hdr.version >= 7) loopi(hdr.lightmaps)
+ loopi(hdr.lightmaps)
{
renderprogress(i/(float)hdr.lightmaps, "loading lightmaps...");
LightMap &lm = lightmaps.add();
- if(hdr.version >= 17)
{
int type = f->getchar();
lm.type = type&0x7F;
- if(hdr.version >= 20 && type&0x80)
+ if(type&0x80)
{
lm.unlitx = f->getlil<ushort>();
lm.unlity = f->getlil<ushort>();
lm.finalize();
}
- if(hdr.version >= 28 && hdr.blendmap) loadblendmap(f, hdr.blendmap);
+ if(hdr.blendmap) loadblendmap(f, hdr.blendmap);
}
mapcrc = f->getcrc();
#include "game.h"
-extern int fog;
-
namespace ai
{
using namespace game;
float viewdist(int x)
{
- return x <= 100 ? clamp((SIGHTMIN+(SIGHTMAX-SIGHTMIN))/100.f*float(x), float(SIGHTMIN), float(fog)) : float(fog);
+ return x <= 100 ? clamp((SIGHTMIN+(SIGHTMAX-SIGHTMIN))/100.f*float(x), float(SIGHTMIN), float(fog)) : 10000.0f;
}
float viewfieldx(int x)
int extraentinfosize() { return 0; } // size in bytes of what the 2 methods below read/write... so it can be skipped by other games
- void writeent(entity &e, char *buf) // write any additional data to disk (except for ET_ ents)
- {
- }
-
- void readent(entity &e, char *buf, int ver) // read from disk, and init
- {
- if(ver <= 30) switch(e.type)
- {
- case TELEDEST:
- e.attr1 = (int(e.attr1)+180)%360;
- break;
- }
- }
-
#ifndef STANDALONE
vector<extentity *> ents;
{
static const char * const entnames[] =
{
- "none?", "light", "mapmodel", "playerstart", "envmap", "particles", "sound", "spotlight",
+ "none?", "light", "mapmodel", "playerstart", "none?", "particles", "sound", "spotlight",
"shells", "bullets", "rockets", "riflerounds", "grenades", "cartridges",
"health", "healthboost", "tinyhealth", "tinyarmour", "greenarmour", "yellowarmour", "quaddamage",
"teleport", "teledest",
void physicstrigger(physent *d, bool local, int floorlevel, int waterlevel, int material)
{
if(d->type==ENT_INANIMATE) return;
- if (waterlevel>0) { if(material!=MAT_LAVA) playsound(S_SPLASH1, d==player1 ? NULL : &d->o); }
- else if(waterlevel<0) playsound(material==MAT_LAVA ? S_BURN : S_SPLASH2, d==player1 ? NULL : &d->o);
if (floorlevel>0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_JUMP, d); }
else if(floorlevel<0) { if(d==player1 || d->type!=ENT_PLAYER || ((fpsent *)d)->ai) msgsound(S_LAND, d); }
}
LIGHT = ET_LIGHT, // lightsource, attr1 = radius, attr2 = intensity
MAPMODEL = ET_MAPMODEL, // attr1 = angle, attr2 = idx
PLAYERSTART, // attr1 = angle, attr2 = team
- ENVMAP = ET_ENVMAP, // attr1 = radius
+ ENVMAP = ET_NOENVMAP, // attr1 = radius
PARTICLES = ET_PARTICLES,
MAPSOUND = ET_SOUND,
SPOTLIGHT = ET_SPOTLIGHT,
if(!insideworld(vec(pos.x, pos.y, min(pos.z, getworldsize() - 1e-3f)))) return -2;
float dist = raycube(pos, vec(0, 0, -1), 0, RAY_CLIPMAT);
int posmat = lookupmaterial(pos), weight = 1;
- if(isliquid(posmat&MATF_VOLUME)) weight *= 5;
if(dist >= 0)
{
weight = int(dist/ai::JUMPMIN);
pos.z -= clamp(dist-8.0f, 0.0f, pos.z);
int trgmat = lookupmaterial(pos);
if(trgmat&MAT_DEATH || (trgmat&MATF_VOLUME) == MAT_LAVA) weight *= 10;
- else if(isliquid(trgmat&MATF_VOLUME)) weight *= 2;
}
return weight;
}
// ET_*: the only static entity types dictated by the engine... rest are gamecode dependent
-enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_ENVMAP, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC };
+enum { ET_EMPTY=0, ET_LIGHT, ET_MAPMODEL, ET_PLAYERSTART, ET_NOENVMAP, ET_PARTICLES, ET_SOUND, ET_SPOTLIGHT, ET_GAMESPECIFIC };
struct entity // persistent map entity
{
enum
{
MATF_INDEX_SHIFT = 0,
- MATF_VOLUME_SHIFT = 2,
MATF_CLIP_SHIFT = 5,
MATF_FLAG_SHIFT = 8,
MATF_INDEX = 3 << MATF_INDEX_SHIFT,
- MATF_VOLUME = 7 << MATF_VOLUME_SHIFT,
MATF_CLIP = 7 << MATF_CLIP_SHIFT,
MATF_FLAGS = 0xFF << MATF_FLAG_SHIFT
};
enum // cube empty-space materials
{
MAT_AIR = 0, // the default, fill the empty space with air
- MAT_WATER = 1 << MATF_VOLUME_SHIFT, // fill with water, showing waves at the surface
- MAT_LAVA = 2 << MATF_VOLUME_SHIFT, // fill with lava
- MAT_GLASS = 3 << MATF_VOLUME_SHIFT, // behaves like clip but is blended blueish
MAT_NOCLIP = 1 << MATF_CLIP_SHIFT, // collisions always treat cube as empty
MAT_CLIP = 2 << MATF_CLIP_SHIFT, // collisions always treat cube as solid
MAT_ALPHA = 4 << MATF_FLAG_SHIFT // alpha blended
};
-#define isliquid(mat) ((mat)==MAT_WATER || (mat)==MAT_LAVA)
-#define isclipped(mat) ((mat)==MAT_GLASS)
-#define isdeadly(mat) ((mat)==MAT_LAVA)
-
extern void lightent(extentity &e, float height = 8.0f);
extern void lightreaching(const vec &target, vec &color, vec &dir, bool fast = false, extentity *e = 0, float ambient = 0.4f);
extern entity *brightestlight(const vec &target, const vec &dir);
extern const char *entnameinfo(entity &e);
extern const char *entname(int i);
extern int extraentinfosize();
- extern void writeent(entity &e, char *buf);
- extern void readent(entity &e, char *buf, int ver);
extern void fixentity(extentity &e);
extern void entradius(extentity &e, bool color);
extern bool mayattach(extentity &e);