浏览代码

Camera-relative rendering WIP

/RenderPassXR_Sandbox
Evgenii Golubev 7 年前
当前提交
b3bd2618
共有 12 个文件被更改,包括 142 次插入31 次删除
  1. 16
      Assets/ScriptableRenderPipeline/Core/Shadow/ShadowUtilities.cs
  2. 39
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 46
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  4. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  5. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  6. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderConfig.cs
  7. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderConfig.cs.hlsl
  8. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl
  9. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VertMesh.hlsl
  10. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl
  11. 29
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariablesFunctions.hlsl
  12. 22
      Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl

16
Assets/ScriptableRenderPipeline/Core/Shadow/ShadowUtilities.cs


// get lightDir
lightDir = vl.light.transform.forward;
// calculate the view matrices
Vector3 lpos = vl.light.transform.position;
Vector3 lpos = vl.localToWorld.GetColumn(3);
view = ShadowUtilsConstants.kCubemapFaces[faceIdx];
Vector3 inverted_viewpos = ShadowUtilsConstants.kCubemapFaces[faceIdx].MultiplyPoint( -lpos );
view.SetColumn( 3, new Vector4( inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f ) );

ShadowUtilsConstants.CubemapEdge cubemapEdge = ShadowUtilsConstants.kCubemapEdgesPerFace[faceIdx,i];
Vector3 cullingPlaneDirection = ShadowUtilsConstants.kCubemapEdgeDirections[(int)cubemapEdge];
splitData.SetCullingPlane( i, new Plane( cullingPlaneDirection, lpos ) );
splitData.SetCullingPlane( i, new Plane( cullingPlaneDirection, vl.light.transform.position) );
}
// following code is from SharedLightData::GetNearPlaneMinBound
float percentageBound = 0.01f * vl.light.range;

for( int i = 0, cnt = splitRatio.Length < 3 ? splitRatio.Length : 3; i < cnt; i++ )
ratios[i] = splitRatio[i];
cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( lightIndex, (int) cascadeIdx, cascadeCount, ratios, (int) width, nearPlaneOffset, out view, out proj, out splitData );
// 'relCamPos' is the WS position of the camera if camera-relative rendering is enabled, 0 otherwise.
Vector3 lightPosWS = vl.light.transform.position;
Vector3 relCamPos = lightPosWS - (Vector3)vl.localToWorld.GetColumn(3);
// Fix-up the sphere.
splitData.cullingSphere.x -= relCamPos.x;
splitData.cullingSphere.y -= relCamPos.y;
splitData.cullingSphere.z -= relCamPos.z;
// Fix-up the matrix (this does NOT work).
Matrix4x4 tr = Matrix4x4.Translate(relCamPos);
view = view * tr;
// and the compound
return proj * view;
}

39
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


get { var p = projMatrix; return new Vector4(p.m20 / (p.m00 * p.m23), p.m21 / (p.m11 * p.m23), -1.0f / p.m23, (-p.m22 + p.m20 * p.m02 / p.m00 + p.m21 * p.m12 / p.m11) / p.m23); }
}
public Vector4[] frustumPlaneEquations
{
get
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(viewProjMatrix);
Vector4[] equations = new Vector4[6];
for (int i = 0; i < 6; i++)
{
equations[i] = new Vector4(planes[i].normal.x, planes[i].normal.y, planes[i].normal.z, -planes[i].distance);
}
return equations;
}
}
// View-projection matrix from the previous frame.
public Matrix4x4 prevViewProjMatrix;

{
// The actual projection matrix used in shaders is actually massaged a bit to work across all platforms
// (different Z value ranges etc.)
var gpuProj = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); // Had to change this from 'false'
var gpuVP = gpuProj * camera.worldToCameraMatrix;
Matrix4x4 gpuProj = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); // Had to change this from 'false'
Matrix4x4 gpuView = camera.worldToCameraMatrix;
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Zero out the translation component.
gpuView.SetColumn(3, new Vector4(0, 0, 0, 1));
}
Matrix4x4 gpuVP = gpuProj * gpuView;
// A camera could be rendered multiple time per frame, only updates the previous viewproj if needed
if (m_LastFrameActive != Time.frameCount)

m_FirstFrame = false;
}
viewMatrix = camera.worldToCameraMatrix;
viewMatrix = gpuView;
projMatrix = gpuProj;
screenSize = new Vector4(camera.pixelWidth, camera.pixelHeight, 1.0f / camera.pixelWidth, 1.0f / camera.pixelHeight);

cmd.SetGlobalVector("_InvProjParam", invProjParam);
cmd.SetGlobalVector("_ScreenSize", screenSize);
cmd.SetGlobalMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetGlobalVectorArray("_FrustumPlanes", frustumPlaneEquations);
}
// Does not modify global settings. Used for shadows, low res. rendering, etc.

