浏览代码

HDRenderLoop: Continue to work on implementing parallax cubemap

- Finish shader side, need to fix C++ side + generate specularDFG
texture
/main
Sebastien Lagarde 8 年前
当前提交
a703417e
共有 10 个文件被更改,包括 187 次插入58 次删除
  1. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  2. 29
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs
  3. 37
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs.hlsl
  4. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightingForward.hlsl
  5. 122
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl
  6. 1
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
  7. 6
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  8. 3
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  9. 31
      Assets/ScriptableRenderLoop/ShaderLibrary/GeometricTools.hlsl
  10. 10
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl

2
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


Vector4 screenSize = ComputeScreenSize(camera);
m_DeferredMaterial.SetVector("_ScreenSize", screenSize);
m_DeferredMaterial.SetTexture("_ReflCubeTextures", m_cubeReflTexArray.GetTexCache());
m_DeferredMaterial.SetTexture("_EnvTextures", m_cubeReflTexArray.GetTexCache());
// gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures

29
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs


};
[GenerateHLSL]
public enum EnvShapeType
{
None,
Box,
Sphere
};
[GenerateHLSL]
public EnvShapeType shapeType;
public Matrix4x4 worldToLocal; // No scale
public Vector3 innerDistance;
public int sliceIndex;
public Vector3 capturePointWS;
public float blendDistance;
/*
volumeWorldToLocal
shapeType - ENV_BOX_PROJECTED
innerDistance - vBoxInnerDist
blendDistance - fProbeBlendDistance
capturePointWS - vLocalCubeCapturePoint // Caution, not the same space local vs world
sliceIndex
light.positionWS
sphereRadius (i.e innerDistance.x)
*/
};
[GenerateHLSL]

37
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs.hlsl


// This file was automatically generated from Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/LightDefinition.cs. Please don't edit by hand.
//
//
// UnityEngine.ScriptableRenderLoop.EnvShapeType: static fields
//
#define ENVSHAPETYPE_NONE (0)
#define ENVSHAPETYPE_BOX (1)
#define ENVSHAPETYPE_SPHERE (2)
// Generated from UnityEngine.ScriptableRenderLoop.PunctualLightData
// PackingRules = Exact
struct PunctualLightData

struct EnvLightData
{
float3 positionWS;
int shapeType;
float4x4 worldToLocal;
float3 innerDistance;
int sliceIndex;
float3 capturePointWS;
float blendDistance;
};
// Generated from UnityEngine.ScriptableRenderLoop.PlanarLightData

float3 GetPositionWS(EnvLightData value)
{
return value.positionWS;
}
int GetShapeType(EnvLightData value)
{
return value.shapeType;
}
float4x4 GetWorldToLocal(EnvLightData value)
{
return value.worldToLocal;
}
float3 GetInnerDistance(EnvLightData value)
{
return value.innerDistance;
}
int GetSliceIndex(EnvLightData value)
{
return value.sliceIndex;
}
float3 GetCapturePointWS(EnvLightData value)
{
return value.capturePointWS;
}
float GetBlendDistance(EnvLightData value)
{
return value.blendDistance;
}
//

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


StructuredBuffer<PunctualLightData> _PunctualLightList;
int _PunctualLightCount;
UNITY_DECLARE_ENV(_ReflCubeTextures);
UNITY_DECLARE_ENV(_EnvTextures);
StructuredBuffer<EnvLightData> _EnvLightList;
int _EnvLightCount;

