浏览代码

HDRenderLoop: Add area light code (not working)

/main
sebastienlagarde 8 年前
当前提交
3234ad1e
共有 12 个文件被更改,包括 305 次插入194 次删除
  1. 19
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  2. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs
  3. 113
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs.hlsl
  4. 205
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl
  5. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
  6. 13
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  7. 18
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  8. 3
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  9. 95
      Assets/ScriptableRenderLoop/ShaderLibrary/Sampling.hlsl
  10. 9
      Assets/ScriptableRenderLoop/fptl/RegularForwardLightingTemplate.hlsl.meta
  11. 9
      Assets/ScriptableRenderLoop/fptl/RegularForwardLightingUtils.hlsl.meta
  12. 9
      Assets/ScriptableRenderLoop/fptl/RegularForwardReflectionTemplate.hlsl.meta

19
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


l.color.Set(lightColorR, lightColorG, lightColorB);
// Light direction is opposite to the forward direction
l.forward = -light.light.transform.forward;
// CAUTION: For IES as we inverse forward maybe this will need rotation.
l.forward = light.light.transform.forward; // Note: Light direction is oriented backward (-Z)
l.up = light.light.transform.up;
l.right = light.light.transform.right;

if (probe.texture == null)
continue;
var l = new EnvLightData
{
positionWS = probe.localToWorld.GetColumn(3),
shapeType = EnvShapeType.None
};
var l = new EnvLightData();
l.positionWS = probe.localToWorld.GetColumn(3);
l.shapeType = EnvShapeType.None;
if (probe.boxProjection != 0)
{

// Caution should only be rigid transform, no scale
l.worldToLocal = probe.localToWorld.transpose;
l.right = probe.localToWorld.GetColumn(0);
l.up = probe.localToWorld.GetColumn(1);
l.forward = probe.localToWorld.GetColumn(2);
l.innerDistance = probe.bounds.extents;
l.sliceIndex = m_cubeReflTexArray.FetchSlice(probe.texture);

4
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs


Sphere,
Disk,
Hemisphere,
Cylindre
Cylinder
};
[GenerateHLSL]

public Vector3 right;
public float shadowDimmer;
Matrix4x4 lightVerts;
public Vector2 size;
public float twoSided;

113
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs.hlsl


//
//
// UnityEngine.ScriptableRenderLoop.AreaShapeType: static fields
//
#define AREASHAPETYPE_RECTANGLE (0)
#define AREASHAPETYPE_LINE (1)
#define AREASHAPETYPE_SPHERE (2)
#define AREASHAPETYPE_DISK (3)
#define AREASHAPETYPE_HEMISPHERE (4)
#define AREASHAPETYPE_CYLINDER (5)
//
// UnityEngine.ScriptableRenderLoop.EnvShapeType: static fields
//
#define ENVSHAPETYPE_NONE (0)

struct AreaLightData
{
float3 positionWS;
float invSqrAttenuationRadius;
float3 color;
int shapeType;
float3 forward;
float diffuseScale;
float3 up;
float specularScale;
float3 right;
float shadowDimmer;
float2 size;
float twoSided;
float unused;
};
// Generated from UnityEngine.ScriptableRenderLoop.EnvLightData

float3 positionWS;
int shapeType;
float4x4 worldToLocal;
float3 forward;
int sliceIndex;
float3 up;
float blendDistance;
float3 right;
float unused0;
int sliceIndex;
float unused1;
float blendDistance;
float unused2;
};
// Generated from UnityEngine.ScriptableRenderLoop.PlanarLightData

