Ticket #721: water_ro_r5_r9546.patch
File water_ro_r5_r9546.patch, 32.2 KB (added by , 13 years ago) |
---|
-
source/renderer/PatchRData.h
41 41 void RenderSides(); 42 42 void RenderPriorities(); 43 43 44 void RenderFancyWater(GLint waterDepth); 45 void RenderSimpleWater(); 46 44 47 static void RenderBases(const std::vector<CPatchRData*>& patches); 45 48 static void RenderBlends(const std::vector<CPatchRData*>& patches); 46 49 static void RenderStreams(const std::vector<CPatchRData*>& patches, int streamflags); … … 128 131 129 132 // splats used in blend pass 130 133 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; 131 172 }; 132 173 133 174 #endif -
source/renderer/TerrainRenderer.h
121 121 private: 122 122 TerrainRendererInternals* m; 123 123 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 124 133 void PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow); 125 134 }; 126 135 -
source/renderer/PatchRData.cpp
57 57 /////////////////////////////////////////////////////////////////// 58 58 // CPatchRData constructor 59 59 CPatchRData::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) 61 62 { 62 63 ENSURE(patch); 63 64 Build(); … … 73 74 if (m_VBBaseIndices) g_VBMan.Release(m_VBBaseIndices); 74 75 if (m_VBBlends) g_VBMan.Release(m_VBBlends); 75 76 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); 76 79 } 77 80 78 81 const float uvFactor = 0.125f / sqrt(2.f); … … 645 648 BuildSides(); 646 649 BuildIndices(); 647 650 BuildBlends(); 651 652 BuildWaterVertices(); 653 BuildWaterIndices(); 648 654 } 649 655 650 656 void CPatchRData::Update() … … 658 664 BuildIndices(); 659 665 BuildBlends(); 660 666 667 BuildWaterVertices(); 668 BuildWaterIndices(); 669 661 670 m_UpdateFlags=0; 662 671 } 663 672 } … … 1127 1136 } 1128 1137 } 1129 1138 } 1139 1140 // 1141 // Water build and rendering 1142 // 1143 1144 // Build vertex buffer for water vertices over our patch 1145 void 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 1229 void 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 1305 const float EPSILON = 1e-12; 1306 1307 // if the maximum water size is negative, the patch is entirely above water 1308 bool CPatchRData::FullyAboveWater() 1309 { 1310 return (max_wdepth < EPSILON); 1311 } 1312 // if the minimum water size is still positive, the patch is entirely under water 1313 bool CPatchRData::EntirelyUnderWater() 1314 { 1315 return (min_wdepth > -EPSILON); 1316 } 1317 1318 void 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 1348 void 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
162 162 m->phase = Phase_Submit; 163 163 } 164 164 165 166 165 /////////////////////////////////////////////////////////////////// 167 166 // Full-featured terrain rendering with blending and everything 168 167 void TerrainRenderer::RenderTerrain() … … 502 501 glDisableClientState(GL_VERTEX_ARRAY); 503 502 } 504 503 505 506 /////////////////////////////////////////////////////////////////// 507 // Render water that is part of the terrain 508 void TerrainRenderer::RenderWater() 504 // Render fancy water 505 bool TerrainRenderer::RenderFancyWater() 509 506 { 510 PROFILE( "render water" );507 PROFILE( "render fancy water" ); 511 508 512 509 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 513 510 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) 518 513 { 519 514 Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml"); 520 515 if (h < 0) 521 516 { 522 517 LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n"); 523 518 g_Renderer.m_Options.m_FancyWater = false; 524 fancy =false;519 return false; 525 520 } 526 521 else 527 522 { 528 523 m->fancyWaterShader = h; 529 524 } 530 525 } 531 CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); // TODO: stop using g_Game532 533 526 CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture(); 534 527 535 528 glEnable(GL_BLEND); … … 542 535 double period = 1.6; 543 536 int curTex = (int)(time*60/period) % 60; 544 537 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(); 553 539 554 540 // Shift the texture coordinates by these amounts to make the water "flow" 555 541 float tx = -fmod(time, 81.0)/81.0; 556 542 float ty = -fmod(time, 34.0)/34.0; 557 543 558 if(!fancy)559 {560 // Perform the shifting by modifying the texture matrix561 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 alpha566 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 texture577 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 594 544 // Set the proper LOD bias 595 545 glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); 596 546 597 547 const CCamera& camera = g_Renderer.GetViewCamera(); 598 548 CVector3D camPos = camera.m_Orientation.GetTranslation(); 599 549 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 ); 601 557 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); 611 559 612 losTexture.BindTexture(3); 560 // Bind water shader and set arguments 561 ogl_program_use( m->fancyWaterShader ); 613 562 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" ); 616 584 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); 637 607 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); 659 609 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); 664 613 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 667 618 for(size_t i=0; i<m->visiblePatches.size(); i++) 668 619 { 669 CPatch* patch = m->visiblePatches[i]->GetPatch(); 620 CPatchRData* patchdata = m->visiblePatches[i]; 621 patchdata->RenderFancyWater(vertexDepth); 622 } 670 623 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); 677 627 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); 681 634 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); 695 638 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 } 700 641 701 float vertX = ix * CELL_SIZE; 702 float vertZ = iz * CELL_SIZE; 642 void TerrainRenderer::RenderSimpleWater() 643 { 644 PROFILE( "render simple water" ); 703 645 704 float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);646 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 705 647 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); 716 654 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; 723 656 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; 732 659 733 } 734 } //end of x loop 735 } //end of z loop 736 } 737 glEnd(); 660 WaterMgr->m_WaterTexture[curTex]->Bind(); 738 661 739 if (fancy)740 {741 // Unbind the LOS/refraction/reflection textures and the shader662 // 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; 742 665 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); 746 675 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); 748 686 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); 751 691 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()); 757 693 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); 759 703 760 pglActiveTextureARB(GL_TEXTURE0_ARB);761 pglClientActiveTextureARB(GL_TEXTURE0_ARB);762 704 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(); 766 717 } 767 718 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 768 737 glMatrixMode(GL_MODELVIEW); 769 738 glDisable(GL_BLEND); 770 739 glDisable(GL_TEXTURE_2D); 771 740 } 772 741 742 743 /////////////////////////////////////////////////////////////////// 744 // Render water that is part of the terrain 745 void 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 773 760 void TerrainRenderer::RenderPriorities() 774 761 { 775 762 PROFILE("render priorities"); -
source/lib/sysdep/gfx.cpp
38 38 39 39 std::wstring CardName() 40 40 { 41 wchar_t cardName[128] = L"Unknown card"; 41 42 #if OS_WIN 42 wchar_t cardName[128];43 43 if(wgfx_CardName(cardName, ARRAY_SIZE(cardName)) != INFO::OK) 44 44 #endif 45 45 { -
binaries/data/mods/public/shaders/water_high.vs
2 2 uniform mat4 refractionMatrix; 3 3 uniform mat4 losMatrix; 4 4 uniform vec4 translation; 5 uniform float repeatPeriod; 5 6 6 7 attribute float vertexDepth; 7 8 … … 13 14 { 14 15 worldPos = gl_Vertex.xyz; 15 16 waterDepth = vertexDepth; 16 gl_TexCoord[0] = gl_MultiTexCoord0 + translation;17 gl_TexCoord[0].st = gl_Vertex.xz / repeatPeriod + translation.xy; 17 18 gl_TexCoord[1] = reflectionMatrix * gl_Vertex; // projective texturing 18 gl_TexCoord[2] = ref lectionMatrix * gl_Vertex;19 gl_TexCoord[2] = refractionMatrix * gl_Vertex; 19 20 gl_TexCoord[3] = losMatrix * gl_Vertex; 20 21 w = gl_TexCoord[1].w; 21 22 gl_Position = ftransform();