diff options
Diffstat (limited to 'linden/indra/newview/lldrawpoolwater.cpp')
-rw-r--r-- | linden/indra/newview/lldrawpoolwater.cpp | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/linden/indra/newview/lldrawpoolwater.cpp b/linden/indra/newview/lldrawpoolwater.cpp new file mode 100644 index 0000000..e3802a1 --- /dev/null +++ b/linden/indra/newview/lldrawpoolwater.cpp | |||
@@ -0,0 +1,748 @@ | |||
1 | /** | ||
2 | * @file lldrawpoolwater.cpp | ||
3 | * @brief LLDrawPoolWater class implementation | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | #include "llfeaturemanager.h" | ||
30 | #include "lldrawpoolwater.h" | ||
31 | |||
32 | #include "llviewercontrol.h" | ||
33 | #include "lldir.h" | ||
34 | #include "llerror.h" | ||
35 | #include "m3math.h" | ||
36 | |||
37 | #include "llagent.h" // for gAgent for getRegion for getWaterHeight | ||
38 | #include "llagparray.h" | ||
39 | #include "llcubemap.h" | ||
40 | #include "lldrawable.h" | ||
41 | #include "llface.h" | ||
42 | #include "llsky.h" | ||
43 | #include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION | ||
44 | #include "llviewerimagelist.h" | ||
45 | #include "llviewerregion.h" | ||
46 | #include "llvosky.h" | ||
47 | #include "llvowater.h" | ||
48 | #include "llworld.h" | ||
49 | #include "pipeline.h" | ||
50 | #include "viewer.h" // gSunTextureID, gMoonTextureID | ||
51 | |||
52 | const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004"); | ||
53 | |||
54 | static float sTime; | ||
55 | |||
56 | int nhpo2(int v) | ||
57 | { | ||
58 | int r = 1; | ||
59 | while (r < v) { | ||
60 | r *= 2; | ||
61 | } | ||
62 | return r; | ||
63 | } | ||
64 | |||
65 | static GLuint sScreenTex = 0; | ||
66 | |||
67 | LLDrawPoolWater::LLDrawPoolWater() : | ||
68 | LLDrawPool(POOL_WATER, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK) | ||
69 | { | ||
70 | mCleanupUnused = TRUE; | ||
71 | mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE); | ||
72 | mHBTex[0]->bind(); | ||
73 | mHBTex[0]->setClamp(TRUE, TRUE); | ||
74 | |||
75 | mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE); | ||
76 | mHBTex[1]->bind(); | ||
77 | mHBTex[1]->setClamp(TRUE, TRUE); | ||
78 | |||
79 | mWaterImagep = gImageList.getImage(WATER_TEST); | ||
80 | mWaterNormp = gImageList.getImage(LLUUID(gViewerArt.getString("water_normal.tga"))); | ||
81 | |||
82 | restoreGL(); | ||
83 | } | ||
84 | |||
85 | LLDrawPoolWater::~LLDrawPoolWater() | ||
86 | { | ||
87 | } | ||
88 | |||
89 | //static | ||
90 | void LLDrawPoolWater::restoreGL() | ||
91 | { | ||
92 | if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= SHADER_LEVEL_RIPPLE) | ||
93 | { | ||
94 | //build screen texture | ||
95 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
96 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
97 | glGenTextures(1, &sScreenTex); | ||
98 | LLGLEnable gl_texture_2d(GL_TEXTURE_2D); | ||
99 | glBindTexture(GL_TEXTURE_2D, sScreenTex); | ||
100 | GLint viewport[4]; | ||
101 | glGetIntegerv(GL_VIEWPORT, viewport); | ||
102 | GLuint resX = nhpo2(viewport[2]); | ||
103 | GLuint resY = nhpo2(viewport[3]); | ||
104 | |||
105 | gImageList.updateMaxResidentTexMem(-1, resX*resY*3); | ||
106 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL); | ||
107 | |||
108 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
109 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
111 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | LLDrawPool *LLDrawPoolWater::instancePool() | ||
117 | { | ||
118 | llerrs << "Should never be calling instancePool on a water pool!" << llendl; | ||
119 | return NULL; | ||
120 | } | ||
121 | |||
122 | |||
123 | void LLDrawPoolWater::prerender() | ||
124 | { | ||
125 | #if 1 // 1.9.1 | ||
126 | mVertexShaderLevel = gSavedSettings.getBOOL("RenderRippleWater") ? | ||
127 | gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) : 0; | ||
128 | #else | ||
129 | mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT); | ||
130 | #endif | ||
131 | } | ||
132 | |||
133 | extern LLColor4U MAX_WATER_COLOR; | ||
134 | |||
135 | void LLDrawPoolWater::render(S32 pass) | ||
136 | { | ||
137 | LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); | ||
138 | if (mDrawFace.empty()) | ||
139 | { | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | LLGLSPipelineAlpha alphaState; | ||
144 | |||
145 | if ((mVertexShaderLevel >= SHADER_LEVEL_RIPPLE)) | ||
146 | { | ||
147 | shade(); | ||
148 | return; | ||
149 | } | ||
150 | |||
151 | if ((mVertexShaderLevel > 0)) | ||
152 | { | ||
153 | renderShaderSimple(); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | LLVOSky *voskyp = gSky.mVOSkyp; | ||
158 | |||
159 | stop_glerror(); | ||
160 | |||
161 | if (!gGLManager.mHasMultitexture) | ||
162 | { | ||
163 | // Ack! No multitexture! Bail! | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | const LLFace* refl_face = voskyp->getReflFace(); | ||
168 | |||
169 | gPipeline.disableLights(); | ||
170 | |||
171 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
172 | |||
173 | LLGLDisable cullFace(GL_CULL_FACE); | ||
174 | |||
175 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
176 | glEnableClientState(GL_VERTEX_ARRAY); | ||
177 | glEnableClientState(GL_NORMAL_ARRAY); | ||
178 | |||
179 | bindGLVertexPointer(); | ||
180 | bindGLNormalPointer(); | ||
181 | bindGLTexCoordPointer(); | ||
182 | |||
183 | // Set up second pass first | ||
184 | glActiveTextureARB(GL_TEXTURE1_ARB); | ||
185 | mWaterImagep->addTextureStats(1024.f*1024.f); | ||
186 | mWaterImagep->bind(1); | ||
187 | |||
188 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | ||
189 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
190 | glEnable(GL_TEXTURE_2D); // Texture unit 1 | ||
191 | |||
192 | LLVector3 camera_up = gCamera->getUpAxis(); | ||
193 | F32 up_dot = camera_up * LLVector3::z_axis; | ||
194 | |||
195 | LLColor4 water_color; | ||
196 | if (gCamera->cameraUnderWater()) | ||
197 | { | ||
198 | water_color.setVec(1.f, 1.f, 1.f, 0.4f); | ||
199 | } | ||
200 | else | ||
201 | { | ||
202 | water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); | ||
203 | } | ||
204 | |||
205 | glColor4fv(water_color.mV); | ||
206 | |||
207 | // Automatically generate texture coords for detail map | ||
208 | glEnable(GL_TEXTURE_GEN_S); //texture unit 1 | ||
209 | glEnable(GL_TEXTURE_GEN_T); //texture unit 1 | ||
210 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | ||
211 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | ||
212 | |||
213 | // Slowly move over time. | ||
214 | F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); | ||
215 | F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; | ||
216 | F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; | ||
217 | glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); | ||
218 | glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); | ||
219 | |||
220 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); | ||
221 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); | ||
222 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); | ||
223 | |||
224 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); | ||
225 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); | ||
226 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); | ||
227 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); | ||
228 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); | ||
229 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); | ||
230 | |||
231 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
232 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
233 | |||
234 | glClearStencil(1); | ||
235 | glClear(GL_STENCIL_BUFFER_BIT); | ||
236 | LLGLEnable gls_stencil(GL_STENCIL_TEST); | ||
237 | glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); | ||
238 | glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); | ||
239 | |||
240 | for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); | ||
241 | iter != mDrawFace.end(); iter++) | ||
242 | { | ||
243 | LLFace *face = *iter; | ||
244 | if (voskyp->isReflFace(face)) | ||
245 | { | ||
246 | continue; | ||
247 | } | ||
248 | face->bindTexture(); | ||
249 | face->renderIndexed(getRawIndices()); | ||
250 | mIndicesDrawn += face->getIndicesCount(); | ||
251 | } | ||
252 | |||
253 | // Now, disable texture coord generation on texture state 1 | ||
254 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | ||
255 | glActiveTextureARB(GL_TEXTURE1_ARB); | ||
256 | glDisable(GL_TEXTURE_2D); // Texture unit 1 | ||
257 | LLImageGL::unbindTexture(1, GL_TEXTURE_2D); | ||
258 | glDisable(GL_TEXTURE_GEN_S); //texture unit 1 | ||
259 | glDisable(GL_TEXTURE_GEN_T); //texture unit 1 | ||
260 | |||
261 | // Disable texture coordinate and color arrays | ||
262 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
263 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
264 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
265 | |||
266 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
267 | stop_glerror(); | ||
268 | |||
269 | if (gSky.mVOSkyp->getCubeMap()) | ||
270 | { | ||
271 | gSky.mVOSkyp->getCubeMap()->enable(0); | ||
272 | gSky.mVOSkyp->getCubeMap()->bind(); | ||
273 | |||
274 | glMatrixMode(GL_TEXTURE); | ||
275 | glLoadIdentity(); | ||
276 | LLMatrix4 camera_mat = gCamera->getModelview(); | ||
277 | LLMatrix4 camera_rot(camera_mat.getMat3()); | ||
278 | camera_rot.invert(); | ||
279 | |||
280 | glLoadMatrixf((F32 *)camera_rot.mMatrix); | ||
281 | |||
282 | glMatrixMode(GL_MODELVIEW); | ||
283 | LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); | ||
284 | |||
285 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||
286 | |||
287 | /*glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); | ||
288 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); | ||
289 | glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); | ||
290 | |||
291 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); | ||
292 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); | ||
293 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); | ||
294 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); | ||
295 | glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); | ||
296 | glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);*/ | ||
297 | |||
298 | for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); | ||
299 | iter != mDrawFace.end(); iter++) | ||
300 | { | ||
301 | LLFace *face = *iter; | ||
302 | if (voskyp->isReflFace(face)) | ||
303 | { | ||
304 | //refl_face = face; | ||
305 | continue; | ||
306 | } | ||
307 | |||
308 | if (face->getGeomCount() > 0) | ||
309 | { | ||
310 | face->renderIndexed(getRawIndices()); | ||
311 | mIndicesDrawn += face->getIndicesCount(); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||
316 | |||
317 | if (gSky.mVOSkyp->getCubeMap()) | ||
318 | { | ||
319 | gSky.mVOSkyp->getCubeMap()->disable(); | ||
320 | } | ||
321 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
322 | glEnable(GL_TEXTURE_2D); | ||
323 | glMatrixMode(GL_TEXTURE); | ||
324 | glLoadIdentity(); | ||
325 | glMatrixMode(GL_MODELVIEW); | ||
326 | |||
327 | } | ||
328 | |||
329 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | ||
330 | |||
331 | if (refl_face) | ||
332 | { | ||
333 | glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); | ||
334 | renderReflection(refl_face); | ||
335 | } | ||
336 | |||
337 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
338 | glDisableClientState(GL_NORMAL_ARRAY); | ||
339 | |||
340 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||
341 | |||
342 | } | ||
343 | |||
344 | |||
345 | void LLDrawPoolWater::renderShaderSimple() | ||
346 | { | ||
347 | LLVOSky *voskyp = gSky.mVOSkyp; | ||
348 | |||
349 | stop_glerror(); | ||
350 | |||
351 | if (!gGLManager.mHasMultitexture) | ||
352 | { | ||
353 | // Ack! No multitexture! Bail! | ||
354 | return; | ||
355 | } | ||
356 | |||
357 | const LLFace* refl_face = voskyp->getReflFace(); | ||
358 | |||
359 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
360 | |||
361 | LLGLDisable cullFace(GL_CULL_FACE); | ||
362 | |||
363 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
364 | glEnableClientState(GL_VERTEX_ARRAY); | ||
365 | glEnableClientState(GL_NORMAL_ARRAY); | ||
366 | |||
367 | bindGLVertexPointer(); | ||
368 | bindGLNormalPointer(); | ||
369 | bindGLTexCoordPointer(); | ||
370 | |||
371 | // Set up second pass first | ||
372 | S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP); | ||
373 | mWaterImagep->addTextureStats(1024.f*1024.f); | ||
374 | mWaterImagep->bind(bumpTex); | ||
375 | |||
376 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | ||
377 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
378 | |||
379 | LLVector3 camera_up = gCamera->getUpAxis(); | ||
380 | F32 up_dot = camera_up * LLVector3::z_axis; | ||
381 | |||
382 | LLColor4 water_color; | ||
383 | if (gCamera->cameraUnderWater()) | ||
384 | { | ||
385 | water_color.setVec(1.f, 1.f, 1.f, 0.4f); | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); | ||
390 | } | ||
391 | |||
392 | glColor4fv(water_color.mV); | ||
393 | |||
394 | // Automatically generate texture coords for detail map | ||
395 | glActiveTextureARB(GL_TEXTURE1_ARB); | ||
396 | glEnable(GL_TEXTURE_GEN_S); //texture unit 1 | ||
397 | glEnable(GL_TEXTURE_GEN_T); //texture unit 1 | ||
398 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | ||
399 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | ||
400 | |||
401 | // Slowly move over time. | ||
402 | F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); | ||
403 | F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; | ||
404 | F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; | ||
405 | glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); | ||
406 | glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); | ||
407 | |||
408 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
409 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
410 | |||
411 | glClearStencil(1); | ||
412 | glClear(GL_STENCIL_BUFFER_BIT); | ||
413 | LLGLEnable gls_stencil(GL_STENCIL_TEST); | ||
414 | glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); | ||
415 | glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); | ||
416 | |||
417 | S32 envTex = -1; | ||
418 | |||
419 | if (gSky.mVOSkyp->getCubeMap()) | ||
420 | { | ||
421 | envTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); | ||
422 | gSky.mVOSkyp->getCubeMap()->bind(); | ||
423 | |||
424 | glMatrixMode(GL_TEXTURE); | ||
425 | glLoadIdentity(); | ||
426 | LLMatrix4 camera_mat = gCamera->getModelview(); | ||
427 | LLMatrix4 camera_rot(camera_mat.getMat3()); | ||
428 | camera_rot.invert(); | ||
429 | |||
430 | glLoadMatrixf((F32 *)camera_rot.mMatrix); | ||
431 | |||
432 | glMatrixMode(GL_MODELVIEW); | ||
433 | } | ||
434 | |||
435 | S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); | ||
436 | LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); | ||
437 | |||
438 | S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); | ||
439 | |||
440 | gPipeline.mWaterProgram.bind(); | ||
441 | |||
442 | for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); | ||
443 | iter != mDrawFace.end(); iter++) | ||
444 | { | ||
445 | LLFace *face = *iter; | ||
446 | if (voskyp->isReflFace(face)) | ||
447 | { | ||
448 | continue; | ||
449 | } | ||
450 | face->bindTexture(diffTex); | ||
451 | face->renderIndexed(getRawIndices()); | ||
452 | mIndicesDrawn += face->getIndicesCount(); | ||
453 | } | ||
454 | |||
455 | if (gSky.mVOSkyp->getCubeMap()) | ||
456 | { | ||
457 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); | ||
458 | glMatrixMode(GL_TEXTURE); | ||
459 | glLoadIdentity(); | ||
460 | glMatrixMode(GL_MODELVIEW); | ||
461 | } | ||
462 | |||
463 | // Now, disable texture coord generation on texture state 1 | ||
464 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP); | ||
465 | LLImageGL::unbindTexture(bumpTex, GL_TEXTURE_2D); | ||
466 | |||
467 | glActiveTextureARB(GL_TEXTURE1_ARB); | ||
468 | glDisable(GL_TEXTURE_GEN_S); //texture unit 1 | ||
469 | glDisable(GL_TEXTURE_GEN_T); //texture unit 1 | ||
470 | |||
471 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); | ||
472 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); | ||
473 | |||
474 | // Disable texture coordinate and color arrays | ||
475 | LLImageGL::unbindTexture(diffTex, GL_TEXTURE_2D); | ||
476 | |||
477 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
478 | stop_glerror(); | ||
479 | |||
480 | glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | ||
481 | |||
482 | glUseProgramObjectARB(0); | ||
483 | gPipeline.disableLights(); | ||
484 | |||
485 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
486 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
487 | glEnable(GL_TEXTURE_2D); | ||
488 | |||
489 | if (refl_face) | ||
490 | { | ||
491 | glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); | ||
492 | renderReflection(refl_face); | ||
493 | } | ||
494 | |||
495 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
496 | glDisableClientState(GL_NORMAL_ARRAY); | ||
497 | } | ||
498 | |||
499 | void LLDrawPoolWater::renderReflection(const LLFace* face) | ||
500 | { | ||
501 | LLVOSky *voskyp = gSky.mVOSkyp; | ||
502 | |||
503 | if (!voskyp) | ||
504 | { | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | if (!face->getGeomCount()) | ||
509 | { | ||
510 | return; | ||
511 | } | ||
512 | |||
513 | S8 dr = voskyp->getDrawRefl(); | ||
514 | if (dr < 0) | ||
515 | { | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | LLGLSNoFog noFog; | ||
520 | |||
521 | glEnableClientState(GL_VERTEX_ARRAY); | ||
522 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
523 | |||
524 | LLViewerImage::bindTexture(mHBTex[dr]); | ||
525 | |||
526 | LLOverrideFaceColor override(this, face->getFaceColor().mV); | ||
527 | face->renderIndexed(getRawIndices()); | ||
528 | mIndicesDrawn += face->getIndicesCount(); | ||
529 | |||
530 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
531 | } | ||
532 | |||
533 | void bindScreenToTexture() | ||
534 | { | ||
535 | GLint viewport[4]; | ||
536 | glGetIntegerv(GL_VIEWPORT, viewport); | ||
537 | GLuint resX = nhpo2(viewport[2]); | ||
538 | GLuint resY = nhpo2(viewport[3]); | ||
539 | |||
540 | glBindTexture(GL_TEXTURE_2D, sScreenTex); | ||
541 | GLint cResX; | ||
542 | GLint cResY; | ||
543 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX); | ||
544 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY); | ||
545 | |||
546 | if (cResX != (GLint)resX || cResY != (GLint)resY) | ||
547 | { | ||
548 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL); | ||
549 | gImageList.updateMaxResidentTexMem(-1, resX*resY*3); | ||
550 | } | ||
551 | |||
552 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); | ||
553 | |||
554 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
555 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
556 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
557 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
558 | |||
559 | float scale[2]; | ||
560 | scale[0] = (float) viewport[2]/resX; | ||
561 | scale[1] = (float) viewport[3]/resY; | ||
562 | glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale); | ||
563 | |||
564 | LLImageGL::sBoundTextureMemory += resX * resY * 3; | ||
565 | } | ||
566 | |||
567 | void LLDrawPoolWater::shade() | ||
568 | { | ||
569 | static LLVector2 d1( 0.5f, -0.17f ); | ||
570 | static LLVector2 d2( 0.58f, -0.67f ); | ||
571 | static LLVector2 d3( 0.5f, 0.25f ); | ||
572 | |||
573 | static LLVector3 wave1(1,0.42f,1); | ||
574 | static LLVector3 wave2(0.58f,0.42f,0.17f); | ||
575 | static LLVector3 wave3(0.42f,0.67f,0.33f); | ||
576 | |||
577 | /*static LLVector2 d1( 0.83f, -1 ); | ||
578 | static LLVector2 d2( 0.58f, 1 ); | ||
579 | static LLVector2 d3( 1, -0.88f ); | ||
580 | |||
581 | static LLVector4 wave1(0.75f,0.08f,0.5f,0.67f); | ||
582 | static LLVector4 wave2(0.17f,0.33f,0.53f,0.62f); | ||
583 | static LLVector4 wave3(0.17f,0.6f,0.67f,1);*/ | ||
584 | |||
585 | /*LLDebugVarMessageBox::show("Wave Direction 1", &d1, LLVector2(1,1), LLVector2(0.01f, 0.01f)); | ||
586 | LLDebugVarMessageBox::show("Wave Direction 2", &d2, LLVector2(1,1), LLVector2(0.01f, 0.01f)); | ||
587 | LLDebugVarMessageBox::show("Wave Direction 3", &d3, LLVector2(1,1), LLVector2(0.01f, 0.01f)); | ||
588 | |||
589 | LLDebugVarMessageBox::show("Wave 1", &wave1, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f)); | ||
590 | LLDebugVarMessageBox::show("Wave 2", &wave2, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f)); | ||
591 | LLDebugVarMessageBox::show("Wave 3", &wave3, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f));*/ | ||
592 | |||
593 | LLVOSky *voskyp = gSky.mVOSkyp; | ||
594 | |||
595 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
596 | glEnableClientState(GL_VERTEX_ARRAY); | ||
597 | glEnableClientState(GL_NORMAL_ARRAY); | ||
598 | LLGLDisable blend(GL_BLEND); | ||
599 | bindGLVertexPointer(); | ||
600 | bindGLNormalPointer(); | ||
601 | bindGLTexCoordPointer(); | ||
602 | |||
603 | LLColor3 light_diffuse(0,0,0); | ||
604 | F32 light_exp = 0.0f; | ||
605 | LLVector3 light_dir; | ||
606 | |||
607 | if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) | ||
608 | { | ||
609 | light_dir = gSky.getSunDirection(); | ||
610 | light_dir.normVec(); | ||
611 | light_diffuse = gSky.mVOSkyp->getSun().getColorCached(); | ||
612 | light_diffuse.normVec(); | ||
613 | light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); | ||
614 | light_diffuse *= light_exp + 0.25f; | ||
615 | } | ||
616 | else | ||
617 | { | ||
618 | light_dir = gSky.getMoonDirection(); | ||
619 | light_dir.normVec(); | ||
620 | light_diffuse = gSky.mVOSkyp->getMoon().getColorCached(); | ||
621 | light_diffuse.normVec(); | ||
622 | light_diffuse *= 0.5f; | ||
623 | light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); | ||
624 | } | ||
625 | |||
626 | light_exp *= light_exp; | ||
627 | light_exp *= light_exp; | ||
628 | light_exp *= light_exp; | ||
629 | light_exp *= light_exp; | ||
630 | light_exp *= light_exp; | ||
631 | light_exp *= 512.f; | ||
632 | light_exp = light_exp > 32.f ? light_exp : 32.f; | ||
633 | |||
634 | sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; | ||
635 | |||
636 | LLCubeMap* skyMap = gSky.mVOSkyp->getCubeMap(); | ||
637 | |||
638 | gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); | ||
639 | skyMap->bind(); | ||
640 | |||
641 | //bind normal map | ||
642 | S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP); | ||
643 | mWaterNormp->addTextureStats(1024.f*1024.f); | ||
644 | mWaterNormp->bind(bumpTex); | ||
645 | |||
646 | gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_WATER_SCREENTEX); | ||
647 | |||
648 | gPipeline.mWaterProgram.bind(); | ||
649 | |||
650 | bindScreenToTexture(); | ||
651 | |||
652 | S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); | ||
653 | LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); | ||
654 | |||
655 | S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); | ||
656 | |||
657 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
658 | |||
659 | glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_TIME], sTime); | ||
660 | glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_SPECULAR], 1, light_diffuse.mV); | ||
661 | glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_SPECULAR_EXP], light_exp); | ||
662 | glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_EYEVEC], 1, gCamera->getOrigin().mV); | ||
663 | glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_WAVE_DIR1], 1, d1.mV); | ||
664 | glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_WAVE_DIR2], 1, d2.mV); | ||
665 | glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_LIGHT_DIR], 1, light_dir.mV); | ||
666 | |||
667 | LLColor4 water_color; | ||
668 | LLVector3 camera_up = gCamera->getUpAxis(); | ||
669 | F32 up_dot = camera_up * LLVector3::z_axis; | ||
670 | if (gCamera->cameraUnderWater()) | ||
671 | { | ||
672 | water_color.setVec(1.f, 1.f, 1.f, 0.4f); | ||
673 | glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_REFSCALE], 0.25f); | ||
674 | } | ||
675 | else | ||
676 | { | ||
677 | water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); | ||
678 | glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_REFSCALE], 0.01f); | ||
679 | } | ||
680 | if (water_color.mV[3] > 0.9f) | ||
681 | { | ||
682 | water_color.mV[3] = 0.9f; | ||
683 | } | ||
684 | |||
685 | glColor4fv(water_color.mV); | ||
686 | |||
687 | { | ||
688 | LLGLDisable cullface(GL_CULL_FACE); | ||
689 | for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); | ||
690 | iter != mDrawFace.end(); iter++) | ||
691 | { | ||
692 | LLFace *face = *iter; | ||
693 | |||
694 | if (voskyp->isReflFace(face)) | ||
695 | { | ||
696 | continue; | ||
697 | } | ||
698 | |||
699 | face->bindTexture(diffTex); | ||
700 | face->renderIndexed(getRawIndices()); | ||
701 | mIndicesDrawn += face->getIndicesCount(); | ||
702 | } | ||
703 | } | ||
704 | |||
705 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); | ||
706 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_WATER_SCREENTEX); | ||
707 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP); | ||
708 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); | ||
709 | gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); | ||
710 | |||
711 | glActiveTextureARB(GL_TEXTURE0_ARB); | ||
712 | glEnable(GL_TEXTURE_2D); | ||
713 | glUseProgramObjectARB(0); | ||
714 | |||
715 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
716 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
717 | |||
718 | /*glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
719 | glDisableClientState(GL_VERTEX_ARRAY); | ||
720 | glDisableClientState(GL_NORMAL_ARRAY);*/ | ||
721 | } | ||
722 | |||
723 | void LLDrawPoolWater::renderForSelect() | ||
724 | { | ||
725 | // Can't select water! | ||
726 | return; | ||
727 | } | ||
728 | |||
729 | |||
730 | void LLDrawPoolWater::renderFaceSelected(LLFace *facep, | ||
731 | LLImageGL *image, | ||
732 | const LLColor4 &color, | ||
733 | const S32 index_offset, const S32 index_count) | ||
734 | { | ||
735 | // Can't select water | ||
736 | return; | ||
737 | } | ||
738 | |||
739 | |||
740 | LLViewerImage *LLDrawPoolWater::getDebugTexture() | ||
741 | { | ||
742 | return LLViewerImage::sSmokeImagep; | ||
743 | } | ||
744 | |||
745 | LLColor3 LLDrawPoolWater::getDebugColor() const | ||
746 | { | ||
747 | return LLColor3(0.f, 1.f, 1.f); | ||
748 | } | ||