Skip to content

Commit

Permalink
Feat: support pbr clearcoat (#669)
Browse files Browse the repository at this point in the history
* feat: support clearcoat

* feat: support  Specular  AA
  • Loading branch information
zhuxudong authored Apr 21, 2022
1 parent a0e66c5 commit 390aed6
Show file tree
Hide file tree
Showing 20 changed files with 394 additions and 137 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/asset/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function requestRes<T>(url: string, config: RequestConfig): AssetPromise<T> {
xhr.setRequestHeader(name, headers[name]);
});
}
xhr.send(config.body as XMLHttpRequestBodyInit);
xhr.send(config.body as any);
});
}

Expand Down
89 changes: 89 additions & 0 deletions packages/core/src/material/PBRBaseMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export abstract class PBRBaseMaterial extends BaseMaterial {
private static _emissiveTextureProp = Shader.getPropertyByName("u_emissiveSampler");
private static _occlusionTextureProp = Shader.getPropertyByName("u_occlusionSampler");

private static _clearCoatProp = Shader.getPropertyByName("u_clearCoat");
private static _clearCoatTextureProp = Shader.getPropertyByName("u_clearCoatTexture");
private static _clearCoatRoughnessProp = Shader.getPropertyByName("u_clearCoatRoughness");
private static _clearCoatRoughnessTextureProp = Shader.getPropertyByName("u_clearCoatRoughnessTexture");
private static _clearCoatNormalTextureProp = Shader.getPropertyByName("u_clearCoatNormalTexture");

/**
* Base color.
*/
Expand Down Expand Up @@ -164,6 +170,86 @@ export abstract class PBRBaseMaterial extends BaseMaterial {
}
}

/**
* The clearCoat layer intensity, default 0.
*/
get clearCoat(): number {
return this.shaderData.getFloat(PBRBaseMaterial._clearCoatProp);
}

set clearCoat(value: number) {
if (!!this.shaderData.getFloat(PBRBaseMaterial._clearCoatProp) !== !!value) {
if (value === 0) {
this.shaderData.disableMacro("CLEARCOAT");
} else {
this.shaderData.enableMacro("CLEARCOAT");
}
}
this.shaderData.setFloat(PBRBaseMaterial._clearCoatProp, value);
}

/**
* The clearCoat layer intensity texture.
*/
get clearCoatTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRBaseMaterial._clearCoatTextureProp);
}

set clearCoatTexture(value: Texture2D) {
this.shaderData.setTexture(PBRBaseMaterial._clearCoatTextureProp, value);

if (value) {
this.shaderData.enableMacro("HAS_CLEARCOATTEXTURE");
} else {
this.shaderData.disableMacro("HAS_CLEARCOATTEXTURE");
}
}

/**
* The clearCoat layer roughness, default 0.
*/
get clearCoatRoughness(): number {
return this.shaderData.getFloat(PBRBaseMaterial._clearCoatRoughnessProp);
}

set clearCoatRoughness(value: number) {
this.shaderData.setFloat(PBRBaseMaterial._clearCoatRoughnessProp, value);
}

/**
* The clearCoat layer roughness texture.
*/
get clearCoatRoughnessTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRBaseMaterial._clearCoatRoughnessTextureProp);
}

set clearCoatRoughnessTexture(value: Texture2D) {
this.shaderData.setTexture(PBRBaseMaterial._clearCoatRoughnessTextureProp, value);

if (value) {
this.shaderData.enableMacro("HAS_CLEARCOATROUGHNESSTEXTURE");
} else {
this.shaderData.disableMacro("HAS_CLEARCOATROUGHNESSTEXTURE");
}
}

/**
* The clearCoat normal map texture.
*/
get clearCoatNormalTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRBaseMaterial._clearCoatNormalTextureProp);
}

set clearCoatNormalTexture(value: Texture2D) {
this.shaderData.setTexture(PBRBaseMaterial._clearCoatNormalTextureProp, value);

if (value) {
this.shaderData.enableMacro("HAS_CLEARCOATNORMALTEXTURE");
} else {
this.shaderData.disableMacro("HAS_CLEARCOATNORMALTEXTURE");
}
}

