From 82ba39d2ff6eb0067bcb384246541eb54e206cd9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sat, 8 Apr 2023 19:30:58 -0700 Subject: Start moving our post process into methods. Lets make post processing make sense again. DRTVWR-559 SL-19524 SL-19513 --- indra/newview/llviewerdisplay.cpp | 3 - indra/newview/pipeline.cpp | 989 +++++++++++++++++++------------------- indra/newview/pipeline.h | 6 + 3 files changed, 490 insertions(+), 508 deletions(-) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 59333b6cee..a44452f0d1 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1307,9 +1307,6 @@ void render_ui(F32 zoom_factor, int subfield) gGL.popMatrix(); } - // Render our post process prior to the HUD, UI, etc. - gPipeline.renderPostProcess(); - // apply gamma correction and post effects gPipeline.renderFinalize(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e4ffa5b6b0..a1183ccb0f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6924,514 +6924,219 @@ void LLPipeline::renderPostProcess() LLVertexBuffer::unbind(); - { - bool dof_enabled = - (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && - RenderDepthOfField && - !gCubeSnapshot; + +} - bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot; +LLRenderTarget* LLPipeline::screenTarget() { - gViewerWindow->setup3DViewport(); + bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() && + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField && + !gCubeSnapshot; - if (dof_enabled) - { - LL_PROFILE_GPU_ZONE("dof"); - LLGLSLShader* shader = &gDeferredPostProgram; - LLGLDisable blend(GL_BLEND); + bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot; - // depth of field focal plane calculations - static F32 current_distance = 16.f; - static F32 start_distance = 16.f; - static F32 transition_time = 1.f; + if (multisample || dof_enabled) + return &mRT->deferredLight; + + return &mRT->screen; +} - LLVector3 focus_point; +void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) { + // luminance sample and mipmap generation + { + LL_PROFILE_GPU_ZONE("luminance sample"); - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } - } + dst->bindTarget(); - if (focus_point.isExactlyZero()) - { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); + gLuminanceProgram.bind(); - focus_point.set(result.getF32ptr()); - } - else - { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); - } - } - } - LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); - F32 target_distance = 16.f; - if (!focus_point.isExactlyZero()) - { - target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye); - } + S32 channel = 0; + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_POINT); + } - if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f) - { // large shift happened, interpolate smoothly to new target distance - transition_time = 0.f; - start_distance = current_distance; - } - else if (transition_time < 1.f) - { // currently in a transition, continue interpolating - transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value(); - transition_time = llmin(transition_time, 1.f); + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + mGlow[1].bindTexture(0, channel); + } - F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f; - current_distance = start_distance + (target_distance - start_distance) * t; - } - else - { // small or no change, just snap to target distance - current_distance = target_distance; - } - // convert to mm - F32 subject_distance = current_distance * 1000.f; - F32 fnumber = CameraFNumber; - F32 default_focal_length = CameraFocalLength; + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + dst->flush(); - F32 fov = LLViewerCamera::getInstance()->getView(); + dst->bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + glGenerateMipmap(GL_TEXTURE_2D); - const F32 default_fov = CameraFieldOfView * F_PI / 180.f; + // note -- unbind AFTER the glGenerateMipMap so time in generatemipmap can be profiled under "Luminance" + // also note -- keep an eye on the performance of glGenerateMipmap, might need to replace it with a mip generation shader + gLuminanceProgram.unbind(); + } +} - // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight(); +void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst) { + // exposure sample + { + LL_PROFILE_GPU_ZONE("exposure sample"); - F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f); + { + // copy last frame's exposure into mLastExposure + mLastExposure.bindTarget(); + gCopyProgram.bind(); + gGL.getTexUnit(0)->bind(&mExposureMap); - F32 focal_length = dv / (2 * tanf(fov / 2.f)); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); + mLastExposure.flush(); + } - // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) - // where N = fnumber - // s2 = dot distance - // s1 = subject distance - // f = focal length - // + dst->bindTarget(); - F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length)); - blur_constant /= 1000.f; // convert to meters for shader - F32 magnification = focal_length / (subject_distance - focal_length); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - { // build diffuse+bloom+CoF - mRT->deferredLight.bindTarget(); - shader = &gDeferredCoFProgram; + gExposureProgram.bind(); - bindDeferredShader(*shader); + S32 channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); + } - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); - if (channel > -1) - { - mRT->screen.bindTexture(0, channel); - } + channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP); + if (channel > -1) + { + mLastExposure.bindTexture(0, channel); + } - shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); - shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); - shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); - shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + static LLCachedControl dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); + static LLCachedControl dynamic_exposure_min(gSavedSettings, "RenderDynamicExposureMin", 0.125f); + static LLCachedControl dynamic_exposure_max(gSavedSettings, "RenderDynamicExposureMax", 1.3f); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); + static LLStaticHashedString dt("dt"); + static LLStaticHashedString noiseVec("noiseVec"); + static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); + gExposureProgram.uniform1f(dt, gFrameIntervalSeconds); + gExposureProgram.uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); + gExposureProgram.uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, dynamic_exposure_min, dynamic_exposure_max); - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); + gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); + gExposureProgram.unbind(); + dst->flush(); + } +} - gGL.end(); +void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { + dst->bindTarget(); + // gamma correct lighting + { + LL_PROFILE_GPU_ZONE("gamma correct"); - unbindDeferredShader(*shader); - mRT->deferredLight.flush(); - } + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale); - U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); - { // perform DoF sampling at half-res (preserve alpha channel) - mRT->screen.bindTarget(); - glViewport(0, 0, dof_width, dof_height); - gGL.setColorMask(true, false); + S32 channel = 0; - shader = &gDeferredPostProgram; - bindDeferredShader(*shader); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage()); - if (channel > -1) - { - mRT->deferredLight.bindTexture(0, channel); - } + gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT); - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight()); - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); + static LLCachedControl exposure(gSavedSettings, "RenderExposure", 1.f); - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); + F32 e = llclamp(exposure(), 0.5f, 4.f); - gGL.end(); + static LLStaticHashedString s_exposure("exposure"); - unbindDeferredShader(*shader); - mRT->screen.flush(); - gGL.setColorMask(true, true); - } + gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e); - { // combine result based on alpha - if (multisample) - { - mRT->deferredLight.bindTarget(); - glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight()); - } - else - { - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - } + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - shader = &gDeferredDoFCombineProgram; - bindDeferredShader(*shader); + gGL.getTexUnit(channel)->unbind(src->getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + } + dst->flush(); +} - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); - if (channel > -1) - { - mRT->screen.bindTexture(0, channel); - } +void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) { - shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - shader->uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)mRT->screen.getWidth()); - shader->uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)mRT->screen.getHeight()); + if (RenderScreenSpaceReflections && !gCubeSnapshot) + { + LL_PROFILE_GPU_ZONE("ssr copy"); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); + LLRenderTarget& depth_src = mRT->deferredScreen; - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); + dst->bindTarget(); + dst->clear(); + gCopyDepthProgram.bind(); - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - gGL.end(); + gGL.getTexUnit(diff_map)->bind(src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); - unbindDeferredShader(*shader); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - if (multisample) - { - mRT->deferredLight.flush(); - } - } - } - else - { - LL_PROFILE_GPU_ZONE("no dof"); - if (multisample) - { - mRT->deferredLight.bindTarget(); - } - LLGLSLShader* shader = &gDeferredPostNoDoFProgram; + dst->flush(); + } +} - bindDeferredShader(*shader); +void LLPipeline::renderGlow(LLRenderTarget* src, LLRenderTarget* dst) { + if (sRenderGlow) + { + LL_PROFILE_GPU_ZONE("glow"); + mGlow[2].bindTarget(); + mGlow[2].clear(); - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); - if (channel > -1) - { - mRT->screen.bindTexture(0, channel); - } + gGlowExtractProgram.bind(); + F32 maxAlpha = RenderGlowMaxExtractAlpha; + F32 warmthAmount = RenderGlowWarmthAmount; + LLVector3 lumWeights = RenderGlowLumWeights; + LLVector3 warmthWeights = RenderGlowWarmthWeights; - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, 9999); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], + lumWeights.mV[2]); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], + warmthWeights.mV[2]); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); + { + LLGLEnable blend_on(GL_BLEND); + LLGLEnable test(GL_ALPHA_TEST); - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - gGL.end(); + gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, src); - unbindDeferredShader(*shader); + gGL.color4f(1, 1, 1, 1); + gPipeline.enableLightsFullbright(); - if (multisample) - { - mRT->deferredLight.flush(); - } + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + mGlow[2].flush(); } - } -} -LLRenderTarget* LLPipeline::screenTarget() { - - bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() && - (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && - RenderDepthOfField && - !gCubeSnapshot; - - bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot; - - if (multisample || dof_enabled) - return &mRT->deferredLight; - - return &mRT->screen; -} - -void LLPipeline::renderFinalize() -{ - LLVertexBuffer::unbind(); - LLGLState::checkStates(); - - assertInitialized(); - - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); - LL_PROFILE_GPU_ZONE("renderFinalize"); - - gGL.color4f(1, 1, 1, 1); - LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable cull(GL_CULL_FACE); - - enableLightsFullbright(); - - LLGLDisable test(GL_ALPHA_TEST); - - gGL.setColorMask(true, true); - glClearColor(0, 0, 0, 0); - - if (!gCubeSnapshot) - { - LLRenderTarget* screen_target = screenTarget(); - - if (RenderScreenSpaceReflections && !gCubeSnapshot) - { - LL_PROFILE_GPU_ZONE("ssr copy"); - LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - - LLRenderTarget& src = *screen_target; - LLRenderTarget& depth_src = mRT->deferredScreen; - LLRenderTarget& dst = mSceneMap; - - dst.bindTarget(); - dst.clear(); - gCopyDepthProgram.bind(); - - S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); - S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - - gGL.getTexUnit(diff_map)->bind(&src); - gGL.getTexUnit(depth_map)->bind(&depth_src, true); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - dst.flush(); - } - - // luminance sample and mipmap generation - { - LL_PROFILE_GPU_ZONE("luminance sample"); - - mLuminanceMap.bindTarget(); - - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - gLuminanceProgram.bind(); - - - S32 channel = 0; - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); - if (channel > -1) - { - screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT); - } - - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - mGlow[1].bindTexture(0, channel); - } - - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mLuminanceMap.flush(); - - mLuminanceMap.bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); - glGenerateMipmap(GL_TEXTURE_2D); - - // note -- unbind AFTER the glGenerateMipMap so time in generatemipmap can be profiled under "Luminance" - // also note -- keep an eye on the performance of glGenerateMipmap, might need to replace it with a mip generation shader - gLuminanceProgram.unbind(); - } - - // exposure sample - { - LL_PROFILE_GPU_ZONE("exposure sample"); - - { - // copy last frame's exposure into mLastExposure - mLastExposure.bindTarget(); - gCopyProgram.bind(); - gGL.getTexUnit(0)->bind(&mExposureMap); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - mLastExposure.flush(); - } - - mExposureMap.bindTarget(); - - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - gExposureProgram.bind(); - - S32 channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - mLuminanceMap.bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); - } - - channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - mLastExposure.bindTexture(0, channel); - } - - static LLCachedControl dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); - static LLCachedControl dynamic_exposure_min(gSavedSettings, "RenderDynamicExposureMin", 0.125f); - static LLCachedControl dynamic_exposure_max(gSavedSettings, "RenderDynamicExposureMax", 1.3f); - - static LLStaticHashedString dt("dt"); - static LLStaticHashedString noiseVec("noiseVec"); - static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); - gExposureProgram.uniform1f(dt, gFrameIntervalSeconds); - gExposureProgram.uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); - gExposureProgram.uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, dynamic_exposure_min, dynamic_exposure_max); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); - gExposureProgram.unbind(); - mExposureMap.flush(); - } - - mPostMap.bindTarget(); - - // gamma correct lighting - { - LL_PROFILE_GPU_ZONE("gamma correct"); - - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - // Apply gamma correction to the frame here. - gDeferredPostGammaCorrectProgram.bind(); - - S32 channel = 0; - - gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, screenTarget(), false, LLTexUnit::TFO_POINT); - - gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap); - - gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screenTarget()->getWidth(), screenTarget()->getHeight()); - - static LLCachedControl exposure(gSavedSettings, "RenderExposure", 1.f); - - F32 e = llclamp(exposure(), 0.5f, 4.f); - - static LLStaticHashedString s_exposure("exposure"); - - gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); - gDeferredPostGammaCorrectProgram.unbind(); - } - - mPostMap.flush(); - - LLVertexBuffer::unbind(); - } - - if (sRenderGlow) - { - LL_PROFILE_GPU_ZONE("glow"); - mGlow[2].bindTarget(); - mGlow[2].clear(); - - gGlowExtractProgram.bind(); - F32 maxAlpha = RenderGlowMaxExtractAlpha; - F32 warmthAmount = RenderGlowWarmthAmount; - LLVector3 lumWeights = RenderGlowLumWeights; - LLVector3 warmthWeights = RenderGlowWarmthWeights; - - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, 9999); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], - lumWeights.mV[2]); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], - warmthWeights.mV[2]); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); - - { - LLGLEnable blend_on(GL_BLEND); - LLGLEnable test(GL_ALPHA_TEST); - - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - - gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mPostMap); - - gGL.color4f(1, 1, 1, 1); - gPipeline.enableLightsFullbright(); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - mGlow[2].flush(); - } - - gGlowExtractProgram.unbind(); + gGlowExtractProgram.unbind(); // power of two between 1 and 1024 U32 glowResPow = RenderGlowResolutionPow; @@ -7480,7 +7185,7 @@ void LLPipeline::renderFinalize() } gGlowProgram.unbind(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + } else // !sRenderGlow, skip the glow ping-pong and just clear the result target { @@ -7489,16 +7194,35 @@ void LLPipeline::renderFinalize() mGlow[1].flush(); } + // Go ahead and do our glow combine here in our destination. We blit this later into the front buffer. + + dst->bindTarget(); + + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + + gGlowCombineProgram.bind(); + + gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src); + gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + dst->flush(); +} + +void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) { { - llassert(!gCubeSnapshot); + llassert(!gCubeSnapshot); bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete(); LLGLSLShader* shader = &gGlowCombineProgram; S32 width = screenTarget()->getWidth(); S32 height = screenTarget()->getHeight(); - S32 channel = -1; - // Present everything. if (multisample) { @@ -7506,38 +7230,27 @@ void LLPipeline::renderFinalize() // bake out texture2D with RGBL for FXAA shader mRT->fxaaBuffer.bindTarget(); - glViewport(0, 0, width, height); - - shader = &gGlowCombineFXAAProgram; - + shader = &gDeferredPostNoDoFProgram; shader->bind(); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height); - channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mPostMap.getUsage()); + S32 channel = gDeferredPostNoDoFProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); if (channel > -1) { - mPostMap.bindTexture(0, channel); + src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); } - channel = shader->enableTexture(LLShaderMgr::DEFERRED_EMISSIVE, mGlow[1].getUsage()); - if (channel > -1) { - mGlow[1].bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); } - { - LLGLDepthTest depth_test(GL_FALSE, GL_FALSE, GL_ALWAYS); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - gGL.flush(); - - shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mPostMap.getUsage()); + shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); shader->unbind(); mRT->fxaaBuffer.flush(); + dst->bindTarget(); shader = &gFXAAProgram; shader->bind(); @@ -7547,12 +7260,6 @@ void LLPipeline::renderFinalize() mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); } - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - F32 scale_x = (F32)width / mRT->fxaaBuffer.getWidth(); F32 scale_y = (F32)height / mRT->fxaaBuffer.getHeight(); shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); @@ -7562,46 +7269,318 @@ void LLPipeline::renderFinalize() shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y, 2.f / width * scale_x, 2.f / height * scale_y); - { - // at this point we should pointed at the backbuffer (or a snapshot render target) - llassert(gSnapshot || LLRenderTarget::sCurFBO == 0); - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); - S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true); + { + // at this point we should pointed at the backbuffer (or a snapshot render target) + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - shader->unbind(); + dst->flush(); } - else + } +} + +void LLPipeline::renderFinalize() +{ + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + + assertInitialized(); + + LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM); + LL_PROFILE_GPU_ZONE("renderFinalize"); + + gGL.color4f(1, 1, 1, 1); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable cull(GL_CULL_FACE); + + enableLightsFullbright(); + + LLGLDisable test(GL_ALPHA_TEST); + + gGL.setColorMask(true, true); + glClearColor(0, 0, 0, 0); + + if (!gCubeSnapshot) + { + + copyScreenSpaceReflections(&mSceneMap, screenTarget()); + + generateLuminance(screenTarget(), &mLuminanceMap); + + generateExposure(&mLuminanceMap, &mExposureMap); + + gammaCorrect(screenTarget(), &mPostMap); + + LLVertexBuffer::unbind(); + } + + renderGlow(&mPostMap, screenTarget()); + /* + { + bool dof_enabled = + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField && + !gCubeSnapshot; + + bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot; + + gViewerWindow->setup3DViewport(); + + if (dof_enabled) { - // at this point we should pointed at the backbuffer (or a snapshot render target) - llassert(gSnapshot || LLRenderTarget::sCurFBO == 0); + LL_PROFILE_GPU_ZONE("dof"); + LLGLSLShader* shader = &gDeferredPostProgram; + LLGLDisable blend(GL_BLEND); + + // depth of field focal plane calculations + static F32 current_distance = 16.f; + static F32 start_distance = 16.f; + static F32 transition_time = 1.f; - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + LLVector3 focus_point; - shader->bind(); + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); - shader->bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mPostMap); - shader->bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - shader->bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]); + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + F32 target_distance = 16.f; + if (!focus_point.isExactlyZero()) + { + target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye); + } - gGL.flush(); - shader->unbind(); + if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f) + { // large shift happened, interpolate smoothly to new target distance + transition_time = 0.f; + start_distance = current_distance; + } + else if (transition_time < 1.f) + { // currently in a transition, continue interpolating + transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value(); + transition_time = llmin(transition_time, 1.f); + + F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f; + current_distance = start_distance + (target_distance - start_distance) * t; + } + else + { // small or no change, just snap to target distance + current_distance = target_distance; + } + + // convert to mm + F32 subject_distance = current_distance * 1000.f; + F32 fnumber = CameraFNumber; + F32 default_focal_length = CameraFocalLength; + + F32 fov = LLViewerCamera::getInstance()->getView(); + + const F32 default_fov = CameraFieldOfView * F_PI / 180.f; + + // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight(); + + F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f); + + F32 focal_length = dv / (2 * tanf(fov / 2.f)); + + // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); + + // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) + // where N = fnumber + // s2 = dot distance + // s1 = subject distance + // f = focal length + // + + F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length)); + blur_constant /= 1000.f; // convert to meters for shader + F32 magnification = focal_length / (subject_distance - focal_length); + + { // build diffuse+bloom+CoF + mRT->deferredLight.bindTarget(); + shader = &gDeferredCoFProgram; + + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); + if (channel > -1) + { + mRT->screen.bindTexture(0, channel); + } + + shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); + shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); + shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); + shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + unbindDeferredShader(*shader); + mRT->deferredLight.flush(); + } + + U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale); + U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale); + + { // perform DoF sampling at half-res (preserve alpha channel) + mRT->screen.bindTarget(); + glViewport(0, 0, dof_width, dof_height); + gGL.setColorMask(true, false); + + shader = &gDeferredPostProgram; + bindDeferredShader(*shader); + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage()); + if (channel > -1) + { + mRT->deferredLight.bindTexture(0, channel); + } + + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + unbindDeferredShader(*shader); + mRT->screen.flush(); + gGL.setColorMask(true, true); + } + + { // combine result based on alpha + if (multisample) + { + mRT->deferredLight.bindTarget(); + glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight()); + } + else + { + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + } + + shader = &gDeferredDoFCombineProgram; + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); + if (channel > -1) + { + mRT->screen.bindTexture(0, channel); + } + + shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + shader->uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)mRT->screen.getWidth()); + shader->uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)mRT->screen.getHeight()); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + unbindDeferredShader(*shader); + + if (multisample) + { + mRT->deferredLight.flush(); + } + } } + else + { + LL_PROFILE_GPU_ZONE("no dof"); + if (multisample) + { + mRT->deferredLight.bindTarget(); + } + LLGLSLShader* shader = &gDeferredPostNoDoFProgram; + + bindDeferredShader(*shader); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); + if (channel > -1) + { + mRT->screen.bindTexture(0, channel); + } + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + unbindDeferredShader(*shader); + + if (multisample) + { + mRT->deferredLight.flush(); + } + } + }*/ + + //applyFXAA(screenTarget(), screenTarget()); + + // Present the screen target. + + gDeferredPostNoDoFProgram.bind(); + + S32 channel = gDeferredPostNoDoFProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screenTarget()->getUsage()); + if (channel > -1) + { + screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); + } + + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); } + gDeferredPostNoDoFProgram.unbind(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index a231084e5c..3ed9ed73a8 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -135,6 +135,12 @@ public: void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false); void bindScreenToTexture(); void renderFinalize(); + void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst); + void generateLuminance(LLRenderTarget* src, LLRenderTarget* dst); + void generateExposure(LLRenderTarget* src, LLRenderTarget* dst); + void gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst); + void renderGlow(LLRenderTarget* src, LLRenderTarget* dst); + void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst); void renderPostProcess(); LLRenderTarget* screenTarget(); -- cgit v1.2.3