LCOV - code coverage report
Current view: top level - engine/render - water.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 0 490 0.0 %
Date: 2024-11-22 05:07:59 Functions: 0 58 0.0 %

          Line data    Source code
       1             : /* water.cpp: rendering of water special effects
       2             :  *
       3             :  * water is a special material to render because of its dynamic effects caused
       4             :  * by the surface moving over time, and as a result has its own implementations
       5             :  * for special water functionality
       6             :  *
       7             :  * implemented are caustics, (light/dark areas on underwater surfaces due to lensing)
       8             :  * screenspace reflection, to capture the reflective surface, dynamic water surface
       9             :  * geometry, and dynamic waterfalls
      10             :  */
      11             : #include "../libprimis-headers/cube.h"
      12             : #include "../../shared/geomexts.h"
      13             : #include "../../shared/glemu.h"
      14             : #include "../../shared/glexts.h"
      15             : 
      16             : #include "octarender.h"
      17             : #include "rendergl.h"
      18             : #include "renderlights.h"
      19             : #include "shader.h"
      20             : #include "shaderparam.h"
      21             : #include "texture.h"
      22             : #include "water.h"
      23             : 
      24             : #include "interface/control.h"
      25             : 
      26             : #include "world/material.h"
      27             : #include "world/octaworld.h"
      28             : #include "world/world.h"
      29             : 
      30             : // ======================= caustics ===================== //
      31             : 
      32             : //caustics: lightening on surfaces underwater due to lensing effects from an
      33             : // uneven water surface
      34             : 
      35             : namespace
      36             : {
      37             :     constexpr int numcaustics = 32; //number of separate caustics textures to load
      38             :     Texture *caustictex[numcaustics] = {nullptr};
      39           0 :     VARFR(causticscale, 0, 50, 10000, preloadwatershaders());
      40           0 :     VARFR(causticmillis, 0, 75, 1000, preloadwatershaders()); //milliseconds between caustics frames
      41             :     FVARR(causticcontrast, 0, 0.6f, 2);
      42             :     FVARR(causticoffset, 0, 0.7f, 1);
      43             : 
      44           0 :     void setupcaustics(int tmu, float surface = -1e16f)
      45             :     {
      46           0 :         if(!caustictex[0])
      47             :         {
      48           0 :             loadcaustics(true);
      49             :         }
      50           0 :         vec s = vec(0.011f, 0, 0.0066f).mul(100.0f/causticscale),
      51           0 :             t = vec(0, 0.011f, 0.0066f).mul(100.0f/causticscale);
      52           0 :         int tex = (lastmillis/causticmillis)%numcaustics;
      53           0 :         float frac = static_cast<float>(lastmillis%causticmillis)/causticmillis;
      54           0 :         for(int i = 0; i < 2; ++i)
      55             :         {
      56           0 :             glActiveTexture(GL_TEXTURE0+tmu+i);
      57           0 :             glBindTexture(GL_TEXTURE_2D, caustictex[(tex+i)%numcaustics]->id);
      58             :         }
      59           0 :         glActiveTexture(GL_TEXTURE0);
      60           0 :         float blendscale = causticcontrast,
      61           0 :               blendoffset = 1;
      62           0 :         if(surface > -1e15f)
      63             :         {
      64           0 :             float bz = surface + camera1->o.z + (vertwater ? wateramplitude : 0);
      65           0 :             matrix4 m(vec4<float>(s.x, t.x,  0, 0),
      66           0 :                       vec4<float>(s.y, t.y,  0, 0),
      67           0 :                       vec4<float>(s.z, t.z, -1, 0),
      68           0 :                       vec4<float>(  0,   0, bz, 1));
      69           0 :             m.mul(worldmatrix);
      70           0 :             GLOBALPARAM(causticsmatrix, m);
      71           0 :             blendscale *= 0.5f;
      72           0 :             blendoffset = 0;
      73             :         }
      74             :         else
      75             :         {
      76           0 :             GLOBALPARAM(causticsS, s);
      77           0 :             GLOBALPARAM(causticsT, t);
      78             :         }
      79           0 :         GLOBALPARAMF(causticsblend, blendscale*(1-frac), blendscale*frac, blendoffset - causticoffset*blendscale);
      80           0 :     }
      81             : 
      82           0 :     VARFP(caustics, 0, 1, 1, { loadcaustics(); preloadwatershaders(); });
      83             : 
      84           0 :     void rendercaustics(float surface, float syl, float syr)
      85             :     {
      86           0 :         if(!caustics || !causticscale || !causticmillis)
      87             :         {
      88           0 :             return;
      89             :         }
      90           0 :         glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
      91           0 :         setupcaustics(0, surface);
      92           0 :         SETSHADER(caustics);
      93           0 :         gle::defvertex(2);
      94           0 :         gle::begin(GL_TRIANGLE_STRIP);
      95           0 :         gle::attribf(1, -1);
      96           0 :         gle::attribf(-1, -1);
      97           0 :         gle::attribf(1, syr);
      98           0 :         gle::attribf(-1, syl);
      99           0 :         gle::end();
     100             :     }
     101             : }
     102             : 
     103           0 : void loadcaustics(bool force)
     104             : {
     105             :     static bool needcaustics = false;
     106           0 :     if(force)
     107             :     {
     108           0 :         needcaustics = true;
     109             :     }
     110           0 :     if(!caustics || !needcaustics)
     111             :     {
     112           0 :         return;
     113             :     }
     114           0 :     useshaderbyname("caustics");
     115           0 :     if(caustictex[0])
     116             :     {
     117           0 :         return;
     118             :     }
     119           0 :     for(int i = 0; i < numcaustics; ++i)
     120             :     {
     121           0 :         DEF_FORMAT_STRING(name, "<grey><noswizzle>media/texture/mat_water/caustic/caust%.2d.png", i);
     122           0 :         caustictex[i] = textureload(name);
     123             :     }
     124             : }
     125             : 
     126             : /* vertex water */
     127             : 
     128             : // vertex water refers to the ability for the engine to dynamically create geom
     129             : // for the water material's surface, to simulate waviness directly by creating
     130             : // 3d geometry
     131             : 
     132             : //these variables control the vertex water geometry intensity
     133             : //(nothing to do with any other rendering)
     134             : VARP(watersubdiv, 0, 3, 3); //gridpower of water geometry
     135             : VARP(waterlod, 0, 1, 3);    //larger means that geometry is finer for longer distances
     136           0 : VARFP(vertwater, 0, 1, 1, rootworld.allchanged());
     137             : 
     138             : namespace
     139             : {
     140             :     int wx1, wy1, wx2, wy2, wsize;
     141             : 
     142             :     float wxscale = 1.0f,
     143             :           wyscale = 1.0f;
     144             : 
     145           0 :     void defvertwt()
     146             :     {
     147           0 :         gle::defvertex();
     148           0 :         gle::deftexcoord0();
     149           0 :     }
     150             : 
     151           0 :     void vertwt(float v1, float v2, float v3, float whscale, float whoffset)
     152             :     {
     153           0 :         float angle = (v1 - wx1) * (v2 - wy1) * (v1 - wx2) * (v2 - wy2) * whscale + whoffset;
     154           0 :         float s = angle - static_cast<int>(angle) - 0.5f; s *= 8 - std::fabs(s)*16;
     155           0 :         float h = wateramplitude*s-wateroffset;
     156           0 :         gle::attribf(v1, v2, v3+h);
     157           0 :         gle::attribf(wxscale*v1, wyscale*v2);
     158           0 :     }
     159             : 
     160           0 :     void defvertwtn()
     161             :     {
     162           0 :         gle::defvertex();
     163           0 :         gle::deftexcoord0();
     164           0 :     }
     165             : 
     166           0 :     void vertwtn(float v1, float v2, float v3)
     167             :     {
     168           0 :         float h = -wateroffset;
     169           0 :         gle::attribf(v1, v2, v3+h);
     170           0 :         gle::attribf(wxscale*v1, wyscale*v2);
     171           0 :     }
     172             : 
     173           0 :     void rendervertwater(int subdiv, int xo, int yo, int z, int size, int mat)
     174             :     {
     175           0 :         wx1 = xo;
     176           0 :         wy1 = yo;
     177           0 :         wx2 = wx1 + size,
     178           0 :         wy2 = wy1 + size;
     179           0 :         wsize = size;
     180           0 :         float whscale = 59.0f/(23.0f*wsize*wsize)/(2*M_PI); //59, 23 magic numbers
     181           0 :         if(mat == Mat_Water)
     182             :         {
     183           0 :             float whoffset = std::fmod(static_cast<float>(lastmillis/600.0f/(2*M_PI)), 1.0f);
     184           0 :             defvertwt();
     185           0 :             gle::begin(GL_TRIANGLE_STRIP, 2*(wy2-wy1 + 1)*(wx2-wx1)/subdiv);
     186           0 :             for(int x = wx1; x<wx2; x += subdiv)
     187             :             {
     188           0 :                 vertwt(x,        wy1, z, whscale, whoffset);
     189           0 :                 vertwt(x+subdiv, wy1, z, whscale, whoffset);
     190           0 :                 for(int y = wy1; y<wy2; y += subdiv)
     191             :                 {
     192           0 :                     vertwt(x,        y+subdiv, z, whscale, whoffset);
     193           0 :                     vertwt(x+subdiv, y+subdiv, z, whscale, whoffset);
     194             :                 }
     195           0 :                 gle::multidraw();
     196             :             }
     197           0 :             xtraverts += gle::end();
     198             :         }
     199           0 :     }
     200             : 
     201           0 :     int calcwatersubdiv(int x, int y, int z, int size)
     202             :     {
     203             :         float dist;
     204           0 :         if(camera1->o.x >= x && camera1->o.x < x + size &&
     205           0 :            camera1->o.y >= y && camera1->o.y < y + size)
     206             :         {
     207           0 :             dist = std::fabs(camera1->o.z - static_cast<float>(z));
     208             :         }
     209             :         else
     210             :         {
     211           0 :             dist = vec(x + size/2, y + size/2, z + size/2).dist(camera1->o) - size*1.42f/2;
     212             :         }
     213           0 :         int subdiv = watersubdiv + static_cast<int>(dist) / (32 << waterlod);
     214           0 :         return subdiv >= 31 ? INT_MAX : 1<<subdiv;
     215             :     }
     216             : 
     217           0 :     int renderwaterlod(int x, int y, int z, int size, int mat)
     218             :     {
     219           0 :         if(size <= (32 << waterlod))
     220             :         {
     221           0 :             int subdiv = calcwatersubdiv(x, y, z, size);
     222           0 :             if(subdiv < size * 2)
     223             :             {
     224           0 :                 rendervertwater(std::min(subdiv, size), x, y, z, size, mat);
     225             :             }
     226           0 :             return subdiv;
     227             :         }
     228             :         else
     229             :         {
     230           0 :             int subdiv = calcwatersubdiv(x, y, z, size);
     231           0 :             if(subdiv >= size)
     232             :             {
     233           0 :                 if(subdiv < size * 2)
     234             :                 {
     235           0 :                     rendervertwater(size, x, y, z, size, mat);
     236             :                 }
     237           0 :                 return subdiv;
     238             :             }
     239           0 :             int childsize = size / 2,
     240           0 :                 subdiv1 = renderwaterlod(x, y, z, childsize, mat),
     241           0 :                 subdiv2 = renderwaterlod(x + childsize, y, z, childsize, mat),
     242           0 :                 subdiv3 = renderwaterlod(x + childsize, y + childsize, z, childsize, mat),
     243           0 :                 subdiv4 = renderwaterlod(x, y + childsize, z, childsize, mat),
     244           0 :                 minsubdiv = subdiv1;
     245           0 :             minsubdiv = std::min(minsubdiv, subdiv2);
     246           0 :             minsubdiv = std::min(minsubdiv, subdiv3);
     247           0 :             minsubdiv = std::min(minsubdiv, subdiv4);
     248           0 :             if(minsubdiv < size * 2)
     249             :             {
     250           0 :                 if(minsubdiv >= size)
     251             :                 {
     252           0 :                     rendervertwater(size, x, y, z, size, mat);
     253             :                 }
     254             :                 else
     255             :                 {
     256           0 :                     if(subdiv1 >= size)
     257             :                     {
     258           0 :                         rendervertwater(childsize, x, y, z, childsize, mat);
     259             :                     }
     260           0 :                     if(subdiv2 >= size)
     261             :                     {
     262           0 :                         rendervertwater(childsize, x + childsize, y, z, childsize, mat);
     263             :                     }
     264           0 :                     if(subdiv3 >= size)
     265             :                     {
     266           0 :                         rendervertwater(childsize, x + childsize, y + childsize, z, childsize, mat);
     267             :                     }
     268           0 :                     if(subdiv4 >= size)
     269             :                     {
     270           0 :                         rendervertwater(childsize, x, y + childsize, z, childsize, mat);
     271             :                     }
     272             :                 }
     273             :             }
     274           0 :             return minsubdiv;
     275             :         }
     276             :     }
     277             : 
     278             :     /* renderflatwater: renders water with no vertex water subdivision
     279             :      */
     280           0 :     void renderflatwater(int x, int y, int z, int rsize, int csize, int mat)
     281             :     {
     282           0 :         if(mat == Mat_Water)
     283             :         {
     284           0 :             if(gle::attribbuf.empty())
     285             :             {
     286           0 :                 defvertwtn();
     287           0 :                 gle::begin(GL_TRIANGLE_FAN);
     288             :             }
     289           0 :             vertwtn(x, y, z);
     290           0 :             vertwtn(x+rsize, y, z);
     291           0 :             vertwtn(x+rsize, y+csize, z);
     292           0 :             vertwtn(x, y+csize, z);
     293           0 :             xtraverts += 4;
     294             :         }
     295           0 :     }
     296             : 
     297           0 :     void renderwater(const materialsurface &m, int mat = Mat_Water)
     298             :     {
     299           0 :         if(!vertwater || drawtex == Draw_TexMinimap)
     300             :         {
     301           0 :             renderflatwater(m.o.x, m.o.y, m.o.z, m.rsize, m.csize, mat);
     302             :         }
     303           0 :         else if(renderwaterlod(m.o.x, m.o.y, m.o.z, m.csize, mat) >= static_cast<int>(m.csize) * 2)
     304             :         {
     305           0 :             rendervertwater(m.csize, m.o.x, m.o.y, m.o.z, m.csize, mat);
     306             :         }
     307           0 :     }
     308             : 
     309             :     //==================================================================== WATERVARS
     310             :     #define WATERVARS(name) \
     311             :         CVAR0R(name##color, 0x01212C); \
     312             :         CVAR0R(name##deepcolor, 0x010A10); \
     313             :         CVAR0R(name##deepfade, 0x60BFFF); \
     314             :         CVAR0R(name##refractcolor, 0xFFFFFF); \
     315             :         VARR(name##fog, 0, 30, 10000); \
     316             :         VARR(name##deep, 0, 50, 10000); \
     317             :         VARR(name##spec, 0, 150, 200); \
     318             :         FVARR(name##refract, 0, 0.1f, 1e3f); \
     319             :         CVARR(name##fallcolor, 0); \
     320             :         CVARR(name##fallrefractcolor, 0); \
     321             :         VARR(name##fallspec, 0, 150, 200); \
     322             :         FVARR(name##fallrefract, 0, 0.1f, 1e3f);
     323             : 
     324           0 :     WATERVARS(water)
     325           0 :     WATERVARS(water2)
     326           0 :     WATERVARS(water3)
     327           0 :     WATERVARS(water4)
     328             : 
     329             : #undef WATERVARS
     330             : //==============================================================================
     331             : 
     332           0 :     VARFP(waterreflect, 0, 1, 1, { preloadwatershaders(); });
     333             : }
     334             : 
     335           0 : GETMATIDXVAR(water, color, const bvec &)
     336           0 : GETMATIDXVAR(water, deepcolor, const bvec &)
     337           0 : GETMATIDXVAR(water, deepfade, const bvec &)
     338           0 : GETMATIDXVAR(water, refractcolor, const bvec &)
     339           0 : GETMATIDXVAR(water, fallcolor, const bvec &)
     340           0 : GETMATIDXVAR(water, fallrefractcolor, const bvec &)
     341           0 : GETMATIDXVAR(water, fog, int)
     342           0 : GETMATIDXVAR(water, deep, int)
     343           0 : GETMATIDXVAR(water, spec, int)
     344           0 : GETMATIDXVAR(water, refract, float)
     345           0 : GETMATIDXVAR(water, fallspec, int)
     346           0 : GETMATIDXVAR(water, fallrefract, float)
     347             : 
     348             : VARR(waterreflectstep, 1, 32, 10000);
     349             : 
     350           0 : void GBuffer::renderwaterfog(int mat, float surface)
     351             : {
     352           0 :     glDepthFunc(GL_NOTEQUAL);
     353           0 :     glDepthMask(GL_FALSE);
     354           0 :     glDepthRange(1, 1);
     355             : 
     356           0 :     glEnable(GL_BLEND);
     357             : 
     358           0 :     glActiveTexture(GL_TEXTURE9);
     359           0 :     if(msaalight)
     360             :     {
     361           0 :         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msdepthtex);
     362             :     }
     363             :     else
     364             :     {
     365           0 :         glBindTexture(GL_TEXTURE_RECTANGLE, gdepthtex);
     366             :     }
     367           0 :     glActiveTexture(GL_TEXTURE0);
     368             : 
     369           0 :     matrix4 invcamprojmatrix = camprojmatrix.inverse();
     370             :     vec p[4] =
     371             :     {
     372           0 :         invcamprojmatrix.perspectivetransform(vec(-1, -1, -1)),
     373           0 :         invcamprojmatrix.perspectivetransform(vec(-1, 1, -1)),
     374           0 :         invcamprojmatrix.perspectivetransform(vec(1, -1, -1)),
     375           0 :         invcamprojmatrix.perspectivetransform(vec(1, 1, -1))
     376           0 :     };
     377           0 :     float bz = surface + camera1->o.z + (vertwater ? wateramplitude : 0),
     378           0 :           syl = (p[1].z > p[0].z) ? (2*(bz - p[0].z)/(p[1].z - p[0].z) - 1) : 1,
     379           0 :           syr = (p[3].z > p[2].z) ? (2*(bz - p[2].z)/(p[3].z - p[2].z) - 1) : 1;
     380             : 
     381           0 :     if((mat&MatFlag_Volume) == Mat_Water)
     382             :     {
     383           0 :         const bvec &deepcolor = getwaterdeepcolor(mat);
     384           0 :         int deep = getwaterdeep(mat);
     385           0 :         GLOBALPARAMF(waterdeepcolor, deepcolor.x*ldrscaleb(), deepcolor.y*ldrscaleb(), deepcolor.z*ldrscaleb());
     386           0 :         vec deepfade = getwaterdeepfade(mat).tocolor().mul(deep);
     387           0 :         GLOBALPARAMF(waterdeepfade,
     388             :             deepfade.x ? calcfogdensity(deepfade.x) : -1e4f,
     389             :             deepfade.y ? calcfogdensity(deepfade.y) : -1e4f,
     390             :             deepfade.z ? calcfogdensity(deepfade.z) : -1e4f,
     391             :             deep ? calcfogdensity(deep) : -1e4f);
     392             : 
     393           0 :         rendercaustics(surface, syl, syr);
     394             :     }
     395             :     else
     396             :     {
     397           0 :         GLOBALPARAMF(waterdeepcolor, 0, 0, 0);
     398           0 :         GLOBALPARAMF(waterdeepfade, -1e4f, -1e4f, -1e4f, -1e4f);
     399             :     }
     400             : 
     401           0 :     GLOBALPARAMF(waterheight, bz);
     402             : 
     403           0 :     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     404             : 
     405           0 :     SETSHADER(waterfog);
     406           0 :     gle::defvertex(3);
     407           0 :     gle::begin(GL_TRIANGLE_STRIP);
     408           0 :     gle::attribf( 1, -1,  1);
     409           0 :     gle::attribf(-1, -1,  1);
     410           0 :     gle::attribf( 1, syr, 1);
     411           0 :     gle::attribf(-1, syl, 1);
     412           0 :     gle::end();
     413             : 
     414           0 :     glDisable(GL_BLEND);
     415             : 
     416           0 :     glDepthFunc(GL_LESS);
     417           0 :     glDepthMask(GL_TRUE);
     418           0 :     glDepthRange(0, 1);
     419           0 : }
     420             : 
     421           0 : void preloadwatershaders(bool force)
     422             : {
     423             :     static bool needwater = false;
     424           0 :     if(force)
     425             :     {
     426           0 :         needwater = true;
     427             :     }
     428           0 :     if(!needwater)
     429             :     {
     430           0 :         return;
     431             :     }
     432           0 :     if(caustics && causticscale && causticmillis)
     433             :     {
     434           0 :         if(waterreflect)
     435             :         {
     436           0 :             useshaderbyname("waterreflectcaustics");
     437             :         }
     438             :         else
     439             :         {
     440           0 :             useshaderbyname("watercaustics");
     441             :         }
     442             :     }
     443             :     else
     444             :     {
     445           0 :         if(waterreflect)
     446             :         {
     447           0 :             useshaderbyname("waterreflect");
     448             :         }
     449             :         else
     450             :         {
     451           0 :             useshaderbyname("water");
     452             :         }
     453             :     }
     454           0 :     useshaderbyname("underwater");
     455           0 :     useshaderbyname("waterfall");
     456           0 :     useshaderbyname("waterfog");
     457           0 :     useshaderbyname("waterminimap");
     458             : }
     459             : 
     460             : static float wfwave = 0.0f, //waterfall wave
     461             :              wfscroll = 0.0f, //waterfall scroll
     462             :              wfxscale = 1.0f, //waterfall x scale
     463             :              wfyscale = 1.0f; //waterfall y scale
     464             : 
     465             : //"waterfall" refers to any rendered side of water material
     466           0 : static void renderwaterfall(const materialsurface &m, float offset, vec normal = vec(0,0,0))
     467             : {
     468           0 :     if(gle::attribbuf.empty())
     469             :     {
     470           0 :         gle::defvertex();
     471           0 :         if(normal != vec(0,0,0))
     472             :         {
     473           0 :             gle::defnormal();
     474             :         }
     475           0 :         gle::deftexcoord0();
     476             :     }
     477           0 :     float x = m.o.x,
     478           0 :           y = m.o.y,
     479           0 :           zmin = m.o.z,
     480           0 :           zmax = zmin;
     481           0 :     if(m.ends&1)
     482             :     {
     483           0 :         zmin += -wateroffset-wateramplitude;
     484             :     }
     485           0 :     if(m.ends&2)
     486             :     {
     487           0 :         zmax += wfwave;
     488             :     }
     489           0 :     int csize = m.csize,
     490           0 :         rsize = m.rsize;
     491           0 :     if(normal != vec(0,0,0))
     492             :     {
     493           0 :         vec n = normal;
     494           0 :         switch(m.orient)
     495             :         {
     496           0 :             case 0:
     497             :             {
     498           0 :                 gle::begin(GL_TRIANGLE_FAN);
     499             :                 {
     500           0 :                     vec v(x + offset, y + rsize, zmax + csize);
     501           0 :                     gle::attribf(v.x, v.y, v.z);
     502           0 :                     gle::attribf(n.x, n.y, n.z);
     503           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     504             :                 }
     505             :                 {
     506           0 :                     vec v(x + offset, y + rsize, zmin );
     507           0 :                     gle::attribf(v.x, v.y, v.z);
     508           0 :                     gle::attribf(n.x, n.y, n.z);
     509           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     510             :                 }
     511             :                 {
     512           0 :                     vec v(x + offset, y , zmin );
     513           0 :                     gle::attribf(v.x, v.y, v.z);
     514           0 :                     gle::attribf(n.x, n.y, n.z);
     515           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     516             :                 }
     517             :                 {
     518           0 :                     vec v(x + offset, y , zmax + csize);
     519           0 :                     gle::attribf(v.x, v.y, v.z);
     520           0 :                     gle::attribf(n.x, n.y, n.z);
     521           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     522             :                 }
     523           0 :                 gle::end();
     524           0 :                 break;
     525             :             }
     526           0 :             case 1:
     527             :             {
     528           0 :                 gle::begin(GL_TRIANGLE_FAN);
     529             :                 {
     530           0 :                     vec v(x - offset, y + rsize, zmax + csize);
     531           0 :                     gle::attribf(v.x, v.y, v.z);
     532           0 :                     gle::attribf(n.x, n.y, n.z);
     533           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     534             :                 }
     535             :                 {
     536           0 :                     vec v(x - offset, y , zmax + csize);
     537           0 :                     gle::attribf(v.x, v.y, v.z);
     538           0 :                     gle::attribf(n.x, n.y, n.z);
     539           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     540             :                 }
     541             :                 {
     542           0 :                     vec v(x - offset, y , zmin );
     543           0 :                     gle::attribf(v.x, v.y, v.z);
     544           0 :                     gle::attribf(n.x, n.y, n.z);
     545           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     546             :                 }
     547             :                 {
     548           0 :                     vec v(x - offset, y + rsize, zmin );
     549           0 :                     gle::attribf(v.x, v.y, v.z);
     550           0 :                     gle::attribf(n.x, n.y, n.z);
     551           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     552             :                 }
     553           0 :                 gle::end();
     554           0 :                 break;
     555             :             }
     556           0 :             case 2:
     557             :             {
     558           0 :                 gle::begin(GL_TRIANGLE_FAN);
     559             :                 {
     560           0 :                     vec v(x + csize, y + offset, zmax + rsize);
     561           0 :                     gle::attribf(v.x, v.y, v.z);
     562           0 :                     gle::attribf(n.x, n.y, n.z);
     563           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     564             :                 }
     565             :                 {
     566           0 :                     vec v(x , y + offset, zmax + rsize);
     567           0 :                     gle::attribf(v.x, v.y, v.z);
     568           0 :                     gle::attribf(n.x, n.y, n.z);
     569           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     570             :                 }
     571             :                 {
     572           0 :                     vec v(x , y + offset, zmin );
     573           0 :                     gle::attribf(v.x, v.y, v.z);
     574           0 :                     gle::attribf(n.x, n.y, n.z);
     575           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     576             :                 }
     577             :                 {
     578           0 :                     vec v(x + csize, y + offset, zmin );
     579           0 :                     gle::attribf(v.x, v.y, v.z);
     580           0 :                     gle::attribf(n.x, n.y, n.z);
     581           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     582             :                 }
     583           0 :                 gle::end();
     584           0 :                 break;
     585             :             }
     586           0 :             case 3:
     587             :             {
     588           0 :                 gle::begin(GL_TRIANGLE_FAN);
     589             :                 {
     590           0 :                     vec v(x , y - offset, zmin );
     591           0 :                     gle::attribf(v.x, v.y, v.z);
     592           0 :                     gle::attribf(n.x, n.y, n.z);
     593           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     594             :                 }
     595             :                 {
     596           0 :                     vec v(x , y - offset, zmax + rsize);
     597           0 :                     gle::attribf(v.x, v.y, v.z);
     598           0 :                     gle::attribf(n.x, n.y, n.z);
     599           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     600             :                 }
     601             :                 {
     602           0 :                     vec v(x + csize, y - offset, zmax + rsize);
     603           0 :                     gle::attribf(v.x, v.y, v.z);
     604           0 :                     gle::attribf(n.x, n.y, n.z);
     605           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     606             :                 }
     607             :                 {
     608           0 :                     vec v(x + csize, y - offset, zmin );
     609           0 :                     gle::attribf(v.x, v.y, v.z);
     610           0 :                     gle::attribf(n.x, n.y, n.z);
     611           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     612             :                 }
     613           0 :                 gle::end();
     614           0 :                 break;
     615             :             }
     616             :         }
     617             :     }
     618             :     else
     619             :     {
     620           0 :         switch(m.orient)
     621             :         {
     622           0 :             case 0:
     623             :             {
     624           0 :                 gle::begin(GL_TRIANGLE_FAN);
     625             :                 {
     626           0 :                     vec v(x + offset, y + rsize, zmax + csize);
     627           0 :                     gle::attribf(v.x, v.y, v.z);
     628           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     629             :                 }
     630             :                 {
     631           0 :                     vec v(x + offset, y + rsize, zmin );
     632           0 :                     gle::attribf(v.x, v.y, v.z);
     633           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     634             :                 }
     635             :                 {
     636           0 :                     vec v(x + offset, y , zmin );
     637           0 :                     gle::attribf(v.x, v.y, v.z);
     638           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     639             :                 }
     640             :                 {
     641           0 :                     vec v(x + offset, y , zmax + csize);
     642           0 :                     gle::attribf(v.x, v.y, v.z);
     643           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     644             :                 }
     645           0 :                 gle::end();
     646           0 :                 break;
     647             :             }
     648           0 :             case 1:
     649             :             {
     650           0 :                 gle::begin(GL_TRIANGLE_FAN);
     651             :                 {
     652           0 :                     vec v(x - offset, y + rsize, zmax + csize);
     653           0 :                     gle::attribf(v.x, v.y, v.z);
     654           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     655             :                 }
     656             :                 {
     657           0 :                     vec v(x - offset, y , zmax + csize);
     658           0 :                     gle::attribf(v.x, v.y, v.z);
     659           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     660             :                 }
     661             :                 {
     662           0 :                     vec v(x - offset, y , zmin );
     663           0 :                     gle::attribf(v.x, v.y, v.z);
     664           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     665             :                 }
     666             :                 {
     667           0 :                     vec v(x - offset, y + rsize, zmin );
     668           0 :                     gle::attribf(v.x, v.y, v.z);
     669           0 :                     gle::attribf(wfxscale*v.y, -wfyscale*(v.z+wfscroll));
     670             :                 }
     671           0 :                 gle::end();
     672           0 :                 break;
     673             :             }
     674           0 :             case 2:
     675             :             {
     676           0 :                 gle::begin(GL_TRIANGLE_FAN);
     677             :                 {
     678           0 :                     vec v(x + csize, y + offset, zmax + rsize);
     679           0 :                     gle::attribf(v.x, v.y, v.z);
     680           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     681             :                 }
     682             :                 {
     683           0 :                     vec v(x , y + offset, zmax + rsize);
     684           0 :                     gle::attribf(v.x, v.y, v.z);
     685           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     686             :                 }
     687             :                 {
     688           0 :                     vec v(x , y + offset, zmin);
     689           0 :                     gle::attribf(v.x, v.y, v.z);
     690           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     691             :                 }
     692             :                 {
     693           0 :                     vec v(x + csize, y + offset, zmin);
     694           0 :                     gle::attribf(v.x, v.y, v.z);
     695           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     696             :                 }
     697           0 :                 gle::end();
     698           0 :                 break;
     699             :             }
     700           0 :             case 3:
     701             :             {
     702           0 :                 gle::begin(GL_TRIANGLE_FAN);
     703             :                 {
     704           0 :                     vec v(x , y - offset, zmin);
     705           0 :                     gle::attribf(v.x, v.y, v.z);
     706           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     707             :                 }
     708             :                 {
     709           0 :                     vec v(x , y - offset, zmax + rsize);
     710           0 :                     gle::attribf(v.x, v.y, v.z);
     711           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     712             :                 }
     713             :                 {
     714           0 :                     vec v(x + csize, y - offset, zmax + rsize);
     715           0 :                     gle::attribf(v.x, v.y, v.z);
     716           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     717             :                 }
     718             :                 {
     719           0 :                     vec v(x + csize, y - offset, zmin);
     720           0 :                     gle::attribf(v.x, v.y, v.z);
     721           0 :                     gle::attribf(wfxscale*v.x, -wfyscale*(v.z+wfscroll));
     722             :                 }
     723           0 :                 gle::end();
     724           0 :                 break;
     725             :             }
     726             :         }
     727             :     }
     728           0 : }
     729             : 
     730           0 : void renderwaterfalls()
     731             : {
     732           0 :     for(int k = 0; k < 4; ++k)
     733             :     {
     734           0 :         const std::vector<materialsurface> &surfs = waterfallsurfs[k];
     735           0 :         if(surfs.empty())
     736             :         {
     737           0 :             continue;
     738             :         }
     739           0 :         const MatSlot &wslot = lookupmaterialslot(Mat_Water+k);
     740             : 
     741           0 :         const Texture *tex = wslot.sts.size() > 2 ? wslot.sts[2].t : (wslot.sts.size() ? wslot.sts[0].t : notexture);
     742           0 :         float angle = std::fmod(static_cast<float>(lastmillis/600.0f/(2*M_PI)), 1.0f),
     743           0 :               s = angle - static_cast<int>(angle) - 0.5f;
     744           0 :         s *= 8 - std::fabs(s)*16;
     745           0 :         wfwave = vertwater ? wateramplitude*s-wateroffset : -wateroffset;
     746           0 :         wfscroll = 16.0f*lastmillis/1000.0f;
     747           0 :         wfxscale = defaulttexscale/(tex->xs*wslot.scale);
     748           0 :         wfyscale = defaulttexscale/(tex->ys*wslot.scale);
     749             :         //waterfall color vectors
     750           0 :         bvec color = getwaterfallcolor(k),
     751           0 :              refractcolor = getwaterfallrefractcolor(k);
     752           0 :         if(color.iszero())
     753             :         {
     754           0 :             color = getwatercolor(k);
     755             :         }
     756           0 :         if(refractcolor.iszero())
     757             :         {
     758           0 :             refractcolor = getwaterrefractcolor(k);
     759             :         }
     760           0 :         float colorscale = (0.5f/255),
     761           0 :               refractscale = colorscale/ldrscale,
     762           0 :               refract = getwaterfallrefract(k);
     763           0 :         int spec = getwaterfallspec(k);
     764           0 :         GLOBALPARAMF(waterfallcolor, color.x*colorscale, color.y*colorscale, color.z*colorscale);
     765           0 :         GLOBALPARAMF(waterfallrefract, refractcolor.x*refractscale, refractcolor.y*refractscale, refractcolor.z*refractscale, refract*viewh);
     766           0 :         GLOBALPARAMF(waterfallspec, spec/100.0f);
     767             : 
     768           0 :         SETSHADER(waterfall);
     769             : 
     770           0 :         glBindTexture(GL_TEXTURE_2D, tex->id);
     771           0 :         glActiveTexture(GL_TEXTURE1);
     772           0 :         glBindTexture(GL_TEXTURE_2D, wslot.sts.size() > 2 ? (wslot.sts.size() > 3 ? wslot.sts[3].t->id : notexture->id) : (wslot.sts.size() > 1 ? wslot.sts[1].t->id : notexture->id));
     773           0 :         glActiveTexture(GL_TEXTURE0);
     774           0 :         for(const materialsurface& m : surfs)
     775             :         {
     776           0 :             renderwaterfall(m, 0.1f, matnormals(m.orient));
     777             :         }
     778           0 :         xtraverts += gle::end();
     779             :     }
     780           0 : }
     781             : 
     782           0 : void renderwater()
     783             : {
     784           0 :     for(int k = 0; k < 4; ++k) //four types of water hardcoded
     785             :     {
     786           0 :         const std::vector<materialsurface> &surfs = watersurfs[k];
     787           0 :         if(surfs.empty())
     788             :         {
     789           0 :             continue;
     790             :         }
     791           0 :         const MatSlot &wslot = lookupmaterialslot(Mat_Water+k);
     792             : 
     793           0 :         const Texture *tex = wslot.sts.size() ? wslot.sts[0].t: notexture;
     794           0 :         wxscale = defaulttexscale/(tex->xs*wslot.scale);
     795           0 :         wyscale = defaulttexscale/(tex->ys*wslot.scale);
     796             : 
     797           0 :         glBindTexture(GL_TEXTURE_2D, tex->id);
     798           0 :         glActiveTexture(GL_TEXTURE1);
     799           0 :         glBindTexture(GL_TEXTURE_2D, wslot.sts.size() > 1 ? wslot.sts[1].t->id : notexture->id);
     800           0 :         if(caustics && causticscale && causticmillis)
     801             :         {
     802           0 :             setupcaustics(2);
     803             :         }
     804           0 :         glActiveTexture(GL_TEXTURE0);
     805             : 
     806           0 :         float colorscale = 0.5f/255,
     807           0 :               refractscale = colorscale/ldrscale,
     808           0 :               reflectscale = 0.5f/ldrscale;
     809           0 :         const bvec &color = getwatercolor(k),
     810           0 :                    &deepcolor = getwaterdeepcolor(k),
     811           0 :                    &refractcolor = getwaterrefractcolor(k);
     812           0 :         int fog = getwaterfog(k),
     813           0 :             deep = getwaterdeep(k),
     814           0 :             spec = getwaterspec(k);
     815           0 :         float refract = getwaterrefract(k);
     816           0 :         GLOBALPARAMF(watercolor, color.x*colorscale, color.y*colorscale, color.z*colorscale);
     817           0 :         GLOBALPARAMF(waterdeepcolor, deepcolor.x*colorscale, deepcolor.y*colorscale, deepcolor.z*colorscale);
     818           0 :         float fogdensity = fog ? calcfogdensity(fog) : -1e4f;
     819           0 :         GLOBALPARAMF(waterfog, fogdensity);
     820           0 :         vec deepfade = getwaterdeepfade(k).tocolor().mul(deep);
     821           0 :         GLOBALPARAMF(waterdeepfade,
     822             :             deepfade.x ? calcfogdensity(deepfade.x) : -1e4f,
     823             :             deepfade.y ? calcfogdensity(deepfade.y) : -1e4f,
     824             :             deepfade.z ? calcfogdensity(deepfade.z) : -1e4f,
     825             :             deep ? calcfogdensity(deep) : -1e4f);
     826           0 :         GLOBALPARAMF(waterspec, spec/100.0f);
     827           0 :         GLOBALPARAMF(waterreflect, reflectscale, reflectscale, reflectscale, waterreflectstep);
     828           0 :         GLOBALPARAMF(waterrefract, refractcolor.x*refractscale, refractcolor.y*refractscale, refractcolor.z*refractscale, refract*viewh);
     829             : 
     830             :         //======================================================= SETWATERSHADER
     831             :         #define SETWATERSHADER(which, name) \
     832             :         do { \
     833             :             static Shader *name##shader = nullptr; \
     834             :             if(!name##shader) \
     835             :             { \
     836             :                 name##shader = lookupshaderbyname(#name); \
     837             :             } \
     838             :             which##shader = name##shader; \
     839             :         } while(0)
     840             : 
     841           0 :         Shader *aboveshader = nullptr;
     842             :         //this if tree will select which shader is the water aboveshader depending on settings
     843           0 :         if(drawtex == Draw_TexMinimap)
     844             :         {
     845           0 :             SETWATERSHADER(above, waterminimap);
     846             :         }
     847           0 :         else if(caustics && causticscale && causticmillis) //caustics
     848             :         {
     849           0 :             if(waterreflect)
     850             :             {
     851           0 :                 SETWATERSHADER(above, waterreflectcaustics);
     852             :             }
     853             :             else
     854             :             {
     855           0 :                 SETWATERSHADER(above, watercaustics);
     856             :             }
     857           0 :         }
     858             :         else //no caustics
     859             :         {
     860           0 :             if(waterreflect)
     861             :             {
     862           0 :                 SETWATERSHADER(above, waterreflect);
     863             :             }
     864             :             else
     865             :             {
     866           0 :                 SETWATERSHADER(above, water);
     867             :             }
     868             :         }
     869             :         //now select the water belowshader
     870           0 :         Shader *belowshader = nullptr;
     871           0 :         if(drawtex != Draw_TexMinimap)
     872             :         {
     873           0 :             SETWATERSHADER(below, underwater); //if rendering water, and not rendering a minimap, sets belowshader to non-null
     874             :         }
     875             :         #undef SETWATERSHADER
     876             :         //======================================================================
     877             : 
     878           0 :         aboveshader->set();
     879           0 :         for(const materialsurface &m: surfs)
     880             :         {
     881           0 :             if(camera1->o.z < m.o.z - wateroffset)
     882             :             {
     883           0 :                 continue;
     884             :             }
     885           0 :             renderwater(m);
     886             :         }
     887           0 :         xtraverts += gle::end();
     888           0 :         if(belowshader)
     889             :         {
     890           0 :             belowshader->set();
     891           0 :             for(const materialsurface& m : surfs)
     892             :             {
     893           0 :                 if(camera1->o.z >= m.o.z - wateroffset)
     894             :                 {
     895           0 :                     continue;
     896             :                 }
     897           0 :                 renderwater(m);
     898             :             }
     899           0 :             xtraverts += gle::end();
     900             :         }
     901             :     }
     902           0 : }
     903             : 

Generated by: LCOV version 1.14