浏览代码

Implement the initial version of the SSS algorithm

/main
Evgenii Golubev 8 年前
当前提交
aa6bf886
共有 6 个文件被更改,包括 207 次插入72 次删除
  1. 64
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs
  2. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/Utilities.cs
  3. 151
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  4. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader.meta
  5. 26
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.compute
  6. 9
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.compute.meta

64
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs


ShadowRenderPass m_ShadowPass;
ComputeShader m_CombineSubsurfaceScatteringCS = null;
int m_FilterVerticalKernel = -1;
int m_FilterHorizontalAndCombineKernel = -1;
[SerializeField]
TextureSettings m_TextureSettings = TextureSettings.Default;

// Various set of material use in render loop
Material m_DebugViewMaterialGBuffer;
Material m_CombineSubsurfaceScattering;
int m_CameraFilteringBuffer;
int m_CameraDepthStencilBuffer;
int m_CameraStencilBuffer;
int m_VelocityBuffer;

// It is stored within 'm_CameraSubsurfaceBufferRT'.
RenderTargetIdentifier m_CameraColorBufferRT;
RenderTargetIdentifier m_CameraSubsurfaceBufferRT;
RenderTargetIdentifier m_CameraFilteringBufferRT;
RenderTargetIdentifier m_CameraDepthStencilBufferRT;
// 'm_CameraStencilBufferRT' is a temporary copy of the stencil buffer and should be removed
// once we are able to read from the depth buffer and perform the stencil test simulatenously.

m_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
m_CameraSubsurfaceBuffer = Shader.PropertyToID("_CameraSubsurfaceTexture");
m_CameraFilteringBuffer = Shader.PropertyToID("_CameraFilteringBuffer");
m_CameraFilteringBufferRT = new RenderTargetIdentifier(m_CameraFilteringBuffer);
m_CameraDepthStencilBufferRT = new RenderTargetIdentifier(m_CameraDepthStencilBuffer);
m_CameraStencilBufferRT = new RenderTargetIdentifier(m_CameraStencilBuffer);

m_CombineSubsurfaceScattering = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CombineSubsurfaceScattering");
m_CombineSubsurfaceScatteringCS = Resources.Load<ComputeShader>("CombineSubsurfaceScattering");
// m_FilterVerticalKernel = m_CombineSubsurfaceScatteringCS.FindKernel("FilterVertical");
m_FilterHorizontalAndCombineKernel = m_CombineSubsurfaceScatteringCS.FindKernel("FilterHorizontalAndCombine");
m_gbufferManager.gbufferCount = m_LitRenderLoop.GetMaterialGBufferCount();
RenderTextureFormat[] RTFormat; RenderTextureReadWrite[] RTReadWrite;
m_LitRenderLoop.GetMaterialGBufferDescription(out RTFormat, out RTReadWrite);

cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraSubsurfaceBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraFilteringBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraDepthStencilBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
cmd.GetTemporaryRT(m_CameraStencilBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);

}
// Clear the diffuse SSS lighting target
using (new Utilities.ProfilingSample("Clear diffuse SSS target", renderContext))
using (new Utilities.ProfilingSample("Clear SSS diffuse target", renderContext))
}
// Clear the SSS filtering target
using (new Utilities.ProfilingSample("Clear SSS filtering target", renderContext))
{
Utilities.SetRenderTarget(renderContext, m_CameraFilteringBuffer, m_CameraDepthStencilBufferRT, ClearFlag.ClearColor, Color.black);
}
// Clear GBuffers

