Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shaderlab pbr support refraction #2470

Merged
merged 44 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
dd09252
feat: shaderlab pbr support refraction
hhhhkrx Dec 18, 2024
1fc002e
fix: disableMacro
hhhhkrx Dec 19, 2024
adfdfec
fix: name
hhhhkrx Dec 19, 2024
62844aa
Merge branch 'dev/1.4' of github.com:galacean/engine into refraction
hhhhkrx Dec 20, 2024
ffa2912
fix: refraction mode
hhhhkrx Dec 20, 2024
1fc63b2
fix: keep iridescenceRange unified
hhhhkrx Dec 20, 2024
bab9582
fix: refraction
hhhhkrx Dec 20, 2024
174e0e7
fix: refraction
hhhhkrx Dec 20, 2024
47fb197
fix: refraction mode
hhhhkrx Dec 20, 2024
f9b748c
fix: refraction
hhhhkrx Dec 24, 2024
4ef6387
Merge branch 'dev/1.4' of github.com:galacean/engine into refraction
hhhhkrx Dec 24, 2024
76b40b1
fix: refraction
hhhhkrx Dec 24, 2024
3abe5c1
fix: refraction
hhhhkrx Dec 24, 2024
b81bbeb
fix: refraction
hhhhkrx Dec 24, 2024
bcc9daf
fix: refraction
hhhhkrx Dec 24, 2024
b9b9558
fix: refraction
hhhhkrx Dec 24, 2024
9d8a37e
Merge branch 'dev/1.4' of github.com:galacean/engine into refraction
hhhhkrx Dec 24, 2024
84e2f0d
fix: refraction mode
hhhhkrx Dec 24, 2024
e977cbc
fix: refraction mode
hhhhkrx Dec 24, 2024
4040c26
fix: refraction shader
hhhhkrx Dec 24, 2024
420566d
fix: refraction
hhhhkrx Dec 24, 2024
4a3ce3e
fix: refraction mode
hhhhkrx Dec 24, 2024
6b19600
fix: refraction
hhhhkrx Dec 24, 2024
129ac02
fix: refraction value
hhhhkrx Dec 24, 2024
1ff952d
fix: refraction
hhhhkrx Dec 24, 2024
1f011eb
Merge branch 'dev/1.4' into refraction
hhhhkrx Dec 27, 2024
76d9063
fix: dev/1.4
hhhhkrx Dec 27, 2024
d2c26cf
refactor: opt code
hhhhkrx Dec 27, 2024
9d9e4ae
fix: refraction mode
hhhhkrx Dec 27, 2024
02ae05e
fix: refractionModel name
hhhhkrx Dec 27, 2024
a493e26
fix: refraction mode
hhhhkrx Dec 27, 2024
59e0da3
fix: sort
hhhhkrx Dec 27, 2024
e062e18
fix: include
hhhhkrx Dec 27, 2024
aa434e4
fix: refraction mode enable
hhhhkrx Dec 27, 2024
82d9754
fix: refracion mode number
hhhhkrx Dec 27, 2024
4c5eb18
fix: refraction model
hhhhkrx Dec 27, 2024
b6c874a
fix: refraction name
hhhhkrx Dec 27, 2024
0bf8d73
fix: refraction mode
hhhhkrx Dec 27, 2024
1f20667
fix: annotation
hhhhkrx Dec 27, 2024
d4b5d11
fix: attenuation
hhhhkrx Dec 27, 2024
df27aef
fix: attenuation
hhhhkrx Dec 27, 2024
1ba3440
fix: refraction
hhhhkrx Dec 27, 2024
09397f0
fix: annotation
hhhhkrx Dec 27, 2024
e7718de
fix: refraction mode
hhhhkrx Dec 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions packages/core/src/material/PBRMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ export class PBRMaterial extends PBRBaseMaterial {
set refractionMode(value: RefractionMode) {
if (value !== this._refractionMode) {
this._refractionMode = value;
this._setRefractionMode(value);
this.shaderData.enableMacro("REFRACTION_MODE", value.toString());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add macro cleanup and value validation.

The current implementation has potential issues:

  1. No cleanup of previous macro value before setting new one
  2. No handling of RefractionMode.None

Apply this diff to fix these issues:

- this.shaderData.enableMacro("REFRACTION_MODE", value.toString());
+ if (value === RefractionMode.None) {
+   this.shaderData.disableMacro("REFRACTION_MODE");
+ } else {
+   this.shaderData.enableMacro("REFRACTION_MODE", value.toString());
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.shaderData.enableMacro("REFRACTION_MODE", value.toString());
if (value === RefractionMode.None) {
this.shaderData.disableMacro("REFRACTION_MODE");
} else {
this.shaderData.enableMacro("REFRACTION_MODE", value.toString());
}

}
}

Expand Down Expand Up @@ -524,18 +524,4 @@ export class PBRMaterial extends PBRBaseMaterial {
}
}
}

