diff options
author | Jonathan "Geenz" Goodman <geenz@lindenlab.com> | 2023-04-12 16:40:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-12 16:40:51 -0700 |
commit | 88d35aaf0f6478c7d426c8d01b230d089a52aaf9 (patch) | |
tree | 2cd307846fafb16c4f53c464a2e55b1d1fd33ca6 /indra | |
parent | bd7a924a9423105f0acaaaf271d611d435299d14 (diff) | |
parent | 6d5c16971654764de28833fd886f522212d3746d (diff) |
Merge pull request #166 from secondlife/DRTVWR-559-post-refactor
Drtvwr 559 post processing refactor
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llrender/llglslshader.cpp | 11 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl | 3 | ||||
-rw-r--r-- | indra/newview/llviewerdisplay.cpp | 3 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 896 | ||||
-rw-r--r-- | indra/newview/pipeline.h | 9 |
5 files changed, 447 insertions, 475 deletions
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index d27528296f..b12de563e4 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1091,7 +1091,6 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, if (uniform < 0 || uniform >= (S32)mTexture.size()) { - LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } @@ -1099,9 +1098,13 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, if (uniform > -1) { - bool has_mips = mode == LLTexUnit::TFO_TRILINEAR || mode == LLTexUnit::TFO_ANISOTROPIC; - gGL.getTexUnit(uniform)->bindManual(texture->getUsage(), texture->getTexture(0), has_mips); - + if (depth) { + gGL.getTexUnit(uniform)->bind(texture, true); + } + else { + bool has_mips = mode == LLTexUnit::TFO_TRILINEAR || mode == LLTexUnit::TFO_ANISOTROPIC; + gGL.getTexUnit(uniform)->bindManual(texture->getUsage(), texture->getTexture(0), has_mips); + } gGL.getTexUnit(uniform)->setTextureFilteringOption(mode); } diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl index 6cc83138a2..c50548d528 100644 --- a/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineFXAAF.glsl @@ -30,7 +30,6 @@ out vec4 frag_color; uniform sampler2D diffuseRect; -uniform sampler2D emissiveRect; uniform vec2 screen_res; @@ -38,7 +37,7 @@ in vec2 vary_tc; void main() { - vec3 col = texture(diffuseRect, vary_tc).rgb + texture(emissiveRect, vary_tc).rgb; + vec3 col = texture(diffuseRect, vary_tc).rgb; frag_color = vec4(col.rgb, dot(col.rgb, vec3(0.299, 0.587, 0.144))); } 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 4266c16f94..3e9a1bb353 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6924,279 +6924,7 @@ void LLPipeline::renderPostProcess() LLVertexBuffer::unbind(); - { - bool dof_enabled = - (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && - RenderDepthOfField && - !gCubeSnapshot; - - bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete() && !gCubeSnapshot; - - gViewerWindow->setup3DViewport(); - - if (dof_enabled) - { - 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; - - LLVector3 focus_point; - - 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(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - - 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); - } - - 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); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); - - gGL.end(); - - 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); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); - - gGL.end(); - - 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()); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); - - gGL.end(); - - 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); - } - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1, -1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1, 3); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(3, -1); - - gGL.end(); - - unbindDeferredShader(*shader); - - if (multisample) - { - mRT->deferredLight.flush(); - } - } - } + } LLRenderTarget* LLPipeline::screenTarget() { @@ -7214,186 +6942,161 @@ LLRenderTarget* LLPipeline::screenTarget() { 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(); +void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) { + // luminance sample and mipmap generation + { + LL_PROFILE_GPU_ZONE("luminance sample"); - S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); - S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + dst->bindTarget(); - gGL.getTexUnit(diff_map)->bind(&src); - gGL.getTexUnit(depth_map)->bind(&depth_src, true); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gLuminanceProgram.bind(); - dst.flush(); - } + S32 channel = 0; + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_POINT); + } - // luminance sample and mipmap generation - { - LL_PROFILE_GPU_ZONE("luminance sample"); + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + mGlow[1].bindTexture(0, channel); + } - mLuminanceMap.bindTarget(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + dst->flush(); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); + dst->bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); + glGenerateMipmap(GL_TEXTURE_2D); - gLuminanceProgram.bind(); + // 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(); + } +} +void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst) { + // exposure sample + { + LL_PROFILE_GPU_ZONE("exposure sample"); - S32 channel = 0; - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); - if (channel > -1) - { - screenTarget()->bindTexture(0, channel, LLTexUnit::TFO_POINT); - } + { + // copy last frame's exposure into mLastExposure + mLastExposure.bindTarget(); + gCopyProgram.bind(); + gGL.getTexUnit(0)->bind(dst); - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - mGlow[1].bindTexture(0, channel); - } + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mLastExposure.flush(); + } - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mLuminanceMap.flush(); + dst->bindTarget(); - mLuminanceMap.bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR); - glGenerateMipmap(GL_TEXTURE_2D); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - // 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(); - } + gExposureProgram.bind(); - // exposure sample - { - LL_PROFILE_GPU_ZONE("exposure sample"); + S32 channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + mLuminanceMap.bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); + } - { - // copy last frame's exposure into mLastExposure - mLastExposure.bindTarget(); - gCopyProgram.bind(); - gGL.getTexUnit(0)->bind(&mExposureMap); + channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP); + if (channel > -1) + { + mLastExposure.bindTexture(0, channel); + } - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + static LLStaticHashedString dt("dt"); + static LLStaticHashedString noiseVec("noiseVec"); + static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); + static LLCachedControl<F32> dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); + static LLCachedControl<F32> dynamic_exposure_min(gSavedSettings, "RenderDynamicExposureMin", 0.125f); + static LLCachedControl<F32> dynamic_exposure_max(gSavedSettings, "RenderDynamicExposureMax", 1.3f); - mLastExposure.flush(); - } + 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); - mExposureMap.bindTarget(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - gExposureProgram.bind(); + gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); + gExposureProgram.unbind(); + dst->flush(); + } +} - S32 channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - mLuminanceMap.bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); - } +void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { + dst->bindTarget(); + // gamma correct lighting + { + LL_PROFILE_GPU_ZONE("gamma correct"); - channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - mLastExposure.bindTexture(0, channel); - } + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - static LLStaticHashedString dt("dt"); - static LLStaticHashedString noiseVec("noiseVec"); - static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); - static LLCachedControl<F32> dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); - static LLCachedControl<F32> dynamic_exposure_min(gSavedSettings, "RenderDynamicExposureMin", 0.125f); - static LLCachedControl<F32> dynamic_exposure_max(gSavedSettings, "RenderDynamicExposureMax", 1.3f); + // Apply gamma correction to the frame here. + gDeferredPostGammaCorrectProgram.bind(); - 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); + S32 channel = 0; - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT); - gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); - gExposureProgram.unbind(); - mExposureMap.flush(); - } + gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap); - mPostMap.bindTarget(); + gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight()); - // gamma correct lighting - { - LL_PROFILE_GPU_ZONE("gamma correct"); + static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); + F32 e = llclamp(exposure(), 0.5f, 4.f); - // Apply gamma correction to the frame here. - gDeferredPostGammaCorrectProgram.bind(); - - S32 channel = 0; + static LLStaticHashedString s_exposure("exposure"); - gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, screenTarget(), false, LLTexUnit::TFO_POINT); + gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e); - gDeferredPostGammaCorrectProgram.bindTexture(LLShaderMgr::EXPOSURE_MAP, &mExposureMap); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screenTarget()->getWidth(), screenTarget()->getHeight()); + gGL.getTexUnit(channel)->unbind(src->getUsage()); + gDeferredPostGammaCorrectProgram.unbind(); + } + dst->flush(); +} - static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f); +void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) { - F32 e = llclamp(exposure(), 0.5f, 4.f); + if (RenderScreenSpaceReflections && !gCubeSnapshot) + { + LL_PROFILE_GPU_ZONE("ssr copy"); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - static LLStaticHashedString s_exposure("exposure"); + LLRenderTarget& depth_src = mRT->deferredScreen; - gDeferredPostGammaCorrectProgram.uniform1f(s_exposure, e); + dst->bindTarget(); + dst->clear(); + gCopyDepthProgram.bind(); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - gGL.getTexUnit(channel)->unbind(screenTarget()->getUsage()); - gDeferredPostGammaCorrectProgram.unbind(); - } + gGL.getTexUnit(diff_map)->bind(src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); - mPostMap.flush(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - LLVertexBuffer::unbind(); - } + dst->flush(); + } +} +void LLPipeline::generateGlow(LLRenderTarget* src) { if (sRenderGlow) { LL_PROFILE_GPU_ZONE("glow"); @@ -7420,7 +7123,7 @@ void LLPipeline::renderFinalize() gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mPostMap); + gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, src); gGL.color4f(1, 1, 1, 1); gPipeline.enableLightsFullbright(); @@ -7480,7 +7183,7 @@ void LLPipeline::renderFinalize() } gGlowProgram.unbind(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + } else // !sRenderGlow, skip the glow ping-pong and just clear the result target { @@ -7488,17 +7191,17 @@ void LLPipeline::renderFinalize() mGlow[1].clear(); mGlow[1].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 +7209,27 @@ void LLPipeline::renderFinalize() // bake out texture2D with RGBL for FXAA shader mRT->fxaaBuffer.bindTarget(); - glViewport(0, 0, width, height); - shader = &gGlowCombineFXAAProgram; - shader->bind(); - shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height); - channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mPostMap.getUsage()); + S32 channel = shader->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 +7239,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,45 +7248,323 @@ 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); + { + 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 + else { + copyRenderTarget(src, dst); + } + } +} + +void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) { + + LL_PROFILE_GPU_ZONE("copyRenderTarget"); + dst->bindTarget(); + + gDeferredPostNoDoFProgram.bind(); + + S32 channel = gDeferredPostNoDoFProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + if (channel > -1) + { + src->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(); + + dst->flush(); +} + +void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) { + // 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::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) { + { + bool dof_enabled = + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField && + !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"); + 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(); + } + } + } - shader->bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mPostMap); - shader->bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - shader->bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]); + 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(); - 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]); + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 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()); + } + } + } - gGL.flush(); - shader->unbind(); + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + F32 target_distance = 16.f; + if (!focus_point.isExactlyZero()) + { + target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye); + } + + 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(); + + gDeferredCoFProgram.bind(); + + gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); + gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + + gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); + gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gDeferredCoFProgram.unbind(); + 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) + src->bindTarget(); + glViewport(0, 0, dof_width, dof_height); + gGL.setColorMask(true, false); + + gDeferredPostProgram.bind(); + gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mRT->deferredLight, LLTexUnit::TFO_POINT); + + gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gDeferredPostProgram.unbind(); + + src->flush(); + gGL.setColorMask(true, true); + } + + { // combine result based on alpha + + dst->bindTarget(); + glViewport(0, 0, dst->getWidth(), dst->getHeight()); + + gDeferredDoFCombineProgram.bind(); + gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); + gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mRT->deferredLight, LLTexUnit::TFO_POINT); + + gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth()); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)src->getHeight()); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gDeferredDoFCombineProgram.unbind(); + + dst->flush(); + } + } + else + { + copyRenderTarget(src, dst); } } +} + +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(&mRT->screen, &mSceneMap); + + generateLuminance(&mRT->screen, &mLuminanceMap); + + generateExposure(&mLuminanceMap, &mExposureMap); + + gammaCorrect(&mRT->screen, &mPostMap); + + LLVertexBuffer::unbind(); + } + + generateGlow(&mPostMap); + + combineGlow(&mPostMap, &mRT->screen); + + renderDoF(&mRT->screen, &mPostMap); + + applyFXAA(&mPostMap, &mRT->screen); + + + // Present the screen target. + + gDeferredPostNoDoFProgram.bind(); + + // Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems. + S32 channel = gDeferredPostNoDoFProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage()); + if (channel > -1) + { + mRT->screen.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); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index a231084e5c..ed9e2dc452 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -135,6 +135,15 @@ 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 generateGlow(LLRenderTarget* src); + void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst); + void renderDoF(LLRenderTarget* src, LLRenderTarget* dst); + void copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst); + void combineGlow(LLRenderTarget* src, LLRenderTarget* dst); void renderPostProcess(); LLRenderTarget* screenTarget(); |