LCOV - code coverage report
Current view: top level - engine/render - renderalpha.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 0 201 0.0 %
Date: 2024-11-22 05:07:59 Functions: 0 2 0.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 1.14