Ticket #721: water_ro_r3_r9066.patch
File water_ro_r3_r9066.patch, 32.7 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); … … 126 129 127 130 // splats used in blend pass 128 131 std::vector<SSplat> m_BlendSplats; 132 133 // Simple water vertex description data structure 134 struct SSimpleWaterVertex { 135 // vertex position 136 CVector3D m_Position; 137 // vertex uvs for texture 0 138 float m_UVs[2]; 139 // vertex 3d for texture 1 == vertex position so removed 140 // CVector3D m_PosTex1; 141 // Color TODO: Try to use packed colors? (here:floats) 142 RGBAColor m_Color; 143 // TODO: Add padding up to 64bytes? (for 32 bytes align) 144 }; 145 146 // Fancy water vertex description data structure 147 struct SWaterVertex { 148 // vertex position 149 CVector3D m_Position; 150 // vertex uvs for normal map texture 151 float m_UVs[2]; 152 // water depth (varying for shader) 153 float m_Depth; 154 // add some padding (TODO: Check) 155 u32 m_Padding[2]; 156 }; 157 158 void BuildSimpleWaterVertices(); 159 void BuildFancyWaterVertices(); 160 161 void BuildWaterVertexData(); // Common to simple and fancy water 162 163 // Water vertex buffer 164 CVertexBuffer::VBChunk* m_VBWater; 165 166 // Water indices into buffer 167 // NB: Indices are identical for fancy or regular water (same path) 168 void BuildWaterIndices(); 169 170 // 256*256 seems to be enough 171 std::vector<unsigned short> m_WaterIndices; 172 173 // Build data for fancy water or reference data for 174 // computing simple water 175 std::vector<SWaterVertex> m_WaterVertexData; 176 177 // maximum and minimum depth of water at all vertices on the patch 178 // signed value: can be negative (if vertex emerges of water) 179 float max_wdepth; 180 float min_wdepth; 181 // Check if there is water on this patch (useful sometimes internally) 182 bool FullyEmerged(); 183 bool EntirelyUnderWater(); 184 129 185 }; 130 186 131 187 #endif -
source/renderer/TerrainRenderer.h
114 114 115 115 private: 116 116 TerrainRendererInternals* m; 117 118 /* 119 * RenderFancyWater: internal rendering method for fancy water 120 */ 121 bool RenderFancyWater(); 122 /* 123 * RenderSimpleWater: internal rendering method for water 124 */ 125 void RenderSimpleWater(); 117 126 }; 118 127 119 128 #endif // INCLUDED_TERRAINRENDERER -
source/renderer/PatchRData.cpp
56 56 /////////////////////////////////////////////////////////////////// 57 57 // CPatchRData constructor 58 58 CPatchRData::CPatchRData(CPatch* patch) : 59 m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0) 59 m_Patch(patch), m_VBSides(0), m_VBBase(0), m_VBBaseIndices(0), m_VBBlends(0), m_VBBlendIndices(0), 60 m_VBWater(0), max_wdepth(-FLT_MAX), min_wdepth(FLT_MAX) 60 61 { 61 62 debug_assert(patch); 62 63 Build(); … … 631 632 BuildSides(); 632 633 BuildIndices(); 633 634 BuildBlends(); 635 636 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 637 if (WaterMgr->WillRenderFancyWater()) { 638 BuildFancyWaterVertices(); 639 } else { 640 BuildSimpleWaterVertices(); 641 } 642 BuildWaterIndices(); 634 643 } 635 644 636 645 void CPatchRData::Update() … … 644 653 BuildIndices(); 645 654 BuildBlends(); 646 655 656 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 657 if (WaterMgr->WillRenderFancyWater()) { 658 // TODO: Switch on fancy or not fancy water 659 BuildFancyWaterVertices(); 660 } else { 661 BuildSimpleWaterVertices(); 662 } 663 647 664 m_UpdateFlags=0; 648 665 } 649 666 } … … 1048 1065 } 1049 1066 } 1050 1067 } 1068 1069 // 1070 // Water build and rendering 1071 // 1072 1073 // Build vertex buffer for water vertices over our patch 1074 void CPatchRData::BuildWaterVertexData() 1075 { 1076 // number of vertices in each direction in each patch 1077 const ssize_t vsize=PATCH_SIZE+1; 1078 1079 m_WaterVertexData.resize(vsize*vsize); 1080 1081 // We need to use this to access the water manager or we may not have the 1082 // actual values but some compiled-in defaults 1083 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 1084 1085 // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults 1086 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 1087 const float repeatPeriod = WaterMgr->m_RepeatPeriod; 1088 #if 0 1089 // With non fancy water, period is a constant? TODO: Check 1090 const float repeatPeriod = 16.0f; 1091 #endif 1092 1093 1094 CPatch* patch = m_Patch; 1095 CTerrain* terrain = patch->m_Parent; 1096 1097 max_wdepth = -FLT_MAX; 1098 min_wdepth = FLT_MAX; 1099 // build vertices, uv, and shader varying 1100 for (ssize_t j=0;j<vsize;j++) 1101 { 1102 for (ssize_t i=0;i<vsize;i++) 1103 { 1104 ssize_t ix=(patch->m_X*PATCH_SIZE)+i; 1105 ssize_t iz=(patch->m_Z*PATCH_SIZE)+j; 1106 ssize_t v=(j*vsize)+i; 1107 1108 // calculate vertex data like for base vertices 1109 terrain->CalcPosition(ix,iz,m_WaterVertexData[v].m_Position); 1110 // at this step, Y is still terrainHeight 1111 const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz); 1112 const float wdepth = waterHeight - m_WaterVertexData[v].m_Position.Y; 1113 m_WaterVertexData[v].m_Depth = wdepth; 1114 // replaces Y by water height 1115 m_WaterVertexData[v].m_Position.Y = waterHeight; 1116 // calculates U/V (TODO: could be done in for fancy water shader? would be beneficial?) 1117 m_WaterVertexData[v].m_UVs[0] = m_WaterVertexData[v].m_Position.X / repeatPeriod; 1118 m_WaterVertexData[v].m_UVs[1] = m_WaterVertexData[v].m_Position.Z / repeatPeriod; 1119 // update min and max depth over patch 1120 if (wdepth > max_wdepth) max_wdepth = wdepth; 1121 if (wdepth < min_wdepth) min_wdepth = wdepth; 1122 } 1123 } 1124 } 1125 1126 // Build all that can be done at build time for simple water 1127 void CPatchRData::BuildSimpleWaterVertices() 1128 { 1129 BuildWaterVertexData(); 1130 // overall depth around patch is ready now 1131 // so, if we are fully emerged, we can get rid of things 1132 if (FullyEmerged()) // i.e.: (max_wdepth < 0.0f) 1133 { 1134 if (m_VBWater) { 1135 g_VBMan.Release(m_VBWater); 1136 } 1137 } 1138 else 1139 { 1140 // allocate vertex buffer (only: update is done at render time) 1141 if (!m_VBWater) { 1142 m_VBWater=g_VBMan.Allocate(sizeof(SSimpleWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER); 1143 } 1144 debug_assert(m_VBWater->m_Index < 65536); 1145 } 1146 1147 // The vertex buffer must be ready for indices calculation 1148 BuildWaterIndices(); 1149 } 1150 1151 void CPatchRData::BuildFancyWaterVertices() 1152 { 1153 BuildWaterVertexData(); 1154 // overall depth around patch is ready now 1155 // so, if we are fully emerged, we can get rid of things 1156 if (FullyEmerged()) // i.e.: (max_wdepth < 0.0f) 1157 { 1158 if (m_VBWater) { 1159 g_VBMan.Release(m_VBWater); 1160 } 1161 } 1162 else 1163 { 1164 // we directly use the vertex data for rendering 1165 // upload to vertex buffer 1166 if (!m_VBWater) { 1167 m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER); 1168 } 1169 m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]); 1170 debug_assert(m_VBWater->m_Index < 65536); 1171 } 1172 // The vertex buffer must be ready for indices calculation 1173 BuildWaterIndices(); 1174 1175 // We directly use the vertex buffer in rendering, so we 1176 // can clear the data buffer for space 1177 m_WaterVertexData.clear(); 1178 } 1179 1180 1181 void CPatchRData::BuildWaterIndices() 1182 { 1183 // release existing indices 1184 m_WaterIndices.clear(); 1185 1186 if (FullyEmerged()) 1187 return; 1188 1189 // must have allocated some vertices before trying to build corresponding indices 1190 debug_assert(m_VBWater); 1191 1192 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 1193 1194 CPatch* patch = m_Patch; 1195 CTerrain* terrain = patch->m_Parent; 1196 1197 // build indices for water 1198 size_t base_indice=m_VBWater->m_Index; 1199 1200 for(ssize_t dx=0; dx<PATCH_SIZE; dx++) 1201 { 1202 for(ssize_t dz=0; dz<PATCH_SIZE; dz++) 1203 { 1204 ssize_t x = (patch->m_X*PATCH_SIZE + dx); 1205 ssize_t z = (patch->m_Z*PATCH_SIZE + dz); 1206 1207 // Some offsets used to go around counterclockwise while keeping code concise 1208 const int DX[] = {1,1,0,0}; 1209 const int DZ[] = {0,1,1,0}; 1210 1211 const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z); 1212 1213 // NB: I do not reuse the values already computed for building the vertex buffer/data 1214 // here, even though it would probably be more readable, because it allows to 1215 // use the same function for building indices for fancy and non-fancy water (which 1216 // have different vertex buffer elements). 1217 // But reference visibility info. is for vertices. 1218 1219 // is any corner of the tile below the water height? if not, no point rendering it 1220 bool shouldRender = false; 1221 for (int j = 0; j < 4; j++) 1222 { 1223 const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]); 1224 if (terrainHeight < waterHeight) 1225 { 1226 shouldRender = true; 1227 break; 1228 } 1229 } 1230 if (!shouldRender) 1231 continue; 1232 for (int j=0; j<4; j++) 1233 { 1234 ssize_t ix = dx + DX[j]; 1235 ssize_t iz = dz + DZ[j]; 1236 ssize_t v=(iz*(PATCH_SIZE+1))+ix; 1237 m_WaterIndices.push_back(u16(v)+base_indice); 1238 debug_assert((u16(v)+base_indice) < 65535); 1239 } 1240 } 1241 } 1242 } 1243 1244 const float EPSILON = 1e-12; 1245 1246 // if the maximum water size is negative, the patch is entirely emerged 1247 bool CPatchRData::FullyEmerged() 1248 { 1249 return (max_wdepth < EPSILON); 1250 } 1251 // if the minimum water size is still positive, the patch is entirely under water 1252 bool CPatchRData::EntirelyUnderWater() 1253 { 1254 return (min_wdepth > -EPSILON); 1255 } 1256 1257 void CPatchRData::RenderSimpleWater() 1258 { 1259 debug_assert(m_UpdateFlags==0); 1260 1261 if (FullyEmerged()) 1262 return; 1263 1264 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 1265 1266 // This is probably changing so vertices need update! 1267 const CCamera& camera = g_Renderer.GetViewCamera(); 1268 CVector3D camPos = camera.m_Orientation.GetTranslation(); 1269 1270 std::vector<SSimpleWaterVertex> vertices; 1271 vertices.reserve(m_WaterVertexData.size()); 1272 1273 // build vertex buffer with adequate alpha 1274 for (unsigned int i=0; i < m_WaterVertexData.size(); i++) 1275 { 1276 SSimpleWaterVertex vertex; 1277 // Copy data identical to build time 1278 vertex.m_Position = m_WaterVertexData[i].m_Position; 1279 vertex.m_UVs[0] = m_WaterVertexData[i].m_UVs[0]; 1280 vertex.m_UVs[1] = m_WaterVertexData[i].m_UVs[1]; 1281 // We use the same pointer/data in array for saving space 1282 // vertex.m_PosTex1 = m_WaterVertexData[i].m_Position; 1283 1284 const float alpha = clamp( (m_WaterVertexData[i].m_Depth) / WaterMgr->m_WaterFullDepth 1285 + WaterMgr->m_WaterAlphaOffset, 1286 WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha); 1287 1288 // (Crappy) fresnel effect 1289 CVector3D CamFaceVertex=CVector3D(vertex.m_Position.X,WaterMgr->m_WaterHeight,vertex.m_Position.Z)-camPos; 1290 // Note: WaterMgr->m_WaterHeight is also vertex.m_Position.Y I think... 1291 CamFaceVertex.Normalize(); 1292 float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f)); 1293 // Invert and set boundaries 1294 FresnelScalar = 1.f - (FresnelScalar * 0.6); 1295 // Set Color 1296 vertex.m_Color.m_X = WaterMgr->m_WaterColor.r; 1297 vertex.m_Color.m_Y = WaterMgr->m_WaterColor.g; 1298 vertex.m_Color.m_Z = WaterMgr->m_WaterColor.b; 1299 vertex.m_Color.m_W = alpha * FresnelScalar; 1300 1301 // save the finalized vertex built 1302 vertices.push_back(vertex); 1303 } 1304 // upload to vertex buffer 1305 m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&vertices[0]); 1306 1307 SSimpleWaterVertex *base=(SSimpleWaterVertex *)m_VBWater->m_Owner->Bind(); 1308 1309 // setup data pointers 1310 GLsizei stride = sizeof(SSimpleWaterVertex); 1311 glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]); 1312 glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]); 1313 pglClientActiveTextureARB(GL_TEXTURE0); 1314 glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]); // render 1315 pglClientActiveTextureARB(GL_TEXTURE1); 1316 glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]); // (same data as vertex) 1317 // glTexCoordPointer(3, GL_FLOAT, stride, &base->m_PosTex1[0]); 1318 1319 if (!g_Renderer.m_SkipSubmit) { 1320 glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(), 1321 GL_UNSIGNED_SHORT, &m_WaterIndices[0]); 1322 } 1323 // bump stats 1324 g_Renderer.m_Stats.m_DrawCalls++; 1325 // TODO: Water stats? 1326 1327 CVertexBuffer::Unbind(); 1328 } 1329 1330 void CPatchRData::RenderFancyWater(GLint waterDepth) 1331 { 1332 debug_assert(m_UpdateFlags==0); 1333 1334 if (FullyEmerged()) 1335 return; 1336 1337 SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind(); 1338 1339 // setup data pointers 1340 GLsizei stride = sizeof(SWaterVertex); 1341 glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]); 1342 pglClientActiveTextureARB(GL_TEXTURE0); 1343 glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]); 1344 pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */ 1345 stride, &base->m_Depth); 1346 // render 1347 if (!g_Renderer.m_SkipSubmit) { 1348 glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(), 1349 GL_UNSIGNED_SHORT, &m_WaterIndices[0]); 1350 } 1351 // bump stats 1352 g_Renderer.m_Stats.m_DrawCalls++; 1353 // TODO: Water stats? 1354 1355 CVertexBuffer::Unbind(); 1356 1357 } 1358 -
source/renderer/TerrainRenderer.cpp
161 161 m->phase = Phase_Submit; 162 162 } 163 163 164 165 164 /////////////////////////////////////////////////////////////////// 166 165 // Full-featured terrain rendering with blending and everything 167 166 void TerrainRenderer::RenderTerrain(ShadowMap* shadow) … … 521 520 glDisableClientState(GL_VERTEX_ARRAY); 522 521 } 523 522 524 525 /////////////////////////////////////////////////////////////////// 526 // Render water that is part of the terrain 527 void TerrainRenderer::RenderWater() 523 // Render fancy water 524 bool TerrainRenderer::RenderFancyWater() 528 525 { 529 PROFILE( "render water" );526 PROFILE( "render fancy water" ); 530 527 531 528 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 532 529 533 bool fancy = WaterMgr->WillRenderFancyWater(); 534 535 // If we're using fancy water, make sure its shader is loaded 536 if(fancy && !m->fancyWaterShader) 530 // We're using fancy water, make sure its shader is loaded 531 if(!m->fancyWaterShader) 537 532 { 538 533 Handle h = ogl_program_load(g_VFS, L"shaders/water_high.xml"); 539 534 if (h < 0) 540 535 { 541 536 LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n"); 542 537 g_Renderer.m_Options.m_FancyWater = false; 543 fancy =false;538 return false; 544 539 } 545 540 else 546 541 { 547 542 m->fancyWaterShader = h; 548 543 } 549 544 } 550 CTerrain* terrain = g_Game->GetWorld()->GetTerrain();551 545 552 546 CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); 553 547 … … 561 555 double period = 1.6; 562 556 int curTex = (int)(time*60/period) % 60; 563 557 564 if(fancy) 565 { 566 WaterMgr->m_NormalMap[curTex]->Bind(); 567 } 568 else 569 { 570 WaterMgr->m_WaterTexture[curTex]->Bind(); 571 } 558 WaterMgr->m_NormalMap[curTex]->Bind(); 572 559 573 560 // Shift the texture coordinates by these amounts to make the water "flow" 574 561 float tx = -fmod(time, 81.0)/81.0; 575 562 float ty = -fmod(time, 34.0)/34.0; 576 563 577 if(!fancy)578 {579 // Perform the shifting by modifying the texture matrix580 glMatrixMode(GL_TEXTURE);581 glLoadIdentity();582 glTranslatef(tx, ty, 0);583 584 // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha585 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);586 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);587 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);588 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);589 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);590 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);591 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);592 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);593 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);594 595 // Multiply by LOS texture596 losTexture.BindTexture(1);597 pglClientActiveTextureARB(GL_TEXTURE1);598 glEnableClientState(GL_TEXTURE_COORD_ARRAY);599 600 glLoadMatrixf(losTexture.GetTextureMatrix());601 602 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);603 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);604 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);605 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);606 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);607 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);608 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);609 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);610 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);611 }612 613 564 // Set the proper LOD bias 614 565 glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); 615 566 616 567 const CCamera& camera = g_Renderer.GetViewCamera(); 617 568 CVector3D camPos = camera.m_Orientation.GetTranslation(); 618 569 619 GLint vertexDepth = 0; // water depth attribute, if using fancy water 570 // Bind reflection and refraction textures on texture units 1 and 2 571 pglActiveTextureARB( GL_TEXTURE1_ARB ); 572 glEnable( GL_TEXTURE_2D ); 573 glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture ); 574 pglActiveTextureARB( GL_TEXTURE2_ARB ); 575 glEnable( GL_TEXTURE_2D ); 576 glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture ); 620 577 621 if(fancy) 622 { 623 // Bind reflection and refraction textures on texture units 1 and 2 624 pglActiveTextureARB( GL_TEXTURE1_ARB ); 625 glEnable( GL_TEXTURE_2D ); 626 glBindTexture( GL_TEXTURE_2D, WaterMgr->m_ReflectionTexture ); 627 pglActiveTextureARB( GL_TEXTURE2_ARB ); 628 glEnable( GL_TEXTURE_2D ); 629 glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture ); 578 losTexture.BindTexture(3); 630 579 631 losTexture.BindTexture(3); 580 // Bind water shader and set arguments 581 ogl_program_use( m->fancyWaterShader ); 632 582 633 // Bind water shader and set arguments 634 ogl_program_use( m->fancyWaterShader ); 583 GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" ); 584 GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" ); 585 GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" ); 586 GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" ); 587 GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" ); 588 GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" ); 589 GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" ); 590 GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" ); 591 GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" ); 592 GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" ); 593 GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" ); 594 GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" ); 595 GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" ); 596 GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" ); 597 GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" ); 598 GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" ); 599 GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" ); 600 GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" ); 601 GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" ); 602 GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" ); 635 603 636 GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" ); 637 GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" ); 638 GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" ); 639 GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" ); 640 GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" ); 641 GLint specularStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "specularStrength" ); 642 GLint waviness = ogl_program_get_uniform_location( m->fancyWaterShader, "waviness" ); 643 GLint murkiness = ogl_program_get_uniform_location( m->fancyWaterShader, "murkiness" ); 644 GLint fullDepth = ogl_program_get_uniform_location( m->fancyWaterShader, "fullDepth" ); 645 GLint tint = ogl_program_get_uniform_location( m->fancyWaterShader, "tint" ); 646 GLint reflectionTint = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTint" ); 647 GLint reflectionTintStrength = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionTintStrength" ); 648 GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" ); 649 GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" ); 650 GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" ); 651 GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" ); 652 GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" ); 653 GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" ); 654 GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" ); 655 GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" ); 604 const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); 605 pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X ); 606 pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X ); 607 pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X ); 608 pglUniform1fARB( shininess, WaterMgr->m_Shininess ); 609 pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength ); 610 pglUniform1fARB( waviness, WaterMgr->m_Waviness ); 611 pglUniform1fARB( murkiness, WaterMgr->m_Murkiness ); 612 pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth ); 613 pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() ); 614 pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength ); 615 pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() ); 616 pglUniform4fARB( translation, tx, ty, 0, 0 ); 617 pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 ); 618 pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 ); 619 pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() ); 620 pglUniform1iARB( normalMap, 0 ); // texture unit 0 621 pglUniform1iARB( reflectionMap, 1 ); // texture unit 1 622 pglUniform1iARB( refractionMap, 2 ); // texture unit 2 623 pglUniform1iARB( losMap, 3 ); // texture unit 3 624 pglUniform3fvARB( cameraPos, 1, &camPos.X ); 656 625 657 const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); 658 pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X ); 659 pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X ); 660 pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X ); 661 pglUniform1fARB( shininess, WaterMgr->m_Shininess ); 662 pglUniform1fARB( specularStrength, WaterMgr->m_SpecularStrength ); 663 pglUniform1fARB( waviness, WaterMgr->m_Waviness ); 664 pglUniform1fARB( murkiness, WaterMgr->m_Murkiness ); 665 pglUniform1fARB( fullDepth, WaterMgr->m_WaterFullDepth ); 666 pglUniform3fvARB( tint, 1, WaterMgr->m_WaterTint.FloatArray() ); 667 pglUniform1fARB( reflectionTintStrength, WaterMgr->m_ReflectionTintStrength ); 668 pglUniform3fvARB( reflectionTint, 1, WaterMgr->m_ReflectionTint.FloatArray() ); 669 pglUniform4fARB( translation, tx, ty, 0, 0 ); 670 pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 ); 671 pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 ); 672 pglUniformMatrix4fvARB( losMatrix, 1, false, losTexture.GetTextureMatrix() ); 673 pglUniform1iARB( normalMap, 0 ); // texture unit 0 674 pglUniform1iARB( reflectionMap, 1 ); // texture unit 1 675 pglUniform1iARB( refractionMap, 2 ); // texture unit 2 676 pglUniform1iARB( losMap, 3 ); // texture unit 3 677 pglUniform3fvARB( cameraPos, 1, &camPos.X ); 626 // glActiveTexture(GL_TEXTURE0); 678 627 679 vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" ); 680 } 681 682 float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f); 628 glEnableClientState(GL_VERTEX_ARRAY); 629 pglClientActiveTextureARB(GL_TEXTURE0_ARB); 630 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 683 631 684 glBegin(GL_QUADS); 685 632 // water depth attribute, when using fancy water 633 GLint vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" ); 634 pglEnableVertexAttribArrayARB(vertexDepth); 635 686 636 for(size_t i=0; i<m->visiblePatches.size(); i++) 687 637 { 688 CPatch* patch = m->visiblePatches[i]->GetPatch(); 638 CPatchRData* patchdata = m->visiblePatches[i]; 639 patchdata->RenderFancyWater(vertexDepth); 640 } 689 641 690 for(ssize_t dx=0; dx<PATCH_SIZE; dx++) 691 { 692 for(ssize_t dz=0; dz<PATCH_SIZE; dz++) 693 { 694 ssize_t x = (patch->m_X*PATCH_SIZE + dx); 695 ssize_t z = (patch->m_Z*PATCH_SIZE + dz); 642 pglDisableVertexAttribArrayARB(vertexDepth); 643 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 644 glDisableClientState(GL_VERTEX_ARRAY); 696 645 697 // Some offsets used to go around counterclockwise while keeping code concise 698 const int DX[] = {1,1,0,0}; 699 const int DZ[] = {0,1,1,0}; 646 // Unbind the LOS/refraction/reflection textures and the shader 647 g_Renderer.BindTexture(3, 0); 648 g_Renderer.BindTexture(2, 0); 649 g_Renderer.BindTexture(1, 0); 650 pglActiveTextureARB(GL_TEXTURE0_ARB); 651 ogl_program_use(0); 700 652 701 // is any corner of the tile below the water height? if not, no point rendering it 702 bool shouldRender = false; 703 for (int j = 0; j < 4; j++) 704 { 705 float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]); 706 if (terrainHeight < WaterMgr->m_WaterHeight) 707 { 708 shouldRender = true; 709 break; 710 } 711 } 712 if (!shouldRender) 713 continue; 653 glMatrixMode(GL_MODELVIEW); 654 glDisable(GL_BLEND); 655 glDisable(GL_TEXTURE_2D); 714 656 715 for (int j=0; j<4; j++) 716 { 717 ssize_t ix = x + DX[j]; 718 ssize_t iz = z + DZ[j]; 657 return true; 658 } 719 659 720 float vertX = ix * CELL_SIZE; 721 float vertZ = iz * CELL_SIZE; 660 void TerrainRenderer::RenderSimpleWater() 661 { 662 PROFILE( "render simple water" ); 722 663 723 float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);664 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 724 665 725 if (fancy) 726 { 727 pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight); 728 pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod); 729 glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ); 730 } 731 else 732 { 733 float alpha = clamp( (WaterMgr->m_WaterHeight - terrainHeight) / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset, 734 WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha); 666 CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); 667 668 glEnable(GL_BLEND); 669 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 670 glEnable(GL_DEPTH_TEST); 671 glDepthFunc(GL_LEQUAL); 735 672 736 // (Crappy) fresnel effect 737 CVector3D CamFaceVertex=CVector3D(vertX,WaterMgr->m_WaterHeight,vertZ)-camPos; 738 CamFaceVertex.Normalize(); 739 float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f)); 740 // Invert and set boundaries 741 FresnelScalar = 1.f - (FresnelScalar * 0.6); 673 double time = WaterMgr->m_WaterTexTimer; 742 674 743 glColor4f(WaterMgr->m_WaterColor.r, 744 WaterMgr->m_WaterColor.g, 745 WaterMgr->m_WaterColor.b, 746 alpha * FresnelScalar); 747 pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod); 748 pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ); 749 glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ); 750 } 675 double period = 16.0f; 676 int curTex = (int)(time*60/period) % 60; 751 677 752 } 753 } //end of x loop 754 } //end of z loop 755 } 756 glEnd(); 678 WaterMgr->m_WaterTexture[curTex]->Bind(); 757 679 758 if (fancy)759 {760 // Unbind the LOS/refraction/reflection textures and the shader680 // Shift the texture coordinates by these amounts to make the water "flow" 681 float tx = -fmod(time, 81.0)/81.0; 682 float ty = -fmod(time, 34.0)/34.0; 761 683 762 g_Renderer.BindTexture(3, 0); 763 g_Renderer.BindTexture(2, 0); 764 g_Renderer.BindTexture(1, 0); 684 // Perform the shifting by modifying the texture matrix 685 glMatrixMode(GL_TEXTURE); 686 glLoadIdentity(); 687 glTranslatef(tx, ty, 0); 765 688 766 pglActiveTextureARB(GL_TEXTURE0_ARB); 689 // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha 690 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 691 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); 692 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); 693 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); 694 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); 695 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); 696 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); 697 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); 698 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 767 699 768 ogl_program_use(0); 769 } 700 // Multiply by LOS texture 701 losTexture.BindTexture(1); 702 pglClientActiveTextureARB(GL_TEXTURE1); 703 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 770 704 771 if (!fancy) 772 { 773 g_Renderer.BindTexture(1, 0); 774 pglClientActiveTextureARB(GL_TEXTURE1_ARB); 775 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 705 glLoadMatrixf(losTexture.GetTextureMatrix()); 776 706 777 glLoadIdentity(); 707 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 708 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); 709 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); 710 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); 711 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); 712 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA); 713 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); 714 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS); 715 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 778 716 779 pglActiveTextureARB(GL_TEXTURE0_ARB);780 pglClientActiveTextureARB(GL_TEXTURE0_ARB);781 717 782 // Clean up the texture matrix and blend mode 783 glLoadIdentity(); 784 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 718 // Set the proper LOD bias 719 glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); 720 721 glEnableClientState(GL_VERTEX_ARRAY); 722 glEnableClientState(GL_COLOR_ARRAY); 723 pglClientActiveTextureARB(GL_TEXTURE0_ARB); 724 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 725 726 for(size_t i=0; i<m->visiblePatches.size(); i++) 727 { 728 CPatchRData* patchdata = m->visiblePatches[i]; 729 patchdata->RenderSimpleWater(); 785 730 } 786 731 732 pglClientActiveTextureARB(GL_TEXTURE0_ARB); 733 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 734 glDisableClientState(GL_COLOR_ARRAY); 735 glDisableClientState(GL_VERTEX_ARRAY); 736 737 g_Renderer.BindTexture(1, 0); 738 pglClientActiveTextureARB(GL_TEXTURE1_ARB); 739 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 740 741 glLoadIdentity(); 742 743 pglActiveTextureARB(GL_TEXTURE0_ARB); 744 pglClientActiveTextureARB(GL_TEXTURE0_ARB); 745 746 // Clean up the texture matrix and blend mode 747 glLoadIdentity(); 748 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 749 787 750 glMatrixMode(GL_MODELVIEW); 788 751 glDisable(GL_BLEND); 789 752 glDisable(GL_TEXTURE_2D); 790 753 } 791 754 755 756 /////////////////////////////////////////////////////////////////// 757 // Render water that is part of the terrain 758 void TerrainRenderer::RenderWater() 759 { 760 // PROFILE is defined in one of the sub functions 761 762 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 763 764 bool fancy = WaterMgr->WillRenderFancyWater(); 765 766 if (fancy) { 767 bool r = RenderFancyWater(); 768 if (r) return; 769 } 770 RenderSimpleWater(); 771 } 772 792 773 void TerrainRenderer::RenderPriorities() 793 774 { 794 775 PROFILE("render priorities"); -
binaries/data/mods/public/shaders/water_high.vs
15 15 waterDepth = vertexDepth; 16 16 gl_TexCoord[0] = gl_MultiTexCoord0 + translation; 17 17 gl_TexCoord[1] = reflectionMatrix * gl_Vertex; // projective texturing 18 gl_TexCoord[2] = ref lectionMatrix * gl_Vertex;18 gl_TexCoord[2] = refractionMatrix * gl_Vertex; 19 19 gl_TexCoord[3] = losMatrix * gl_Vertex; 20 20 w = gl_TexCoord[1].w; 21 21 gl_Position = ftransform();