#include "cube.h" int wx1, wy1, wx2, wy2; float wsx1, wsy1, wsx2, wsy2; VARP(watersubdiv, 1, 4, 64); VARF(waterlevel, -128, -128, 127, if(!noteditmode("waterlevel")) hdr.waterlevel = waterlevel); void setwatercolor(const char *r, const char *g, const char *b, const char *a) { if(r[0]) { hdr.watercolor[0] = ATOI(r); hdr.watercolor[1] = ATOI(g); hdr.watercolor[2] = ATOI(b); hdr.watercolor[3] = a[0] ? ATOI(a) : 178; } else { hdr.watercolor[0] = 20; hdr.watercolor[1] = 25; hdr.watercolor[2] = 20; hdr.watercolor[3] = 178; } } COMMANDN(watercolour, setwatercolor, ARG_4STR); // renders water for bounding rect area that contains water... simple but very inefficient #define VERTW(vertw, body) \ inline void vertw(float v1, float v2, float v3, float t) \ { \ float angle = v1*v2*0.1f + t; \ float h = 0.3f*sinf(angle); \ body; \ glVertex3f(v1, v2, v3+h); \ } #define VERTWT(vertwt, body) VERTW(vertwt, { float v = cosf(angle); float duv = 0.2f*v; body; }) VERTW(vertw, {}) VERTW(vertwc, { float v = cosf(angle); glColor4ub(hdr.watercolor[0], hdr.watercolor[1], hdr.watercolor[2], (uchar)(hdr.watercolor[3] + (max(v, 0.0f) - 0.5f)*51.0f)); }) VERTWT(vertwt, { glTexCoord3f(v1+duv, v2+duv, v3+h); }) VERTWT(vertwtc, { glColor4f(1, 1, 1, 0.15f + max(v, 0.0f)*0.15f); glTexCoord3f(v1+duv, v2+duv, v3+h); }) VERTWT(vertwmtc, { glColor4f(1, 1, 1, 0.15f + max(v, 0.0f)*0.15f); glMultiTexCoord3f_(GL_TEXTURE0_ARB, v1-duv, v2+duv, v3+h); glMultiTexCoord3f_(GL_TEXTURE1_ARB, v1+duv, v2+duv, v3+h); }) extern int nquads; #define renderwaterstrips(vertw, hf, t) \ for(int x = wx1; x=2 && reflecttex) { if(refracttex) { setupmultitexrefract(reflecttex, refracttex); renderwaterstrips(vertwmtc, hf, t); } else { setupmultitexreflect(reflecttex); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_SRC_ALPHA); renderwaterstrips(vertwtc, hf, t); glDisable(GL_BLEND); glDepthMask(GL_TRUE); } cleanupmultitex(reflecttex, refracttex); return nquads; } if(!refracttex) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); } glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if(reflecttex) { if(!refracttex) { glColor4ubv(hdr.watercolor); renderwaterstrips(vertw, hf, t); glEnable(GL_TEXTURE_2D); } setprojtexmatrix(); glBindTexture(GL_TEXTURE_2D, refracttex ? refracttex : reflecttex); } if(refracttex) { glColor3f(1, 1, 1); renderwaterstrips(vertwt, hf, t); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, reflecttex); glDepthMask(GL_TRUE); } if(reflecttex) { renderwaterstrips(vertwtc, hf, t); } else { renderwaterstrips(vertwc, hf, t); } if(reflecttex) { glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } else glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); if(!refracttex) glDepthMask(GL_TRUE); return nquads; } void addwaterquad(int x, int y, int size) // update bounding rect that contains water { int x2 = x+size; int y2 = y+size; if(wx1<0) { wx1 = x; wy1 = y; wx2 = x2; wy2 = y2; } else { if(xwx2) wx2 = x2; if(y2>wy2) wy2 = y2; } } void calcwaterscissor() { vec4 v[4]; float sx1 = 1, sy1 = 1, sx2 = -1, sy2 = -1; loopi(4) { vec4 &p = v[i]; mvpmatrix.transform(vec(i&1 ? wx2 : wx1, i&2 ? wy2 : wy1, hdr.waterlevel-0.3f), p); if(p.z >= 0) { 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) { sx1 = sy1 = -1; sx2 = sy2 = 1; } else loopi(4) { const vec4 &p = v[i]; if(p.z >= 0) continue; loopj(2) { const vec4 &o = v[i^(1<