Closed but0n closed 6 years ago
@emackey Hi, Recently I'm learning about PBR, your project is great, it help me a lot! I've already done:
And I've composition those with BRDF, but currently I'm confuse about how to calculate the final color,
#define PI 3.1415926535898
precision mediump float;
uniform vec3 u_ambientLight; // Current frame const 环境光颜色
uniform vec3 u_lightColor; // Current frame const 光源颜色
// uniform vec3 u_lightPosition; // Current frame const 光源位置
uniform vec3 u_lightDirection; // Current frame const 光源位置
uniform samplerCube u_sky;
uniform vec3 u_Camera;
varying mat4 v_model;
uniform sampler2D u_sampler;
varying vec3 v_normal; // 每个片元的法线
varying vec3 v_pos; // 每个片元的位置
varying vec2 v_texCoord; // 每个片元的纹素坐标
// varying vec4 v_color; // 每个片元的固有色
void main () {
// vec4 color = texture2D(u_sampler, v_texCoord);
vec3 n = normalize(v_normal);
vec3 v = normalize(( vec4(u_Camera - v_pos, 0.0)).xyz);
// vec3 v = normalize(u_Camera - v_pos);
// vec3 l = normalize(u_lightDirection);
vec3 l = normalize((v_model * vec4(u_lightDirection, 0.0)).xyz);
vec3 h = normalize(l+v);
// Fresnel - Specular Reflection
vec3 F;
vec3 f0 = vec3(0.01);
// float VdotH = dot(v, h);
float VdotH = clamp(dot(v, n), 0.0, 1.0);
F = f0 + (1.0 - f0) * pow(1.0 - VdotH, 2.0);
// Distribution
float D;
float roughness = 0.1;
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float NdotH = clamp(dot(n, h), 0.001, 1.0);
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = abs(dot(n, v));
float NdotHSq = NdotH * NdotH;
D = alphaSq / (pow( NdotHSq * alphaSq - NdotHSq + 1.0, 2.0) * PI);
// Geometric
float G;
float k = pow(roughness + 1.0, 2.0) / 8.0;
float Gl = NdotL / ((NdotL - NdotL * k) + k);
float Gv = NdotV / ((NdotV - NdotV * k) + k);
G = Gl * Gv;
vec3 specularContrib = F * G * D / (4.0 * NdotL * NdotV);
// Diffuse
float LdotH = dot(l, h);
float f90 = 2.0 * LdotH * LdotH * roughness - 0.5;
vec3 color = vec3(0.0, 0.4, 0.8);
vec3 specularColor = textureCube(u_sky, (v_model *vec4(reflect(n,v), 1.0)).xyz).rgb;
color = (color) * (1.0 + f90 * pow((1.0 - NdotL), 5.0)) * (1.0 + f90 * pow((1.0 - NdotV), 5.0));
// vec3 diffuseContrib = (1.0 - F) * color;
// vec3 diffuseContrib = vec3(0.3, 0.8, 0.9) * max(dot(n, l), 0.01); // Lamber
vec3 diffuseContrib = vec3(0.1, 0.6, 1.0);
// gl_FragColor = vec4(F, 1.0);
// gl_FragColor = vec4(specularContrib, 1.0);
// gl_FragColor = vec4(specularContrib * specularColor, 1.0);
gl_FragColor = vec4(diffuseContrib + specularColor * (specularContrib + F), 1.0);
// gl_FragColor = vec4(diffuseContrib * (1.0-F) + specularColor * F , 1.0);
// gl_FragColor = vec4(diffuseContrib + specularColor * (specularContrib), 1.0);
}
The final image is weird, and I have no idea how to fix it, can you help me?
Thanks!
F = f0 + (1.0 - f0) * pow(1.0 - VdotN, 2.0);
F = f0 + (1.0 - f0) * pow(1.0 - VdotH, 2.0);
vec2 envBRDF = texture2D(BRDFIntegrationMap, vec2(NdotV, roughness)).xy;
vec3 indirectSpecular = prefilteredColor * (F * envBRDF.x + envBRDF.y)
BRDF black hole???
#define PI 3.1415926535898
precision mediump float;
uniform vec3 u_ambientLight; // Current frame const 环境光颜色
uniform vec3 u_lightColor; // Current frame const 光源颜色
// uniform vec3 u_lightPosition; // Current frame const 光源位置
uniform vec3 u_lightDirection; // Current frame const 光源位置
uniform samplerCube u_sky;
uniform sampler2D brdf; // BRDF LUT
uniform sampler2D uv_Normal;
uniform sampler2D uv_Basecolor;
uniform sampler2D uv_Metallic;
uniform sampler2D uv_Roughness;
uniform vec3 u_Camera;
varying mat4 v_model;
uniform sampler2D u_sampler;
varying vec3 v_normal; // 每个片元的法线
varying vec3 v_pos; // 每个片元的位置
varying vec2 v_texCoord; // 每个片元的纹素坐标
// varying vec4 v_color; // 每个片元的固有色
vec3 Fresnel(vec3 f0, float LoN, vec3 roughness) {
return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - LoN, 5.0);
}
float Distribution(float roughness, float NoH) {
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float NoHsqr = NoH * NoH;
return alphaSq / (pow( NoHsqr * alphaSq - NoHsqr + 1.0, 2.0) * PI);;
}
float Geometric(float roughness, float NoL, float NoV) {
float k = pow(roughness + 1.0, 2.0) / 8.0;
float Gl = NoL / ((NoL - NoL * k) + k);
float Gv = NoV / ((NoV - NoV * k) + k);
return Gl * Gv;
}
void main () {
// PBR Material
vec4 PBRBasecolor = texture2D(uv_Basecolor, v_texCoord);
vec4 PBRNormal = texture2D(uv_Normal, v_texCoord);
vec4 PBRMetallic = texture2D(uv_Metallic, v_texCoord);
vec4 PBRRoughness = texture2D(uv_Roughness, v_texCoord);
vec3 normalAddation = PBRNormal.xyz;
vec3 n = normalize(v_normal + normalAddation);
// vec3 v = normalize(( vec4(u_Camera - v_pos, 0.0)).xyz);
vec3 v = normalize(u_Camera - v_pos);
// vec3 l = normalize(u_lightDirection);
vec3 l = normalize((v_model * vec4(u_lightDirection, 0.0)).xyz);
vec3 h = normalize(l+v);
// Fresnel - Specular Reflection
vec3 F;
// vec3 f0 = vec3(0.04);
vec3 f0 = 1.0-PBRMetallic.xyz;
float metallic = 0.9;
float VdotH = dot(v, h);
// Distribution
float D;
float roughness = 0.1;
float NdotH = clamp(dot(n, h), 0.001, 1.0);
float NdotL = clamp(dot(n, l), 0.001, 1.0);
// float NdotV = abs(dot(n, v));
float NdotV = clamp(dot(n, v), 0.000, 0.99);
// D = Distribution(roughness, NdotH);
// Geometric
float G;
G = Geometric(roughness, NdotL, NdotV);
// vec3 specularContrib = F * G * D / (4.0 * NdotL * NdotV);
// Diffuse
float LdotH = dot(l, h);
float f90 = 2.0 * LdotH * LdotH * roughness - 0.5;
vec3 specularColor = textureCube(u_sky, (v_model *vec4(reflect(-v,n), 1.0)).xyz).rgb;
vec2 envBRDF = texture2D(brdf, vec2(NdotV, PBRRoughness)).rg;
vec3 Fre = Fresnel(f0, NdotV, PBRRoughness.xyz);
vec3 indirectSpecular = specularColor * (Fre * envBRDF.r + envBRDF.g);
gl_FragColor = vec4(1.0-Fre, 1.0) * PBRMetallic * PBRBasecolor + vec4(indirectSpecular, 0.0);
uniform sampler2D uv_Normal;
uniform sampler2D uv_Basecolor;
uniform sampler2D uv_Metallic;
uniform sampler2D uv_Roughness;
varying vec3 v_normal;
varying vec3 v_pos;
varying vec2 xlv_TEXCOORD0;
varying mat4 v_w2o;
vec3 Fresnel(vec3 f0, float LoN, vec3 roughness) {
return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - LoN, 5.0);
}
float Distribution(float roughness, float NoH) {
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float NoHsqr = NoH * NoH;
return alphaSq / (pow( NoHsqr * alphaSq - NoHsqr + 1.0, 2.0) * PI);;
}
float Geometric(float roughness, float NoL, float NoV) {
float k = pow(roughness + 1.0, 2.0) / 8.0;
float Gl = NoL / ((NoL - NoL * k) + k);
float Gv = NoV / ((NoV - NoV * k) + k);
return Gl * Gv;
}
void main () {
// PBR Material
vec4 PBRBasecolor = texture2D(uv_Basecolor, xlv_TEXCOORD0);
vec4 PBRNormal = texture2D(uv_Normal, xlv_TEXCOORD0);
vec4 PBRMetallic = texture2D(uv_Metallic, xlv_TEXCOORD0);
vec4 PBRRoughness = texture2D(uv_Roughness, xlv_TEXCOORD0);
vec3 n = normalize(v_normal + PBRNormal.xyz);
vec3 v = normalize(glstate_eyepos - v_pos);
float NdotV = clamp(dot(n, v), 0.000, 0.99);
vec3 f0 = vec3(0.04);
f0 = mix(f0, PBRBasecolor.xyz, PBRMetallic.xyz);
vec3 envLight = textureCube(u_sky, (glstate_matrix_world2object * vec4(reflect(-v,n), 1.0)).xyz).rgb;
vec2 envBRDF = texture2D(brdf, vec2(NdotV, PBRRoughness)).rg;
vec3 F = Fresnel(f0, NdotV, PBRRoughness.xyz);
vec3 indirectSpecular = envLight * (F * envBRDF.r + envBRDF.g);
gl_FragColor = vec4(1.0 - F, 1.0) * (1.0 - PBRMetallic) * PBRBasecolor + vec4(indirectSpecular, 0.0); // IBL+PBR
}
http://blog.csdn.net/w450468524/article/details/51649703 Normal Texture Usage
This version is use standard material, add AO texture and compression Metallic and Roughness
It is important to note here that although
metallic
androughness
are separate parameters, they are provided as a single texture in which themetallic
values are in the blue channel and theroughness
values are in the green channel to save on space.
In those standard PBR material from Unity and UE , the metallic
values are in both RGB channel, and the roughness
values are in the alpha channel.
#extension GL_OES_standard_derivatives : enable
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define PI 3.141592653589
uniform samplerCube u_sky; // IBL
uniform sampler2D brdf; // BRDF LUT
uniform vec3 glstate_eyepos;
uniform highp mat4 glstate_matrix_world2object;
// PBR 材质贴图
uniform sampler2D uv_Normal;
uniform sampler2D uv_Basecolor;
uniform sampler2D uv_MetallicRoughness;
uniform sampler2D uv_AO;
varying vec3 v_normal;
varying vec3 v_pos;
varying vec2 xlv_TEXCOORD0;
varying mat4 v_w2o;
vec3 Fresnel(vec3 f0, float LoN, float roughness) {
return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - LoN, 5.0);
}
float Distribution(float roughness, float NoH) {
float alpha = roughness * roughness;
float alphaSq = alpha * alpha;
float NoHsqr = NoH * NoH;
return alphaSq / (pow( NoHsqr * alphaSq - NoHsqr + 1.0, 2.0) * PI);;
}
float Geometric(float roughness, float NoL, float NoV) {
float k = pow(roughness + 1.0, 2.0) / 8.0;
float Gl = NoL / ((NoL - NoL * k) + k);
float Gv = NoV / ((NoV - NoV * k) + k);
return Gl * Gv;
}
mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv){
// get edge vectors of the pixel triangle
vec3 dp1 = dFdx( p );
vec3 dp2 = dFdy( p );
vec2 duv1 = dFdx( uv );
vec2 duv2 = dFdy( uv );
// solve the linear system
vec3 dp2perp = cross( dp2, N );
vec3 dp1perp = cross( N, dp1 );
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
// construct a scale-invariant frame
float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
return mat3( T * invmax, B * invmax, N );
}
void main () {
// PBR Material
vec4 PBRBasecolor = texture2D(uv_Basecolor, xlv_TEXCOORD0);
vec4 PBRNormal = texture2D(uv_Normal, xlv_TEXCOORD0);
vec3 PBRMetallic = texture2D(uv_MetallicRoughness, xlv_TEXCOORD0).rgb;
float PBRRoughness = texture2D(uv_MetallicRoughness, xlv_TEXCOORD0).a;
vec4 PBRAO = texture2D(uv_AO, xlv_TEXCOORD0);
vec3 n = normalize(v_normal);
vec3 v = normalize(glstate_eyepos - v_pos);
mat3 TBN = cotangent_frame(n, v, xlv_TEXCOORD0);
vec3 normalAddation = PBRNormal.rgb * 2.0 - 1.0;
n = normalize(TBN * normalAddation);
float NdotV = abs(dot(n, v));
vec3 f0 = vec3(0.04);
f0 = mix(f0, PBRBasecolor.xyz, PBRMetallic);
vec3 envLight = textureCube(u_sky, (glstate_matrix_world2object * vec4(reflect(-v,n), 1.0)).xyz).rgb;
vec2 envBRDF = texture2D(brdf, vec2(NdotV, PBRRoughness)).rg;
vec3 F = Fresnel(f0, NdotV, PBRRoughness);
vec3 indirectSpecular = envLight * (F * envBRDF.r + envBRDF.g);
// vec3 indirectSpecular = envLight * (f0 * envBRDF.r + envBRDF.g);
gl_FragColor = (vec4((1.0 - F) * (1.0 - PBRMetallic), 1.0) * PBRBasecolor + vec4(indirectSpecular, 1.0)) * PBRAO; // IBL+PBR
}
http://www.babylonjs.com/demos/pbrglossy/
http://github.khronos.org/glTF-WebGL-PBR/
https://megascans.se/