Skip to content

Commit

Permalink
pbr sheen (#312)
Browse files Browse the repository at this point in the history
* feat: pbr support sheen
  • Loading branch information
hhhhkrx authored Dec 12, 2024
1 parent d2e966c commit 3bfc9c0
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#define FUNCTION_SPECULAR_IBL evaluateSpecularIBLIridescence
#include "BRDF.glsl"
#include "./IridescenceFunction.glsl"
#include "LightProbe.glsl"
#include "LightIndirectFunctions.glsl"

void evaluateSpecularIBLIridescence(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, float radianceAttenuation, inout vec3 specularColor){

Expand Down
31 changes: 9 additions & 22 deletions packages/shaderlab/src/shaders/PBR.gs
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,20 @@ Shader "PBR.gs" {
material_IridescenceTexture("IridescenceTexture", Texture2D);
}

Header("Sheen"){
ui_SheenIntensity("Intensity", Range(0, 1, 0.01)) = 0;
ui_SheenColor("Color", Color ) = (0, 0, 0, 0);
material_SheenRoughness("Roughness", Range(0, 1, 0.01)) = 0;
material_SheenTexture("ColorTexture", Texture2D);
material_SheenRoughnessTexture("RoughnessTexture", Texture2D);
}

Header("Common") {
material_AlphaCutoff( "AlphaCutoff", Range(0, 1, 0.01) ) = 0;
material_TilingOffset("TilingOffset", Vector4) = (1, 1, 0, 0);
}
}

EditorMacros {
Header("Conditional Macors") {
MATERIAL_HAS_BASETEXTURE("HAS_BASETEXTURE");
MATERIAL_HAS_ROUGHNESS_METALLIC_TEXTURE("HAS_ROUGHNESS_METALLIC_TEXTURE");
MATERIAL_ENABLE_ANISOTROPY("ENABLE_ANISOTROPY");
MATERIAL_HAS_ANISOTROPY_TEXTURE("HAS_ANISOTROPY_TEXTURE")
MATERIAL_HAS_NORMALTEXTURE("HAS_NORMALTEXTURE");
MATERIAL_HAS_EMISSIVETEXTURE("HAS_EMISSIVETEXTURE");
MATERIAL_HAS_OCCLUSION_TEXTURE("HAS_OCCLUSION_TEXTURE");
MATERIAL_ENABLE_CLEAR_COAT("ENABLE_CLEAR_COAT");
MATERIAL_HAS_CLEAR_COAT_TEXTURE("HAS_CLEAR_COAT_TEXTURE");
MATERIAL_HAS_CLEAR_COAT_ROUGHNESS_TEXTURE("HAS_CLEAR_COAT_ROUGHNESS_TEXTURE");
MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE("HAS_CLEAR_COAT_NORMAL_TEXTURE");
MATERIAL_ENABLE_IRIDESCENCE("ENABLE_IRIDESCENCE");
MATERIAL_HAS_IRIDESCENCE_THICKNESS_TEXTURE("HAS_IRIDESCENCE_THICKNESS_TEXTURE");
MATERIAL_HAS_IRIDESCENCE_TEXTURE("HAS_IRIDESCENCE_TEXTURE");
MATERIAL_IS_TRANSPARENT("IS_TRANSPARENT");
MATERIAL_IS_ALPHA_CUTOFF("IS_ALPHA_CUTOFF");
}
}


SubShader "Default" {
UsePass "pbr/Default/ShadowCaster"

Expand Down
73 changes: 73 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/BRDF.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#define NEED_TANGENT
#endif

#ifdef MATERIAL_ENABLE_SHEEN
sampler2D scene_prefilteredLUT;
#endif

struct SurfaceData{
// common
Expand Down Expand Up @@ -56,6 +59,11 @@ struct SurfaceData{
float iridescenceThickness;
#endif

#ifdef MATERIAL_ENABLE_SHEEN
float sheenRoughness;
vec3 sheenColor;
#endif

};


Expand All @@ -72,6 +80,13 @@ struct BRDFData{
#ifdef MATERIAL_ENABLE_IRIDESCENCE
vec3 iridescenceSpecularColor;
#endif

#ifdef MATERIAL_ENABLE_SHEEN
float sheenRoughness;
float sheenScaling;
float approxIBLSheenDG;
#endif

};


Expand Down Expand Up @@ -305,6 +320,58 @@ vec3 BRDF_Diffuse_Lambert(vec3 diffuseColor) {
}
#endif

#ifdef MATERIAL_ENABLE_SHEEN
// http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf
float D_Charlie(float roughness, float dotNH) {
float invAlpha = 1.0 / roughness;
float cos2h = dotNH * dotNH;
float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16
return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);
}

// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886".
float V_Neubelt(float NoV, float NoL) {
return saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));
}

vec3 sheenBRDF(vec3 incidentDirection, SurfaceData surfaceData, vec3 sheenColor, float sheenRoughness) {
vec3 halfDir = normalize(incidentDirection + surfaceData.viewDir);
float dotNL = saturate(dot(surfaceData.normal, incidentDirection));
float dotNH = saturate(dot(surfaceData.normal, halfDir));
float D = D_Charlie(sheenRoughness, dotNH);
float V = V_Neubelt(surfaceData.dotNV, dotNL);
vec3 F = sheenColor;
return D * V * F;
}

float prefilteredSheenDFG(float dotNV, float sheenRoughness) {
#ifdef HAS_TEX_LOD
return texture2DLodEXT(scene_prefilteredLUT, vec2(dotNV, sheenRoughness), 0.0).b;
#else
return texture2D(scene_prefilteredLUT, vec2(dotNV, sheenRoughness),0.0).b;
#endif
}
#endif

// ------------------------Indirect Specular------------------------
// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
vec3 envBRDFApprox(vec3 specularColor, float roughness, float dotNV ) {

const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );

const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );

vec4 r = roughness * c0 + c1;

float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;

vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;

return specularColor * AB.x + AB.y;

}


void initBRDFData(SurfaceData surfaceData, out BRDFData brdfData){
vec3 albedoColor = surfaceData.albedoColor;
vec3 specularColor = surfaceData.specularColor;
Expand Down Expand Up @@ -332,6 +399,12 @@ void initBRDFData(SurfaceData surfaceData, out BRDFData brdfData){
float topIOR = 1.0;
brdfData.iridescenceSpecularColor = evalIridescenceSpecular(topIOR, surfaceData.dotNV, surfaceData.iridesceceIOR, brdfData.specularColor, surfaceData.iridescenceThickness);
#endif

#ifdef MATERIAL_ENABLE_SHEEN
brdfData.sheenRoughness = max(MIN_PERCEPTUAL_ROUGHNESS, min(surfaceData.sheenRoughness + getAARoughnessFactor(surfaceData.normal), 1.0));
brdfData.approxIBLSheenDG = prefilteredSheenDFG(surfaceData.dotNV, brdfData.sheenRoughness);
brdfData.sheenScaling = 1.0 - brdfData.approxIBLSheenDG * max(max(surfaceData.sheenColor.r, surfaceData.sheenColor.g), surfaceData.sheenColor.b);
#endif
}

#endif
29 changes: 29 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ float material_OcclusionTextureCoord;
#endif
#endif

#ifdef MATERIAL_ENABLE_SHEEN
float material_SheenRoughness;
vec3 material_SheenColor;
#ifdef MATERIAL_HAS_SHEEN_TEXTURE
sampler2D material_SheenTexture;
#endif

#ifdef MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE
sampler2D material_SheenRoughnessTexture;
#endif
#endif

// Texture
#ifdef MATERIAL_HAS_BASETEXTURE
sampler2D material_BaseTexture;
Expand Down Expand Up @@ -263,6 +275,23 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
#endif
#endif

#ifdef MATERIAL_ENABLE_SHEEN
vec3 sheenColor = material_SheenColor;
#ifdef MATERIAL_HAS_SHEEN_TEXTURE
vec4 sheenTextureColor = texture2D(material_SheenTexture, uv);
#ifndef ENGINE_IS_COLORSPACE_GAMMA
sheenTextureColor = gammaToLinear(sheenTextureColor);
#endif
sheenColor *= sheenTextureColor.rgb;
#endif
surfaceData.sheenColor = sheenColor;

surfaceData.sheenRoughness = material_SheenRoughness;
#ifdef MATERIAL_HAS_SHEEN_ROUGHNESS_TEXTURE
surfaceData.sheenRoughness *= texture2D(material_SheenRoughnessTexture, uv).a;
#endif
#endif

// AO
float diffuseAO = 1.0;
float specularAO = 1.0;
Expand Down
5 changes: 5 additions & 0 deletions packages/shaderlab/src/shaders/shadingPBR/LightDirectPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#ifndef FUNCTION_CLEAR_COAT_LOBE
#define FUNCTION_CLEAR_COAT_LOBE clearCoatLobe
#endif
#ifndef FUNCTION_SHEEN_LOBE
#define FUNCTION_SHEEN_LOBE sheenLobe
#endif

#include "BRDF.glsl"
#include "Light.glsl"
Expand All @@ -34,6 +37,8 @@ void surfaceShading(Varyings varyings, SurfaceData surfaceData, BRDFData brdfDat
FUNCTION_DIFFUSE_LOBE(varyings, surfaceData, brdfData, attenuationIrradiance, diffuseColor);
// Specular Lobe
FUNCTION_SPECULAR_LOBE(varyings, surfaceData, brdfData, incidentDirection, attenuationIrradiance, specularColor);
// Sheen Lobe
FUNCTION_SHEEN_LOBE(varyings, surfaceData, brdfData, incidentDirection, attenuationIrradiance, diffuseColor, specularColor);

color += diffuseColor + specularColor;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
#ifndef LIGHT_PROBE
#define LIGHT_PROBE

// ------------------------Specular------------------------

// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
vec3 envBRDFApprox(vec3 specularColor, float roughness, float dotNV ) {

const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );

const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );

vec4 r = roughness * c0 + c1;

float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;

vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;

return specularColor * AB.x + AB.y;

}

#ifndef LIGHT_INDIRECT_FUNCTIONS_INCLUDED
#define LIGHT_INDIRECT_FUNCTIONS_INCLUDED
#include "Light.glsl"

vec3 getReflectedVector(SurfaceData surfaceData, vec3 n) {
#ifdef MATERIAL_ENABLE_ANISOTROPY
Expand Down Expand Up @@ -67,5 +48,4 @@ vec3 getLightProbeRadiance(SurfaceData surfaceData, vec3 normal, float roughness

#endif
}

#endif
21 changes: 18 additions & 3 deletions packages/shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
#ifndef FUNCTION_CLEAR_COAT_IBL
#define FUNCTION_CLEAR_COAT_IBL evaluateClearCoatIBL
#endif

#ifndef FUNCTION_SHEEN_IBL
#define FUNCTION_SHEEN_IBL evaluateSheenIBL
#endif
#include "BRDF.glsl"
#include "Light.glsl"
#include "LightProbe.glsl"
#include "LightIndirectFunctions.glsl"

// ------------------------Diffuse------------------------

Expand Down Expand Up @@ -77,6 +79,15 @@ void evaluateSpecularIBL(Varyings varyings, SurfaceData surfaceData, BRDFData br
outSpecularColor += surfaceData.specularAO * radianceAttenuation * radiance * envBRDFApprox(speculaColor, brdfData.roughness, surfaceData.dotNV);
}

void evaluateSheenIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor){
#ifdef MATERIAL_ENABLE_SHEEN
diffuseColor *= brdfData.sheenScaling;
specularColor *= brdfData.sheenScaling;

vec3 reflectance = surfaceData.specularAO * radianceAttenuation * brdfData.approxIBLSheenDG * surfaceData.sheenColor;
specularColor += reflectance;
#endif
}

void evaluateIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, inout vec3 color){
vec3 diffuseColor = vec3(0);
Expand All @@ -90,8 +101,12 @@ void evaluateIBL(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData,

// IBL specular
FUNCTION_SPECULAR_IBL(varyings, surfaceData, brdfData, radianceAttenuation, specularColor);


// IBL sheen
FUNCTION_SHEEN_IBL(varyings, surfaceData, brdfData, radianceAttenuation, diffuseColor, specularColor);

color += diffuseColor + specularColor;

}


Expand Down
13 changes: 11 additions & 2 deletions packages/shaderlab/src/shaders/shadingPBR/ReflectionLobe.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ void diffuseLobe(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData,
}

void specularLobe(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 specularColor){
specularColor += attenuationIrradiance * BRDF_Specular_GGX( incidentDirection, surfaceData, brdfData, surfaceData.normal, brdfData.specularColor, brdfData.roughness);
specularColor += attenuationIrradiance * BRDF_Specular_GGX( incidentDirection, surfaceData, brdfData, surfaceData.normal, brdfData.specularColor, brdfData.roughness);
}

void sheenLobe(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, vec3 incidentDirection, vec3 attenuationIrradiance, inout vec3 diffuseColor, inout vec3 specularColor){
#ifdef MATERIAL_ENABLE_SHEEN
diffuseColor *= brdfData.sheenScaling;
specularColor *= brdfData.sheenScaling;

specularColor += attenuationIrradiance * sheenBRDF(incidentDirection, surfaceData, surfaceData.sheenColor, brdfData.sheenRoughness);
#endif
}

float clearCoatLobe(Varyings varyings, SurfaceData surfaceData, BRDFData brdfData, vec3 incidentDirection, vec3 color, inout vec3 specularColor){
Expand All @@ -16,7 +25,7 @@ float clearCoatLobe(Varyings varyings, SurfaceData surfaceData, BRDFData brdfDat
float clearCoatDotNL = saturate( dot( surfaceData.clearCoatNormal, incidentDirection ) );
vec3 clearCoatIrradiance = clearCoatDotNL * color;

specularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX( incidentDirection, surfaceData, surfaceData.clearCoatNormal, brdfData.clearCoatSpecularColor, brdfData.clearCoatRoughness );
specularColor += surfaceData.clearCoat * clearCoatIrradiance * BRDF_Specular_GGX( incidentDirection, surfaceData, brdfData, surfaceData.clearCoatNormal, brdfData.clearCoatSpecularColor, brdfData.clearCoatRoughness );
attenuation -= surfaceData.clearCoat * F_Schlick(0.04, surfaceData.clearCoatDotNV);
#endif

Expand Down
4 changes: 2 additions & 2 deletions packages/shaderlab/src/shaders/shadingPBR/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import AttributesPBR from "./AttributesPBR.glsl";
import BRDF from "./BRDF.glsl";
import LightProbe from "./LightProbe.glsl";
import LightIndirectFunctions from "./LightIndirectFunctions.glsl";
import ForwardPassPBR from "./ForwardPassPBR.glsl";
import FragmentPBR from "./FragmentPBR.glsl";
import LightDirectPBR from "./LightDirectPBR.glsl";
Expand All @@ -18,6 +18,6 @@ export default [
{ source: LightIndirectPBR, includeKey: "LightIndirectPBR.glsl" },
{ source: VertexPBR, includeKey: "VertexPBR.glsl" },
{ source: BRDF, includeKey: "BRDF.glsl" },
{ source: LightProbe, includeKey: "LightProbe.glsl" },
{ source: LightIndirectFunctions, includeKey: "LightIndirectFunctions.glsl" },
{ source: ReflectionLobe, includeKey: "ReflectionLobe.glsl" }
];

0 comments on commit 3bfc9c0

Please sign in to comment.