{
return value.positionWS;
}
float GetInvSqrAttenuationRadius(AreaLightData value)
{
return value.invSqrAttenuationRadius;
}
float3 GetColor(AreaLightData value)
{
return value.color;
}
int GetShapeType(AreaLightData value)
{
return value.shapeType;
}
float3 GetForward(AreaLightData value)
{
return value.forward;
}
float GetDiffuseScale(AreaLightData value)
{
return value.diffuseScale;
}
float3 GetUp(AreaLightData value)
{
return value.up;
}
float GetSpecularScale(AreaLightData value)
{
return value.specularScale;
}
float3 GetRight(AreaLightData value)
{
return value.right;
}
float GetShadowDimmer(AreaLightData value)
{
return value.shadowDimmer;
}
float2 GetSize(AreaLightData value)
{
return value.size;
}
float GetTwoSided(AreaLightData value)
{
return value.twoSided;
}
float GetUnused(AreaLightData value)
{
return value.unused;
}
//
// Accessors for UnityEngine.ScriptableRenderLoop.EnvLightData

{
return value.shapeType;
}
float4x4 GetWorldToLocal(EnvLightData value)
float3 GetForward(EnvLightData value)
return value.worldToLocal;
return value.forward;
}
int GetSliceIndex(EnvLightData value)
{
return value.sliceIndex;
}
float3 GetUp(EnvLightData value)
{
return value.up;
}
float GetBlendDistance(EnvLightData value)
{
return value.blendDistance;
}
float3 GetRight(EnvLightData value)
{
return value.right;
}
float GetUnused0(EnvLightData value)
{
return value.unused0;
int GetSliceIndex(EnvLightData value)
float GetUnused1(EnvLightData value)
return value.sliceIndex;
return value.unused1;
float GetBlendDistance(EnvLightData value)
float GetUnused2(EnvLightData value)
return value.blendDistance;
return value.unused2;
}
//

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


#ifndef UNITY_MATERIAL_LIT_INCLUDED
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
#pragma exclude_renderers gles
#define UNITY_MATERIAL_LIT_INCLUDED
//-----------------------------------------------------------------------------

// SurfaceData is define in Lit.cs which generate Lit.cs.hlsl
#include "Lit.cs.hlsl"
// Reference Lambert diffuse / GGX Specular for IBL and area lights
//#define LIT_DISPLAY_REFERENCE
// TODO: Check if anisotropy with a dynamic if on anisotropy > 0 is performant. Because it may mean we always calculate both isotrpy and anisotropy case.
// Maybe we should always calculate anisotropy in case of standard ? Don't think the compile can optimize correctly.

