浏览代码

Improve the support of orthographic rendering

/main
Evgenii Golubev 7 年前
当前提交
a3e9bdfc
共有 16 个文件被更改,包括 62 次插入49 次删除
  1. 61
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  2. 13
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs
  3. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader
  4. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewMaterialGBuffer.shader
  5. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewTiles.shader
  6. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  7. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader
  8. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute
  9. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute
  10. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  11. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl
  12. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/CameraMotionVectors.shader
  13. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl
  14. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VaryingMesh.hlsl
  15. 9
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl
  16. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/OpaqueAtmosphericScattering.shader

61
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


// ----------------------------------------------------------------------------
// Z buffer to linear 0..1 depth (0 at near plane, 1 at far plane).
// Does not correctly handle oblique view frustums.
// Does NOT correctly handle oblique view frustums.
// Does NOT work with orthographic projection.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float Linear01DepthFromNear(float depth, float4 zBufferParam)
{

// Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane).
// Does not correctly handle oblique view frustums.
// Does NOT work with orthographic projections.
// Does NOT correctly handle oblique view frustums.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float Linear01Depth(float depth, float4 zBufferParam)
{

// Z buffer to linear depth.
// Does not correctly handle oblique view frustums.
// Does NOT correctly handle oblique view frustums.
// Does NOT work with orthographic projection.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float LinearEyeDepth(float depth, float4 zBufferParam)
{

// Z buffer to linear depth.
// Correctly handles oblique view frustums. Only valid for projection matrices!
// Correctly handles oblique view frustums.
// Does NOT work with orthographic projection.
// The view space uses a right-handed coordinate system.
return -viewSpaceZ;
// If the matrix is right-handed, we have to flip the Z axis to get a positive value.
return abs(viewSpaceZ);
// Correctly handles oblique view frustums.
// Works in all cases.
float LinearEyeDepth(float3 positionWS, float4x4 viewProjMatrix)
// Assumes that the 'positionWS' is in front of the camera.
float LinearEyeDepth(float3 positionWS, float4x4 viewMatrix)
return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
float viewSpaceZ = mul(viewMatrix, float4(positionWS, 1.0)).z;
// If the matrix is right-handed, we have to flip the Z axis to get a positive value.
return abs(viewSpaceZ);
}
// 'z' is the view space Z position (linear depth).

return mul(clipSpaceTransform, float4(position, 1.0));
}
// The returned Z value is the depth buffer value (and NOT linear view space Z value).
// Use case examples:
// (position = positionCS) => (clipSpaceTransform = use default)
// (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P)

PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS, uint2 tileCoord)
{
PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord);
posInput.deviceDepth = deviceDepth;
posInput.linearDepth = linearDepth;
posInput.positionWS = positionWS;
posInput.positionWS = positionWS;
posInput.deviceDepth = deviceDepth;
posInput.linearDepth = linearDepth;
return posInput;
}

// From deferred or compute shader
// depth must be the depth from the raw depth buffer. This allow to handle all kind of depth automatically with the inverse view projection matrix.
// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, uint2 tileCoord)
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth,
float4x4 invViewProjMatrix, float4x4 viewMatrix,
uint2 tileCoord)
posInput.deviceDepth = deviceDepth;
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionNDC, deviceDepth, invViewProjMatrix);
// The compiler should optimize this (less expensive than reconstruct depth VS from depth buffer)
posInput.linearDepth = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionNDC, deviceDepth, invViewProjMatrix);
posInput.deviceDepth = deviceDepth;
posInput.linearDepth = LinearEyeDepth(posInput.positionWS, viewMatrix);
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix)
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth,
float4x4 invViewProjMatrix, float4x4 viewMatrix)
return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewProjMatrix, uint2(0, 0));
return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewMatrix, uint2(0, 0));
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float4x4 viewProjMatrix, inout PositionInputs posInput)
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float3 viewForwardDir, float4x4 viewProjMatrix, inout PositionInputs posInput)
posInput.deviceDepth = ComputeNormalizedDeviceCoordinatesWithZ(posInput.positionWS, viewProjMatrix).z;
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0));
posInput.linearDepth = positionCS.w;
posInput.deviceDepth = positionCS.z / positionCS.w;
// Transform the displacement along the view vector to the displacement along the forward vector.
// Use abs() to make sure we get the sign right.
// 'depthOffsetVS' applies in the direction away from the camera.
posInput.linearDepth += depthOffsetVS * abs(dot(V, viewForwardDir));
}
// ----------------------------------------------------------------------------

