142 lines
5.1 KiB
GLSL
142 lines
5.1 KiB
GLSL
/**
|
|
* @file class1/deferred/genbrdflut.glsl
|
|
*
|
|
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2022, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
/* Taken from Sascha Willem's Vulkan GLTF refernce implementation
|
|
MIT License
|
|
|
|
Copyright (c) 2018 Sascha Willems
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
/*[EXTRA_CODE_HERE]*/
|
|
|
|
in vec2 vary_uv;
|
|
|
|
out vec4 outColor;
|
|
|
|
#define NUM_SAMPLES 1024u
|
|
|
|
const float PI = 3.1415926536;
|
|
|
|
// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
|
|
float random(vec2 co)
|
|
{
|
|
float a = 12.9898;
|
|
float b = 78.233;
|
|
float c = 43758.5453;
|
|
float dt= dot(co.xy ,vec2(a,b));
|
|
float sn= mod(dt,3.14);
|
|
return fract(sin(sn) * c);
|
|
}
|
|
|
|
vec2 hammersley2d(uint i, uint N)
|
|
{
|
|
// Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
|
uint bits = (i << 16u) | (i >> 16u);
|
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
float rdi = float(bits) * 2.3283064365386963e-10;
|
|
return vec2(float(i) /float(N), rdi);
|
|
}
|
|
|
|
// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
|
|
vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
|
|
{
|
|
// Maps a 2D point to a hemisphere with spread based on roughness
|
|
float alpha = roughness * roughness;
|
|
float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
|
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
|
|
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
|
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);
|
|
}
|
|
|
|
// Geometric Shadowing function
|
|
float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
|
|
{
|
|
float k = (roughness * roughness) / 2.0;
|
|
float GL = dotNL / (dotNL * (1.0 - k) + k);
|
|
float GV = dotNV / (dotNV * (1.0 - k) + k);
|
|
return GL * GV;
|
|
}
|
|
|
|
vec2 BRDF(float NoV, float roughness)
|
|
{
|
|
// Normal always points along z-axis for the 2D lookup
|
|
const vec3 N = vec3(0.0, 0.0, 1.0);
|
|
vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
|
|
|
|
vec2 LUT = vec2(0.0);
|
|
for(uint i = 0u; i < NUM_SAMPLES; i++) {
|
|
vec2 Xi = hammersley2d(i, NUM_SAMPLES);
|
|
vec3 H = importanceSample_GGX(Xi, roughness, N);
|
|
vec3 L = 2.0 * dot(V, H) * H - V;
|
|
|
|
float dotNL = max(dot(N, L), 0.0);
|
|
float dotNV = max(dot(N, V), 0.0);
|
|
float dotVH = max(dot(V, H), 0.0);
|
|
float dotNH = max(dot(H, N), 0.0);
|
|
|
|
if (dotNL > 0.0) {
|
|
float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
|
|
float G_Vis = (G * dotVH) / (dotNH * dotNV);
|
|
float Fc = pow(1.0 - dotVH, 5.0);
|
|
LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
|
|
}
|
|
}
|
|
return LUT / float(NUM_SAMPLES);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
outColor = vec4(BRDF(vary_uv.s, 1.0-vary_uv.t), 0.0, 1.0);
|
|
}
|