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

pbr support transmission #2478

Merged
merged 39 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
39 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
0093886
Merge branch 'dev/1.4' of github.com:galacean/engine into refraction
hhhhkrx Dec 25, 2024
cf77ec4
feat: transmission
hhhhkrx Dec 25, 2024
2764f86
feat: transmission
hhhhkrx Dec 25, 2024
141095a
fix: transmission name
hhhhkrx Dec 26, 2024
36c994c
fix: refraction name
hhhhkrx Dec 26, 2024
2928dcc
fix: refraction mode
hhhhkrx Dec 26, 2024
26c7fd5
fix: refraction mode
hhhhkrx Dec 26, 2024
dd6e0ec
fix: refraction mode
hhhhkrx Dec 26, 2024
e9f3480
fix: specular name
hhhhkrx Dec 26, 2024
d12ff04
fix: specular name
hhhhkrx Dec 26, 2024
9338ec2
fix: diffuseColor mix refraction
hhhhkrx Dec 26, 2024
730548b
fix: diffuse and specular light
hhhhkrx Dec 26, 2024
0a776c4
fix: btdf
hhhhkrx Dec 26, 2024
ce75450
refactor: opt code
GuoLei1990 Dec 26, 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
216 changes: 204 additions & 12 deletions packages/core/src/material/PBRMaterial.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { MathUtil, Vector2, Vector3, Vector4, Color } from "@galacean/engine-math";
import { Engine } from "../Engine";
import { ShaderProperty } from "../shader";
import { ShaderMacro, ShaderProperty } from "../shader";
import { Shader } from "../shader/Shader";
import { Texture2D } from "../texture/Texture2D";
import { PBRBaseMaterial } from "./PBRBaseMaterial";
import { RefractionMode } from "./enums/Refraction";
import { RenderQueueType } from "../shader/enums/RenderQueueType";

/**
* PBR (Metallic-Roughness Workflow) Material.
Expand All @@ -18,19 +20,35 @@ export class PBRMaterial extends PBRBaseMaterial {
private static _anisotropyInfoProp = ShaderProperty.getByName("material_AnisotropyInfo");
private static _anisotropyTextureProp = ShaderProperty.getByName("material_AnisotropyTexture");

private _anisotropyRotation: number = 0;

private static _iridescenceInfoProp = ShaderProperty.getByName("material_IridescenceInfo");
private static _iridescenceThicknessTextureProp = ShaderProperty.getByName("material_IridescenceThicknessTexture");
private static _iridescenceTextureProp = ShaderProperty.getByName("material_IridescenceTexture");
private _iridescenceRange = new Vector2(100, 400);

private _sheenEnabled = false;
private static _sheenColorProp = ShaderProperty.getByName("material_SheenColor");
private static _sheenRoughnessProp = ShaderProperty.getByName("material_SheenRoughness");
private static _sheenTextureProp = ShaderProperty.getByName("material_SheenTexture");
private static _sheenRoughnessTextureProp = ShaderProperty.getByName("material_SheenRoughnessTexture");

private static _refractionMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_ENABLE_SS_REFRACTION");
private static _transmissionMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_HAS_TRANSMISSION");
private static _thicknessMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_HAS_THICKNESS");
private static _absorptionMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_HAS_ABSORPTION");
private static _thicknessTextureMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_HAS_THICKNESS_TEXTURE");
private static _transmissionTextureMacro: ShaderMacro = ShaderMacro.getByName("MATERIAL_HAS_TRANSMISSION_TEXTURE");
private static _transmissionProp = ShaderProperty.getByName("material_Transmission");
private static _transmissionTextureProp = ShaderProperty.getByName("material_TransmissionTexture");
private static _attenuationColorProp = ShaderProperty.getByName("material_AttenuationColor");
private static _attenuationDistanceProp = ShaderProperty.getByName("material_AttenuationDistance");
private static _thicknessProp = ShaderProperty.getByName("material_Thickness");
private static _thicknessTextureProp = ShaderProperty.getByName("material_ThicknessTexture");

private _refractionMode: RefractionMode;
private _anisotropyRotation: number = 0;
private _iridescenceRange = new Vector2(100, 400);
private _sheenEnabled = false;
private _absorptionEnabled = true;
private _lastRenderQueueType = RenderQueueType.Opaque;

/**
* Index Of Refraction.
* @defaultValue `1.5`
Expand Down Expand Up @@ -289,6 +307,143 @@ export class PBRMaterial extends PBRBaseMaterial {
}
}

/**
* Refraction switch.
* @remarks Use refractionMode to set the refraction shape.
*/
get refractionMode(): RefractionMode {
return this._refractionMode;
}

