diff --git a/shaders/lighting.frag.glsl b/shaders/lighting.frag.glsl index 0497e5e..7bfb68e 100644 --- a/shaders/lighting.frag.glsl +++ b/shaders/lighting.frag.glsl @@ -53,107 +53,8 @@ uniform mat4 inverseProjectionMatrix; layout(location = 0)out vec4 outColor; -// CONSTANTS - -const float PI = 3.14159265359; -const float MAX_REFLECTION_LOD = 4.0; - -// FUNCTIONS - -#ifdef AMBIENT_LIGHT -vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) -{ - return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); -} - -vec3 GGX( - in vec3 albedoColor, - in float metallic, - in float roughness, - in vec3 N, - in vec3 V) -{ - float NdotV = max(dot(N, V), 0.0); - vec3 R = reflect(-V, N); - vec3 albedo = pow(albedoColor, vec3(2.2)); - // 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) - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - // ambient lighting (we now use IBL as the ambient term) (fresnelSchlickRoughness function) - vec3 F = fresnelSchlickRoughness(NdotV, F0, roughness); - - vec3 kS = F; - vec3 kD = 1.0 - kS; - kD *= 1.0 - metallic; - - mat3 viewToWorld = inverseViewMatrix; - - vec3 irradiance = texture(ambientMap, viewToWorld * N).rgb; - vec3 diffuse = irradiance * albedo; - - // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. - - vec3 prefilteredColor = textureLod(reflectMap, viewToWorld * R, roughness * MAX_REFLECTION_LOD).rgb; - vec2 brdf2 = texture(brdfLUT, vec2(NdotV, roughness)).rg; - vec3 specular = prefilteredColor * (F * brdf2.x + brdf2.y); - - // combining light - return kD * diffuse + specular; -} -#elif !defined UNLIT -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 denom = (NdotH * NdotH * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; - return a2 / denom; -} - -float GeometrySchlickGGX(float cosAlpha, float roughness) -{ - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - return cosAlpha / (cosAlpha * (1.0 - k) + k); -} - -vec3 GGX( - in vec3 albedoColor, - in float metallic, - in float roughness, - in vec3 radiance, - in vec3 N, - in vec3 L, - in vec3 H, - in vec3 V) -{ - vec3 albedo = pow(albedoColor, vec3(2.2)); - vec3 F0 = mix(vec3(0.04), albedo, metallic); - float NdotL = max(dot(N, L), 0.0); - float NdotV = max(dot(N, V), 0.0); - - // Cook-Torrance BRDF - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySchlickGGX(NdotV, roughness) * GeometrySchlickGGX(NdotL, roughness); - vec3 F = F0 + (1.0 - F0) * pow(1.0 - clamp(dot(H, V), 0.0, 1.0), 5.0); - - vec3 nominator = NDF * G * F; - float denominator = 4 * NdotV * NdotL + 0.001; // 0.001 to prevent divide by zero. - vec3 brdf = nominator / denominator; - - vec3 kD = 1.0 - F; - kD *= 1.0 - metallic; - - return (kD * albedo / PI + brdf) * radiance * NdotL; -} -#endif - // MAIN PROGRAM - void main(void) { // get fragment information from the G-Buffer ivec2 texCoord = ivec2(gl_FragCoord.xy); @@ -198,7 +99,8 @@ void main(void) { vec3 viewDir = normalize(-fragPos.xyz); #ifdef AMBIENT_LIGHT - outColor = vec4(emission + GGX(albedo, metallic, roughness, normal, viewDir), 1); + vec3 ambientLight = ambientGGX(albedo, metallic, roughness, normal, viewDir, inverseViewMatrix, ambientMap, reflectMap, brdfLUT); + outColor = vec4(emission + ambientLight, 1); #else vec3 halfVec = normalize(viewDir + dirLight); vec3 light = GGX(albedo, metallic, roughness, lightColor, normal, dirLight, halfVec, viewDir); diff --git a/shaders/utils.glsl b/shaders/utils.glsl new file mode 100644 index 0000000..5fd9ad6 --- /dev/null +++ b/shaders/utils.glsl @@ -0,0 +1,99 @@ + +// CONSTANTS + +const float PI = 3.14159265359; +const float MAX_REFLECTION_LOD = 4.0; + +// FUNCTIONS + +vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) +{ + return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); +} + +vec3 ambientGGX( + in vec3 albedoColor, + in float metallic, + in float roughness, + in vec3 N, + in vec3 V, + in mat3 viewToWorld, + in samplerCube irradianceMap, + in samplerCube radianceMap, + in sampler2D lut) +{ + float NdotV = max(dot(N, V), 0.0); + vec3 R = reflect(-V, N); + vec3 albedo = pow(albedoColor, vec3(2.2)); + // 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) + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // ambient lighting (we now use IBL as the ambient term) (fresnelSchlickRoughness function) + vec3 F = fresnelSchlickRoughness(NdotV, F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + + vec3 irradiance = texture(irradianceMap, viewToWorld * N).rgb; + vec3 diffuse = irradiance * albedo; + + // sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part. + + vec3 prefilteredColor = textureLod(radianceMap, viewToWorld * R, roughness * MAX_REFLECTION_LOD).rgb; + vec2 brdf2 = texture(lut, vec2(NdotV, roughness)).rg; + vec3 specular = prefilteredColor * (F * brdf2.x + brdf2.y); + + // combining light + return kD * diffuse + specular; +} + +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 denom = (NdotH * NdotH * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + return a2 / denom; +} + +float GeometrySchlickGGX(float cosAlpha, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + return cosAlpha / (cosAlpha * (1.0 - k) + k); +} + +vec3 GGX( + in vec3 albedoColor, + in float metallic, + in float roughness, + in vec3 radiance, + in vec3 N, + in vec3 L, + in vec3 H, + in vec3 V) +{ + vec3 albedo = pow(albedoColor, vec3(2.2)); + vec3 F0 = mix(vec3(0.04), albedo, metallic); + float NdotL = max(dot(N, L), 0.0); + float NdotV = max(dot(N, V), 0.0); + + // Cook-Torrance BRDF + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySchlickGGX(NdotV, roughness) * GeometrySchlickGGX(NdotL, roughness); + vec3 F = F0 + (1.0 - F0) * pow(1.0 - clamp(dot(H, V), 0.0, 1.0), 5.0); + + vec3 nominator = NDF * G * F; + float denominator = 4 * NdotV * NdotL + 0.001; // 0.001 to prevent divide by zero. + vec3 brdf = nominator / denominator; + + vec3 kD = 1.0 - F; + kD *= 1.0 - metallic; + + return (kD * albedo / PI + brdf) * radiance * NdotL; +} + diff --git a/src/shadersource.cpp b/src/shadersource.cpp index 0f4b112..5ba250d 100644 --- a/src/shadersource.cpp +++ b/src/shadersource.cpp @@ -7,8 +7,22 @@ #include "mesh.h" #include "light.h" +// resource packs +#include + +RESOURCE_PACK(shaders) + +std::string ShaderSource::m_utilsSource = ""; + ShaderSource::ShaderSource() { + if(m_utilsSource.empty()) + { + Resource::ResourceMap shaderMap; + Resource::getResourcePack_shaders(shaderMap); + m_utilsSource = shaderMap["shaders/utils.glsl"]; + } + for(int i=0; i &defines) header += "\n#define "+std::string(def); header += "\n#line 1\n"; + header += m_utilsSource; + header += "\n#line 1\n"; if(sources[VERTEX] == NULL || sources[FRAGMENT] == NULL) return NULL; diff --git a/src/shadersource.h b/src/shadersource.h index a3e7ec6..5b1dbfd 100644 --- a/src/shadersource.h +++ b/src/shadersource.h @@ -28,6 +28,8 @@ public: private: std::string* sources[NB_TYPES]; + + static std::string m_utilsSource; }; #endif // SHADERSOURCE_H diff --git a/src/textureblur.cpp b/src/textureblur.cpp index 12d3be2..80fded4 100644 --- a/src/textureblur.cpp +++ b/src/textureblur.cpp @@ -11,7 +11,7 @@ TextureBlur::TextureBlur(FrameBuffer* input, int downsampling, int textureId) : horizontal(NULL), vertical(NULL) { - Texture* srcTexture = input->getTexture(textureId); + Texture* srcTexture = m_input->getTexture(textureId); int nb_fbos = (downsampling+1)*2; fbos = new FrameBuffer[nb_fbos]; Texture* tex = srcTexture;