浏览代码

Add misc function for deferred rendering

- Add world reconstruction function
- Add macro to abstrct GBuffer
- Add lighting information into SurfaceData and BSDFData
- Clean  / comment some stuff

Note: forward and deferred code do not produce lighting for now
/main
Sebastien Lagarde 8 年前
当前提交
6a00b2b9
共有 12 个文件被更改,包括 233 次插入131 次删除
  1. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta
  2. 11
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/DisneyGGX.shader
  3. 8
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Lighting.hlsl
  4. 143
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingDeferred.shader
  5. 6
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl
  6. 38
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/DisneyGGX.hlsl
  7. 60
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
  8. 1
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/PostProcess/FinalPass.shader
  9. 20
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderVariables.hlsl
  10. 10
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/TemplateDisneyGGX.hlsl
  11. 56
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  12. 9
      Assets/ScriptableRenderLoop/ShaderLibrary/Postprocress.meta

2
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta


fileFormatVersion: 2
guid: 2400b74f5ce370c4481e5dc417d03703
timeCreated: 1474539935
timeCreated: 1474923798
licenseType: Pro
NativeFormatImporter:
userData:

11
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/DisneyGGX.shader


#include "TemplateDisneyGGX.hlsl"
void FragDeferred( PackedVaryings packedInput,
out float4 outGBuffer0 : SV_Target0,
out float4 outGBuffer1 : SV_Target1,
out float4 outGBuffer2 : SV_Target2,
out float4 outEmission : SV_Target3
OUTPUT_GBUFFER(outGBuffer)
EncodeIntoGBuffer(surfaceData, outGBuffer0, outGBuffer1, outGBuffer2);
// Lightmap + Emisive lighting buffer
outEmission = float4(0, 0, 0, 1);
ENCODE_INTO_GBUFFER(surfaceData, outGBuffer);
}
ENDCG

8
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Lighting.hlsl


#ifndef UNITY_LIGHTING_INCLUDED
#define UNITY_LIGHTING_INCLUDED
#include "../Material/Material.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl"
#if UNITY_SHADERRENDERPASS == UNITY_SHADERRENDERPASS_FORWARD
#if UNITY_SHADERRENDERPASS == UNITY_SHADERRENDERPASS_FORWARD || UNITY_SHADERRENDERPASS == UNITY_SHADERRENDERPASS_DEFERRED
#elif UNITY_SHADERRENDERPASS == UNITY_SHADERRENDERPASS_DEFERRED
#include "LightingDeferred.hlsl"
//#elif UNITY_SHADERRENDERPASS == UNITY_SHADERRENDERPASS_DEFERRED
//#include "LightingDeferred.hlsl"
#endif
#endif // UNITY_LIGHTING_INCLUDED

143
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingDeferred.shader


