aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lldrawpoolalpha.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/lldrawpoolalpha.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/lldrawpoolalpha.cpp603
1 files changed, 603 insertions, 0 deletions
diff --git a/linden/indra/newview/lldrawpoolalpha.cpp b/linden/indra/newview/lldrawpoolalpha.cpp
new file mode 100644
index 0000000..c62db17
--- /dev/null
+++ b/linden/indra/newview/lldrawpoolalpha.cpp
@@ -0,0 +1,603 @@
1/**
2 * @file lldrawpoolalpha.cpp
3 * @brief LLDrawPoolAlpha 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
30#include "lldrawpoolalpha.h"
31
32#include "llviewercontrol.h"
33#include "llcriticaldamp.h"
34#include "llfasttimer.h"
35
36#include "llagparray.h"
37#include "llcubemap.h"
38#include "llsky.h"
39#include "llagent.h"
40#include "lldrawable.h"
41#include "llface.h"
42#include "llviewercamera.h"
43#include "llviewerimagelist.h" // For debugging
44#include "llviewerobjectlist.h" // For debugging
45#include "llviewerwindow.h"
46#include "pipeline.h"
47
48const F32 MAX_DIST = 512.f;
49const F32 ALPHA_FALLOFF_START_DISTANCE = 0.8f;
50
51BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
52
53LLDrawPoolAlpha::LLDrawPoolAlpha() :
54 LLDrawPool(POOL_ALPHA,
55 DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK,
56 DATA_SIMPLE_NIL_MASK)
57{
58 mRebuiltLastFrame = FALSE;
59 mMinDistance = 0.f;
60 mMaxDistance = MAX_DIST;
61 mInvBinSize = NUM_ALPHA_BINS/(mMaxDistance - mMinDistance);
62 mCleanupUnused = TRUE;
63 //mRebuildFreq = -1 ; // Only rebuild if nearly full
64
65// for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
66// {
67// mDistanceBins[i].realloc(200);
68// }
69}
70
71LLDrawPoolAlpha::~LLDrawPoolAlpha()
72{
73}
74
75LLDrawPool *LLDrawPoolAlpha::instancePool()
76{
77 llerrs << "Should never be calling instancePool on an alpha pool!" << llendl;
78 return NULL;
79}
80
81void LLDrawPoolAlpha::enqueue(LLFace *facep)
82{
83 if (!facep->isState(LLFace::GLOBAL))
84 {
85 facep->mCenterAgent = facep->mCenterLocal * facep->getRenderMatrix();
86 }
87 facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis();
88
89 if (facep->isState(LLFace::BACKLIST))
90 {
91 mMoveFace.put(facep);
92 }
93 else
94 {
95 mDrawFace.put(facep);
96 }
97
98 {
99 S32 dist_bin = lltrunc( (mMaxDistance - (facep->mDistance+32))*mInvBinSize );
100
101 if (dist_bin >= NUM_ALPHA_BINS)
102 {
103 mDistanceBins[NUM_ALPHA_BINS-1].put(facep);
104 //mDistanceBins[NUM_ALPHA_BINS-1].push(facep, (U32)(void*)facep->getTexture());
105 }
106 else if (dist_bin > 0)
107 {
108 mDistanceBins[dist_bin].put(facep);
109 //mDistanceBins[dist_bin].push(facep, (U32)(void*)facep->getTexture());
110 }
111 else
112 {
113 mDistanceBins[0].put(facep);
114 //mDistanceBins[0].push(facep, (U32)(void*)facep->getTexture());
115 }
116 }
117}
118
119BOOL LLDrawPoolAlpha::removeFace(LLFace *facep)
120{
121 BOOL removed = FALSE;
122
123 LLDrawPool::removeFace(facep);
124
125 {
126 for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
127 {
128 if (mDistanceBins[i].removeObj(facep) != -1)
129 {
130 if (removed)
131 {
132 llerrs << "Warning! " << "Face in multiple distance bins on removal" << llendl;
133 }
134 removed = TRUE;
135 }
136 }
137 }
138 if (removed)
139 {
140 return TRUE;
141 }
142
143 return FALSE;
144}
145
146void LLDrawPoolAlpha::prerender()
147{
148 mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT);
149}
150
151void LLDrawPoolAlpha::beginRenderPass(S32 pass)
152{
153 if (mDrawFace.empty())
154 {
155 // No alpha objects, early exit.
156 return;
157 }
158
159 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
160 glEnableClientState(GL_VERTEX_ARRAY);
161 glEnableClientState(GL_NORMAL_ARRAY);
162 if (gPipeline.getLightingDetail() >= 2)
163 {
164 glEnableClientState(GL_COLOR_ARRAY);
165 }
166}
167
168
169void LLDrawPoolAlpha::render(S32 pass)
170{
171 LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
172
173 if (mDrawFace.empty())
174 {
175 // No alpha objects, early exit.
176 return;
177 }
178
179 GLfloat shiny[4] =
180 {
181 0.00f,
182 0.25f,
183 0.5f,
184 0.75f
185 };
186
187 GLint specularIndex = (mVertexShaderLevel > 0) ?
188 gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR] : 0;
189
190 S32 diffTex = 0;
191 S32 envTex = -1;
192
193 if (mVertexShaderLevel > 0) //alpha pass uses same shader as shiny/bump
194 {
195 envTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
196 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
197 if (envTex >= 0 && cube_map)
198 {
199 cube_map->bind();
200 cube_map->setMatrix(1);
201 }
202
203 if (specularIndex > 0)
204 {
205 glVertexAttrib4fARB(specularIndex, 0, 0, 0, 0);
206 }
207
208 S32 scatterTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
209 LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
210
211 diffTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
212 }
213
214 bindGLVertexPointer();
215 bindGLTexCoordPointer();
216 bindGLNormalPointer();
217 if (gPipeline.getLightingDetail() >= 2)
218 {
219 bindGLColorPointer();
220 }
221
222 S32 i, j;
223 glAlphaFunc(GL_GREATER,0.01f);
224 // This needs to be turned off or there will be lots of artifacting with the clouds - djs
225 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
226
227 LLGLSPipelineAlpha gls_pipeline_alpha;
228
229 LLDynamicArray<LLFace*>* distance_bins;
230 distance_bins = mDistanceBins;
231
232 S32 num_bins_no_alpha_test = ((gPickAlphaThreshold != 0.f) && gUsePickAlpha) ?
233 (NUM_ALPHA_BINS - llmax(2, (S32)(ALPHA_FALLOFF_START_DISTANCE * mInvBinSize))) :
234 NUM_ALPHA_BINS;
235
236 typedef std::vector<LLFace*> face_list_t;
237
238 for (i = 0; i < num_bins_no_alpha_test; i++)
239 {
240 S32 obj_count = distance_bins[i].count();
241
242 if (!obj_count)
243 {
244 continue;
245 }
246 else if (i > (NUM_ALPHA_BINS / 2) && obj_count < 100)
247 {
248 face_list_t pri_queue;
249 pri_queue.reserve(distance_bins[i].count());
250 for (j = 0; j < distance_bins[i].count(); j++)
251 {
252 pri_queue.push_back(distance_bins[i][j]);
253 }
254 std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
255
256 for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++)
257 {
258 const LLFace &face = *(*iter);
259 face.enableLights();
260 face.bindTexture(diffTex);
261 if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
262 {
263 U8 s = face.getTextureEntry()->getShiny();
264 glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
265 }
266 face.renderIndexed(getRawIndices());
267 mIndicesDrawn += face.getIndicesCount();
268 }
269 }
270 else
271 {
272 S32 count = distance_bins[i].count();
273 for (j = 0; j < count; j++)
274 {
275 const LLFace &face = *distance_bins[i][j];
276 face.enableLights();
277 face.bindTexture(diffTex);
278 if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
279 {
280 U8 s = face.getTextureEntry()->getShiny();
281 glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
282 }
283 face.renderIndexed(getRawIndices());
284 mIndicesDrawn += face.getIndicesCount();
285 }
286 }
287 }
288
289 GLfloat ogl_matrix[16];
290 gCamera->getOpenGLTransform(ogl_matrix);
291
292 for (i = num_bins_no_alpha_test; i < NUM_ALPHA_BINS; i++)
293 {
294 BOOL use_pri_queue = distance_bins[i].count() < 100;
295
296 face_list_t pri_queue;
297
298 if (use_pri_queue)
299 {
300 pri_queue.reserve(distance_bins[i].count());
301 for (j = 0; j < distance_bins[i].count(); j++)
302 {
303 pri_queue.push_back(distance_bins[i][j]);
304 }
305 std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
306 }
307
308 S32 count = distance_bins[i].count();
309 for (j = 0; j < count; j++)
310 {
311 const LLFace &face = use_pri_queue ? *pri_queue[j] : *distance_bins[i][j];
312 F32 fade_value = face.mAlphaFade * gPickAlphaThreshold;
313
314 face.enableLights();
315
316 if (fade_value < 1.f)
317 {
318 {
319 LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
320 glAlphaFunc(GL_LESS, fade_value);
321 glBlendFunc(GL_ZERO, GL_ONE);
322 LLViewerImage::bindTexture(gPipeline.mAlphaSizzleImagep, diffTex);
323 LLVector4 s_params(ogl_matrix[2], ogl_matrix[6], ogl_matrix[10], ogl_matrix[14]);
324 LLVector4 t_params(ogl_matrix[1], ogl_matrix[5], ogl_matrix[9], ogl_matrix[13]);
325
326 LLGLEnable gls_texgen_s(GL_TEXTURE_GEN_S);
327 LLGLEnable gls_texgen_t(GL_TEXTURE_GEN_T);
328 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
329 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
330 glTexGenfv(GL_S, GL_OBJECT_PLANE, s_params.mV);
331 glTexGenfv(GL_T, GL_OBJECT_PLANE, t_params.mV);
332 if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
333 {
334 U8 s = face.getTextureEntry()->getShiny();
335 glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
336 }
337 face.renderIndexed(getRawIndices());
338 }
339
340 {
341 // should get GL_GREATER to work, as it's faster
342 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LESS);
343 glAlphaFunc(GL_GEQUAL, fade_value);
344 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
345 face.bindTexture(diffTex);
346 if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0)
347 {
348 U8 s = face.getTextureEntry()->getShiny();
349 glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]);
350 }
351 face.renderIndexed(getRawIndices());
352 }
353 }
354
355 // render opaque portion of actual texture
356 glAlphaFunc(GL_GREATER, 0.98f);
357
358 face.bindTexture(diffTex);
359 face.renderIndexed(getRawIndices());
360
361 glAlphaFunc(GL_GREATER, 0.01f);
362
363 mIndicesDrawn += face.getIndicesCount();
364 }
365 }
366
367 if (mVertexShaderLevel > 0) //single pass shader driven shiny/bump
368 {
369 gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
370 LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap();
371 if (envTex >= 0 && cube_map)
372 {
373 cube_map->restoreMatrix();
374 }
375 gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
376 gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
377
378 glClientActiveTextureARB(GL_TEXTURE0_ARB);
379 glActiveTextureARB(GL_TEXTURE0_ARB);
380 glEnable(GL_TEXTURE_2D);
381 }
382
383 if (sShowDebugAlpha)
384 {
385 gPipeline.disableLights();
386 if ((mVertexShaderLevel > 0))
387 {
388 gPipeline.mHighlightProgram.bind();
389 }
390
391 LLViewerImage::sSmokeImagep->bind();
392 LLOverrideFaceColor override_color(this, 1.f, 0.f, 0.f, 1.f);
393 glColor4f(1.f, 0.f, 0.f, 1.f); // in case vertex shaders are enabled
394 glDisableClientState(GL_COLOR_ARRAY);
395
396 for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
397 {
398 if (distance_bins[i].count() < 100)
399 {
400 face_list_t pri_queue;
401 pri_queue.reserve(distance_bins[i].count());
402 for (j = 0; j < distance_bins[i].count(); j++)
403 {
404 pri_queue.push_back(distance_bins[i][j]);
405 }
406 std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater());
407
408 for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++)
409 {
410 const LLFace &face = *(*iter);
411 face.renderIndexed(getRawIndices());
412 mIndicesDrawn += face.getIndicesCount();
413 }
414 }
415 else
416 {
417 for (j = 0; j < distance_bins[i].count(); j++)
418 {
419 const LLFace &face = *distance_bins[i][j];
420 face.renderIndexed(getRawIndices());
421 mIndicesDrawn += face.getIndicesCount();
422 }
423 }
424 }
425
426 if ((mVertexShaderLevel > 0))
427 {
428 gPipeline.mHighlightProgram.unbind();
429 }
430
431 }
432
433}
434
435void LLDrawPoolAlpha::renderForSelect()
436{
437 if (mDrawFace.empty() || !mMemory.count())
438 {
439 return;
440 }
441
442 // force faces on focus object to proper alpha cutoff based on object bbox distance
443 if (gAgent.getFocusObject())
444 {
445 LLDrawable* drawablep = gAgent.getFocusObject()->mDrawable;
446
447 if (drawablep)
448 {
449 const S32 num_faces = drawablep->getNumFaces();
450
451 for (S32 f = 0; f < num_faces; f++)
452 {
453 LLFace* facep = drawablep->getFace(f);
454 facep->mDistance = gAgent.getFocusObjectDist();
455 }
456 }
457 }
458
459 glEnableClientState (GL_VERTEX_ARRAY);
460 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
461
462 LLGLSObjectSelectAlpha gls_alpha;
463
464 glBlendFunc(GL_ONE, GL_ZERO);
465 glAlphaFunc(gPickTransparent ? GL_GEQUAL : GL_GREATER, 0.f);
466
467 bindGLVertexPointer();
468 bindGLTexCoordPointer();
469
470 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
471 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
472 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
473
474 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
475 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
476
477 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
478 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
479
480 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
481 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
482
483 LLDynamicArray<LLFace*>* distance_bins;
484 distance_bins = mDistanceBins;
485
486 S32 j;
487 S32 num_bins_no_alpha_test = (gPickAlphaThreshold != 0.f) ?
488 (NUM_ALPHA_BINS - llmax(2, (S32)(ALPHA_FALLOFF_START_DISTANCE * mInvBinSize))) :
489 NUM_ALPHA_BINS;
490
491 S32 i;
492 for (i = 0; i < num_bins_no_alpha_test; i++)
493 {
494 S32 distance_bin_size = distance_bins[i].count();
495 for (j = 0; j < distance_bin_size; j++)
496 {
497 const LLFace &face = *distance_bins[i][j];
498 if (face.getDrawable() && !face.getDrawable()->isDead() && (face.getViewerObject()->mGLName))
499 {
500 face.bindTexture();
501 face.renderForSelect();
502 }
503 }
504 }
505
506 for (i = num_bins_no_alpha_test; i < NUM_ALPHA_BINS; i++)
507 {
508 S32 distance_bin_size = distance_bins[i].count();
509 if (distance_bin_size)
510 {
511 for (j = 0; j < distance_bin_size; j++)
512 {
513 const LLFace &face = *distance_bins[i][j];
514
515 glAlphaFunc(GL_GEQUAL, face.mAlphaFade * gPickAlphaTargetThreshold);
516
517 if (face.getDrawable() && !face.getDrawable()->isDead() && (face.getViewerObject()->mGLName))
518 {
519 face.bindTexture();
520 face.renderForSelect();
521 }
522 }
523 }
524 }
525
526 glAlphaFunc(GL_GREATER, 0.01f);
527 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
528 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
529 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
530}
531
532
533void LLDrawPoolAlpha::renderFaceSelected(LLFace *facep,
534 LLImageGL *image,
535 const LLColor4 &color,
536 const S32 index_offset, const S32 index_count)
537{
538 facep->renderSelected(image, color, index_offset, index_count);
539}
540
541
542void LLDrawPoolAlpha::resetDrawOrders()
543{
544 LLDrawPool::resetDrawOrders();
545
546 for (S32 i = 0; i < NUM_ALPHA_BINS; i++)
547 {
548 mDistanceBins[i].resize(0);
549 }
550}
551
552BOOL LLDrawPoolAlpha::verify() const
553{
554 S32 i, j;
555 BOOL ok;
556 ok = LLDrawPool::verify();
557 for (i = 0; i < NUM_ALPHA_BINS; i++)
558 {
559 for (j = 0; j < mDistanceBins[i].count(); j++)
560 {
561 const LLFace &face = *mDistanceBins[i][j];
562 if (!face.verify())
563 {
564 ok = FALSE;
565 }
566 }
567 }
568 return ok;
569}
570
571LLViewerImage *LLDrawPoolAlpha::getDebugTexture()
572{
573 return LLViewerImage::sSmokeImagep;
574}
575
576
577LLColor3 LLDrawPoolAlpha::getDebugColor() const
578{
579 return LLColor3(1.f, 0.f, 0.f);
580}
581
582S32 LLDrawPoolAlpha::getMaterialAttribIndex()
583{
584 return gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
585}
586
587// virtual
588void LLDrawPoolAlpha::enableShade()
589{
590 glDisableClientState(GL_COLOR_ARRAY);
591}
592
593// virtual
594void LLDrawPoolAlpha::disableShade()
595{
596 glEnableClientState(GL_COLOR_ARRAY);
597}
598
599// virtual
600void LLDrawPoolAlpha::setShade(F32 shade)
601{
602 glColor4f(0,0,0,shade);
603}