PageRenderTime 114ms CodeModel.GetById 10ms app.highlight 96ms RepoModel.GetById 3ms app.codeStats 0ms

/indra/newview/lldrawpoolalpha.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 538 lines | 420 code | 77 blank | 41 comment | 77 complexity | 4280fa9aa473f7d3263e4a7ebeb3f68d MD5 | raw file
  1/** 
  2 * @file lldrawpoolalpha.cpp
  3 * @brief LLDrawPoolAlpha class implementation
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "lldrawpoolalpha.h"
 30
 31#include "llglheaders.h"
 32#include "llviewercontrol.h"
 33#include "llcriticaldamp.h"
 34#include "llfasttimer.h"
 35#include "llrender.h"
 36
 37#include "llcubemap.h"
 38#include "llsky.h"
 39#include "lldrawable.h"
 40#include "llface.h"
 41#include "llviewercamera.h"
 42#include "llviewertexturelist.h"	// For debugging
 43#include "llviewerobjectlist.h" // For debugging
 44#include "llviewerwindow.h"
 45#include "pipeline.h"
 46#include "llviewershadermgr.h"
 47#include "llviewerregion.h"
 48#include "lldrawpoolwater.h"
 49#include "llspatialpartition.h"
 50
 51BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
 52
 53static BOOL deferred_render = FALSE;
 54
 55LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
 56		LLRenderPass(type), current_shader(NULL), target_shader(NULL),
 57		simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL),
 58		mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF),
 59		mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF)
 60{
 61
 62}
 63
 64LLDrawPoolAlpha::~LLDrawPoolAlpha()
 65{
 66}
 67
 68
 69void LLDrawPoolAlpha::prerender()
 70{
 71	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 72}
 73
 74S32 LLDrawPoolAlpha::getNumDeferredPasses()
 75{
 76	return 1;
 77}
 78
 79void LLDrawPoolAlpha::beginDeferredPass(S32 pass)
 80{
 81	
 82}
 83
 84void LLDrawPoolAlpha::endDeferredPass(S32 pass)
 85{
 86	
 87}
 88
 89void LLDrawPoolAlpha::renderDeferred(S32 pass)
 90{
 91	LLFastTimer t(FTM_RENDER_GRASS);
 92	gDeferredDiffuseAlphaMaskProgram.bind();
 93	gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f);
 94
 95	//render alpha masked objects
 96	LLRenderPass::pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 97	gDeferredDiffuseAlphaMaskProgram.unbind();			
 98}
 99
100
101S32 LLDrawPoolAlpha::getNumPostDeferredPasses() 
102{ 
103	if (LLPipeline::sImpostorRender)
104	{ //skip depth buffer filling pass when rendering impostors
105		return 1;
106	}
107	else if (gSavedSettings.getBOOL("RenderDepthOfField"))
108	{
109		return 2; 
110	}
111	else
112	{
113		return 1;
114	}
115}
116
117void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) 
118{ 
119	LLFastTimer t(FTM_RENDER_ALPHA);
120
121	if (pass == 0)
122	{
123		simple_shader = &gDeferredAlphaProgram;
124		fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
125
126		//prime simple shader (loads shadow relevant uniforms)
127		gPipeline.bindDeferredShader(*simple_shader);
128	}
129	else
130	{
131		//update depth buffer sampler
132		gPipeline.mScreen.flush();
133		gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
134							0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
135		gPipeline.mDeferredDepth.bindTarget();
136		simple_shader = NULL;
137		fullbright_shader = NULL;
138		gObjectFullbrightAlphaMaskProgram.bind();
139		gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f);
140	}
141
142	deferred_render = TRUE;
143	if (mVertexShaderLevel > 0)
144	{
145		// Start out with no shaders.
146		current_shader = target_shader = NULL;
147	}
148	gPipeline.enableLightsDynamic();
149}
150
151void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) 
152{ 
153
154	if (pass == 1)
155	{
156		gPipeline.mDeferredDepth.flush();
157		gPipeline.mScreen.bindTarget();
158		gObjectFullbrightAlphaMaskProgram.unbind();
159	}
160
161	deferred_render = FALSE;
162	endRenderPass(pass);
163}
164
165void LLDrawPoolAlpha::renderPostDeferred(S32 pass) 
166{ 
167	render(pass); 
168}
169
170void LLDrawPoolAlpha::beginRenderPass(S32 pass)
171{
172	LLFastTimer t(FTM_RENDER_ALPHA);
173	
174	if (LLPipeline::sUnderWaterRender)
175	{
176		simple_shader = &gObjectSimpleWaterAlphaMaskProgram;
177		fullbright_shader = &gObjectFullbrightWaterAlphaMaskProgram;
178		emissive_shader = &gObjectEmissiveWaterProgram;
179	}
180	else
181	{
182		simple_shader = &gObjectSimpleAlphaMaskProgram;
183		fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
184		emissive_shader = &gObjectEmissiveProgram;
185	}
186
187	if (mVertexShaderLevel > 0)
188	{
189		// Start out with no shaders.
190		current_shader = target_shader = NULL;
191		LLGLSLShader::bindNoShader();
192	}
193	gPipeline.enableLightsDynamic();
194}
195
196void LLDrawPoolAlpha::endRenderPass( S32 pass )
197{
198	LLFastTimer t(FTM_RENDER_ALPHA);
199	LLRenderPass::endRenderPass(pass);
200
201	if(gPipeline.canUseWindLightShaders()) 
202	{
203		LLGLSLShader::bindNoShader();
204	}
205}
206
207void LLDrawPoolAlpha::render(S32 pass)
208{
209	LLFastTimer t(FTM_RENDER_ALPHA);
210
211	LLGLSPipelineAlpha gls_pipeline_alpha;
212
213	if (deferred_render && pass == 1)
214	{ //depth only
215		gGL.setColorMask(false, false);
216	}
217	else
218	{
219		gGL.setColorMask(true, true);
220	}
221
222	if (LLPipeline::sAutoMaskAlphaNonDeferred)
223	{
224		mColorSFactor = LLRender::BF_ONE;  // }
225		mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow
226		mAlphaSFactor = LLRender::BF_ZERO;
227		mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds
228		gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
229
230		if (mVertexShaderLevel > 0)
231		{
232			if (!LLPipeline::sRenderDeferred || !deferred_render)
233			{
234				simple_shader->bind();
235				simple_shader->setMinimumAlpha(0.33f);
236
237				pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
238			}
239			if (fullbright_shader)
240			{
241				fullbright_shader->bind();
242				fullbright_shader->setMinimumAlpha(0.33f);
243			}
244			pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
245			//LLGLSLShader::bindNoShader();
246		}
247		else
248		{
249			gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); //OK
250			gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
251			pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask());
252			gPipeline.enableLightsDynamic();
253			pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask());
254			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
255		}
256	}
257
258	LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy || 
259				(deferred_render && pass == 1) ? GL_TRUE : GL_FALSE);
260
261	if (deferred_render && pass == 1)
262	{
263		gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
264	}
265	else
266	{
267		mColorSFactor = LLRender::BF_SOURCE_ALPHA;           // } regular alpha blend
268		mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
269		mAlphaSFactor = LLRender::BF_ZERO;                         // } glow suppression
270		mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;       // }
271		gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
272
273		if (mVertexShaderLevel > 0)
274		{
275			if (LLPipeline::sImpostorRender)
276			{
277				fullbright_shader->bind();
278				fullbright_shader->setMinimumAlpha(0.5f);
279				simple_shader->bind();
280				simple_shader->setMinimumAlpha(0.5f);
281			}				
282			else
283			{
284				fullbright_shader->bind();
285				fullbright_shader->setMinimumAlpha(0.f);
286				simple_shader->bind();
287				simple_shader->setMinimumAlpha(0.f);
288			}
289		}
290		else
291		{
292			if (LLPipeline::sImpostorRender)
293			{
294				gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK
295			}
296			else
297			{
298				gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
299			}
300		}
301	}
302
303	if (mVertexShaderLevel > 0)
304	{
305		renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX);
306	}
307	else
308	{
309		renderAlpha(getVertexDataMask());
310	}
311
312	gGL.setColorMask(true, false);
313
314	if (deferred_render && pass == 1)
315	{
316		gGL.setSceneBlendType(LLRender::BT_ALPHA);
317	}
318
319	if (sShowDebugAlpha)
320	{
321		BOOL shaders = gPipeline.canUseVertexShaders();
322		if(shaders) 
323		{
324			gHighlightProgram.bind();
325		}
326		else
327		{
328			gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
329		}
330
331		gGL.diffuseColor4f(1,0,0,1);
332				
333		LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
334		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
335		renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
336							LLVertexBuffer::MAP_TEXCOORD0);
337
338		pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
339		pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
340
341		if(shaders) 
342		{
343			gHighlightProgram.unbind();
344		}
345	}
346}
347
348void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
349{
350	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
351	{
352		LLSpatialGroup* group = *i;
353		if (group->mSpatialPartition->mRenderByGroup &&
354			!group->isDead())
355		{
356			LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];	
357
358			for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)	
359			{
360				LLDrawInfo& params = **k;
361				
362				if (params.mParticle)
363				{
364					continue;
365				}
366
367				LLRenderPass::applyModelMatrix(params);
368				if (params.mGroup)
369				{
370					params.mGroup->rebuildMesh();
371				}
372				params.mVertexBuffer->setBuffer(mask);
373				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
374				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
375			}
376		}
377	}
378}
379
380void LLDrawPoolAlpha::renderAlpha(U32 mask)
381{
382	BOOL initialized_lighting = FALSE;
383	BOOL light_enabled = TRUE;
384	
385	BOOL use_shaders = gPipeline.canUseVertexShaders();
386		
387	for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
388	{
389		LLSpatialGroup* group = *i;
390		llassert(group);
391		llassert(group->mSpatialPartition);
392
393		if (group->mSpatialPartition->mRenderByGroup &&
394		    !group->isDead())
395		{
396			bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
397				// All particle systems seem to come off the wire with texture entries which claim that they glow.  This is probably a bug in the data.  Suppress.
398				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
399				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
400
401			LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
402
403			for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)	
404			{
405				LLDrawInfo& params = **k;
406
407				LLRenderPass::applyModelMatrix(params);
408
409				
410				if (params.mFullbright)
411				{
412					// Turn off lighting if it hasn't already been so.
413					if (light_enabled || !initialized_lighting)
414					{
415						initialized_lighting = TRUE;
416						if (use_shaders) 
417						{
418							target_shader = fullbright_shader;
419						}
420						else
421						{
422							gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
423						}
424						light_enabled = FALSE;
425					}
426				}
427				// Turn on lighting if it isn't already.
428				else if (!light_enabled || !initialized_lighting)
429				{
430					initialized_lighting = TRUE;
431					if (use_shaders) 
432					{
433						target_shader = simple_shader;
434					}
435					else
436					{
437						gPipeline.enableLightsDynamic();
438					}
439					light_enabled = TRUE;
440				}
441
442				// If we need shaders, and we're not ALREADY using the proper shader, then bind it
443				// (this way we won't rebind shaders unnecessarily).
444				if(use_shaders && (current_shader != target_shader))
445				{
446					llassert(target_shader != NULL);
447					current_shader = target_shader;
448					current_shader->bind();
449				}
450				else if (!use_shaders && current_shader != NULL)
451				{
452					LLGLSLShader::bindNoShader();
453					current_shader = NULL;
454				}
455
456				if (params.mGroup)
457				{
458					params.mGroup->rebuildMesh();
459				}
460
461				bool tex_setup = false;
462
463				if (use_shaders && params.mTextureList.size() > 1)
464				{
465					for (U32 i = 0; i < params.mTextureList.size(); ++i)
466					{
467						if (params.mTextureList[i].notNull())
468						{
469							gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
470						}
471					}
472				}
473				else
474				{ //not batching textures or batch has only 1 texture -- might need a texture matrix
475					if (params.mTexture.notNull())
476					{
477						params.mTexture->addTextureStats(params.mVSize);
478						gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
479						if (params.mTextureMatrix)
480						{
481							tex_setup = true;
482							gGL.getTexUnit(0)->activate();
483							gGL.matrixMode(LLRender::MM_TEXTURE);
484							gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
485							gPipeline.mTextureMatrixOps++;
486						}
487					}
488					else
489					{
490						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
491					}
492				}
493
494				params.mVertexBuffer->setBuffer(mask);
495				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
496				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
497				
498				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.
499				if (current_shader && 
500					draw_glow_for_this_partition &&
501					params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
502				{
503					// install glow-accumulating blend mode
504					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
505						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
506
507					emissive_shader->bind();
508					
509					// glow doesn't use vertex colors from the mesh data
510					params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
511					
512					// do the actual drawing, again
513					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
514					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
515
516					// restore our alpha blend mode
517					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
518
519					current_shader->bind();
520				}
521			
522				if (tex_setup)
523				{
524					gGL.getTexUnit(0)->activate();
525					gGL.loadIdentity();
526					gGL.matrixMode(LLRender::MM_MODELVIEW);
527				}
528			}
529		}
530	}
531
532	LLVertexBuffer::unbind();	
533		
534	if (!light_enabled)
535	{
536		gPipeline.enableLightsDynamic();
537	}
538}