LCOV - code coverage report
Current view: top level - engine/render - renderalpha.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 201 0
Test Date: 2025-02-18 06:21:28 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /* renderalpha.cpp: alpha geoemtry rendering
       2              :  *
       3              :  * libprimis has support for a single level of alpha geometry, which is rendered
       4              :  * using a single stencil layer over the base geometry
       5              :  *
       6              :  * combinations of alpha materials (glass, alpha, water) therefore do not stack
       7              :  * since there is only one stencil and only the nearest layer in the view frustum
       8              :  * is rendered
       9              :  */
      10              : #include "../libprimis-headers/cube.h"
      11              : #include "../../shared/geomexts.h"
      12              : #include "../../shared/glexts.h"
      13              : 
      14              : #include "hdr.h"
      15              : #include "rendergl.h"
      16              : #include "renderlights.h"
      17              : #include "rendermodel.h"
      18              : #include "renderparticles.h"
      19              : #include "rendertimers.h"
      20              : #include "renderva.h"
      21              : #include "shader.h"
      22              : #include "shaderparam.h"
      23              : #include "stain.h"
      24              : #include "texture.h"
      25              : 
      26              : #include "world/material.h"
      27              : #include "world/octaedit.h"
      28              : 
      29              : //internally relevant functionality
      30              : namespace
      31              : {
      32              :     FVAR(refractmargin, 0, 0.1f, 1);     //margin for gl scissoring around refractive materials
      33              :     FVAR(refractdepth, 1e-3f, 16, 1e3f); //sets depth for refract shader effect
      34              : }
      35              : 
      36              : //sets up alpha handling as needed then executes main particle rendering routine
      37              : //private method of gbuffer
      38            0 : void GBuffer::alphaparticles(float allsx1, float allsy1, float allsx2, float allsy2) const
      39              : {
      40            0 :     if(particlelayers && ghasstencil)
      41              :     {
      42            0 :         bool scissor = allsx1 > -1 || allsy1 > -1 || allsx2 < 1 || allsy2 < 1;
      43            0 :         if(scissor)
      44              :         {
      45            0 :             int x1 = static_cast<int>(std::floor((allsx1*0.5f+0.5f)*static_cast<float>(vieww))),
      46            0 :                 y1 = static_cast<int>(std::floor((allsy1*0.5f+0.5f)*static_cast<float>(viewh))),
      47            0 :                 x2 = static_cast<int>(std::ceil((allsx2*0.5f+0.5f)*static_cast<float>(vieww))),
      48            0 :                 y2 = static_cast<int>(std::ceil((allsy2*0.5f+0.5f)*static_cast<float>(viewh)));
      49            0 :             glEnable(GL_SCISSOR_TEST);
      50            0 :             glScissor(x1, y1, x2 - x1, y2 - y1);
      51              :         }
      52            0 :         glStencilFunc(GL_NOTEQUAL, 0, 0x07);
      53            0 :         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
      54            0 :         glEnable(GL_STENCIL_TEST);
      55            0 :         renderparticles(ParticleLayer_Over);
      56            0 :         glDisable(GL_STENCIL_TEST);
      57            0 :         if(scissor)
      58              :         {
      59            0 :             glDisable(GL_SCISSOR_TEST);
      60              :         }
      61            0 :         renderparticles(ParticleLayer_NoLayer);
      62            0 :     }
      63              :     else
      64              :     {
      65            0 :         renderparticles();
      66              :     }
      67            0 : }
      68              : 
      69              : //externally relevant functionality
      70              : 
      71            0 : void GBuffer::rendertransparent()
      72              : {
      73            0 :     const MaterialInfo &mi = findmaterials(); //generate mat* vars
      74            0 :     const AlphaInfo &ai = findalphavas(); //generate mat* vars
      75            0 :     int hasalphavas = ai.hasalphavas;
      76            0 :     int hasmats = mi.hasmats;
      77            0 :     bool hasmodels = tmodelinfo.mdlsx1 < tmodelinfo.mdlsx2 && tmodelinfo.mdlsy1 < tmodelinfo.mdlsy2;
      78            0 :     if(!hasalphavas && !hasmats && !hasmodels) //don't transparent render if there is no alpha
      79              :     {
      80            0 :         if(!editmode)
      81              :         {
      82            0 :             renderparticles();
      83              :         }
      84            0 :         return;
      85              :     }
      86            0 :     if(!editmode && particlelayers && ghasstencil)
      87              :     {
      88            0 :         renderparticles(ParticleLayer_Under);
      89              :     }
      90            0 :     timer *transtimer = begintimer("transparent");
      91            0 :     if(hasalphavas&4 || hasmats&4)
      92              :     {
      93            0 :         glBindFramebuffer(GL_FRAMEBUFFER, msaalight ? msrefractfbo : refractfbo);
      94            0 :         glDepthMask(GL_FALSE);
      95            0 :         if(msaalight)
      96              :         {
      97            0 :             glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msdepthtex);
      98              :         }
      99              :         else
     100              :         {
     101            0 :             glBindTexture(GL_TEXTURE_RECTANGLE, gdepthtex);
     102              :         }
     103            0 :         float sx1 = std::min(ai.alpharefractsx1, mi.matrefractsx1),
     104            0 :               sy1 = std::min(ai.alpharefractsy1, mi.matrefractsy1),
     105            0 :               sx2 = std::max(ai.alpharefractsx2, mi.matrefractsx2),
     106            0 :               sy2 = std::max(ai.alpharefractsy2, mi.matrefractsy2);
     107            0 :         bool scissor = sx1 > -1 || sy1 > -1 || sx2 < 1 || sy2 < 1;
     108            0 :         if(scissor)
     109              :         {
     110            0 :             int x1 = static_cast<int>(std::floor(std::max(sx1*0.5f+0.5f-refractmargin*static_cast<float>(viewh)/static_cast<float>(vieww), 0.0f)*static_cast<float>(vieww))),
     111            0 :                 y1 = static_cast<int>(std::floor(std::max(sy1*0.5f+0.5f-refractmargin, 0.0f)*static_cast<float>(viewh))),
     112            0 :                 x2 = static_cast<int>(std::ceil(std::min(sx2*0.5f+0.5f+refractmargin*static_cast<float>(viewh)/static_cast<float>(vieww), 1.0f)*static_cast<float>(vieww))),
     113            0 :                 y2 = static_cast<int>(std::ceil(std::min(sy2*0.5f+0.5f+refractmargin, 1.0f)*static_cast<float>(viewh)));
     114            0 :             glEnable(GL_SCISSOR_TEST);
     115            0 :             glScissor(x1, y1, x2 - x1, y2 - y1);
     116              :         }
     117            0 :         glClearColor(0, 0, 0, 0);
     118            0 :         glClear(GL_COLOR_BUFFER_BIT);
     119            0 :         if(scissor)
     120              :         {
     121            0 :             glDisable(GL_SCISSOR_TEST);
     122              :         }
     123            0 :         GLOBALPARAMF(refractdepth, 1.0f/refractdepth);
     124            0 :         SETSHADER(refractmask,);
     125            0 :         if(hasalphavas&4)
     126              :         {
     127            0 :             renderrefractmask();
     128              :         }
     129            0 :         if(hasmats&4)
     130              :         {
     131            0 :             rendermaterialmask();
     132              :         }
     133            0 :         glDepthMask(GL_TRUE);
     134              :     }
     135              : 
     136            0 :     glActiveTexture(GL_TEXTURE7);
     137            0 :     if(msaalight)
     138              :     {
     139            0 :         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msrefracttex);
     140              :     }
     141              :     else
     142              :     {
     143            0 :         glBindTexture(GL_TEXTURE_RECTANGLE, refracttex);
     144              :     }
     145            0 :     glActiveTexture(GL_TEXTURE8);
     146            0 :     if(msaalight)
     147              :     {
     148            0 :         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
     149              :     }
     150              :     else
     151              :     {
     152            0 :         glBindTexture(GL_TEXTURE_RECTANGLE, hdrtex);
     153              :     }
     154            0 :     glActiveTexture(GL_TEXTURE9);
     155            0 :     if(msaalight)
     156              :     {
     157            0 :         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msdepthtex);
     158              :     }
     159              :     else
     160              :     {
     161            0 :         glBindTexture(GL_TEXTURE_RECTANGLE, gdepthtex);
     162              :     }
     163            0 :     glActiveTexture(GL_TEXTURE0);
     164            0 :     if(ghasstencil)
     165              :     {
     166            0 :         glEnable(GL_STENCIL_TEST);
     167              :     }
     168            0 :     matrix4 raymatrix(vec(-0.5f*static_cast<float>(vieww)*projmatrix.a.x, 0, 0.5f*static_cast<float>(vieww) - 0.5f*static_cast<float>(vieww)*projmatrix.c.x),
     169            0 :                       vec(0, -0.5f*static_cast<float>(viewh)*projmatrix.b.y, 0.5f*static_cast<float>(viewh) - 0.5f*static_cast<float>(viewh)*projmatrix.c.y));
     170            0 :     raymatrix.muld(cammatrix);
     171            0 :     GLOBALPARAM(raymatrix, raymatrix);
     172            0 :     GLOBALPARAM(linearworldmatrix, linearworldmatrix);
     173              : 
     174              :     std::array<uint, lighttilemaxheight> tiles;
     175            0 :     float allsx1 =  1,
     176            0 :           allsy1 =  1,
     177            0 :           allsx2 = -1,
     178            0 :           allsy2 = -1;
     179              :     float sx1, sy1, sx2, sy2;
     180              : 
     181            0 :     for(int layer = 0; layer < 4; ++layer)
     182              :     {
     183            0 :         switch(layer)
     184              :         {
     185            0 :             case 0:
     186              :             {
     187            0 :                 if(!(hasmats&1))
     188              :                 {
     189            0 :                     continue;
     190              :                 }
     191            0 :                 sx1 = mi.matliquidsx1;
     192            0 :                 sy1 = mi.matliquidsy1;
     193            0 :                 sx2 = mi.matliquidsx2;
     194            0 :                 sy2 = mi.matliquidsy2;
     195            0 :                 std::memcpy(tiles.data(), mi.matliquidtiles, sizeof(tiles));
     196            0 :                 break;
     197              :             }
     198            0 :             case 1:
     199              :             {
     200            0 :                 if(!(hasalphavas&1))
     201              :                 {
     202            0 :                     continue;
     203              :                 }
     204            0 :                 sx1 = ai.alphabacksx1;
     205            0 :                 sy1 = ai.alphabacksy1;
     206            0 :                 sx2 = ai.alphabacksx2;
     207            0 :                 sy2 = ai.alphabacksy2;
     208            0 :                 std::memcpy(tiles.data(), alphatiles, tiles.size()*sizeof(uint));
     209            0 :                 break;
     210              :             }
     211            0 :             case 2:
     212              :             {
     213            0 :                 if(!(hasalphavas&2) && !(hasmats&2))
     214              :                 {
     215            0 :                     continue;
     216              :                 }
     217            0 :                 sx1 = ai.alphafrontsx1;
     218            0 :                 sy1 = ai.alphafrontsy1;
     219            0 :                 sx2 = ai.alphafrontsx2;
     220            0 :                 sy2 = ai.alphafrontsy2;
     221            0 :                 std::memcpy(tiles.data(), alphatiles, tiles.size()*sizeof(uint));
     222            0 :                 if(hasmats&2)
     223              :                 {
     224            0 :                     sx1 = std::min(sx1, mi.matsolidsx1);
     225            0 :                     sy1 = std::min(sy1, mi.matsolidsy1);
     226            0 :                     sx2 = std::max(sx2, mi.matsolidsx2);
     227            0 :                     sy2 = std::max(sy2, mi.matsolidsy2);
     228            0 :                     for(int j = 0; j < lighttilemaxheight; ++j)
     229              :                     {
     230            0 :                         tiles[j] |= mi.matsolidtiles[j];
     231              :                     }
     232              :                 }
     233            0 :                 break;
     234              :             }
     235            0 :             case 3:
     236              :             {
     237            0 :                 if(!hasmodels)
     238              :                 {
     239            0 :                     continue;
     240              :                 }
     241            0 :                 sx1 = tmodelinfo.mdlsx1;
     242            0 :                 sy1 = tmodelinfo.mdlsy1;
     243            0 :                 sx2 = tmodelinfo.mdlsx2;
     244            0 :                 sy2 = tmodelinfo.mdlsy2;
     245            0 :                 std::memcpy(tiles.data(), tmodelinfo.mdltiles.data(), tiles.size()*sizeof(uint));
     246            0 :                 break;
     247              :             }
     248            0 :             default:
     249              :             {
     250            0 :                 continue;
     251              :             }
     252            0 :         }
     253            0 :         transparentlayer = layer+1;
     254            0 :         allsx1 = std::min(allsx1, sx1);
     255            0 :         allsy1 = std::min(allsy1, sy1);
     256            0 :         allsx2 = std::max(allsx2, sx2);
     257            0 :         allsy2 = std::max(allsy2, sy2);
     258              : 
     259            0 :         glBindFramebuffer(GL_FRAMEBUFFER, msaalight ? msfbo : gfbo);
     260            0 :         if(ghasstencil)
     261              :         {
     262            0 :             glStencilFunc(GL_ALWAYS, layer+1, ~0);
     263            0 :             glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
     264              :         }
     265              :         else
     266              :         {
     267            0 :             bool scissor = sx1 > -1 || sy1 > -1 || sx2 < 1 || sy2 < 1;
     268            0 :             if(scissor)
     269              :             {
     270            0 :                 int x1 = static_cast<int>(std::floor((sx1*0.5f+0.5f)*static_cast<float>(vieww))),
     271            0 :                     y1 = static_cast<int>(std::floor((sy1*0.5f+0.5f)*static_cast<float>(viewh))),
     272            0 :                     x2 = static_cast<int>(std::ceil((sx2*0.5f+0.5f)*static_cast<float>(vieww))),
     273            0 :                     y2 = static_cast<int>(std::ceil((sy2*0.5f+0.5f)*static_cast<float>(viewh)));
     274            0 :                 glEnable(GL_SCISSOR_TEST);
     275            0 :                 glScissor(x1, y1, x2 - x1, y2 - y1);
     276              :             }
     277              : 
     278            0 :             maskgbuffer("n");
     279            0 :             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
     280            0 :             glClearColor(0, 0, 0, 0);
     281            0 :             glClear(GL_COLOR_BUFFER_BIT);
     282            0 :             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     283            0 :             if(scissor)
     284              :             {
     285            0 :                 glDisable(GL_SCISSOR_TEST);
     286              :             }
     287              :         }
     288            0 :         maskgbuffer("cndg");
     289              : 
     290            0 :         if(wireframe && editmode)
     291              :         {
     292            0 :             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     293              :         }
     294              : 
     295            0 :         switch(layer)
     296              :         {
     297            0 :             case 0:
     298              :             {
     299            0 :                 renderliquidmaterials();
     300            0 :                 break;
     301              :             }
     302            0 :             case 1:
     303              :             {
     304            0 :                 renderalphageom(1);
     305            0 :                 break;
     306              :             }
     307            0 :             case 2:
     308              :             {
     309            0 :                 if(hasalphavas&2)
     310              :                 {
     311            0 :                     renderalphageom(2);
     312              :                 }
     313            0 :                 if(hasmats&2)
     314              :                 {
     315            0 :                     rendersolidmaterials();
     316              :                 }
     317            0 :                 renderstains(StainBuffer_Transparent, true, layer+1);
     318            0 :                 break;
     319              :             }
     320            0 :             case 3:
     321              :             {
     322            0 :                 rendertransparentmodelbatches(layer+1);
     323            0 :                 break;
     324              :             }
     325              :         }
     326              : 
     327            0 :         if(wireframe && editmode)
     328              :         {
     329            0 :             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     330              :         }
     331              : 
     332            0 :         if(msaalight)
     333              :         {
     334            0 :             glBindFramebuffer(GL_FRAMEBUFFER, mshdrfbo);
     335            0 :             if((ghasstencil && msaaedgedetect) || msaalight==2)
     336              :             {
     337            0 :                 for(int i = 0; i < 2; ++i)
     338              :                 {
     339            0 :                     renderlights(sx1, sy1, sx2, sy2, tiles.data(), layer+1, i+1, true);
     340              :                 }
     341            0 :             }
     342              :             else
     343              :             {
     344            0 :                 renderlights(sx1, sy1, sx2, sy2, tiles.data(), layer+1, 3, true);
     345              :             }
     346              :         }
     347              :         else
     348              :         {
     349            0 :             glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
     350            0 :             renderlights(sx1, sy1, sx2, sy2, tiles.data(), layer+1, 0, true);
     351              :         }
     352              : 
     353            0 :         switch(layer)
     354              :         {
     355            0 :             case 2:
     356              :             {
     357            0 :                 renderstains(StainBuffer_Transparent, false, layer+1);
     358            0 :                 break;
     359              :             }
     360              :         }
     361              :     }
     362              : 
     363            0 :     transparentlayer = 0;
     364              : 
     365            0 :     if(ghasstencil)
     366              :     {
     367            0 :         glDisable(GL_STENCIL_TEST);
     368              :     }
     369              : 
     370            0 :     endtimer(transtimer);
     371              : 
     372            0 :     if(editmode)
     373              :     {
     374            0 :         return;
     375              :     }
     376            0 :     alphaparticles(allsx1, allsy1, allsx2, allsy2);
     377              : }
        

Generated by: LCOV version 2.0-1