PBR Shader fix to code standard.

This commit is contained in:
Joey de Vries
2017-05-26 15:49:29 +02:00
parent 701f4fe608
commit a398a343a4
41 changed files with 430 additions and 100 deletions

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform vec3 albedo;
@@ -66,7 +65,7 @@ void main()
vec3 V = normalize(camPos - WorldPos);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
@@ -120,4 +119,4 @@ void main()
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0);
}
}

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform sampler2D albedoMap;
@@ -93,7 +92,7 @@ void main()
vec3 V = normalize(camPos - WorldPos);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
@@ -147,4 +146,4 @@ void main()
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0);
}
}

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
@@ -8,7 +8,7 @@ out vec3 WorldPos;
void main()
{
WorldPos = pos;
WorldPos = aPos;
mat4 rotView = mat4(mat3(view));
vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0);

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
out vec3 WorldPos;
@@ -8,7 +8,7 @@ uniform mat4 view;
void main()
{
WorldPos = pos;
WorldPos = aPos;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform vec3 albedo;
@@ -71,7 +70,7 @@ void main()
vec3 R = reflect(-V, N);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -75,9 +75,9 @@ int main()
// build and compile shaders
// -------------------------
Shader pbrShader("2.1.1.pbr.vs", "2.1.1.pbr.frag");
Shader equirectangularToCubemapShader("2.1.1.cubemap.vs", "2.1.1.equirectangular_to_cubemap.frag");
Shader backgroundShader("2.1.1.background.vs", "2.1.1.background.frag");
Shader pbrShader("2.1.1.pbr.vs", "2.1.1.pbr.fs");
Shader equirectangularToCubemapShader("2.1.1.cubemap.vs", "2.1.1.equirectangular_to_cubemap.fs");
Shader backgroundShader("2.1.1.background.vs", "2.1.1.background.fs");
pbrShader.use();

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
@@ -8,7 +8,7 @@ out vec3 WorldPos;
void main()
{
WorldPos = pos;
WorldPos = aPos;
mat4 rotView = mat4(mat3(view));
vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0);

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
out vec3 WorldPos;
@@ -8,7 +8,7 @@ uniform mat4 view;
void main()
{
WorldPos = pos;
WorldPos = aPos;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -4,11 +4,11 @@ in vec3 WorldPos;
uniform samplerCube environmentMap;
const float PI = 3.14159265359f;
const float PI = 3.14159265359;
void main()
{
// NOTE(Joey): the world vector acts as the normal of a tangent surface
// The world vector acts as the normal of a tangent surface
// from the origin, aligned to WorldPos. Given this normal, calculate all
// incoming radiance of the environment. The result of this radiance
// is the radiance of light coming from -Normal direction, which is what
@@ -17,13 +17,13 @@ void main()
vec3 irradiance = vec3(0.0);
// NOTE(Joey): tangent space calculation from origin point
// tangent space calculation from origin point
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = cross(up, N);
up = cross(N, right);
float sampleDelta = 0.025f;
float nrSamples = 0.0f;
float sampleDelta = 0.025;
float nrSamples = 0.0;
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
{
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform vec3 albedo;
@@ -69,7 +68,7 @@ void main()
vec3 R = reflect(-V, N);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
@@ -128,4 +127,4 @@ void main()
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color , 1.0);
}
}

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -75,10 +75,10 @@ int main()
// build and compile shaders
// -------------------------
Shader pbrShader("2.1.2.pbr.vs", "2.1.2.pbr.frag");
Shader equirectangularToCubemapShader("2.1.2.cubemap.vs", "2.1.2.equirectangular_to_cubemap.frag");
Shader irradianceShader("2.1.2.cubemap.vs", "2.1.2.irradiance_convolution.frag");
Shader backgroundShader("2.1.2.background.vs", "2.1.2.background.frag");
Shader pbrShader("2.1.2.pbr.vs", "2.1.2.pbr.fs");
Shader equirectangularToCubemapShader("2.1.2.cubemap.vs", "2.1.2.equirectangular_to_cubemap.fs");
Shader irradianceShader("2.1.2.cubemap.vs", "2.1.2.irradiance_convolution.fs");
Shader backgroundShader("2.1.2.background.vs", "2.1.2.background.fs");
pbrShader.use();

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
@@ -8,7 +8,7 @@ out vec3 WorldPos;
void main()
{
WorldPos = pos;
WorldPos = aPos;
mat4 rotView = mat4(mat3(view));
vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0);

View File

@@ -2,7 +2,7 @@
out vec2 FragColor;
in vec2 TexCoords;
const float PI = 3.14159265359f;
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// efficient VanDerCorpus calculation.
@@ -29,13 +29,13 @@ vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
// NOTE(Joey): from spherical coordinates to cartesian coordinates - halfway vector
// from spherical coordinates to cartesian coordinates - halfway vector
vec3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// NOTE(Joey): from tangent-space H vector to world-space sample vector
// from tangent-space H vector to world-space sample vector
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
@@ -81,7 +81,7 @@ vec2 IntegrateBRDF(float NdotV, float roughness)
const uint SAMPLE_COUNT = 1024u;
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
{
// NOTE(Joey): generates a sample vector that's biased towards the
// generates a sample vector that's biased towards the
// preferred alignment direction (importance sampling).
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);

View File

@@ -1,11 +1,11 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = texCoords;
gl_Position = vec4(pos, 1.0);
TexCoords = aTexCoords;
gl_Position = vec4(aPos, 1.0);
}