// 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 = UNITY_SAMPLE_TEX2D_LOD(_LtcGGXMatrix, uv);
preLightData.minV._m00_m02_m11_m20 = UNITY_SAMPLE_TEX2D_LOD(_LtcGGXMatrix, uv, 0);
preLightData.ltcGGXMagnitude = UNITY_SAMPLE_TEX2D_LOD(_LtcGGXMagnitude, uv).w;
preLightData.ltcGGXMagnitude = UNITY_SAMPLE_TEX2D_LOD(_LtcGGXMagnitude, uv, 0).w;
return preLightData;
}

}
//-----------------------------------------------------------------------------
// BSDF share between area light (reference) and punctual light
//-----------------------------------------------------------------------------
void BSDF( float3 V, float3 L, float3 positionWS, PreLightData prelightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
{
float3 H = normalize(V + L);
float LdotH = saturate(dot(L, H));
float NdotH = saturate(dot(bsdfData.normalWS, H));
float NdotL = saturate(dot(bsdfData.normalWS, L));
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float Vis;
float D;
// TODO: this way of handling aniso may not be efficient, or maybe with material classification, need to check perf here
// Maybe always using aniso maybe a win ?
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
float TdotL = saturate(dot(bsdfData.tangentWS, L));
float BdotL = saturate(dot(bsdfData.bitangentWS, L));
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV( prelightData.TdotV, prelightData.BdotV, prelightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, prelightData.anisoGGXlambdaV);
#else
Vis = V_SmithJointGGXAniso( prelightData.TdotV, prelightData.BdotV, prelightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB);
#endif
float TdotH = saturate(dot(bsdfData.tangentWS, H));
float BdotH = saturate(dot(bsdfData.bitangentWS, H));
D = D_GGXAnisoDividePI(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
}
else
{
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, prelightData.NdotV, bsdfData.roughness, prelightData.ggxLambdaV);
#else
Vis = V_SmithJointGGX(NdotL, prelightData.NdotV, bsdfData.roughness);
#endif
D = D_GGXDividePI(NdotH, bsdfData.roughness);
}
specularLighting.rgb = F * Vis * D;
#ifdef DIFFUSE_LAMBERT_BRDF
float diffuseTerm = LambertDividePI();
#else
float diffuseTerm = DisneyDiffuseDividePI(prelightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
#endif
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Punctual
//-----------------------------------------------------------------------------

float3 L = normalize(unL);
float attenuation = GetDistanceAttenuation(unL, lightData.invSqrAttenuationRadius);
attenuation *= GetAngleAttenuation(L, lightData.forward, lightData.angleScale, lightData.angleOffset);
// Reminder: lights are ortiented backward (-Z)
attenuation *= GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
float illuminance = saturate(dot(bsdfData.normalWS, L)) * attenuation;
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);

{
float3 H = normalize(V + L);
float LdotH = saturate(dot(L, H));
float NdotH = saturate(dot(bsdfData.normalWS, H));
float NdotL = saturate(dot(bsdfData.normalWS, L));
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float Vis;
float D;
// TODO: this way of handling aniso may not be efficient, or maybe with material classification, need to check perf here
// Maybe always using aniso maybe a win ?
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
float TdotL = saturate(dot(bsdfData.tangentWS, L));
float BdotL = saturate(dot(bsdfData.bitangentWS, L));
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV( prelightData.TdotV, prelightData.BdotV, prelightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, prelightData.anisoGGXlambdaV);
#else
Vis = V_SmithJointGGXAniso( prelightData.TdotV, prelightData.BdotV, prelightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB);
#endif
float TdotH = saturate(dot(bsdfData.tangentWS, H));
float BdotH = saturate(dot(bsdfData.bitangentWS, H));
D = D_GGXAnisoDividePI(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
}
else
{
#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, prelightData.NdotV, bsdfData.roughness, prelightData.ggxLambdaV);
#else
Vis = V_SmithJointGGX(NdotL, prelightData.NdotV, bsdfData.roughness);
#endif
D = D_GGXDividePI(NdotH, bsdfData.roughness);
}
specularLighting.rgb = F * Vis * D;
#ifdef DIFFUSE_LAMBERT_BRDF
float diffuseTerm = LambertDividePI();
#else
float diffuseTerm = DisneyDiffuseDividePI(prelightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
#endif
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;
diffuseLighting.rgb *= lightData.color * illuminance;
specularLighting.rgb *= lightData.color * illuminance;
BSDF(V, L, positionWS, prelightData, bsdfData, diffuseLighting.rgb, specularLighting.rgb);
diffuseLighting.rgb *= lightData.color * illuminance * lightData.diffuseScale;
specularLighting.rgb *= lightData.color * illuminance * lightData.specularScale;
}
}

// We calculate area reference light with the area integral rather than the solid angle one.
void evaluateAreaLightReference(float3 V, float3 positionWS, AreaLightData lightData, BSDFData bsdfData,
void IntegrateGGXAreaRef(float3 V, float3 positionWS, PreLightData prelightData, AreaLightData lightData, BSDFData bsdfData,
out float4 diffuseLighting,
out float4 specularLighting,
uint sampleCount = 512)

// Accumulate this light locally, then add on at the end (avoids any accidental multiplies of in/out accumulated variables)
float3 accBottom = float3(0.0, 0.0, 0.0);
float3 accTop = float3(0.0, 0.0, 0.0);
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
for (uint i = 0; i < sampleCount; ++i)
{

float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(light.positionWS, 1.0));
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(lightData.positionWS, 1.0));
if (areaLightType == AREASHAPETYPE_SPHERE)
sampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (areaLightType == AREASHAPETYPE_HEMISPHERE)
sampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (areaLightType == AREASHAPETYPE_CYLINDER)
sampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (areaLightType == AREASHAPETYPE_RECTANGLE)
sampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (areaLightType == AREASHAPETYPE_DISK)
sampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (areaLightType == AREASHAPETYPE_LINE)
// sampleLine(u, localToWorld, areaLight.lightRadius0, lightPdf, P, Ns);
if (lightData.shapeType == AREASHAPETYPE_SPHERE)
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.shapeType == AREASHAPETYPE_HEMISPHERE)
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.shapeType == AREASHAPETYPE_CYLINDER)
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (lightData.shapeType == AREASHAPETYPE_RECTANGLE)
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (lightData.shapeType == AREASHAPETYPE_DISK)
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.shapeType == AREASHAPETYPE_LINE)
// SampleLine(u, localToWorld, areaLight.lightRadius0, lightPdf, P, Ns);
float3 unL = P - worldPos;
float3 unL = P - positionWS;
// We calculate area reference light with the area integral rather than the solid angle one.
float3 localDiffuse = float3(0.0, 0.0, 0.0);
float3 localSpecular = float3(0.0, 0.0, 0.0);
float3 localDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 localSpecularLighting = float3(0.0, 0.0, 0.0);
// TODO
// BSDF(V, L, data localDiffuse, localSpecular);
localDiffuse *= illuminance;
localSpecular *= illuminance;
BSDF(V, L, positionWS, prelightData, bsdfData, localDiffuseLighting, localSpecularLighting);
localDiffuseLighting *= lightData.color * illuminance * lightData.diffuseScale;
localSpecularLighting *= lightData.color * illuminance * lightData.specularScale;
accBottom += localDiffuse;
accTop += localSpecular;
diffuseLighting.rgb += localDiffuseLighting;
specularLighting.rgb += localSpecularLighting;
// Generate the final values to accumulate
float3 localBottom = (accBottom / float(sampleCount)) * light.color * light.diffuseScale;
float3 localTop = (accTop / float(sampleCount)) * light.color * light.specularScale;
// Accumulate this light into in/out accumulation variables
outBottom += localBottom;
outTop += localTop;
diffuseLighting.rgb /= float(sampleCount);
specularLighting.rgb /= float(sampleCount);
}
//-----------------------------------------------------------------------------

