浏览代码

Added a nullify option for distortion, based on stencil buffer usage

/stochastic_alpha_test
Frédéric Vauchelles 7 年前
当前提交
e533651d
共有 5 个文件被更改,包括 69 次插入57 次删除
  1. 9
      SampleScenes/HDTest/GraphicTest/Common/Material/Mat_Distorsion_Reject.mat
  2. 90
      ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 12
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  4. 4
      ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs
  5. 11
      ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/ApplyDistorsion.compute

9
SampleScenes/HDTest/GraphicTest/Common/Material/Mat_Distorsion_Reject.mat


m_Name: Mat_Distorsion_Reject
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _ALBEDOAFFECTEMISSIVE_OFF _ALPHACUTOFFENABLE_OFF _BLENDMODE_LERP
_DEPTHOFFSETENABLE_OFF _DISTORTIONNULLIFY_OFF _DISTORTION_ON _DOUBLESIDEDENABLE_OFF
_ENABLEPERPIXELDISPLACEMENT_OFF _ENABLESPECULAROCCLUSION_OFF _ENABLEVERTEXDISPLACEMENT_OFF
_ENABLEWIND_OFF _NORMALMAP_TANGENT_SPACE
_DEPTHOFFSETENABLE_OFF _DISTORTION_ON _DOUBLESIDEDENABLE_OFF _ENABLEPERPIXELDISPLACEMENT_OFF
_ENABLESPECULAROCCLUSION_OFF _ENABLEVERTEXDISPLACEMENT_OFF _ENABLEWIND_OFF _NORMALMAP_TANGENT_SPACE
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

- _DetailSmoothnessScale: 1
- _DistortionDepthTest: 1
- _DistortionEnable: 1
- _DistortionNullify: 0
- _DistortionNullify: 1
- _DistortionStencilRef: 1
- _DistortionStencilRef: 8
- _DoubleSidedEnable: 0
- _DoubleSidedNormalMode: 1
- _Drag: 1

90
ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


[Flags]
public enum StencilBitMask
{
Clear = 0, // 0x0
Lighting = 3, // 0x3 - 2 bit
All = 255 // 0xFF - 8 bit
Clear = 0, // 0x0
Lighting = 3, // 0x3 - 2 bit
DistortionEnabled = 4, // 0x4 - 1 bit
All = 255 // 0xFF - 8 bit
}
RenderStateBlock m_DepthStateOpaque;

m_CopyStencilForRegularLighting.SetInt(HDShaderIDs._StencilRef, (int)StencilLightingUsage.RegularLighting);
m_CopyStencilForDistortion = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/CopyStencilBuffer");
m_CopyStencilForDistortion.DisableKeyword("EXPORT_HTILE");
m_CopyStencilForDistortion.SetInt(HDShaderIDs._StencilRef, 3); // Distortion mask
m_CopyStencilForDistortion.SetInt(HDShaderIDs._StencilRef, (int)StencilBitMask.DistortionEnabled);
m_CameraMotionVectorsMaterial = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/CameraMotionVectors");
InitializeDebugMaterials();

{
// Currently, Unity does not offer a way to bind the stencil buffer as a texture in a compute shader.
// Therefore, it's manually copied using a pixel shader.
return m_CurrentDebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission
|| m_CurrentDebugDisplaySettings.renderingDebugSettings.enableDistortion
|| LightLoop.GetFeatureVariantsEnabled(m_Asset.tileSettings);
return m_CurrentDebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission || LightLoop.GetFeatureVariantsEnabled(m_Asset.tileSettings);
}
bool NeedHTileCopy()

// Our method of exporting the stencil requires one pass per unique stencil value.
CoreUtils.DrawFullScreen(cmd, m_CopyStencilForSplitLighting, m_CameraStencilBufferCopyRT, m_CameraDepthStencilBufferRT);
CoreUtils.DrawFullScreen(cmd, m_CopyStencilForRegularLighting, m_CameraStencilBufferCopyRT, m_CameraDepthStencilBufferRT);
CoreUtils.DrawFullScreen(cmd, m_CopyStencilForDistortion, m_CameraStencilBufferCopyRT, m_CameraDepthStencilBufferRT);
cmd.ClearRandomWriteTargets();
}
}

RenderPyramidDepth(camera, cmd);
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness. This
RenderDistortion(m_CullResults, camera, renderContext, cmd);
// Required for the SSS and the shader feature classification pass.
PrepareAndBindStencilTexture(cmd);

RenderVelocity(m_CullResults, hdCamera, renderContext, cmd); // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
RenderGaussianPyramidColor(camera, cmd);
ApplyDistortion(cmd, m_Asset.renderPipelineResources);
// TODO: Check with VFX team.
// Rendering distortion here have off course lot of artifact.
// But resolving at each objects that write in distortion is not possible (need to sort transparent, render those that do not distort, then resolve, then etc...)
// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness.
AccumulateDistortion(m_CullResults, camera, renderContext, cmd);
// We need the stencil buffer to render the distortion in a compute shader
// Due to API limitation, it will OVERRIDE previous values in copied stencil buffer
PrepareAndBindStencilTextureForDistortion(cmd);
RenderDistortion(cmd, m_Asset.renderPipelineResources);
RenderPostProcesses(camera, cmd, postProcessLayer);
}

renderContext.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings, stateBlock.Value);
}
void ApplyDistortion(CommandBuffer cmd, RenderPipelineResources resources)
/// <summary>
/// Distortion is resolved in two steps:
/// - AccumulateDistortion is a pass that
/// 1. Accumulate distortion vectors (add)
/// 2. Accumulate smoothness (max)
/// 3. Mark in DistortionBuffer pixel eligible as source for distortion
/// 4. Mark in stencil buffer pixel eligible to be distorted
/// - RenderDistortion is a pass that distort eligible pixels with eligible sources with a specified smoothness
/// </summary>
void AccumulateDistortion(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext, CommandBuffer cmd)
{
if (!m_CurrentDebugDisplaySettings.renderingDebugSettings.enableDistortion)
return;
using (new ProfilingSample(cmd, "Distortion"))
{
int w = camera.pixelWidth;
int h = camera.pixelHeight;
cmd.GetTemporaryRT(m_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.GetDistortionBufferFormat(), Builtin.GetDistortionBufferReadWrite());
cmd.SetRenderTarget(m_DistortionBufferRT, m_CameraDepthStencilBufferRT);
cmd.ClearRenderTarget(false, true, Color.clear);
// Only transparent object can render distortion vectors
RenderTransparentRenderList(cullResults, camera, renderContext, cmd, HDShaderPassNames.s_DistortionVectorsName);
}
}
void PrepareAndBindStencilTextureForDistortion(CommandBuffer cmd)
{
// We need to get the 3rd bit of the stencil buffer for distortion
// This call will overwrite the stencil with the value of the third bit (0 or 4)
using (new ProfilingSample(cmd, "Copy StencilBuffer For Distortion"))
CoreUtils.DrawFullScreen(cmd, m_CopyStencilForDistortion, m_CameraStencilBufferCopyRT, m_CameraDepthStencilBufferRT);
}
void RenderDistortion(CommandBuffer cmd, RenderPipelineResources resources)
{
using (new ProfilingSample(cmd, "ApplyDistortion"))
{

cmd.SetComputeTextureParam(resources.applyDistortionCS, resources.applyDistortionKernel, HDShaderIDs._DistortionTexture, m_DistortionBufferRT);
cmd.SetComputeTextureParam(resources.applyDistortionCS, resources.applyDistortionKernel, HDShaderIDs._GaussianPyramidColorTexture, m_GaussianPyramidColorBufferRT);
cmd.SetComputeTextureParam(resources.applyDistortionCS, resources.applyDistortionKernel, HDShaderIDs._CameraColorTexture, m_CameraColorBufferRT);
cmd.SetComputeTextureParam(resources.applyDistortionCS, resources.applyDistortionKernel, HDShaderIDs._StencilTexture, GetStencilTexture());
cmd.SetComputeTextureParam(resources.applyDistortionCS, resources.applyDistortionKernel, HDShaderIDs._StencilTexture, m_CameraStencilBufferCopyRT);
cmd.SetComputeVectorParam(resources.applyDistortionCS, HDShaderIDs._Size, size);
cmd.SetComputeVectorParam(resources.applyDistortionCS, HDShaderIDs._GaussianPyramidColorMipSize, Shader.GetGlobalVector(HDShaderIDs._GaussianPyramidColorMipSize));
cmd.DispatchCompute(resources.applyDistortionCS, resources.applyDistortionKernel, (int)(size.x) / (int)x, (int)(size.y) / (int)y, 1);

for (int i = 0; i < lodCount + 1; i++)
cmd.ReleaseTemporaryRT(HDShaderIDs._DepthPyramidMips[i]);
}
}
void RenderDistortion(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext, CommandBuffer cmd)
{
if (!m_CurrentDebugDisplaySettings.renderingDebugSettings.enableDistortion)
return;
using (new ProfilingSample(cmd, "Distortion"))
{
int w = camera.pixelWidth;
int h = camera.pixelHeight;
cmd.GetTemporaryRT(m_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.GetDistortionBufferFormat(), Builtin.GetDistortionBufferReadWrite());
cmd.SetRenderTarget(m_DistortionBufferRT, m_CameraDepthStencilBufferRT);
cmd.ClearRenderTarget(false, true, Color.clear); // TODO: can we avoid this clear for performance ?
// Only transparent object can render distortion vectors
RenderTransparentRenderList(cullResults, camera, renderContext, cmd, HDShaderPassNames.s_DistortionVectorsName);
}
}