View File

@@ -1,5 +1,5 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 0) in vec3 aPos;
out vec3 WorldPos;
@@ -8,7 +8,7 @@ uniform mat4 view;
void main()
{
WorldPos = pos;
WorldPos = aPos;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -4,7 +4,7 @@ in vec3 WorldPos;
uniform samplerCube environmentMap;
const float PI = 3.14159265359f;
const float PI = 3.14159265359;
void main()
{
@@ -17,7 +17,7 @@ void main()
vec3 right = cross(up, N);
up = cross(N, right);
float sampleDelta = 0.025f;
float sampleDelta = 0.025;
float nrSamples = 0.0f;
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
{

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform vec3 albedo;
@@ -76,7 +75,7 @@ void main()
vec3 R = reflect(-V, N);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -5,7 +5,7 @@ in vec3 WorldPos;
uniform samplerCube environmentMap;
uniform float roughness;
const float PI = 3.14159265359f;
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
float DistributionGGX(vec3 N, vec3 H, float roughness)
{

View File

@@ -79,12 +79,12 @@ int main()
// build and compile shaders
// -------------------------
Shader pbrShader("2.2.1.pbr.vs", "2.2.1.pbr.frag");
Shader equirectangularToCubemapShader("2.2.1.cubemap.vs", "2.2.1.equirectangular_to_cubemap.frag");
Shader irradianceShader("2.2.1.cubemap.vs", "2.2.1.irradiance_convolution.frag");
Shader prefilterShader("2.2.1.cubemap.vs", "2.2.1.prefilter.frag");
Shader brdfShader("2.2.1.brdf.vs", "2.2.1.brdf.frag");
Shader backgroundShader("2.2.1.background.vs", "2.2.1.background.frag");
Shader pbrShader("2.2.1.pbr.vs", "2.2.1.pbr.fs");
Shader equirectangularToCubemapShader("2.2.1.cubemap.vs", "2.2.1.equirectangular_to_cubemap.fs");
Shader irradianceShader("2.2.1.cubemap.vs", "2.2.1.irradiance_convolution.fs");
Shader prefilterShader("2.2.1.cubemap.vs", "2.2.1.prefilter.fs");
Shader brdfShader("2.2.1.brdf.vs", "2.2.1.brdf.fs");
Shader backgroundShader("2.2.1.background.vs", "2.2.1.background.fs");
pbrShader.use();
pbrShader.setInt("irradianceMap", 0);

View File

@@ -0,0 +1,16 @@
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;
uniform samplerCube environmentMap;
void main()
{
vec3 envColor = textureLod(environmentMap, WorldPos, 0.0).rgb;
// HDR tonemap and gamma correct
envColor = envColor / (envColor + vec3(1.0));
envColor = pow(envColor, vec3(1.0/2.2));
FragColor = vec4(envColor, 1.0);
}

View File

@@ -0,0 +1,17 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 view;
out vec3 WorldPos;
void main()
{
WorldPos = aPos;
mat4 rotView = mat4(mat3(view));
vec4 clipPos = projection * rotView * vec4(WorldPos, 1.0);
gl_Position = clipPos.xyww;
}

View File

@@ -0,0 +1,113 @@
#version 330 core
out vec2 FragColor;
in vec2 TexCoords;
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// efficient VanDerCorpus calculation.
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 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);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
// ----------------------------------------------------------------------------
vec2 Hammersley(uint i, uint N)
{
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
}
// ----------------------------------------------------------------------------
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
{
float a = roughness*roughness;
float phi = 2.0 * PI * Xi.x;
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
// from spherical coordinates to cartesian coordinates - halfway vector
vec3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// from tangent-space H vector to world-space sample vector
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
return normalize(sampleVec);
}
// ----------------------------------------------------------------------------
float GeometrySchlickGGX(float NdotV, float roughness)
{
// note that we use a different k for IBL
float a = roughness;
float k = (a * a) / 2.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
// ----------------------------------------------------------------------------
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
// ----------------------------------------------------------------------------
vec2 IntegrateBRDF(float NdotV, float roughness)
{
vec3 V;
V.x = sqrt(1.0 - NdotV*NdotV);
V.y = 0.0;
V.z = NdotV;
float A = 0.0;
float B = 0.0;
vec3 N = vec3(0.0, 0.0, 1.0);
const uint SAMPLE_COUNT = 1024u;
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
{
// generates a sample vector that's biased towards the
// preferred alignment direction (importance sampling).
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = max(L.z, 0.0);
float NdotH = max(H.z, 0.0);
float VdotH = max(dot(V, H), 0.0);
if(NdotL > 0.0)
{
float G = GeometrySmith(N, V, L, roughness);
float G_Vis = (G * VdotH) / (NdotH * NdotV);
float Fc = pow(1.0 - VdotH, 5.0);
A += (1.0 - Fc) * G_Vis;
B += Fc * G_Vis;
}
}
A /= float(SAMPLE_COUNT);
B /= float(SAMPLE_COUNT);
return vec2(A, B);
}
// ----------------------------------------------------------------------------
void main()
{
vec2 integratedBRDF = IntegrateBRDF(TexCoords.x, TexCoords.y);
FragColor = integratedBRDF;
}

View File

@@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos, 1.0);
}

View File

@@ -0,0 +1,14 @@
#version 330 core
layout (location = 0) in vec3 aPos;
out vec3 WorldPos;
uniform mat4 projection;
uniform mat4 view;
void main()
{
WorldPos = aPos;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -0,0 +1,22 @@
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;
uniform sampler2D equirectangularMap;
const vec2 invAtan = vec2(0.1591, 0.3183);
vec2 SampleSphericalMap(vec3 v)
{
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
uv *= invAtan;
uv += 0.5;
return uv;
}
void main()
{
vec2 uv = SampleSphericalMap(normalize(WorldPos));
vec3 color = texture(equirectangularMap, uv).rgb;
FragColor = vec4(color, 1.0);
}

View File

@@ -0,0 +1,38 @@
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;
uniform samplerCube environmentMap;
const float PI = 3.14159265359;
void main()
{
vec3 N = normalize(WorldPos);
vec3 irradiance = vec3(0.0);
// tangent space calculation from origin point
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = cross(up, N);
up = cross(N, right);
float sampleDelta = 0.025;
float nrSamples = 0.0f;
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
{
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)
{
// spherical to cartesian (in tangent space)
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
// tangent space to world
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
nrSamples++;
}
}
irradiance = PI * irradiance * (1.0 / float(nrSamples));
FragColor = vec4(irradiance, 1.0);
}

View File

@@ -3,7 +3,6 @@ out vec4 FragColor;
in vec2 TexCoords;
in vec3 WorldPos;
in vec3 Normal;
in mat3 TBN;
// material parameters
uniform sampler2D albedoMap;
@@ -98,15 +97,14 @@ void main()
float metallic = texture(metallicMap, TexCoords).r;
float roughness = texture(roughnessMap, TexCoords).r;
float ao = texture(aoMap, TexCoords).r;
// input lighting data
vec3 N = getNormalFromMap();
vec3 V = normalize(camPos - WorldPos);
vec3 R = reflect(-V, N);
// calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
// of 0.04 and if it's a metal, use their albedo color as F0 (metallic workflow)
// of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);

View File

@@ -1,7 +1,7 @@
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normal;
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aNormal;
out vec2 TexCoords;
out vec3 WorldPos;
@@ -13,9 +13,9 @@ uniform mat4 model;
void main()
{
TexCoords = texCoords;
WorldPos = vec3(model * vec4(pos, 1.0f));
Normal = mat3(model) * normal;
TexCoords = aTexCoords;
WorldPos = vec3(model * vec4(aPos, 1.0f));
Normal = mat3(model) * aNormal;
gl_Position = projection * view * vec4(WorldPos, 1.0);
}

View File

@@ -0,0 +1,106 @@
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;
uniform samplerCube environmentMap;
uniform float roughness;
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
float DistributionGGX(vec3 N, vec3 H, float roughness)
{
float a = roughness*roughness;
float a2 = a*a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
// ----------------------------------------------------------------------------
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// efficient VanDerCorpus calculation.
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 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);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
// ----------------------------------------------------------------------------
vec2 Hammersley(uint i, uint N)
{
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
}
// ----------------------------------------------------------------------------
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
{
float a = roughness*roughness;
float phi = 2.0 * PI * Xi.x;
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
// from spherical coordinates to cartesian coordinates - halfway vector
vec3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// from tangent-space H vector to world-space sample vector
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
return normalize(sampleVec);
}
// ----------------------------------------------------------------------------
void main()
{
vec3 N = normalize(WorldPos);
// make the simplyfying assumption that V equals R equals the normal
vec3 R = N;
vec3 V = R;
const uint SAMPLE_COUNT = 1024u;
vec3 prefilteredColor = vec3(0.0);
float totalWeight = 0.0;
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
{
// generates a sample vector that's biased towards the preferred alignment direction (importance sampling).
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = max(dot(N, L), 0.0);
if(NdotL > 0.0)
{
// sample from the environment's mip level based on roughness/pdf
float D = DistributionGGX(N, H, roughness);
float NdotH = max(dot(N, H), 0.0);
float HdotV = max(dot(H, V), 0.0);
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
float resolution = 512.0; // resolution of source cubemap (per face)
float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL;
totalWeight += NdotL;
}
}
prefilteredColor = prefilteredColor / totalWeight;
FragColor = vec4(prefilteredColor, 1.0);
}

View File

@@ -80,12 +80,12 @@ int main()
// build and compile shaders
// -------------------------
Shader pbrShader("2.2.2.pbr.vs", "2.2.2.pbr.frag");
Shader equirectangularToCubemapShader("2.2.1.cubemap.vs", "2.2.1.equirectangular_to_cubemap.frag");
Shader irradianceShader("2.2.1.cubemap.vs", "2.2.1.irradiance_convolution.frag");
Shader prefilterShader("2.2.1.cubemap.vs", "2.2.1.prefilter.frag");
Shader brdfShader("2.2.1.brdf.vs", "2.2.1.brdf.frag");
Shader backgroundShader("2.2.1.background.vs", "2.2.1.background.frag");
Shader pbrShader("2.2.2.pbr.vs", "2.2.2.pbr.fs");
Shader equirectangularToCubemapShader("2.2.2.cubemap.vs", "2.2.2.equirectangular_to_cubemap.fs");
Shader irradianceShader("2.2.2.cubemap.vs", "2.2.2.irradiance_convolution.fs");
Shader prefilterShader("2.2.2.cubemap.vs", "2.2.2.prefilter.fs");
Shader brdfShader("2.2.2.brdf.vs", "2.2.2.brdf.fs");
Shader backgroundShader("2.2.2.background.vs", "2.2.2.background.fs");
pbrShader.use();
pbrShader.setInt("irradianceMap", 0);