diff options
| author | xolatile | 2025-08-06 22:54:55 +0200 |
|---|---|---|
| committer | xolatile | 2025-08-06 22:54:55 +0200 |
| commit | 0a1172b75f571685c264a8b9d8ee224bbf11381f (patch) | |
| tree | d041fdc68a60f0ebb48a3852bbcce6d9432f83d5 /src/engine/decal.cpp | |
| parent | affde05dc07a94643f1fd2751b2b441f57f73d7d (diff) | |
| download | xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.xz xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.zst | |
Please do not hate me, it makes sense...
Diffstat (limited to 'src/engine/decal.cpp')
| -rw-r--r-- | src/engine/decal.cpp | 281 |
1 files changed, 79 insertions, 202 deletions
diff --git a/src/engine/decal.cpp b/src/engine/decal.cpp index 43ef667..bc39c1f 100644 --- a/src/engine/decal.cpp +++ b/src/engine/decal.cpp @@ -1,21 +1,18 @@ #include "engine.h" -struct decalvert -{ +struct decalvert { vec pos; bvec4 color; vec2 tc; }; -struct decalinfo -{ +struct decalinfo { int millis; bvec color; ushort startvert, endvert; }; -enum -{ +enum { DF_RND4 = 1<<0, DF_ROTATE = 1<<1, DF_INVMOD = 1<<2, @@ -27,8 +24,7 @@ enum VARFP(maxdecaltris, 1, 1024, 16384, initdecals()); VARP(decalfade, 1000, 10000, 60000); -struct decalrenderer -{ +struct decalrenderer { const char *texname; int flags, fadeintime, fadeouttime, timetolive; Texture *tex; @@ -38,7 +34,6 @@ struct decalrenderer int maxverts, startvert, endvert, lastvert, availverts; GLuint vbo; bool dirty; - decalrenderer(const char *texname, int flags = 0, int fadeintime = 0, int fadeouttime = 1000, int timetolive = -1) : texname(texname), flags(flags), fadeintime(fadeintime), fadeouttime(fadeouttime), timetolive(timetolive), @@ -46,25 +41,18 @@ struct decalrenderer decals(NULL), maxdecals(0), startdecal(0), enddecal(0), verts(NULL), maxverts(0), startvert(0), endvert(0), lastvert(0), availverts(0), vbo(0), dirty(false), - decalu(0), decalv(0) - { + decalu(0), decalv(0) { } - - ~decalrenderer() - { + ~decalrenderer() { DELETEA(decals); DELETEA(verts); } - - void init(int tris) - { - if(decals) - { + void init(int tris) { + if(decals) { DELETEA(decals); maxdecals = startdecal = enddecal = 0; } - if(verts) - { + if(verts) { DELETEA(verts); maxverts = startvert = endvert = lastvert = availverts = 0; } @@ -75,80 +63,59 @@ struct decalrenderer availverts = maxverts - 3; verts = new decalvert[maxverts]; } - - int hasdecals() - { + int hasdecals() { return enddecal < startdecal ? maxdecals - (startdecal - enddecal) : enddecal - startdecal; } - - void cleanup() - { + void cleanup() { if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } } - - void cleardecals() - { + void cleardecals() { startdecal = enddecal = 0; startvert = endvert = lastvert = 0; availverts = maxverts - 3; dirty = true; } - - int freedecal() - { + int freedecal() { if(startdecal==enddecal) return 0; - decalinfo &d = decals[startdecal]; startdecal++; if(startdecal >= maxdecals) startdecal = 0; - int removed = d.endvert < d.startvert ? maxverts - (d.startvert - d.endvert) : d.endvert - d.startvert; startvert = d.endvert; if(startvert==endvert) startvert = endvert = lastvert = 0; availverts += removed; - return removed; } - - void fadedecal(decalinfo &d, uchar alpha) - { + void fadedecal(decalinfo &d, uchar alpha) { bvec rgb; if(flags&DF_OVERBRIGHT) rgb = bvec(128, 128, 128); - else - { + else { rgb = d.color; if(flags&(DF_ADD|DF_INVMOD)) rgb.scale(alpha, 255); } bvec4 color(rgb, alpha); - decalvert *vert = &verts[d.startvert], *end = &verts[d.endvert < d.startvert ? maxverts : d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } - if(d.endvert < d.startvert) - { + if(d.endvert < d.startvert) { vert = verts; end = &verts[d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } } dirty = true; } - - void clearfadeddecals() - { + void clearfadeddecals() { int threshold = lastmillis - (timetolive>=0 ? timetolive : decalfade) - fadeouttime; decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; while(d < end && d->millis <= threshold) d++; - if(d >= end && enddecal < startdecal) - { + if(d >= end && enddecal < startdecal) { d = decals; end = &decals[enddecal]; while(d < end && d->millis <= threshold) d++; @@ -161,25 +128,20 @@ struct decalrenderer availverts = endvert < startvert ? startvert - endvert - 3 : maxverts - 3 - (endvert - startvert); dirty = true; } - - void fadeindecals() - { + void fadeindecals() { if(!fadeintime) return; decalinfo *d = &decals[enddecal], *end = &decals[enddecal < startdecal ? 0 : startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; fadedecal(*d, (fade<<8)/fadeintime); } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = &decals[maxdecals]; end = &decals[startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; @@ -187,25 +149,20 @@ struct decalrenderer } } } - - void fadeoutdecals() - { + void fadeoutdecals() { decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; int offset = (timetolive>=0 ? timetolive : decalfade) + fadeouttime - lastmillis; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); d++; } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = decals; end = &decals[enddecal]; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); @@ -213,84 +170,59 @@ struct decalrenderer } } } - - static void setuprenderstate() - { + static void setuprenderstate() { enablepolygonoffset(GL_POLYGON_OFFSET_FILL); - glDepthMask(GL_FALSE); glEnable(GL_BLEND); - gle::enablevertex(); gle::enabletexcoord0(); gle::enablecolor(); } - - static void cleanuprenderstate() - { + static void cleanuprenderstate() { gle::clearvbo(); - gle::disablevertex(); gle::disabletexcoord0(); gle::disablecolor(); - glDepthMask(GL_TRUE); glDisable(GL_BLEND); - disablepolygonoffset(GL_POLYGON_OFFSET_FILL); } - - void render() - { + void render() { if(startvert==endvert) return; - - if(flags&DF_OVERBRIGHT) - { + if(flags&DF_OVERBRIGHT) { glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); SETSHADER(overbrightdecal); } - else - { + else { 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); } - glBindTexture(GL_TEXTURE_2D, tex->id); - if(!vbo) { glGenBuffers_(1, &vbo); dirty = true; } gle::bindvbo(vbo); - int count = endvert < startvert ? maxverts - startvert : endvert - startvert; - if(dirty) - { + if(dirty) { glBufferData_(GL_ARRAY_BUFFER, maxverts*sizeof(decalvert), NULL, GL_STREAM_DRAW); glBufferSubData_(GL_ARRAY_BUFFER, 0, count*sizeof(decalvert), &verts[startvert]); - if(endvert < startvert) - { + if(endvert < startvert) { glBufferSubData_(GL_ARRAY_BUFFER, count*sizeof(decalvert), endvert*sizeof(decalvert), verts); count += endvert; } dirty = false; } else if(endvert < startvert) count += endvert; - const decalvert *ptr = 0; gle::vertexpointer(sizeof(decalvert), ptr->pos.v); gle::texcoord0pointer(sizeof(decalvert), ptr->tc.v); gle::colorpointer(sizeof(decalvert), ptr->color.v); - glDrawArrays(GL_TRIANGLES, 0, count); xtravertsva += count; - extern int intel_vertexarray_bug; if(intel_vertexarray_bug) glFlush(); } - - decalinfo &newdecal() - { + decalinfo &newdecal() { decalinfo &d = decals[enddecal]; int next = enddecal + 1; if(next>=maxdecals) next = 0; @@ -299,20 +231,15 @@ struct decalrenderer dirty = true; return d; } - ivec bbmin, bbmax; vec decalcenter, decalnormal, decaltangent, decalbitangent; float decalradius, decalu, decalv; bvec4 decalcolor; - - void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) - { + void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) { if(dir.iszero()) return; - int bbradius = int(ceil(radius)); bbmin = ivec(center).sub(bbradius); bbmax = ivec(center).add(bbradius); - decalcolor = bvec4(color, 255); decalcenter = center; decalradius = radius; @@ -326,46 +253,36 @@ struct decalrenderer if(flags&DF_ROTATE) decaltangent.rotate(rnd(360)*RAD, dir); decaltangent.normalize(); decalbitangent.cross(decaltangent, dir); - if(flags&DF_RND4) - { + if(flags&DF_RND4) { decalu = 0.5f*(info&1); decalv = 0.5f*((info>>1)&1); } - lastvert = endvert; gentris(worldroot, ivec(0, 0, 0), worldsize>>1); if(endvert==lastvert) return; - decalinfo &d = newdecal(); d.color = color; d.millis = lastmillis; d.startvert = lastvert; d.endvert = endvert; } - - static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) - { + static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) { int numout = 0; const vec *p = &in[numin-1]; float pc = dir.dot(*p); - loopi(numin) - { + loopi(numin) { const vec &v = in[i]; float c = dir.dot(v); - if(c < below) - { + if(c < below) { if(pc > above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); if(pc > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } - else if(c > above) - { + else if(c > above) { if(pc < below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); if(pc < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); } - else - { - if(pc < below) - { + else { + if(pc < below) { if(c > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } else if(pc > above && c < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); @@ -376,17 +293,13 @@ struct decalrenderer } return numout; } - - void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) - { + void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) { vec pos[MAXFACEVERTS+4] = { vec(0, 0, 0) }; int numverts = 0, numplanes = 1; vec planes[2] = { vec(0, 0, 0) }; - if(mat) - { + if(mat) { planes[0] = vec(0, 0, 0); - switch(orient) - { + switch(orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ case orient: \ planes[0][dimension(orient)] = dimcoord(orient) ? 1 : -1; \ @@ -399,21 +312,18 @@ struct decalrenderer #undef GENFACEVERT } } - else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) - { + else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) { vertinfo *verts = cu.ext->verts() + cu.ext->surfaces[orient].verts; ivec vo = ivec(o).mask(~0xFFF).shl(3); loopj(numverts) pos[j] = vec(verts[j].getxyz().add(vo)).mul(1/8.0f); planes[0].cross(pos[0], pos[1], pos[2]).normalize(); - if(numverts >= 4 && !(cu.merged&(1<<orient)) && !flataxisface(cu, orient) && faceconvexity(verts, numverts, size)) - { + if(numverts >= 4 && !(cu.merged&(1<<orient)) && !flataxisface(cu, orient) && faceconvexity(verts, numverts, size)) { planes[1].cross(pos[0], pos[2], pos[3]).normalize(); numplanes++; } } else if(cu.merged&(1<<orient)) return; - else if(!vismask || (vismask&0x40 && visibleface(cu, orient, o, size, MAT_AIR, (cu.material&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA))) - { + else if(!vismask || (vismask&0x40 && visibleface(cu, orient, o, size, MAT_AIR, (cu.material&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA))) { ivec v[4]; genfaceverts(cu, orient, v); int vis = 3, convex = faceconvexity(v, vis), order = convex < 0 ? 1 : 0; @@ -426,9 +336,7 @@ struct decalrenderer if(convex) { planes[1].cross(pos[0], pos[2], pos[3]).normalize(); numplanes++; } } else return; - - loopl(numplanes) - { + loopl(numplanes) { const vec &n = planes[l]; float facing = n.dot(decalnormal); if(facing <= 0) continue; @@ -455,14 +363,12 @@ struct decalrenderer vec v1[MAXFACEVERTS+4], v2[MAXFACEVERTS+4]; float ptc = pt.dot(pcenter), pbc = pb.dot(pcenter); int numv; - if(numplanes >= 2) - { + if(numplanes >= 2) { if(l) { pos[1] = pos[2]; pos[2] = pos[3]; } numv = clip(pos, 3, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } - else - { + else { numv = clip(pos, numverts, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } @@ -475,13 +381,11 @@ struct decalrenderer dv2 = { v2[1], decalcolor, vec2(pt.dot(v2[1]) + tu, pb.dot(v2[1]) + tv) }; int totalverts = 3*(numv-2); if(totalverts > maxverts-3) return; - while(availverts < totalverts) - { + while(availverts < totalverts) { if(!freedecal()) return; } availverts -= totalverts; - loopk(numv-2) - { + loopk(numv-2) { verts[endvert++] = dv1; verts[endvert++] = dv2; dv2.pos = v2[k+2]; @@ -491,25 +395,20 @@ struct decalrenderer } } } - - void findmaterials(vtxarray *va) - { + void findmaterials(vtxarray *va) { materialsurface *matbuf = va->matbuf; int matsurfs = va->matsurfs; - loopi(matsurfs) - { + loopi(matsurfs) { materialsurface &m = matbuf[i]; 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]; - for(;;) - { + for(;;) { materialsurface &m = matbuf[i]; if(m.o[dim] >= bbmin[dim] && m.o[dim] <= bbmax[dim] && m.o[c] + m.csize >= bbmin[c] && m.o[c] <= bbmax[c] && - m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) - { + m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) { static cube dummy; gentris(dummy, m.orient, m.o, max(m.csize, m.rsize), &m); } @@ -520,51 +419,38 @@ struct decalrenderer } } } - - void findescaped(cube *cu, const ivec &o, int size, int escaped) - { - loopi(8) - { - if(escaped&(1<<i)) - { + void findescaped(cube *cu, const ivec &o, int size, int escaped) { + loopi(8) { + if(escaped&(1<<i)) { ivec co(i, o, size); if(cu[i].children) findescaped(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } } } } - - void gentris(cube *cu, const ivec &o, int size, int escaped = 0) - { + void gentris(cube *cu, const ivec &o, int size, int escaped = 0) { int overlap = octaboxoverlap(o, size, bbmin, bbmax); - loopi(8) - { - if(overlap&(1<<i)) - { + loopi(8) { + if(overlap&(1<<i)) { ivec co(i, o, size); if(cu[i].ext && cu[i].ext->va && cu[i].ext->va->matsurfs) findmaterials(cu[i].ext->va); if(cu[i].children) gentris(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].visible; - if(vismask&0xC0) - { + if(vismask&0xC0) { if(vismask&0x80) loopj(6) gentris(cu[i], j, co, size, NULL, vismask); else loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } } } - else if(escaped&(1<<i)) - { + else if(escaped&(1<<i)) { ivec co(i, o, size); if(cu[i].children) findescaped(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } @@ -573,45 +459,37 @@ struct decalrenderer } }; -decalrenderer decals[] = -{ +decalrenderer decals[] = { decalrenderer("<grey>packages/particles/scorch.png", DF_ROTATE, 500), decalrenderer("<grey>packages/particles/blood.png", DF_RND4|DF_ROTATE|DF_INVMOD), decalrenderer("<grey>packages/particles/bullet.png", DF_OVERBRIGHT) }; -void initdecals() -{ +void initdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].init(maxdecaltris); } -void cleardecals() -{ +void cleardecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleardecals(); } -void cleanupdecals() -{ +void cleanupdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleanup(); } VARNP(decals, showdecals, 0, 1, 1); -void renderdecals(bool mainpass) -{ +void renderdecals(bool mainpass) { bool rendered = false; - loopi(sizeof(decals)/sizeof(decals[0])) - { + loopi(sizeof(decals)/sizeof(decals[0])) { decalrenderer &d = decals[i]; - if(mainpass) - { + if(mainpass) { d.clearfadeddecals(); d.fadeindecals(); d.fadeoutdecals(); } if(!showdecals || !d.hasdecals()) continue; - if(!rendered) - { + if(!rendered) { rendered = true; decalrenderer::setuprenderstate(); } @@ -623,8 +501,7 @@ void renderdecals(bool mainpass) VARP(maxdecaldistance, 1, 512, 10000); -void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) -{ +void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) { if(!showdecals || type<0 || (size_t)type>=sizeof(decals)/sizeof(decals[0]) || center.dist(camera1->o) - radius > maxdecaldistance) return; decalrenderer &d = decals[type]; d.adddecal(center, surface, radius, color, info); |
