浏览代码

Add Fresnel to LTC. Reduce the number of textures and samplers

/main
Evgenii Golubev 8 年前
当前提交
ebdf0660
共有 2 个文件被更改,包括 88 次插入52 次删除
  1. 52
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.cs
  2. 88
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl

52
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.cs


private RenderTexture m_PreIntegratedFGD;
// For area lighting
private Texture2D m_LtcGGXMatrix;
private Texture2D m_LtcGGXMagnitude;
const int k_LtcLUTMatrixDim = 3; // size of the matrix (3x3)
private Texture2D m_LtcGGXMatrix; // RGBA
private Texture2D m_LtcDisneyDiffuseMatrix; // RGBA
private Texture2D m_LtcMultiGGXFresnelDisneyDiffuse; // RGB, A unused
const int k_LtcLUTMatrixDim = 3; // size of the matrix (3x3)
const int k_LtcLUTResolution = 64;
Material CreateEngineMaterial(string shaderPath)

// transformInv
for (int i = 0; i < count; i++)
{
// Only columns 0, 2, 4 and 6 contain interesting values (at least in the case of GGX).
pixels[i] = new Color( (float)LUTTransformInv[i, 0],
(float)LUTTransformInv[i, 2],
(float)LUTTransformInv[i, 4],
(float)LUTTransformInv[i, 6]);
// Both GGX and Disney Diffuse BRDFs have zero values in columns 1, 3, 5, 7.
// Column 8 contains only ones.
pixels[i] = new Color((float)LUTTransformInv[i, 0],
(float)LUTTransformInv[i, 2],
(float)LUTTransformInv[i, 4],
(float)LUTTransformInv[i, 6]);
// Special-case function for 'm_LtcMultiGGXFresnelDisneyDiffuse'.
Texture2D LoadLUT(TextureFormat format, float[] LtcGGXMagnitudeData,
float[] LtcGGXFresnelData,
float[] LtcDisneyDiffuseMagnitudeData)
{
const int count = k_LtcLUTResolution * k_LtcLUTResolution;
Color[] pixels = new Color[count];
for (int i = 0; i < count; i++)
{
// We store the result of the subtraction as a run-time optimization.
// See the footnote 2 of "LTC Fresnel Approximation" by Stephen Hill.
pixels[i] = new Color(LtcGGXMagnitudeData[i] - LtcGGXFresnelData[i],
LtcGGXFresnelData[i], LtcDisneyDiffuseMagnitudeData[i], 1);
}
return CreateLUT(k_LtcLUTResolution, k_LtcLUTResolution, format, pixels);
}
m_LtcGGXMatrix = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMatrixData);
m_LtcGGXMagnitude = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMagnitudeData);
m_LtcGGXMatrix = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMatrixData);
m_LtcDisneyDiffuseMatrix = LoadLUT(TextureFormat.RGBAHalf, s_LtcDisneyDiffuseMatrixData);
m_LtcMultiGGXFresnelDisneyDiffuse = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMagnitudeData,
s_LtcGGXFresnelData,
s_LtcDisneyDiffuseMagnitudeData);
isInit = false;
}

public void Bind()
{
Shader.SetGlobalTexture("_PreIntegratedFGD", m_PreIntegratedFGD);
Shader.SetGlobalTexture("_LtcGGXMatrix", m_LtcGGXMatrix);
Shader.SetGlobalTexture("_LtcGGXMagnitude", m_LtcGGXMagnitude);
Shader.SetGlobalTexture("_PreIntegratedFGD", m_PreIntegratedFGD);
Shader.SetGlobalTexture("_LtcGGXMatrix", m_LtcGGXMatrix);
Shader.SetGlobalTexture("_LtcDisneyDiffuseMatrix", m_LtcDisneyDiffuseMatrix);
Shader.SetGlobalTexture("_LtcMultiGGXFresnelDisneyDiffuse", m_LtcMultiGGXFresnelDisneyDiffuse);
}
}
}

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


#include "Lit.cs.hlsl"
// Reference Lambert diffuse / GGX Specular for IBL and area lights
//#define LIT_DISPLAY_REFERENCE
// #define LIT_DISPLAY_REFERENCE
// TODO: How can I declare a sampler for this one that is bilinear filtering
SAMPLER2D(sampler_PreIntegratedFGD);
#define SRL_PointSampler sampler_PreIntegratedFGD // Used for all textures
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);
TEXTURE2D(_LtcGGXMatrix); // RGBA
TEXTURE2D(_LtcDisneyDiffuseMatrix); // RGBA
TEXTURE2D(_LtcMultiGGXFresnelDisneyDiffuse); // RGB, A unused
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material

return int(round(f * 3.0));
}
// TODO: How can I declare a sampler for this one that is bilinear filtering
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);
SAMPLER2D(sampler_PreIntegratedFGD);
TEXTURE2D(_LtcGGXMatrix);
SAMPLER2D(sampler_LtcGGXMatrix);
TEXTURE2D(_LtcGGXMagnitude);
SAMPLER2D(sampler_LtcGGXMagnitude);
// For image based lighting, a part of the BSDF is pre-integrated.
// This is done both for specular and diffuse (in case of DisneyDiffuse)
void GetPreIntegratedFGD(float NdotV, float perceptualRoughness, float3 fresnel0, out float3 specularFGD, out float diffuseFGD)