out float4 diffuseLighting,
out float4 specularLighting)
{
// Can be precomputed - light.LightVerts is a tab of 4 vertices representing the light quad
// TODO: can be simplify as a rect, with extend
float4x3 L = lightData.lightVerts - float4x3(positionWS, positionWS, positionWS, positionWS);
#ifdef LIT_DISPLAY_REFERENCE
IntegrateGGXAreaRef(V, positionWS, prelightData, lightData, bsdfData, diffuseLighting, specularLighting);
#else
// TODO: This could be precomputed
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;
float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;
float3 p3 = lightData.positionWS + lightData.right * halfWidth + lightData.up * halfHeight;
float4x3 matL = float4x3(p0, p1, p2, p3);
float4x3 L = matL - float4x3(positionWS, positionWS, positionWS, positionWS);
// TODO: Can we get early out based on diffuse computation ? (if all point are clip)
diffuseLighting = float4(0.0f, 0.0f, 0.0f, 1.0f);

specularLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, prelightData.minV, L) prelightData.ltcGGXMagnitude;
specularLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, prelightData.minV, L, lightData.twoSided) * prelightData.ltcGGXMagnitude;
diffuseLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, identity, L) * bsdfData.diffuseColor;
diffuseLighting.rgb = LTCEvaluate(V, bsdfData.normalWS, identity, L, lightData.twoSided) * bsdfData.diffuseColor;
diffuseLighting.rgb *= lightData.color / (2 * PI);
specularLighting.rgb *= lightData.color / (2 * PI);
diffuseLighting.rgb *= lightData.color * INV_TWO_PI * lightData.diffuseScale;
specularLighting.rgb *= lightData.color * INV_TWO_PI * lightData.specularScale;
#endif
}
//-----------------------------------------------------------------------------

