#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, "ssss"); FVAR(waveheight, 0, 0.3f, 1.0f); // renders water for bounding rect area that contains water... simple but very inefficient #define VERTW(vertw, defbody, body) \ static inline void def##vertw() \ { \ varray::defattrib(varray::ATTRIB_VERTEX, 3, GL_FLOAT); \ defbody; \ } \ inline void vertw(float v1, float v2, float v3, float t) \ { \ float angle = v1*v2*0.1f/(2*M_PI) + t; \ float s = angle - int(angle) - 0.5f; \ s *= 8 - fabs(s)*16; \ float h = waveheight*0.5f*s; \ varray::attrib(v1, v2, v3+h); \ body; \ } #define VERTWC(vertwc, defbody, body) \ VERTW(vertwc, defbody, { \ float v = angle - int(angle+0.25) - 0.25; \ v *= 8 - fabs(v)*16; \ body; \ }) #define VERTWT(vertwt, defbody, body) \ VERTWC(vertwt, defbody, { \ float duv = waveheight*0.5f*v; \ body; \ }) VERTW(vertw, {}, {}) VERTWC(vertwc, { varray::defattrib(varray::ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE); }, { varray::attrib(hdr.watercolor[0], hdr.watercolor[1], hdr.watercolor[2], (uchar)(hdr.watercolor[3] + (max(v, 0.0f) - 0.5f)*51.0f)); }) VERTWT(vertwt, { varray::defattrib(varray::ATTRIB_TEXCOORD0, 3, GL_FLOAT); }, { varray::attrib(v1+duv, v2+duv, v3+h); }) VERTWT(vertwtc, { varray::defattrib(varray::ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE); varray::defattrib(varray::ATTRIB_TEXCOORD0, 3, GL_FLOAT); }, { varray::attrib(255, 255, 255, uchar(38 + max(v, 0.0f)*38)); varray::attrib(v1+duv, v2+duv, v3+h); }) VERTWT(vertwmtc, { varray::defattrib(varray::ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE); varray::defattrib(varray::ATTRIB_TEXCOORD0, 3, GL_FLOAT); varray::defattrib(varray::ATTRIB_TEXCOORD1, 3, GL_FLOAT); }, { varray::attrib(255, 255, 255, uchar(38 + max(v, 0.0f)*38)); varray::attrib(v1-duv, v2+duv, v3+h); varray::attrib(v1+duv, v2+duv, v3+h); }) extern int nquads; #define renderwaterstrips(vertw, hf, t) \ def##vertw(); \ for(int x = wx1; x=2 && reflecttex) { varray::enable(); 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); varray::disable(); return nquads; } if(!refracttex) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); } glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); varray::enable(); 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); } varray::disable(); 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<