material.SetVector("_InvProjParam", invProjParam);
material.SetVector("_ScreenSize", screenSize);
material.SetMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
material.SetVectorArray("_FrustumPlanes", frustumPlaneEquations);
}
public void SetupComputeShader(ComputeShader cs, CommandBuffer cmd)

cmd.SetComputeVectorParam( cs, "_InvProjParam", invProjParam);
cmd.SetComputeVectorParam( cs, "_ScreenSize", screenSize);
Utilities.SetMatrixCS(cmd, cs, "_PrevViewProjMatrix", prevViewProjMatrix);
Utilities.SetVectorArrayCS(cmd, cs, "_FrustumPlanes", frustumPlaneEquations);
}
}

renderContext.SetupCameraProperties(camera);
var hdCamera = HDCamera.Get(camera);
HDCamera hdCamera = HDCamera.Get(camera);
PushGlobalParams(hdCamera, renderContext, m_Asset.sssSettings);
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode

}
InitAndClearBuffer(camera, renderContext);
PushGlobalParams(hdCamera, renderContext, m_Asset.sssSettings);
RenderDepthPrepass(m_CullResults, camera, renderContext);

cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
renderContext.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
else
{

46
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


// Then Culling side
var range = light.range;
var lightToWorld = light.localToWorld;
Vector3 lightPos = lightToWorld.GetColumn(3);
Vector3 lightPos = lightData.positionWS;
// Fill bounds
var bound = new SFiniteLightBound();

{
m_lightList.Clear();
Vector3 camPosWS = camera.transform.position;
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Caution: 'VisibleLight.localToWorld' is camera-relative after this point.
Vector4 camPos4WS = new Vector4(camPosWS.x, camPosWS.y, camPosWS.z, 0);
for (int i = 0, n = cullResults.visibleLights.Count; i < n; i++)
{
VisibleLight light = cullResults.visibleLights[i];
light.localToWorld.SetColumn(3, light.localToWorld.GetColumn(3) - camPos4WS);
cullResults.visibleLights[i] = light;
}
}
if (cullResults.visibleLights.Count != 0 || cullResults.visibleReflectionProbes.Count != 0)
{
// 0. deal with shadows

if (gpuLightType == GPULightType.Directional)
{
if (GetDirectionalLightData(shadowSettings, gpuLightType, light, additionalLightData, additionalShadowData, lightIndex))
{
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Caution: 'DirectionalLightData.positionWS' is camera-relative after this point.
int n = m_lightList.directionalLights.Count;
DirectionalLightData lightData = m_lightList.directionalLights[n - 1];
lightData.positionWS -= camPosWS;
m_lightList.directionalLights[n - 1] = lightData;
}
}
continue;
}
// Punctual, area, projector lights - the rendering side.

// Then culling side. Must be call in this order as we pass the created Light data to the function
GetLightVolumeDataAndBound(lightCategory, gpuLightType, lightVolumeType, light, m_lightList.lights[m_lightList.lights.Count - 1], worldToView);
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Caution: 'LightData.positionWS' is camera-relative after this point.
int n = m_lightList.lights.Count;
LightData lightData = m_lightList.lights[n - 1];
lightData.positionWS -= camPosWS;
m_lightList.lights[n - 1] = lightData;
}
}
}

GetEnvLightData(probe);
GetEnvLightVolumeDataAndBound(probe, lightVolumeType, worldToView);
if (ShaderConfig.s_CameraRelativeRendering != 0)
{
// Caution: 'EnvLightData.positionWS' is camera-relative after this point.
int n = m_lightList.envLights.Count;
EnvLightData envLightData = m_lightList.envLights[n - 1];
envLightData.positionWS -= camPosWS;
m_lightList.envLights[n - 1] = envLightData;
}
}
// Sanity check

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(positionWS * worldScale, uvXZ, uvXY, uvZY);
GetTriplanarCoordinate(GetAbsolutePositionWS(positionWS) * worldScale, uvXZ, uvXY, uvZY);
// Planar is just XZ of triplanar
if (mappingType == UV_MAPPING_PLANAR)

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl


{
float maxDisplacement = GetMaxDisplacement();
bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes);
bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes);
bool faceCull = false;

float3 camPosWS = _WorldSpaceCameraPos;
float3 camPosWS = GetPrimaryCameraPosition();
#ifndef _DOUBLESIDED_ON
// TODO: Handle inverse culling (for mirror)!

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderConfig.cs


// All this could be fix we a new Mesh API not ready yet. Note that this feature only affect animated mesh (vertex or skin) as others use depth reprojection.
VelocityInGBuffer = 0, // Change to 1 to enable the feature, then regenerate hlsl headers.
// TODO: not working yet, waiting for UINT16 RT format support
PackGBufferInU16 = 0
PackGBufferInU16 = 0,
CameraRelativeRendering = 1 // Rendering sets the origin of the world to the position of the primary (scene view) camera
};
// Note: #define can't be use in include file in C# so we chose this way to configure both C# and hlsl