out float4 diffuseLighting,
out float4 specularLighting)
{
// Reference Lambert diffuse / GGX Specular
//#define LIT_DISPLAY_REFERENCE
#ifdef LIT_DISPLAY_REFERENCE
specularLighting.rgb = IntegrateSpecularGGXIBLRef(V, lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures));

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


#include "Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Sampling.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/Debug.hlsl"
#include "Assets/ScriptableRenderLoop/ShaderLibrary/GeometricTools.hlsl"

13
Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl


#ifndef UNITY_AREA_LIGHTING_INCLUDED
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
#pragma exclude_renderers gles
float3 cosTheta = dot(v1, v2);
float cosTheta = dot(v1, v2);
// TODO: Explain the 0.9999 <= precision is important!
float3 theta = acos(cosTheta);
float3 res = cross(v1, v2).z * theta / sin(theta);
float theta = acos(cosTheta);
float res = cross(v1, v2).z * theta / sin(theta);
return res;
}

return twoSided > 0.0 ? abs(sum) : max(0.0, sum);
}
float LTCEvaluate(float3 V, float3 N, float3x3 minV, float4x3 L)
float LTCEvaluate(float3 V, float3 N, float3x3 minV, float4x3 L, bool twoSided)
{
// Construct local orthonormal basis around N, aligned with N
float3x3 basis;

L = mul(L, minV);
// Polygon radiance in transformed configuration - specular
return PolygonRadiance(L);
return PolygonRadiance(L, twoSided);
}
#endif // UNITY_AREA_LIGHTING_INCLUDED

18
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


// Common math definition and fastmath function
// ----------------------------------------------------------------------------
#define PI 3.14159265359f
#define TWO_PI 6.28318530718f
#define FOUR_PI 12.56637061436f
#define INV_PI 0.31830988618f
#define INV_TWO_PI 0.15915494309f
#define INV_FOUR_PI 0.07957747155f
#define HALF_PI 1.57079632679f
#define INV_HALF_PI 0.636619772367f
#define PI 3.14159265359
#define TWO_PI 6.28318530718
#define FOUR_PI 12.56637061436
#define INV_PI 0.31830988618
#define INV_TWO_PI 0.15915494309
#define INV_FOUR_PI 0.07957747155
#define HALF_PI 1.57079632679
#define INV_HALF_PI 0.636619772367
#define FLT_EPSILON 1.192092896e-07f // smallest such that 1.0 + FLT_EPSILON != 1.0
#define MERGE_NAME(X, Y) X##Y

3
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


#ifndef UNITY_COMMON_LIGHTING_INCLUDED
#define UNITY_COMMON_LIGHTING_INCLUDED
// Ligthing convention
// Light direction is oriented backward (-Z). i.e in shader code, light direction is - lightData.forward
//-----------------------------------------------------------------------------
// Attenuation functions
//-----------------------------------------------------------------------------

95
Assets/ScriptableRenderLoop/ShaderLibrary/Sampling.hlsl


//-----------------------------------------------------------------------------
// Sampling function
// Reference : http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf + PBRT
// Caution: Our light point backward (-Z), these sampling function follow this convention
// Reference : Monte Carlo techniques for direct lighting calculations http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf + PBRT
float3 UniformSampleSphere(float u1, float u2)
{
float phi = TWO_PI * u2;

return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // our light point backward (-Z)
return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // Light point backward (-Z)
}
float3 UniformSampleHemisphere(float u1, float u2)

float sinTheta = sqrt(max(0.0, 1.0 - cosTheta * cosTheta));
return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // our light point backward (-Z)
return float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); // Light point backward (-Z)
}
float3 UniformSampleDisk(float u1, float u2)

return float3(r * cos(phi), r * sin(phi), 0); // generate in the XY plane as light point backward (-Z)
return float3(r * cos(phi), r * sin(phi), 0); // Generate in XY plane as light point backward (-Z)
}
void SampleSphere( float2 u,

float u1 = u.x;
float u2 = u.y;
// Random point at light surface
Ns = uniformSampleSphere(u1, u2);
// Transform point on unit sphere to world space
Ns = UniformSampleSphere(u1, u2);
// Transform from unit sphere to world space
// pdf is just the inverse of the area
// pdf is inverse of area
lightPdf = 1.0 / (FOUR_PI * radius * radius);
}