private _setRefractionMode(refractionMode: RefractionMode): void {
switch (refractionMode) {
case RefractionMode.Sphere:
this.shaderData.enableMacro("REFRACTION_MODE", "SPHERE");
break;
case RefractionMode.Plane:
this.shaderData.enableMacro("REFRACTION_MODE", "PLANE");
break;
case RefractionMode.Thin:
this.shaderData.enableMacro("REFRACTION_MODE", "THIN");
break;
}
}
}
6 changes: 2 additions & 4 deletions packages/core/src/material/enums/Refraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
*/
export enum RefractionMode {
zhuxudong marked this conversation as resolved.
Show resolved Hide resolved
/** Refraction shape is sphere. */
Sphere,
Sphere = 0,
/** Refraction shape is plane. */
Plane,
/** Refraction shape is thin. */
Thin
Plane = 1
}
12 changes: 6 additions & 6 deletions packages/shader-shaderlab/src/shaders/Common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define EPSILON 1e-6
#define LOG2 1.442695
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
// #define HALF_EPS 4.8828125e-4 // 2^-11, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f)
#define HALF_EPS 4.8828125e-4 // 2^-11, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f)

#define saturate( a ) clamp( a, 0.0, 1.0 )

Expand Down Expand Up @@ -99,10 +99,10 @@ float remapDepthBufferLinear01(float z){
#define INVERSE_MAT(mat) inverseMat(mat)
#endif

// vec3 safeNormalize(vec3 inVec)
// {
// float dp3 = max(float(HALF_MIN), dot(inVec, inVec));
// return inVec * inversesqrt(dp3);
// }
vec3 safeNormalize(vec3 inVec)
{
float dp3 = max(float(HALF_MIN), dot(inVec, inVec));
return inVec * inversesqrt(dp3);
}

#endif
4 changes: 4 additions & 0 deletions packages/shader-shaderlab/src/shaders/PBR.gs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ Shader "PBR.gs" {
Header("Transmission"){
material_Transmission("Transmission", Range(0, 1, 0.01)) = 0;
material_TransmissionTexture("TransmissionTexture", Texture2D);
material_AttenuationColor("AttenuationColor", Color ) = (1, 1, 1, 1);
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
material_AttenuationDistance("AttenuationDistance", Range(0, 1, 0.01)) = 0;
material_Thickness("Thickness", Range(0, 5, 0.01)) = 0;
material_ThicknessTexture("ThicknessTexture", Texture2D);
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
}

Header("Common") {
Expand Down
22 changes: 19 additions & 3 deletions packages/shader-shaderlab/src/shaders/shadingPBR/BTDF.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,28 @@
sampler2D camera_OpaqueTexture;
vec3 evaluateRefraction(SurfaceData surfaceData, BRDFData brdfData) {
RefractionModelResult ray;
#ifdef REFRACTION_MODE
refractionModelBox(-surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, 0.005, ray);
// '0' is refraction sphere, '1' is refraction plane, '2' is refraction thin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function named evaluateTransmission is better

#if REFRACTION_MODE == 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// RefractionMode.Plane

refractionModelSphere(-surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray);
#elif REFRACTION_MODE == 1
refractionModelBox(-surfaceData.viewDir, surfaceData.position, surfaceData.normal, surfaceData.IOR, surfaceData.thickness, ray);
#endif
//TODO: support cubemap refraction.

vec3 refractedRayExit = ray.positionExit;

// We calculate the screen space position of the refracted point
vec4 samplingPositionNDC = camera_ProjMat * camera_ViewMat * vec4( refractedRayExit, 1.0 );
vec2 refractionCoords = (samplingPositionNDC.xy / samplingPositionNDC.w) * 0.5 + 0.5;
Copy link
Member

@zhuxudong zhuxudong Dec 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@todo: No need to process if the coord exceeds the screen?


// Absorption coefficient from Disney: http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf
#ifdef MATERIAL_HAS_ABSORPTION
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
#ifdef MATERIAL_HAS_THICKNESS
vec3 transmittance = min(vec3(1.0), exp(-surfaceData.absorptionCoefficient * ray.transmissionLength));
#else
vec3 transmittance = 1.0 - surfaceData.absorptionCoefficient;
#endif
#endif

// Sample the opaque texture to get the transmitted light
vec4 getTransmission = texture2D(camera_OpaqueTexture, refractionCoords);
vec3 refractionTransmitted = getTransmission.rgb;
Expand All @@ -27,6 +39,10 @@
vec3 specularDFG = brdfData.envSpecularDFG;

refractionTransmitted *= (1.0 - specularDFG);

GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
#ifdef MATERIAL_HAS_ABSORPTION
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@todo: camera distance

refractionTransmitted *= transmittance;
#endif

return refractionTransmitted;
}
Expand Down
34 changes: 26 additions & 8 deletions packages/shader-shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,20 @@ float material_OcclusionTextureCoord;
#endif
#endif

#ifdef MATERIAL_ENABLE_TRANSMISSION
float material_Transmission;
#ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
sampler2D material_TransmissionTexture;
#ifdef MATERIAL_ENABLE_TRANSMISSION
vec3 material_AttenuationColor;
float material_AttenuationDistance;
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
float material_Transmission;
zhuxudong marked this conversation as resolved.
Show resolved Hide resolved
#ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
sampler2D material_TransmissionTexture;
#endif

#ifdef MATERIAL_HAS_THICKNESS
float material_Thickness;
#ifdef MATERIAL_HAS_THICKNESS_TEXTURE
sampler2D material_ThicknessTexture;
#endif
#endif
#endif

// Texture
Expand Down Expand Up @@ -302,10 +311,19 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
#endif

#ifdef MATERIAL_ENABLE_TRANSMISSION
surfaceData.transmission = material_Transmission;
#ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
surfaceData.transmission *= texture2D(material_TransmissionTexture, uv).r;
#endif
surfaceData.transmission = material_Transmission;
#ifdef MATERIAL_HAS_TRANSMISSION_TEXTURE
surfaceData.transmission *= texture2D(material_TransmissionTexture, uv).r;
#endif

surfaceData.absorptionCoefficient = -log(material_AttenuationColor + HALF_EPS) / max(HALF_EPS, material_AttenuationDistance);

#ifdef MATERIAL_HAS_THICKNESS
surfaceData.thickness = max(material_Thickness, 0.0001);
#ifdef MATERIAL_HAS_THICKNESS_TEXTURE
surfaceData.thickness *= texture2D( material_ThicknessTexture, uv).g;
#endif
#endif
#endif

// AO
Expand Down
21 changes: 21 additions & 0 deletions packages/shader-shaderlab/src/shaders/shadingPBR/Refraction.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ struct RefractionModelResult{
// vec3 directionExit; // out ray direction
};

//https://docs.unity3d.com/Packages/[email protected]/manual/refraction-models.html
void refractionModelSphere(vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray){
// Refracted ray
vec3 R1 = refract(V, normalWS, 1.0 / ior);
// Center of the tangent sphere
vec3 C = positionWS - normalWS * thickness * 0.5;

// Second refraction (tangent sphere out)
float dist = dot(-normalWS, R1) * thickness;
// Out hit point in the tangent sphere
vec3 P1 = positionWS + R1 * dist;
// Out normal
vec3 N1 = safeNormalize(C - P1);
// Out refracted ray
// vec3 R2 = refract(R1, N1, ior);

ray.transmissionLength = dist;
ray.positionExit = P1;
// ray.directionExit = R2;
}

void refractionModelBox(vec3 V, vec3 positionWS, vec3 normalWS, float ior, float thickness, out RefractionModelResult ray){
// Refracted ray
vec3 R = refract(V, normalWS, 1.0 / ior);
Expand Down
Loading