Ticket #721: water_ro_r5_r9546.patch

File water_ro_r5_r9546.patch, 32.2 KB (added by Rodolphe Ortalo, 13 years ago)

Patch with respect to trunk and revision 9546

  • source/renderer/PatchRData.h

     
    4141    void RenderSides();
    4242    void RenderPriorities();
    4343
     44    void RenderFancyWater(GLint waterDepth);
     45    void RenderSimpleWater();
     46
    4447    static void RenderBases(const std::vector<CPatchRData*>& patches);
    4548    static void RenderBlends(const std::vector<CPatchRData*>& patches);
    4649    static void RenderStreams(const std::vector<CPatchRData*>& patches, int streamflags);
     
    128131
    129132    // splats used in blend pass
    130133    std::vector<SSplat> m_BlendSplats;
     134
     135    // Mixed Fancy/Simple water vertex description data structure
     136    struct SWaterVertex {
     137        // vertex position
     138        CVector3D m_Position;
     139        // (fancy water only) vertex 3d for texture 1 == vertex position so removed
     140        // U/V computed from vertex position
     141        // water depth (varying for shader)
     142        float m_Depth;
     143        // (simple water only) Color TODO: Try to use packed colors? (here:floats, but no padding)
     144        RGBAColor m_Color;
     145    };
     146    cassert(sizeof(SWaterVertex) == 32);
     147
     148    // Water vertex buffer
     149    CVertexBuffer::VBChunk* m_VBWater;
     150
     151    // Water indices buffer
     152    CVertexBuffer::VBChunk* m_VBWaterIndices;
     153
     154    // Build water vertices (vertex buffer and data vector)
     155    void BuildWaterVertices();
     156    // Build water indices array
     157    void BuildWaterIndices();
     158
     159    // maximum and minimum depth of water at all vertices on the patch
     160    // signed value: can be negative (if vertex emerges of water)
     161    float max_wdepth;
     162    float min_wdepth;
     163    // Check if there is water on this patch (useful sometimes internally)
     164    bool FullyAboveWater();
     165    bool EntirelyUnderWater();
     166
     167    // parameter allowing a varying number of triangles per patch for LOD
     168    // MUST be an exact divisor of PATCH_SIZE
     169    // compiled const for the moment until/if dynamic water LOD is offered
     170    // savings would be mostly beneficial for GPU or simple water
     171    static const size_t water_cell_size = 1;
    131172};
    132173
    133174#endif
  • source/renderer/TerrainRenderer.h

     
    121121private:
    122122    TerrainRendererInternals* m;
    123123
     124    /*
     125     * RenderFancyWater: internal rendering method for fancy water
     126     */
     127    bool RenderFancyWater();
     128    /*
     129     * RenderSimpleWater: internal rendering method for water
     130     */
     131    void RenderSimpleWater();
     132
    124133    void PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow);
    125134};
    126135
  • source/renderer/PatchRData.cpp

     
    5757///////////////////////////////////////////////////////////////////
    5858// CPatchRData constructor
    5959CPatchRData::CPatchRData(CPatch* patch) :
    60     m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0)
     60    m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0),
     61    m_VBWater(0), m_VBWaterIndices(0), max_wdepth(-FLT_MAX), min_wdepth(FLT_MAX)
    6162{
    6263    ENSURE(patch);
    6364    Build();
     
    7374    if (m_VBBaseIndices) g_VBMan.Release(m_VBBaseIndices);
    7475    if (m_VBBlends) g_VBMan.Release(m_VBBlends);
    7576    if (m_VBBlendIndices) g_VBMan.Release(m_VBBlendIndices);
     77    if (m_VBWater) g_VBMan.Release(m_VBWater);
     78    if (m_VBWaterIndices) g_VBMan.Release(m_VBWaterIndices);
    7679}
    7780
    7881const float uvFactor = 0.125f / sqrt(2.f);
     
    645648    BuildSides();
    646649    BuildIndices();
    647650    BuildBlends();
     651
     652    BuildWaterVertices();
     653    BuildWaterIndices();
    648654}
    649655
    650656void CPatchRData::Update()
     
    658664        BuildIndices();
    659665        BuildBlends();
    660666
     667        BuildWaterVertices();
     668        BuildWaterIndices();
     669
    661670        m_UpdateFlags=0;
    662671    }
    663672}
     
    11271136        }
    11281137    }
    11291138}
     1139
     1140//
     1141// Water build and rendering
     1142//
     1143
     1144// Build vertex buffer for water vertices over our patch
     1145void CPatchRData::BuildWaterVertices()
     1146{
     1147    // Build data for water
     1148    std::vector<SWaterVertex> water_vertex_data;
     1149
     1150    // number of vertices in each direction in each patch
     1151    ENSURE((PATCH_SIZE % water_cell_size) == 0);
     1152    const ssize_t vsize=(PATCH_SIZE / water_cell_size)+1;
     1153
     1154    water_vertex_data.resize(vsize*vsize);
     1155
     1156    // We need to use this to access the water manager or we may not have the
     1157    // actual values but some compiled-in defaults
     1158    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1159
     1160    // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
     1161    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     1162    const bool fancy = WaterMgr->WillRenderFancyWater();
     1163
     1164    CPatch* patch = m_Patch;
     1165    CTerrain* terrain = patch->m_Parent;
     1166
     1167    max_wdepth = -FLT_MAX;
     1168    min_wdepth = FLT_MAX;
     1169    // build vertices, uv, and shader varying
     1170    for (ssize_t j=0;j<vsize;j++)
     1171    {
     1172        for (ssize_t i=0;i<vsize;i++)
     1173        {
     1174            ssize_t ix=(patch->m_X*PATCH_SIZE)+(i*water_cell_size);
     1175            ssize_t iz=(patch->m_Z*PATCH_SIZE)+(j*water_cell_size);
     1176            ssize_t v=(j*vsize)+i;
     1177
     1178            // calculate vertex data like for base vertices
     1179            terrain->CalcPosition(ix,iz,water_vertex_data[v].m_Position);
     1180            // at this step, Y is still terrainHeight
     1181            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz);
     1182            const float wdepth = waterHeight - water_vertex_data[v].m_Position.Y;
     1183            water_vertex_data[v].m_Depth = wdepth;
     1184            // replaces Y by water height
     1185            water_vertex_data[v].m_Position.Y = waterHeight;
     1186            // texture U/V is calculated from vertex position
     1187            // Set initial color (for simple water only)
     1188            water_vertex_data[v].m_Color.m_X = WaterMgr->m_WaterColor.r;
     1189            water_vertex_data[v].m_Color.m_Y = WaterMgr->m_WaterColor.g;
     1190            water_vertex_data[v].m_Color.m_Z = WaterMgr->m_WaterColor.b;
     1191            float alpha = clamp( wdepth / WaterMgr->m_WaterFullDepth
     1192                     + WaterMgr->m_WaterAlphaOffset,
     1193                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     1194            // NB: Usually this factor is view dependent, but for performance reason
     1195            // we do not take it into account with basic non-shader based water.
     1196            if (!(fancy))
     1197                alpha *= 0.70f; // Average constant Fresnel effect for non-fancy water
     1198            water_vertex_data[v].m_Color.m_W = alpha;
     1199            // update min and max depth over patch
     1200            if (wdepth > max_wdepth) max_wdepth = wdepth;
     1201            if (wdepth < min_wdepth) min_wdepth = wdepth;
     1202        }
     1203    }
     1204
     1205    // overall depth around patch is ready now
     1206    // so, if we are fully emerged, we can get rid of things
     1207    if (FullyAboveWater())      // i.e.: (max_wdepth < 0.0f)
     1208    {
     1209        if (m_VBWater) {
     1210            g_VBMan.Release(m_VBWater);
     1211            m_VBWater = 0;
     1212        }
     1213    }
     1214    else
     1215    {
     1216        // allocate vertex buffer
     1217        if (!m_VBWater) {
     1218            m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),water_vertex_data.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
     1219        }
     1220        // upload now for fancy water usage
     1221        // for simple water upload will be redone for each frame with color update
     1222        m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&water_vertex_data[0]);
     1223        ENSURE(m_VBWater->m_Index < 65536);
     1224    }
     1225    // The vertex buffer must be ready for indices calculation
     1226}
     1227
     1228
     1229void CPatchRData::BuildWaterIndices()
     1230{
     1231    if (FullyAboveWater())
     1232        return;
     1233
     1234    // must have allocated some vertices before trying to build corresponding indices
     1235    ENSURE(m_VBWater);
     1236
     1237    // 256*256 seems to be enough
     1238    std::vector<unsigned short> water_indices;
     1239
     1240    CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     1241
     1242    CPatch* patch = m_Patch;
     1243    CTerrain* terrain = patch->m_Parent;
     1244
     1245    // build indices for water
     1246    size_t base_indice=m_VBWater->m_Index;
     1247
     1248    for(ssize_t dx=0; dx<PATCH_SIZE; dx+=water_cell_size)
     1249    {
     1250        for(ssize_t dz=0; dz<PATCH_SIZE; dz+=water_cell_size)
     1251        {
     1252            ssize_t x = (patch->m_X*PATCH_SIZE + dx);
     1253            ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     1254
     1255            // Some offsets used to go around counterclockwise while keeping code concise
     1256            const int DX[] = {water_cell_size,water_cell_size,0,0};
     1257            const int DZ[] = {0,water_cell_size,water_cell_size,0};
     1258
     1259            const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z);
     1260
     1261            // NB: I do not reuse the values already computed for building the vertex buffer/data
     1262            // here, even though it would probably be more readable, because it allows to
     1263            // use the same function for building indices for fancy and non-fancy water (even if
     1264            // they have different vertex buffer elements - not the case but could be).
     1265            // However reference visibility info. is for vertices.
     1266
     1267            // is any corner of the tile below the water height? if not, no point rendering it
     1268            bool shouldRender = false;
     1269            for (int j = 0; j < 4; j++)
     1270            {
     1271                const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
     1272                if (terrainHeight < waterHeight)
     1273                {
     1274                    shouldRender = true;
     1275                    break;
     1276                }
     1277            }
     1278            if (!shouldRender)
     1279                continue;
     1280            for (int j=0; j<4; j++)
     1281            {
     1282                ssize_t ix = (dx + DX[j])/water_cell_size;
     1283                ssize_t iz = (dz + DZ[j])/water_cell_size;
     1284                ssize_t v=(iz*((PATCH_SIZE/water_cell_size)+1))+ix;
     1285                water_indices.push_back(u16(v)+base_indice);
     1286                ENSURE((u16(v)+base_indice) < 65535);
     1287            }
     1288        }
     1289    }
     1290
     1291    // Release existing vertex buffer chunk
     1292    if (m_VBWaterIndices)
     1293    {
     1294        g_VBMan.Release(m_VBWaterIndices);
     1295        m_VBWaterIndices = 0;
     1296    }
     1297
     1298    ENSURE(water_indices.size());
     1299
     1300    // Construct indices buffer
     1301    m_VBWaterIndices = g_VBMan.Allocate(sizeof(u16), water_indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
     1302    m_VBWaterIndices->m_Owner->UpdateChunkVertices(m_VBWaterIndices, &water_indices[0]);
     1303}
     1304
     1305const float EPSILON = 1e-12;
     1306
     1307// if the maximum water size is negative, the patch is entirely above water
     1308bool CPatchRData::FullyAboveWater()
     1309{
     1310    return (max_wdepth < EPSILON);
     1311}
     1312// if the minimum water size is still positive, the patch is entirely under water
     1313bool CPatchRData::EntirelyUnderWater()
     1314{
     1315    return (min_wdepth > -EPSILON);
     1316}
     1317
     1318void CPatchRData::RenderSimpleWater()
     1319{
     1320    ASSERT(m_UpdateFlags==0);
     1321
     1322    if (FullyAboveWater())
     1323        return;
     1324
     1325    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1326
     1327    // setup data pointers
     1328    GLsizei stride = sizeof(SWaterVertex);
     1329    glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]);
     1330    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1331    pglClientActiveTextureARB(GL_TEXTURE0);
     1332    glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);   // (same data as vertex)
     1333    pglClientActiveTextureARB(GL_TEXTURE1);
     1334    glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]);   // (same data as vertex)
     1335
     1336    if (!g_Renderer.m_SkipSubmit) {
     1337        u8* indexBase = m_VBWaterIndices->m_Owner->Bind();
     1338        glDrawElements(GL_QUADS, (GLsizei) m_VBWaterIndices->m_Count,
     1339            GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndices->m_Index));
     1340    }
     1341    // bump stats
     1342    g_Renderer.m_Stats.m_DrawCalls++;
     1343    // TODO: Water stats?
     1344
     1345    CVertexBuffer::Unbind();
     1346}
     1347
     1348void CPatchRData::RenderFancyWater(GLint waterDepth)
     1349{
     1350    ASSERT(m_UpdateFlags==0);
     1351
     1352    if (FullyAboveWater())
     1353        return;
     1354
     1355    SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
     1356
     1357    // setup data pointers
     1358    GLsizei stride = sizeof(SWaterVertex);
     1359    glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
     1360    pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */
     1361            stride, &base->m_Depth);
     1362    // render
     1363    if (!g_Renderer.m_SkipSubmit) {
     1364        u8* indexBase = m_VBWaterIndices->m_Owner->Bind();
     1365        glDrawElements(GL_QUADS, (GLsizei) m_VBWaterIndices->m_Count,
     1366            GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndices->m_Index));
     1367    }
     1368    // bump stats
     1369    g_Renderer.m_Stats.m_DrawCalls++;
     1370    // TODO: Water stats?
     1371
     1372    CVertexBuffer::Unbind();
     1373
     1374}
     1375
  • source/renderer/TerrainRenderer.cpp

     
    162162    m->phase = Phase_Submit;
    163163}
    164164
    165 
    166165///////////////////////////////////////////////////////////////////
    167166// Full-featured terrain rendering with blending and everything
    168167void TerrainRenderer::RenderTerrain()
     
    502501    glDisableClientState(GL_VERTEX_ARRAY);
    503502}
    504503
    505 
    506 ///////////////////////////////////////////////////////////////////
    507 // Render water that is part of the terrain
    508 void TerrainRenderer::RenderWater()
     504// Render fancy water
     505bool TerrainRenderer::RenderFancyWater()
    509506{
    510     PROFILE( "render water" );
     507    PROFILE( "render fancy water" );
    511508
    512509    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    513510
    514     bool fancy = WaterMgr->WillRenderFancyWater();
    515 
    516     // If we're using fancy water, make sure its shader is loaded
    517     if(fancy && !m->fancyWaterShader)
     511    // We're using fancy water, make sure its shader is loaded
     512    if(!m->fancyWaterShader)
    518513    {
    519514        Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml");
    520515        if (h < 0)
    521516        {
    522517            LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
    523518            g_Renderer.m_Options.m_FancyWater = false;
    524             fancy = false;
     519            return false;
    525520        }
    526521        else
    527522        {
    528523            m->fancyWaterShader = h;
    529524        }
    530525    }
    531     CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); // TODO: stop using g_Game
    532 
    533526    CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
    534527   
    535528    glEnable(GL_BLEND);
     
    542535    double period = 1.6;
    543536    int curTex = (int)(time*60/period) % 60;
    544537
    545     if(fancy)
    546     {
    547         WaterMgr->m_NormalMap[curTex]->Bind();
    548     }
    549     else
    550     {
    551         WaterMgr->m_WaterTexture[curTex]->Bind();
    552     }
     538    WaterMgr->m_NormalMap[curTex]->Bind();
    553539
    554540    // Shift the texture coordinates by these amounts to make the water "flow"
    555541    float tx = -fmod(time, 81.0)/81.0;
    556542    float ty = -fmod(time, 34.0)/34.0;
    557543
    558     if(!fancy)
    559     {
    560         // Perform the shifting by modifying the texture matrix
    561         glMatrixMode(GL_TEXTURE);
    562         glLoadIdentity();
    563         glTranslatef(tx, ty, 0);
    564 
    565         // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
    566         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    567         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    568         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
    569         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    570         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
    571         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
    572         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    573         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
    574         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    575 
    576         // Multiply by LOS texture
    577         losTexture.BindTexture(1);
    578         pglClientActiveTextureARB(GL_TEXTURE1);
    579         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    580 
    581         glLoadMatrixf(losTexture.GetTextureMatrix());
    582 
    583         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    584         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
    585         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
    586         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
    587         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
    588         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
    589         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
    590         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
    591         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    592     }
    593 
    594544    // Set the proper LOD bias
    595545    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
    596546
    597547    const CCamera& camera = g_Renderer.GetViewCamera();
    598548    CVector3D camPos = camera.m_Orientation.GetTranslation();
    599549
    600     GLint vertexDepth = 0;  // water depth attribute, if using fancy water
     550    // Bind reflection and refraction textures on texture units 1 and 2
     551    pglActiveTextureARB( GL_TEXTURE1_ARB );
     552    glEnable( GL_TEXTURE_2D );
     553    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
     554    pglActiveTextureARB( GL_TEXTURE2_ARB );
     555    glEnable( GL_TEXTURE_2D );
     556    glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
    601557
    602     if(fancy)
    603     {
    604         // Bind reflection and refraction textures on texture units 1 and 2
    605         pglActiveTextureARB( GL_TEXTURE1_ARB );
    606         glEnable( GL_TEXTURE_2D );
    607         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture );
    608         pglActiveTextureARB( GL_TEXTURE2_ARB );
    609         glEnable( GL_TEXTURE_2D );
    610         glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
     558    losTexture.BindTexture(3);
    611559
    612         losTexture.BindTexture(3);
     560    // Bind water shader and set arguments
     561    ogl_program_use( m->fancyWaterShader );
    613562
    614         // Bind water shader and set arguments
    615         ogl_program_use( m->fancyWaterShader );
     563    GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
     564    GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
     565    GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
     566    GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
     567    GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
     568    GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
     569    GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
     570    GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
     571    GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
     572    GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
     573    GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
     574    GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
     575    GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
     576    GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
     577    GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
     578    GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
     579    GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
     580    GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
     581    GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
     582    GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
     583    GLint repeatPeriod = ogl_program_get_uniform_location( m->fancyWaterShader, "repeatPeriod" );
    616584
    617         GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
    618         GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
    619         GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
    620         GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
    621         GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
    622         GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" );
    623         GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" );
    624         GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" );
    625         GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" );
    626         GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" );
    627         GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" );
    628         GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" );
    629         GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
    630         GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
    631         GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
    632         GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
    633         GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
    634         GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
    635         GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
    636         GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
     585    const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
     586    pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
     587    pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
     588    pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
     589    pglUniform1fARB( shininess, WaterMgr->m_Shininess );
     590    pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
     591    pglUniform1fARB( waviness, WaterMgr->m_Waviness );
     592    pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
     593    pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
     594    pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
     595    pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
     596    pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
     597    pglUniform4fARB( translation, tx, ty, 0, 0 );
     598    pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
     599    pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
     600    pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
     601    pglUniform1iARB( normalMap, 0 );        // texture unit 0
     602    pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
     603    pglUniform1iARB( refractionMap, 2 );    // texture unit 2
     604    pglUniform1iARB( losMap, 3 );           // texture unit 3
     605    pglUniform3fvARB( cameraPos, 1, &camPos.X );
     606    pglUniform1fARB( repeatPeriod, WaterMgr->m_RepeatPeriod);
    637607
    638         const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
    639         pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
    640         pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
    641         pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
    642         pglUniform1fARB( shininess, WaterMgr->m_Shininess );
    643         pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength );
    644         pglUniform1fARB( waviness, WaterMgr->m_Waviness );
    645         pglUniform1fARB( murkiness, WaterMgr->m_Murkiness );
    646         pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth );
    647         pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() );
    648         pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength );
    649         pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() );
    650         pglUniform4fARB( translation, tx, ty, 0, 0 );
    651         pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
    652         pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
    653         pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() );
    654         pglUniform1iARB( normalMap, 0 );        // texture unit 0
    655         pglUniform1iARB( reflectionMap, 1 );    // texture unit 1
    656         pglUniform1iARB( refractionMap, 2 );    // texture unit 2
    657         pglUniform1iARB( losMap, 3 );           // texture unit 3
    658         pglUniform3fvARB( cameraPos, 1, &camPos.X );
     608//  glActiveTexture(GL_TEXTURE0);
    659609
    660         vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
    661     }
    662    
    663     float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
     610    glEnableClientState(GL_VERTEX_ARRAY);
     611    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     612    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    664613
    665     glBegin(GL_QUADS);
    666 
     614    // water depth attribute, when using fancy water
     615    GLint vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
     616    pglEnableVertexAttribArrayARB(vertexDepth);
     617   
    667618    for(size_t i=0; i<m->visiblePatches.size(); i++)
    668619    {
    669         CPatch* patch = m->visiblePatches[i]->GetPatch();
     620        CPatchRData* patchdata = m->visiblePatches[i];
     621        patchdata->RenderFancyWater(vertexDepth);
     622    }
    670623
    671         for(ssize_t dx=0; dx<PATCH_SIZE; dx++)
    672         {
    673             for(ssize_t dz=0; dz<PATCH_SIZE; dz++)
    674             {
    675                 ssize_t x = (patch->m_X*PATCH_SIZE + dx);
    676                 ssize_t z = (patch->m_Z*PATCH_SIZE + dz);
     624    pglDisableVertexAttribArrayARB(vertexDepth);
     625    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     626    glDisableClientState(GL_VERTEX_ARRAY);
    677627
    678                 // Some offsets used to go around counterclockwise while keeping code concise
    679                 const int DX[] = {1,1,0,0};
    680                 const int DZ[] = {0,1,1,0};
     628    // Unbind the LOS/refraction/reflection textures and the shader
     629    g_Renderer.BindTexture(3, 0);
     630    g_Renderer.BindTexture(2, 0);
     631    g_Renderer.BindTexture(1, 0);
     632    pglActiveTextureARB(GL_TEXTURE0_ARB);
     633    ogl_program_use(0);
    681634
    682                 // is any corner of the tile below the water height? if not, no point rendering it
    683                 bool shouldRender = false;
    684                 for (int j = 0; j < 4; j++)
    685                 {
    686                     float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]);
    687                     if (terrainHeight < WaterMgr->m_WaterHeight)
    688                     {
    689                         shouldRender = true;
    690                         break;
    691                     }
    692                 }
    693                 if (!shouldRender)
    694                     continue;
     635    glMatrixMode(GL_MODELVIEW);
     636    glDisable(GL_BLEND);
     637    glDisable(GL_TEXTURE_2D);
    695638
    696                 for (int j=0; j<4; j++)
    697                 {
    698                     ssize_t ix = x + DX[j];
    699                     ssize_t iz = z + DZ[j];
     639    return true;
     640}
    700641
    701                     float vertX = ix * CELL_SIZE;
    702                     float vertZ = iz * CELL_SIZE;
     642void TerrainRenderer::RenderSimpleWater()
     643{
     644    PROFILE( "render simple water" );
    703645
    704                     float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
     646    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
    705647
    706                     if (fancy)
    707                     {
    708                         pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight);
    709                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    710                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    711                     }
    712                     else
    713                     {
    714                         float alpha = clamp( (WaterMgr->m_WaterHeight - terrainHeight) / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset,
    715                                               WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
     648    CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
     649   
     650    glEnable(GL_BLEND);
     651    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
     652    glEnable(GL_DEPTH_TEST);
     653    glDepthFunc(GL_LEQUAL);
    716654
    717                         // (Crappy) fresnel effect
    718                         CVector3D CamFaceVertex=CVector3D(vertX,WaterMgr->m_WaterHeight,vertZ)-camPos;
    719                         CamFaceVertex.Normalize();
    720                         float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f));
    721                         // Invert and set boundaries
    722                         FresnelScalar = 1.f - (FresnelScalar * 0.6);
     655    double time = WaterMgr->m_WaterTexTimer;
    723656
    724                         glColor4f(WaterMgr->m_WaterColor.r,
    725                                   WaterMgr->m_WaterColor.g,
    726                                   WaterMgr->m_WaterColor.b,
    727                                   alpha * FresnelScalar);
    728                         pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
    729                         pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ);
    730                         glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
    731                     }
     657    double period = 1.6f;
     658    int curTex = (int)(time*60/period) % 60;
    732659
    733                 }
    734             }   //end of x loop
    735         }   //end of z loop
    736     }
    737     glEnd();
     660    WaterMgr->m_WaterTexture[curTex]->Bind();
    738661
    739     if (fancy)
    740     {
    741         // Unbind the LOS/refraction/reflection textures and the shader
     662    // Shift the texture coordinates by these amounts to make the water "flow"
     663    float tx = -fmod(time, 81.0)/81.0;
     664    float ty = -fmod(time, 34.0)/34.0;
    742665
    743         g_Renderer.BindTexture(3, 0);
    744         g_Renderer.BindTexture(2, 0);
    745         g_Renderer.BindTexture(1, 0);
     666    // Perform the shifting by modifying the texture matrix
     667    glMatrixMode(GL_TEXTURE);
     668    const float repeatPeriod = WaterMgr->m_RepeatPeriod;
     669    const GLfloat xzswap[16] = {    (1.0f/repeatPeriod), 0.0f, 0.0f, 0.0f,
     670                    0.0f, 0.0f, 0.0f, 0.0f,
     671                    0.0f, (1.0f/repeatPeriod), 0.0f, 0.0f,
     672                    0.0f, 0.0f, 0.0f, 1.0f  };
     673    glLoadMatrixf(xzswap);
     674    glTranslatef(tx, ty, 0);
    746675
    747         pglActiveTextureARB(GL_TEXTURE0_ARB);
     676    // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
     677    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     678    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     679    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
     680    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     681    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
     682    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
     683    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     684    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
     685    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    748686
    749         ogl_program_use(0);
    750     }
     687    // Multiply by LOS texture
     688    losTexture.BindTexture(1);
     689    pglClientActiveTextureARB(GL_TEXTURE1);
     690    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    751691
    752     if (!fancy)
    753     {
    754         g_Renderer.BindTexture(1, 0);
    755         pglClientActiveTextureARB(GL_TEXTURE1_ARB);
    756         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     692    glLoadMatrixf(losTexture.GetTextureMatrix());
    757693
    758         glLoadIdentity();
     694    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
     695    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
     696    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
     697    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
     698    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
     699    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
     700    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
     701    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
     702    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
    759703
    760         pglActiveTextureARB(GL_TEXTURE0_ARB);
    761         pglClientActiveTextureARB(GL_TEXTURE0_ARB);
    762704
    763         // Clean up the texture matrix and blend mode
    764         glLoadIdentity();
    765         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     705    // Set the proper LOD bias
     706    glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
     707
     708    glEnableClientState(GL_VERTEX_ARRAY);
     709    glEnableClientState(GL_COLOR_ARRAY);
     710    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     711    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     712
     713    for(size_t i=0; i<m->visiblePatches.size(); i++)
     714    {
     715        CPatchRData* patchdata = m->visiblePatches[i];
     716        patchdata->RenderSimpleWater();
    766717    }
    767718
     719    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     720    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     721    glDisableClientState(GL_COLOR_ARRAY);
     722    glDisableClientState(GL_VERTEX_ARRAY);
     723
     724    g_Renderer.BindTexture(1, 0);
     725    pglClientActiveTextureARB(GL_TEXTURE1_ARB);
     726    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     727
     728    glLoadIdentity();
     729
     730    pglActiveTextureARB(GL_TEXTURE0_ARB);
     731    pglClientActiveTextureARB(GL_TEXTURE0_ARB);
     732
     733    // Clean up the texture matrix and blend mode
     734    glLoadIdentity();
     735    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     736
    768737    glMatrixMode(GL_MODELVIEW);
    769738    glDisable(GL_BLEND);
    770739    glDisable(GL_TEXTURE_2D);
    771740}
    772741
     742
     743///////////////////////////////////////////////////////////////////
     744// Render water that is part of the terrain
     745void TerrainRenderer::RenderWater()
     746{
     747    // PROFILE is defined in one of the sub functions
     748
     749    WaterManager* WaterMgr = g_Renderer.GetWaterManager();
     750
     751    bool fancy = WaterMgr->WillRenderFancyWater();
     752
     753    if (fancy) {
     754        bool r = RenderFancyWater();
     755        if (r) return;
     756    }
     757    RenderSimpleWater();
     758}
     759
    773760void TerrainRenderer::RenderPriorities()
    774761{
    775762    PROFILE("render priorities");
  • source/lib/sysdep/gfx.cpp

     
    3838
    3939std::wstring CardName()
    4040{
     41    wchar_t cardName[128] = L"Unknown card";
    4142#if OS_WIN
    42     wchar_t cardName[128];
    4343    if(wgfx_CardName(cardName, ARRAY_SIZE(cardName)) != INFO::OK)
    4444#endif
    4545    {
  • binaries/data/mods/public/shaders/water_high.vs

     
    22uniform mat4 refractionMatrix;
    33uniform mat4 losMatrix;
    44uniform vec4 translation;
     5uniform float repeatPeriod;
    56
    67attribute float vertexDepth;
    78
     
    1314{
    1415    worldPos = gl_Vertex.xyz;
    1516    waterDepth = vertexDepth;
    16     gl_TexCoord[0] = gl_MultiTexCoord0 + translation;
     17    gl_TexCoord[0].st = gl_Vertex.xz / repeatPeriod + translation.xy;
    1718    gl_TexCoord[1] = reflectionMatrix * gl_Vertex;      // projective texturing
    18     gl_TexCoord[2] = reflectionMatrix * gl_Vertex;
     19    gl_TexCoord[2] = refractionMatrix * gl_Vertex;
    1920    gl_TexCoord[3] = losMatrix * gl_Vertex;
    2021    w = gl_TexCoord[1].w;
    2122    gl_Position = ftransform();