Ticket #721: water_ro_r2.patch

File water_ro_r2.patch, 38.2 KB (added by Rodolphe Ortalo, 13 years ago)

patch with respect to trunk/ and revision 9001

  • source/renderer/PatchRData.h

     
    4444    void RenderSides();
    4545    void RenderPriorities();
    4646
     47    void RenderFancyWater(GLint waterDepth);
     48    void RenderSimpleWater();
     49
     50    // Check if there is water on this patch
     51    bool HasWaterVisible();
     52    bool FullyEmerged();
     53    bool EntirelyUnderWater();
    4754private:
    4855    struct SSplat {
    4956        SSplat() : m_Texture(0), m_IndexCount(0) {}
     
    117124
    118125    // splats used in blend pass
    119126    std::vector<SSplat> m_BlendSplats;
     127
     128    // Simple water vertex description data structure
     129    struct SSimpleWaterVertex {
     130        // vertex position
     131        CVector3D m_Position;
     132        // vertex uvs for texture 0
     133        float m_UVs[2];
     134        // vertex 3d for texture 1 == vertex position so removed
     135        // CVector3D m_PosTex1;
     136        // Color TODO: Try to use packed colors? (here:floats)
     137        RGBAColor m_Color;
     138    };
     139
     140    // Fancy water vertex description data structure
     141    struct SWaterVertex {
     142        // vertex position
     143        CVector3D m_Position;
     144        // vertex uvs for normal map texture
     145        float m_UVs[2];
     146        // water depth (varying for shader)
     147        float m_Depth;
     148    };
     149
     150    void BuildSimpleWaterVertices();
     151    void BuildFancyWaterVertices();
     152
     153    void BuildWaterVertexData(); // Common to simple and fancy water
     154
     155    // Water vertex buffer
     156    CVertexBuffer::VBChunk* m_VBWater;
     157
     158    // Water indices into buffer
     159    // NB: Indices are identical for fancy or regular water (same path)
     160    void BuildWaterIndices();
     161
     162    // 256*256 seems to be enough
     163    std::vector<unsigned short> m_WaterIndices;
     164
     165    // Build data for fancy water or reference data for
     166    // computing simple water
     167    std::vector<SWaterVertex> m_WaterVertexData;
     168
     169    // maximum and minimum depth of water at all vertices on the patch
     170    // signed value: can be negative (if vertex emerges of water)
     171    float max_wdepth;
     172    float min_wdepth;
    120173};
    121174
    122175
  • source/renderer/TerrainRenderer.h

     
    7575     */
    7676    bool HaveSubmissions();
    7777
     78    /*
     79     * HasWaterVisible: indicate if one of the patches currently visible
     80     * has water visible.
     81     */
     82    bool HasWaterVisible();
     83
     84
    7885    /**
    7986     * RenderTerrain: Render textured terrain (including blends between
    8087     * different terrain types).
     
    8491     *
    8592     * @param shadow A prepared shadow map, in case rendering with shadows is enabled.
    8693     */
    87     void RenderTerrain(ShadowMap* shadow);
     94    enum RenderTerrainMode { // Offer the ability to skip some patches (reflections, refractions)
     95        NORMAL,
     96        NOT_UNDERWATER,
     97        NOT_EMERGED,
     98    };
     99    void RenderTerrain(ShadowMap* shadow, RenderTerrainMode mode = NORMAL);
    88100
    89101    /**
    90102     * RenderPatches: Render all patches un-textured as polygons.
     
    118130
    119131private:
    120132    TerrainRendererInternals* m;
     133
     134    /*
     135     * RenderFancyWater: internal rendering method for fancy water
     136     */
     137    bool RenderFancyWater();
     138    /*
     139     * RenderSimpleWater: internal rendering method for water
     140     */
     141    void RenderSimpleWater();
    121142};
    122143
    123144#endif // INCLUDED_TERRAINRENDERER
  • source/renderer/Renderer.cpp

     
    10841084    // Render sky, terrain and models
    10851085    m->skyManager.RenderSky();
    10861086    ogl_WarnIfError();
    1087     RenderPatches();
     1087//  RenderPatches();
     1088    // Directly call terrain renderer without underwater patches
     1089    // render all the patches, including blend pass
     1090    m->terrainRenderer->RenderTerrain((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0, TerrainRenderer::NOT_UNDERWATER);
     1091
    10881092    ogl_WarnIfError();
    10891093    RenderModels();
    10901094    ogl_WarnIfError();
     
    11501154    glDepthFunc(GL_GEQUAL);
    11511155
    11521156    // Render terrain and models
    1153     RenderPatches();
     1157//  RenderPatches();
     1158    // Directly call terrain renderer without fully emerged (out of water) patches
     1159    // render all the patches, including blend pass
     1160    m->terrainRenderer->RenderTerrain((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0, TerrainRenderer::NOT_EMERGED);
    11541161    ogl_WarnIfError();
    11551162    RenderModels();
    11561163    ogl_WarnIfError();
     
    12131220
    12141221    ogl_WarnIfError();
    12151222
    1216     if (m_WaterManager->m_RenderWater && m_WaterManager->WillRenderFancyWater())
     1223    if (m_WaterManager->m_RenderWater && m_WaterManager->WillRenderFancyWater() && m->terrainRenderer->HasWaterVisible())
    12171224    {
    12181225        // render reflected and refracted scenes, then re-clear the screen
    12191226        RenderReflections();
     
    12501257    ogl_WarnIfError();
    12511258
    12521259    // render water
    1253     if (m_WaterManager->m_RenderWater && g_Game)
     1260    PROFILE_START("render water");
     1261    if (m_WaterManager->m_RenderWater && g_Game && m->terrainRenderer->HasWaterVisible())
    12541262    {
    12551263        m->terrainRenderer->RenderWater();
    12561264        ogl_WarnIfError();
     
    12671275        // turning the water off. On the other hand every user will have water
    12681276        // on all the time, so it might not be worth worrying about.
    12691277    }
     1278    PROFILE_END("render water");
    12701279
    12711280    // Clean up texture blend mode so particles and other things render OK
    12721281    // (really this should be cleaned up by whoever set it)
  • source/renderer/PatchRData.cpp

     
    5454///////////////////////////////////////////////////////////////////
    5555// CPatchRData constructor
    5656CPatchRData::CPatchRData(CPatch* patch) :
    57     m_Patch(patch), m_VBBase(0), m_VBSides(0), m_VBBlends(0), m_Vertices(0)
     57    m_Patch(patch), m_VBBase(0), m_VBSides(0), m_VBBlends(0), m_Vertices(0),
     58    m_VBWater(0), max_wdepth(-FLT_MAX), min_wdepth(FLT_MAX)
    5859{
    5960    debug_assert(patch);
    6061    Build();
     
    561562    BuildSides();
    562563    BuildIndices();
    563564    BuildBlends();
     565
     566    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     567    if (WaterMgr->WillRenderFancyWater()) {
     568        // TODO: Switch on fancy or not fancy water
     569        BuildFancyWaterVertices();
     570    } else {
     571        BuildSimpleWaterVertices();
     572    }
     573        BuildWaterIndices();
    564574}
    565575
    566576void CPatchRData::Update()
     
    574584        BuildIndices();
    575585        BuildBlends();
    576586
     587        WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     588        if (WaterMgr->WillRenderFancyWater()) {
     589            // TODO: Switch on fancy or not fancy water
     590            BuildFancyWaterVertices();
     591        } else {
     592            BuildSimpleWaterVertices();
     593        }
     594
    577595        m_UpdateFlags=0;
    578596    }
    579597}
     
    708726        g_Renderer.m_Stats.m_BlendSplats++;
    709727        g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
    710728    }
    711 
    712729    CVertexBuffer::Unbind();
    713730}
    714731
     
    799816        }
    800817    }
    801818}
     819
     820//
     821// Water build and rendering
     822//
     823
     824// Build vertex buffer for water vertices over our patch
     825void CPatchRData::BuildWaterVertexData()
     826{
     827    // number of vertices in each direction in each patch
     828    const ssize_t vsize=PATCH_SIZE+1;
     829
     830    m_WaterVertexData.resize(vsize*vsize);
     831
     832    // We need to use this to access the water manager or we may not have the
     833    // actual values but some compiled-in defaults
     834    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     835
     836    // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
     837    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     838    const float repeatPeriod = WaterMgr->m_RepeatPeriod;
     839#if 0
     840    // With non fancy water, period is a constant? TODO: Check
     841    const float repeatPeriod = 16.0f;
     842#endif
     843
     844
     845    CPatch* patch = m_Patch;
     846    CTerrain* terrain = patch->m_Parent;
     847
     848    max_wdepth = -FLT_MAX;
     849    min_wdepth = FLT_MAX;
     850    // build vertices, uv, and shader varying
     851    for (ssize_t j=0;j<vsize;j++)
     852    {
     853        for (ssize_t i=0;i<vsize;i++)
     854        {
     855            ssize_t ix=(patch->m_X*PATCH_SIZE)+i;
     856            ssize_t iz=(patch->m_Z*PATCH_SIZE)+j;
     857            ssize_t v=(j*vsize)+i;
     858
     859            // calculate vertex data like for base vertices
     860            terrain->CalcPosition(ix,iz,m_WaterVertexData[v].m_Position);
     861            // at this step, Y is still terrainHeight
     862            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz);
     863            const float wdepth = waterHeight - m_WaterVertexData[v].m_Position.Y;
     864            m_WaterVertexData[v].m_Depth = wdepth;
     865            // replaces Y by water height
     866            m_WaterVertexData[v].m_Position.Y = waterHeight;
     867            // calculates U/V (TODO: could be done in shader? would be beneficial?)
     868            m_WaterVertexData[v].m_UVs[0] = m_WaterVertexData[v].m_Position.X / repeatPeriod;
     869            m_WaterVertexData[v].m_UVs[1] = m_WaterVertexData[v].m_Position.Z / repeatPeriod;
     870            // update min and max depth over patch
     871            if (wdepth > max_wdepth) max_wdepth = wdepth;
     872            if (wdepth < min_wdepth) min_wdepth = wdepth;
     873        }
     874    }
     875}
     876
     877// Build all that can be done at build time for simple water
     878void CPatchRData::BuildSimpleWaterVertices()
     879{
     880    BuildWaterVertexData();
     881    // overall depth around patch is ready now
     882    // so, if we are fully emerged, we can get rid of things
     883    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     884    {
     885        if (m_VBWater) {
     886            g_VBMan.Release(m_VBWater);
     887        }
     888    }
     889    else
     890    {
     891        // allocate vertex buffer (only: update is done at render time)
     892        if (!m_VBWater) {
     893            m_VBWater=g_VBMan.Allocate(sizeof(SSimpleWaterVertex),m_WaterVertexData.size(),true);
     894        }
     895        debug_assert(m_VBWater->m_Index < 65536);
     896    }
     897
     898    // The vertex buffer must be ready for indices calculation
     899    BuildWaterIndices();
     900}
     901
     902void CPatchRData::BuildFancyWaterVertices()
     903{
     904    BuildWaterVertexData();
     905    // overall depth around patch is ready now
     906    // so, if we are fully emerged, we can get rid of things
     907    if (FullyEmerged())         // i.e.: (max_wdepth < 0.0f)
     908    {
     909        if (m_VBWater) {
     910            g_VBMan.Release(m_VBWater);
     911        }
     912    }
     913    else
     914    {
     915        // we directly use the vertex data for rendering
     916        // upload to vertex buffer
     917        if (!m_VBWater) {
     918            m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),m_WaterVertexData.size(),true);
     919        }
     920        m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]);
     921        debug_assert(m_VBWater->m_Index < 65536);
     922    }
     923    // The vertex buffer must be ready for indices calculation
     924    BuildWaterIndices();
     925
     926    // We directly use the vertex buffer in rendering, so we
     927    // can clear the data buffer for space
     928    m_WaterVertexData.clear();
     929}
     930
     931
     932void CPatchRData::BuildWaterIndices()
     933{
     934    // release existing indices
     935    m_WaterIndices.clear();
     936
     937    if (FullyEmerged())
     938        return;
     939
     940    // must have allocated some vertices before trying to build corresponding indices
     941    debug_assert(m_VBWater);
     942
     943    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     944
     945    CPatch* patch = m_Patch;
     946    CTerrain* terrain = patch->m_Parent;
     947
     948    // build indices for water
     949    // TODO: Adapt method for non fancy water!
     950    size_t base_indice=m_VBWater->m_Index;
     951
     952    for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
     953    {
     954        for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
     955        {
     956            ssize_t x = (patch->m_X*PATCH_SIZE + dx);
     957            ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     958
     959            // Some offsets used to go around counterclockwise while keeping code concise
     960            const int DX[] = {1,1,0,0};
     961            const int DZ[] = {0,1,1,0};
     962
     963            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z);
     964
     965            // NB: I do not reuse the values already computed for building the vertex buffer/data
     966            // here, even though it would probably be more readable, because it allows to
     967            // use the same function for building indices for fancy and non-fancy water (which
     968            // have different vertex buffer elements).
     969            // But reference visibility info. is for vertices.
     970
     971            // is any corner of the tile below the water height? if not, no point rendering it
     972            bool shouldRender = false;
     973            for (int j = 0; j < 4; j++)
     974            {
     975                const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
     976                if (terrainHeight < waterHeight)
     977                {
     978                    shouldRender = true;
     979                    break;
     980                }
     981            }
     982            if (!shouldRender)
     983                continue;
     984            for (int j=0; j<4; j++)
     985            {
     986                ssize_t ix = dx + DX[j];
     987                ssize_t iz = dz + DZ[j];
     988                ssize_t v=(iz*(PATCH_SIZE+1))+ix;
     989                m_WaterIndices.push_back(u16(v)+base_indice);
     990                debug_assert((u16(v)+base_indice) < 65535);
     991            }
     992        }
     993    }
     994}
     995
     996const float EPSILON = 1e-12;
     997
     998// if there is a positive water depth there is water on the patch
     999bool CPatchRData::HasWaterVisible()
     1000{
     1001    return (max_wdepth > EPSILON);
     1002}
     1003// if the maximum water size is negative, the patch is entirely emerged
     1004bool CPatchRData::FullyEmerged()
     1005{
     1006    return (max_wdepth < EPSILON);
     1007}
     1008// if the minimum water size is still positive, the patch is entirely under water
     1009bool CPatchRData::EntirelyUnderWater()
     1010{
     1011    return (min_wdepth > -EPSILON);
     1012}
     1013
     1014void CPatchRData::RenderSimpleWater()
     1015{
     1016    debug_assert(m_UpdateFlags==0);
     1017
     1018    if (FullyEmerged())
     1019        return;
     1020
     1021    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1022
     1023    // This is probably changing so vertices need update!
     1024    const CCamera& camera = g_Renderer.GetViewCamera();
     1025    CVector3D camPos = camera.m_Orientation.GetTranslation();
     1026
     1027    std::vector<SSimpleWaterVertex> vertices;
     1028    vertices.reserve(m_WaterVertexData.size());
     1029
     1030    // build vertex buffer with adequate alpha
     1031    for (unsigned int i=0; i < m_WaterVertexData.size(); i++) // TODO: Use iterators
     1032    {
     1033        SSimpleWaterVertex vertex;
     1034        // Copy data identical to build time
     1035        vertex.m_Position = m_WaterVertexData[i].m_Position;
     1036        vertex.m_UVs[0] = m_WaterVertexData[i].m_UVs[0];
     1037        vertex.m_UVs[1] = m_WaterVertexData[i].m_UVs[1];
     1038        // We use the same pointer/data in array for saving space
     1039        // vertex.m_PosTex1 = m_WaterVertexData[i].m_Position;
     1040
     1041        const float alpha = clamp( (m_WaterVertexData[i].m_Depth) / WaterMgr->m_WaterFullDepth
     1042                     + WaterMgr->m_WaterAlphaOffset,
     1043                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     1044
     1045        // (Crappy) fresnel effect
     1046        CVector3D CamFaceVertex=CVector3D(vertex.m_Position.X,WaterMgr->m_WaterHeight,vertex.m_Position.Z)-camPos;
     1047                    // Note: WaterMgr->m_WaterHeight is also vertex.m_Position.Y I think...
     1048        CamFaceVertex.Normalize();
     1049        float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
     1050        // Invert and set boundaries
     1051        FresnelScalar = 1.f - (FresnelScalar * 0.6);
     1052        // Set Color
     1053        vertex.m_Color.m_X = WaterMgr->m_WaterColor.r;
     1054        vertex.m_Color.m_Y = WaterMgr->m_WaterColor.g;
     1055        vertex.m_Color.m_Z = WaterMgr->m_WaterColor.b;
     1056        vertex.m_Color.m_W = alpha * FresnelScalar;
     1057
     1058        // save the finalized vertex built
     1059        vertices.push_back(vertex);
     1060    }
     1061    // upload to vertex buffer
     1062    m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&vertices[0]);
     1063
     1064    SSimpleWaterVertex *base=(SSimpleWaterVertex *)m_VBWater->m_Owner->Bind();
     1065
     1066    // setup data pointers
     1067    GLsizei stride = sizeof(SSimpleWaterVertex);
     1068    glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]);
     1069    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1070    pglClientActiveTextureARB(GL_TEXTURE0);
     1071    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);    // render
     1072    pglClientActiveTextureARB(GL_TEXTURE1);
     1073    glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);   // (same data as vertex)
     1074    // glTexCoordPointer(3, GL_FLOAT, stride, &base->m_PosTex1[0]);
     1075
     1076    if (!g_Renderer.m_SkipSubmit) {
     1077        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1078            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1079    }
     1080    // bump stats
     1081    g_Renderer.m_Stats.m_DrawCalls++;
     1082    // TODO: Water stats?
     1083
     1084    CVertexBuffer::Unbind();
     1085}
     1086
     1087void CPatchRData::RenderFancyWater(GLint waterDepth)
     1088{
     1089    debug_assert(m_UpdateFlags==0);
     1090
     1091    if (FullyEmerged())
     1092        return;
     1093
     1094    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1095
     1096    // setup data pointers
     1097    GLsizei stride = sizeof(SWaterVertex);
     1098    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1099    pglClientActiveTextureARB(GL_TEXTURE0);
     1100    glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
     1101    pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */
     1102            stride, &base->m_Depth);
     1103    // render
     1104    if (!g_Renderer.m_SkipSubmit) {
     1105        glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(),
     1106            GL_UNSIGNED_SHORT, &m_WaterIndices[0]);
     1107    }
     1108    // bump stats
     1109    g_Renderer.m_Stats.m_DrawCalls++;
     1110    // TODO: Water stats?
     1111
     1112    CVertexBuffer::Unbind();
     1113
     1114}
     1115
  • source/renderer/TerrainRenderer.cpp

     
    149149}
    150150
    151151
     152bool TerrainRenderer::HasWaterVisible()
     153{
     154    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
     155    {
     156        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     157        if (patchdata->HasWaterVisible())
     158            return true;
     159    }
     160    return false;
     161}
     162
    152163///////////////////////////////////////////////////////////////////
    153164// Full-featured terrain rendering with blending and everything
    154 void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
     165void TerrainRenderer::RenderTerrain(ShadowMap* shadow, RenderTerrainMode mode)
    155166{
     167    PROFILE("render terrain");
     168
    156169    debug_assert(m->phase == Phase_Render);
    157170
     171#if 0
     172// Debug Savings evaluation
     173    int c = 0;
     174    int d = 0;
     175    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
     176    {
     177        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     178        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) c++;
     179        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) d++;
     180    }
     181    if (mode == NOT_UNDERWATER)
     182        std::cout << " Saving under=" << c << " patchrendering on frame" << std::endl;
     183    else if (mode == NOT_EMERGED)
     184        std::cout << " Saving emerged=" << d << " patchrendering on frame" << std::endl;
     185#endif
     186
    158187    // render the solid black sides of the map first
    159188    g_Renderer.BindTexture(0, 0);
    160189    glEnableClientState(GL_VERTEX_ARRAY);
     
    162191    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
    163192    {
    164193        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     194        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) continue;
     195        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) continue;
    165196        patchdata->RenderSides();
    166197    }
    167198
     
    187218    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
    188219    {
    189220        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     221        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) continue;
     222        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) continue;
    190223        patchdata->RenderBase();
    191224    }
    192225   
     
    219252    for(size_t i = 0; i < m->visiblePatches.size(); ++i)
    220253    {
    221254        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     255        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) continue;
     256        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) continue;
    222257        patchdata->RenderBlends();
    223258    }
    224259   
     
    415450    for (size_t i = 0; i < m->visiblePatches.size(); ++i)
    416451    {
    417452        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     453        if ((mode == NOT_UNDERWATER) && (patchdata->EntirelyUnderWater())) continue;
     454        if ((mode == NOT_EMERGED) && (patchdata->FullyEmerged())) continue;
    418455        patchdata->RenderStreams(streamflags);
    419456    }
    420457
     
    499536    glDisableClientState(GL_VERTEX_ARRAY);
    500537}
    501538
    502 
    503 ///////////////////////////////////////////////////////////////////
    504 // Render water that is part of the terrain
    505 void TerrainRenderer::RenderWater()
     539// Render fancy water
     540bool TerrainRenderer::RenderFancyWater()
    506541{
    507     PROFILE( "render water" );
     542    PROFILE( "render fancy water" );
    508543
    509544    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    510545
    511     bool fancy = WaterMgr->WillRenderFancyWater();
    512 
    513     // If we're using fancy water, make sure its shader is loaded
    514     if(fancy && !m->fancyWaterShader)
     546    // We're using fancy water, make sure its shader is loaded
     547    if(!m->fancyWaterShader)
    515548    {
    516549        Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml");
    517550        if (h < 0)
    518551        {
    519552            LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
    520553            g_Renderer.m_Options.m_FancyWater = false;
    521             fancy = false;
     554            return false;
    522555        }
    523556        else
    524557        {
    525558            m->fancyWaterShader = h;
    526559        }
    527560    }
    528     CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
    529561
    530562    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
    531563   
     
    539571    double period = 1.6;
    540572    int curTex = (int)(time*60/period) % 60;
    541573
    542     if(fancy)
    543     {
    544         WaterMgr->m_NormalMap[curTex]->Bind();
    545     }
    546     else
    547     {
    548         WaterMgr->m_WaterTexture[curTex]->Bind();
    549     }
     574    WaterMgr->m_NormalMap[curTex]->Bind();
    550575
    551576    // Shift the texture coordinates by these amounts to make the water "flow"
    552577    float tx = -fmod(time, 81.0)/81.0;
    553578    float ty = -fmod(time, 34.0)/34.0;
    554579
    555     if(!fancy)
    556     {
    557         // Perform the shifting by modifying the texture matrix
    558         glMatrixMode(GL_TEXTURE);
    559         glLoadIdentity();
    560         glTranslatef(tx, ty, 0);
     580    // Set the proper LOD bias
     581    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    561582
    562         // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
    563         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    564         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    565         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
    566         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    567         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
    568         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
    569         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    570         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
    571         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
     583    const CCamera& camera = g_Renderer.GetViewCamera();
     584    CVector3D camPos = camera.m_Orientation.GetTranslation();
    572585
    573         // Multiply by LOS texture
    574         losTexture.BindTexture(1);
    575         pglClientActiveTextureARB(GL_TEXTURE1);
    576         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     586    // Bind reflection and refraction textures on texture units 1 and 2
     587    pglActiveTextureARB( GL_TEXTURE1_ARB );
     588    glEnable( GL_TEXTURE_2D );
     589    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
     590    pglActiveTextureARB( GL_TEXTURE2_ARB );
     591    glEnable( GL_TEXTURE_2D );
     592    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
    577593
    578         glLoadMatrixf(losTexture.GetTextureMatrix());
     594    losTexture.BindTexture(3);
    579595
    580         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    581         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    582         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
    583         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    584         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
    585         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
    586         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    587         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
    588         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    589     }
     596    // Bind water shader and set arguments
     597    ogl_program_use( m->fancyWaterShader );
    590598
    591     // Set the proper LOD bias
    592     glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     599    GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
     600    GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
     601    GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
     602    GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
     603    GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
     604    GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
     605    GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
     606    GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
     607    GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
     608    GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
     609    GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
     610    GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
     611    GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
     612    GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
     613    GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
     614    GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
     615    GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
     616    GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
     617    GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
     618    GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
    593619
    594     const CCamera& camera = g_Renderer.GetViewCamera();
    595     CVector3D camPos = camera.m_Orientation.GetTranslation();
     620    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
     621    pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
     622    pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
     623    pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
     624    pglUniform1fARB( shininess, WaterMgr->m_Shininess );
     625    pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
     626    pglUniform1fARB( waviness, WaterMgr->m_Waviness );
     627    pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
     628    pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
     629    pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
     630    pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
     631    pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
     632    pglUniform4fARB( translation, tx, ty, 0, 0 );
     633    pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
     634    pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
     635    pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
     636    pglUniform1iARB( normalMap, 0 );        // texture unit 0
     637    pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
     638    pglUniform1iARB( refractionMap, 2 );    // texture unit 2
     639    pglUniform1iARB( losMap, 3 );           // texture unit 3
     640    pglUniform3fvARB( cameraPos, 1, &camPos.X );
    596641
    597     GLint vertexDepth = 0;  // water depth attribute, if using fancy water
     642//  glActiveTexture(GL_TEXTURE0);
    598643
    599     if(fancy)
     644    glEnableClientState(GL_VERTEX_ARRAY);
     645    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     646    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     647
     648    // water depth attribute, when using fancy water
     649    GLint vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
     650    pglEnableVertexAttribArrayARB(vertexDepth);
     651   
     652    for(size_t i=0; i<m->visiblePatches.size(); i++)
    600653    {
    601         // Bind reflection and refraction textures on texture units 1 and 2
    602         pglActiveTextureARB( GL_TEXTURE1_ARB );
    603         glEnable( GL_TEXTURE_2D );
    604         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
    605         pglActiveTextureARB( GL_TEXTURE2_ARB );
    606         glEnable( GL_TEXTURE_2D );
    607         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
     654        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     655        patchdata->RenderFancyWater(vertexDepth);
     656    }
    608657
    609         losTexture.BindTexture(3);
     658    pglDisableVertexAttribArrayARB(vertexDepth);
     659    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     660    glDisableClientState(GL_VERTEX_ARRAY);
    610661
    611         // Bind water shader and set arguments
    612         ogl_program_use( m->fancyWaterShader );
     662    // Unbind the LOS/refraction/reflection textures and the shader
     663    g_Renderer.BindTexture(3, 0);
     664    g_Renderer.BindTexture(2, 0);
     665    g_Renderer.BindTexture(1, 0);
     666    pglActiveTextureARB(GL_TEXTURE0_ARB);
     667    ogl_program_use(0);
    613668
    614         GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
    615         GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
    616         GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
    617         GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
    618         GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
    619         GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
    620         GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
    621         GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
    622         GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
    623         GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
    624         GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
    625         GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
    626         GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
    627         GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
    628         GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
    629         GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
    630         GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
    631         GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
    632         GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
    633         GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
     669    glMatrixMode(GL_MODELVIEW);
     670    glDisable(GL_BLEND);
     671    glDisable(GL_TEXTURE_2D);
    634672
    635         const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
    636         pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
    637         pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
    638         pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
    639         pglUniform1fARB( shininess, WaterMgr->m_Shininess );
    640         pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
    641         pglUniform1fARB( waviness, WaterMgr->m_Waviness );
    642         pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
    643         pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
    644         pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
    645         pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
    646         pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
    647         pglUniform4fARB( translation, tx, ty, 0, 0 );
    648         pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
    649         pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
    650         pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
    651         pglUniform1iARB( normalMap, 0 );        // texture unit 0
    652         pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
    653         pglUniform1iARB( refractionMap, 2 );    // texture unit 2
    654         pglUniform1iARB( losMap, 3 );           // texture unit 3
    655         pglUniform3fvARB( cameraPos, 1, &camPos.X );
     673    return true;
     674}
    656675
    657         vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
    658     }
     676void TerrainRenderer::RenderSimpleWater()
     677{
     678    PROFILE( "render simple water" );
     679
     680    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     681
     682    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
    659683   
    660     float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
     684    glEnable(GL_BLEND);
     685    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     686    glEnable(GL_DEPTH_TEST);
     687    glDepthFunc(GL_LEQUAL);
    661688
    662     glBegin(GL_QUADS);
     689    double time = WaterMgr->m_WaterTexTimer;
    663690
    664     for(size_t i=0; i<m->visiblePatches.size(); i++)
    665     {
    666         CPatch* patch = m->visiblePatches[i];
     691    double period = 1.6;
     692    int curTex = (int)(time*60/period) % 60;
    667693
    668         for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
    669         {
    670             for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
    671             {
    672                 ssize_t x = (patch->m_X*PATCH_SIZE + dx);
    673                 ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     694    WaterMgr->m_WaterTexture[curTex]->Bind();
    674695
    675                 // Some offsets used to go around counterclockwise while keeping code concise
    676                 const int DX[] = {1,1,0,0};
    677                 const int DZ[] = {0,1,1,0};
     696    // Shift the texture coordinates by these amounts to make the water "flow"
     697    float tx = -fmod(time, 81.0)/81.0;
     698    float ty = -fmod(time, 34.0)/34.0;
    678699
    679                 // is any corner of the tile below the water height? if not, no point rendering it
    680                 bool shouldRender = false;
    681                 for (int j = 0; j < 4; j++)
    682                 {
    683                     float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
    684                     if (terrainHeight < WaterMgr->m_WaterHeight)
    685                     {
    686                         shouldRender = true;
    687                         break;
    688                     }
    689                 }
    690                 if (!shouldRender)
    691                     continue;
     700    // Perform the shifting by modifying the texture matrix
     701    glMatrixMode(GL_TEXTURE);
     702    glLoadIdentity();
     703    glTranslatef(tx, ty, 0);
    692704
    693                 for (int j=0; j<4; j++)
    694                 {
    695                     ssize_t ix = x + DX[j];
    696                     ssize_t iz = z + DZ[j];
     705    // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
     706    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     707    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     708    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     709    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     710    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
     711    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     712    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     713    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
     714    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    697715
    698                     float vertX = ix * CELL_SIZE;
    699                     float vertZ = iz * CELL_SIZE;
     716    // Multiply by LOS texture
     717    losTexture.BindTexture(1);
     718    pglClientActiveTextureARB(GL_TEXTURE1);
     719    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    700720
    701                     float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
     721    glLoadMatrixf(losTexture.GetTextureMatrix());
    702722
    703                     if (fancy)
    704                     {
    705                         pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight);
    706                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    707                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    708                     }
    709                     else
    710                     {
    711                         float alpha = clamp( (WaterMgr->m_WaterHeight - terrainHeight) / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset,
    712                                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     723    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     724    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     725    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     726    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     727    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     728    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     729    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     730    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     731    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    713732
    714                         // (Crappy) fresnel effect
    715                         CVector3D CamFaceVertex=CVector3D(vertX,WaterMgr->m_WaterHeight,vertZ)-camPos;
    716                         CamFaceVertex.Normalize();
    717                         float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
    718                         // Invert and set boundaries
    719                         FresnelScalar = 1.f - (FresnelScalar * 0.6);
    720733
    721                         glColor4f(WaterMgr->m_WaterColor.r,
    722                                   WaterMgr->m_WaterColor.g,
    723                                   WaterMgr->m_WaterColor.b,
    724                                   alpha * FresnelScalar);
    725                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    726                         pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ);
    727                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    728                     }
     734    // Set the proper LOD bias
     735    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    729736
    730                 }
    731             }   //end of x loop
    732         }   //end of z loop
    733     }
    734     glEnd();
     737    glEnableClientState(GL_VERTEX_ARRAY);
     738    glEnableClientState(GL_COLOR_ARRAY);
     739    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     740    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    735741
    736     if (fancy)
     742    for(size_t i=0; i<m->visiblePatches.size(); i++)
    737743    {
    738         // Unbind the LOS/refraction/reflection textures and the shader
     744        CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
     745        patchdata->RenderSimpleWater();
     746    }
    739747
    740         g_Renderer.BindTexture(3, 0);
    741         g_Renderer.BindTexture(2, 0);
    742         g_Renderer.BindTexture(1, 0);
     748    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     749    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     750    glDisableClientState(GL_COLOR_ARRAY);
     751    glDisableClientState(GL_VERTEX_ARRAY);
    743752
    744         pglActiveTextureARB(GL_TEXTURE0_ARB);
     753    g_Renderer.BindTexture(1, 0);
     754    pglClientActiveTextureARB(GL_TEXTURE1_ARB);
     755    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    745756
    746         ogl_program_use(0);
    747     }
     757    glLoadIdentity();
    748758
    749     if (!fancy)
    750     {
    751         g_Renderer.BindTexture(1, 0);
    752         pglClientActiveTextureARB(GL_TEXTURE1_ARB);
    753         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     759    pglActiveTextureARB(GL_TEXTURE0_ARB);
     760    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    754761
    755         glLoadIdentity();
     762    // Clean up the texture matrix and blend mode
     763    glLoadIdentity();
     764    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    756765
    757         pglActiveTextureARB(GL_TEXTURE0_ARB);
    758         pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    759 
    760         // Clean up the texture matrix and blend mode
    761         glLoadIdentity();
    762         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    763     }
    764 
    765766    glMatrixMode(GL_MODELVIEW);
    766767    glDisable(GL_BLEND);
    767768    glDisable(GL_TEXTURE_2D);
    768769}
    769770
     771
     772///////////////////////////////////////////////////////////////////
     773// Render water that is part of the terrain
     774void TerrainRenderer::RenderWater()
     775{
     776    // PROFILE is defined in one of the sub functions
     777
     778    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     779
     780    bool fancy = WaterMgr->WillRenderFancyWater();
     781
     782    if (fancy) {
     783        bool r = RenderFancyWater();
     784        if (r) return;
     785    }
     786    RenderSimpleWater();
     787}
     788
    770789void TerrainRenderer::RenderPriorities()
    771790{
    772791    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();