#version 300 es
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoords;
layout(location = 3) in vec3 aTangent;
out vec3 Normal;
out vec2 TexCoords;
out vec3 TangentViewDir;
out mat3 iTBN;
out vec3 FragPos;
out vec3 camPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat3 normalMat;
uniform vec3 eyePos;
void main()
{
TexCoords = aTexCoords;
vec3 Position = aPos;
gl_Position = projection * view * model * vec4(Position, 1.0);
vec3 T = normalize(vec3(normalMat * aTangent));
vec3 N = normalize(vec3(normalMat * aNormal));
vec3 B = cross(N, T);
Normal = N;
mat3 TBN = transpose(mat3(T, B, N));
FragPos = vec3(model * vec4(Position, 1.0));
TangentViewDir = TBN * (eyePos - FragPos);
iTBN = inverse(TBN);
camPos = eyePos;
}
#version 300 es
precision mediump float;
#define PI 3.1415926535897932384626433832795
in vec3 Normal;
in vec2 TexCoords;
in vec3 TangentViewDir;
in mat3 iTBN;
in vec3 FragPos;
in vec3 camPos;
out vec4 FragColor;
uniform sampler2D albedoMap;
uniform sampler2D normalMap;
uniform sampler2D metallicMap;
uniform sampler2D roughnessMap;
uniform sampler2D aoMap;
uniform sampler2D brdfLUT;
uniform sampler2D environmentMap;
uniform float opacity;
//Fresnel-Schlick Fresnel equation
vec3 fresnelSchlick(float cosTheta, vec3 F0);
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness);
void main()
{
vec2 texCoords = TexCoords;
vec3 albedo = texture(albedoMap, texCoords).rgb;
float metallic = texture(metallicMap, texCoords).r;
float roughness = texture(roughnessMap, texCoords).r;
float ao = texture(aoMap, texCoords).r;
vec3 N = texture(normalMap, texCoords).rgb;
N = normalize(N * 2.0 - 1.0);
vec3 V = normalize(TangentViewDir);
vec3 R = reflect(-V, N);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 Lo = vec3(0.0);
// IBL
vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);
vec3 kS = F;
vec3 kD = 1.0 - kS;
kD *= 1.0 - metallic;
vec3 viewDir = normalize(FragPos - camPos);
vec3 reflectDir = reflect(viewDir, normalize(Normal));
// 模拟立方体映射
vec3 cubeMapUVW = reflectDir * 0.5 + 0.5;
// 从2D环境贴图中采样
vec3 irradiance = texture(environmentMap, cubeMapUVW.xy).rgb;
vec3 diffuse = irradiance * albedo;
vec3 prefilteredColor = mix(irradiance, vec3(1.0), roughness);
vec3 specular = prefilteredColor * F;
vec3 ambient = (kD * diffuse + specular) * ao;
vec3 color = ambient + Lo;
const float gamma = 2.2;
// gamma correction
color = pow(color, vec3(1.0/gamma));
FragColor = vec4(color, opacity);
}
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);
}