// Currently, forward-rendered objects do not output split lighting required for the SSS pass.
if (debugParameters.ShouldUseForwardRenderingOnly()) return;
int screenWidth = (int)hdCamera.screenSize.x;
int screenHeight = (int)hdCamera.screenSize.y;
const int groupSize = 256;
int groupSizeHorizontal = (screenWidth + groupSize - 1) / groupSize;
int groupSizeVertical = (screenHeight + groupSize - 1) / groupSize;
// Assume that the height of the projection window is 2 meters.
float distanceToProjectionWindow = 1.0f / Mathf.Tan(0.5f * Mathf.Deg2Rad * hdCamera.camera.fieldOfView);
m_CombineSubsurfaceScattering.SetFloat("_DistToProjWindow", distanceToProjectionWindow);
m_CombineSubsurfaceScattering.SetFloat("_FilterWidth", 20.0f);
m_CombineSubsurfaceScattering.SetFloat("_BilateralScale", 0.1f);
var cmdBuf = new CommandBuffer() { name = "Combine Subsurface Scattering" };
MaterialPropertyBlock properties = new MaterialPropertyBlock();
// Set the common data.
cmdBuf.SetComputeIntParam(m_CombineSubsurfaceScatteringCS, "screenWidth", screenWidth);
cmdBuf.SetComputeIntParam(m_CombineSubsurfaceScatteringCS, "screenHeight", screenHeight);
var cmd = new CommandBuffer() { name = "Combine Subsurface Scattering" };
cmd.SetGlobalTexture("_CameraDepthTexture", m_CameraDepthStencilBufferRT);
// TODO.
properties.SetFloat("_DstBlend", (float)BlendMode.Zero); // TODO: this doesn't work for some reason...
properties.SetFloat("_FilterHorizontal", 0);
cmd.SetGlobalTexture("_IrradianceSource", m_CameraSubsurfaceBufferRT);
Utilities.DrawFullscreen(cmd, m_CombineSubsurfaceScattering, hdCamera,
m_CameraFilteringBufferRT, m_CameraStencilBufferRT, properties);
cmdBuf.SetComputeTextureParam(m_CombineSubsurfaceScatteringCS, m_FilterHorizontalAndCombineKernel,
"diffuseFilterSource", m_CameraSubsurfaceBufferRT);
cmdBuf.SetComputeTextureParam(m_CombineSubsurfaceScatteringCS, m_FilterHorizontalAndCombineKernel,
"specularSourceAndColorTarget", m_CameraColorBufferRT);
cmdBuf.DispatchCompute(m_CombineSubsurfaceScatteringCS, m_FilterHorizontalAndCombineKernel, groupSizeHorizontal, screenHeight, 1);
properties.SetFloat("_DstBlend", (float)BlendMode.One); // TODO: this doesn't work for some reason...
properties.SetFloat("_FilterHorizontal", 1);
cmd.SetGlobalTexture("_IrradianceSource", m_CameraFilteringBufferRT);
Utilities.DrawFullscreen(cmd, m_CombineSubsurfaceScattering, hdCamera,
m_CameraColorBufferRT, m_CameraStencilBufferRT, properties);
context.ExecuteCommandBuffer(cmdBuf);
cmdBuf.Dispose();
context.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
void UpdateSkyEnvironment(HDCamera hdCamera, ScriptableRenderContext renderContext)

20
Assets/ScriptableRenderLoop/HDRenderPipeline/Utilities.cs


// Draws a full screen triangle as a faster alternative to drawing a full-screen quad.
public static void DrawFullscreen(CommandBuffer commandBuffer, Material material, HDRenderPipeline.HDCamera camera,
RenderTargetIdentifier colorBuffer, int shaderPassID = 0)
RenderTargetIdentifier colorBuffer,
MaterialPropertyBlock properties = null, int shaderPassID = 0)
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID);
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID, properties);
RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthStencilBuffer, int shaderPassID = 0)
RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthStencilBuffer,
MaterialPropertyBlock properties = null, int shaderPassID = 0)
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID);
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID, properties);
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer, int shaderPassID = 0)
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer,
MaterialPropertyBlock properties = null, int shaderPassID = 0)
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID);
commandBuffer.DrawMesh(GetScreenSpaceTriangle(), Matrix4x4.identity, material, 0, shaderPassID, properties);
RenderTargetIdentifier[] colorBuffers, int shaderPassID = 0)
RenderTargetIdentifier[] colorBuffers,
MaterialPropertyBlock properties = null, int shaderPassID = 0)
DrawFullscreen(commandBuffer, material, camera, colorBuffers, colorBuffers[0], shaderPassID);
DrawFullscreen(commandBuffer, material, camera, colorBuffers, colorBuffers[0], properties, shaderPassID);
}
}
}

151
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader


Shader "Hidden/HDRenderPipeline/CombineSubsurfaceScattering"
{
Properties
{
_FilterWidth("", Float) = 20
_BilateralScale("", Float) = 0.1
[HideInInspector] _DstBlend("", Float) = 1 // Can be set to 1 for blending with specular
}
SubShader
{
Pass
{
Stencil
{
Ref 1 // StencilBits.SSS
Comp Equal
Pass Keep
}
ZTest Always
ZWrite Off
Blend One [_DstBlend]
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma vertex Vert
#pragma fragment Frag
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
//-------------------------------------------------------------------------------------
// Inputs & outputs
//-------------------------------------------------------------------------------------
float _FilterWidth; // Uses world-space units
float _BilateralScale; // Uses world-space units
float _FilterHorizontal; // Vertical = 0, horizontal = 1
float _DistToProjWindow; // The height of the projection window is 2 meters
TEXTURE2D(_CameraDepthTexture);
TEXTURE2D(_IrradianceSource);
SAMPLER2D(sampler_IrradianceSource);
#define bilinearSampler sampler_IrradianceSource
//-------------------------------------------------------------------------------------
// Implementation
//-------------------------------------------------------------------------------------
struct Attributes
{
uint vertexId : SV_VertexID;
};
struct Varyings
{
float4 positionCS : SV_Position;
};
Varyings Vert(Attributes input)
{
Varyings output;
// Generate a triangle in homogeneous clip space, s.t.
// v0 = (-1, -1, 1), v1 = (3, -1, 1), v2 = (-1, 3, 1).
float2 uv = float2((input.vertexId << 1) & 2, input.vertexId & 2);
output.positionCS = float4(uv * 2 - 1, 1, 1);
return output;
}
#define N_SAMPLES 17
static const float4 kernel[] = {
float4(0.536343, 0.624624, 0.748867, 0),
float4(0.00317394, 0.000134823, 3.77269e-005, -2),
float4(0.0100386, 0.000914679, 0.000275702, -1.53125),
float4(0.0144609, 0.00317269, 0.00106399, -1.125),
float4(0.0216301, 0.00794618, 0.00376991, -0.78125),
float4(0.0347317, 0.0151085, 0.00871983, -0.5),
float4(0.0571056, 0.0287432, 0.0172844, -0.28125),
float4(0.0582416, 0.0659959, 0.0411329, -0.125),
float4(0.0324462, 0.0656718, 0.0532821, -0.03125),
float4(0.0324462, 0.0656718, 0.0532821, 0.03125),
float4(0.0582416, 0.0659959, 0.0411329, 0.125),
float4(0.0571056, 0.0287432, 0.0172844, 0.28125),
float4(0.0347317, 0.0151085, 0.00871983, 0.5),
float4(0.0216301, 0.00794618, 0.00376991, 0.78125),
float4(0.0144609, 0.00317269, 0.00106399, 1.125),
float4(0.0100386, 0.000914679, 0.000275702, 1.53125),
float4(0.00317394, 0.000134823, 3.77269e-005, 2),
};
float4 Frag(Varyings input) : SV_Target
{
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float rawDepth = LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r;
float cDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
float widthScale = _FilterWidth * _DistToProjWindow / cDepth;
// Compute the filtering direction.
float2 unitDirection = _FilterHorizontal ? float2(1, 0) : float2(0, 1);
float2 scaledDirection = widthScale * unitDirection;
// Premultiply with the inverse of the screen size.
scaledDirection *= _ScreenSize.zw;
// Take the first (central) sample.
float3 sWeight = kernel[0].rgb;
float2 sPosition = posInput.unPositionSS;
float3 sIrradiance = LOAD_TEXTURE2D(_IrradianceSource, sPosition).rgb;
float3 cIrradiance = sIrradiance;
// Accumulate filtered irradiance (already weighted by (albedo / Pi)).
float3 filteredIrradiance = sIrradiance * sWeight;
[unroll]
for (int i = 1; i < N_SAMPLES; i++)
{
sWeight = kernel[i].rgb;
sPosition = posInput.positionSS + scaledDirection * kernel[i].a;
sIrradiance = SAMPLE_TEXTURE2D_LOD(_IrradianceSource, bilinearSampler, sPosition, 0).rgb;
rawDepth = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, bilinearSampler, sPosition, 0).r;
// Apply bilateral filtering.
float sDepth = LinearEyeDepth(rawDepth, _ZBufferParams);
float dDepth = abs(sDepth - cDepth);
float dScale = _FilterWidth * _DistToProjWindow * _BilateralScale;
float t = saturate(dScale * dDepth);
filteredIrradiance += lerp(sIrradiance, cIrradiance, t) * sWeight;
}
return float4(false ? cIrradiance : filteredIrradiance, 1.0);
}
ENDHLSL
}
}
Fallback Off
}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader.meta


fileFormatVersion: 2
guid: 867b36db983aa0548889a66f8d685ff6
timeCreated: 1485184880
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

26
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.compute


#include "Common.hlsl"
uint screenWidth, screenHeight;
RWTexture2D<float3> diffuseFilterSource;
RWTexture2D<float4> specularSourceAndColorTarget;
#define GROUP_SIZE 256
#pragma kernel FilterHorizontalAndCombine
[numthreads(GROUP_SIZE, 1, 1)]
void FilterHorizontalAndCombine(uint3 threadID : SV_DispatchThreadID)
{
uint2 screenPos = threadID.xy;
if (screenPos.x >= screenWidth || screenPos.y >= screenHeight) return;
float3 diffuseLighting = diffuseFilterSource[screenPos];
float4 specularLighting = specularSourceAndColorTarget[screenPos];
float3 color = specularLighting.rgb + diffuseLighting;
float alpha = specularLighting.a;
specularSourceAndColorTarget[screenPos] = float4(color, alpha);
}

9
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.compute.meta


fileFormatVersion: 2
guid: 7b82788b274d2e64f8516c36e42d2a6a
timeCreated: 1485165439
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存