float u1 = u.x;
float u2 = u.y;
// Random point at light surface
Ns = -uniformSampleHemisphere(u1, u2); // We want the y down hemisphere
// Random point at hemisphere surface
Ns = -UniformSampleHemisphere(u1, u2); // We want the y down hemisphere
Ns = mul(Ns, convertFloat3x3(localToWorld));
// pdf is just the inverse of the area
Ns = mul(Ns, (float3x3)(localToWorld));
// pdf is inverse of area
lightPdf = 1.0 / (TWO_PI * radius * radius);
}

float u1 = u.x;
float u2 = u.y;
// Random point at light surface
// Random point at cylinder surface
P = float3(t, radius * cosTheta, radius * sinTheta); // Cylinder are align on the left axis in Frosbite
// Cylinder are align on the right axis
P = float3(t, radius * cosTheta, radius * sinTheta);
Ns = mul(Ns, convertFloat3x3(localToWorld));
// pdf is just the inverse of the area
Ns = mul(Ns, (float3x3)(localToWorld));
// pdf is inverse of area
void SampleCapsule( float2 u,
float4x4 localToWorld,
float radius,
float width,
int passIt,
out float lightPdf,
out float3 P,
out float3 Ns)
{
// Capsules are sampled in two times:
// - Pass 0: Cylinder
// - Pass 1: Hemisphere caps
if (passIt == 0)
{
sampleCylinder(u, localToWorld, radius, width, lightPdf, P, Ns);
}
else
{
float u1 = u.x;
float u2 = u.y;
// Random point at light surface
Ns = uniformSampleSphere(u1, u2);
P = radius * Ns;
// Split the sphere into two hemisphere and shift each hemisphere on one side of the cylinder
P.x += (Ns.x > 0.0 ? 1.0 : -1.0) * 0.5 * width;
// Transform to world space
P = mul(float4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, convertFloat3x3(localToWorld));
// pdf is just the inverse of the area
lightPdf = 1.0 / (FOUR_PI * radius * radius);
}
}
void SampleRectangle( float2 u,
float4x4 localToWorld,
float width,

out float3 Ns)
{
// Random point at light surface
// Random point at rectangle surface
Ns = float3(0, 0, -1); // By default our rectangle light point backward
Ns = float3(0, 0, -1); // Light point backward (-Z)
Ns = mul(Ns, convertFloat3x3(localToWorld));
// pdf is just the inverse of the area
Ns = mul(Ns, (float3x3)(localToWorld));
// pdf is inverse of area
lightPdf = 1.0 / (width * height);
}

out float3 P,
out float3 Ns)
{
// Random point at light surface
P = uniformSampleDisk(u.x, u.y) * radius;
Ns = float3(0.0, 0.0, -1.0);
// Random point at disk surface
P = UniformSampleDisk(u.x, u.y) * radius;
Ns = float3(0.0, 0.0, -1.0); // Light point backward (-Z)
Ns = mul(Ns, convertFloat3x3(localToWorld));
Ns = mul(Ns, (float3x3)(localToWorld));
// pdf is just the inverse of the area
// pdf is inverse of area
lightPdf = 1.0 / (PI * radius * radius);
}

9
Assets/ScriptableRenderLoop/fptl/RegularForwardLightingTemplate.hlsl.meta


fileFormatVersion: 2
guid: addc185d48decc34d9bf21cb3a4ea28c
timeCreated: 1476774180
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/RegularForwardLightingUtils.hlsl.meta


fileFormatVersion: 2
guid: 13dff6ea8f6c55743a3cbb841066cc27
timeCreated: 1476774180
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/fptl/RegularForwardReflectionTemplate.hlsl.meta


fileFormatVersion: 2
guid: 61d33edab0cf72c4e881ea8c05dcd596
timeCreated: 1476774180
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存