// _PreIntegratedFGD.y = Gv * Fc
// Pre integrate DisneyDiffuse FGD:
// _PreIntegratedFGD.z = DisneyDiffuse
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, sampler_PreIntegratedFGD, float2(NdotV, perceptualRoughness), 0).xyz;
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, SRL_PointSampler, float2(NdotV, perceptualRoughness), 0).xyz;
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;

// 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 iblR; // Reflection vector, same as above.
float3 specularFGD; // Store preconvole BRDF for both specular and diffuse
float diffuseFGD;

// area light
float3x3 minV;
float ltcGGXMagnitude;
float3x3 ltcXformGGX; // TODO: make sure the compiler not wasting VGPRs on constants
float3x3 ltcXformDisneyDiffuse; // TODO: make sure the compiler not wasting VGPRs on constants
float ltcGGXFresnelMagnitudeDiff; // The difference of magnitudes of GGX and Fresnel
float ltcGGXFresnelMagnitude;
float ltcDisneyDiffuseMagnitude;
// Shadow (sampling rotation disc)
float2 unPositionSS;

// Get the inverse LTC matrix for GGX
// Note we load the matrix transpose (avoid to have to transpose it in shader)
preLightData.minV = 0.0;
preLightData.minV._m22 = 1.0;
preLightData.minV._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_LOD(_LtcGGXMatrix, sampler_LtcGGXMatrix, uv, 0);
preLightData.ltcXformGGX = 0.0;
preLightData.ltcXformGGX._m22 = 1.0;
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_LOD(_LtcGGXMatrix, SRL_PointSampler, uv, 0);
preLightData.ltcGGXMagnitude = SAMPLE_TEXTURE2D_LOD(_LtcGGXMagnitude, sampler_LtcGGXMagnitude, uv, 0).w;
// Get the inverse LTC matrix for Disney Diffuse
// Note we load the matrix transpose (avoid to have to transpose it in shader)
preLightData.ltcXformDisneyDiffuse = 0.0;
preLightData.ltcXformDisneyDiffuse._m22 = 1.0;
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_LOD(_LtcDisneyDiffuseMatrix, SRL_PointSampler, uv, 0);
preLightData.ltcGGXFresnelMagnitudeDiff = SAMPLE_TEXTURE2D_LOD(_LtcMultiGGXFresnelDisneyDiffuse, SRL_PointSampler, uv, 0).r;
preLightData.ltcGGXFresnelMagnitude = SAMPLE_TEXTURE2D_LOD(_LtcMultiGGXFresnelDisneyDiffuse, SRL_PointSampler, uv, 0).g;
preLightData.ltcDisneyDiffuseMagnitude = SAMPLE_TEXTURE2D_LOD(_LtcMultiGGXFresnelDisneyDiffuse, SRL_PointSampler, uv, 0).b;
// Shadow
preLightData.unPositionSS = coord.unPositionSS;

IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
#else
// TODO: This could be precomputed
float halfWidth = lightData.size.x * 0.5f;
float halfHeight = lightData.size.y * 0.5f;
float halfWidth = lightData.size.x * 0.5;
float halfHeight = lightData.size.y * 0.5;
float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;

float4x3 matL = float4x3(p0, p1, p2, p3);
float4x3 L = matL - float4x3(positionWS, positionWS, positionWS, positionWS);
diffuseLighting = float4(0.0f, 0.0f, 0.0f, 1.0f);
specularLighting = float4(0.0f, 0.0f, 0.0f, 1.0f);
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
float ltcValue;

static float3x3 identity = {1.f, 0.f, 0.f,
0.f, 1.f, 0.f,
0.f, 0.f, 1.f};
static float3x3 identity = {1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
if (ltcValue == 0.f)
if (ltcValue == 0.0)
// Group scalars.
diffuseLighting.rgb = ltcValue * bsdfData.diffuseColor * lightData.color;
diffuseLighting.rgb = bsdfData.diffuseColor * lightData.color * ltcValue;
//#else
// TODO: Disney
//#endif

{
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.minV, L, lightData.twoSided);
float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
// Group scalars.
// TODO: Fresnel is missing here but should be present.
ltcValue *= preLightData.ltcGGXMagnitude * lightData.specularScale;
specularLighting.rgb = ltcValue * lightData.color;
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.ltcXformGGX, L, lightData.twoSided);
ltcValue *= lightData.specularScale;
specularLighting.rgb = fresnelTerm * lightData.color * ltcValue;
}
// TODO: current area light code doesn't take into account artist attenuation radius!

#ifdef LIT_DISPLAY_REFERENCE
// TODO: fix 'IntegrateSpecularGGXIBLRef'.
//specularLighting.rgb = IntegrateSpecularGGXIBLRef(lightLoopContext, V, lightData, bsdfData);
//specularLighting.a = 1.0;
specularLighting = float4(0.0, 0.0, 0.0, 0.0);
// specularLighting.rgb = IntegrateSpecularGGXIBLRef(lightLoopContext, V, lightData, bsdfData);
// specularLighting.a = 1.0;
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
/*
#ifdef DIFFUSE_LAMBERT_BRDF

#endif
diffuseLighting.a = 1.0;
*/
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
#else
// TODO: factor this code in common, so other material authoring don't require to rewrite everything,

specularLighting.rgb *= bsdfData.specularOcclusion;
specularLighting.a = weight;
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0);
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
#endif
}

正在加载...
取消
保存