{
float4 localDiffuseLighting;
float4 localSpecularLighting;
EvaluateBSDF_Env(V, positionWS, prelightData, _EnvLightList[j], bsdfData, UNITY_PASS_ENV(_ReflCubeTextures), localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Env(V, positionWS, prelightData, _EnvLightList[j], bsdfData, UNITY_PASS_ENV(_EnvTextures), localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}

122
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit.hlsl


bsdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness);
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
bsdfData.materialId = surfaceData.materialId;
bsdfData.diffuseColor = surfaceData.baseColor;
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
{

struct PreLightData
{
float NdotV;
float3 R;
float ggxLambdaV;
// Aniso

float anisoGGXLambdaV;
float3 anisoNormalWS;
float3 anisoR; // TODO: check if this is needed, I don't think we use R anymore for other thing than imagebased lighting
// image based lighting
float3 specularDFG;
// image based lighting
// These variables aim to be use with EvaluateBSDF_Env
float3 iblNormalWS; // Normal to be use with image based lighting
float3 iblR; // Reflction vector, same as above.
float3 specularDFG; // Store preconvole BRDF for both specular and diffuse
float diffuseDFG;
// TODO: if we want we can store ambient occlusion here from SSAO pass for example that can be use for IBL specular occlusion

PreLightData GetPreLightData(float3 V, float3 positionWS, Coordinate coord, BSDFData bsdfData)
{
PreLightData preLightData = (PreLightData)0;
PreLightData preLightData;
preLightData.NdotV = GetShiftedNdotV(bsdfData.normalWS, V);
preLightData.NdotV = GetShiftedNdotV(bsdfData.normalWS, V); // Note: May not work with speedtree...
preLightData.R = reflect(-V, bsdfData.normalWS);
// Check if we precompute anisotropy too (should not be necessary as if the variables are not used they will be optimize out, but may avoid
float iblNdotV = preLightData.NdotV;
float3 iblNormalWS = bsdfData.normalWS;
// Check if we precompute anisotropy too
preLightData.TdotV = dot(bsdfData.tangentWS, bsdfData.normalWS);
preLightData.BdotV = dot(bsdfData.bitangentWS, bsdfData.normalWS);
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.anisoNormalWS = GetAnisotropicModifiedNormal(bsdfData.normalWS, bsdfData.tangentWS, V, bsdfData.anisotropy);
// We need to take into account the modified normal for faking anisotropic here.
float anisoNdotV = GetNdotV(preLightData.anisoNormalWS, V); // TODO: is it necessary here to use the GetNDotV function
preLightData.anisoR = reflect(-V, preLightData.anisoNormalWS); // TODO: check if this is needed, I don't think we use R anymore for other thing than imagebased lighting
GetPreIntegratedDFG(anisoNdotV, bsdfData.roughness, bsdfData.fresnel0, preLightData.specularDFG, preLightData.diffuseDFG);
}
else
{
GetPreIntegratedDFG(preLightData.NdotV, bsdfData.roughness, bsdfData.fresnel0, preLightData.specularDFG, preLightData.diffuseDFG);
iblNormalWS = GetAnisotropicModifiedNormal(bsdfData.normalWS, bsdfData.tangentWS, V, bsdfData.anisotropy);
// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NDotV) and use iblNormalWS
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
// With this in mind and for performance reasons we chose to only use modified normal to calculate R.
// iblNdotV = GetNdotV(iblNormalWS, V);
// We need to take into account the modified normal for faking anisotropic here.
preLightData.iblR = reflect(-V, iblNormalWS);
GetPreIntegratedDFG(iblNdotV, bsdfData.roughness, bsdfData.fresnel0, preLightData.specularDFG, preLightData.diffuseDFG);
// #if SHADERPASS == SHADERPASS_GBUFFER
// preLightData.ambientOcclusion = _AmbientOcclusion.Load(uint3(coord.unPositionSS, 0)).x;

// _preIntegratedFG and _CubemapLD are unique for each BRDF
void EvaluateBSDF_Env( float3 V, float3 positionWS, PreLightData prelightData, EnvLightData lightData, BSDFData bsdfData,
UNITY_ARGS_ENV(_ReflCubeTextures),
UNITY_ARGS_ENV(_EnvTextures),
/*
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
// Use fake aniso normal
// We can overwrite locally the normal without problem
bsdfData.normalWS = bsdfData.anisoNormalWS;
prelightData.R = prelightData.anisoR;
}
// TODO: test the strech from Tomasz
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV);
// Note: As explain in GetPreLightData we use normalWS and not iblNormalWS here (in case of anisotropy)
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness);
// Perform box collision to parallax correct the cubemap
// invTransform go from worldspace to local box space without scaling
float3 positionLS = mul(float4(positionWS, 1.0), lightData.invTransform).xyz;
float3 dirLS = mul(prelightData.R, (float3x3)lightData.invTransform);
float2 intersections = BoxRayIntersect(positionLS, dirLS, -lightData.extend, lightData.extend);
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
float3 R = rayWS;
float weight = 1.0;
if (intersections.y > intersections.x)
if (lightData.shapeType == ENVSHAPETYPE_BOX)
float3 R = positionLS + intersections.y * dirLS;
// local offset
R = R - light.localOffset;
// worldToLocal assume no scaling
float3 positionLS = mul(lightData.worldToLocal, float4(positionWS, 1.0)).xyz;
float3 rayLS = mul((float3x3)lightData.worldToLocal, rayWS);
float3 boxOuterDistance = lightData.innerDistance + float3(lightData.blendDistance, lightData.blendDistance, lightData.blendDistance);
float dist = BoxRayIntersectSimple(positionLS, rayLS, -boxOuterDistance, boxOuterDistance);
// No need to normalize for fetching cubemap
R = (positionWS + dist * rayWS) - lightData.capturePointWS; // TODO: check that
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
R = GetSpecularDominantDir(bsdfData.normalWS, R, bsdfData.roughness);
// TODO: add distance based roughness
float4 preLD = UNITY_SAMPLE_ENV_LOD(tex, float4(R, lightData.sliceIndex), mip);
specularLighting.rgb = preLD.rgb * prelightData.specularDFG;
// Apply specular occlusion on it
specularLighting.rgb *= bsdfData.specularOcclusion;
// Calculate falloff value, so reflections on the edges of the Volume would gradually blend to previous reflection.
// Also this ensures that pixels not located in the reflection Volume AABB won't
// accidentally pick up reflections from this Volume.
float distFade = DistancePointBox(positionLS, -lightData.innerDistance, lightData.innerDistance);
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
// Smooth weighting
weight = smoothstep01(weight);
*/
else if (lightData.shapeType == ENVSHAPETYPE_SPHERE)
{
float sphereRadius = lightData.innerDistance.x;
float2 intersections;
SphereRayIntersect(intersections, positionWS - lightData.positionWS, R, sphereRadius);
// TODO: check if we can have simplified formula like for box
// No need to normalize for fetching cubemap
R = (positionWS + intersections.y * rayWS) - lightData.capturePointWS;
float distFade = length(positionWS - lightData.positionWS);
weight = saturate(((sphereRadius + lightData.blendDistance) - distFade) / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
}
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
float4 preLD = UNITY_SAMPLE_ENV_LOD(_EnvTextures, float4(R, lightData.sliceIndex), mip);
specularLighting.rgb = preLD.rgb * prelightData.specularDFG;
// Apply specular occlusion on it
specularLighting.rgb *= bsdfData.specularOcclusion;
specularLighting.a = weight;
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
}
#endif // UNITY_MATERIAL_LIT_INCLUDED

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


#include "Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Debug.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/GeometricTools.hlsl"
#include "../ShaderConfig.cs"
#include "../LightDefinition.cs.hlsl"

6
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


return (x < 0.0) ? -t0 : t0;
}
// Same smoothstep except it assume 0, 1 interval for x
float smoothstep01(float x)
{
return x * x * (3.0 - (2.0 * x));
}
// ----------------------------------------------------------------------------
// World position reconstruction / transformation
// ----------------------------------------------------------------------------

3
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


roughnessB = roughness / anisoAspect;
}
// Ref: http://www.nvidia.com/object/real-time-ycocg-dxt-compression.html
// Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// anisotropic ratio (0->no isotropic; 1->full anisotropy in tangent direction)
float3 GetAnisotropicModifiedNormal(float3 N, float3 T, float3 V, float anisotropy)
{

31
Assets/ScriptableRenderLoop/ShaderLibrary/GeometricTools.hlsl


// Intersection functions
//-----------------------------------------------------------------------------
// return furthest near intersection in x and closest far intersection in y
// return furthest near intersection in x and closest far intersection in y
// if (intersections.y > intersections.x) the ray hit the box, else it miss it
// Assume dir is normalize
float2 BoxRayIntersect(float3 start, float3 dir, float3 boxMin, float3 boxMax)
{
float3 invDir = 1.0 / dir;

return intersections;
}
// TODO: Describe difference with above
// AND compare with intersections.y
// Assume dir is normalize
float BoxRayIntersectSimple(float3 start, float3 dir, float3 boxMin, float3 boxMax)
{
float3 invDir = 1.0 / dir;
// Find the ray intersection with box plane
float3 rbmin = (boxMin - start) * invDir;
float3 rbmax = (boxMax - start) * invDir;
float3 rbminmax = (dir > 0.0) ? rbmax : rbmin;
return min(min(rbminmax.x, rbminmax.y), rbminmax.z);
}
// Sphere is at the origin
bool SphereRayIntersect(out float2 intersections, float3 start, float3 dir, float radius)
{

// Distance functions
//-----------------------------------------------------------------------------
/*
float DistanceBoxPoint(float3 boxMin, float3 boxMax, float3 pos)
float DistancePointBox(float3 pos, float3 boxMin, float3 boxMax)
{
// Clamp to find closest point then calc distance
float3 distanceToMin = pos < boxMin ? (boxMin - pos) * (boxMin - pos) : 0.0;

return sqrt(distanceSquare);
}
*/
// TODO: check that this code is effectively equivalent to code above (it should)
// Box is AABB
float3 DistancePointBox(float3 pos, float3 boxMin, float3 boxMax)
{
return length(max(max(pos - boxMax, boxMin - pos), float3(0.0, 0.0, 0.0)));
}
#endif // UNITY_GEOMETRICTOOLS_INCLUDED

10
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


}
// Ref: See "Moving Frostbite to PBR" Listing 22
// This formulation is for GGX only (with smith joint visibility or regular)
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness)
{
float a = 1.0 - roughness;

}
//-------------------------------------------------------------------------------------
// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84
float AnisotropicStrechAtGrazingAngle(float roughness, float perceptualRoughness, float NdotV)
{
return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
}
#endif // UNITY_IMAGE_BASED_LIGHTING_INCLUDED
正在加载...
取消
保存