testss
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
#ifndef UNITY_SAMPLING_INCLUDED
|
||||
#define UNITY_SAMPLING_INCLUDED
|
||||
|
||||
#if SHADER_API_MOBILE || SHADER_API_GLES || SHADER_API_GLES3
|
||||
#pragma warning (disable : 3205) // conversion of larger type to smaller
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sample generator
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Fibonacci.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Hammersley.hlsl"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Coordinate system conversion
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
|
||||
real3 SphericalToCartesian(real cosPhi, real sinPhi, real cosTheta)
|
||||
{
|
||||
real sinTheta = SinFromCos(cosTheta);
|
||||
|
||||
return real3(real2(cosPhi, sinPhi) * sinTheta, cosTheta);
|
||||
}
|
||||
|
||||
real3 SphericalToCartesian(real phi, real cosTheta)
|
||||
{
|
||||
real sinPhi, cosPhi;
|
||||
sincos(phi, sinPhi, cosPhi);
|
||||
|
||||
return SphericalToCartesian(cosPhi, sinPhi, cosTheta);
|
||||
}
|
||||
|
||||
// Converts Cartesian coordinates given in the right-handed coordinate system
|
||||
// with Z pointing upwards (OpenGL style) to the coordinates in the left-handed
|
||||
// coordinate system with Y pointing up and Z facing forward (DirectX style).
|
||||
real3 TransformGLtoDX(real3 v)
|
||||
{
|
||||
return v.xzy;
|
||||
}
|
||||
|
||||
// Performs conversion from equiareal map coordinates to Cartesian (DirectX cubemap) ones.
|
||||
real3 ConvertEquiarealToCubemap(real u, real v)
|
||||
{
|
||||
real phi = TWO_PI - TWO_PI * u;
|
||||
real cosTheta = 1.0 - 2.0 * v;
|
||||
|
||||
return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
|
||||
}
|
||||
|
||||
// Convert a texel position into normalized position [-1..1]x[-1..1]
|
||||
real2 CubemapTexelToNVC(uint2 unPositionTXS, uint cubemapSize)
|
||||
{
|
||||
return 2.0 * real2(unPositionTXS) / real(max(cubemapSize - 1, 1)) - 1.0;
|
||||
}
|
||||
|
||||
// Map cubemap face to world vector basis
|
||||
static const real3 CUBEMAP_FACE_BASIS_MAPPING[6][3] =
|
||||
{
|
||||
//XPOS face
|
||||
{
|
||||
real3(0.0, 0.0, -1.0),
|
||||
real3(0.0, -1.0, 0.0),
|
||||
real3(1.0, 0.0, 0.0)
|
||||
},
|
||||
//XNEG face
|
||||
{
|
||||
real3(0.0, 0.0, 1.0),
|
||||
real3(0.0, -1.0, 0.0),
|
||||
real3(-1.0, 0.0, 0.0)
|
||||
},
|
||||
//YPOS face
|
||||
{
|
||||
real3(1.0, 0.0, 0.0),
|
||||
real3(0.0, 0.0, 1.0),
|
||||
real3(0.0, 1.0, 0.0)
|
||||
},
|
||||
//YNEG face
|
||||
{
|
||||
real3(1.0, 0.0, 0.0),
|
||||
real3(0.0, 0.0, -1.0),
|
||||
real3(0.0, -1.0, 0.0)
|
||||
},
|
||||
//ZPOS face
|
||||
{
|
||||
real3(1.0, 0.0, 0.0),
|
||||
real3(0.0, -1.0, 0.0),
|
||||
real3(0.0, 0.0, 1.0)
|
||||
},
|
||||
//ZNEG face
|
||||
{
|
||||
real3(-1.0, 0.0, 0.0),
|
||||
real3(0.0, -1.0, 0.0),
|
||||
real3(0.0, 0.0, -1.0)
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a normalized cubemap face position into a direction
|
||||
real3 CubemapTexelToDirection(real2 positionNVC, uint faceId)
|
||||
{
|
||||
real3 dir = CUBEMAP_FACE_BASIS_MAPPING[faceId][0] * positionNVC.x
|
||||
+ CUBEMAP_FACE_BASIS_MAPPING[faceId][1] * positionNVC.y
|
||||
+ CUBEMAP_FACE_BASIS_MAPPING[faceId][2];
|
||||
|
||||
return normalize(dir);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sampling function
|
||||
// Reference : http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf + PBRT
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Performs uniform sampling of the unit disk.
|
||||
// Ref: PBRT v3, p. 777.
|
||||
real2 SampleDiskUniform(real u1, real u2)
|
||||
{
|
||||
real r = sqrt(u1);
|
||||
real phi = TWO_PI * u2;
|
||||
|
||||
real sinPhi, cosPhi;
|
||||
sincos(phi, sinPhi, cosPhi);
|
||||
|
||||
return r * real2(cosPhi, sinPhi);
|
||||
}
|
||||
|
||||
// Performs cubic sampling of the unit disk.
|
||||
real2 SampleDiskCubic(real u1, real u2)
|
||||
{
|
||||
real r = u1;
|
||||
real phi = TWO_PI * u2;
|
||||
|
||||
real sinPhi, cosPhi;
|
||||
sincos(phi, sinPhi, cosPhi);
|
||||
|
||||
return r * real2(cosPhi, sinPhi);
|
||||
}
|
||||
|
||||
real3 SampleConeUniform(real u1, real u2, real cos_theta)
|
||||
{
|
||||
float r0 = cos_theta + u1 * (1.0f - cos_theta);
|
||||
float r = sqrt(max(0.0, 1.0 - r0 * r0));
|
||||
float phi = TWO_PI * u2;
|
||||
return float3(r * cos(phi), r * sin(phi), r0);
|
||||
}
|
||||
|
||||
real3 SampleSphereUniform(real u1, real u2)
|
||||
{
|
||||
real phi = TWO_PI * u2;
|
||||
real cosTheta = 1.0 - 2.0 * u1;
|
||||
|
||||
return SphericalToCartesian(phi, cosTheta);
|
||||
}
|
||||
|
||||
// Performs cosine-weighted sampling of the hemisphere.
|
||||
// Ref: PBRT v3, p. 780.
|
||||
real3 SampleHemisphereCosine(real u1, real u2)
|
||||
{
|
||||
real3 localL;
|
||||
|
||||
// Since we don't really care about the area distortion,
|
||||
// we substitute uniform disk sampling for the concentric one.
|
||||
localL.xy = SampleDiskUniform(u1, u2);
|
||||
|
||||
// Project the point from the disk onto the hemisphere.
|
||||
localL.z = sqrt(1.0 - u1);
|
||||
|
||||
return localL;
|
||||
}
|
||||
|
||||
// Cosine-weighted sampling without the tangent frame.
|
||||
// Ref: http://www.amietia.com/lambertnotangent.html
|
||||
real3 SampleHemisphereCosine(real u1, real u2, real3 normal)
|
||||
{
|
||||
// This function needs to used safenormalize because there is a probability
|
||||
// that the generated direction is the exact opposite of the normal and that would lead
|
||||
// to a nan vector otheriwse.
|
||||
real3 pointOnSphere = SampleSphereUniform(u1, u2);
|
||||
return SafeNormalize(normal + pointOnSphere);
|
||||
}
|
||||
|
||||
real3 SampleHemisphereUniform(real u1, real u2)
|
||||
{
|
||||
real phi = TWO_PI * u2;
|
||||
real cosTheta = 1.0 - u1;
|
||||
|
||||
return SphericalToCartesian(phi, cosTheta);
|
||||
}
|
||||
|
||||
void SampleSphere(real2 u,
|
||||
real4x4 localToWorld,
|
||||
real radius,
|
||||
out real lightPdf,
|
||||
out real3 P,
|
||||
out real3 Ns)
|
||||
{
|
||||
real u1 = u.x;
|
||||
real u2 = u.y;
|
||||
|
||||
Ns = SampleSphereUniform(u1, u2);
|
||||
|
||||
// Transform from unit sphere to world space
|
||||
P = radius * Ns + localToWorld[3].xyz;
|
||||
|
||||
// pdf is inverse of area
|
||||
lightPdf = 1.0 / (FOUR_PI * radius * radius);
|
||||
}
|
||||
|
||||
void SampleHemisphere(real2 u,
|
||||
real4x4 localToWorld,
|
||||
real radius,
|
||||
out real lightPdf,
|
||||
out real3 P,
|
||||
out real3 Ns)
|
||||
{
|
||||
real u1 = u.x;
|
||||
real u2 = u.y;
|
||||
|
||||
// Random point at hemisphere surface
|
||||
Ns = -SampleHemisphereUniform(u1, u2); // We want the y down hemisphere
|
||||
P = radius * Ns;
|
||||
|
||||
// Transform to world space
|
||||
P = mul(real4(P, 1.0), localToWorld).xyz;
|
||||
Ns = mul(Ns, (real3x3)(localToWorld));
|
||||
|
||||
// pdf is inverse of area
|
||||
lightPdf = 1.0 / (TWO_PI * radius * radius);
|
||||
}
|
||||
|
||||
// Note: The cylinder has no end caps (i.e. no disk on the side)
|
||||
void SampleCylinder(real2 u,
|
||||
real4x4 localToWorld,
|
||||
real radius,
|
||||
real width,
|
||||
out real lightPdf,
|
||||
out real3 P,
|
||||
out real3 Ns)
|
||||
{
|
||||
real u1 = u.x;
|
||||
real u2 = u.y;
|
||||
|
||||
// Random point at cylinder surface
|
||||
real t = (u1 - 0.5) * width;
|
||||
real theta = 2.0 * PI * u2;
|
||||
real cosTheta = cos(theta);
|
||||
real sinTheta = sin(theta);
|
||||
|
||||
// Cylinder are align on the right axis
|
||||
P = real3(t, radius * cosTheta, radius * sinTheta);
|
||||
Ns = normalize(real3(0.0, cosTheta, sinTheta));
|
||||
|
||||
// Transform to world space
|
||||
P = mul(real4(P, 1.0), localToWorld).xyz;
|
||||
Ns = mul(Ns, (real3x3)(localToWorld));
|
||||
|
||||
// pdf is inverse of area
|
||||
lightPdf = 1.0 / (TWO_PI * radius * width);
|
||||
}
|
||||
|
||||
void SampleRectangle(real2 u,
|
||||
real4x4 localToWorld,
|
||||
real width,
|
||||
real height,
|
||||
out real lightPdf,
|
||||
out real3 P,
|
||||
out real3 Ns)
|
||||
{
|
||||
// Random point at rectangle surface
|
||||
P = real3((u.x - 0.5) * width, (u.y - 0.5) * height, 0);
|
||||
Ns = real3(0, 0, -1); // Light down (-Z)
|
||||
|
||||
// Transform to world space
|
||||
P = mul(real4(P, 1.0), localToWorld).xyz;
|
||||
Ns = mul(Ns, (real3x3)(localToWorld));
|
||||
|
||||
// pdf is inverse of area
|
||||
lightPdf = 1.0 / (width * height);
|
||||
}
|
||||
|
||||
void SampleDisk(real2 u,
|
||||
real4x4 localToWorld,
|
||||
real radius,
|
||||
out real lightPdf,
|
||||
out real3 P,
|
||||
out real3 Ns)
|
||||
{
|
||||
// Random point at disk surface
|
||||
P = real3(radius * SampleDiskUniform(u.x, u.y), 0);
|
||||
Ns = real3(0.0, 0.0, -1.0); // Light down (-Z)
|
||||
|
||||
// Transform to world space
|
||||
P = mul(real4(P, 1.0), localToWorld).xyz;
|
||||
Ns = mul(Ns, (real3x3)(localToWorld));
|
||||
|
||||
// pdf is inverse of area
|
||||
lightPdf = 1.0 / (PI * radius * radius);
|
||||
}
|
||||
|
||||
// Solid angle cone sampling.
|
||||
// Takes the cosine of the aperture as an input.
|
||||
void SampleCone(real2 u, real cosHalfAngle,
|
||||
out real3 dir, out real rcpPdf)
|
||||
{
|
||||
real cosTheta = lerp(1, cosHalfAngle, u.x);
|
||||
real phi = TWO_PI * u.y;
|
||||
|
||||
dir = SphericalToCartesian(phi, cosTheta);
|
||||
rcpPdf = TWO_PI * (1 - cosHalfAngle);
|
||||
}
|
||||
|
||||
#if SHADER_API_MOBILE || SHADER_API_GLES || SHADER_API_GLES3
|
||||
#pragma warning (enable : 3205) // conversion of larger type to smaller
|
||||
#endif
|
||||
|
||||
#endif // UNITY_SAMPLING_INCLUDED
|
Reference in New Issue
Block a user