Ticket #721: water_ro_r4_r9073.patch
File water_ro_r4_r9073.patch, 32.1 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 // Fancy water vertex description data structure 134 struct SWaterVertex { 135 // vertex position 136 CVector3D m_Position; 137 // vertex uvs for normal map texture 138 float m_UVs[2]; 139 // (fancy water only) vertex 3d for texture 1 == vertex position so removed 140 // water depth (varying for shader) 141 float m_Depth; 142 // (simple water only) Color TODO: Try to use packed colors? (here:floats) 143 RGBAColor m_Color; 144 // TODO: Add padding up to 64bytes? (for 32 bytes align) 145 }; 146 147 // Water vertex buffer 148 CVertexBuffer::VBChunk* m_VBWater; 149 150 // Build data for water (NB: needed each frame as reference data for 151 // computing simple water) 152 std::vector<SWaterVertex> m_WaterVertexData; 153 154 // 256*256 seems to be enough 155 std::vector<unsigned short> m_WaterIndices; 156 157 // Build water vertices (vertex buffer and data vector) 158 void BuildWaterVertices(); 159 // Build water indices array 160 void BuildWaterIndices(); 161 162 // maximum and minimum depth of water at all vertices on the patch 163 // signed value: can be negative (if vertex emerges of water) 164 float max_wdepth; 165 float min_wdepth; 166 // Check if there is water on this patch (useful sometimes internally) 167 bool FullyEmerged(); 168 bool EntirelyUnderWater(); 169 170 // parameter allowing a varying number of triangles per patch for LOD 171 // MUST be an exact divisor of PATCH_SIZE 172 // compiled const for the moment until/if dynamic water LOD is offered 173 // savings would be mostly beneficial for GPU or simple water 174 static const size_t water_cell_size = 1; 129 175 }; 130 176 131 177 #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(); … … 72 73 if (m_VBBaseIndices) g_VBMan.Release(m_VBBaseIndices); 73 74 if (m_VBBlends) g_VBMan.Release(m_VBBlends); 74 75 if (m_VBBlendIndices) g_VBMan.Release(m_VBBlendIndices); 76 if (m_VBWater) g_VBMan.Release(m_VBWater); 75 77 } 76 78 77 79 const float uvFactor = 0.125f / sqrt(2.f); … … 631 633 BuildSides(); 632 634 BuildIndices(); 633 635 BuildBlends(); 636 637 BuildWaterVertices(); 638 BuildWaterIndices(); 634 639 } 635 640 636 641 void CPatchRData::Update() … … 644 649 BuildIndices(); 645 650 BuildBlends(); 646 651 652 BuildWaterVertices(); 653 BuildWaterIndices(); 654 647 655 m_UpdateFlags=0; 648 656 } 649 657 } … … 1048 1056 } 1049 1057 } 1050 1058 } 1059 1060 // 1061 // Water build and rendering 1062 // 1063 1064 // Build vertex buffer for water vertices over our patch 1065 void CPatchRData::BuildWaterVertices() 1066 { 1067 // number of vertices in each direction in each patch 1068 debug_assert((PATCH_SIZE % water_cell_size) == 0); 1069 const ssize_t vsize=(PATCH_SIZE / water_cell_size)+1; 1070 1071 m_WaterVertexData.resize(vsize*vsize); 1072 1073 // We need to use this to access the water manager or we may not have the 1074 // actual values but some compiled-in defaults 1075 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 1076 1077 // TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults 1078 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 1079 const float repeatPeriod = WaterMgr->m_RepeatPeriod; 1080 #if 0 1081 // With non fancy water, period is a constant? TODO: Check 1082 const float repeatPeriod = 16.0f; 1083 #endif 1084 1085 1086 CPatch* patch = m_Patch; 1087 CTerrain* terrain = patch->m_Parent; 1088 1089 max_wdepth = -FLT_MAX; 1090 min_wdepth = FLT_MAX; 1091 // build vertices, uv, and shader varying 1092 for (ssize_t j=0;j<vsize;j++) 1093 { 1094 for (ssize_t i=0;i<vsize;i++) 1095 { 1096 ssize_t ix=(patch->m_X*PATCH_SIZE)+(i*water_cell_size); 1097 ssize_t iz=(patch->m_Z*PATCH_SIZE)+(j*water_cell_size); 1098 ssize_t v=(j*vsize)+i; 1099 1100 // calculate vertex data like for base vertices 1101 terrain->CalcPosition(ix,iz,m_WaterVertexData[v].m_Position); 1102 // at this step, Y is still terrainHeight 1103 const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(ix,iz); 1104 const float wdepth = waterHeight - m_WaterVertexData[v].m_Position.Y; 1105 m_WaterVertexData[v].m_Depth = wdepth; 1106 // replaces Y by water height 1107 m_WaterVertexData[v].m_Position.Y = waterHeight; 1108 // calculates U/V (TODO: could be done in vertex shader for fancy water? would be beneficial?) 1109 m_WaterVertexData[v].m_UVs[0] = m_WaterVertexData[v].m_Position.X / repeatPeriod; 1110 m_WaterVertexData[v].m_UVs[1] = m_WaterVertexData[v].m_Position.Z / repeatPeriod; 1111 // Set initial color (for simple water only) 1112 m_WaterVertexData[v].m_Color.m_X = WaterMgr->m_WaterColor.r; 1113 m_WaterVertexData[v].m_Color.m_Y = WaterMgr->m_WaterColor.g; 1114 m_WaterVertexData[v].m_Color.m_Z = WaterMgr->m_WaterColor.b; 1115 const float alpha = clamp( wdepth / WaterMgr->m_WaterFullDepth 1116 + WaterMgr->m_WaterAlphaOffset, 1117 WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha); 1118 m_WaterVertexData[v].m_Color.m_W = alpha; 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 // overall depth around patch is ready now 1126 // so, if we are fully emerged, we can get rid of things 1127 if (FullyEmerged()) // i.e.: (max_wdepth < 0.0f) 1128 { 1129 if (m_VBWater) { 1130 g_VBMan.Release(m_VBWater); 1131 } 1132 } 1133 else 1134 { 1135 // allocate vertex buffer 1136 if (!m_VBWater) { 1137 m_VBWater=g_VBMan.Allocate(sizeof(SWaterVertex),m_WaterVertexData.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER); 1138 } 1139 // upload now for fancy water usage 1140 // for simple water upload will be redone for each frame with color update 1141 m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]); 1142 debug_assert(m_VBWater->m_Index < 65536); 1143 } 1144 // The vertex buffer must be ready for indices calculation 1145 } 1146 1147 1148 void CPatchRData::BuildWaterIndices() 1149 { 1150 // release existing indices 1151 m_WaterIndices.clear(); 1152 1153 if (FullyEmerged()) 1154 return; 1155 1156 // must have allocated some vertices before trying to build corresponding indices 1157 debug_assert(m_VBWater); 1158 1159 CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); 1160 1161 CPatch* patch = m_Patch; 1162 CTerrain* terrain = patch->m_Parent; 1163 1164 // build indices for water 1165 size_t base_indice=m_VBWater->m_Index; 1166 1167 for(ssize_t dx=0; dx<PATCH_SIZE; dx+=water_cell_size) 1168 { 1169 for(ssize_t dz=0; dz<PATCH_SIZE; dz+=water_cell_size) 1170 { 1171 ssize_t x = (patch->m_X*PATCH_SIZE + dx); 1172 ssize_t z = (patch->m_Z*PATCH_SIZE + dz); 1173 1174 // Some offsets used to go around counterclockwise while keeping code concise 1175 const int DX[] = {water_cell_size,water_cell_size,0,0}; 1176 const int DZ[] = {0,water_cell_size,water_cell_size,0}; 1177 1178 const float waterHeight = (cmpWaterManager.null()) ? 0.0f : cmpWaterManager->GetExactWaterLevel(x,z); 1179 1180 // NB: I do not reuse the values already computed for building the vertex buffer/data 1181 // here, even though it would probably be more readable, because it allows to 1182 // use the same function for building indices for fancy and non-fancy water (which 1183 // have different vertex buffer elements). 1184 // But reference visibility info. is for vertices. 1185 1186 // is any corner of the tile below the water height? if not, no point rendering it 1187 bool shouldRender = false; 1188 for (int j = 0; j < 4; j++) 1189 { 1190 const float terrainHeight = terrain->GetVertexGroundLevel(x + DX[j], z + DZ[j]); 1191 if (terrainHeight < waterHeight) 1192 { 1193 shouldRender = true; 1194 break; 1195 } 1196 } 1197 if (!shouldRender) 1198 continue; 1199 for (int j=0; j<4; j++) 1200 { 1201 ssize_t ix = (dx + DX[j])/water_cell_size; 1202 ssize_t iz = (dz + DZ[j])/water_cell_size; 1203 ssize_t v=(iz*((PATCH_SIZE/water_cell_size)+1))+ix; 1204 m_WaterIndices.push_back(u16(v)+base_indice); 1205 debug_assert((u16(v)+base_indice) < 65535); 1206 } 1207 } 1208 } 1209 } 1210 1211 const float EPSILON = 1e-12; 1212 1213 // if the maximum water size is negative, the patch is entirely emerged 1214 bool CPatchRData::FullyEmerged() 1215 { 1216 return (max_wdepth < EPSILON); 1217 } 1218 // if the minimum water size is still positive, the patch is entirely under water 1219 bool CPatchRData::EntirelyUnderWater() 1220 { 1221 return (min_wdepth > -EPSILON); 1222 } 1223 1224 void CPatchRData::RenderSimpleWater() 1225 { 1226 debug_assert(m_UpdateFlags==0); 1227 1228 if (FullyEmerged()) 1229 return; 1230 1231 #if 1 // Cut here if you do not want the CPU+buffer_update effect (costly) 1232 WaterManager* WaterMgr = g_Renderer.GetWaterManager(); 1233 1234 // This is probably changing so vertices need update! 1235 const CCamera& camera = g_Renderer.GetViewCamera(); 1236 CVector3D camPos = camera.m_Orientation.GetTranslation(); 1237 1238 // build vertex buffer with adequate alpha 1239 for (unsigned int i=0; i < m_WaterVertexData.size(); i++) 1240 { 1241 const float alpha = clamp( (m_WaterVertexData[i].m_Depth) / WaterMgr->m_WaterFullDepth 1242 + WaterMgr->m_WaterAlphaOffset, 1243 WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha); 1244 1245 // (Crappy) fresnel effect 1246 CVector3D CamFaceVertex=CVector3D(m_WaterVertexData[i].m_Position.X, 1247 WaterMgr->m_WaterHeight, 1248 m_WaterVertexData[i].m_Position.Z) - camPos; 1249 // Note: WaterMgr->m_WaterHeight is also m_WaterVertexData[i].m_Position.Y I think... 1250 CamFaceVertex.Normalize(); 1251 float FresnelScalar = CamFaceVertex.Dot(CVector3D(0.0f, -1.0f, 0.0f)); 1252 // Invert and set boundaries 1253 FresnelScalar = 1.f - (FresnelScalar * 0.6); 1254 // Set Color 1255 // (r,g,b) done statically 1256 // m_WaterVertexData[i].m_Color.m_X = WaterMgr->m_WaterColor.r; 1257 //m_WaterVertexData[i].m_Color.m_Y = WaterMgr->m_WaterColor.g; 1258 //m_WaterVertexData[i].m_Color.m_Z = WaterMgr->m_WaterColor.b; 1259 m_WaterVertexData[i].m_Color.m_W = alpha * FresnelScalar; 1260 } 1261 // upload to vertex buffer 1262 m_VBWater->m_Owner->UpdateChunkVertices(m_VBWater,&m_WaterVertexData[0]); 1263 #endif 1264 1265 SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind(); 1266 1267 // setup data pointers 1268 GLsizei stride = sizeof(SWaterVertex); 1269 glColorPointer(4, GL_FLOAT, stride, &base->m_Color[0]); 1270 glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]); 1271 pglClientActiveTextureARB(GL_TEXTURE0); 1272 glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]); // render 1273 pglClientActiveTextureARB(GL_TEXTURE1); 1274 glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position[0]); // (same data as vertex) 1275 1276 if (!g_Renderer.m_SkipSubmit) { 1277 glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(), 1278 GL_UNSIGNED_SHORT, &m_WaterIndices[0]); 1279 } 1280 // bump stats 1281 g_Renderer.m_Stats.m_DrawCalls++; 1282 // TODO: Water stats? 1283 1284 CVertexBuffer::Unbind(); 1285 } 1286 1287 void CPatchRData::RenderFancyWater(GLint waterDepth) 1288 { 1289 debug_assert(m_UpdateFlags==0); 1290 1291 if (FullyEmerged()) 1292 return; 1293 1294 SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind(); 1295 1296 // setup data pointers 1297 GLsizei stride = sizeof(SWaterVertex); 1298 glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]); 1299 pglClientActiveTextureARB(GL_TEXTURE0); 1300 glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]); 1301 pglVertexAttribPointerARB(waterDepth, 1, GL_FLOAT, GL_FALSE, /* not to be normalized */ 1302 stride, &base->m_Depth); 1303 // render 1304 if (!g_Renderer.m_SkipSubmit) { 1305 glDrawElements(GL_QUADS, (GLsizei) m_WaterIndices.size(), 1306 GL_UNSIGNED_SHORT, &m_WaterIndices[0]); 1307 } 1308 // bump stats 1309 g_Renderer.m_Stats.m_DrawCalls++; 1310 // TODO: Water stats? 1311 1312 CVertexBuffer::Unbind(); 1313 1314 } 1315 -
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();