Shader "Hidden/Unity/LightingDeferred" {
Properties{
_SrcBlend("", Float) = 1
_DstBlend("", Float) = 1
}
SubShader{
Shader "Hidden/Unity/LightingDeferred"
{
Properties
{
_SrcBlend("", Float) = 1
_DstBlend("", Float) = 1
}
SubShader
{
Pass{
ZWrite Off
Blend[_SrcBlend][_DstBlend]
Pass
{
ZWrite Off
Blend[_SrcBlend][_DstBlend]
CGPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
CGPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma vertex VertDeferred
#pragma fragment FragDeferred
#pragma vertex VertDeferred
#pragma fragment FragDeferred
#define UNITY_SHADERRENDERPASS UNITY_SHADERRENDERPASS_DEFERRED
// CAUTION: In case deferred lighting need to support various lighting model statically, we will require to do multicompile with different define like UNITY_MATERIAL_DISNEYGXX
#define UNITY_MATERIAL_DISNEYGXX // Need to be define before including Material.hlsl
#include "Lighting/Lighting.hlsl" // This include Material.hlsl
#include "ShaderVariables.hlsl"
#define UNITY_SHADERRENDERPASS UNITY_SHADERRENDERPASS_DEFERRED
// CAUTION: In case deferred lighting need to support various lighting model statically, we will require to do multicompile with different define like UNITY_MATERIAL_DISNEYGXX
#define UNITY_MATERIAL_DISNEYGXX // Need to be define before including Material.hlsl
#include "Lighting.hlsl" // This include Material.hlsl
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderVariables.hlsl"
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;
sampler2D _CameraGBufferTexture3;
DECLARE_GBUFFER_TEXTURE(_CameraGBufferTexture);
Texture2D _CameraDepthTexture;
sampler2D_float _CameraDepthTexture;
float4x4 _InvProjMatrix;
float _LightAsQuad;
struct Attributes
{
float3 positionOS : POSITION;
};
struct Attributes
{
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 positionHS : SV_POSITION;
};
struct Varyings
{
float4 positionHS : SV_POSITION;
float4 uv : TEXCOORD0;
float3 ray : TEXCOORD1;
};
Varyings VertDeferred(Attributes input)
{
// TODO: implement SV_vertexID full screen quad
// Lights are draw as one fullscreen quad
Varyings output;
float3 positionWS = TransformObjectToWorld(input.positionOS);
output.positionHS = TransformWorldToHClip(positionWS);
Varyings VertDeferred(Attributes input)
{
Varyings output;
output.positionWS = TransformObjectToWorld(input.positionOS);
output.positionHS = TransformWorldToHClip(output.positionWS);
output.uv = ComputeScreenPos(o.positionOS);
output.ray = TransformObjectToView(input.positionOS) * float3(-1, -1, 1);
return output;
}
// normal contains a ray pointing from the camera to one of near plane's
// corners in camera space when we are drawing a full screen quad.
// Otherwise, when rendering 3D shapes, use the ray calculated here.
output.ray = lerp(output.ray, normalOS, _LightAsQuad);
float4 FragDeferred(Varyings input) : SV_Target
{
// TEMP: It is cheaper to pass inv screen size than using GetDimension on GCN
uint width;
uint height;
_CameraDepthTexture.GetDimensions(width, height);
Coordinate coord = GetCoordinate(input.positionHS.xy, float2(width, height));
return output;
}
// No need to manage inverse depth, this is handled by the projection matrix
float depth = _CameraDepthTexture.Load(uint3(coord.unPositionSS, 0)).x;
float3 positionWS = UnprojectToWorld(depth, coord.positionSS, _InvProjMatrix);
float3 V = GetWorldSpaceNormalizeViewDir(positionWS);
float4 FragDeferred(Varyings input) : SV_Target
{
/*
input.ray = input.ray * tex2D(_CameraDepthTexture.z / input.ray.z);
float2 uv = input.uv.xy / input.uv.w;
FETCH_GBUFFER(gbuffer, _CameraGBufferTexture, coord.unPositionSS);
BSDFData bsdfData = DECODE_FROM_GBUFFER(gbuffer);
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
depth = Linear01Depth(depth);
float4 vpos = float4(i.ray * depth, 1);
float3 wpos = mul(unity_CameraToWorld, vpos).xyz;
// NOTE: Currently calling the forward loop, same code... :)
float4 diffuseLighting;
float4 specularLighting;
ForwardLighting(V, positionWS, bsdfData, diffuseLighting, specularLighting);
// read depth and reconstruct world position
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
depth = Linear01Depth(depth);
float4 vpos = float4(i.ray * depth, 1);
float3 wpos = mul(unity_CameraToWorld, vpos).xyz;
return float4(diffuseLighting.rgb + specularLighting.rgb, 1.0);
}
// unpack Gbuffer
float4 gbuffer0 = tex2D(_CameraGBufferTexture0, input.uv);
float4 gbuffer1 = tex2D(_CameraGBufferTexture1, input.uv);
float4 gbuffer2 = tex2D(_CameraGBufferTexture2, input.uv);
float4 gbuffer3 = tex2D(_CameraGBufferTexture3, input.uv);
BSDFData bsdfData = DecodeFromGBuffer(gbuffer0, gbuffer1, gbuffer2);
return bsdfData.diffuseColor;
*/
return float4(1, 0, 0, 0);
ENDCG
ENDCG
}
}
Fallback Off

6
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl


// TODO: Think about how to apply Disney diffuse preconvolve on indirect diffuse => must be done during GBuffer layout! Else emissive will be fucked...
// That's mean we need to read DFG texture during Gbuffer...
void ForwardLighting(float3 V, float3 positionWS, BSDFData material,
out float4 diffuseLighting,
out float4 specularLighting)
void ForwardLighting( float3 V, float3 positionWS, BSDFData material,
out float4 diffuseLighting,
out float4 specularLighting)
{
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
specularLighting = float4(0.0, 0.0, 0.0, 0.0);

38
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/DisneyGGX.hlsl


float smoothness;
float3 normal; // normal in world space
// TODO: create a system surfaceData for thing like that + Transparent
// As we collect some lighting information (Lightmap, lightprobe/proxy volume)
// and emissive ahead (i.e in Gbuffer pass when doing deferred), we need to
// to have them in the SurfaceData structure.
float3 baked;
float3 emissiveColor; // Linear space
float emissiveIntensity;
};
struct BSDFData

float3 normalWS;
float roughness;
// System
float3 bakedAndEmissive;
};
//-----------------------------------------------------------------------------

output.normalWS = data.normal;
output.roughness = PerceptualRoughnessToRoughness(output.perceptualRoughness);
output.bakedAndEmissive = data.baked + data.emissiveColor * data.emissiveIntensity;
#define GBUFFER_COUNT 4
void EncodeIntoGBuffer(SurfaceData data, out float4 outGBuffer0, out float4 outGBuffer1, out float4 outGBuffer2)
void EncodeIntoGBuffer(SurfaceData data, out float4 outGBuffer0, out float4 outGBuffer1, out float4 outGBuffer2, out float4 outGBuffer3)
{
// RT0: diffuse color (rgb), occlusion (a) - sRGB rendertarget
outGBuffer0 = float4(data.diffuseColor, data.occlusion);

// RT2: normal (rgb), --unused, very low precision-- (a)
outGBuffer2 = float4(PackNormalCartesian(data.normal), 1.0f);
// RT3: 11, 11, 10 float
outGBuffer3 = float4(data.baked + data.emissiveColor * data.emissiveIntensity, 0.0f);
BSDFData DecodeFromGBuffer(float4 inGBuffer0, float4 inGBuffer1, float4 inGBuffer2)
BSDFData DecodeFromGBuffer(float4 inGBuffer0, float4 inGBuffer1, float4 inGBuffer2, float4 inGBuffer3)
BSDFData output;
BSDFData bsdfData;
bsdfData.diffuseColor = inGBuffer0.rgb;
bsdfData.occlusion = inGBuffer0.a;
output.diffuseColor = inGBuffer0.rgb;
output.occlusion = inGBuffer0.a;
bsdfData.fresnel0 = inGBuffer1.rgb;
bsdfData.perceptualRoughness = inGBuffer1.a;
output.fresnel0 = inGBuffer1.rgb;
output.perceptualRoughness = inGBuffer1.a;
bsdfData.normalWS = UnpackNormalCartesian(inGBuffer2.rgb);
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
output.normalWS = UnpackNormalCartesian(inGBuffer2.rgb);
output.roughness = PerceptualRoughnessToRoughness(output.perceptualRoughness);
bsdfData.bakedAndEmissive = inGBuffer3.rgb;
return output;
return bsdfData;
}
//-----------------------------------------------------------------------------

60
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl


#ifndef UNITY_MATERIAL_INCLUDED
#define UNITY_MATERIAL_INCLUDED
#include "../../ShaderLibrary/Packing.hlsl"
#include "../../ShaderLibrary/BSDF.hlsl"
#include "../../ShaderLibrary/CommonLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl"
#include "../LightDefinition.cs"
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs"
#include "CommonMaterial.hlsl"
// Here we include all the different lighting model supported by the renderloop based on define done in .shader

//-----------------------------------------------------------------------------
// Define for GBuffer
//-----------------------------------------------------------------------------
#ifdef GBUFFER_COUNT
#if GBUFFER_COUNT == 3
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2);
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0));
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, NAME) EncodeIntoGBuffer(SURFACE_DATA, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2))
#define DECODE_FROM_GBUFFER(NAME) DecodeFromGBuffer(MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2))
#elif GBUFFER_COUNT == 4
#define OUTPUT_GBUFFER(NAME) \
out float4 MERGE_NAME(NAME, 0) : SV_Target0, \
out float4 MERGE_NAME(NAME, 1) : SV_Target1, \
out float4 MERGE_NAME(NAME, 2) : SV_Target2, \
out float4 MERGE_NAME(NAME, 3) : SV_Target3
#define DECLARE_GBUFFER_TEXTURE(NAME) \
Texture2D MERGE_NAME(NAME, 0); \
Texture2D MERGE_NAME(NAME, 1); \
Texture2D MERGE_NAME(NAME, 2); \
Texture2D MERGE_NAME(NAME, 3);
#define FETCH_GBUFFER(NAME, TEX, UV) \
float4 MERGE_NAME(NAME, 0) = MERGE_NAME(TEX, 0).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 1) = MERGE_NAME(TEX, 1).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 2) = MERGE_NAME(TEX, 2).Load(uint3(UV, 0)); \
float4 MERGE_NAME(NAME, 3) = MERGE_NAME(TEX, 3).Load(uint3(UV, 0));
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, NAME) EncodeIntoGBuffer(SURFACE_DATA, MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3))
#define DECODE_FROM_GBUFFER(NAME) DecodeFromGBuffer(MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3))
#endif
#endif // #ifdef GBUFFER_COUNT
#endif // UNITY_MATERIAL_INCLUDED

