浏览代码
Merge pull request #892 from Unity-Technologies/feature/ReflectionRefraction
Merge pull request #892 from Unity-Technologies/feature/ReflectionRefraction
Use fullscreen depth/color pyramids/main
GitHub
7 年前
当前提交
9f5cddad
共有 12 个文件被更改,包括 476 次插入 和 178 次删除
-
15ScriptableRenderPipeline/Core/CoreRP/Debugging/DebugItemHandler.cs
-
61ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs
-
4ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/HDAssetFactory.cs
-
190ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/HDRenderPipelineResources.asset
-
9ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/DepthPyramid.compute
-
209ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/BufferPyramid.cs
-
11ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/BufferPyramid.cs.meta
-
144ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/ColorPyramid.compute
-
9ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/ColorPyramid.compute.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/DepthPyramid.compute.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/DepthPyramid.compute
|
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
class BufferPyramid |
|||
{ |
|||
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; |
|||
ComputeShader m_ColorPyramidCS; |
|||
|
|||
RenderTextureDescriptor m_ColorRenderTextureDescriptor; |
|||
int[] m_ColorPyramidMips = new int[0]; |
|||
int m_ColorPyramidKernel; |
|||
|
|||
ComputeShader m_DepthPyramidCS; |
|||
RenderTextureDescriptor m_DepthRenderTextureDescriptor; |
|||
int[] m_DepthPyramidMips = new int[0]; |
|||
int m_DepthPyramidKernel_8; |
|||
int m_DepthPyramidKernel_1; |
|||
|
|||
public RenderTextureDescriptor colorRenderTextureDescriptor { get { return m_ColorRenderTextureDescriptor; } } |
|||
public int colorUsedMipMapCount { get { return Mathf.Min(colorBufferMipMapCount, m_ColorPyramidMips.Length); } } |
|||
public int colorBufferMipMapCount |
|||
{ |
|||
get |
|||
{ |
|||
var minSize = Mathf.Min(colorRenderTextureDescriptor.width, colorRenderTextureDescriptor.height); |
|||
return Mathf.FloorToInt(Mathf.Log(minSize, 2f)); |
|||
} |
|||
} |
|||
|
|||
public RenderTextureDescriptor depthRenderTextureDescriptor { get { return m_DepthRenderTextureDescriptor; } } |
|||
public int depthUsedMipMapCount { get { return Mathf.Min(depthBufferMipMapCount, m_DepthPyramidMips.Length); } } |
|||
public int depthBufferMipMapCount |
|||
{ |
|||
get |
|||
{ |
|||
var minSize = Mathf.Min(depthRenderTextureDescriptor.width, depthRenderTextureDescriptor.height); |
|||
return Mathf.FloorToInt(Mathf.Log(minSize, 2f)); |
|||
} |
|||
} |
|||
|
|||
public BufferPyramid( |
|||
ComputeShader colorPyramidCS, int[] colorMipIds, |
|||
ComputeShader depthPyramidCS, GPUCopy gpuCopy, int[] depthMipIds) |
|||
{ |
|||
m_ColorPyramidCS = colorPyramidCS; |
|||
m_ColorPyramidKernel = m_ColorPyramidCS.FindKernel("KMain"); |
|||
m_ColorPyramidMips = colorMipIds; |
|||
|
|||
m_DepthPyramidCS = depthPyramidCS; |
|||
m_GPUCopy = gpuCopy; |
|||
m_DepthPyramidMips = depthMipIds; |
|||
m_DepthPyramidKernel_8 = m_DepthPyramidCS.FindKernel("KMain_8"); |
|||
m_DepthPyramidKernel_1 = m_DepthPyramidCS.FindKernel("KMain_1"); |
|||
} |
|||
|
|||
public void RenderDepthPyramid( |
|||
HDCamera hdCamera, |
|||
CommandBuffer cmd, |
|||
ScriptableRenderContext renderContext, |
|||
RenderTargetIdentifier depthTexture, |
|||
RenderTargetIdentifier targetTexture) |
|||
{ |
|||
var depthPyramidDesc = m_DepthRenderTextureDescriptor; |
|||
|
|||
var lodCount = depthBufferMipMapCount; |
|||
if (lodCount > m_DepthPyramidMips.Length) |
|||
{ |
|||
Debug.LogWarningFormat("Cannot compute all mipmaps of the depth pyramid, max texture size supported: {0}", (2 << m_DepthPyramidMips.Length).ToString()); |
|||
lodCount = m_DepthPyramidMips.Length; |
|||
} |
|||
|
|||
cmd.ReleaseTemporaryRT(m_DepthPyramidMips[0]); |
|||
|
|||
depthPyramidDesc.sRGB = false; |
|||
depthPyramidDesc.enableRandomWrite = true; |
|||
depthPyramidDesc.useMipMap = false; |
|||
|
|||
cmd.GetTemporaryRT(m_DepthPyramidMips[0], depthPyramidDesc, FilterMode.Bilinear); |
|||
m_GPUCopy.SampleCopyChannel_xyzw2x(cmd, depthTexture, m_DepthPyramidMips[0], new Vector2(depthPyramidDesc.width, depthPyramidDesc.height)); |
|||
cmd.CopyTexture(m_DepthPyramidMips[0], 0, 0, targetTexture, 0, 0); |
|||
|
|||
for (var i = 0; i < lodCount; i++) |
|||
{ |
|||
var srcMipWidth = depthPyramidDesc.width; |
|||
var srcMipHeight = depthPyramidDesc.height; |
|||
depthPyramidDesc.width = srcMipWidth >> 1; |
|||
depthPyramidDesc.height = srcMipHeight >> 1; |
|||
|
|||
var kernel = m_DepthPyramidKernel_8; |
|||
var kernelBlockSize = 8f; |
|||
if (depthPyramidDesc.width < 4 * k_DepthBlockSize |
|||
|| depthPyramidDesc.height < 4 * k_DepthBlockSize) |
|||
{ |
|||
kernel = m_DepthPyramidKernel_1; |
|||
kernelBlockSize = 1; |
|||
} |
|||
|
|||
cmd.ReleaseTemporaryRT(m_DepthPyramidMips[i + 1]); |
|||
cmd.GetTemporaryRT(m_DepthPyramidMips[i + 1], depthPyramidDesc, FilterMode.Bilinear); |
|||
|
|||
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Source, m_DepthPyramidMips[i]); |
|||
cmd.SetComputeTextureParam(m_DepthPyramidCS, kernel, _Result, m_DepthPyramidMips[i + 1]); |
|||
cmd.SetComputeVectorParam(m_DepthPyramidCS, _SrcSize, new Vector4(srcMipWidth, srcMipHeight, 1f / srcMipWidth, 1f / srcMipHeight)); |
|||
|
|||
cmd.DispatchCompute( |
|||
m_DepthPyramidCS, |
|||
kernel, |
|||
Mathf.CeilToInt(depthPyramidDesc.width / kernelBlockSize), |
|||
Mathf.CeilToInt(depthPyramidDesc.height / kernelBlockSize), |
|||
1); |
|||
|
|||
cmd.CopyTexture(m_DepthPyramidMips[i + 1], 0, 0, targetTexture, 0, i + 1); |
|||
} |
|||
|
|||
for (int i = 0; i < lodCount + 1; i++) |
|||
cmd.ReleaseTemporaryRT(m_DepthPyramidMips[i]); |
|||
} |
|||
|
|||
public void RenderColorPyramid( |
|||
HDCamera hdCamera, |
|||
CommandBuffer cmd, |
|||
ScriptableRenderContext renderContext, |
|||
RenderTargetIdentifier colorTexture, |
|||
RenderTargetIdentifier targetTexture) |
|||
{ |
|||
var colorPyramidDesc = colorRenderTextureDescriptor; |
|||
|
|||
var lodCount = colorBufferMipMapCount; |
|||
if (lodCount > m_ColorPyramidMips.Length) |
|||
{ |
|||
Debug.LogWarningFormat("Cannot compute all mipmaps of the color pyramid, max texture size supported: {0}", (2 << m_ColorPyramidMips.Length).ToString()); |
|||
lodCount = m_ColorPyramidMips.Length; |
|||
} |
|||
|
|||
// Copy mip 0
|
|||
cmd.CopyTexture(colorTexture, 0, 0, targetTexture, 0, 0); |
|||
var last = colorTexture; |
|||
|
|||
colorPyramidDesc.sRGB = false; |
|||
colorPyramidDesc.enableRandomWrite = true; |
|||
colorPyramidDesc.useMipMap = false; |
|||
|
|||
for (var i = 0; i < lodCount; i++) |
|||
{ |
|||
colorPyramidDesc.width = colorPyramidDesc.width >> 1; |
|||
colorPyramidDesc.height = colorPyramidDesc.height >> 1; |
|||
|
|||
// TODO: Add proper stereo support to the compute job
|
|||
|
|||
cmd.ReleaseTemporaryRT(m_ColorPyramidMips[i + 1]); |
|||
cmd.GetTemporaryRT(m_ColorPyramidMips[i + 1], colorPyramidDesc, FilterMode.Bilinear); |
|||
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Source, last); |
|||
cmd.SetComputeTextureParam(m_ColorPyramidCS, m_ColorPyramidKernel, _Result, m_ColorPyramidMips[i + 1]); |
|||
cmd.SetComputeVectorParam(m_ColorPyramidCS, _Size, new Vector4(colorPyramidDesc.width, colorPyramidDesc.height, 1f / colorPyramidDesc.width, 1f / colorPyramidDesc.height)); |
|||
cmd.DispatchCompute( |
|||
m_ColorPyramidCS, |
|||
m_ColorPyramidKernel, |
|||
Mathf.CeilToInt(colorPyramidDesc.width / 8f), |
|||
Mathf.CeilToInt(colorPyramidDesc.height / 8f), |
|||
1); |
|||
cmd.CopyTexture(m_ColorPyramidMips[i + 1], 0, 0, targetTexture, 0, i + 1); |
|||
|
|||
last = m_ColorPyramidMips[i + 1]; |
|||
} |
|||
|
|||
for (int i = 0; i < lodCount; i++) |
|||
cmd.ReleaseTemporaryRT(m_ColorPyramidMips[i + 1]); |
|||
} |
|||
|
|||
public void Initialize(HDCamera hdCamera, bool enableStereo) |
|||
{ |
|||
var colorDesc = CalculateRenderTextureDescriptor(hdCamera, enableStereo); |
|||
colorDesc.colorFormat = RenderTextureFormat.ARGBHalf; |
|||
m_ColorRenderTextureDescriptor = colorDesc; |
|||
|
|||
var depthDesc = CalculateRenderTextureDescriptor(hdCamera, enableStereo); |
|||
depthDesc.colorFormat = RenderTextureFormat.RFloat; |
|||
m_DepthRenderTextureDescriptor = depthDesc; |
|||
} |
|||
|
|||
public static RenderTextureDescriptor CalculateRenderTextureDescriptor(HDCamera hdCamera, bool enableStereo) |
|||
{ |
|||
var desc = hdCamera.renderTextureDesc; |
|||
desc.depthBufferBits = 0; |
|||
desc.useMipMap = true; |
|||
desc.autoGenerateMips = false; |
|||
|
|||
desc.msaaSamples = 1; // These are approximation textures, they don't need MSAA
|
|||
|
|||
// for stereo double-wide, each half of the texture will represent a single eye's pyramid
|
|||
//var widthModifier = 1;
|
|||
//if (stereoEnabled && (desc.dimension != TextureDimension.Tex2DArray))
|
|||
// widthModifier = 2; // double-wide
|
|||
|
|||
//desc.width = pyramidSize * widthModifier;
|
|||
desc.width = (int)hdCamera.screenSize.x; |
|||
desc.height = (int)hdCamera.screenSize.y; |
|||
|
|||
return desc; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ea3e7945ee7dc7a479b9e6846a0c544c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// |
|||
// This is a modified version of the BlurCS compute shader from Microsoft's MiniEngine |
|||
// library. The copyright notice from the original version is included below. |
|||
// |
|||
// The original source code of MiniEngine is available on GitHub. |
|||
// https://github.com/Microsoft/DirectX-Graphics-Samples |
|||
// |
|||
|
|||
// |
|||
// Copyright (c) Microsoft. All rights reserved. |
|||
// This code is licensed under the MIT License (MIT). |
|||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF |
|||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY |
|||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR |
|||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. |
|||
// |
|||
// Developed by Minigraph |
|||
// |
|||
// Author: Bob Brown |
|||
// |
|||
|
|||
#include "CoreRP/ShaderLibrary/Common.hlsl" |
|||
|
|||
Texture2D<float4> _Source; |
|||
RWTexture2D<float4> _Result; |
|||
|
|||
SamplerState sampler_LinearClamp; |
|||
|
|||
CBUFFER_START(cb) |
|||
float4 _Size; |
|||
CBUFFER_END |
|||
|
|||
// 16x16 pixels with an 8x8 center that we will be blurring writing out. Each uint is two color |
|||
// channels packed together. |
|||
// The reason for separating channels is to reduce bank conflicts in the local data memory |
|||
// controller. A large stride will cause more threads to collide on the same memory bank. |
|||
groupshared uint gs_cacheR[128]; |
|||
groupshared uint gs_cacheG[128]; |
|||
groupshared uint gs_cacheB[128]; |
|||
groupshared uint gs_cacheA[128]; |
|||
|
|||
float4 BlurPixels(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h, float4 i) |
|||
{ |
|||
return 0.27343750 * (e ) |
|||
+ 0.21875000 * (d + f) |
|||
+ 0.10937500 * (c + g) |
|||
+ 0.03125000 * (b + h) |
|||
+ 0.00390625 * (a + i); |
|||
} |
|||
|
|||
void Store2Pixels(uint index, float4 pixel1, float4 pixel2) |
|||
{ |
|||
gs_cacheR[index] = f32tof16(pixel1.r) | f32tof16(pixel2.r) << 16; |
|||
gs_cacheG[index] = f32tof16(pixel1.g) | f32tof16(pixel2.g) << 16; |
|||
gs_cacheB[index] = f32tof16(pixel1.b) | f32tof16(pixel2.b) << 16; |
|||
gs_cacheA[index] = f32tof16(pixel1.a) | f32tof16(pixel2.a) << 16; |
|||
} |
|||
|
|||
void Load2Pixels(uint index, out float4 pixel1, out float4 pixel2) |
|||
{ |
|||
uint rr = gs_cacheR[index]; |
|||
uint gg = gs_cacheG[index]; |
|||
uint bb = gs_cacheB[index]; |
|||
uint aa = gs_cacheA[index]; |
|||
pixel1 = float4(f16tof32(rr ), f16tof32(gg ), f16tof32(bb ), f16tof32(aa )); |
|||
pixel2 = float4(f16tof32(rr >> 16), f16tof32(gg >> 16), f16tof32(bb >> 16), f16tof32(aa >> 16)); |
|||
} |
|||
|
|||
void Store1Pixel(uint index, float4 pixel) |
|||
{ |
|||
gs_cacheR[index] = asuint(pixel.r); |
|||
gs_cacheG[index] = asuint(pixel.g); |
|||
gs_cacheB[index] = asuint(pixel.b); |
|||
gs_cacheA[index] = asuint(pixel.a); |
|||
} |
|||
|
|||
void Load1Pixel(uint index, out float4 pixel) |
|||
{ |
|||
pixel = asfloat(uint4(gs_cacheR[index], gs_cacheG[index], gs_cacheB[index], gs_cacheA[index])); |
|||
} |
|||
|
|||
// Blur two pixels horizontally. This reduces LDS reads and pixel unpacking. |
|||
void BlurHorizontally(uint outIndex, uint leftMostIndex) |
|||
{ |
|||
float4 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; |
|||
Load2Pixels(leftMostIndex + 0, s0, s1); |
|||
Load2Pixels(leftMostIndex + 1, s2, s3); |
|||
Load2Pixels(leftMostIndex + 2, s4, s5); |
|||
Load2Pixels(leftMostIndex + 3, s6, s7); |
|||
Load2Pixels(leftMostIndex + 4, s8, s9); |
|||
|
|||
Store1Pixel(outIndex , BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8)); |
|||
Store1Pixel(outIndex + 1, BlurPixels(s1, s2, s3, s4, s5, s6, s7, s8, s9)); |
|||
} |
|||
|
|||
void BlurVertically(uint2 pixelCoord, uint topMostIndex) |
|||
{ |
|||
float4 s0, s1, s2, s3, s4, s5, s6, s7, s8; |
|||
Load1Pixel(topMostIndex , s0); |
|||
Load1Pixel(topMostIndex + 8, s1); |
|||
Load1Pixel(topMostIndex + 16, s2); |
|||
Load1Pixel(topMostIndex + 24, s3); |
|||
Load1Pixel(topMostIndex + 32, s4); |
|||
Load1Pixel(topMostIndex + 40, s5); |
|||
Load1Pixel(topMostIndex + 48, s6); |
|||
Load1Pixel(topMostIndex + 56, s7); |
|||
Load1Pixel(topMostIndex + 64, s8); |
|||
|
|||
float4 blurred = BlurPixels(s0, s1, s2, s3, s4, s5, s6, s7, s8); |
|||
|
|||
// Write to the final target |
|||
_Result[pixelCoord] = blurred; |
|||
} |
|||
|
|||
#pragma kernel KMain |
|||
[numthreads(8, 8, 1)] |
|||
void KMain(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID) |
|||
{ |
|||
// Upper-left pixel coordinate of quad that this thread will read |
|||
int2 threadUL = (groupThreadId << 1) + (groupId << 3) - 4; |
|||
|
|||
// Downsample the block |
|||
float2 offset = float2(threadUL); |
|||
float4 p00 = _Source.SampleLevel(sampler_LinearClamp, (offset + 0.5) * _Size.zw, 0.0); |
|||
float4 p10 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 0.0) + 0.5) * _Size.zw, 0.0); |
|||
float4 p01 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(0.0, 1.0) + 0.5) * _Size.zw, 0.0); |
|||
float4 p11 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 1.0) + 0.5) * _Size.zw, 0.0); |
|||
|
|||
// Store the 4 downsampled pixels in LDS |
|||
uint destIdx = groupThreadId.x + (groupThreadId.y << 4u); |
|||
Store2Pixels(destIdx , p00, p10); |
|||
Store2Pixels(destIdx + 8u, p01, p11); |
|||
|
|||
GroupMemoryBarrierWithGroupSync(); |
|||
|
|||
// Horizontally blur the pixels in LDS |
|||
uint row = groupThreadId.y << 4u; |
|||
BlurHorizontally(row + (groupThreadId.x << 1u), row + groupThreadId.x + (groupThreadId.x & 4u)); |
|||
|
|||
GroupMemoryBarrierWithGroupSync(); |
|||
|
|||
// Vertically blur the pixels in LDS and write the result to memory |
|||
BlurVertically(dispatchThreadId, (groupThreadId.y << 3u) + groupThreadId.x); |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4e3267a1135742441a14298d8dcac04a |
|||
timeCreated: 1503754250 |
|||
licenseType: Pro |
|||
ComputeShaderImporter: |
|||
currentAPIMask: 131076 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue