diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldrawpoolbump.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 1154 |
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 | ||
57 | LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; | ||
58 | |||
59 | // static | ||
60 | U32 LLStandardBumpmap::sStandardBumpmapCount = 0; | ||
61 | |||
62 | // static | ||
63 | LLBumpImageList gBumpImageList; | ||
64 | |||
65 | const S32 STD_BUMP_LATEST_FILE_VERSION = 1; | ||
66 | |||
67 | S32 LLDrawPoolBump::sBumpTex = -1; | ||
68 | S32 LLDrawPoolBump::sDiffTex = -1; | ||
69 | S32 LLDrawPoolBump::sEnvTex = -1; | ||
70 | |||
71 | // static | ||
72 | void LLStandardBumpmap::init() | ||
73 | { | ||
74 | LLStandardBumpmap::restoreGL(); | ||
75 | } | ||
76 | |||
77 | // static | ||
78 | void LLStandardBumpmap::shutdown() | ||
79 | { | ||
80 | LLStandardBumpmap::destroyGL(); | ||
81 | } | ||
82 | |||
83 | // static | ||
84 | void 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 | ||
139 | void 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 | |||
153 | LLDrawPoolBump::LLDrawPoolBump(LLViewerImage *texturep) : | ||
154 | LLDrawPool(POOL_BUMP, DATA_BUMP_IL_MASK | DATA_COLORS_MASK, DATA_SIMPLE_NIL_MASK), | ||
155 | mTexturep(texturep) | ||
156 | { | ||
157 | } | ||
158 | |||
159 | LLDrawPool *LLDrawPoolBump::instancePool() | ||
160 | { | ||
161 | return new LLDrawPoolBump(mTexturep); | ||
162 | } | ||
163 | |||
164 | |||
165 | void LLDrawPoolBump::prerender() | ||
166 | { | ||
167 | mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT); | ||
168 | } | ||
169 | |||
170 | BOOL 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 | ||
203 | S32 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 | |||
218 | S32 LLDrawPoolBump::getNumPasses() | ||
219 | { | ||
220 | return numBumpPasses(); | ||
221 | } | ||
222 | |||
223 | void 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 | |||
242 | void 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 | |||
316 | void 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 | ||
336 | void 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 | ||
368 | S32 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 | ||
460 | void 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 | ||
488 | void 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 | ||
504 | S32 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 | ||
560 | void 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 | ||
577 | LLImageGL* 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 | ||
607 | void 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 | ||
675 | S32 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 | ||
731 | void 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 | |||
750 | void 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 | |||
773 | void 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 | |||
782 | void 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 | |||
795 | LLViewerImage *LLDrawPoolBump::getTexture() | ||
796 | { | ||
797 | return mTexturep; | ||
798 | } | ||
799 | |||
800 | LLViewerImage *LLDrawPoolBump::getDebugTexture() | ||
801 | { | ||
802 | return mTexturep; | ||
803 | } | ||
804 | |||
805 | LLColor3 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 | |||
816 | void LLBumpImageList::init() | ||
817 | { | ||
818 | llassert( mBrightnessEntries.size() == 0 ); | ||
819 | llassert( mDarknessEntries.size() == 0 ); | ||
820 | |||
821 | LLStandardBumpmap::init(); | ||
822 | } | ||
823 | |||
824 | void LLBumpImageList::shutdown() | ||
825 | { | ||
826 | mBrightnessEntries.clear(); | ||
827 | mDarknessEntries.clear(); | ||
828 | LLStandardBumpmap::shutdown(); | ||
829 | } | ||
830 | |||
831 | void LLBumpImageList::destroyGL() | ||
832 | { | ||
833 | mBrightnessEntries.clear(); | ||
834 | mDarknessEntries.clear(); | ||
835 | LLStandardBumpmap::destroyGL(); | ||
836 | } | ||
837 | |||
838 | void LLBumpImageList::restoreGL() | ||
839 | { | ||
840 | // Images will be recreated as they are needed. | ||
841 | LLStandardBumpmap::restoreGL(); | ||
842 | } | ||
843 | |||
844 | |||
845 | LLBumpImageList::~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) | ||
854 | void 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 | |||
866 | void 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. | ||
926 | LLImageGL* 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 | ||
979 | void 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 | ||
990 | void 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 | ||
1002 | void 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 | |||
1133 | S32 LLDrawPoolBump::getMaterialAttribIndex() | ||
1134 | { | ||
1135 | return gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; | ||
1136 | } | ||
1137 | |||
1138 | // virtual | ||
1139 | void LLDrawPoolBump::enableShade() | ||
1140 | { | ||
1141 | glDisableClientState(GL_COLOR_ARRAY); | ||
1142 | } | ||
1143 | |||
1144 | // virtual | ||
1145 | void LLDrawPoolBump::disableShade() | ||
1146 | { | ||
1147 | glEnableClientState(GL_COLOR_ARRAY); | ||
1148 | } | ||
1149 | |||
1150 | // virtual | ||
1151 | void LLDrawPoolBump::setShade(F32 shade) | ||
1152 | { | ||
1153 | glColor4f(0,0,0,shade); | ||
1154 | } | ||