This commit is contained in:
Richard Smith 2019-05-21 10:56:31 +01:00
parent cd300d256e
commit a703659c9d
76 changed files with 87245 additions and 0 deletions

View file

@ -0,0 +1,140 @@
/*******************************************************************************************
*
* rPBR [shader] - Bidirectional reflectance distribution function fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
#define MAX_SAMPLES 1024u
# Input vertex attributes (from vertex shader)
in vec2 fragTexCoord
# Constant values
const float PI = 3.14159265359
# Output fragment color
out vec4 finalColor
float DistributionGGX(vec3 N, vec3 H, float roughness)
float RadicalInverse_VdC(uint bits)
vec2 Hammersley(uint i, uint N)
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
float GeometrySchlickGGX(float NdotV, float roughness)
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
vec2 IntegrateBRDF(float NdotV, float roughness)
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
]
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)
# Transform from spherical coordinates to cartesian coordinates (halfway vector)
vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta)
# Transform 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)
[
# For IBL k is calculated different
float k = (roughness*roughness)/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 = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV)
float A = 0.0
float B = 0.0
vec3 N = vec3(0.0, 0.0, 1.0)
for(uint i = 0u i < MAX_SAMPLES i++)
[
# Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
vec2 Xi = Hammersley(i, MAX_SAMPLES)
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
]
]
# Calculate brdf average sample
A /= float(MAX_SAMPLES)
B /= float(MAX_SAMPLES)
return vec2(A, B)
]
void main()
[
# Calculate brdf based on texture coordinates
vec2 brdf = IntegrateBRDF(fragTexCoord.x, fragTexCoord.y)
# Calculate final fragment color
finalColor = vec4(brdf.r, brdf.g, 0.0, 1.0)
]

View file

@ -0,0 +1,25 @@
/*******************************************************************************************
*
* rPBR [shader] - Bidirectional reflectance distribution function vertex shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes
in vec3 vertexPosition
in vec2 vertexTexCoord
# Output vertex attributes (to fragment shader)
out vec2 fragTexCoord
void main()
[
# Calculate fragment position based on model transformations
fragTexCoord = vertexTexCoord
# Calculate final vertex position
gl_Position = vec4(vertexPosition, 1.0)
]

View file

@ -0,0 +1,38 @@
/*******************************************************************************************
*
* rPBR [shader] - Equirectangular to cubemap fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes (from vertex shader)
in vec3 fragPos
# Input uniform values
uniform sampler2D equirectangularMap
# Output fragment color
out vec4 finalColor
vec2 SampleSphericalMap(vec3 v)
[
vec2 uv = vec2(atan(v.z, v.x), asin(v.y))
uv *= vec2(0.1591, 0.3183)
uv += 0.5
return uv
]
void main()
[
# Normalize local position
vec2 uv = SampleSphericalMap(normalize(fragPos))
# Fetch color from texture map
vec3 color = texture(equirectangularMap, uv).rgb
# Calculate final fragment color
finalColor = vec4(color, 1.0)
]

View file

@ -0,0 +1,28 @@
/*******************************************************************************************
*
* rPBR [shader] - Equirectangular to cubemap vertex shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes
in vec3 vertexPosition
# Input uniform values
uniform mat4 projection
uniform mat4 view
# Output vertex attributes (to fragment shader)
out vec3 fragPos
void main()
[
# Calculate fragment position based on model transformations
fragPos = vertexPosition
# Calculate final vertex position
gl_Position = projection*view*vec4(vertexPosition, 1.0)
]

View file

@ -0,0 +1,58 @@
/*******************************************************************************************
*
* rPBR [shader] - Irradiance cubemap fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes (from vertex shader)
in vec3 fragPos
# Input uniform values
uniform samplerCube environmentMap
# Constant values
const float PI = 3.14159265359f
# Output fragment color
out vec4 finalColor
void main()
[
# The sample direction equals the hemisphere's orientation
vec3 normal = normalize(fragPos)
vec3 irradiance = vec3(0.0)
vec3 up = vec3(0.0, 1.0, 0.0)
vec3 right = cross(up, normal)
up = cross(normal, right)
float sampleDelta = 0.025f
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)
[
# 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*normal
# Fetch color from environment cubemap
irradiance += texture(environmentMap, sampleVec).rgb*cos(theta)*sin(theta)
nrSamples++
]
]
# Calculate irradiance average value from samples
irradiance = PI*irradiance*(1.0/float(nrSamples))
# Calculate final fragment color
finalColor = vec4(irradiance, 1.0)
]

View file

@ -0,0 +1,298 @@
/*******************************************************************************************
*
* rPBR [shader] - Physically based rendering fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
#define MAX_REFLECTION_LOD 4.0
#define MAX_DEPTH_LAYER 20
#define MIN_DEPTH_LAYER 10
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
struct MaterialProperty [
vec3 color
int useSampler
sampler2D sampler
]
struct Light [
int enabled
int type
vec3 position
vec3 target
vec4 color
]
# Input vertex attributes (from vertex shader)
in vec3 fragPosition
in vec2 fragTexCoord
in vec3 fragNormal
in vec3 fragTangent
in vec3 fragBinormal
# Input material values
uniform MaterialProperty albedo
uniform MaterialProperty normals
uniform MaterialProperty metalness
uniform MaterialProperty roughness
uniform MaterialProperty occlusion
uniform MaterialProperty emission
uniform MaterialProperty height
# Input uniform values
uniform samplerCube irradianceMap
uniform samplerCube prefilterMap
uniform sampler2D brdfLUT
# Input lighting values
uniform Light lights[MAX_LIGHTS]
# Other uniform values
uniform int renderMode
uniform vec3 viewPos
vec2 texCoord
# Constant values
const float PI = 3.14159265359
# Output fragment color
out vec4 finalColor
vec3 ComputeMaterialProperty(MaterialProperty property)
float DistributionGGX(vec3 N, vec3 H, float roughness)
float GeometrySchlickGGX(float NdotV, float roughness)
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
vec3 fresnelSchlick(float cosTheta, vec3 F0)
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir)
vec3 ComputeMaterialProperty(MaterialProperty property)
[
vec3 result = vec3(0.0, 0.0, 0.0)
if (property.useSampler == 1) result = texture(property.sampler, texCoord).rgb
else result = property.color
return result
]
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
]
float GeometrySchlickGGX(float NdotV, float roughness)
[
float r = (roughness + 1.0)
float k = r*r/8.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
]
vec3 fresnelSchlick(float cosTheta, vec3 F0)
[
return F0 + (1.0 - F0)*pow(1.0 - cosTheta, 5.0)
]
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
[
return F0 + (max(vec3(1.0 - roughness), F0) - F0)*pow(1.0 - cosTheta, 5.0)
]
vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir)
[
# Calculate the number of depth layers and calculate the size of each layer
float numLayers = mix(MAX_DEPTH_LAYER, MIN_DEPTH_LAYER, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)))
float layerDepth = 1.0/numLayers
# Calculate depth of current layer
float currentLayerDepth = 0.0
# Calculate the amount to shift the texture coordinates per layer (from vector P)
# Note: height amount is stored in height material attribute color R channel (sampler use is independent)
vec2 P = viewDir.xy*height.color.r
vec2 deltaTexCoords = P/numLayers
# Store initial texture coordinates and depth values
vec2 currentTexCoords = texCoords
float currentDepthMapValue = texture(height.sampler, currentTexCoords).r
while (currentLayerDepth < currentDepthMapValue)
[
# Shift texture coordinates along direction of P
currentTexCoords -= deltaTexCoords
# Get depth map value at current texture coordinates
currentDepthMapValue = texture(height.sampler, currentTexCoords).r
# Get depth of next layer
currentLayerDepth += layerDepth
]
# Get texture coordinates before collision (reverse operations)
vec2 prevTexCoords = currentTexCoords + deltaTexCoords
# Get depth after and before collision for linear interpolation
float afterDepth = currentDepthMapValue - currentLayerDepth
float beforeDepth = texture(height.sampler, prevTexCoords).r - currentLayerDepth + layerDepth
# Interpolation of texture coordinates
float weight = afterDepth/(afterDepth - beforeDepth)
vec2 finalTexCoords = prevTexCoords*weight + currentTexCoords*(1.0 - weight)
return finalTexCoords
]
void main()
[
# Calculate TBN and RM matrices
mat3 TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal))
# Calculate lighting required attributes
vec3 normal = normalize(fragNormal)
vec3 view = normalize(viewPos - fragPosition)
vec3 refl = reflect(-view, normal)
# Check if parallax mapping is enabled and calculate texture coordinates to use based on height map
# NOTE: remember that 'texCoord' variable must be assigned before calling any ComputeMaterialProperty() function
if (height.useSampler == 1) texCoord = ParallaxMapping(fragTexCoord, view)
else texCoord = fragTexCoord # Use default texture coordinates
# Fetch material values from texture sampler or color attributes
vec3 color = ComputeMaterialProperty(albedo)
vec3 metal = ComputeMaterialProperty(metalness)
vec3 rough = ComputeMaterialProperty(roughness)
vec3 emiss = ComputeMaterialProperty(emission)
vec3 ao = ComputeMaterialProperty(occlusion)
# Check if normal mapping is enabled
if (normals.useSampler == 1)
[
# Fetch normal map color and transform lighting values to tangent space
normal = ComputeMaterialProperty(normals)
normal = normalize(normal*2.0 - 1.0)
normal = normalize(normal*TBN)
# Convert tangent space normal to world space due to cubemap reflection calculations
refl = normalize(reflect(-view, normal))
]
# Calculate reflectance at normal incidence
vec3 F0 = vec3(0.04)
F0 = mix(F0, color, metal.r)
# Calculate lighting for all lights
vec3 Lo = vec3(0.0)
vec3 lightDot = vec3(0.0)
for (int i = 0 i < MAX_LIGHTS i++)
[
if (lights[i].enabled == 1)
[
# Calculate per-light radiance
vec3 light = vec3(0.0)
vec3 radiance = lights[i].color.rgb
if (lights[i].type == LIGHT_DIRECTIONAL) light = -normalize(lights[i].target - lights[i].position)
else if (lights[i].type == LIGHT_POINT)
[
light = normalize(lights[i].position - fragPosition)
float distance = length(lights[i].position - fragPosition)
float attenuation = 1.0/(distance*distance)
radiance *= attenuation
]
# Cook-torrance BRDF
vec3 high = normalize(view + light)
float NDF = DistributionGGX(normal, high, rough.r)
float G = GeometrySmith(normal, view, light, rough.r)
vec3 F = fresnelSchlick(max(dot(high, view), 0.0), F0)
vec3 nominator = NDF*G*F
float denominator = 4*max(dot(normal, view), 0.0)*max(dot(normal, light), 0.0) + 0.001
vec3 brdf = nominator/denominator
# Store to kS the fresnel value and calculate energy conservation
vec3 kS = F
vec3 kD = vec3(1.0) - kS
# Multiply kD by the inverse metalness such that only non-metals have diffuse lighting
kD *= 1.0 - metal.r
# Scale light by dot product between normal and light direction
float NdotL = max(dot(normal, light), 0.0)
# Add to outgoing radiance Lo
# Note: BRDF is already multiplied by the Fresnel so it doesn't need to be multiplied again
Lo += (kD*color/PI + brdf)*radiance*NdotL*lights[i].color.a
lightDot += radiance*NdotL + brdf*lights[i].color.a
]
]
# Calculate ambient lighting using IBL
vec3 F = fresnelSchlickRoughness(max(dot(normal, view), 0.0), F0, rough.r)
vec3 kS = F
vec3 kD = 1.0 - kS
kD *= 1.0 - metal.r
# Calculate indirect diffuse
vec3 irradiance = texture(irradianceMap, fragNormal).rgb
vec3 diffuse = color*irradiance
# Sample both the prefilter map and the BRDF lut and combine them together as per the Split-Sum approximation
vec3 prefilterColor = textureLod(prefilterMap, refl, rough.r*MAX_REFLECTION_LOD).rgb
vec2 brdf = texture(brdfLUT, vec2(max(dot(normal, view), 0.0), rough.r)).rg
vec3 reflection = prefilterColor*(F*brdf.x + brdf.y)
# Calculate final lighting
vec3 ambient = (kD*diffuse + reflection)*ao
# Calculate fragment color based on render mode
vec3 fragmentColor = ambient + Lo + emiss # Physically Based Rendering
if (renderMode == 1) fragmentColor = color # Albedo
else if (renderMode == 2) fragmentColor = normal # Normals
else if (renderMode == 3) fragmentColor = metal # Metalness
else if (renderMode == 4) fragmentColor = rough # Roughness
else if (renderMode == 5) fragmentColor = ao # Ambient Occlusion
else if (renderMode == 6) fragmentColor = emiss # Emission
else if (renderMode == 7) fragmentColor = lightDot # Lighting
else if (renderMode == 8) fragmentColor = kS # Fresnel
else if (renderMode == 9) fragmentColor = irradiance # Irradiance
else if (renderMode == 10) fragmentColor = reflection # Reflection
# Apply HDR tonemapping
fragmentColor = fragmentColor/(fragmentColor + vec3(1.0))
# Apply gamma correction
fragmentColor = pow(fragmentColor, vec3(1.0/2.2))
# Calculate final fragment color
finalColor = vec4(fragmentColor, 1.0)
]

View file

@ -0,0 +1,49 @@
/*******************************************************************************************
*
* rPBR [shader] - Physically based rendering vertex shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes
in vec3 vertexPosition
in vec2 vertexTexCoord
in vec3 vertexNormal
in vec4 vertexTangent
# Input uniform values
uniform mat4 mvp
uniform mat4 matModel
# Output vertex attributes (to fragment shader)
out vec3 fragPosition
out vec2 fragTexCoord
out vec3 fragNormal
out vec3 fragTangent
out vec3 fragBinormal
void main()
[
# Calculate binormal from vertex normal and tangent
vec3 vertexBinormal = cross(vertexNormal, vec3(vertexTangent))
# Calculate fragment normal based on normal transformations
mat3 normalMatrix = transpose(inverse(mat3(matModel)))
# Calculate fragment position based on model transformations
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0))
# Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord
fragNormal = normalize(normalMatrix*vertexNormal)
fragTangent = normalize(normalMatrix*vec3(vertexTangent))
fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal)
fragBinormal = normalize(normalMatrix*vertexBinormal)
fragBinormal = cross(fragNormal, fragTangent)
# Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0)
]

View file

@ -0,0 +1,120 @@
/*******************************************************************************************
*
* rPBR [shader] - Prefiltered environment for reflections fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
#define MAX_SAMPLES 1024u
#define CUBEMAP_RESOLUTION 1024.0
# Input vertex attributes (from vertex shader)
in vec3 fragPos
# Input uniform values
uniform samplerCube environmentMap
uniform float roughness
# Constant values
const float PI = 3.14159265359f
# Output fragment color
out vec4 finalColor
float DistributionGGX(vec3 N, vec3 H, float roughness)
float RadicalInverse_VdC(uint bits)
vec2 Hammersley(uint i, uint N)
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
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
]
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)
# Transform from spherical coordinates to cartesian coordinates (halfway vector)
vec3 H = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta)
# Transform 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()
[
# Make the simplyfying assumption that V equals R equals the normal
vec3 N = normalize(fragPos)
vec3 R = N
vec3 V = R
vec3 prefilteredColor = vec3(0.0)
float totalWeight = 0.0
for (uint i = 0u i < MAX_SAMPLES i++)
[
# Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
vec2 Xi = Hammersley(i, MAX_SAMPLES)
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 = CUBEMAP_RESOLUTION
float saTexel = 4.0*PI/(6.0*resolution*resolution)
float saSample = 1.0/(float(MAX_SAMPLES)*pdf + 0.0001)
float mipLevel = ((roughness == 0.0) ? 0.0 : 0.5*log2(saSample/saTexel))
prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb*NdotL
totalWeight += NdotL
]
]
# Calculate prefilter average color
prefilteredColor = prefilteredColor/totalWeight
# Calculate final fragment color
finalColor = vec4(prefilteredColor, 1.0)
]

View file

@ -0,0 +1,31 @@
/*******************************************************************************************
*
* rPBR [shader] - Background skybox fragment shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes (from vertex shader)
in vec3 fragPos
# Input uniform values
uniform samplerCube environmentMap
# Output fragment color
out vec4 finalColor
void main()
[
# Fetch color from texture map
vec3 color = texture(environmentMap, fragPos).rgb
# Apply gamma correction
color = color/(color + vec3(1.0))
color = pow(color, vec3(1.0/2.2))
# Calculate final fragment color
finalColor = vec4(color, 1.0)
]

View file

@ -0,0 +1,32 @@
/*******************************************************************************************
*
* rPBR [shader] - Background skybox vertex shader
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
# Input vertex attributes
in vec3 vertexPosition
# Input uniform values
uniform mat4 projection
uniform mat4 view
# Output vertex attributes (to fragment shader)
out vec3 fragPos
void main()
[
# Calculate fragment position based on model transformations
fragPos = vertexPosition
# Remove translation from the view matrix
mat4 rotView = mat4(mat3(view))
vec4 clipPos = projection*rotView*vec4(vertexPosition, 1.0)
# Calculate final vertex position
gl_Position = clipPos.xyww
]