/**
* Create a pbr base material instance.
* @param engine - Engine to which the material belongs
Expand All @@ -184,5 +270,8 @@ export abstract class PBRBaseMaterial extends BaseMaterial {
shaderData.setFloat(PBRBaseMaterial._normalTextureIntensityProp, 1);
shaderData.setFloat(PBRBaseMaterial._occlusionTextureIntensityProp, 1);
shaderData.setFloat(PBRBaseMaterial._occlusionTextureCoordProp, TextureCoordinate.UV0);

shaderData.setFloat(PBRBaseMaterial._clearCoatProp, 0);
shaderData.setFloat(PBRBaseMaterial._clearCoatRoughnessProp, 0);
}
}
8 changes: 4 additions & 4 deletions packages/core/src/material/PBRMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class PBRMaterial extends PBRBaseMaterial {
private static _metallicRoughnessTextureProp = Shader.getPropertyByName("u_metallicRoughnessSampler");

/**
* Metallic.
* Metallic, default 1.0.
*/
get metallic(): number {
return this.shaderData.getFloat(PBRMaterial._metallicProp);
Expand All @@ -23,7 +23,7 @@ export class PBRMaterial extends PBRBaseMaterial {
}

/**
* Roughness.
* Roughness, default 1.0.
*/
get roughness(): number {
return this.shaderData.getFloat(PBRMaterial._roughnessProp);
Expand Down Expand Up @@ -56,8 +56,8 @@ export class PBRMaterial extends PBRBaseMaterial {
*/
constructor(engine: Engine) {
super(engine, Shader.find("pbr"));
this.shaderData.setFloat(PBRMaterial._metallicProp, 1.0);
this.shaderData.setFloat(PBRMaterial._roughnessProp, 1.0);
this.shaderData.setFloat(PBRMaterial._metallicProp, 1);
this.shaderData.setFloat(PBRMaterial._roughnessProp, 1);
}

/**
Expand Down
12 changes: 5 additions & 7 deletions packages/core/src/shaderlib/begin_normal_vert.glsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#ifndef OMIT_NORMAL
#ifdef O3_HAS_NORMAL
vec3 normal = vec3( NORMAL );
#endif

vec3 normal = vec3( NORMAL );

#if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE )

#ifdef O3_HAS_TANGENT
vec4 tangent = vec4( TANGENT );

#endif

#endif
#endif
4 changes: 2 additions & 2 deletions packages/core/src/shaderlib/blendShape_vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
normal += getBlendShapeVertexElement(i, vertexElementOffset) * weight;
#endif

#if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) && defined( OASIS_BLENDSHAPE_TANGENT )
#if defined( O3_HAS_TANGENT ) && defined(OASIS_BLENDSHAPE_TANGENT) && ( defined(O3_NORMAL_TEXTURE) || defined(HAS_CLEARCOATNORMALTEXTURE) )
vertexElementOffset += 1;
tangent.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight;
#endif
Expand All @@ -33,7 +33,7 @@
normal += NORMAL_BS3 * u_blendShapeWeights[3];
#endif

#if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) && defined( OASIS_BLENDSHAPE_TANGENT )
#if defined( O3_HAS_TANGENT ) && defined(OASIS_BLENDSHAPE_TANGENT) && ( defined(O3_NORMAL_TEXTURE) || defined(HAS_CLEARCOATNORMALTEXTURE) )
tangent.xyz += TANGENT_BS0 * u_blendShapeWeights[0];
tangent.xyz += TANGENT_BS1 * u_blendShapeWeights[1];
tangent.xyz += TANGENT_BS2 * u_blendShapeWeights[2];
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/shaderlib/common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#define saturate( a ) clamp( a, 0.0, 1.0 )
#define whiteCompliment(a) ( 1.0 - saturate( a ) )

float pow2(float x ) {
return x * x;
}

vec4 RGBMToLinear(vec4 value, float maxRange ) {
return vec4( value.rgb * value.a * maxRange, 1.0 );
}
Expand Down
8 changes: 7 additions & 1 deletion packages/core/src/shaderlib/mobile_blinnphong_frag.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
vec3 N = getNormal();
#ifdef O3_NORMAL_TEXTURE
mat3 tbn = getTBN();
vec3 N = getNormalByNormalTexture(tbn, u_normalTexture, u_normalIntensity, v_uv);
#else
vec3 N = getNormal();
#endif

vec3 lightDiffuse = vec3( 0.0, 0.0, 0.0 );
vec3 lightSpecular = vec3( 0.0, 0.0, 0.0 );

Expand Down
84 changes: 46 additions & 38 deletions packages/core/src/shaderlib/normal_get.glsl
Original file line number Diff line number Diff line change
@@ -1,47 +1,55 @@
vec3 getNormal()
{
#ifdef O3_NORMAL_TEXTURE
#ifndef O3_HAS_TANGENT
#ifdef HAS_DERIVATIVES
vec3 pos_dx = dFdx(v_pos);
vec3 pos_dy = dFdy(v_pos);
vec3 tex_dx = dFdx(vec3(v_uv, 0.0));
vec3 tex_dy = dFdy(vec3(v_uv, 0.0));
vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
#ifdef O3_HAS_NORMAL
vec3 ng = normalize(v_normal);
#else
vec3 ng = normalize( cross(pos_dx, pos_dy) );
#endif
t = normalize(t - ng * dot(ng, t));
vec3 b = normalize(cross(ng, t));
mat3 tbn = mat3(t, b, ng);
#else
#ifdef O3_HAS_NORMAL
vec3 ng = normalize(v_normal);
#else
vec3 ng = vec3(0.0, 0.0, 1.0);
#endif
mat3 tbn = mat3(vec3(0.0), vec3(0.0), ng);
#endif
#else
mat3 tbn = v_TBN;
#endif
vec3 n = texture2D(u_normalTexture, v_uv ).rgb;
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalIntensity, u_normalIntensity, 1.0)));
#else
vec3 getNormal(){
#ifdef O3_HAS_NORMAL
vec3 n = normalize(v_normal);
vec3 normal = v_normal;
#elif defined(HAS_DERIVATIVES)
vec3 pos_dx = dFdx(v_pos);
vec3 pos_dy = dFdy(v_pos);
vec3 n = normalize( cross(pos_dx, pos_dy) );
vec3 normal = normalize( cross(pos_dx, pos_dy) );
#else
vec3 n= vec3(0.0,0.0,1.0);
vec3 normal = vec3(0, 0, 1);
#endif
#endif

n *= float( gl_FrontFacing ) * 2.0 - 1.0;
normal *= float( gl_FrontFacing ) * 2.0 - 1.0;
return normal;
}

vec3 getNormalByNormalTexture(mat3 tbn, sampler2D normalTexture, float normalIntensity, vec2 uv){
vec3 normal = texture2D(normalTexture, uv).rgb;
normal = normalize(tbn * ((2.0 * normal - 1.0) * vec3(normalIntensity, normalIntensity, 1.0)));
normal *= float( gl_FrontFacing ) * 2.0 - 1.0;

return n;
return normal;
}

mat3 getTBN(){
#if defined(O3_HAS_NORMAL) && defined(O3_HAS_TANGENT) && ( defined(O3_NORMAL_TEXTURE) || defined(HAS_CLEARCOATNORMALTEXTURE) )
mat3 tbn = v_TBN;
#else
vec3 normal = getNormal();
vec3 position = v_pos;
vec2 uv = gl_FrontFacing? v_uv: -v_uv;

#ifdef HAS_DERIVATIVES
// ref: http://www.thetenthplanet.de/archives/1180
// get edge vectors of the pixel triangle
vec3 dp1 = dFdx(position);
vec3 dp2 = dFdy(position);
vec2 duv1 = dFdx(uv);
vec2 duv2 = dFdy(uv);

// solve the linear system
vec3 dp2perp = cross(dp2, normal);
vec3 dp1perp = cross(normal, dp1);
vec3 tangent = dp2perp * duv1.x + dp1perp * duv2.x;
vec3 binormal = dp2perp * duv1.y + dp1perp * duv2.y;

// construct a scale-invariant frame
float invmax = inversesqrt(max(dot(tangent, tangent), dot(binormal, binormal)));
mat3 tbn = mat3(tangent * invmax, binormal * invmax, normal);
#else
mat3 tbn = mat3(vec3(0.0), vec3(0.0), normal);
#endif
#endif

return tbn;
}
19 changes: 7 additions & 12 deletions packages/core/src/shaderlib/normal_share.glsl
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
#ifdef O3_HAS_NORMAL

#if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE )

varying mat3 v_TBN;

#else

varying vec3 v_normal;

#ifndef OMIT_NORMAL
#ifdef O3_HAS_NORMAL
varying vec3 v_normal;
#if defined(O3_HAS_TANGENT) && ( defined(O3_NORMAL_TEXTURE) || defined(HAS_CLEARCOATNORMALTEXTURE) )
varying mat3 v_TBN;
#endif
#endif

#endif
#endif
19 changes: 8 additions & 11 deletions packages/core/src/shaderlib/normal_vert.glsl
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
#ifndef OMIT_NORMAL
#ifdef O3_HAS_NORMAL

#if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE )

vec3 normalW = normalize( mat3(u_normalMat) * normal.xyz );
vec3 tangentW = normalize( mat3(u_normalMat) * tangent.xyz );
vec3 bitangentW = cross( normalW, tangentW ) * tangent.w;
v_TBN = mat3( tangentW, bitangentW, normalW );

#else

v_normal = normalize( mat3(u_normalMat) * normal );

#endif
#if defined(O3_HAS_TANGENT) && ( defined(O3_NORMAL_TEXTURE) || defined(HAS_CLEARCOATNORMALTEXTURE) )
vec3 normalW = normalize( mat3(u_normalMat) * normal.xyz );
vec3 tangentW = normalize( mat3(u_normalMat) * tangent.xyz );
vec3 bitangentW = cross( normalW, tangentW ) * tangent.w;

v_TBN = mat3( tangentW, bitangentW, normalW );
#endif
#endif
#endif
18 changes: 13 additions & 5 deletions packages/core/src/shaderlib/pbr/brdf.glsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
float F_Schlick(float dotLH) {
return 0.04 + 0.96 * (pow(1.0 - dotLH, 5.0));
}

vec3 F_Schlick(vec3 specularColor, float dotLH ) {

// Original approximation by Christophe Schlick '94
Expand Down Expand Up @@ -39,15 +43,15 @@ float D_GGX(float alpha, float dotNH ) {
}

// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
vec3 BRDF_Specular_GGX(vec3 incidentDirection, GeometricContext geometry, vec3 specularColor, float roughness ) {
vec3 BRDF_Specular_GGX(vec3 incidentDirection, vec3 viewDir, vec3 normal, vec3 specularColor, float roughness ) {

float alpha = pow2( roughness ); // UE4's roughness

vec3 halfDir = normalize( incidentDirection + geometry.viewDir );
vec3 halfDir = normalize( incidentDirection + viewDir );

float dotNL = saturate( dot( geometry.normal, incidentDirection ) );
float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
float dotNH = saturate( dot( geometry.normal, halfDir ) );
float dotNL = saturate( dot( normal, incidentDirection ) );
float dotNV = saturate( dot( normal, viewDir ) );
float dotNH = saturate( dot( normal, halfDir ) );
float dotLH = saturate( dot( incidentDirection, halfDir ) );

vec3 F = F_Schlick( specularColor, dotLH );
Expand All @@ -59,3 +63,7 @@ vec3 BRDF_Specular_GGX(vec3 incidentDirection, GeometricContext geometry, vec3 s
return F * ( G * D );

}

vec3 BRDF_Diffuse_Lambert(vec3 diffuseColor ) {
return RECIPROCAL_PI * diffuseColor;
}
Loading

0 comments on commit 390aed6

Please sign in to comment.