GitHub
6 年前
当前提交
1d71d3d6
共有 27 个文件被更改,包括 2773 次插入 和 3188 次删除
-
998TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png
-
6TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png.meta
-
999TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png
-
17TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png.meta
-
998TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png
-
6TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png.meta
-
999TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png
-
6TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png.meta
-
998TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png
-
6TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png.meta
-
6com.unity.render-pipelines.core/CoreRP/Textures/DepthBits.cs
-
3com.unity.render-pipelines.high-definition/CHANGELOG.md
-
4com.unity.render-pipelines.high-definition/HDRP/Camera/HDCameraFrameHistoryType.cs
-
1com.unity.render-pipelines.high-definition/HDRP/Lighting/Reflection/PlanarReflectionProbeCache.cs
-
83com.unity.render-pipelines.high-definition/HDRP/Material/GGXConvolution/RuntimeFilterIBL.cs
-
2com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDCustomSamplerId.cs
-
114com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs
-
5com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDStringConstants.cs
-
9com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ApplyDistorsion.compute
-
58com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/ColorPyramid.compute
-
62com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/DepthPyramid.compute
-
136com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs
-
11com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/MipGenerator.cs.meta
-
11com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramid.cs.meta
-
176com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramid.cs
-
11com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs.meta
-
236com.unity.render-pipelines.high-definition/HDRP/RenderPipelineResources/BufferPyramidProcessor.cs
998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1101_Unlit.png
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
999
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1102_Unlit_Distortion.png
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1103_Unlit_Distortion_DepthTest.png
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
999
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1205_Lit_Transparent_Refraction.png
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
998
TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Direct3D11/1206_Lit_Transparent_Distortion.png
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
using UnityEngine.Serialization; |
|||
|
|||
DepthPyramid, |
|||
ColorPyramid, |
|||
VolumetricLighting, |
|||
Count |
|||
} |
|
|||
#include "CoreRP/ShaderLibrary/Common.hlsl" |
|||
|
|||
// ------------------------------------------------ |
|||
// Algorithm |
|||
// ------------------------------------------------ |
|||
// Downsample a depth texture by taking min value of sampled pixels |
|||
|
|||
// ------------------------------------------------ |
|||
// Variants |
|||
// ------------------------------------------------ |
|||
|
|||
#pragma kernel KDepthDownSample8 KERNEL_SIZE=8 KERNEL_NAME=KDepthDownSample8 |
|||
#pragma kernel KDepthDownSample1 KERNEL_SIZE=1 KERNEL_NAME=KDepthDownSample1 |
|||
|
|||
// ------------------------------------------------ |
|||
// Texture buffers |
|||
// ------------------------------------------------ |
|||
#pragma kernel KDepthDownsample8DualUav KERNEL_SIZE=8 KERNEL_NAME=KDepthDownsample8DualUav |
|||
Texture2D<float2> _Source; |
|||
RW_TEXTURE2D(float2, _Result); |
|||
|
|||
SamplerState sampler_PointClamp; //TODO: could we use min-sampler instead of using ALU? |
|||
RW_TEXTURE2D(float, _Destination); |
|||
RW_TEXTURE2D(float, _Source); |
|||
// ------------------------------------------------ |
|||
// Constant buffers |
|||
// ------------------------------------------------ |
|||
float4 _SrcSize; |
|||
int2 _RectOffset; // Offset in source texture |
|||
float4 _Size; // x: src width, y: src height, zw: unused |
|||
// ------------------------------------------------ |
|||
// Kernel |
|||
// ------------------------------------------------ |
|||
|
|||
# define MAX_DEPTH(l, r) min(l, r) |
|||
# define MAX_DEPTH(l, r) max(l, r) |
|||
// Downsample a depth texture by taking the min value of sampled pixels |
|||
// The size of the dispatch is (DstMipSize / KernelSize). |
|||
void KERNEL_NAME(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID) |
|||
void KERNEL_NAME(uint2 dispatchThreadId : SV_DispatchThreadID) |
|||
uint2 srcPixelUL = _RectOffset + (dispatchThreadId << 1); |
|||
// Offset by 0.5 so sampling get the proper pixels |
|||
float2 offset = float2(srcPixelUL) + 0.5; |
|||
uint2 srcPixelUL = dispatchThreadId << 1; |
|||
#if defined(PLATFORM_SUPPORT_GATHER) |
|||
float4 depths = GATHER_RED_TEXTURE2D(_Source, sampler_PointClamp, offset * _SrcSize.zw).wzxy; |
|||
#else |
|||
float p00 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset) * _SrcSize.zw, 0.0).x; |
|||
float p10 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(1.0, 0.0)) * _SrcSize.zw, 0.0).x; |
|||
float p01 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(0.0, 1.0)) * _SrcSize.zw, 0.0).x; |
|||
float p11 = SAMPLE_TEXTURE2D_LOD(_Source, sampler_PointClamp, (offset + float2(1.0, 1.0)) * _SrcSize.zw, 0.0).x; |
|||
// '_Source' and '_Destination' are two different MIP levels of the same texture. |
|||
// TODO: Use Gather here instead of 4 loads |
|||
uint2 size = uint2(_Size.xy) - 1u; |
|||
float p00 = _Source[min(srcPixelUL + uint2(0u, 0u), size)]; |
|||
float p10 = _Source[min(srcPixelUL + uint2(1u, 0u), size)]; |
|||
float p01 = _Source[min(srcPixelUL + uint2(0u, 1u), size)]; |
|||
float p11 = _Source[min(srcPixelUL + uint2(1u, 1u), size)]; |
|||
#endif |
|||
float maxDepth = MAX_DEPTH(MAX_DEPTH(depths.x, depths.y), MAX_DEPTH(depths.z, depths.w)); |
|||
uint2 dstPixel = (_RectOffset >> 1) + dispatchThreadId; |
|||
_Result[dstPixel] = float2(minDepth, maxDepth); |
|||
_Destination[dispatchThreadId] = minDepth; |
|||
#undef MAX_DEPTH |
|
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
using RTHandle = RTHandleSystem.RTHandle; |
|||
|
|||
public class MipGenerator |
|||
{ |
|||
RTHandle m_TempColorTarget; |
|||
|
|||
ComputeShader m_DepthPyramidCS; |
|||
ComputeShader m_ColorPyramidCS; |
|||
|
|||
int m_DepthDownsampleKernel; |
|||
int m_ColorDownsampleKernel; |
|||
int m_ColorDownsampleKernelCopyMip0; |
|||
int m_ColorGaussianKernel; |
|||
|
|||
public MipGenerator(HDRenderPipelineAsset asset) |
|||
{ |
|||
m_DepthPyramidCS = asset.renderPipelineResources.depthPyramidCS; |
|||
m_ColorPyramidCS = asset.renderPipelineResources.colorPyramidCS; |
|||
|
|||
m_DepthDownsampleKernel = m_DepthPyramidCS.FindKernel("KDepthDownsample8DualUav"); |
|||
m_ColorDownsampleKernel = m_ColorPyramidCS.FindKernel("KColorDownsample"); |
|||
m_ColorDownsampleKernelCopyMip0 = m_ColorPyramidCS.FindKernel("KColorDownsampleCopyMip0"); |
|||
m_ColorGaussianKernel = m_ColorPyramidCS.FindKernel("KColorGaussian"); |
|||
} |
|||
|
|||
public void Release() |
|||
{ |
|||
RTHandles.Release(m_TempColorTarget); |
|||
m_TempColorTarget = null; |
|||
} |
|||
|
|||
// Generates an in-place depth pyramid
|
|||
// Returns the number of generated mips
|
|||
// TODO: Mip-mapping depth is problematic for precision at lower mips, generate a packed atlas instead
|
|||
public int RenderMinDepthPyramid(CommandBuffer cmd, Vector2Int size, RenderTexture texture) |
|||
{ |
|||
var cs = m_DepthPyramidCS; |
|||
int kernel = m_DepthDownsampleKernel; |
|||
int srcMipLevel = 0; |
|||
int srcMipWidth = size.x; |
|||
int srcMipHeight = size.y; |
|||
|
|||
// TODO: Do it 1x MIP at a time for now. In the future, do 4x MIPs per pass, or even use a single pass.
|
|||
// Note: Gather() doesn't take a LOD parameter and we cannot bind an SRV of a MIP level,
|
|||
// and we don't support Min samplers either. So we are forced to perform 4x loads.
|
|||
while (srcMipWidth >= 2 || srcMipHeight >= 2) |
|||
{ |
|||
int dstMipWidth = Mathf.Max(1, srcMipWidth >> 1); |
|||
int dstMipHeight = Mathf.Max(1, srcMipHeight >> 1); |
|||
|
|||
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(srcMipWidth, srcMipHeight, 0f, 0f)); |
|||
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._Source, texture, srcMipLevel); |
|||
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._Destination, texture, srcMipLevel + 1); |
|||
cmd.DispatchCompute(cs, kernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1); |
|||
|
|||
srcMipLevel++; |
|||
srcMipWidth = srcMipWidth >> 1; |
|||
srcMipHeight = srcMipHeight >> 1; |
|||
} |
|||
|
|||
return srcMipLevel - 1; |
|||
} |
|||
|
|||
// Generates the gaussian pyramid of source into destination
|
|||
// We can't do it in place as the color pyramid has to be read while writing to the color
|
|||
// buffer in some cases (e.g. refraction, distortion)
|
|||
// Returns the number of mips
|
|||
public int RenderColorGaussianPyramid(CommandBuffer cmd, Vector2Int size, Texture source, RenderTexture destination) |
|||
{ |
|||
// Only create the temporary target on-demand in case the game doesn't actually need it
|
|||
if (m_TempColorTarget == null) |
|||
{ |
|||
m_TempColorTarget = RTHandles.Alloc( |
|||
Vector2.one * 0.5f, |
|||
filterMode: FilterMode.Bilinear, |
|||
colorFormat: RenderTextureFormat.ARGBHalf, |
|||
sRGB: false, |
|||
enableRandomWrite: true, |
|||
useMipMap: false, |
|||
enableMSAA: false, |
|||
name: "Temp Gaussian Pyramid Target" |
|||
); |
|||
} |
|||
|
|||
var cs = m_ColorPyramidCS; |
|||
int downsampleKernel = m_ColorDownsampleKernel; |
|||
int downsampleKernelMip0 = m_ColorDownsampleKernelCopyMip0; |
|||
int gaussianKernel = m_ColorGaussianKernel; |
|||
int srcMipLevel = 0; |
|||
int srcMipWidth = size.x; |
|||
int srcMipHeight = size.y; |
|||
|
|||
|
|||
// Note: smaller mips are excluded as we don't need them and the gaussian compute works
|
|||
// on 8x8 blocks
|
|||
// TODO: Could be further optimized by merging the smaller mips to reduce the amount of dispatches
|
|||
while (srcMipWidth >= 8 || srcMipHeight >= 8) |
|||
{ |
|||
int dstMipWidth = Mathf.Max(1, srcMipWidth >> 1); |
|||
int dstMipHeight = Mathf.Max(1, srcMipHeight >> 1); |
|||
|
|||
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(srcMipWidth, srcMipHeight, 0f, 0f)); |
|||
|
|||
// First dispatch also copies src to dst mip0
|
|||
if (srcMipLevel == 0) |
|||
{ |
|||
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Source, source, 0); |
|||
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Mip0, destination, 0); |
|||
cmd.SetComputeTextureParam(cs, downsampleKernelMip0, HDShaderIDs._Destination, m_TempColorTarget); |
|||
cmd.DispatchCompute(cs, downsampleKernelMip0, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1); |
|||
} |
|||
else |
|||
{ |
|||
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Source, destination, srcMipLevel); |
|||
cmd.SetComputeTextureParam(cs, downsampleKernel, HDShaderIDs._Destination, m_TempColorTarget); |
|||
cmd.DispatchCompute(cs, downsampleKernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1); |
|||
} |
|||
|
|||
cmd.SetComputeVectorParam(cs, HDShaderIDs._Size, new Vector4(dstMipWidth, dstMipHeight, 0f, 0f)); |
|||
cmd.SetComputeTextureParam(cs, gaussianKernel, HDShaderIDs._Source, m_TempColorTarget); |
|||
cmd.SetComputeTextureParam(cs, gaussianKernel, HDShaderIDs._Destination, destination, srcMipLevel + 1); |
|||
cmd.DispatchCompute(cs, gaussianKernel, (dstMipWidth + 7) / 8, (dstMipHeight + 7) / 8, 1); |
|||
|
|||
srcMipLevel++; |
|||
srcMipWidth = srcMipWidth >> 1; |
|||
srcMipHeight = srcMipHeight >> 1; |
|||
} |
|||
|
|||
return srcMipLevel - 1; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9fb5527a68d5789439b1caea92b87bdf |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: ea3e7945ee7dc7a479b9e6846a0c544c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
class BufferPyramid |
|||
{ |
|||
List<RTHandleSystem.RTHandle> m_ColorPyramidMips = new List<RTHandleSystem.RTHandle>(); |
|||
List<RTHandleSystem.RTHandle> m_DepthPyramidMips = new List<RTHandleSystem.RTHandle>(); |
|||
|
|||
BufferPyramidProcessor m_Processor; |
|||
|
|||
public BufferPyramid(BufferPyramidProcessor processor) |
|||
{ |
|||
m_Processor = processor; |
|||
} |
|||
|
|||
float GetXRscale() |
|||
{ |
|||
// for stereo double-wide, each half of the texture will represent a single eye's pyramid
|
|||
float scale = 1.0f; |
|||
//if (m_Asset.renderPipelineSettings.supportsStereo && (desc.dimension != TextureDimension.Tex2DArray))
|
|||
// scale = 2.0f; // double-wide
|
|||
return scale; |
|||
} |
|||
|
|||
public void DestroyBuffers() |
|||
{ |
|||
foreach (var rth in m_ColorPyramidMips) |
|||
RTHandles.Release(rth); |
|||
|
|||
foreach (var rth in m_DepthPyramidMips) |
|||
RTHandles.Release(rth); |
|||
} |
|||
|
|||
public int GetPyramidLodCount(Vector2Int size) |
|||
{ |
|||
var minSize = Mathf.Min(size.x, size.y); |
|||
return Mathf.Max(0, Mathf.FloorToInt(Mathf.Log(minSize, 2f))); |
|||
} |
|||
|
|||
Vector2Int CalculatePyramidMipSize(Vector2Int baseMipSize, int mipIndex) |
|||
{ |
|||
return new Vector2Int(baseMipSize.x >> mipIndex, baseMipSize.y >> mipIndex); |
|||
} |
|||
|
|||
Vector2Int CalculatePyramidSize(Vector2Int size) |
|||
{ |
|||
// Instead of using the screen size, we round up to the next power of 2 because currently some platforms don't support NPOT Render Texture with mip maps (PS4 for example)
|
|||
// Then we render in a Screen Sized viewport.
|
|||
// Note that even if PS4 supported POT Mips, the buffers would be padded to the next power of 2 anyway (TODO: check with other platforms...)
|
|||
int pyramidSize = (int)Mathf.NextPowerOfTwo(Mathf.Max(size.x, size.y)); |
|||
return new Vector2Int((int)(pyramidSize * GetXRscale()), pyramidSize); |
|||
} |
|||
|
|||
void UpdatePyramidMips(HDCamera camera, RenderTextureFormat format, List<RTHandleSystem.RTHandle> mipList, int lodCount) |
|||
{ |
|||
int currentLodCount = mipList.Count; |
|||
if (lodCount > currentLodCount) |
|||
{ |
|||
for (int i = currentLodCount; i < lodCount; ++i) |
|||
{ |
|||
int mipIndexCopy = i + 1; // Don't remove this copy! It's important for the value to be correctly captured by the lambda.
|
|||
var newMip = RTHandles.Alloc(size => CalculatePyramidMipSize(CalculatePyramidSize(size), mipIndexCopy), colorFormat: format, sRGB: false, enableRandomWrite: true, useMipMap: false, filterMode: FilterMode.Bilinear, name: string.Format("PyramidMip{0}", i)); |
|||
mipList.Add(newMip); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Vector2 GetPyramidToScreenScale(HDCamera camera, RTHandleSystem.RTHandle rth) |
|||
{ |
|||
return new Vector2((float)camera.actualWidth / rth.rt.width, (float)camera.actualHeight / rth.rt.height); |
|||
} |
|||
|
|||
public void RenderDepthPyramid( |
|||
HDCamera hdCamera, |
|||
CommandBuffer cmd, |
|||
ScriptableRenderContext renderContext, |
|||
RTHandleSystem.RTHandle sourceDepthTexture, |
|||
RTHandleSystem.RTHandle targetDepthTexture) |
|||
{ |
|||
int lodCount = Mathf.Min( |
|||
GetPyramidLodCount(targetDepthTexture.referenceSize), |
|||
GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight)) |
|||
); |
|||
if (lodCount == 0) |
|||
{ |
|||
Debug.LogWarning("The target for the pyramid buffer has an invalid size. Skipping DepthPyramid calculation."); |
|||
return; |
|||
} |
|||
|
|||
UpdatePyramidMips(hdCamera, targetDepthTexture.rt.format, m_DepthPyramidMips, lodCount); |
|||
|
|||
Vector2 scale = GetPyramidToScreenScale(hdCamera, targetDepthTexture); |
|||
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight)); |
|||
cmd.SetGlobalVector(HDShaderIDs._DepthPyramidScale, new Vector4(scale.x, scale.y, lodCount, 0.0f)); |
|||
|
|||
m_Processor.RenderDepthPyramid( |
|||
hdCamera.actualWidth, hdCamera.actualHeight, |
|||
cmd, |
|||
sourceDepthTexture, |
|||
targetDepthTexture, |
|||
m_DepthPyramidMips, |
|||
lodCount, |
|||
scale |
|||
); |
|||
|
|||
cmd.SetGlobalTexture(HDShaderIDs._DepthPyramidTexture, targetDepthTexture); |
|||
} |
|||
|
|||
public void RenderColorPyramid( |
|||
HDCamera hdCamera, |
|||
CommandBuffer cmd, |
|||
ScriptableRenderContext renderContext, |
|||
RTHandleSystem.RTHandle sourceColorTexture, |
|||
RTHandleSystem.RTHandle targetColorTexture) |
|||
{ |
|||
int lodCount = Mathf.Min( |
|||
GetPyramidLodCount(targetColorTexture.referenceSize), |
|||
GetPyramidLodCount(new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight)) |
|||
); |
|||
if (lodCount == 0) |
|||
{ |
|||
Debug.LogWarning("The target for the pyramid buffer has an invalid size. Skipping ColorPyramid calculation."); |
|||
return; |
|||
} |
|||
|
|||
UpdatePyramidMips(hdCamera, targetColorTexture.rt.format, m_ColorPyramidMips, lodCount); |
|||
|
|||
Vector2 scale = GetPyramidToScreenScale(hdCamera, targetColorTexture); |
|||
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidSize, new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1f / hdCamera.actualWidth, 1f / hdCamera.actualHeight)); |
|||
cmd.SetGlobalVector(HDShaderIDs._ColorPyramidScale, new Vector4(scale.x, scale.y, lodCount, 0.0f)); |
|||
|
|||
m_Processor.RenderColorPyramid( |
|||
hdCamera, |
|||
cmd, |
|||
sourceColorTexture, |
|||
targetColorTexture, |
|||
m_ColorPyramidMips, |
|||
lodCount, |
|||
scale |
|||
); |
|||
|
|||
cmd.SetGlobalTexture(HDShaderIDs._ColorPyramidTexture, targetColorTexture); |
|||
} |
|||
|
|||
public RTHandleSystem.RTHandle AllocColorRT(string id, int frameIndex, RTHandleSystem rtHandleSystem) |
|||
{ |
|||
return rtHandleSystem.Alloc( |
|||
size => CalculatePyramidSize(size), |
|||
filterMode: FilterMode.Trilinear, |
|||
colorFormat: RenderTextureFormat.ARGBHalf, |
|||
sRGB: false, |
|||
useMipMap: true, |
|||
autoGenerateMips: false, |
|||
enableRandomWrite: true, |
|||
name: string.Format("ColorPyramid-{0}-{1}", id, frameIndex) |
|||
); |
|||
} |
|||
|
|||
public RTHandleSystem.RTHandle AllocDepthRT(string id, int frameIndex, RTHandleSystem rtHandleSystem) |
|||
{ |
|||
return rtHandleSystem.Alloc( |
|||
size => CalculatePyramidSize(size), |
|||
filterMode: FilterMode.Trilinear, |
|||
colorFormat: RenderTextureFormat.RGFloat, |
|||
sRGB: false, |
|||
useMipMap: true, |
|||
autoGenerateMips: false, |
|||
enableRandomWrite: true, // Need randomReadWrite because we downsample the first mip with a compute shader.
|
|||
name: string.Format("DepthPyramid-{0}-{1}", id, frameIndex) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5555ed542465a3a42aa9f58eccc62c68 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine.Assertions; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
public class BufferPyramidProcessor |
|||
{ |
|||
static readonly int _Size = Shader.PropertyToID("_Size"); |
|||
static readonly int _Source = Shader.PropertyToID("_Source"); |
|||
static readonly int _Result = Shader.PropertyToID("_Result"); |
|||
static readonly int _SrcSize = Shader.PropertyToID("_SrcSize"); |
|||
const int k_DepthBlockSize = 4; |
|||
|
|||
GPUCopy m_GPUCopy; |
|||
TexturePadding m_TexturePadding; |
|||
ComputeShader m_ColorPyramidCS; |
|||
int m_ColorPyramidKernel; |
|||
|
|||
ComputeShader m_DepthPyramidCS; |
|||
int[] m_DepthKernels = null; |
|||
int depthKernel8 { get { return m_DepthKernels[0]; } } |
|||
int depthKernel1 { get { return m_DepthKernels[1]; } } |
|||
|
|||
List<RenderTexture> m_RenderColorPyramid_CastTmp = new List<RenderTexture>(); |
|||
|
|||
public BufferPyramidProcessor( |
|||
ComputeShader colorPyramidCS, |
|||
ComputeShader depthPyramidCS, |
|||
GPUCopy gpuCopy, |
|||
TexturePadding texturePadding |
|||
) |
|||
{ |
|||
m_ColorPyramidCS = colorPyramidCS; |
|||
m_ColorPyramidKernel = m_ColorPyramidCS.FindKernel("KMain"); |
|||
|
|||
m_DepthPyramidCS = depthPyramidCS; |
|||
m_GPUCopy = gpuCopy; |
|||
m_DepthKernels = new int[] |
|||
{ |
|||
m_DepthPyramidCS.FindKernel("KDepthDownSample8"), |
|||
m_DepthPyramidCS.FindKernel("KDepthDownSample1") |
|||
}; |
|||
|
|||
m_TexturePadding = texturePadding; |
|||
} |
|||
|
|||
public void RenderDepthPyramid( |
|||
int width, int height, |
|||
CommandBuffer cmd, |
|||
RTHandleSystem.RTHandle sourceTexture, |
|||
RTHandleSystem.RTHandle targetTexture, |
|||
List<RTHandleSystem.RTHandle> mips, |
|||
int lodCount, |
|||
Vector2 scale |
|||
) |
|||
{ |
|||
m_GPUCopy.SampleCopyChannel_xyzw2x(cmd, sourceTexture, targetTexture, new RectInt(0, 0, width, height)); |
|||
|
|||
var src = targetTexture; |
|||
for (var i = 0; i < lodCount; i++) |
|||
{ |
|||
var dest = mips[i]; |
|||
|
|||
var srcMip = new RectInt(0, 0, width >> i, height >> i); |
|||
var dstMip = new RectInt(0, 0, srcMip.width >> 1, srcMip.height >> 1); |
|||
|
|||
var kernel = depthKernel1; |
|||
var kernelSize = 1; |
|||
var srcWorkMip = srcMip; |
|||
var dstWorkMip = dstMip; |
|||
|
|||
if (dstWorkMip.width >= 8 && dstWorkMip.height >= 8) |
|||
{ |
|||
srcWorkMip.width = Mathf.CeilToInt(srcWorkMip.width / 16.0f) * 16; |
|||
srcWorkMip.height = Mathf.CeilToInt(srcWorkMip.height / 16.0f) * 16; |
|||
dstWorkMip.width = srcWorkMip.width >> 1; |
|||
dstWorkMip.height = srcWorkMip.height >> 1; |
|||
|
|||
m_TexturePadding.Pad(cmd, src, srcMip, srcWorkMip); |
|||
kernel = depthKernel8; |
|||
kernelSize = 8; |
|||
} |
|||
else |
|||
{ |
|||
m_TexturePadding.Pad(cmd, src, srcMip, new RectInt(0, 0, src.rt.width, src.rt.height)); |
|||
} |
|||
|
|||
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Source, src); |
|||
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Result, dest); |
|||
// The compute shader work in texture space
|
|||
// So we must provide the texture's size
|
|||
cmd.SetComputeVectorParam(m_DepthPyramidCS, _SrcSize, new Vector4( |
|||
src.rt.width, src.rt.height, |
|||
(1.0f / src.rt.width), (1.0f / src.rt.height)) |
|||
); |
|||
|
|||
cmd.DispatchCompute( |
|||
m_DepthPyramidCS, |
|||
kernel, |
|||
Mathf.CeilToInt(dstWorkMip.width / (float)kernelSize), |
|||
Mathf.CeilToInt(dstWorkMip.height / (float)kernelSize), |
|||
1 |
|||
); |
|||
|
|||
var dstMipWidthToCopy = Mathf.Min(Mathf.Min(targetTexture.rt.width >> (i + 1), dstWorkMip.width), mips[i].rt.width); |
|||
var dstMipHeightToCopy = Mathf.Min(Mathf.Min(targetTexture.rt.height >> (i + 1), dstWorkMip.height), mips[i].rt.height); |
|||
|
|||
// If we could bind texture mips as UAV we could avoid this copy...(which moreover copies more than the needed viewport if not fullscreen)
|
|||
cmd.CopyTexture(mips[i], 0, 0, 0, 0, dstMipWidthToCopy, dstMipHeightToCopy, targetTexture, 0, i + 1, 0, 0); |
|||
src = dest; |
|||
} |
|||
} |
|||
|
|||
public void RenderColorPyramid( |
|||
HDCamera hdCamera, |
|||
CommandBuffer cmd, |
|||
RTHandleSystem.RTHandle sourceTexture, |
|||
RTHandleSystem.RTHandle targetTexture, |
|||
List<RTHandleSystem.RTHandle> mips, |
|||
int lodCount, |
|||
Vector2 scale |
|||
) |
|||
{ |
|||
// Copy mip 0
|
|||
// Here we blit a "camera space" texture into a square texture but we want to keep the original viewport.
|
|||
// Other BlitCameraTexture version will setup the viewport based on the destination RT scale (square here) so we need override it here.
|
|||
HDUtils.BlitCameraTexture(cmd, hdCamera, sourceTexture, targetTexture, new Rect(0.0f, 0.0f, hdCamera.actualWidth, hdCamera.actualHeight)); |
|||
|
|||
m_RenderColorPyramid_CastTmp.Clear(); |
|||
for (var i = 0; i < mips.Count; ++i) |
|||
m_RenderColorPyramid_CastTmp.Add(mips[i]); |
|||
RenderColorPyramidMips( |
|||
new RectInt(0, 0, hdCamera.actualWidth, hdCamera.actualHeight), |
|||
cmd, |
|||
targetTexture, |
|||
m_RenderColorPyramid_CastTmp, |
|||
lodCount, |
|||
scale |
|||
); |
|||
} |
|||
|
|||
public void RenderColorPyramid( |
|||
RectInt srcRect, |
|||
CommandBuffer cmd, |
|||
Texture sourceTexture, |
|||
RenderTexture targetTexture, |
|||
List<RenderTexture> mips, |
|||
int lodCount |
|||
) |
|||
{ |
|||
Assert.AreEqual(0, srcRect.x, "Offset are not supported"); |
|||
Assert.AreEqual(0, srcRect.y, "Offset are not supported"); |
|||
Assert.IsTrue(srcRect.width > 0); |
|||
Assert.IsTrue(srcRect.height > 0); |
|||
|
|||
var scale = new Vector2( |
|||
sourceTexture.width / (float)srcRect.width, |
|||
sourceTexture.height / (float)srcRect.height |
|||
); |
|||
|
|||
cmd.Blit(sourceTexture, targetTexture, scale, Vector2.zero); |
|||
|
|||
RenderColorPyramidMips( |
|||
srcRect, |
|||
cmd, |
|||
targetTexture, |
|||
mips, |
|||
lodCount, |
|||
scale |
|||
); |
|||
} |
|||
|
|||
void RenderColorPyramidMips( |
|||
RectInt srcRect, |
|||
CommandBuffer cmd, |
|||
RenderTexture targetTexture, |
|||
List<RenderTexture> mips, |
|||
int lodCount, |
|||
Vector2 scale |
|||
) |
|||
{ |
|||
Assert.AreEqual(0, srcRect.x, "Offset are not supported"); |
|||
Assert.AreEqual(0, srcRect.y, "Offset are not supported"); |
|||
Assert.IsTrue(srcRect.width > 0); |
|||
Assert.IsTrue(srcRect.height > 0); |
|||
|
|||
var src = targetTexture; |
|||
for (var i = 0; i < lodCount; i++) |
|||
{ |
|||
var dest = mips[i]; |
|||
|
|||
var srcMip = new RectInt(0, 0, srcRect.width >> i, srcRect.height >> i); |
|||
var srcWorkMip = new RectInt( |
|||
0, |
|||
0, |
|||
Mathf.CeilToInt(srcMip.width / 16.0f) * 16, |
|||
Mathf.CeilToInt(srcMip.height / 16.0f) * 16 |
|||
); |
|||
var dstWorkMip = new RectInt(0, 0, srcWorkMip.width >> 1, srcWorkMip.height >> 1); |
|||
|
|||
m_TexturePadding.Pad(cmd, src, srcMip, srcWorkMip); |
|||
|
|||
// TODO: Add proper stereo support to the compute job
|
|||
|
|||
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Source, src); |
|||
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Result, dest); |
|||
// _Size is used as a scale inside the whole render target so here we need to keep the full size (and not the scaled size depending on the current camera)
|
|||
cmd.SetComputeVectorParam( |
|||
m_ColorPyramidCS, |
|||
_Size, |
|||
new Vector4(src.width >> 1, src.height >> 1, 1f / (src.width >> 1), 1f / (src.height >> 1)) |
|||
); |
|||
cmd.DispatchCompute( |
|||
m_ColorPyramidCS, |
|||
m_ColorPyramidKernel, |
|||
dstWorkMip.width / 8, |
|||
dstWorkMip.height / 8, |
|||
1 |
|||
); |
|||
|
|||
var dstMipWidthToCopy = Mathf.Min(Mathf.Min(targetTexture.width >> (i + 1), dstWorkMip.width), mips[i].width); |
|||
var dstMipHeightToCopy = Mathf.Min(Mathf.Min(targetTexture.height >> (i + 1), dstWorkMip.height), mips[i].height); |
|||
|
|||
// If we could bind texture mips as UAV we could avoid this copy...(which moreover copies more than the needed viewport if not fullscreen)
|
|||
cmd.CopyTexture( |
|||
mips[i], |
|||
0, 0, 0, 0, |
|||
dstMipWidthToCopy, dstMipHeightToCopy, targetTexture, 0, i + 1, 0, 0 |
|||
); |
|||
|
|||
src = dest; |
|||
} |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue