t01y / WebGL_Learning

0 stars 0 forks source link

Support PBR #3

Closed but0n closed 6 years ago

but0n commented 6 years ago
but0n commented 6 years ago

http://blog.csdn.net/leonwei/article/details/44539217

but0n commented 6 years ago

https://www.shadertoy.com/view/4sSfzK

but0n commented 6 years ago

https://sketchfab.com/search?q=PBR

but0n commented 6 years ago

but0n commented 6 years ago

http://www.klayge.org/wiki/index.php/%E5%9F%BA%E4%BA%8E%E7%89%A9%E7%90%86%E7%9A%84BRDF

知乎大佬推荐

but0n commented 6 years ago

https://www.cnblogs.com/cg4213/p/5946077.html

公式

but0n commented 6 years ago

http://blog.selfshadow.com/publications/s2012-shading-course/

Disney

but0n commented 6 years ago

Physically Based Shading and Image Based Lighting

but0n commented 6 years ago

https://seblagarde.wordpress.com/2011/08/17/hello-world/amp/

but0n commented 6 years ago

IBL

https://blog.uwa4d.com/archives/Study_IBL.html

but0n commented 6 years ago

http://www.jianshu.com/p/936dd66f5135 http://www.humus.name/index.php?page=Textures 贴图素材

but0n commented 6 years ago

http://www.babylonjs.com/demos/pbr/

but0n commented 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!

but0n commented 6 years ago

image

but0n commented 6 years ago

image

Fresnel

but0n commented 6 years ago
F = f0 + (1.0 - f0) * pow(1.0 - VdotN, 2.0);

image image


F = f0 + (1.0 - f0) * pow(1.0 - VdotH, 2.0);

image

but0n commented 6 years ago

https://computergraphics.stackexchange.com/questions/2494/in-a-physically-based-brdf-what-vector-should-be-used-to-compute-the-fresnel-co

but0n commented 6 years ago

https://blog.playcanvas.com/physically-based-rendering-comes-to-webgl/

but0n commented 6 years ago

https://www.youtube.com/watch?v=K-WRY8MKHvk

but0n commented 6 years ago

https://h3r.github.io/wpbr/

but0n commented 6 years ago

but0n commented 6 years ago

http://blog.csdn.net/huangzhipeng/article/details/54620005?locationNum=15&fps=1

but0n commented 6 years ago

but0n commented 6 years ago

LookUpTexture

vec2 envBRDF          = texture2D(BRDFIntegrationMap, vec2(NdotV, roughness)).xy;
vec3 indirectSpecular = prefilteredColor * (F * envBRDF.x + envBRDF.y)
but0n commented 6 years ago

image BRDF black hole???

but0n commented 6 years ago

Looks Great

image image image

#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);
but0n commented 6 years ago

image image image

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
}
but0n commented 6 years ago

http://blog.csdn.net/w450468524/article/details/51649703 Normal Texture Usage

but0n commented 6 years ago

image This version is use standard material, add AO texture and compression Metallic and Roughness image

but0n commented 6 years ago

image

but0n commented 6 years ago

The fresnel is come back after I figure out how does the normal texture works #

image

image

but0n commented 6 years ago

Metallic is weird

image

but0n commented 6 years ago

Material from glTF-WebGL-PBR

image

It is important to note here that although metallic and roughness are separate parameters, they are provided as a single texture in which the metallic values are in the blue channel and the roughness 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.

image

image

but0n commented 6 years ago

BACKUP

#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
}
but0n commented 6 years ago

总结

https://learnopengl-cn.github.io/07%20PBR/01%20Theory/#_1

but0n commented 6 years ago

Sphere Matrix

image

image

but0n commented 6 years ago

Light

image

image

but0n commented 6 years ago

http://twvideo01.ubm-us.net/o1/vault/gdc2016/Presentations/Bugden_Sam_AnEndTo.pdf 比较详细的资料