mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 15:36:14 +03:00
88 lines
3.1 KiB
GLSL
88 lines
3.1 KiB
GLSL
#ifndef IBL_COMMON_GLSL
|
|
#define IBL_COMMON_GLSL
|
|
|
|
/*
|
|
** Physical based render code, develop by engineer: qiutanguu.
|
|
*/
|
|
|
|
#include "LightingCommon.glsl"
|
|
|
|
// https://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/ImportanceSampling/importance_sampling_notes.pdf
|
|
// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
|
|
// https://bruop.github.io/ibl/
|
|
vec3 importanceSampleGGX(vec2 Xi, float alphaRoughness, vec3 normal)
|
|
{
|
|
// Maps a 2D point to a hemisphere with spread based on roughness.
|
|
float alpha = alphaRoughness * alphaRoughness;
|
|
|
|
// Sample in spherical coordinates.
|
|
float phi = 2.0 * kPI * Xi.x;
|
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha * alpha - 1.0) * Xi.y));
|
|
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
|
|
|
// Construct tangent space sample vector.
|
|
vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
|
|
|
|
// Tangent space
|
|
vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
vec3 tangentX = normalize(cross(up, normal));
|
|
vec3 tangentY = normalize(cross(normal, tangentX));
|
|
|
|
// Convert to world Space
|
|
return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
|
|
}
|
|
|
|
// http://jcgt.org/published/0007/04/01/paper.pdf by Eric Heitz
|
|
// Input Ve: view direction
|
|
// Input alpha_x, alpha_y: roughness parameters
|
|
// Input U1, U2: uniform random numbers
|
|
// Output Ne: normal sampled with PDF D_Ve(Ne) = G1(Ve) * max(0, dot(Ve, Ne)) * D(Ne) / Ve.z
|
|
vec3 importanceSampleGGXVNDF(vec3 Ve, float alpha_x, float alpha_y, float U1, float U2)
|
|
{
|
|
// Section 3.2: transforming the view direction to the hemisphere configuration
|
|
vec3 Vh = normalize(vec3(alpha_x * Ve.x, alpha_y * Ve.y, Ve.z));
|
|
|
|
// Section 4.1: orthonormal basis (with special case if cross product is zero)
|
|
float lensq = Vh.x * Vh.x + Vh.y * Vh.y;
|
|
vec3 T1 = lensq > 0 ? vec3(-Vh.y, Vh.x, 0) * inversesqrt(lensq) : vec3(1, 0, 0);
|
|
vec3 T2 = cross(Vh, T1);
|
|
|
|
// Section 4.2: parameterization of the projected area
|
|
float r = sqrt(U1);
|
|
float phi = 2.0 * kPI * U2;
|
|
float t1 = r * cos(phi);
|
|
float t2 = r * sin(phi);
|
|
float s = 0.5 * (1.0 + Vh.z);
|
|
t2 = (1.0 - s) * sqrt(1.0 - t1 * t1) + s * t2;
|
|
|
|
// Section 4.3: reprojection onto hemisphere
|
|
vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - t1 * t1 - t2 * t2)) * Vh;
|
|
|
|
// Section 3.4: transforming the normal back to the ellipsoid configuration
|
|
vec3 Ne = normalize(vec3(alpha_x * Nh.x, alpha_y * Nh.y, max(0.0, Nh.z)));
|
|
return Ne;
|
|
}
|
|
|
|
// Importance sample use cosine weight.
|
|
vec3 importanceSampleCosine(vec2 xi, vec3 N)
|
|
{
|
|
float phi = 2.f * kPI * xi.y;
|
|
|
|
float cosTheta = sqrt(xi.x);
|
|
float sinTheta = sqrt(1 - xi.x);
|
|
vec3 sampleHemisphere = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
|
|
|
//orient sample into world space
|
|
vec3 up = abs(N.z) < 0.999 ? vec3(0.f, 0.f, 1.f) : vec3(1.f, 0.f, 0.f);
|
|
vec3 tangent = normalize(cross(up, N));
|
|
vec3 bitangent = cross(N, tangent);
|
|
|
|
vec3 sampleWorld = vec3(0);
|
|
sampleWorld += sampleHemisphere.x * tangent;
|
|
sampleWorld += sampleHemisphere.y * bitangent;
|
|
sampleWorld += sampleHemisphere.z * N;
|
|
|
|
return sampleWorld;
|
|
}
|
|
|
|
#endif |