void LLPostProcess::applyColorFilterShader(void) { if(gPostColorFilterProgram.mProgramObject == 0) return; gPostColorFilterProgram.bind(); gGL.getTexUnit(0)->bind(mSceneRenderTexture); gPostColorFilterProgram.uniform1f("gamma", tweaks.getGamma()); gPostColorFilterProgram.uniform1f("brightness", tweaks.getBrightness()); gPostColorFilterProgram.uniform1f("contrast", tweaks.getContrast()); float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f; baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI); float baseR = tweaks.getContrastBaseR() * baseI; float baseG = tweaks.getContrastBaseG() * baseI; float baseB = tweaks.getContrastBaseB() * baseI; gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); gPostColorFilterProgram.uniform1f("saturation", tweaks.getSaturation()); gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV); /// Draw a screen space quad drawOrthoQuad(QUAD_NORMAL); gPostColorFilterProgram.unbind(); }
QuadType bind() { if(!isEnabled()) return QUAD_NONE; /// CALCULATING LUMINANCE (Using NTSC lum weights) /// http://en.wikipedia.org/wiki/Luma_%28video%29 static const float LUMINANCE_R = 0.299f; static const float LUMINANCE_G = 0.587f; static const float LUMINANCE_B = 0.114f; gPostColorFilterProgram.bind(); gPostColorFilterProgram.uniform1f("gamma", mGamma); gPostColorFilterProgram.uniform1f("brightness", mBrightness); gPostColorFilterProgram.uniform1f("contrast", mContrast); float baseI = (mContrastBase.mValue[VX] + mContrastBase.mValue[VY] + mContrastBase.mValue[VZ]) / 3.0f; baseI = mContrastBase.mValue[VW] / ((baseI < 0.001f) ? 0.001f : baseI); float baseR = mContrastBase.mValue[VX] * baseI; float baseG = mContrastBase.mValue[VY] * baseI; float baseB = mContrastBase.mValue[VZ] * baseI; gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); gPostColorFilterProgram.uniform1f("saturation", mSaturation); gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV); return QUAD_NORMAL; }
void LLDrawPoolGlow::render(S32 pass) { LLFastTimer t(FTM_RENDER_GLOW); LLGLEnable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.flush(); /// Get rid of z-fighting with non-glow pass. LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); //should never get here without basic shaders enabled llassert(shader_level > 0); LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; shader->bind(); LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); gGL.setColorMask(true, false); gGL.setSceneBlendType(LLRender::BT_ALPHA); if (shader_level > 0 && fullbright_shader) { shader->unbind(); } }
QuadType bind() { if(!isEnabled()) return QUAD_NONE; gPostPosterizeProgram.bind(); gPostPosterizeProgram.uniform1i("layerCount", mNumLayers); return QUAD_NORMAL; }
QuadType bind() { if(!isEnabled()) return QUAD_NONE; gPostGaussianBlurProgram.bind(); mPassLoc = gPostGaussianBlurProgram.getUniformLocation("horizontalPass"); return QUAD_NORMAL; }
QuadType bind() { if(!isEnabled()) return QUAD_NONE; gPostNightVisionProgram.bind(); LLPostProcess::getInstance()->bindNoise(1); gPostNightVisionProgram.uniform1f("brightMult", mBrightnessMult); gPostNightVisionProgram.uniform1f("noiseStrength", mNoiseStrength); return QUAD_NOISE; }
void LLPostProcess::applyNightVisionShader(void) { if(gPostNightVisionProgram.mProgramObject == 0) return; gPostNightVisionProgram.bind(); gGL.getTexUnit(0)->bind(mSceneRenderTexture); gGL.getTexUnit(1)->bind(mNoiseTexture); gPostNightVisionProgram.uniform1f("brightMult", tweaks.getBrightMult()); gPostNightVisionProgram.uniform1f("noiseStrength", tweaks.getNoiseStrength()); mNoiseTextureScale = 0.001f + ((100.f - tweaks.getNoiseSize()) / 100.f); mNoiseTextureScale *= (mScreenHeight / NOISE_SIZE); /// Draw a screen space quad drawOrthoQuad(QUAD_NOISE); gPostNightVisionProgram.unbind(); }
void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const { if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectSimpleWaterProgram : &gWLSkyProgram; LLGLDisable blend(GL_BLEND); shader->bind(); /// Render the skydome renderDome(camHeightLocal, shader); shader->unbind(); } }
QuadType bind() { if(!isEnabled()) { return QUAD_NONE; } glh::matrix4f inv_proj(gGLModelView); inv_proj.mult_left(gGLProjection); inv_proj = inv_proj.inverse(); glh::matrix4f prev_proj(gGLPreviousModelView); prev_proj.mult_left(gGLProjection); LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions(); gPostMotionBlurProgram.bind(); gPostMotionBlurProgram.uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m); gPostMotionBlurProgram.uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m); gPostMotionBlurProgram.uniform2fv("screen_res", 1, screen_rect.mV); gPostMotionBlurProgram.uniform1i("blur_strength", mStrength); return QUAD_NORMAL; }
void LLPostProcess::applyGaussBlurShader(void) { int pass_count = tweaks.getGaussBlurPasses(); if(!pass_count || gPostGaussianBlurProgram.mProgramObject == 0) return; gPostGaussianBlurProgram.bind(); gGL.getTexUnit(0)->bind(mSceneRenderTexture); GLint horiz_pass = gPostGaussianBlurProgram.getUniformLocation("horizontalPass"); for(int i = 0;i<pass_count;++i) { for(int j = 0;j<2;++j) { if(i || j) copyFrameBuffer(); glUniform1iARB(horiz_pass, j); drawOrthoQuad(QUAD_NORMAL); } } gPostGaussianBlurProgram.unbind(); }
void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const { if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WL_CLOUDS)) { LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectSimpleWaterProgram : &gWLCloudProgram; LLGLEnable blend(GL_BLEND); LLGLSBlendFunc blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.getTexUnit(0)->bind(sCloudNoiseTexture); shader->bind(); /// Render the skydome renderDome(camHeightLocal, shader); shader->unbind(); } }
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); }