set refractionMode(value: RefractionMode) {
if (value !== this._refractionMode) {
if (value) {
this.renderState.renderQueueType = RenderQueueType.Transparent;
} else {
this.renderState.renderQueueType = this._lastRenderQueueType;
}
this._refractionMode = value;
this._setRefractionMode(value);
}
}
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved

override set isTransparent(value: boolean) {
super.isTransparent = value;
this._lastRenderQueueType = this.renderState.renderQueueType;
if (this.refractionMode !== RefractionMode.None) {
this.renderState.renderQueueType = RenderQueueType.Transparent;
}
}

override set alphaCutoff(value: number) {
super.alphaCutoff = value;
this._lastRenderQueueType = this.renderState.renderQueueType;
if (this.refractionMode !== RefractionMode.None) {
this.renderState.renderQueueType = RenderQueueType.Transparent;
}
}

/**
* Transmission factor.
* @defaultValue `0.0`
*/
get transmission(): number {
return this.shaderData.getFloat(PBRMaterial._transmissionProp);
}

set transmission(value: number) {
value = MathUtil.clamp(value, 0, 1);
if (!!this.shaderData.getFloat(PBRMaterial._transmissionProp) !== !!value) {
if (value > 0) {
this.shaderData.enableMacro(PBRMaterial._transmissionMacro);
} else {
this.shaderData.disableMacro(PBRMaterial._transmissionMacro);
}
}
this.shaderData.setFloat(PBRMaterial._transmissionProp, value);
}

/**
* Transmission texture.
* @remarks Use red channel, and multiply 'transmission'.
*/
get transmissionTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRMaterial._transmissionTextureProp);
}

set transmissionTexture(value: Texture2D) {
this.shaderData.setTexture(PBRMaterial._transmissionTextureProp, value);
if (value) {
this.shaderData.enableMacro(PBRMaterial._transmissionTextureMacro);
} else {
this.shaderData.disableMacro(PBRMaterial._transmissionTextureMacro);
}
}

/**
* Attenuation color.
* @defaultValue `[1,1,1]`
*/
get attenuationColor(): Color {
return this.shaderData.getColor(PBRMaterial._attenuationColorProp);
}

set attenuationColor(value: Color) {
const attenuationColor = this.shaderData.getColor(PBRMaterial._attenuationColorProp);
if (value !== attenuationColor) {
attenuationColor.copyFrom(value);
}
}

/**
* Attenuation distance, greater than 0.0.
* @defaultValue `infinity`
*/
get attenuationDistance(): number {
return this.shaderData.getFloat(PBRMaterial._attenuationDistanceProp);
}

set attenuationDistance(value: number) {
value = Math.max(0, value);
this.shaderData.setFloat(PBRMaterial._attenuationDistanceProp, value);
}

/**
* Thickness, greater than or equal to 0.0.
* @defaultValue `0.0`
*/
get thickness(): number {
return this.shaderData.getFloat(PBRMaterial._thicknessProp);
}

set thickness(value: number) {
value = Math.max(0, value);
if (!!this.shaderData.getFloat(PBRMaterial._thicknessProp) !== !!value) {
if (value > 0) {
this.shaderData.enableMacro(PBRMaterial._thicknessMacro);
} else {
this.shaderData.disableMacro(PBRMaterial._thicknessMacro);
}
}
this.shaderData.setFloat(PBRMaterial._thicknessProp, value);
}

/**
* Thickness texture.
* @remarks Use green channel, and multiply 'thickness', range is 0.0 to 1.0.
*/
get thicknessTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRMaterial._thicknessTextureProp);
}