13
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs


public Matrix4x4 projMatrix;
public Matrix4x4 nonJitteredProjMatrix;
public Vector4 cameraPositionWS;
public float viewParam;
public float detViewMatrix;
public Vector4 screenSize;
public Frustum frustum;
public Vector4[] frustumPlaneEquations;

// avoid one-frame jumps/hiccups with temporal effects (motion blur, TAA...)
public bool isFirstFrame { get; private set; }
// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
// TODO: pass this as "_DepthBufferParam" if the projection matrix is oblique.
// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
get
{
var p = projMatrix;

projMatrix = gpuProj;
nonJitteredProjMatrix = gpuNonJitteredProj;
cameraPos = pos;
viewParam = viewMatrix.determinant;
detViewMatrix = viewMatrix.determinant;
if (ShaderConfig.s_CameraRelativeRendering != 0)
{

// What constants in UnityPerPass need updating for stereo considerations?
// _ViewProjMatrix - It is used directly for generating tesselation factors. This should be the same
// across both eyes for consistency, and to keep shadow-generation eye-independent
// _ViewParam - Used for isFrontFace determination, should be the same for both eyes. There is the scenario
// _DetViewMatrix - Used for isFrontFace determination, should be the same for both eyes. There is the scenario
// where there might be multi-eye sets that are divergent enough where this assumption is not valid,
// but that's a future problem
// _InvProjParam - Intention was for generating linear depths, but not currently used. Will need to be stereo-ized if

var stereoCombinedProjMatrix = cullingParams.cullStereoProj;
projMatrix = GL.GetGPUProjectionMatrix(stereoCombinedProjMatrix, true);
viewParam = viewMatrix.determinant;
detViewMatrix = viewMatrix.determinant;
frustum = Frustum.Create(viewProjMatrix, true, true);

cmd.SetGlobalMatrix(HDShaderIDs._NonJitteredViewProjMatrix, nonJitteredViewProjMatrix);
cmd.SetGlobalMatrix(HDShaderIDs._PrevViewProjMatrix, prevViewProjMatrix);
cmd.SetGlobalVector(HDShaderIDs._CameraPositionWS, cameraPositionWS);
cmd.SetGlobalFloat( HDShaderIDs._ViewParam, viewParam);
cmd.SetGlobalFloat( HDShaderIDs._DetViewMatrix, detViewMatrix);
cmd.SetGlobalVector(HDShaderIDs._ScreenSize, screenSize);
cmd.SetGlobalVector(HDShaderIDs._ScreenToTargetScale, scaleBias);
cmd.SetGlobalVector(HDShaderIDs._DepthBufferParam, depthBufferParam);

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader


{
// Reuse depth display function from DebugViewMaterial
float depth = SAMPLE_TEXTURE2D(_DebugFullScreenTexture, s_point_clamp_sampler, input.texcoord).r;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float linearDepth = frac(posInput.linearDepth * 0.1);
return float4(linearDepth.xxx, 1.0);
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewMaterialGBuffer.shader


{
// input.positionCS is SV_Position
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
BSDFData bsdfData;
BakeLightingData bakeLightingData;

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugViewTiles.shader


{
// positionCS is SV_Position
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, uint2(input.positionCS.xy) / GetTileSize());
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, uint2(input.positionCS.xy) / GetTileSize());
int2 pixelCoord = posInput.positionSS.xy;
int2 tileCoord = (float2)pixelCoord / GetTileSize();

if (tileCoord.y < LIGHTCATEGORY_COUNT && tileCoord.x < maxLights + 3)
{
float depthMouse = LOAD_TEXTURE2D(_MainDepthTexture, _MousePixelCoord.xy).x;
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord.xy, _ScreenSize.zw, depthMouse, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, mouseTileCoord);
PositionInputs mousePosInput = GetPositionInput(_MousePixelCoord.xy, _ScreenSize.zw, depthMouse, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, mouseTileCoord);
uint category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
uint start;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _NonJitteredViewProjMatrix = Shader.PropertyToID("_NonJitteredViewProjMatrix");
public static readonly int _ViewProjMatrix = Shader.PropertyToID("_ViewProjMatrix");
public static readonly int _InvViewProjMatrix = Shader.PropertyToID("_InvViewProjMatrix");
public static readonly int _ViewParam = Shader.PropertyToID("_ViewParam");
public static readonly int _DetViewMatrix = Shader.PropertyToID("_DetViewMatrix");
public static readonly int _DepthBufferParam = Shader.PropertyToID("_DepthBufferParam");
public static readonly int _InvProjParam = Shader.PropertyToID("_InvProjParam");
public static readonly int _ScreenSize = Shader.PropertyToID("_ScreenSize");

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Deferred.shader


// input.positionCS is SV_Position
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, uint2(input.positionCS.xy) / GetTileSize());
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, uint2(input.positionCS.xy) / GetTileSize());
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
BSDFData bsdfData;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute


if (depth == UNITY_RAW_FAR_CLIP_VALUE)
return;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, tileCoord);
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
#ifdef ENABLE_NORMALS
BSDFData bsdfData;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Deferred.compute


