void LLDrawPoolTerrain::renderFullShader()
{
	// Hack! Get the region that this draw pool is rendering from!
	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
	LLVLComposition *compp = regionp->getComposition();
	LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
	LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
	LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
	LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];

	LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
	F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
	F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale;

	LLVector4 tp0, tp1;
	
	tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x);
	tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y);

	//
	// detail texture 0
	//
	S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0);
	gGL.getTexUnit(detail0)->bind(detail_texture0p);
	gGL.getTexUnit(0)->activate();

	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
	llassert(shader);
		
	shader->uniform4fv("object_plane_s", 1, tp0.mV);
	shader->uniform4fv("object_plane_t", 1, tp1.mV);

	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);

	//
	// detail texture 1
	//
	S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); 
	gGL.getTexUnit(detail1)->bind(detail_texture1p);
	
	/// ALPHA TEXTURE COORDS 0:
	gGL.getTexUnit(1)->activate();
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
	
	// detail texture 2
	//
	S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2);
	gGL.getTexUnit(detail2)->bind(detail_texture2p);

	gGL.getTexUnit(2)->activate();
	
	/// ALPHA TEXTURE COORDS 1:
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.translatef(-2.f, 0.f, 0.f);
	gGL.matrixMode(LLRender::MM_MODELVIEW);

	//
	// detail texture 3
	//
	S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);
	gGL.getTexUnit(detail3)->bind(detail_texture3p);
	
	/// ALPHA TEXTURE COORDS 2:
	gGL.getTexUnit(3)->activate();
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.translatef(-1.f, 0.f, 0.f);
	gGL.matrixMode(LLRender::MM_MODELVIEW);

	//
	// Alpha Ramp 
	//
	S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
	gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep);
		
	// GL_BLEND disabled by default
	drawLoop();

	// Disable multitexture
	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0);
	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1);
	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2);
	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);

	gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(4)->disable();
	gGL.getTexUnit(4)->activate();
	
	gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(3)->disable();
	gGL.getTexUnit(3)->activate();
	
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);

	gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(2)->disable();
	gGL.getTexUnit(2)->activate();
	
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);

	gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(1)->disable();
	gGL.getTexUnit(1)->activate();
	
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
	
	//----------------------------------------------------------------------------
	// Restore Texture Unit 0 defaults
	
	gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(0)->activate();
	gGL.matrixMode(LLRender::MM_TEXTURE);
	gGL.loadIdentity();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
}
示例#2
0
void LLDrawPoolWater::shade()
{
	if (!deferred_render)
	{
		gGL.setColorMask(true, true);
	}

	LLVOSky *voskyp = gSky.mVOSkyp;

	if(voskyp == NULL) 
	{
		return;
	}

	LLGLDisable blend(GL_BLEND);

	LLColor3 light_diffuse(0,0,0);
	F32 light_exp = 0.0f;
	LLVector3 light_dir;
	LLColor3 light_color;

	if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) 	 
    { 	 
        light_dir  = gSky.getSunDirection(); 	 
        light_dir.normVec(); 	
		light_color = gSky.getSunDiffuseColor();
		if(gSky.mVOSkyp) {
	        light_diffuse = gSky.mVOSkyp->getSun().getColorCached(); 	 
			light_diffuse.normVec(); 	 
		}
        light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); 	 
        light_diffuse *= light_exp + 0.25f; 	 
    } 	 
    else  	 
    { 	 
        light_dir       = gSky.getMoonDirection(); 	 
        light_dir.normVec(); 	 
		light_color = gSky.getMoonDiffuseColor();
        light_diffuse   = gSky.mVOSkyp->getMoon().getColorCached(); 	 
        light_diffuse.normVec(); 	 
        light_diffuse *= 0.5f; 	 
        light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); 	 
    }

	light_exp *= light_exp;
	light_exp *= light_exp;
	light_exp *= light_exp;
	light_exp *= light_exp;
	light_exp *= 256.f;
	light_exp = light_exp > 32.f ? light_exp : 32.f;

	LLGLSLShader* shader;

	F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight();
	
	if (deferred_render)
	{
		shader = &gDeferredWaterProgram;
	}
	else if (eyedepth < 0.f && LLPipeline::sWaterReflections)
	{
		shader = &gUnderWaterProgram;
	}
	else
	{
		shader = &gWaterProgram;
	}

	if (deferred_render)
	{
		gPipeline.bindDeferredShader(*shader);
	}
	else
	{
		shader->bind();
	}

	sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
	
	S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);
		
	if (reftex > -1)
	{
		gGL.getTexUnit(reftex)->activate();
		gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef);
		gGL.getTexUnit(0)->activate();
	}	

	//bind normal map
	S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);

	LLWaterParamManager * param_mgr = LLWaterParamManager::instance();

	// change mWaterNormp if needed
	if (mWaterNormp->getID() != param_mgr->getNormalMapID())
	{
		mWaterNormp = LLViewerTextureManager::getFetchedTexture(param_mgr->getNormalMapID());
	}

	mWaterNormp->addTextureStats(1024.f*1024.f);
	gGL.getTexUnit(bumpTex)->bind(mWaterNormp) ;
	if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
	{
		mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
	}
	else 
	{
		mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT);
	}
	
	S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX);	
		
	if (screentex > -1)
	{
		shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
		shader->uniform1f(LLViewerShaderMgr::WATER_FOGDENSITY, 
			param_mgr->getFogDensity());
		gPipeline.mWaterDis.bindTexture(0, screentex);
	}
	
	stop_glerror();
	
	gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);	

	if (mVertexShaderLevel == 1)
	{
		sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue;
		shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
	}

	F32 screenRes[] = 
	{
		1.f/gGLViewport[2],
		1.f/gGLViewport[3]
	};
	shader->uniform2fv("screenRes", 1, screenRes);
	stop_glerror();
	
	S32 diffTex = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
	stop_glerror();
	
	light_dir.normVec();
	sLightDir = light_dir;
	
	light_diffuse *= 6.f;

	//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
	shader->uniform1f(LLViewerShaderMgr::WATER_WATERHEIGHT, eyedepth);
	shader->uniform1f(LLViewerShaderMgr::WATER_TIME, sTime);
	shader->uniform3fv(LLViewerShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
	shader->uniform3fv(LLViewerShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
	shader->uniform1f(LLViewerShaderMgr::WATER_SPECULAR_EXP, light_exp);
	shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV);
	shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV);
	shader->uniform3fv(LLViewerShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);

	shader->uniform3fv("normScale", 1, param_mgr->getNormalScale().mV);
	shader->uniform1f("fresnelScale", param_mgr->getFresnelScale());
	shader->uniform1f("fresnelOffset", param_mgr->getFresnelOffset());
	shader->uniform1f("blurMultiplier", param_mgr->getBlurMultiplier());

	F32 sunAngle = llmax(0.f, light_dir.mV[2]);
	F32 scaledAngle = 1.f - sunAngle;

	shader->uniform1f("sunAngle", sunAngle);
	shader->uniform1f("scaledAngle", scaledAngle);
	shader->uniform1f("sunAngle2", 0.1f + 0.2f*sunAngle);

	LLColor4 water_color;
	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
	F32 up_dot = camera_up * LLVector3::z_axis;
	if (LLViewerCamera::getInstance()->cameraUnderWater())
	{
		water_color.setVec(1.f, 1.f, 1.f, 0.4f);
		shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());
	}
	else
	{
		water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
		shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());
	}

	if (water_color.mV[3] > 0.9f)
	{
		water_color.mV[3] = 0.9f;
	}

	glColor4fv(water_color.mV);

	{
		LLGLDisable cullface(GL_CULL_FACE);
		for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
			iter != mDrawFace.end(); iter++)
		{
			LLFace *face = *iter;

			if (voskyp->isReflFace(face))
			{
				continue;
			}

			LLVOWater* water = (LLVOWater*) face->getViewerObject();
			gGL.getTexUnit(diffTex)->bind(face->getTexture());

			sNeedsReflectionUpdate = TRUE;
			
			if (water->getUseTexture())
			{
				sNeedsDistortionUpdate = TRUE;
				face->renderIndexed();
			}
			else
			{ //smash background faces to far clip plane
				if (water->getIsEdgePatch())
				{
					if (deferred_render)
					{
						face->renderIndexed();
					}
					else
					{
						LLGLClampToFarClip far_clip(glh_get_current_projection());
						face->renderIndexed();
					}
				}
				else
				{
					sNeedsDistortionUpdate = TRUE;
					face->renderIndexed();
				}
			}
		}
	}
	
	shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
	shader->disableTexture(LLViewerShaderMgr::WATER_SCREENTEX);	
	shader->disableTexture(LLViewerShaderMgr::BUMP_MAP);
	shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
	shader->disableTexture(LLViewerShaderMgr::WATER_REFTEX);
	shader->disableTexture(LLViewerShaderMgr::WATER_SCREENDEPTH);

	if (deferred_render)
	{
		gPipeline.unbindDeferredShader(*shader);
	}
	else
	{
		shader->unbind();
	}

	gGL.getTexUnit(0)->activate();
	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
	if (!deferred_render)
	{
		gGL.setColorMask(true, false);
	}

}
// for low end hardware
void LLDrawPoolWater::renderOpaqueLegacyWater()
{
	LLVOSky *voskyp = gSky.mVOSkyp;

	LLGLSLShader* shader = NULL;
	if (LLGLSLShader::sNoFixedFunction)
	{
		if (LLPipeline::sUnderWaterRender)
		{
			shader = &gObjectSimpleNonIndexedTexGenWaterProgram;
		}
		else
		{
			shader = &gObjectSimpleNonIndexedTexGenProgram;
		}

		shader->bind();
	}

	stop_glerror();

	// Depth sorting and write to depth buffer
	// since this is opaque, we should see nothing
	// behind the water.  No blending because
	// of no transparency.  And no face culling so
	// that the underside of the water is also opaque.
	LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
	LLGLDisable no_cull(GL_CULL_FACE);
	LLGLDisable no_blend(GL_BLEND);

	gPipeline.disableLights();

	//Singu note: This is a hack around bizarre opensim behavior. The opaque water texture we get is pure white and only has one channel.
	// This behavior is clearly incorrect, so we try to detect that case, purge it from the cache, and try to re-fetch the texture.
	// If the re-fetched texture is still invalid, or doesn't exist, we use transparent water, which is fine since alphablend is unset.
	// The current logic for refetching is crude here, and probably wont work if, say, a prim were to also have the texture for some reason,
	// however it works well enough otherwise, and is much cleaner than diving into LLTextureList, LLViewerFetchedTexture, and LLViewerTexture.
	// Perhaps a proper reload mechanism could be done if we ever add user-level texture reloading, but until then it's not a huge priority.
	// Failing to fully refetch will just give us the same invalid texture we started with, which will result in the fallback texture being used.
	if(mOpaqueWaterImagep != mWaterImagep)
	{
		if(mOpaqueWaterImagep->isMissingAsset())
		{
			mOpaqueWaterImagep = mWaterImagep;
		}
		else if(mOpaqueWaterImagep->hasGLTexture() && mOpaqueWaterImagep->getComponents() < 3)
		{
			LLAppViewer::getTextureCache()->removeFromCache(mOpaqueWaterImagep->getID());
			static bool sRefetch = true;
			if(sRefetch)
			{
				sRefetch = false;
				((LLViewerFetchedTexture*)mOpaqueWaterImagep.get())->forceRefetch();
			}
			else
				mOpaqueWaterImagep = mWaterImagep;
		}
	}
	mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);

	// Activate the texture binding and bind one
	// texture since all images will have the same texture
	gGL.getTexUnit(0)->activate();
	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(0)->bind(mOpaqueWaterImagep);

	// Automatically generate texture coords for water texture
	if (!shader)
	{
		glEnable(GL_TEXTURE_GEN_S); //texture unit 0
		glEnable(GL_TEXTURE_GEN_T); //texture unit 0
		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
	}

	// Use the fact that we know all water faces are the same size
	// to save some computation

	// Slowly move texture coordinates over time so the water appears
	// to be moving.
	F32 movement_period_secs = 50.f;

	static const LLCachedControl<bool> freeze_time("FreezeTime",false);
	static F32 frame_time;
	if (!freeze_time) frame_time = gFrameTimeSeconds;
	F32 offset = fmod(frame_time, movement_period_secs);

	if (movement_period_secs != 0)
	{
		offset /= movement_period_secs;
	}
	else
	{
		offset = 0;
	}

	F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset };
	F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset };

	if (!shader)
	{
		glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
		glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
	}
	else
	{
		shader->uniform4fv("object_plane_s", 1, tp0);
		shader->uniform4fv("object_plane_t", 1, tp1);
	}

	gGL.diffuseColor3f(1.f, 1.f, 1.f);

	for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
		 iter != mDrawFace.end(); iter++)
	{
		LLFace *face = *iter;
		if (voskyp->isReflFace(face))
		{
			continue;
		}

		face->renderIndexed();
	}

	stop_glerror();

	if (!shader)
	{
		// Reset the settings back to expected values
		glDisable(GL_TEXTURE_GEN_S); //texture unit 0
		glDisable(GL_TEXTURE_GEN_T); //texture unit 0
	}

	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}