set thicknessTexture(value: Texture2D) {
this.shaderData.setTexture(PBRMaterial._thicknessTextureProp, value);
if (value) {
this.shaderData.enableMacro(PBRMaterial._thicknessTextureMacro);
} else {
this.shaderData.disableMacro(PBRMaterial._thicknessTextureMacro);
}
}
/**
* Create a pbr metallic-roughness workflow material instance.
* @param engine - Engine to which the material belongs
Expand All @@ -304,8 +459,19 @@ export class PBRMaterial extends PBRBaseMaterial {
shaderData.setVector4(PBRMaterial._iridescenceInfoProp, new Vector4(0, 1.3, 100, 400));
const sheenColor = new Color(0, 0, 0);
shaderData.setColor(PBRMaterial._sheenColorProp, sheenColor);
shaderData.setFloat(PBRMaterial._transmissionProp, 0);
shaderData.setFloat(PBRMaterial._thicknessProp, 0);
shaderData.setFloat(PBRMaterial._attenuationDistanceProp, Infinity);
const attenuationColor = new Color(1, 1, 1);
shaderData.setColor(PBRMaterial._attenuationColorProp, attenuationColor);
shaderData.enableMacro(PBRMaterial._absorptionMacro);

// @ts-ignore
this._iridescenceRange._onValueChanged = this._onIridescenceRangeChanged.bind(this);
this._iridescenceRange._onValueChanged = () => {
Copy link
Member

Choose a reason for hiding this comment

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

Use bind this is more readability

const iridescenceInfo = this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp);
iridescenceInfo.z = this._iridescenceRange.x;
iridescenceInfo.w = this._iridescenceRange.y;
};
// @ts-ignore
sheenColor._onValueChanged = () => {
const enableSheen = sheenColor.r + sheenColor.g + sheenColor.b > 0;
Expand All @@ -318,12 +484,18 @@ export class PBRMaterial extends PBRBaseMaterial {
}
}
};
}

private _onIridescenceRangeChanged(): void {
const iridescenceInfo = this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp);
iridescenceInfo.z = this._iridescenceRange.x;
iridescenceInfo.w = this._iridescenceRange.y;
// @ts-ignore
attenuationColor._onValueChanged = () => {
const enableAbsorption = attenuationColor.r + attenuationColor.g + attenuationColor.b > 0;
if (enableAbsorption !== this._absorptionEnabled) {
this._absorptionEnabled = enableAbsorption;
if (enableAbsorption) {
this.shaderData.enableMacro(PBRMaterial._absorptionMacro);
} else {
this.shaderData.disableMacro(PBRMaterial._absorptionMacro);
}
}
};
}

/**
Expand All @@ -334,4 +506,24 @@ export class PBRMaterial extends PBRBaseMaterial {
this.cloneTo(dest);
return dest;
}

private _setRefractionMode(refractionMode: RefractionMode): void {
switch (refractionMode) {
case RefractionMode.None:
this.shaderData.disableMacro(PBRMaterial._refractionMacro);
break;
case RefractionMode.Sphere:
this.shaderData.enableMacro(PBRMaterial._refractionMacro);
this.shaderData.enableMacro("REFRACTION_MODE", "SPHERE");
break;
case RefractionMode.Plane:
this.shaderData.enableMacro(PBRMaterial._refractionMacro);
this.shaderData.enableMacro("REFRACTION_MODE", "PLANE");
break;
case RefractionMode.Thin:
this.shaderData.enableMacro(PBRMaterial._refractionMacro);
this.shaderData.enableMacro("REFRACTION_MODE", "THIN");
break;
}
}
}
13 changes: 13 additions & 0 deletions packages/core/src/material/enums/Refraction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Refraction mode.
*/
export enum RefractionMode {
/** No refraction. */
None,
/** Refraction shape is sphere. */
Sphere,
/** Refraction shape is plane. */
Plane,
/** Refraction shape is thin. */
Thin
}
1 change: 1 addition & 0 deletions packages/core/src/material/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { PBRBaseMaterial } from "./PBRBaseMaterial";
export { PBRMaterial } from "./PBRMaterial";
export { PBRSpecularMaterial } from "./PBRSpecularMaterial";
export { UnlitMaterial } from "./UnlitMaterial";
export { RefractionMode } from "./enums/Refraction";
11 changes: 11 additions & 0 deletions packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,16 @@ export interface IKHRMaterialsIridescence {
iridescenceThicknessTexture?: ITextureInfo;
}

