guiradio "^f3intense" motionblurscale 0.8
]
]
- guilist [
- guicheckbox "^f3grass^t^t^t" grass
- if $grass [
- guibar
- guiradio "^f2quick fade" grassdist 128
- guibar
- guiradio "^f2moderate fade" grassdist 256
- guibar
- guiradio "^f3slow fade" grassdist 512
- ]
- ]
guilist [
guicheckbox "^f0dynamic lights^t" maxdynlights 3 0
if $maxdynlights [
engine/decal.o \
engine/dynlight.o \
engine/glare.o \
- engine/grass.o \
engine/lightmap.o \
engine/main.o \
engine/material.o \
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/grass.o: engine/engine.h shared/cube.h shared/tools.h shared/geom.h
-engine/grass.o: shared/ents.h shared/command.h shared/glexts.h shared/glemu.h
-engine/grass.o: shared/iengine.h shared/igame.h engine/world.h engine/octa.h
-engine/grass.o: engine/lightmap.h engine/bih.h engine/texture.h
-engine/grass.o: engine/model.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
extern void closemumble();
extern void updatemumble();
-// grass
-extern void generategrass();
-extern void rendergrass();
-extern void cleanupgrass();
-
// blendmap
extern int blendpaintmode;
+++ /dev/null
-#include "engine.h"
-
-VARP(grass, 0, 0, 1);
-VAR(dbggrass, 0, 0, 1);
-VARP(grassdist, 0, 256, 10000);
-FVARP(grasstaper, 0, 0.2, 1);
-FVARP(grassstep, 0.5, 3, 8);
-VARP(grassheight, 1, 4, 64);
-VARP(grassmargin, 0, 8, 32);
-FVAR(grassmarginfade, 0, 0.5f, 1);
-
-#define NUMGRASSWEDGES 8
-
-static struct grasswedge
-{
- vec dir, across, edge1, edge2;
- plane bound1, bound2;
- bvec4 vertbounds;
-
- grasswedge(int i) :
- dir(2*M_PI*(i+0.5f)/float(NUMGRASSWEDGES), 0),
- across(2*M_PI*((i+0.5f)/float(NUMGRASSWEDGES) + 0.25f), 0),
- edge1(vec(2*M_PI*i/float(NUMGRASSWEDGES), 0).div(cos(M_PI/NUMGRASSWEDGES))),
- edge2(vec(2*M_PI*(i+1)/float(NUMGRASSWEDGES), 0).div(cos(M_PI/NUMGRASSWEDGES))),
- bound1(vec(2*M_PI*(i/float(NUMGRASSWEDGES) - 0.25f), 0), 0),
- bound2(vec(2*M_PI*((i+1)/float(NUMGRASSWEDGES) + 0.25f), 0), 0)
- {
- across.div(-across.dot(bound1));
-
- bvec vertbound1(bound1), vertbound2(bound2);
- vertbounds = bvec4(vertbound1.x, vertbound1.y, vertbound2.x, vertbound2.y);
- vertbounds.flip();
- }
-} grasswedges[NUMGRASSWEDGES] = { 0, 1, 2, 3, 4, 5, 6, 7 };
-
-struct grassvert
-{
- vec pos;
- bvec4 color;
- vec2 tc;
- svec2 lm;
- bvec4 bounds;
-};
-
-static vector<grassvert> grassverts;
-static GLuint grassvbo = 0;
-static int grassvbosize = 0;
-
-struct grassgroup
-{
- const grasstri *tri;
- float dist;
- int tex, lmtex, offset, numquads;
-};
-
-static vector<grassgroup> grassgroups;
-
-#define NUMGRASSOFFSETS 32
-
-static float grassoffsets[NUMGRASSOFFSETS] = { -1 }, grassanimoffsets[NUMGRASSOFFSETS];
-static int lastgrassanim = -1;
-
-VARR(grassanimmillis, 0, 3000, 60000);
-FVARR(grassanimscale, 0, 0.03f, 1);
-
-static void animategrass()
-{
- loopi(NUMGRASSOFFSETS) grassanimoffsets[i] = grassanimscale*sinf(2*M_PI*(grassoffsets[i] + lastmillis/float(grassanimmillis)));
- lastgrassanim = lastmillis;
-}
-
-VARR(grassscale, 1, 2, 64);
-bvec grasscolor(255, 255, 255);
-HVARFR(grasscolour, 0, 0xFFFFFF, 0xFFFFFF,
-{
- if(!grasscolour) grasscolour = 0xFFFFFF;
- grasscolor = bvec((grasscolour>>16)&0xFF, (grasscolour>>8)&0xFF, grasscolour&0xFF);
-});
-FVARR(grassalpha, 0, 1, 1);
-
-static void gengrassquads(grassgroup *&group, const grasswedge &w, const grasstri &g, Texture *tex)
-{
- float t = camera1->o.dot(w.dir);
- int tstep = int(ceil(t/grassstep));
- float tstart = tstep*grassstep,
- t0 = w.dir.dot(g.v[0]), t1 = w.dir.dot(g.v[1]), t2 = w.dir.dot(g.v[2]), t3 = w.dir.dot(g.v[3]),
- tmin = min(min(t0, t1), min(t2, t3)),
- tmax = max(max(t0, t1), max(t2, t3));
- if(tmax < tstart || tmin > t + grassdist) return;
-
- int minstep = max(int(ceil(tmin/grassstep)) - tstep, 1),
- maxstep = int(floor(min(tmax, t + grassdist)/grassstep)) - tstep,
- numsteps = maxstep - minstep + 1;
-
- float texscale = (grassscale*tex->ys)/float(grassheight*tex->xs), animscale = grassheight*texscale;
- vec tc;
- tc.cross(g.surface, w.dir).mul(texscale);
-
- int offset = tstep + maxstep;
- if(offset < 0) offset = NUMGRASSOFFSETS - (-offset)%NUMGRASSOFFSETS;
- offset += numsteps + NUMGRASSOFFSETS - numsteps%NUMGRASSOFFSETS;
-
- float leftdist = t0;
- const vec *leftv = &g.v[0];
- if(t1 > leftdist) { leftv = &g.v[1]; leftdist = t1; }
- if(t2 > leftdist) { leftv = &g.v[2]; leftdist = t2; }
- if(t3 > leftdist) { leftv = &g.v[3]; leftdist = t3; }
- float rightdist = leftdist;
- const vec *rightv = leftv;
-
- vec across(w.across.x, w.across.y, g.surface.zdelta(w.across)), leftdir(0, 0, 0), rightdir(0, 0, 0), leftp = *leftv, rightp = *rightv;
- float taperdist = grassdist*grasstaper,
- taperscale = 1.0f / (grassdist - taperdist),
- dist = maxstep*grassstep + tstart,
- leftb = 0, rightb = 0, leftdb = 0, rightdb = 0;
- for(int i = maxstep; i >= minstep; i--, offset--, leftp.add(leftdir), rightp.add(rightdir), leftb += leftdb, rightb += rightdb, dist -= grassstep)
- {
- if(dist <= leftdist)
- {
- const vec *prev = leftv;
- float prevdist = leftdist;
- if(--leftv < g.v) leftv += g.numv;
- leftdist = leftv->dot(w.dir);
- if(dist <= leftdist)
- {
- prev = leftv;
- prevdist = leftdist;
- if(--leftv < g.v) leftv += g.numv;
- leftdist = leftv->dot(w.dir);
- }
- leftdir = vec(*leftv).sub(*prev);
- leftdir.mul(grassstep/-w.dir.dot(leftdir));
- leftp = vec(leftdir).mul((prevdist - dist)/grassstep).add(*prev);
- leftb = w.bound1.dist(leftp);
- leftdb = w.bound1.dot(leftdir);
- }
- if(dist <= rightdist)
- {
- const vec *prev = rightv;
- float prevdist = rightdist;
- if(++rightv >= &g.v[g.numv]) rightv = g.v;
- rightdist = rightv->dot(w.dir);
- if(dist <= rightdist)
- {
- prev = rightv;
- prevdist = rightdist;
- if(++rightv >= &g.v[g.numv]) rightv = g.v;
- rightdist = rightv->dot(w.dir);
- }
- rightdir = vec(*rightv).sub(*prev);
- rightdir.mul(grassstep/-w.dir.dot(rightdir));
- rightp = vec(rightdir).mul((prevdist - dist)/grassstep).add(*prev);
- rightb = w.bound2.dist(rightp);
- rightdb = w.bound2.dot(rightdir);
- }
- vec p1 = leftp, p2 = rightp;
- if(leftb > grassmargin)
- {
- if(w.bound1.dist(p2) >= grassmargin) continue;
- p1.add(vec(across).mul(leftb - grassmargin));
- }
- if(rightb > grassmargin)
- {
- if(w.bound2.dist(p1) >= grassmargin) continue;
- p2.sub(vec(across).mul(rightb - grassmargin));
- }
-
- if(!group)
- {
- group = &grassgroups.add();
- group->tri = &g;
- group->tex = tex->id;
- extern bool brightengeom;
- extern int fullbright;
- int lmid = brightengeom && (g.lmid < LMID_RESERVED || (fullbright && editmode)) ? (int) LMID_BRIGHT : (int) g.lmid;
- group->lmtex = lightmaptexs.inrange(lmid) ? lightmaptexs[lmid].id : notexture->id;
- group->offset = grassverts.length()/4;
- group->numquads = 0;
- if(lastgrassanim!=lastmillis) animategrass();
- }
-
- group->numquads++;
-
- float tcoffset = grassoffsets[offset%NUMGRASSOFFSETS],
- animoffset = animscale*grassanimoffsets[offset%NUMGRASSOFFSETS],
- tc1 = tc.dot(p1) + tcoffset, tc2 = tc.dot(p2) + tcoffset,
- fade = dist - t > taperdist ? (grassdist - (dist - t))*taperscale : 1,
- height = grassheight * fade;
- svec2 lm1(short(g.tcu.dot(p1)), short(g.tcv.dot(p1))),
- lm2(short(g.tcu.dot(p2)), short(g.tcv.dot(p2)));
- bvec4 color(grasscolor, uchar(fade*grassalpha*255));
-
- #define GRASSVERT(n, tcv, modify) { \
- grassvert &gv = grassverts.add(); \
- gv.pos = p##n; \
- gv.color = color; \
- gv.tc = vec2(tc##n, tcv); \
- gv.lm = lm##n; \
- gv.bounds = w.vertbounds; \
- modify; \
- }
-
- GRASSVERT(2, 0, { gv.pos.z += height; gv.tc.x += animoffset; });
- GRASSVERT(1, 0, { gv.pos.z += height; gv.tc.x += animoffset; });
- GRASSVERT(1, 1, );
- GRASSVERT(2, 1, );
- }
-}
-
-static void gengrassquads(vtxarray *va)
-{
- loopv(va->grasstris)
- {
- grasstri &g = va->grasstris[i];
- if(isfoggedsphere(g.radius, g.center)) continue;
- float dist = g.center.dist(camera1->o);
- if(dist - g.radius > grassdist) continue;
-
- Slot &s = *lookupvslot(g.texture, false).slot;
- if(!s.grasstex)
- {
- if(!s.autograss) continue;
- s.grasstex = textureload(s.autograss, 2);
- }
-
- grassgroup *group = NULL;
- loopi(NUMGRASSWEDGES)
- {
- grasswedge &w = grasswedges[i];
- if(w.bound1.dist(g.center) > g.radius + grassmargin || w.bound2.dist(g.center) > g.radius + grassmargin) continue;
- gengrassquads(group, w, g, s.grasstex);
- }
- if(group) group->dist = dist;
- }
-}
-
-static inline bool comparegrassgroups(const grassgroup &x, const grassgroup &y)
-{
- return x.dist > y.dist;
-}
-
-void generategrass()
-{
- if(!grass || !grassdist) return;
-
- grassgroups.setsize(0);
- grassverts.setsize(0);
-
- if(grassoffsets[0] < 0) loopi(NUMGRASSOFFSETS) grassoffsets[i] = rnd(0x1000000)/float(0x1000000);
-
- loopi(NUMGRASSWEDGES)
- {
- grasswedge &w = grasswedges[i];
- w.bound1.offset = -camera1->o.dot(w.bound1);
- w.bound2.offset = -camera1->o.dot(w.bound2);
- }
-
- for(vtxarray *va = visibleva; va; va = va->next)
- {
- if(va->grasstris.empty() || va->occluded >= OCCLUDE_GEOM) continue;
- if(va->distance > grassdist) continue;
- if(reflecting || refracting>0 ? va->o.z+va->size<reflectz : va->o.z>=reflectz) continue;
- gengrassquads(va);
- }
-
- if(grassgroups.empty()) return;
-
- grassgroups.sort(comparegrassgroups);
-
- if(!grassvbo) glGenBuffers_(1, &grassvbo);
- gle::bindvbo(grassvbo);
- int size = grassverts.length()*sizeof(grassvert);
- grassvbosize = max(grassvbosize, size);
- glBufferData_(GL_ARRAY_BUFFER, grassvbosize, size == grassvbosize ? grassverts.getbuf() : NULL, GL_STREAM_DRAW);
- if(size != grassvbosize) glBufferSubData_(GL_ARRAY_BUFFER, 0, size, grassverts.getbuf());
- gle::clearvbo();
-}
-
-void rendergrass()
-{
- if(!grass || !grassdist || grassgroups.empty() || dbggrass) return;
-
- glDisable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glDepthMask(GL_FALSE);
-
- GLOBALPARAM(camera, camera1->o);
-
- SETSHADER(grass);
-
- LOCALPARAMF(grassmargin, grassmargin, grassmargin ? grassmarginfade / grassmargin : 0.0f, grassmargin ? grassmarginfade : 1.0f);
-
- gle::bindvbo(grassvbo);
-
- const grassvert *ptr = 0;
- gle::vertexpointer(sizeof(grassvert), ptr->pos.v);
- gle::colorpointer(sizeof(grassvert), ptr->color.v);
- gle::texcoord0pointer(sizeof(grassvert), ptr->tc.v);
- gle::texcoord1pointer(sizeof(grassvert), ptr->lm.v, GL_SHORT);
- gle::tangentpointer(sizeof(grassvert), ptr->bounds.v, GL_BYTE);
- gle::enablevertex();
- gle::enablecolor();
- gle::enabletexcoord0();
- gle::enabletexcoord1();
- gle::enabletangent();
- gle::enablequads();
-
- int texid = -1, lmtexid = -1;
- loopv(grassgroups)
- {
- grassgroup &g = grassgroups[i];
-
- if(reflecting || refracting)
- {
- if(refracting < 0 ? g.tri->minz > reflectz : g.tri->maxz + grassheight < reflectz) continue;
- if(isfoggedsphere(g.tri->radius, g.tri->center)) continue;
- }
-
- if(texid != g.tex)
- {
- glBindTexture(GL_TEXTURE_2D, g.tex);
- texid = g.tex;
- }
- if(lmtexid != g.lmtex)
- {
- glActiveTexture_(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, g.lmtex);
- glActiveTexture_(GL_TEXTURE0);
- lmtexid = g.lmtex;
- }
-
- gle::drawquads(g.offset, g.numquads);
- xtravertsva += 4*g.numquads;
- }
-
- gle::disablequads();
- gle::disablevertex();
- gle::disablecolor();
- gle::disabletexcoord0();
- gle::disabletexcoord1();
- gle::disabletangent();
-
- gle::clearvbo();
-
- glDisable(GL_BLEND);
- glDepthMask(GL_TRUE);
- glEnable(GL_CULL_FACE);
-}
-
-void cleanupgrass()
-{
- if(grassvbo) { glDeleteBuffers_(1, &grassvbo); grassvbo = 0; }
- grassvbosize = 0;
-}
-
LAYER_DUP = (1<<7),
LAYER_BLEND = LAYER_TOP|LAYER_BOTTOM,
-
+
MAXFACEVERTS = 15
};
static const surfaceinfo brightsurface = {{LMID_BRIGHT, LMID_AMBIENT}, 0, LAYER_TOP};
static const surfaceinfo brightbottomsurface = {{LMID_AMBIENT, LMID_BRIGHT}, 0, LAYER_BOTTOM};
-struct grasstri
-{
- vec v[4];
- int numv;
- vec4 tcu, tcv;
- plane surface;
- vec center;
- float radius;
- float minz, maxz;
- ushort texture, lmid;
-};
-
struct occludequery
{
void *owner;
uchar curvfc, occluded;
occludequery *query;
vector<octaentities *> mapmodels;
- vector<grasstri> grasstris;
int hasmerges, mergelevel;
uint dynlightmask;
bool shadowed;
uchar maxverts; // allocated space for verts
vertinfo *verts() { return (vertinfo *)(this+1); }
-};
+};
struct cube
{
int size;
hashtable<sortkey, sortval> indices;
vector<sortkey> texs;
- vector<grasstri> grasstris;
vector<materialsurface> matsurfs;
vector<octaentities *> mapmodels;
vector<ushort> skyindices, explicitskyindices;
explicitskyindices.setsize(0);
matsurfs.setsize(0);
mapmodels.setsize(0);
- grasstris.setsize(0);
texs.setsize(0);
loopi(6) skyfaces[i].setsize(0);
}
va->alphatris = va->alphabacktris + va->alphafronttris;
- if(grasstris.length())
- {
- va->grasstris.move(grasstris);
- useshaderbyname("grass");
- }
-
if(mapmodels.length()) va->mapmodels.put(mapmodels.getbuf(), mapmodels.length());
}
bool emptyva()
{
- return verts.empty() && matsurfs.empty() && skyindices.empty() && explicitskyindices.empty() && grasstris.empty() && mapmodels.empty();
+ return verts.empty() && matsurfs.empty() && skyindices.empty() && explicitskyindices.empty() && mapmodels.empty();
}
} vc;
}
}
-void addgrasstri(int face, vertex *verts, int numv, ushort texture, ushort lmid)
-{
- grasstri &g = vc.grasstris.add();
- int i1, i2, i3, i4;
- if(numv <= 3 && face%2) { i1 = face+1; i2 = face+2; i3 = i4 = 0; }
- else { i1 = 0; i2 = face+1; i3 = face+2; i4 = numv > 3 ? face+3 : i3; }
- g.v[0] = verts[i1].pos;
- g.v[1] = verts[i2].pos;
- g.v[2] = verts[i3].pos;
- g.v[3] = verts[i4].pos;
- g.numv = numv;
-
- g.surface.toplane(g.v[0], g.v[1], g.v[2]);
- if(g.surface.z <= 0) { vc.grasstris.pop(); return; }
-
- g.minz = min(min(g.v[0].z, g.v[1].z), min(g.v[2].z, g.v[3].z));
- g.maxz = max(max(g.v[0].z, g.v[1].z), max(g.v[2].z, g.v[3].z));
-
- g.center = vec(0, 0, 0);
- loopk(numv) g.center.add(g.v[k]);
- g.center.div(numv);
- g.radius = 0;
- loopk(numv) g.radius = max(g.radius, g.v[k].dist(g.center));
-
- vec area, bx, by;
- area.cross(vec(g.v[1]).sub(g.v[0]), vec(g.v[2]).sub(g.v[0]));
- float scale;
- int px, py;
-
- if(fabs(area.x) >= fabs(area.y) && fabs(area.x) >= fabs(area.z))
- scale = 1/area.x, px = 1, py = 2;
- else if(fabs(area.y) >= fabs(area.x) && fabs(area.y) >= fabs(area.z))
- scale = -1/area.y, px = 0, py = 2;
- else
- scale = 1/area.z, px = 0, py = 1;
-
- bx.x = (g.v[2][py] - g.v[0][py])*scale;
- bx.y = (g.v[2][px] - g.v[0][px])*scale;
- bx.z = bx.x*g.v[2][px] - bx.y*g.v[2][py];
-
- by.x = (g.v[2][py] - g.v[1][py])*scale;
- by.y = (g.v[2][px] - g.v[1][px])*scale;
- by.z = by.x*g.v[1][px] - by.y*g.v[1][py] - 1;
- by.sub(bx);
-
- float tc1u = verts[i1].lm.x,
- tc1v = verts[i1].lm.y,
- tc2u = verts[i2].lm.x - verts[i1].lm.x,
- tc2v = verts[i2].lm.y - verts[i1].lm.y,
- tc3u = verts[i3].lm.x - verts[i1].lm.x,
- tc3v = verts[i3].lm.y - verts[i1].lm.y;
-
- g.tcu = vec4(0, 0, 0, tc1u - (bx.z*tc2u + by.z*tc3u));
- g.tcu[px] = bx.x*tc2u + by.x*tc3u;
- g.tcu[py] = -(bx.y*tc2u + by.y*tc3u);
-
- g.tcv = vec4(0, 0, 0, tc1v - (bx.z*tc2v + by.z*tc3v));
- g.tcv[px] = bx.x*tc2v + by.x*tc3v;
- g.tcv[py] = -(bx.y*tc2v + by.y*tc3v);
-
- g.texture = texture;
- g.lmid = lmid;
-}
-
static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen)
{
Texture *tex = vslot.slot->sts.empty() ? notexture : vslot.slot->sts[0].t;
void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, ushort envmap = EMID_NONE, int grassy = 0, bool alpha = false, int layer = LAYER_TOP)
{
+ (void) grassy;
int dim = dimension(orient);
int shadowmask = texture==DEFAULT_SKY || alpha ? 0 : calcshadowmask(pos, numverts);
sortkey key(texture, lmid, !vslot.scroll.iszero() ? dim : 3, layer == LAYER_BLEND ? LAYER_BLEND : LAYER_TOP, envmap, alpha ? (vslot.alphaback ? ALPHA_BACK : (vslot.alphafront ? ALPHA_FRONT : NO_ALPHA)) : NO_ALPHA);
addtris(key, orient, verts, index, numverts, convex, shadowmask, tj);
-
- if(grassy)
- {
- for(int i = 0; i < numverts-2; i += 2)
- {
- int faces = 0;
- if(index[0]!=index[i+1] && index[i+1]!=index[i+2] && index[i+2]!=index[0]) faces |= 1;
- if(i+3 < numverts && index[0]!=index[i+2] && index[i+2]!=index[i+3] && index[i+3]!=index[0]) faces |= 2;
- if(grassy > 1 && faces==3) addgrasstri(i, verts, 4, texture, lmid);
- else
- {
- if(faces&1) addgrasstri(i, verts, 3, texture, lmid);
- if(faces&2) addgrasstri(i+1, verts, 3, texture, lmid);
- }
- }
- }
}
struct edgegroup
envmap2 = layer && layer->slot->shader->type&SHADER_ENVMAP ? (int) (layer->slot->texmask&(1<<TEX_ENVMAP) ? (int) EMID_CUSTOM : (int) closestenvmap(i, co, size)) : (int) EMID_NONE;
while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next;
int hastj = tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1) ? tj : -1;
- int grassy = vslot.slot->autograss && i!=O_BOTTOM ? (vis!=3 || convex ? 1 : 2) : 0;
if(!c.ext)
- addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, envmap, grassy, (c.material&MAT_ALPHA)!=0);
+ addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, envmap, 0, (c.material&MAT_ALPHA)!=0);
else
{
const surfaceinfo &surf = c.ext->surfaces[i];
if(!surf.numverts || surf.numverts&LAYER_TOP)
- addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, envmap, grassy, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND));
+ addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, envmap, 0, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND));
if(surf.numverts&LAYER_BOTTOM)
addcubeverts(layer ? *layer : vslot, i, size, pos, convex, vslot.layer, surf.lmid[1], surf.numverts&LAYER_DUP ? verts + numverts : verts, numverts, hastj, envmap2);
}
pos[i] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo);
}
VSlot &vslot = lookupvslot(mf.tex, true);
- int grassy = vslot.slot->autograss && mf.orient!=O_BOTTOM && mf.numverts&LAYER_TOP ? 2 : 0;
- addcubeverts(vslot, mf.orient, 1<<level, pos, 0, mf.tex, mf.lmid, mf.verts, numverts, mf.tjoints, mf.envmap, grassy, (mf.mat&MAT_ALPHA)!=0, mf.numverts&LAYER_BLEND);
+ addcubeverts(vslot, mf.orient, 1<<level, pos, 0, mf.tex, mf.lmid, mf.verts, numverts, mf.tjoints, mf.envmap, 0, (mf.mat&MAT_ALPHA)!=0, mf.numverts&LAYER_BLEND);
vahasmerges |= MERGE_USE;
}
mfl.setsize(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 grass, glare, maxdynlights, depthfxsize, blurdepthfx, texcompress;
- grass = 1;
+ extern int glare, maxdynlights, depthfxsize, blurdepthfx, texcompress;
waterfallrefract = 1;
glare = 1;
maxdynlights = MAXDYNLIGHTS;
setcamprojmatrix(false, true);
}
- if(refracting) rendergrass();
rendermaterials();
renderalphageom(fogging);
renderparticles();
queryreflections();
- generategrass();
-
if(!limitsky()) drawskybox(farplane, false);
renderdecals(true);
if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
renderwater();
- rendergrass();
rendermaterials();
renderalphageom();
clearvas(worldroot);
clearqueries();
cleanupbb();
- cleanupgrass();
loopi(NUMCAUSTICS) caustictex[i] = NULL;
}
COMMAND(texture, "ssiiif");
-void autograss(char *name)
-{
- if(slots.empty()) return;
- Slot &s = *slots.last();
- DELETEA(s.autograss);
- s.autograss = name[0] ? newstring(makerelpath("packages", name, NULL, "<premul>")) : NULL;
-}
-COMMAND(autograss, "s");
-
void texscroll(float *scrollS, float *scrollT)
{
if(slots.empty()) return;
}
};
-enum
-{
- SHADER_DEFAULT = 0,
- SHADER_NORMALSLMS = 1<<0,
+enum
+{
+ SHADER_DEFAULT = 0,
+ SHADER_NORMALSLMS = 1<<0,
SHADER_ENVMAP = 1<<1,
SHADER_OPTION = 1<<3,
{
if(lastshader!=detailshader) detailshader->bindprograms();
}
-
+
void set()
{
if(isnull() || !loaded()) return;
bool compile();
void cleanup(bool invalid = false);
-
+
static int uniformlocversion();
};
template<class T>
T *reserve(int n = 1) { return (T *)resolve()->buf; }
-};
+};
struct LocalShaderParam
{
int loc;
LocalShaderParam(const char *name) : name(name), loc(-1) {}
-
+
LocalShaderParamState *resolve()
{
Shader *s = Shader::lastshader;
: data(NULL), owner(NULL), freefunc(NULL)
{}
-
- ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE)
- {
- setdata(NULL, nw, nh, nbpp, nlevels, nalign, ncompressed);
+
+ ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE)
+ {
+ setdata(NULL, nw, nh, nbpp, nlevels, nalign, ncompressed);
}
ImageData(int nw, int nh, int nbpp, uchar *data)
: owner(NULL), freefunc(NULL)
- {
- setdata(data, nw, nh, nbpp);
+ {
+ setdata(data, nw, nh, nbpp);
}
ImageData(SDL_Surface *s) { wrap(s); }
data = ndata ? ndata : new uchar[calcsize()];
if(!ndata) { owner = this; freefunc = NULL; }
}
-
+
int calclevelsize(int level) const { return ((max(w>>level, 1)+align-1)/align)*((max(h>>level, 1)+align-1)/align)*bpp; }
-
+
int calcsize() const
{
if(!align) return w*h*bpp;
IMAGE = 0,
CUBEMAP = 1,
TYPE = 0xFF,
-
+
STUB = 1<<8,
TRANSIENT = 1<<9,
- COMPRESSED = 1<<10,
+ COMPRESSED = 1<<10,
ALPHA = 1<<11,
MIRROR = 1<<12,
FLAGS = 0xFF00
TEX_ENVMAP
};
-enum
-{
- VSLOT_SHPARAM = 0,
- VSLOT_SCALE,
- VSLOT_ROTATION,
- VSLOT_OFFSET,
- VSLOT_SCROLL,
- VSLOT_LAYER,
+enum
+{
+ VSLOT_SHPARAM = 0,
+ VSLOT_SCALE,
+ VSLOT_ROTATION,
+ VSLOT_OFFSET,
+ VSLOT_SCROLL,
+ VSLOT_LAYER,
VSLOT_ALPHA,
VSLOT_COLOR,
- VSLOT_NUM
+ VSLOT_NUM
};
-
+
struct VSlot
{
Slot *slot;
vec glowcolor;
VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0)
- {
+ {
reset();
- if(slot) addvariant(slot);
+ if(slot) addvariant(slot);
}
void addvariant(Slot *slot);
VSlot *variants;
bool loaded;
uint texmask;
- char *autograss;
- Texture *grasstex, *thumbnail;
+ Texture *thumbnail;
char *layermaskname;
int layermaskmode;
float layermaskscale;
ImageData *layermask;
- Slot(int index = -1) : index(index), variants(NULL), autograss(NULL), layermaskname(NULL), layermask(NULL) { reset(); }
-
+ Slot(int index = -1) : index(index), variants(NULL), layermaskname(NULL), layermask(NULL) { reset(); }
+
void reset()
{
sts.shrink(0);
params.shrink(0);
loaded = false;
texmask = 0;
- DELETEA(autograss);
- grasstex = NULL;
thumbnail = NULL;
DELETEA(layermaskname);
layermaskmode = 0;
void cleanup()
{
loaded = false;
- grasstex = NULL;
thumbnail = NULL;
- loopv(sts)
+ loopv(sts)
{
Tex &t = sts[i];
t.t = NULL;
{
if(vslots.empty()) return;
int *prev = new int[numvslots];
- memset(prev, -1, numvslots*sizeof(int));
+ for(int i=0;i<numvslots;++i)prev[i]=-1;
+ //~memset((void*)prev, -1, (size_t)numvslots*sizeof(int));
loopi(numvslots)
{
VSlot *vs = vslots[i];
{
int *prev = new (false) int[numvslots];
if(!prev) return;
- memset(prev, -1, numvslots*sizeof(int));
+ for(int i=0;i<numvslots;++i)prev[i]=-1;
+ //~memset((void*)prev, -1, (size_t)numvslots*sizeof(int));
while(numvslots > 0)
{
int changed = f->getlil<int>();