12
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Depth Test Enable", Float) = 0.0
[ToggleOff] _DepthOffsetEnable("Depth Offset View space", Float) = 0.0
[HideInInspector] _DistortionStencilRef("Distortion Stencil Comparison", Int) = 1 // UnityEngine.Rendering.CompareFunction.Never
[HideInInspector] _DistortionStencilRef("Distortion Stencil Ref", Int) = 4
[ToggleOff] _DistortionNullify("Nullify distortion", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0

Ref [_StencilRef]
Comp Always
Pass Replace
ReadMask 3
WriteMask 3
}
HLSLPROGRAM

Ref [_StencilRef]
Comp Always
Pass Replace
ReadMask 3
WriteMask 3
}
HLSLPROGRAM

Stencil
{
Ref 4
Ref [_DistortionStencilRef]
ReadMask 4
WriteMask 4
// This will erase previous stencil information
// Make sure this pass is called after light stencil bits were used
}
HLSLPROGRAM

4
ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs


bool distortionNullify = material.GetFloat(kDistortionNullify) > 0.0f;
if (distortionNullify)
{
material.SetInt("_DistortionStencilRef", (int)UnityEngine.Rendering.CompareFunction.Always);
material.SetInt("_DistortionStencilRef", 0);
material.SetInt("_DistortionStencilRef", (int)UnityEngine.Rendering.CompareFunction.Never);
material.SetInt("_DistortionStencilRef", (int)HDRenderPipeline.StencilBitMask.DistortionEnabled);
}
}

11
ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/ApplyDistorsion.compute


#include "../../Core/ShaderLibrary/Packing.hlsl"
#include "../Material/Builtin/BuiltinData.hlsl"
#define DISTORTIONENABLED_STENCILBIT 4
Texture2D<float4> _DistortionTexture;
Texture2D<float4> _StencilTexture;
Texture2D<float4> _GaussianPyramidColorTexture;

// Reject pixels based on stencil buffer
// 3rd bit is 1 for rejected pixels
uint stencil = UnpackByte(_StencilTexture.Load(uint3(dispatchThreadId, 0)).r);
bool isRejected = stencil & 4 != 0;
//bool isRejected = (uint(stencil) & 4) != 0;
/*if (isRejected)
return;*/
bool isValid = (stencil & DISTORTIONENABLED_STENCILBIT) != 0;
if (!isValid)
return;
_CameraColorTexture[dispatchThreadId] = float4(isRejected, isRejected, isRejected, 1.0);
return;
// We use a bias when fetching distortion source pixels
// This avoid artifacts when a distortion is overlapped by an opaque object
const float _FetchBias = 0.9;

正在加载...
取消
保存