/**
* Interfaces from the KHR_materials_volume extension
*/
export interface IKHRMaterialsVolume {
thicknessFactor?: number;
thicknessTexture?: ITextureInfo;
attenuationDistance?: number;
attenuationColor?: number[];
}

export type GLTFExtensionSchema =
| IKHRLightsPunctual_Light
| IKHRMaterialsClearcoat
Expand All @@ -207,4 +217,5 @@ export type GLTFExtensionSchema =
| IKHRXmp_Node
| IGalaceanAnimation
| IKHRMaterialsIridescence
| IKHRMaterialsVolume
| Object;
22 changes: 22 additions & 0 deletions packages/loader/src/gltf/extensions/KHR_materials_transmission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { PBRMaterial, Texture2D, RefractionMode } from "@galacean/engine-core";
import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
import { registerGLTFExtension } from "../parser/GLTFParser";
import { GLTFParserContext, GLTFParserType } from "../parser/GLTFParserContext";
import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
import { IKHRMaterialsTransmission } from "./GLTFExtensionSchema";
@registerGLTFExtension("KHR_materials_transmission", GLTFExtensionMode.AdditiveParse)
class KHR_materials_transmission extends GLTFExtensionParser {
override additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsTransmission): void {
const { transmissionFactor = 0, transmissionTexture } = schema;
material.refractionMode = RefractionMode.Plane;
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
material.transmission = transmissionFactor;

if (transmissionTexture) {
GLTFMaterialParser._checkOtherTextureTransform(transmissionTexture, "Transmission texture");

context.get<Texture2D>(GLTFParserType.Texture, transmissionTexture.index).then((texture) => {
material.transmissionTexture = texture;
});
}
}
}
34 changes: 34 additions & 0 deletions packages/loader/src/gltf/extensions/KHR_materials_volume.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { PBRMaterial, Texture2D, RefractionMode } from "@galacean/engine-core";
import { Color } from "@galacean/engine-math";
import { GLTFMaterialParser } from "../parser/GLTFMaterialParser";
import { registerGLTFExtension } from "../parser/GLTFParser";
import { GLTFParserContext, GLTFParserType } from "../parser/GLTFParserContext";
import { GLTFExtensionMode, GLTFExtensionParser } from "./GLTFExtensionParser";
import { IKHRMaterialsVolume } from "./GLTFExtensionSchema";

@registerGLTFExtension("KHR_materials_volume", GLTFExtensionMode.AdditiveParse)
class KHR_materials_volume extends GLTFExtensionParser {
override additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsVolume): void {
const { thicknessFactor = 0, thicknessTexture, attenuationDistance = Infinity, attenuationColor } = schema;
material.refractionMode = RefractionMode.Plane;
material.thickness = thicknessFactor;
material.attenuationDistance = attenuationDistance;

if (attenuationColor) {
material.attenuationColor.set(
Color.linearToGammaSpace(attenuationColor[0]),
Color.linearToGammaSpace(attenuationColor[1]),
Color.linearToGammaSpace(attenuationColor[2]),
undefined
);
}

if (thicknessTexture) {
GLTFMaterialParser._checkOtherTextureTransform(thicknessTexture, "Thickness texture");

context.get<Texture2D>(GLTFParserType.Texture, thicknessTexture.index).then((texture) => {
material.thicknessTexture = texture;
});
}
}
}
7 changes: 7 additions & 0 deletions packages/shader-shaderlab/src/shaders/Common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#define RECIPROCAL_PI 0.31830988618
#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
GuoLei1990 marked this conversation as resolved.
Show resolved Hide resolved
// #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 @@ -97,5 +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);
// }

#endif
Loading
Loading