1
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/PostProcess/FinalPass.shader


#include "../ShaderVariables.hlsl"
sampler2D _MainTex;
uniform float4 _MainTex_ST;
struct Attributes {
float3 vertex : POSITION;

20
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/ShaderVariables.hlsl


// As I haven't change the variables name yet, I simply don't define anything, and I put the transform function at the end of the file outside the guard header.
// This need to be fixed.
float4x4 glstate_matrix_inv_projection;
#ifndef UNITY_SHADER_VARIABLES_INCLUDED
#define UNITY_SHADER_VARIABLES_INCLUDED

return unity_MatrixVP;
}
// Transform from clip space to homogenous world space
float4x4 GetClipToHWorldMatrix()
{
return glstate_matrix_inv_projection;
}
float4x4 GetObjectToWorldViewMatrix()
{
return glstate_matrix_modelview0;

#endif
}
// Tranforms position from view to homogenous space
// Tranforms position from world space to homogenous space
float4 TransformWorldToHClip(float3 positionWS)
{
return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));

{
return normalize(_WorldSpaceCameraPos.xyz - positionWS);
}
float4 ComputeScreenPos(float4 positionH)
{
// TODO: upgrade this function to work for compute shader and pixel shaders
float4 positionSS = positionH * 0.5f;
positionSS.xy = float2(positionSS.x, positionSS.y * _ProjectionParams.x) + positionSS.w;
positionSS.zw = positionH.zw;
return positionSS;
}