// This need to stay in sync with deferred.shader
float depth = LOAD_TEXTURE2D(_MainDepthTexture, pixelCoord.xy).x;
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, tileCoord);
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
// For indirect case: we can still overlap inside a tile with the sky/background, reject it
// Can't rely on stencil as we are in compute shader

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/LayeredLit/LayeredLitData.hlsl


float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord, blendMasks);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
ApplyDepthOffsetPositionInput(V, depthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput);
#endif
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/LitData.hlsl


float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, GetWorldToHClipMatrix(), posInput);
ApplyDepthOffsetPositionInput(V, depthOffset, GetViewForwardDir(), GetWorldToHClipMatrix(), posInput);
#endif
// We perform the conversion to world of the normalTS outside of the GetSurfaceData

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/RenderPipelineResources/CameraMotionVectors.shader


{
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float4 worldPos = float4(posInput.positionWS, 1.0);
float4 prevPos = worldPos;

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/ShaderPassDBuffer.hlsl


FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionSS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
// Transform from world space to decal space (DS) to clip the decal.
// For this we must use absolute position.

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderPass/VaryingMesh.hlsl


output.isFrontFace = IS_FRONT_VFACE(input.cullFace, true, false);
// Handle handness of the view matrix (In Unity view matrix default to a determinant of -1)
// when we render a cubemap the view matrix handness is flipped (due to convention used for cubemap) we have a determinant of +1
output.isFrontFace = _ViewParam < 0.0 ? output.isFrontFace : !output.isFrontFace;
output.isFrontFace = _DetViewMatrix < 0.0 ? output.isFrontFace : !output.isFrontFace;
#endif
return output;

9
ScriptableRenderPipeline/HDRenderPipeline/HDRP/ShaderVariables.hlsl


// TODO: sort the vars below by the frequency of use (descending), and put commonly used ones together.
// Note: a matrix is 4 * 4 * 4 = 64 bytes (1x cache line), so no need to sort those.
float3 _CameraPositionWS;
float _ViewParam; // determinant(_ViewMatrix)
float4 _ScreenSize; // { w, h, 1 / w, 1 / h }
float4 _ScreenToTargetScale; // { w / RTHandle.maxWidth, h / RTHandle.maxHeight, 0, 0 }
float _DetViewMatrix; // determinant(_ViewMatrix)
float4 _ScreenSize; // { w, h, 1 / w, 1 / h }
float4 _ScreenToTargetScale; // { w / RTHandle.maxWidth, h / RTHandle.maxHeight, 0, 0 }
// Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
// x = 1-far/near

// z = x/far
// w = 1/far
float4 _DepthBufferParam;
float4 _InvProjParam;
float4 _FrustumPlanes[6]; // { (a, b, c) = N, d = -dot(N, P) } [L, R, T, B, N, F]
float4 _FrustumPlanes[6]; // { (a, b, c) = N, d = -dot(N, P) } [L, R, T, B, N, F]
CBUFFER_END
// Custom generated by HDRP, not from Unity Engine (passed in via HDCamera)

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/OpaqueAtmosphericScattering.shader


float4 Frag(Varyings input) : SV_Target
{
float depth = LOAD_TEXTURE2D(_MainDepthTexture, input.positionCS.xy).x;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
{

正在加载...
取消
保存