Ticket #721: water_ro_r2_r9062.patch

File water_ro_r2_r9062.patch, 38.6 KB (added by Rodolphe Ortalo, 13 years ago)

Patch with respect to trunk and revision 9062

  • source/renderer/PatchRData.h

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

     
    7171     */
    7272    void EndFrame();
    7373
     74    /*
     75     * HasWaterVisible: indicate if one of the patches currently visible
     76     * has water visible.
     77     */
     78    bool HasWaterVisible();
     79
     80
    7481    /**
    7582     * RenderTerrain: Render textured terrain (including blends between
    7683     * different terrain types).
     
    8087     *
    8188     * @param shadow A prepared shadow map, in case rendering with shadows is enabled.
    8289     */
    83     void RenderTerrain(ShadowMap* shadow);
     90    enum RenderTerrainMode { // Offer the ability to skip some patches (reflections, refractions)
     91        NORMAL,
     92        NOT_UNDERWATER,
     93        NOT_EMERGED,
     94    };
     95    void RenderTerrain(ShadowMap* shadow, RenderTerrainMode mode = NORMAL);
    8496
    8597    /**
    8698     * RenderPatches: Render all patches un-textured as polygons.
     
    114126
    115127private:
    116128    TerrainRendererInternals* m;
     129
     130    /*
     131     * RenderFancyWater: internal rendering method for fancy water
     132     */
     133    bool RenderFancyWater();
     134    /*
     135     * RenderSimpleWater: internal rendering method for water
     136     */
     137    void RenderSimpleWater();
    117138};
    118139
    119140#endif // INCLUDED_TERRAINRENDERER
  • source/renderer/Renderer.cpp

     
    11021102    // Render sky, terrain and models
    11031103    m->skyManager.RenderSky();
    11041104    ogl_WarnIfError();
    1105     RenderPatches();
     1105//  RenderPatches();
     1106    // Directly call terrain renderer without underwater patches
     1107    // render all the patches, including blend pass
     1108    m->terrainRenderer->RenderTerrain((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0, TerrainRenderer::NOT_UNDERWATER);
     1109
    11061110    ogl_WarnIfError();
    11071111    RenderModels();
    11081112    ogl_WarnIfError();
     
    11681172    glDepthFunc(GL_GEQUAL);
    11691173
    11701174    // Render terrain and models
    1171     RenderPatches();
     1175//  RenderPatches();
     1176    // Directly call terrain renderer without fully emerged (out of water) patches
     1177    // render all the patches, including blend pass
     1178    m->terrainRenderer->RenderTerrain((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0, TerrainRenderer::NOT_EMERGED);
    11721179    ogl_WarnIfError();
    11731180    RenderModels();
    11741181    ogl_WarnIfError();
     
    12351242
    12361243    ogl_WarnIfError();
    12371244
    1238     if (m_WaterManager->m_RenderWater && m_WaterManager->WillRenderFancyWater())
     1245    if (m_WaterManager->m_RenderWater && m_WaterManager->WillRenderFancyWater() && m->terrainRenderer->HasWaterVisible())
    12391246    {
    12401247        // render reflected and refracted scenes, then re-clear the screen
    12411248        RenderReflections();
     
    12721279    ogl_WarnIfError();
    12731280
    12741281    // render water
    1275     if (m_WaterManager->m_RenderWater && g_Game)
     1282    PROFILE_START("render water");
     1283    if (m_WaterManager->m_RenderWater && g_Game && m->terrainRenderer->HasWaterVisible())
    12761284    {
    12771285        m->terrainRenderer->RenderWater();
    12781286        ogl_WarnIfError();
     
    12891297        // turning the water off. On the other hand every user will have water
    12901298        // on all the time, so it might not be worth worrying about.
    12911299    }
     1300    PROFILE_END("render water");
    12921301
    12931302    // Clean up texture blend mode so particles and other things render OK
    12941303    // (really this should be cleaned up by whoever set it)
  • 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        // TODO: Switch on fancy or not fancy water
     639        BuildFancyWaterVertices();
     640    } else {
     641        BuildSimpleWaterVertices();
     642    }
     643        BuildWaterIndices();
    634644}
    635645
    636646void CPatchRData::Update()
     
    644654        BuildIndices();
    645655        BuildBlends();
    646656
     657        WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     658        if (WaterMgr->WillRenderFancyWater()) {
     659            // TODO: Switch on fancy or not fancy water
     660            BuildFancyWaterVertices();
     661        } else {
     662            BuildSimpleWaterVertices();
     663        }
     664
    647665        m_UpdateFlags=0;
    648666    }
    649667}
     
    946964            g_Renderer.m_Stats.m_TerrainTris += std::accumulate(batch.first.begin(), batch.first.end(), 0) / 3;
    947965        }
    948966    }
    949 
    950967    pglClientActiveTextureARB(GL_TEXTURE0);
    951968
    952969    CVertexBuffer::Unbind();
     
    10451062        }
    10461063    }
    10471064}
     1065
     1066//
     1067// Water build and rendering
     1068//
     1069
     1070// Build vertex buffer for water vertices over our patch
     1071void CPatchRData::BuildWaterVertexData()
     1072{
     1073    // number of vertices in each direction in each patch
     1074    const ssize_t vsize=PATCH_SIZE+1;
     1075
     1076    m_WaterVertexData.resize(vsize*vsize);
     1077
     1078    // We need to use this to access the water manager or we may not have the
     1079    // actual values but some compiled-in defaults
     1080    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1081
     1082    // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
     1083    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1084    const float repeatPeriod = WaterMgr->m_RepeatPeriod;
     1085#if 0
     1086    // With non fancy water, period is a constant? TODO: Check
     1087    const float repeatPeriod = 16.0f;
     1088#endif
     1089
     1090
     1091    CPatch* patch = m_Patch;
     1092    CTerrain* terrain = patch->m_Parent;
     1093
     1094    max_wdepth = -FLT_MAX;
     1095    min_wdepth = FLT_MAX;
     1096    // build vertices, uv, and shader varying
     1097    for (ssize_t j=0;j<vsize;j++)
     1098    {
     1099        for (ssize_t i=0;i<vsize;i++)
     1100        {
     1101            ssize_t ix=(patch->m_X*PATCH_SIZE)+i;
     1102            ssize_t iz=(patch->m_Z*PATCH_SIZE)+j;
     1103            ssize_t v=(j*vsize)+i;
     1104
     1105            // calculate vertex data like for base vertices
     1106            terrain->CalcPosition(ix,iz,m_WaterVertexData[v].m_Position);
     1107            // at this step, Y is still terrainHeight
     1108            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz);
     1109            const float wdepth = waterHeight - m_WaterVertexData[v].m_Position.Y;
     1110            m_WaterVertexData[v].m_Depth = wdepth;
     1111            // replaces Y by water height
     1112            m_WaterVertexData[v].m_Position.Y = waterHeight;
     1113            // calculates U/V (TODO: could be done in shader? would be beneficial?)
     1114            m_WaterVertexData[v].m_UVs[0] = m_WaterVertexData[v].m_Position.X / repeatPeriod;
     1115            m_WaterVertexData[v].m_UVs[1] = m_WaterVertexData[v].m_Position.Z / repeatPeriod;
     1116            // update min and max depth over patch
     1117            if (wdepth > max_wdepth) max_wdepth = wdepth;
     1118            if (wdepth < min_wdepth) min_wdepth = wdepth;
     1119        }
     1120    }
     1121}
     1122
     1123// Build all that can be done at build time for simple water
     1124void CPatchRData::BuildSimpleWaterVertices()
     1125{
     1126    BuildWaterVertexData();
     1127    // overall depth around patch is ready now
     1128    // so, if we are fully emerged, we can get rid of things
     1129    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     1130    {
     1131        if (m_VBWater) {
     1132            g_VBMan.Release(m_VBWater);
     1133        }
     1134    }
     1135    else
     1136    {
     1137        // allocate vertex buffer (only: update is done at render time)
     1138        if (!m_VBWater) {
     1139            m_VBWater=g_VBMan.Allocate(sizeof(SSimpleWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1140        }
     1141        debug_assert(m_VBWater->m_Index < 65536);
     1142    }
     1143
     1144    // The vertex buffer must be ready for indices calculation
     1145    BuildWaterIndices();
     1146}
     1147
     1148void CPatchRData::BuildFancyWaterVertices()
     1149{
     1150    BuildWaterVertexData();
     1151    // overall depth around patch is ready now
     1152    // so, if we are fully emerged, we can get rid of things
     1153    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     1154    {
     1155        if (m_VBWater) {
     1156            g_VBMan.Release(m_VBWater);
     1157        }
     1158    }
     1159    else
     1160    {
     1161        // we directly use the vertex data for rendering
     1162        // upload to vertex buffer
     1163        if (!m_VBWater) {
     1164            m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1165        }
     1166        m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]);
     1167        debug_assert(m_VBWater->m_Index < 65536);
     1168    }
     1169    // The vertex buffer must be ready for indices calculation
     1170    BuildWaterIndices();
     1171
     1172    // We directly use the vertex buffer in rendering, so we
     1173    // can clear the data buffer for space
     1174    m_WaterVertexData.clear();
     1175}
     1176
     1177
     1178void CPatchRData::BuildWaterIndices()
     1179{
     1180    // release existing indices
     1181    m_WaterIndices.clear();
     1182
     1183    if (FullyEmerged())
     1184        return;
     1185
     1186    // must have allocated some vertices before trying to build corresponding indices
     1187    debug_assert(m_VBWater);
     1188
     1189    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1190
     1191    CPatch* patch = m_Patch;
     1192    CTerrain* terrain = patch->m_Parent;
     1193
     1194    // build indices for water
     1195    // TODO: Adapt method for non fancy water!
     1196    size_t base_indice=m_VBWater->m_Index;
     1197
     1198    for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
     1199    {
     1200        for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
     1201        {
     1202            ssize_t x = (patch->m_X*PATCH_SIZE + dx);
     1203            ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     1204
     1205            // Some offsets used to go around counterclockwise while keeping code concise
     1206            const int DX[] = {1,1,0,0};
     1207            const int DZ[] = {0,1,1,0};
     1208
     1209            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z);
     1210
     1211            // NB: I do not reuse the values already computed for building the vertex buffer/data
     1212            // here, even though it would probably be more readable, because it allows to
     1213            // use the same function for building indices for fancy and non-fancy water (which
     1214            // have different vertex buffer elements).
     1215            // But reference visibility info. is for vertices.
     1216
     1217            // is any corner of the tile below the water height? if not, no point rendering it
     1218            bool shouldRender = false;
     1219            for (int j = 0; j < 4; j++)
     1220            {
     1221                const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
     1222                if (terrainHeight < waterHeight)
     1223                {
     1224                    shouldRender = true;
     1225                    break;
     1226                }
     1227            }
     1228            if (!shouldRender)
     1229                continue;
     1230            for (int j=0; j<4; j++)
     1231            {
     1232                ssize_t ix = dx + DX[j];
     1233                ssize_t iz = dz + DZ[j];
     1234                ssize_t v=(iz*(PATCH_SIZE+1))+ix;
     1235                m_WaterIndices.push_back(u16(v)+base_indice);
     1236                debug_assert((u16(v)+base_indice) < 65535);
     1237            }
     1238        }
     1239    }
     1240}
     1241
     1242const float EPSILON = 1e-12;
     1243
     1244// if there is a positive water depth there is water on the patch
     1245bool CPatchRData::HasWaterVisible()
     1246{
     1247    return (max_wdepth > EPSILON);
     1248}
     1249// if the maximum water size is negative, the patch is entirely emerged
     1250bool CPatchRData::FullyEmerged()
     1251{
     1252    return (max_wdepth < EPSILON);
     1253}
     1254// if the minimum water size is still positive, the patch is entirely under water
     1255bool CPatchRData::EntirelyUnderWater()
     1256{
     1257    return (min_wdepth > -EPSILON);
     1258}
     1259
     1260void CPatchRData::RenderSimpleWater()
     1261{
     1262    debug_assert(m_UpdateFlags==0);
     1263
     1264    if (FullyEmerged())
     1265        return;
     1266
     1267    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1268
     1269    // This is probably changing so vertices need update!
     1270    const CCamera& camera = g_Renderer.GetViewCamera();
     1271    CVector3D camPos = camera.m_Orientation.GetTranslation();
     1272
     1273    std::vector<SSimpleWaterVertex> vertices;
     1274    vertices.reserve(m_WaterVertexData.size());
     1275
     1276    // build vertex buffer with adequate alpha
     1277    for (unsigned int i=0; i < m_WaterVertexData.size(); i++) // TODO: Use iterators
     1278    {
     1279        SSimpleWaterVertex vertex;
     1280        // Copy data identical to build time
     1281        vertex.m_Position = m_WaterVertexData[i].m_Position;
     1282        vertex.m_UVs[0] = m_WaterVertexData[i].m_UVs[0];
     1283        vertex.m_UVs[1] = m_WaterVertexData[i].m_UVs[1];
     1284        // We use the same pointer/data in array for saving space
     1285        // vertex.m_PosTex1 = m_WaterVertexData[i].m_Position;
     1286
     1287        const float alpha = clamp( (m_WaterVertexData[i].m_Depth) / WaterMgr->m_WaterFullDepth
     1288                     + WaterMgr->m_WaterAlphaOffset,
     1289                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     1290
     1291        // (Crappy) fresnel effect
     1292        CVector3D CamFaceVertex=CVector3D(vertex.m_Position.X,WaterMgr->m_WaterHeight,vertex.m_Position.Z)-camPos;
     1293                    // Note: WaterMgr->m_WaterHeight is also vertex.m_Position.Y I think...
     1294        CamFaceVertex.Normalize();
     1295        float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
     1296        // Invert and set boundaries
     1297        FresnelScalar = 1.f - (FresnelScalar * 0.6);
     1298        // Set Color
     1299        vertex.m_Color.m_X = WaterMgr->m_WaterColor.r;
     1300        vertex.m_Color.m_Y = WaterMgr->m_WaterColor.g;
     1301        vertex.m_Color.m_Z = WaterMgr->m_WaterColor.b;
     1302        vertex.m_Color.m_W = alpha * FresnelScalar;
     1303
     1304        // save the finalized vertex built
     1305        vertices.push_back(vertex);
     1306    }
     1307    // upload to vertex buffer
     1308    m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&vertices[0]);
     1309
     1310    SSimpleWaterVertex *base=(SSimpleWaterVertex *)m_VBWater->m_Owner->Bind();
     1311
     1312    // setup data pointers
     1313    GLsizei stride = sizeof(SSimpleWaterVertex);
     1314    glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]);
     1315    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1316    pglClientActiveTextureARB(GL_TEXTURE0);
     1317    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);    // render
     1318    pglClientActiveTextureARB(GL_TEXTURE1);
     1319    glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);   // (same data as vertex)
     1320    // glTexCoordPointer(3, GL_FLOAT, stride, &base->m_PosTex1[0]);
     1321
     1322    if (!g_Renderer.m_SkipSubmit) {
     1323        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1324            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1325    }
     1326    // bump stats
     1327    g_Renderer.m_Stats.m_DrawCalls++;
     1328    // TODO: Water stats?
     1329
     1330    CVertexBuffer::Unbind();
     1331}
     1332
     1333void CPatchRData::RenderFancyWater(GLint waterDepth)
     1334{
     1335    debug_assert(m_UpdateFlags==0);
     1336
     1337    if (FullyEmerged())
     1338        return;
     1339
     1340    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1341
     1342    // setup data pointers
     1343    GLsizei stride = sizeof(SWaterVertex);
     1344    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1345    pglClientActiveTextureARB(GL_TEXTURE0);
     1346    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
     1347    pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */
     1348            stride, &base->m_Depth);
     1349    // render
     1350    if (!g_Renderer.m_SkipSubmit) {
     1351        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1352            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1353    }
     1354    // bump stats
     1355    g_Renderer.m_Stats.m_DrawCalls++;
     1356    // TODO: Water stats?
     1357
     1358    CVertexBuffer::Unbind();
     1359
     1360}
     1361
  • source/renderer/TerrainRenderer.cpp

     
    163163
    164164
    165165///////////////////////////////////////////////////////////////////
     166
     167bool TerrainRenderer::HasWaterVisible()
     168{
     169    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
     170    {
     171        CPatchRData* patchdata = m->visiblePatches[i];
     172        if (patchdata->HasWaterVisible())
     173            return true;
     174    }
     175    return false;
     176}
     177
     178///////////////////////////////////////////////////////////////////
    166179// Full-featured terrain rendering with blending and everything
    167 void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
     180void TerrainRenderer::RenderTerrain(ShadowMap* shadow, RenderTerrainMode mode)
    168181{
     182    PROFILE("render terrain");
     183
    169184    debug_assert(m->phase == Phase_Render);
    170185
     186#if 0
     187// Debug Savings evaluation
     188    int c = 0;
     189    int d = 0;
     190    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
     191    {
     192        CPatchRData* patchdata = m->visiblePatches[i];
     193        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) c++;
     194        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) d++;
     195    }
     196    if (mode == NOT_UNDERWATER)
     197        std::cout << " Saving under=" << c << " patchrendering on frame" << std::endl;
     198    else if (mode == NOT_EMERGED)
     199        std::cout << " Saving emerged=" << d << " patchrendering on frame" << std::endl;
     200#endif
     201
     202    std::vector<CPatchRData*> patchesToRender;
     203    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
     204    {
     205        CPatchRData* patchdata = m->visiblePatches[i];
     206        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) continue;
     207        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) continue;
     208        patchesToRender.push_back(patchdata);
     209    }
     210
    171211    // render the solid black sides of the map first
    172212    g_Renderer.BindTexture(0, 0);
    173213    glEnableClientState(GL_VERTEX_ARRAY);
    174214    glColor3f(0, 0, 0);
    175215    PROFILE_START("render terrain sides");
    176     for (size_t i = 0; i < m->visiblePatches.size(); ++i)
    177         m->visiblePatches[i]->RenderSides();
     216    for(size_t i = 0; i < patchesToRender.size(); ++i)
     217        patchesToRender[i]->RenderSides();
    178218    PROFILE_END("render terrain sides");
    179219
    180220    // switch on required client states
     
    197237    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one);
    198238   
    199239    PROFILE_START("render terrain base");
    200     CPatchRData::RenderBases(m->visiblePatches);
     240    CPatchRData::RenderBases(patchesToRender);
    201241    PROFILE_END("render terrain base");
    202242
    203243    // render blends
     
    227267   
    228268    // render blend passes for each patch
    229269    PROFILE_START("render terrain blends");
    230     CPatchRData::RenderBlends(m->visiblePatches);
     270    CPatchRData::RenderBlends(patchesToRender);
    231271    PROFILE_END("render terrain blends");
    232272
    233273    // Disable second texcoord array
     
    444484    pglClientActiveTextureARB(GL_TEXTURE0);
    445485
    446486    PROFILE_START("render terrain streams");
    447     CPatchRData::RenderStreams(m->visiblePatches, streamflags);
     487    CPatchRData::RenderStreams(patchesToRender, streamflags);
    448488    PROFILE_END("render terrain streams");
    449489
    450490    glMatrixMode(GL_TEXTURE);
     
    521561    glDisableClientState(GL_VERTEX_ARRAY);
    522562}
    523563
    524 
    525 ///////////////////////////////////////////////////////////////////
    526 // Render water that is part of the terrain
    527 void TerrainRenderer::RenderWater()
     564// Render fancy water
     565bool TerrainRenderer::RenderFancyWater()
    528566{
    529     PROFILE( "render water" );
     567    PROFILE( "render fancy water" );
    530568
    531569    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    532570
    533     bool fancy = WaterMgr->WillRenderFancyWater();
    534 
    535     // If we're using fancy water, make sure its shader is loaded
    536     if(fancy && !m->fancyWaterShader)
     571    // We're using fancy water, make sure its shader is loaded
     572    if(!m->fancyWaterShader)
    537573    {
    538574        Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml");
    539575        if (h < 0)
    540576        {
    541577            LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
    542578            g_Renderer.m_Options.m_FancyWater = false;
    543             fancy = false;
     579            return false;
    544580        }
    545581        else
    546582        {
    547583            m->fancyWaterShader = h;
    548584        }
    549585    }
    550     CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
    551586
    552587    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
    553588   
     
    561596    double period = 1.6;
    562597    int curTex = (int)(time*60/period) % 60;
    563598
    564     if(fancy)
    565     {
    566         WaterMgr->m_NormalMap[curTex]->Bind();
    567     }
    568     else
    569     {
    570         WaterMgr->m_WaterTexture[curTex]->Bind();
    571     }
     599    WaterMgr->m_NormalMap[curTex]->Bind();
    572600
    573601    // Shift the texture coordinates by these amounts to make the water "flow"
    574602    float tx = -fmod(time, 81.0)/81.0;
    575603    float ty = -fmod(time, 34.0)/34.0;
    576604
    577     if(!fancy)
    578     {
    579         // Perform the shifting by modifying the texture matrix
    580         glMatrixMode(GL_TEXTURE);
    581         glLoadIdentity();
    582         glTranslatef(tx, ty, 0);
     605    // Set the proper LOD bias
     606    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    583607
    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);
     608    const CCamera& camera = g_Renderer.GetViewCamera();
     609    CVector3D camPos = camera.m_Orientation.GetTranslation();
    594610
    595         // Multiply by LOS texture
    596         losTexture.BindTexture(1);
    597         pglClientActiveTextureARB(GL_TEXTURE1);
    598         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     611    // Bind reflection and refraction textures on texture units 1 and 2
     612    pglActiveTextureARB( GL_TEXTURE1_ARB );
     613    glEnable( GL_TEXTURE_2D );
     614    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
     615    pglActiveTextureARB( GL_TEXTURE2_ARB );
     616    glEnable( GL_TEXTURE_2D );
     617    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
    599618
    600         glLoadMatrixf(losTexture.GetTextureMatrix());
     619    losTexture.BindTexture(3);
    601620
    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     }
     621    // Bind water shader and set arguments
     622    ogl_program_use( m->fancyWaterShader );
    612623
    613     // Set the proper LOD bias
    614     glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     624    GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
     625    GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
     626    GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
     627    GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
     628    GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
     629    GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
     630    GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
     631    GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
     632    GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
     633    GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
     634    GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
     635    GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
     636    GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
     637    GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
     638    GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
     639    GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
     640    GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
     641    GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
     642    GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
     643    GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
    615644
    616     const CCamera& camera = g_Renderer.GetViewCamera();
    617     CVector3D camPos = camera.m_Orientation.GetTranslation();
     645    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
     646    pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
     647    pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
     648    pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
     649    pglUniform1fARB( shininess, WaterMgr->m_Shininess );
     650    pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
     651    pglUniform1fARB( waviness, WaterMgr->m_Waviness );
     652    pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
     653    pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
     654    pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
     655    pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
     656    pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
     657    pglUniform4fARB( translation, tx, ty, 0, 0 );
     658    pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
     659    pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
     660    pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
     661    pglUniform1iARB( normalMap, 0 );        // texture unit 0
     662    pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
     663    pglUniform1iARB( refractionMap, 2 );    // texture unit 2
     664    pglUniform1iARB( losMap, 3 );           // texture unit 3
     665    pglUniform3fvARB( cameraPos, 1, &camPos.X );
    618666
    619     GLint vertexDepth = 0;  // water depth attribute, if using fancy water
     667//  glActiveTexture(GL_TEXTURE0);
    620668
    621     if(fancy)
     669    glEnableClientState(GL_VERTEX_ARRAY);
     670    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     671    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     672
     673    // water depth attribute, when using fancy water
     674    GLint vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
     675    pglEnableVertexAttribArrayARB(vertexDepth);
     676   
     677    for(size_t i=0; i<m->visiblePatches.size(); i++)
    622678    {
    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 );
     679        CPatchRData* patchdata = m->visiblePatches[i];
     680        patchdata->RenderFancyWater(vertexDepth);
     681    }
    630682
    631         losTexture.BindTexture(3);
     683    pglDisableVertexAttribArrayARB(vertexDepth);
     684    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     685    glDisableClientState(GL_VERTEX_ARRAY);
    632686
    633         // Bind water shader and set arguments
    634         ogl_program_use( m->fancyWaterShader );
     687    // Unbind the LOS/refraction/reflection textures and the shader
     688    g_Renderer.BindTexture(3, 0);
     689    g_Renderer.BindTexture(2, 0);
     690    g_Renderer.BindTexture(1, 0);
     691    pglActiveTextureARB(GL_TEXTURE0_ARB);
     692    ogl_program_use(0);
    635693
    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" );
     694    glMatrixMode(GL_MODELVIEW);
     695    glDisable(GL_BLEND);
     696    glDisable(GL_TEXTURE_2D);
    656697
    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 );
     698    return true;
     699}
    678700
    679         vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
    680     }
     701void TerrainRenderer::RenderSimpleWater()
     702{
     703    PROFILE( "render simple water" );
     704
     705    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     706
     707    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
    681708   
    682     float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
     709    glEnable(GL_BLEND);
     710    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     711    glEnable(GL_DEPTH_TEST);
     712    glDepthFunc(GL_LEQUAL);
    683713
    684     glBegin(GL_QUADS);
     714    double time = WaterMgr->m_WaterTexTimer;
    685715
    686     for(size_t i=0; i<m->visiblePatches.size(); i++)
    687     {
    688         CPatch* patch = m->visiblePatches[i]->GetPatch();
     716    double period = 16.0f;
     717    int curTex = (int)(time*60/period) % 60;
    689718
    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);
     719    WaterMgr->m_WaterTexture[curTex]->Bind();
    696720
    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};
     721    // Shift the texture coordinates by these amounts to make the water "flow"
     722    float tx = -fmod(time, 81.0)/81.0;
     723    float ty = -fmod(time, 34.0)/34.0;
    700724
    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;
     725    // Perform the shifting by modifying the texture matrix
     726    glMatrixMode(GL_TEXTURE);
     727    glLoadIdentity();
     728    glTranslatef(tx, ty, 0);
    714729
    715                 for (int j=0; j<4; j++)
    716                 {
    717                     ssize_t ix = x + DX[j];
    718                     ssize_t iz = z + DZ[j];
     730    // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
     731    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     732    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     733    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     734    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     735    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
     736    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     737    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     738    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
     739    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    719740
    720                     float vertX = ix * CELL_SIZE;
    721                     float vertZ = iz * CELL_SIZE;
     741    // Multiply by LOS texture
     742    losTexture.BindTexture(1);
     743    pglClientActiveTextureARB(GL_TEXTURE1);
     744    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    722745
    723                     float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
     746    glLoadMatrixf(losTexture.GetTextureMatrix());
    724747
    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);
     748    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     749    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     750    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     751    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     752    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     753    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     754    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     755    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     756    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    735757
    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);
    742758
    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                     }
     759    // Set the proper LOD bias
     760    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    751761
    752                 }
    753             }   //end of x loop
    754         }   //end of z loop
    755     }
    756     glEnd();
     762    glEnableClientState(GL_VERTEX_ARRAY);
     763    glEnableClientState(GL_COLOR_ARRAY);
     764    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     765    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    757766
    758     if (fancy)
     767    for(size_t i=0; i<m->visiblePatches.size(); i++)
    759768    {
    760         // Unbind the LOS/refraction/reflection textures and the shader
     769        CPatchRData* patchdata = m->visiblePatches[i];
     770        patchdata->RenderSimpleWater();
     771    }
    761772
    762         g_Renderer.BindTexture(3, 0);
    763         g_Renderer.BindTexture(2, 0);
    764         g_Renderer.BindTexture(1, 0);
     773    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     774    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     775    glDisableClientState(GL_COLOR_ARRAY);
     776    glDisableClientState(GL_VERTEX_ARRAY);
    765777
    766         pglActiveTextureARB(GL_TEXTURE0_ARB);
     778    g_Renderer.BindTexture(1, 0);
     779    pglClientActiveTextureARB(GL_TEXTURE1_ARB);
     780    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    767781
    768         ogl_program_use(0);
    769     }
     782    glLoadIdentity();
    770783
    771     if (!fancy)
    772     {
    773         g_Renderer.BindTexture(1, 0);
    774         pglClientActiveTextureARB(GL_TEXTURE1_ARB);
    775         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     784    pglActiveTextureARB(GL_TEXTURE0_ARB);
     785    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    776786
    777         glLoadIdentity();
     787    // Clean up the texture matrix and blend mode
     788    glLoadIdentity();
     789    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    778790
    779         pglActiveTextureARB(GL_TEXTURE0_ARB);
    780         pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    781 
    782         // Clean up the texture matrix and blend mode
    783         glLoadIdentity();
    784         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    785     }
    786 
    787791    glMatrixMode(GL_MODELVIEW);
    788792    glDisable(GL_BLEND);
    789793    glDisable(GL_TEXTURE_2D);
    790794}
    791795
     796
     797///////////////////////////////////////////////////////////////////
     798// Render water that is part of the terrain
     799void TerrainRenderer::RenderWater()
     800{
     801    // PROFILE is defined in one of the sub functions
     802
     803    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     804
     805    bool fancy = WaterMgr->WillRenderFancyWater();
     806
     807    if (fancy) {
     808        bool r = RenderFancyWater();
     809        if (r) return;
     810    }
     811    RenderSimpleWater();
     812}
     813
    792814void TerrainRenderer::RenderPriorities()
    793815{
    794816    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();