aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lldrawpoolbump.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldrawpoolbump.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/lldrawpoolbump.cpp1154
1 files changed, 1154 insertions, 0 deletions
diff --git a/linden/indra/newview/lldrawpoolbump.cpp b/linden/indra/newview/lldrawpoolbump.cpp
new file mode 100644
index 0000000..28e60f1
--- /dev/null
+++ b/linden/indra/newview/lldrawpoolbump.cpp
@@ -0,0 +1,1154 @@
1/**
2 * @file lldrawpoolbump.cpp
3 * @brief LLDrawPoolBump class implementation
4 *
5 * Copyright (c) 2003-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
30#include "lldrawpoolbump.h"
31
32#include "llstl.h"
33#include "llviewercontrol.h"
34#include "lldir.h"
35#include "llimagegl.h"
36#include "m3math.h"
37#include "m4math.h"
38
39#include "llagent.h"
40#include "llagparray.h"
41#include "llcubemap.h"
42#include "lldrawable.h"
43#include "lldrawpoolsimple.h"
44#include "llface.h"
45#include "llgl.h"
46#include "llsky.h"
47#include "lltextureentry.h"
48#include "llviewercamera.h"
49#include "llviewerimagelist.h"
50#include "pipeline.h"
51
52
53//#include "llimagebmp.h"
54//#include "../tools/imdebug/imdebug.h"
55
56// static
57LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
58
59// static
60U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
61
62// static
63LLBumpImageList gBumpImageList;
64
65const S32 STD_BUMP_LATEST_FILE_VERSION = 1;
66
67S32 LLDrawPoolBump::sBumpTex = -1;
68S32 LLDrawPoolBump::sDiffTex = -1;
69S32 LLDrawPoolBump::sEnvTex = -1;
70
71// static
72void LLStandardBumpmap::init()
73{
74 LLStandardBumpmap::restoreGL();
75}
76
77// static
78void LLStandardBumpmap::shutdown()
79{
80 LLStandardBumpmap::destroyGL();
81}
82
83// static
84void LLStandardBumpmap::restoreGL()
85{
86 llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
87 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None"); // BE_NO_BUMP
88 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness"); // BE_BRIGHTNESS
89 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS
90
91 std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
92 FILE* file = LLFile::fopen( file_name.c_str(), "rt" );
93 if( !file )
94 {
95 llwarns << "Could not open std_bump <" << file_name << ">" << llendl;
96 return;
97 }
98
99 S32 file_version = 0;
100
101 S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version );
102 if( fields_read != 1 )
103 {
104 llwarns << "Bad LLStandardBumpmap header" << llendl;
105 return;
106 }
107
108 if( file_version > STD_BUMP_LATEST_FILE_VERSION )
109 {
110 llwarns << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << llendl;
111 return;
112 }
113
114 while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) )
115 {
116 char label[2048] = "";
117 char bump_file[2048] = "";
118 fields_read = fscanf( file, "\n%s %s", label, bump_file);
119 if( EOF == fields_read )
120 {
121 break;
122 }
123 if( fields_read != 2 )
124 {
125 llwarns << "Bad LLStandardBumpmap entry" << llendl;
126 return;
127 }
128
129 llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
130 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
131 gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImage( LLUUID(gViewerArt.getString(bump_file)) );
132 LLStandardBumpmap::sStandardBumpmapCount++;
133 }
134
135 fclose( file );
136}
137
138// static
139void LLStandardBumpmap::destroyGL()
140{
141 for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ )
142 {
143 gStandardBumpmapList[i].mLabel.assign("");
144 gStandardBumpmapList[i].mImage = NULL;
145 }
146 sStandardBumpmapCount = 0;
147}
148
149
150
151////////////////////////////////////////////////////////////////
152
153LLDrawPoolBump::LLDrawPoolBump(LLViewerImage *texturep) :
154 LLDrawPool(POOL_BUMP, DATA_BUMP_IL_MASK | DATA_COLORS_MASK, DATA_SIMPLE_NIL_MASK),
155 mTexturep(texturep)
156{
157}
158
159LLDrawPool *LLDrawPoolBump::instancePool()
160{
161 return new LLDrawPoolBump(mTexturep);
162}
163
164
165void LLDrawPoolBump::prerender()
166{
167 mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT);
168}
169
170BOOL LLDrawPoolBump::match(LLFace* last_face, LLFace* facep)
171{
172 if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES) &&
173 !last_face->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
174 !facep->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) &&
175 facep->getIndicesStart() == last_face->getIndicesStart()+last_face->getIndicesCount() &&
176 facep->getRenderColor() == last_face->getRenderColor() &&
177 facep->getTextureEntry()->getShiny() == last_face->getTextureEntry()->getShiny() &&
178 facep->getTextureEntry()->getBumpmap() == last_face->getTextureEntry()->getBumpmap())
179 {
180 if (facep->isState(LLFace::GLOBAL))
181 {
182 if (last_face->isState(LLFace::GLOBAL))
183 {
184 return TRUE;
185 }
186 }
187 else
188 {
189 if (!last_face->isState(LLFace::GLOBAL))
190 {
191 if (last_face->getRenderMatrix() == facep->getRenderMatrix())
192 {
193 return TRUE;
194 }
195 }
196 }
197 }
198
199 return FALSE;
200}
201
202// static
203S32 LLDrawPoolBump::numBumpPasses()
204{
205 if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0)
206 {
207 return 1; // single pass for shaders
208 }
209 else
210 {
211 if (gSavedSettings.getBOOL("RenderObjectBump"))
212 return 3;
213 else
214 return 1;
215 }
216}
217
218S32 LLDrawPoolBump::getNumPasses()
219{
220 return numBumpPasses();
221}
222
223void LLDrawPoolBump::beginRenderPass(S32 pass)
224{
225 switch( pass )
226 {
227 case 0:
228 beginPass0(this);
229 break;
230 case 1:
231 beginPass1();
232 break;
233 case 2:
234 beginPass2();
235 break;
236 default:
237 llassert(0);
238 break;
239 }
240}
241
242void LLDrawPoolBump::render(S32 pass)
243{
244 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
245 if (!mTexturep)
246 {
247 return;
248 }
249
250 if (mDrawFace.empty())
251 {
252 return;
253 }
254
255 const U32* index_array = getRawIndices();
256
257 S32 indices = 0;
258 switch( pass )
259 {
260 case 0:
261 {
262 stop_glerror();
263
264 bindGLVertexPointer();
265 bindGLTexCoordPointer();
266 bindGLNormalPointer();
267 if (gPipeline.getLightingDetail() >= 2)
268 {
269 bindGLColorPointer();
270 }
271
272 stop_glerror();
273
274 LLGLState alpha_test(GL_ALPHA_TEST, FALSE);
275 LLGLState blend(GL_BLEND, FALSE);
276 LLViewerImage* tex = getTexture();
277 if (tex && tex->getPrimaryFormat() == GL_ALPHA)
278 {
279 // Enable Invisibility Hack
280 alpha_test.enable();
281 blend.enable();
282 }
283 indices += renderPass0(this, mDrawFace, index_array, mTexturep);
284 break;
285 }
286 case 1:
287 {
288 bindGLVertexPointer();
289 bindGLNormalPointer();
290 indices += renderPass1(mDrawFace, index_array, mTexturep);
291 break;
292 }
293 case 2:
294 {
295 bindGLVertexPointer();
296 // Texture unit 0
297 glActiveTextureARB(GL_TEXTURE0_ARB);
298 glClientActiveTextureARB(GL_TEXTURE0_ARB);
299 bindGLTexCoordPointer();
300 // Texture unit 1
301 glActiveTextureARB(GL_TEXTURE1_ARB);
302 glClientActiveTextureARB(GL_TEXTURE1_ARB);
303 bindGLTexCoordPointer(1);
304 indices += renderPass2(mDrawFace, index_array, mTexturep);
305 break;
306 }
307 default:
308 {
309 llassert(0);
310 break;
311 }
312 }
313 mIndicesDrawn += indices;
314}
315
316void LLDrawPoolBump::endRenderPass(S32 pass)
317{
318 switch( pass )
319 {
320 case 0:
321 endPass0(this);
322 break;
323 case 1:
324 endPass1();
325 break;
326 case 2:
327 endPass2();
328 break;
329 default:
330 llassert(0);
331 break;
332 }
333}
334
335//static
336void LLDrawPoolBump::beginPass0(LLDrawPool* pool)
337{
338 stop_glerror();
339 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
340 glEnableClientState(GL_VERTEX_ARRAY);
341 glEnableClientState(GL_NORMAL_ARRAY);
342 if (gPipeline.getLightingDetail() >= 2)
343 {
344 glEnableClientState(GL_COLOR_ARRAY);
345 }
346
347 if (pool->getVertexShaderLevel() > 0)
348 {
349 enable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
350
351 sEnvTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
352 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
353 if (sEnvTex >= 0 && cube_map)
354 {
355 cube_map->bind();
356 cube_map->setMatrix(1);
357 }
358
359 sBumpTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP);
360 sDiffTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
361 S32 scatterTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
362 LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
363 }
364 stop_glerror();
365}
366
367//static
368S32 LLDrawPoolBump::renderPass0(LLDrawPool* pool, face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
369{
370 if (!tex)
371 {
372 return 0;
373 }
374
375 if (face_list.empty())
376 {
377 return 0;
378 }
379
380 stop_glerror();
381
382 S32 res = 0;
383 if (pool->getVertexShaderLevel() > 0)
384 {
385 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
386 pool->bindGLBinormalPointer(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
387
388 LLViewerImage::bindTexture(tex, sDiffTex);
389
390 //single pass shader driven shiny/bump
391 LLGLDisable(GL_ALPHA_TEST);
392
393 LLViewerImage::sWhiteImagep->bind(sBumpTex);
394
395 GLfloat alpha[4] =
396 {
397 0.00f,
398 0.25f,
399 0.5f,
400 0.75f
401 };
402
403 LLImageGL* last_bump = NULL;
404
405 for (std::vector<LLFace*>::iterator iter = face_list.begin();
406 iter != face_list.end(); iter++)
407 {
408 LLFace *facep = *iter;
409 if (facep->mSkipRender)
410 {
411 continue;
412 }
413
414 const LLTextureEntry* te = facep->getTextureEntry();
415 if (te)
416 {
417 U8 index = te->getShiny();
418 LLColor4 col = te->getColor();
419
420 gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR,
421 col.mV[0], col.mV[1], col.mV[2], alpha[index]);
422 gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_SPECULAR_COLOR,
423 alpha[index], alpha[index], alpha[index], alpha[index]);
424
425 LLImageGL* bump = getBumpMap(te, tex);
426 if (bump != last_bump)
427 {
428 if (bump)
429 {
430 bump->bind(sBumpTex);
431 }
432 else
433 {
434 LLViewerImage::sWhiteImagep->bind(sBumpTex);
435 }
436 }
437 last_bump = bump;
438
439 // Draw the geometry
440 facep->enableLights();
441 res += facep->renderIndexed(index_array);
442 stop_glerror();
443 }
444 else
445 {
446 llwarns << "DrawPoolBump has face with invalid texture entry." << llendl;
447 }
448 }
449 }
450 else
451 {
452 LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
453 LLViewerImage::bindTexture(tex);
454 res = LLDrawPool::drawLoop(face_list, index_array);
455 }
456 return res;
457}
458
459//static
460void LLDrawPoolBump::endPass0(LLDrawPool* pool)
461{
462 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
463 glDisableClientState(GL_NORMAL_ARRAY);
464 glDisableClientState(GL_COLOR_ARRAY);
465
466 if (pool->getVertexShaderLevel() > 0)
467 {
468 gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
469 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
470 if (sEnvTex >= 0 && cube_map)
471 {
472 cube_map->restoreMatrix();
473 }
474
475 gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
476 gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP);
477 gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
478
479 disable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]);
480
481 glActiveTextureARB(GL_TEXTURE0_ARB);
482 glEnable(GL_TEXTURE_2D);
483 }
484}
485
486
487//static
488void LLDrawPoolBump::beginPass1()
489{
490 // Second pass: environment map
491 glEnableClientState(GL_VERTEX_ARRAY);
492 glEnableClientState(GL_NORMAL_ARRAY);
493
494 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
495 if( cube_map )
496 {
497 cube_map->enable(0);
498 cube_map->setMatrix(0);
499 cube_map->bind();
500 }
501}
502
503//static
504S32 LLDrawPoolBump::renderPass1(face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
505{
506 LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
507 if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0
508 {
509 return 0;
510 }
511
512 S32 res = 0;
513 if( gSky.mVOSkyp->getCubeMap() )
514 {
515 //LLGLSPipelineAlpha gls;
516 //LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL);
517 LLGLEnable blend_enable(GL_BLEND);
518
519 GLfloat alpha[4] =
520 {
521 0.00f,
522 0.25f,
523 0.5f,
524 0.75f
525 };
526
527 for (std::vector<LLFace*>::iterator iter = face_list.begin();
528 iter != face_list.end(); iter++)
529 {
530 LLFace *facep = *iter;
531 if (facep->mSkipRender)
532 {
533 continue;
534 }
535
536 const LLTextureEntry* te = facep->getTextureEntry();
537 if (te)
538 {
539 U8 index = te->getShiny();
540 if( index > 0 )
541 {
542 LLOverrideFaceColor override_color(facep->getPool(), 1, 1, 1, alpha[index]);
543
544 // Draw the geometry
545 facep->enableLights();
546 res += facep->renderIndexed(index_array);
547 stop_glerror();
548 }
549 }
550 else
551 {
552 llwarns << "DrawPoolBump has face with invalid texture entry." << llendl;
553 }
554 }
555 }
556 return res;
557}
558
559//static
560void LLDrawPoolBump::endPass1()
561{
562 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
563 if( cube_map )
564 {
565 cube_map->disable();
566 cube_map->restoreMatrix();
567 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
568 }
569
570 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
571
572 glDisableClientState(GL_NORMAL_ARRAY);
573}
574
575
576// static
577LLImageGL* LLDrawPoolBump::getBumpMap(const LLTextureEntry* te, LLViewerImage* tex)
578{
579 U32 bump_code = te->getBumpmap();
580 LLImageGL* bump = NULL;
581
582 switch( bump_code )
583 {
584 case BE_NO_BUMP:
585 bump = NULL;
586 break;
587 case BE_BRIGHTNESS:
588 case BE_DARKNESS:
589 if( tex )
590 {
591 bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
592 }
593 break;
594
595 default:
596 if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
597 {
598 bump = gStandardBumpmapList[bump_code].mImage;
599 }
600 break;
601 }
602
603 return bump;
604}
605
606//static
607void LLDrawPoolBump::beginPass2()
608{
609 LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
610 // Optional third pass: emboss bump map
611 stop_glerror();
612
613 // TEXTURE UNIT 0
614 // Output.rgb = texture at texture coord 0
615 glActiveTextureARB(GL_TEXTURE0_ARB);
616 glClientActiveTextureARB(GL_TEXTURE0_ARB);
617
618 glEnableClientState(GL_VERTEX_ARRAY);
619 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
620 glDisableClientState(GL_NORMAL_ARRAY);
621
622 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
623 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
624
625 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
626 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_ALPHA);
627
628 // Don't care about alpha output
629 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
630 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
631 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
632
633
634 // TEXTURE UNIT 1
635 glActiveTextureARB(GL_TEXTURE1_ARB);
636 glClientActiveTextureARB(GL_TEXTURE1_ARB);
637
638 glEnableClientState(GL_VERTEX_ARRAY);
639 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
640 glDisableClientState(GL_NORMAL_ARRAY);
641
642 glEnable(GL_TEXTURE_2D); // Texture unit 1
643
644 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
645 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
646
647 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
648 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
649
650 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
651 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
652
653 // Don't care about alpha output
654 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
655 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
656 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
657
658 // src = tex0 + (1 - tex1) - 0.5
659 // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
660 // = (1 + bump0 - bump1) / 2
661
662
663 // Blend: src * dst + dst * src
664 // = 2 * src * dst
665 // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst]
666 // = (1 + bump0 - bump1) * dst.rgb
667 // = dst.rgb + dst.rgb * (bump0 - bump1)
668 glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
669// glBlendFunc(GL_ONE, GL_ZERO); // temp
670
671 stop_glerror();
672}
673
674//static
675S32 LLDrawPoolBump::renderPass2(face_array_t& face_list, const U32* index_array, LLViewerImage* tex)
676{
677 if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0
678 {
679 return 0;
680 }
681
682 LLGLDisable fog(GL_FOG);
683 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL);
684 LLGLEnable tex2d(GL_TEXTURE_2D);
685 LLGLEnable blend(GL_BLEND);
686 S32 res = 0;
687
688 LLImageGL* last_bump = NULL;
689
690 for (std::vector<LLFace*>::iterator iter = face_list.begin();
691 iter != face_list.end(); iter++)
692 {
693 LLFace *facep = *iter;
694 if (facep->mSkipRender)
695 {
696 continue;
697 }
698 LLOverrideFaceColor override_color(facep->getPool(), 1,1,1,1);
699
700 const LLTextureEntry* te = facep->getTextureEntry();
701 LLImageGL* bump = getBumpMap(te, tex);
702
703 if( bump )
704 {
705 if( bump != last_bump )
706 {
707 last_bump = bump;
708
709 // Texture unit 0
710 bump->bind(0);
711 stop_glerror();
712
713 // Texture unit 1
714 bump->bind(1);
715 stop_glerror();
716 }
717
718 // Draw the geometry
719 res += facep->renderIndexed(index_array);
720 stop_glerror();
721 }
722 else
723 {
724// llwarns << "Skipping invalid bump code " << (S32) te->getBumpmap() << llendl;
725 }
726 }
727 return res;
728}
729
730//static
731void LLDrawPoolBump::endPass2()
732{
733 // Disable texture unit 1
734 glActiveTextureARB(GL_TEXTURE1_ARB);
735 glClientActiveTextureARB(GL_TEXTURE1_ARB);
736 glDisable(GL_TEXTURE_2D); // Texture unit 1
737 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
738 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
739
740 // Disable texture unit 0
741 glActiveTextureARB(GL_TEXTURE0_ARB);
742 glClientActiveTextureARB(GL_TEXTURE0_ARB);
743 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
744 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
745
746 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
747}
748
749
750void LLDrawPoolBump::renderForSelect()
751{
752 if (mDrawFace.empty() || !mMemory.count())
753 {
754 return;
755 }
756
757 glEnableClientState ( GL_VERTEX_ARRAY );
758
759 bindGLVertexPointer();
760
761 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
762 iter != mDrawFace.end(); iter++)
763 {
764 LLFace *facep = *iter;
765 if (facep->getDrawable() && !facep->getDrawable()->isDead() && (facep->getViewerObject()->mGLName))
766 {
767 facep->renderForSelect();
768 }
769 }
770}
771
772
773void LLDrawPoolBump::renderFaceSelected(LLFace *facep,
774 LLImageGL *image,
775 const LLColor4 &color,
776 const S32 index_offset, const S32 index_count)
777{
778 facep->renderSelected(image, color, index_offset, index_count);
779}
780
781
782void LLDrawPoolBump::dirtyTexture(const LLViewerImage *texturep)
783{
784 if (mTexturep == texturep)
785 {
786 for (std::vector<LLFace*>::iterator iter = mReferences.begin();
787 iter != mReferences.end(); iter++)
788 {
789 LLFace *facep = *iter;
790 gPipeline.markTextured(facep->getDrawable());
791 }
792 }
793}
794
795LLViewerImage *LLDrawPoolBump::getTexture()
796{
797 return mTexturep;
798}
799
800LLViewerImage *LLDrawPoolBump::getDebugTexture()
801{
802 return mTexturep;
803}
804
805LLColor3 LLDrawPoolBump::getDebugColor() const
806{
807 return LLColor3(1.f, 1.f, 0.f);
808}
809
810////////////////////////////////////////////////////////////////
811// List of one-component bump-maps created from other texures.
812
813
814//const LLUUID TEST_BUMP_ID("3d33eaf2-459c-6f97-fd76-5fce3fc29447");
815
816void LLBumpImageList::init()
817{
818 llassert( mBrightnessEntries.size() == 0 );
819 llassert( mDarknessEntries.size() == 0 );
820
821 LLStandardBumpmap::init();
822}
823
824void LLBumpImageList::shutdown()
825{
826 mBrightnessEntries.clear();
827 mDarknessEntries.clear();
828 LLStandardBumpmap::shutdown();
829}
830
831void LLBumpImageList::destroyGL()
832{
833 mBrightnessEntries.clear();
834 mDarknessEntries.clear();
835 LLStandardBumpmap::destroyGL();
836}
837
838void LLBumpImageList::restoreGL()
839{
840 // Images will be recreated as they are needed.
841 LLStandardBumpmap::restoreGL();
842}
843
844
845LLBumpImageList::~LLBumpImageList()
846{
847 // Shutdown should have already been called.
848 llassert( mBrightnessEntries.size() == 0 );
849 llassert( mDarknessEntries.size() == 0 );
850}
851
852
853// Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness)
854void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id,
855 F32 pixel_area, F32 texel_area_ratio, F32 cos_center_angle)
856{
857 bump &= TEM_BUMP_MASK;
858 LLViewerImage* bump_image = gStandardBumpmapList[bump].mImage;
859 if( bump_image )
860 {
861 bump_image->addTextureStats(pixel_area, texel_area_ratio, cos_center_angle);
862 }
863}
864
865
866void LLBumpImageList::updateImages()
867{
868 for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
869 {
870 bump_image_map_t::iterator curiter = iter++;
871 LLImageGL* image = curiter->second;
872 if( image )
873 {
874 BOOL destroy = TRUE;
875 if( image->getHasGLTexture())
876 {
877 if( image->getBoundRecently() )
878 {
879 destroy = FALSE;
880 }
881 else
882 {
883 image->destroyGLTexture();
884 }
885 }
886
887 if( destroy )
888 {
889 //llinfos << "*** Destroying bright " << (void*)image << llendl;
890 mBrightnessEntries.erase(curiter); // deletes the image thanks to reference counting
891 }
892 }
893 }
894
895 for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
896 {
897 bump_image_map_t::iterator curiter = iter++;
898 LLImageGL* image = curiter->second;
899 if( image )
900 {
901 BOOL destroy = TRUE;
902 if( image->getHasGLTexture())
903 {
904 if( image->getBoundRecently() )
905 {
906 destroy = FALSE;
907 }
908 else
909 {
910 image->destroyGLTexture();
911 }
912 }
913
914 if( destroy )
915 {
916 //llinfos << "*** Destroying dark " << (void*)image << llendl;;
917 mDarknessEntries.erase(curiter); // deletes the image thanks to reference counting
918 }
919 }
920 }
921
922}
923
924
925// Note: the caller SHOULD NOT keep the pointer that this function returns. It may be updated as more data arrives.
926LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code )
927{
928 llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
929
930 LLImageGL* bump = NULL;
931 const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
932 if( src_image->mMaxVirtualSize > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
933 {
934 bump_image_map_t* entries_list = NULL;
935 void (*callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
936
937 switch( bump_code )
938 {
939 case BE_BRIGHTNESS:
940 entries_list = &mBrightnessEntries;
941 callback_func = LLBumpImageList::onSourceBrightnessLoaded;
942 break;
943 case BE_DARKNESS:
944 entries_list = &mDarknessEntries;
945 callback_func = LLBumpImageList::onSourceDarknessLoaded;
946 break;
947 default:
948 llassert(0);
949 return NULL;
950 }
951
952 bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
953 if (iter != entries_list->end())
954 {
955 bump = iter->second;
956 }
957 else
958 {
959 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
960 raw->clear(0x77, 0x77, 0x77, 0xFF);
961 bump = new LLImageGL( raw, TRUE);
962 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
963 (*entries_list)[src_image->getID()] = bump;
964
965 // Note: this may create an LLImageGL immediately
966 src_image->setLoadedCallback( callback_func, 0, TRUE, new LLUUID(src_image->getID()) );
967 bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
968
969// bump_total++;
970// llinfos << "*** Creating " << (void*)bump << " " << bump_total << llendl;
971 }
972 }
973
974 return bump;
975}
976
977
978// static
979void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
980{
981 LLUUID* source_asset_id = (LLUUID*)userdata;
982 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
983 if( final )
984 {
985 delete source_asset_id;
986 }
987}
988
989// static
990void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
991{
992 LLUUID* source_asset_id = (LLUUID*)userdata;
993 LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
994 if( final )
995 {
996 delete source_asset_id;
997 }
998}
999
1000
1001// static
1002void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
1003{
1004 if( success )
1005 {
1006 bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
1007 bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
1008 if (iter != entries_list.end())
1009 {
1010 LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
1011 U8* dst_data = dst_image->getData();
1012 S32 dst_data_size = dst_image->getDataSize();
1013
1014 U8* src_data = src->getData();
1015 S32 src_data_size = src->getDataSize();
1016
1017 S32 src_components = src->getComponents();
1018
1019 // Convert to luminance and then scale and bias that to get ready for
1020 // embossed bump mapping. (0-255 maps to 127-255)
1021
1022 // Convert to fixed point so we don't have to worry about precision/clamping.
1023 const S32 FIXED_PT = 8;
1024 const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
1025 const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
1026 const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
1027
1028 S32 minimum = 255;
1029 S32 maximum = 0;
1030
1031 switch( src_components )
1032 {
1033 case 1:
1034 case 2:
1035 if( src_data_size == dst_data_size * src_components )
1036 {
1037 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
1038 {
1039 dst_data[i] = src_data[j];
1040 if( dst_data[i] < minimum )
1041 {
1042 minimum = dst_data[i];
1043 }
1044 if( dst_data[i] > maximum )
1045 {
1046 maximum = dst_data[i];
1047 }
1048 }
1049 }
1050 else
1051 {
1052 llassert(0);
1053 dst_image->clear();
1054 }
1055 break;
1056 case 3:
1057 case 4:
1058 if( src_data_size == dst_data_size * src_components )
1059 {
1060 for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
1061 {
1062 // RGB to luminance
1063 dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
1064 //llassert( dst_data[i] <= 255 );true because it's 8bit
1065 if( dst_data[i] < minimum )
1066 {
1067 minimum = dst_data[i];
1068 }
1069 if( dst_data[i] > maximum )
1070 {
1071 maximum = dst_data[i];
1072 }
1073 }
1074 }
1075 else
1076 {
1077 llassert(0);
1078 dst_image->clear();
1079 }
1080 break;
1081 default:
1082 llassert(0);
1083 dst_image->clear();
1084 break;
1085 }
1086
1087 if( maximum > minimum )
1088 {
1089 U8 bias_and_scale_lut[256];
1090 F32 twice_one_over_range = 2.f / (maximum - minimum);
1091 S32 i;
1092
1093 const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exagerates the effect in midrange. Disadvantage: clamps at the extremes.
1094 if( BE_DARKNESS == bump_code )
1095 {
1096 for( i = minimum; i <= maximum; i++ )
1097 {
1098 F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
1099 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
1100 }
1101 }
1102 else
1103 {
1104 // BE_LIGHTNESS
1105 for( i = minimum; i <= maximum; i++ )
1106 {
1107 F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
1108 bias_and_scale_lut[i] = llclampb(llround(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
1109 }
1110 }
1111
1112 for( i = 0; i < dst_data_size; i++ )
1113 {
1114 dst_data[i] = bias_and_scale_lut[dst_data[i]];
1115 }
1116 }
1117
1118 LLImageGL* bump = new LLImageGL( TRUE);
1119 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
1120 bump->createGLTexture(0, dst_image);
1121 iter->second = bump; // derefs (and deletes) old image
1122 }
1123 else
1124 {
1125 // entry should have been added in LLBumpImageList::getImage().
1126
1127 // Not a legit assertion - the bump texture could have been flushed by the bump image manager
1128 //llassert(0);
1129 }
1130 }
1131}
1132
1133S32 LLDrawPoolBump::getMaterialAttribIndex()
1134{
1135 return gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
1136}
1137
1138// virtual
1139void LLDrawPoolBump::enableShade()
1140{
1141 glDisableClientState(GL_COLOR_ARRAY);
1142}
1143
1144// virtual
1145void LLDrawPoolBump::disableShade()
1146{
1147 glEnableClientState(GL_COLOR_ARRAY);
1148}
1149
1150// virtual
1151void LLDrawPoolBump::setShade(F32 shade)
1152{
1153 glColor4f(0,0,0,shade);
1154}