Ticket #721: water_ro_r3_r9066.patch

File water_ro_r3_r9066.patch, 32.7 KB (added by Rodolphe Ortalo, 13 years ago)

Patch with respect to trunk and revision 9066

  • source/renderer/PatchRData.h

     
    4141    void RenderSides();
    4242    void RenderPriorities();
    4343
     44    void RenderFancyWater(GLint waterDepth);
     45    void RenderSimpleWater();
     46
    4447    static void RenderBases(const std::vector<CPatchRData*>& patches);
    4548    static void RenderBlends(const std::vector<CPatchRData*>& patches);
    4649    static void RenderStreams(const std::vector<CPatchRData*>& patches, int streamflags);
     
    126129
    127130    // splats used in blend pass
    128131    std::vector<SSplat> m_BlendSplats;
     132
     133    // Simple water vertex description data structure
     134    struct SSimpleWaterVertex {
     135        // vertex position
     136        CVector3D m_Position;
     137        // vertex uvs for texture 0
     138        float m_UVs[2];
     139        // vertex 3d for texture 1 == vertex position so removed
     140        // CVector3D m_PosTex1;
     141        // Color TODO: Try to use packed colors? (here:floats)
     142        RGBAColor m_Color;
     143        // TODO: Add padding up to 64bytes? (for 32 bytes align)
     144    };
     145
     146    // Fancy water vertex description data structure
     147    struct SWaterVertex {
     148        // vertex position
     149        CVector3D m_Position;
     150        // vertex uvs for normal map texture
     151        float m_UVs[2];
     152        // water depth (varying for shader)
     153        float m_Depth;
     154        // add some padding (TODO: Check)
     155        u32 m_Padding[2];
     156    };
     157
     158    void BuildSimpleWaterVertices();
     159    void BuildFancyWaterVertices();
     160
     161    void BuildWaterVertexData(); // Common to simple and fancy water
     162
     163    // Water vertex buffer
     164    CVertexBuffer::VBChunk* m_VBWater;
     165
     166    // Water indices into buffer
     167    // NB: Indices are identical for fancy or regular water (same path)
     168    void BuildWaterIndices();
     169
     170    // 256*256 seems to be enough
     171    std::vector<unsigned short> m_WaterIndices;
     172
     173    // Build data for fancy water or reference data for
     174    // computing simple water
     175    std::vector<SWaterVertex> m_WaterVertexData;
     176
     177    // maximum and minimum depth of water at all vertices on the patch
     178    // signed value: can be negative (if vertex emerges of water)
     179    float max_wdepth;
     180    float min_wdepth;
     181    // Check if there is water on this patch (useful sometimes internally)
     182    bool FullyEmerged();
     183    bool EntirelyUnderWater();
     184
    129185};
    130186
    131187#endif
  • source/renderer/TerrainRenderer.h

     
    114114
    115115private:
    116116    TerrainRendererInternals* m;
     117
     118    /*
     119     * RenderFancyWater: internal rendering method for fancy water
     120     */
     121    bool RenderFancyWater();
     122    /*
     123     * RenderSimpleWater: internal rendering method for water
     124     */
     125    void RenderSimpleWater();
    117126};
    118127
    119128#endif // INCLUDED_TERRAINRENDERER
  • source/renderer/PatchRData.cpp

     
    5656///////////////////////////////////////////////////////////////////
    5757// CPatchRData constructor
    5858CPatchRData::CPatchRData(CPatch* patch) :
    59     m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0)
     59    m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0),
     60    m_VBWater(0), max_wdepth(-FLT_MAX), min_wdepth(FLT_MAX)
    6061{
    6162    debug_assert(patch);
    6263    Build();
     
    631632    BuildSides();
    632633    BuildIndices();
    633634    BuildBlends();
     635
     636    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     637    if (WaterMgr->WillRenderFancyWater()) {
     638        BuildFancyWaterVertices();
     639    } else {
     640        BuildSimpleWaterVertices();
     641    }
     642    BuildWaterIndices();
    634643}
    635644
    636645void CPatchRData::Update()
     
    644653        BuildIndices();
    645654        BuildBlends();
    646655
     656        WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     657        if (WaterMgr->WillRenderFancyWater()) {
     658            // TODO: Switch on fancy or not fancy water
     659            BuildFancyWaterVertices();
     660        } else {
     661            BuildSimpleWaterVertices();
     662        }
     663
    647664        m_UpdateFlags=0;
    648665    }
    649666}
     
    10481065        }
    10491066    }
    10501067}
     1068
     1069//
     1070// Water build and rendering
     1071//
     1072
     1073// Build vertex buffer for water vertices over our patch
     1074void CPatchRData::BuildWaterVertexData()
     1075{
     1076    // number of vertices in each direction in each patch
     1077    const ssize_t vsize=PATCH_SIZE+1;
     1078
     1079    m_WaterVertexData.resize(vsize*vsize);
     1080
     1081    // We need to use this to access the water manager or we may not have the
     1082    // actual values but some compiled-in defaults
     1083    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1084
     1085    // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
     1086    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1087    const float repeatPeriod = WaterMgr->m_RepeatPeriod;
     1088#if 0
     1089    // With non fancy water, period is a constant? TODO: Check
     1090    const float repeatPeriod = 16.0f;
     1091#endif
     1092
     1093
     1094    CPatch* patch = m_Patch;
     1095    CTerrain* terrain = patch->m_Parent;
     1096
     1097    max_wdepth = -FLT_MAX;
     1098    min_wdepth = FLT_MAX;
     1099    // build vertices, uv, and shader varying
     1100    for (ssize_t j=0;j<vsize;j++)
     1101    {
     1102        for (ssize_t i=0;i<vsize;i++)
     1103        {
     1104            ssize_t ix=(patch->m_X*PATCH_SIZE)+i;
     1105            ssize_t iz=(patch->m_Z*PATCH_SIZE)+j;
     1106            ssize_t v=(j*vsize)+i;
     1107
     1108            // calculate vertex data like for base vertices
     1109            terrain->CalcPosition(ix,iz,m_WaterVertexData[v].m_Position);
     1110            // at this step, Y is still terrainHeight
     1111            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz);
     1112            const float wdepth = waterHeight - m_WaterVertexData[v].m_Position.Y;
     1113            m_WaterVertexData[v].m_Depth = wdepth;
     1114            // replaces Y by water height
     1115            m_WaterVertexData[v].m_Position.Y = waterHeight;
     1116            // calculates U/V (TODO: could be done in for fancy water shader? would be beneficial?)
     1117            m_WaterVertexData[v].m_UVs[0] = m_WaterVertexData[v].m_Position.X / repeatPeriod;
     1118            m_WaterVertexData[v].m_UVs[1] = m_WaterVertexData[v].m_Position.Z / repeatPeriod;
     1119            // update min and max depth over patch
     1120            if (wdepth > max_wdepth) max_wdepth = wdepth;
     1121            if (wdepth < min_wdepth) min_wdepth = wdepth;
     1122        }
     1123    }
     1124}
     1125
     1126// Build all that can be done at build time for simple water
     1127void CPatchRData::BuildSimpleWaterVertices()
     1128{
     1129    BuildWaterVertexData();
     1130    // overall depth around patch is ready now
     1131    // so, if we are fully emerged, we can get rid of things
     1132    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     1133    {
     1134        if (m_VBWater) {
     1135            g_VBMan.Release(m_VBWater);
     1136        }
     1137    }
     1138    else
     1139    {
     1140        // allocate vertex buffer (only: update is done at render time)
     1141        if (!m_VBWater) {
     1142            m_VBWater=g_VBMan.Allocate(sizeof(SSimpleWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1143        }
     1144        debug_assert(m_VBWater->m_Index < 65536);
     1145    }
     1146
     1147    // The vertex buffer must be ready for indices calculation
     1148    BuildWaterIndices();
     1149}
     1150
     1151void CPatchRData::BuildFancyWaterVertices()
     1152{
     1153    BuildWaterVertexData();
     1154    // overall depth around patch is ready now
     1155    // so, if we are fully emerged, we can get rid of things
     1156    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     1157    {
     1158        if (m_VBWater) {
     1159            g_VBMan.Release(m_VBWater);
     1160        }
     1161    }
     1162    else
     1163    {
     1164        // we directly use the vertex data for rendering
     1165        // upload to vertex buffer
     1166        if (!m_VBWater) {
     1167            m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1168        }
     1169        m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]);
     1170        debug_assert(m_VBWater->m_Index < 65536);
     1171    }
     1172    // The vertex buffer must be ready for indices calculation
     1173    BuildWaterIndices();
     1174
     1175    // We directly use the vertex buffer in rendering, so we
     1176    // can clear the data buffer for space
     1177    m_WaterVertexData.clear();
     1178}
     1179
     1180
     1181void CPatchRData::BuildWaterIndices()
     1182{
     1183    // release existing indices
     1184    m_WaterIndices.clear();
     1185
     1186    if (FullyEmerged())
     1187        return;
     1188
     1189    // must have allocated some vertices before trying to build corresponding indices
     1190    debug_assert(m_VBWater);
     1191
     1192    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1193
     1194    CPatch* patch = m_Patch;
     1195    CTerrain* terrain = patch->m_Parent;
     1196
     1197    // build indices for water
     1198    size_t base_indice=m_VBWater->m_Index;
     1199
     1200    for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
     1201    {
     1202        for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
     1203        {
     1204            ssize_t x = (patch->m_X*PATCH_SIZE + dx);
     1205            ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     1206
     1207            // Some offsets used to go around counterclockwise while keeping code concise
     1208            const int DX[] = {1,1,0,0};
     1209            const int DZ[] = {0,1,1,0};
     1210
     1211            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z);
     1212
     1213            // NB: I do not reuse the values already computed for building the vertex buffer/data
     1214            // here, even though it would probably be more readable, because it allows to
     1215            // use the same function for building indices for fancy and non-fancy water (which
     1216            // have different vertex buffer elements).
     1217            // But reference visibility info. is for vertices.
     1218
     1219            // is any corner of the tile below the water height? if not, no point rendering it
     1220            bool shouldRender = false;
     1221            for (int j = 0; j < 4; j++)
     1222            {
     1223                const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
     1224                if (terrainHeight < waterHeight)
     1225                {
     1226                    shouldRender = true;
     1227                    break;
     1228                }
     1229            }
     1230            if (!shouldRender)
     1231                continue;
     1232            for (int j=0; j<4; j++)
     1233            {
     1234                ssize_t ix = dx + DX[j];
     1235                ssize_t iz = dz + DZ[j];
     1236                ssize_t v=(iz*(PATCH_SIZE+1))+ix;
     1237                m_WaterIndices.push_back(u16(v)+base_indice);
     1238                debug_assert((u16(v)+base_indice) < 65535);
     1239            }
     1240        }
     1241    }
     1242}
     1243
     1244const float EPSILON = 1e-12;
     1245
     1246// if the maximum water size is negative, the patch is entirely emerged
     1247bool CPatchRData::FullyEmerged()
     1248{
     1249    return (max_wdepth < EPSILON);
     1250}
     1251// if the minimum water size is still positive, the patch is entirely under water
     1252bool CPatchRData::EntirelyUnderWater()
     1253{
     1254    return (min_wdepth > -EPSILON);
     1255}
     1256
     1257void CPatchRData::RenderSimpleWater()
     1258{
     1259    debug_assert(m_UpdateFlags==0);
     1260
     1261    if (FullyEmerged())
     1262        return;
     1263
     1264    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1265
     1266    // This is probably changing so vertices need update!
     1267    const CCamera& camera = g_Renderer.GetViewCamera();
     1268    CVector3D camPos = camera.m_Orientation.GetTranslation();
     1269
     1270    std::vector<SSimpleWaterVertex> vertices;
     1271    vertices.reserve(m_WaterVertexData.size());
     1272
     1273    // build vertex buffer with adequate alpha
     1274    for (unsigned int i=0; i < m_WaterVertexData.size(); i++)
     1275    {
     1276        SSimpleWaterVertex vertex;
     1277        // Copy data identical to build time
     1278        vertex.m_Position = m_WaterVertexData[i].m_Position;
     1279        vertex.m_UVs[0] = m_WaterVertexData[i].m_UVs[0];
     1280        vertex.m_UVs[1] = m_WaterVertexData[i].m_UVs[1];
     1281        // We use the same pointer/data in array for saving space
     1282        // vertex.m_PosTex1 = m_WaterVertexData[i].m_Position;
     1283
     1284        const float alpha = clamp( (m_WaterVertexData[i].m_Depth) / WaterMgr->m_WaterFullDepth
     1285                     + WaterMgr->m_WaterAlphaOffset,
     1286                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     1287
     1288        // (Crappy) fresnel effect
     1289        CVector3D CamFaceVertex=CVector3D(vertex.m_Position.X,WaterMgr->m_WaterHeight,vertex.m_Position.Z)-camPos;
     1290                    // Note: WaterMgr->m_WaterHeight is also vertex.m_Position.Y I think...
     1291        CamFaceVertex.Normalize();
     1292        float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
     1293        // Invert and set boundaries
     1294        FresnelScalar = 1.f - (FresnelScalar * 0.6);
     1295        // Set Color
     1296        vertex.m_Color.m_X = WaterMgr->m_WaterColor.r;
     1297        vertex.m_Color.m_Y = WaterMgr->m_WaterColor.g;
     1298        vertex.m_Color.m_Z = WaterMgr->m_WaterColor.b;
     1299        vertex.m_Color.m_W = alpha * FresnelScalar;
     1300
     1301        // save the finalized vertex built
     1302        vertices.push_back(vertex);
     1303    }
     1304    // upload to vertex buffer
     1305    m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&vertices[0]);
     1306
     1307    SSimpleWaterVertex *base=(SSimpleWaterVertex *)m_VBWater->m_Owner->Bind();
     1308
     1309    // setup data pointers
     1310    GLsizei stride = sizeof(SSimpleWaterVertex);
     1311    glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]);
     1312    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1313    pglClientActiveTextureARB(GL_TEXTURE0);
     1314    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);    // render
     1315    pglClientActiveTextureARB(GL_TEXTURE1);
     1316    glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);   // (same data as vertex)
     1317    // glTexCoordPointer(3, GL_FLOAT, stride, &base->m_PosTex1[0]);
     1318
     1319    if (!g_Renderer.m_SkipSubmit) {
     1320        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1321            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1322    }
     1323    // bump stats
     1324    g_Renderer.m_Stats.m_DrawCalls++;
     1325    // TODO: Water stats?
     1326
     1327    CVertexBuffer::Unbind();
     1328}
     1329
     1330void CPatchRData::RenderFancyWater(GLint waterDepth)
     1331{
     1332    debug_assert(m_UpdateFlags==0);
     1333
     1334    if (FullyEmerged())
     1335        return;
     1336
     1337    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1338
     1339    // setup data pointers
     1340    GLsizei stride = sizeof(SWaterVertex);
     1341    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1342    pglClientActiveTextureARB(GL_TEXTURE0);
     1343    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
     1344    pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */
     1345            stride, &base->m_Depth);
     1346    // render
     1347    if (!g_Renderer.m_SkipSubmit) {
     1348        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1349            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1350    }
     1351    // bump stats
     1352    g_Renderer.m_Stats.m_DrawCalls++;
     1353    // TODO: Water stats?
     1354
     1355    CVertexBuffer::Unbind();
     1356
     1357}
     1358
  • source/renderer/TerrainRenderer.cpp

     
    161161    m->phase = Phase_Submit;
    162162}
    163163
    164 
    165164///////////////////////////////////////////////////////////////////
    166165// Full-featured terrain rendering with blending and everything
    167166void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
     
    521520    glDisableClientState(GL_VERTEX_ARRAY);
    522521}
    523522
    524 
    525 ///////////////////////////////////////////////////////////////////
    526 // Render water that is part of the terrain
    527 void TerrainRenderer::RenderWater()
     523// Render fancy water
     524bool TerrainRenderer::RenderFancyWater()
    528525{
    529     PROFILE( "render water" );
     526    PROFILE( "render fancy water" );
    530527
    531528    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    532529
    533     bool fancy = WaterMgr->WillRenderFancyWater();
    534 
    535     // If we're using fancy water, make sure its shader is loaded
    536     if(fancy && !m->fancyWaterShader)
     530    // We're using fancy water, make sure its shader is loaded
     531    if(!m->fancyWaterShader)
    537532    {
    538533        Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml");
    539534        if (h < 0)
    540535        {
    541536            LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
    542537            g_Renderer.m_Options.m_FancyWater = false;
    543             fancy = false;
     538            return false;
    544539        }
    545540        else
    546541        {
    547542            m->fancyWaterShader = h;
    548543        }
    549544    }
    550     CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
    551545
    552546    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
    553547   
     
    561555    double period = 1.6;
    562556    int curTex = (int)(time*60/period) % 60;
    563557
    564     if(fancy)
    565     {
    566         WaterMgr->m_NormalMap[curTex]->Bind();
    567     }
    568     else
    569     {
    570         WaterMgr->m_WaterTexture[curTex]->Bind();
    571     }
     558    WaterMgr->m_NormalMap[curTex]->Bind();
    572559
    573560    // Shift the texture coordinates by these amounts to make the water "flow"
    574561    float tx = -fmod(time, 81.0)/81.0;
    575562    float ty = -fmod(time, 34.0)/34.0;
    576563
    577     if(!fancy)
    578     {
    579         // Perform the shifting by modifying the texture matrix
    580         glMatrixMode(GL_TEXTURE);
    581         glLoadIdentity();
    582         glTranslatef(tx, ty, 0);
    583 
    584         // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
    585         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    586         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    587         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
    588         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    589         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
    590         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
    591         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    592         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
    593         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    594 
    595         // Multiply by LOS texture
    596         losTexture.BindTexture(1);
    597         pglClientActiveTextureARB(GL_TEXTURE1);
    598         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    599 
    600         glLoadMatrixf(losTexture.GetTextureMatrix());
    601 
    602         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    603         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    604         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
    605         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    606         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
    607         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
    608         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    609         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
    610         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    611     }
    612 
    613564    // Set the proper LOD bias
    614565    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    615566
    616567    const CCamera& camera = g_Renderer.GetViewCamera();
    617568    CVector3D camPos = camera.m_Orientation.GetTranslation();
    618569
    619     GLint vertexDepth = 0;  // water depth attribute, if using fancy water
     570    // Bind reflection and refraction textures on texture units 1 and 2
     571    pglActiveTextureARB( GL_TEXTURE1_ARB );
     572    glEnable( GL_TEXTURE_2D );
     573    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
     574    pglActiveTextureARB( GL_TEXTURE2_ARB );
     575    glEnable( GL_TEXTURE_2D );
     576    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
    620577
    621     if(fancy)
    622     {
    623         // Bind reflection and refraction textures on texture units 1 and 2
    624         pglActiveTextureARB( GL_TEXTURE1_ARB );
    625         glEnable( GL_TEXTURE_2D );
    626         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
    627         pglActiveTextureARB( GL_TEXTURE2_ARB );
    628         glEnable( GL_TEXTURE_2D );
    629         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
     578    losTexture.BindTexture(3);
    630579
    631         losTexture.BindTexture(3);
     580    // Bind water shader and set arguments
     581    ogl_program_use( m->fancyWaterShader );
    632582
    633         // Bind water shader and set arguments
    634         ogl_program_use( m->fancyWaterShader );
     583    GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
     584    GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
     585    GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
     586    GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
     587    GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
     588    GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
     589    GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
     590    GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
     591    GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
     592    GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
     593    GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
     594    GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
     595    GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
     596    GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
     597    GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
     598    GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
     599    GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
     600    GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
     601    GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
     602    GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
    635603
    636         GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
    637         GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
    638         GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
    639         GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
    640         GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
    641         GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
    642         GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
    643         GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
    644         GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
    645         GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
    646         GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
    647         GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
    648         GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
    649         GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
    650         GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
    651         GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
    652         GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
    653         GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
    654         GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
    655         GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
     604    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
     605    pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
     606    pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
     607    pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
     608    pglUniform1fARB( shininess, WaterMgr->m_Shininess );
     609    pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
     610    pglUniform1fARB( waviness, WaterMgr->m_Waviness );
     611    pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
     612    pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
     613    pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
     614    pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
     615    pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
     616    pglUniform4fARB( translation, tx, ty, 0, 0 );
     617    pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
     618    pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
     619    pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
     620    pglUniform1iARB( normalMap, 0 );        // texture unit 0
     621    pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
     622    pglUniform1iARB( refractionMap, 2 );    // texture unit 2
     623    pglUniform1iARB( losMap, 3 );           // texture unit 3
     624    pglUniform3fvARB( cameraPos, 1, &camPos.X );
    656625
    657         const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
    658         pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
    659         pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
    660         pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
    661         pglUniform1fARB( shininess, WaterMgr->m_Shininess );
    662         pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
    663         pglUniform1fARB( waviness, WaterMgr->m_Waviness );
    664         pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
    665         pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
    666         pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
    667         pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
    668         pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
    669         pglUniform4fARB( translation, tx, ty, 0, 0 );
    670         pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
    671         pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
    672         pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
    673         pglUniform1iARB( normalMap, 0 );        // texture unit 0
    674         pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
    675         pglUniform1iARB( refractionMap, 2 );    // texture unit 2
    676         pglUniform1iARB( losMap, 3 );           // texture unit 3
    677         pglUniform3fvARB( cameraPos, 1, &camPos.X );
     626//  glActiveTexture(GL_TEXTURE0);
    678627
    679         vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
    680     }
    681    
    682     float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
     628    glEnableClientState(GL_VERTEX_ARRAY);
     629    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     630    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    683631
    684     glBegin(GL_QUADS);
    685 
     632    // water depth attribute, when using fancy water
     633    GLint vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
     634    pglEnableVertexAttribArrayARB(vertexDepth);
     635   
    686636    for(size_t i=0; i<m->visiblePatches.size(); i++)
    687637    {
    688         CPatch* patch = m->visiblePatches[i]->GetPatch();
     638        CPatchRData* patchdata = m->visiblePatches[i];
     639        patchdata->RenderFancyWater(vertexDepth);
     640    }
    689641
    690         for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
    691         {
    692             for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
    693             {
    694                 ssize_t x = (patch->m_X*PATCH_SIZE + dx);
    695                 ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     642    pglDisableVertexAttribArrayARB(vertexDepth);
     643    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     644    glDisableClientState(GL_VERTEX_ARRAY);
    696645
    697                 // Some offsets used to go around counterclockwise while keeping code concise
    698                 const int DX[] = {1,1,0,0};
    699                 const int DZ[] = {0,1,1,0};
     646    // Unbind the LOS/refraction/reflection textures and the shader
     647    g_Renderer.BindTexture(3, 0);
     648    g_Renderer.BindTexture(2, 0);
     649    g_Renderer.BindTexture(1, 0);
     650    pglActiveTextureARB(GL_TEXTURE0_ARB);
     651    ogl_program_use(0);
    700652
    701                 // is any corner of the tile below the water height? if not, no point rendering it
    702                 bool shouldRender = false;
    703                 for (int j = 0; j < 4; j++)
    704                 {
    705                     float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
    706                     if (terrainHeight < WaterMgr->m_WaterHeight)
    707                     {
    708                         shouldRender = true;
    709                         break;
    710                     }
    711                 }
    712                 if (!shouldRender)
    713                     continue;
     653    glMatrixMode(GL_MODELVIEW);
     654    glDisable(GL_BLEND);
     655    glDisable(GL_TEXTURE_2D);
    714656
    715                 for (int j=0; j<4; j++)
    716                 {
    717                     ssize_t ix = x + DX[j];
    718                     ssize_t iz = z + DZ[j];
     657    return true;
     658}
    719659
    720                     float vertX = ix * CELL_SIZE;
    721                     float vertZ = iz * CELL_SIZE;
     660void TerrainRenderer::RenderSimpleWater()
     661{
     662    PROFILE( "render simple water" );
    722663
    723                     float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
     664    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    724665
    725                     if (fancy)
    726                     {
    727                         pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight);
    728                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    729                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    730                     }
    731                     else
    732                     {
    733                         float alpha = clamp( (WaterMgr->m_WaterHeight - terrainHeight) / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset,
    734                                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     666    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
     667   
     668    glEnable(GL_BLEND);
     669    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     670    glEnable(GL_DEPTH_TEST);
     671    glDepthFunc(GL_LEQUAL);
    735672
    736                         // (Crappy) fresnel effect
    737                         CVector3D CamFaceVertex=CVector3D(vertX,WaterMgr->m_WaterHeight,vertZ)-camPos;
    738                         CamFaceVertex.Normalize();
    739                         float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
    740                         // Invert and set boundaries
    741                         FresnelScalar = 1.f - (FresnelScalar * 0.6);
     673    double time = WaterMgr->m_WaterTexTimer;
    742674
    743                         glColor4f(WaterMgr->m_WaterColor.r,
    744                                   WaterMgr->m_WaterColor.g,
    745                                   WaterMgr->m_WaterColor.b,
    746                                   alpha * FresnelScalar);
    747                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    748                         pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ);
    749                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    750                     }
     675    double period = 16.0f;
     676    int curTex = (int)(time*60/period) % 60;
    751677
    752                 }
    753             }   //end of x loop
    754         }   //end of z loop
    755     }
    756     glEnd();
     678    WaterMgr->m_WaterTexture[curTex]->Bind();
    757679
    758     if (fancy)
    759     {
    760         // Unbind the LOS/refraction/reflection textures and the shader
     680    // Shift the texture coordinates by these amounts to make the water "flow"
     681    float tx = -fmod(time, 81.0)/81.0;
     682    float ty = -fmod(time, 34.0)/34.0;
    761683
    762         g_Renderer.BindTexture(3, 0);
    763         g_Renderer.BindTexture(2, 0);
    764         g_Renderer.BindTexture(1, 0);
     684    // Perform the shifting by modifying the texture matrix
     685    glMatrixMode(GL_TEXTURE);
     686    glLoadIdentity();
     687    glTranslatef(tx, ty, 0);
    765688
    766         pglActiveTextureARB(GL_TEXTURE0_ARB);
     689    // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
     690    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     691    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     692    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     693    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     694    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
     695    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     696    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     697    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
     698    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    767699
    768         ogl_program_use(0);
    769     }
     700    // Multiply by LOS texture
     701    losTexture.BindTexture(1);
     702    pglClientActiveTextureARB(GL_TEXTURE1);
     703    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    770704
    771     if (!fancy)
    772     {
    773         g_Renderer.BindTexture(1, 0);
    774         pglClientActiveTextureARB(GL_TEXTURE1_ARB);
    775         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     705    glLoadMatrixf(losTexture.GetTextureMatrix());
    776706
    777         glLoadIdentity();
     707    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     708    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     709    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     710    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     711    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     712    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     713    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     714    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     715    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    778716
    779         pglActiveTextureARB(GL_TEXTURE0_ARB);
    780         pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    781717
    782         // Clean up the texture matrix and blend mode
    783         glLoadIdentity();
    784         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     718    // Set the proper LOD bias
     719    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     720
     721    glEnableClientState(GL_VERTEX_ARRAY);
     722    glEnableClientState(GL_COLOR_ARRAY);
     723    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     724    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     725
     726    for(size_t i=0; i<m->visiblePatches.size(); i++)
     727    {
     728        CPatchRData* patchdata = m->visiblePatches[i];
     729        patchdata->RenderSimpleWater();
    785730    }
    786731
     732    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     733    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     734    glDisableClientState(GL_COLOR_ARRAY);
     735    glDisableClientState(GL_VERTEX_ARRAY);
     736
     737    g_Renderer.BindTexture(1, 0);
     738    pglClientActiveTextureARB(GL_TEXTURE1_ARB);
     739    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     740
     741    glLoadIdentity();
     742
     743    pglActiveTextureARB(GL_TEXTURE0_ARB);
     744    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     745
     746    // Clean up the texture matrix and blend mode
     747    glLoadIdentity();
     748    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     749
    787750    glMatrixMode(GL_MODELVIEW);
    788751    glDisable(GL_BLEND);
    789752    glDisable(GL_TEXTURE_2D);
    790753}
    791754
     755
     756///////////////////////////////////////////////////////////////////
     757// Render water that is part of the terrain
     758void TerrainRenderer::RenderWater()
     759{
     760    // PROFILE is defined in one of the sub functions
     761
     762    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     763
     764    bool fancy = WaterMgr->WillRenderFancyWater();
     765
     766    if (fancy) {
     767        bool r = RenderFancyWater();
     768        if (r) return;
     769    }
     770    RenderSimpleWater();
     771}
     772
    792773void TerrainRenderer::RenderPriorities()
    793774{
    794775    PROFILE("render priorities");
  • binaries/data/mods/public/shaders/water_high.vs

     
    1515    waterDepth = vertexDepth;
    1616    gl_TexCoord[0] = gl_MultiTexCoord0 + translation;
    1717    gl_TexCoord[1] = reflectionMatrix * gl_Vertex;      // projective texturing
    18     gl_TexCoord[2] = reflectionMatrix * gl_Vertex;
     18    gl_TexCoord[2] = refractionMatrix * gl_Vertex;
    1919    gl_TexCoord[3] = losMatrix * gl_Vertex;
    2020    w = gl_TexCoord[1].w;
    2121    gl_Position = ftransform();