//--PIX vs_skybox layout(location = 0) in vec3 Position; uniform mat4 MVPMat; uniform mat4 ModelViewMat; out vec3 glUV; void main() { vec4 pos = vec4(Position, 1); gl_Position = MVPMat * pos; glUV = Position; } //--PIX ps_skybox in vec3 glUV; layout(location = 0) out vec4 glFragColor; uniform samplerCube skybox_tex; uniform float iExposure; const float gamma = 2.2; void main() { vec3 c = textureLod(skybox_tex, glUV, 0).rgb; c = 1 - exp(-c * iExposure); c = pow(c, vec3(1. / gamma)); glFragColor = vec4(c, 1); } //--VER vs_material_based_render layout(location = 0) in vec3 Position; layout(location = 1) in vec2 TexCoord; layout(location = 2) in vec3 Normal; uniform mat4 MVPMat; uniform mat4 ModelViewMat; uniform mat3 NormalViewMat; uniform mat3 NormalMat; out vec3 glPos; out vec2 glUV; out vec3 glNormal; out vec3 glNormalWorld; void main() { vec4 pos = vec4(Position, 1); gl_Position = MVPMat * pos; glPos = (ModelViewMat * pos).xyz; glUV = TexCoord; glNormal = NormalViewMat * Normal; glNormalWorld = NormalMat * Normal; } //--PIX ps_material_based_render in vec3 glPos; in vec2 glUV; in vec3 glNormal; in vec3 glNormalWorld; layout(location = 0) out vec4 glFragColor; struct Light { vec3 Pos; vec4 Color; }; layout(std140) uniform iLights { int iLightsNum; Light iLight[ 20 ]; }; uniform samplerCube irradiance_cubetex; uniform samplerCube specular_cubetex; uniform sampler2D brdf_lut_tex; uniform vec3 iCameraWorld; uniform vec3 iAlbedo; uniform float iMetallicity; uniform float iRoughness; uniform float iExposure; uniform float iMaxLod; const float gamma = 2.2; const float ao = .1; const float refractive_index = .1; const float PI = 3.1415927; vec3 fresnelSchlick(float cos_theta, vec3 F0) { return F0 + (max(vec3(1. - iRoughness), F0) - F0) * pow(1. - cos_theta, 5); } float DistributionGGX(vec3 N, vec3 H) { float a = iRoughness * iRoughness; float a2 = a * a; float NdotH = max(dot(N, H), 0); float NdotH2 = NdotH * NdotH; float num = a2; float denom = (NdotH2 * (a2 - 1) + 1); denom = PI * denom * denom; return num / denom; } float GeometrySchlickGGX(float NdotV) { float r = (iRoughness + 1); float k = (r * r) / 8; float num = NdotV; float denom = NdotV * (1. - k) + k; return num / denom; } float GeometrySmith(vec3 N, vec3 V, vec3 L) { float NdotV = max(dot(N, V), 0); float NdotL = max(dot(N, L), 0); float ggx2 = GeometrySchlickGGX(NdotV); float ggx1 = GeometrySchlickGGX(NdotL); return ggx1 * ggx2; } void main() { vec3 normal = normalize(glNormal); vec3 eye_vec = normalize(-glPos); vec3 F0 = mix(vec3(.04), iAlbedo, iMetallicity); vec3 Lo = vec3(0); for (int i = 0; i < iLightsNum; ++i) { vec3 light_vec = normalize(iLight[ i ].Pos - glPos); vec3 half_vec = normalize(eye_vec + light_vec); float dist = length(iLight[ i ].Pos - glPos); vec3 radiance = iLight[ i ].Color.xyz * iLight[ i ].Color.a / (dist * dist); float NDF = DistributionGGX(normal, half_vec); float G = GeometrySmith(normal, eye_vec, light_vec); vec3 F = fresnelSchlick(max(dot(half_vec, eye_vec), 0), F0); vec3 kS = F; vec3 kD = 1 - kS; kD *= 1. - iMetallicity; vec3 numerator = NDF * G * F; float denominator = max(dot(normal, eye_vec), 0) * max(dot(normal, light_vec), 0) * 4; vec3 specular = numerator / max(denominator, .01); float NdotL = max(dot(normal, light_vec), 0); const float invPI = 1. / PI; Lo += (kD * iAlbedo * invPI + specular) * radiance * NdotL; } vec3 kS = fresnelSchlick(max(dot(normal, eye_vec), 0), F0); vec3 kD = 1. - kS; kD *= 1. - iMetallicity; vec3 normal_world = normalize(glNormalWorld); vec3 irradiance = texture(irradiance_cubetex, normal_world).rgb; vec3 diffuse = irradiance * iAlbedo; vec3 R = reflect(-iCameraWorld, normal_world); vec3 prefiltered = textureLod(specular_cubetex, R, iRoughness * iMaxLod).rgb; vec2 brdf = texture(brdf_lut_tex, vec2(max(dot(normal, eye_vec), 0), iRoughness)).rg; vec3 specular = prefiltered * (kS * brdf.x + brdf.y); vec3 ambient = (kD * diffuse + specular) * ao; vec3 c = ambient + Lo; c = 1 - exp(-c * iExposure); c = pow(c, vec3(1. / gamma)); glFragColor = vec4(c, 1); }