10
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/TemplateDisneyGGX.hlsl


#endif
//-------------------------------------------------------------------------------------
// Fill SurfaceData function
// Fill SurfaceData/Lighting data function
//-------------------------------------------------------------------------------------
SurfaceData GetSurfaceData(Varyings input)

data.smoothness = _Smoothness;
data.normal = input.tangentToWorld[2].xyz;//UnpackNormalDXT5nm(tex2D(_NormalMap, input.texCoord0));
// TODO: Sample lightmap/lightprobe/volume proxy
// This should also handle projective lightmap
// Note that data input above can be use to sample into lightmap (like normal)
data.baked = float3(0.0, 0.0, 0.0);
data.emissiveColor = float3(0.0, 0.0, 0.0);
data.emissiveIntensity = 0.0;
return data;
}

56
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


// The lighting code assume that 1 Unity unit (1uu) == 1 meters. This is very important regarding physically based light unit and inverse square attenuation
// When declaring "out" argument of function, they are always last
// Include language header
#if defined(SHADER_API_D3D11)

#define INV_FOUR_PI 0.07957747155f
#define HALF_PI 1.57079632679f
#define INV_HALF_PI 0.636619772367f
#define MERGE_NAME(X, Y) X##Y
// Ref: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
float FastACos(float inX)

// ----------------------------------------------------------------------------
// World position reconstruction / transformation
// ----------------------------------------------------------------------------
struct Coordinate
{
// Normalize coordinates
float2 positionSS;
// Unormalize coordinates
int2 unPositionSS;
};
// This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.
// This allow to easily share code.
// If a compute shader call this function inPositionSS is an interger usually calculate like: uint2 inPositionSS = groupId.xy * BLOCK_SIZE + groupThreadId.xy
// else it is current unormalized screen coordinate like return by VPOS
Coordinate GetCoordinate(float2 inPositionSS, float2 invScreenSize)
{
Coordinate coord;
coord.positionSS = inPositionSS;
// TODO: How to detect automatically that we are a compute shader ?
// #if
// In case of compute shader an extra half offset is added to the screenPos to shift the integer position to pixel center.
// coord.positionSS.xy += float2(0.5f, 0.5f);
//#endif
coord.positionSS *= invScreenSize;
coord.unPositionSS = int2(inPositionSS);
return coord;
}
// screenPos is screen coordinate in [0..1]
// depth come directly from the depth buffer without any transformation
float4 GetClipPosition(float depth, float2 screenPos)
{
float4 positionCS = float4(screenPos.xy, depth, 1.0);
positionCS.xyz = positionCS.xyz * 2.0f - 1.0f;
#if UNITY_UV_STARTS_AT_TOP == 1
positionCS.y = -positionCS.y;
#endif
return positionCS;
}
// screenPos is screen coordinate in [0..1]
// (can be provide by VPOS and divide by screen size)
float3 UnprojectToWorld(float depth, float2 screenPos, float4x4 invViewProjectionMatrix)
{
float4 positionCS = GetClipPosition(depth, screenPos);
float4 hpositionWS = mul(invViewProjectionMatrix, positionCS);
return hpositionWS.xyz / hpositionWS.w;
}
#endif // UNITY_COMMON_INCLUDED

9
Assets/ScriptableRenderLoop/ShaderLibrary/Postprocress.meta


fileFormatVersion: 2
guid: d90c5a99d7855ad46b792d749ce7ca6f
folderAsset: yes
timeCreated: 1472140530
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存