public const int k_PackgbufferInU16 = (int)ShaderOptions.PackGBufferInU16;
public static int s_PackgbufferInU16 = (int)ShaderOptions.PackGBufferInU16;
public const int k_CameraRelativeRendering = (int)ShaderOptions.CameraRelativeRendering;
public static int s_CameraRelativeRendering = (int)ShaderOptions.CameraRelativeRendering;
}
}

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderConfig.cs.hlsl


//
#define SHADEROPTIONS_VELOCITY_IN_GBUFFER (0)
#define SHADEROPTIONS_PACK_GBUFFER_IN_U16 (0)
#define SHADEROPTIONS_CAMERA_RELATIVE_RENDERING (1)
#endif

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl


// position, so also take this opportunity to create a dependence on it.
inputMesh.positionOS.z = inputMesh.positionOS.z > 0 ? 1.0e-4 : 0.0;
float3 positionWS = TransformObjectToWorld(inputMesh.positionOS);
float3 positionWS = GetCameraRelativePositionWS(TransformObjectToWorld(inputMesh.positionOS));
output.vmesh.positionCS = TransformWorldToHClip(positionWS);
output.vmesh.texCoord0 = inputMesh.uv0;
output.vmesh.texCoord1 = inputMesh.uv1;

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VertMesh.hlsl


ApplyWind(positionWS, normalWS, rootWP, _Stiffness, _Drag, _ShiverDrag, _ShiverDirectionality, _InitialBend, vertexColor.a, _Time);
#endif
positionWS = GetCameraRelativePositionWS(positionWS);
#ifdef TESSELLATION_ON
output.positionWS = positionWS;
#ifdef _TESSELLATION_OBJECT_SCALE

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


float4x4 _InvViewMatrix;
float4x4 _InvProjMatrix;
float4 _InvProjParam;
float4 _ScreenSize;
float4 _ScreenSize; // (w, h, 1/w, 1/h)
float4 _FrustumPlanes[6]; // (N, -dot(N, P))
CBUFFER_END
#ifdef USE_LEGACY_UNITY_MATRIX_VARIABLES

29
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariablesFunctions.hlsl


return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
}
float3 GetAbsolutePositionWS(float3 cameraRelativePositionWS)
{
float3 pos = cameraRelativePositionWS;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
pos += _WorldSpaceCameraPos;
#endif
return pos;
}
float3 GetCameraRelativePositionWS(float3 absolutePositionWS)
{
float3 pos = absolutePositionWS;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
pos -= _WorldSpaceCameraPos;
#endif
return pos;
}
// Returns the position of the primary (scene view) camera.
// Note: '_WorldSpaceCameraPos' is set by the legacy Unity code.
float3 GetPrimaryCameraPosition()
{
return GetCameraRelativePositionWS(_WorldSpaceCameraPos);
}
return _WorldSpaceCameraPos;
return GetPrimaryCameraPosition();
#else
// TEMP: this is rather expensive. Then again, we need '_WorldSpaceCameraPos'
// to represent the position of the primary (scene view) camera in order to

float3 rotCamPos = trViewMat[3].xyz;
return mul((float3x3)trViewMat, -rotCamPos);
return mul((float3x3)trViewMat, -rotCamPos);
#endif
}

22
Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl


return positionSS;
}
float3 ComputeViewSpacePosition(float2 positionSS, float depthRaw, float4x4 invProjMatrix)
{
float4 positionCS = ComputeClipSpacePosition(positionSS, depthRaw);
float4 positionVS = mul(invProjMatrix, positionCS);
// The view space uses a right-handed coordinate system.
positionVS.z = -positionVS.z;
return positionVS.xyz / positionVS.w;
}
// It may be necessary to flip the Y axis as the origin of the screen-space coordinate system
// of Direct3D is at the top left corner of the screen, with the Y axis pointing downwards.
void UpdatePositionInput(float depthRaw, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, inout PositionInputs posInput)
{
posInput.depthRaw = depthRaw;

// The compiler should optimize this (less expensive than reconstruct depth VS from depth buffer)
posInput.depthVS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
}
// It may be necessary to flip the Y axis as the origin of the screen-space coordinate system
// of Direct3D is at the top left corner of the screen, with the Y axis pointing downwards.
float3 ComputeViewSpacePosition(float2 positionSS, float depthRaw, float4x4 invProjMatrix)
{
float4 positionCS = ComputeClipSpacePosition(positionSS, depthRaw);
float4 positionVS = mul(invProjMatrix, positionCS);
// The view space uses a right-handed coordinate system.
positionVS.z = -positionVS.z;
return positionVS.xyz / positionVS.w;
}
// The view direction 'V' points towards the camera.

正在加载...
取消
保存