Skip to content

Commit

Permalink
PBR shader support Iridescence (#2425)
Browse files Browse the repository at this point in the history
* feat(shader): pbr shader support Iridescence
  • Loading branch information
hhhhkrx authored Nov 19, 2024
1 parent 410dd72 commit 9a2b42f
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 6 deletions.
101 changes: 100 additions & 1 deletion packages/core/src/material/PBRMaterial.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MathUtil, Vector3 } from "@galacean/engine-math";
import { MathUtil, Vector2, Vector3, Vector4 } from "@galacean/engine-math";
import { Engine } from "../Engine";
import { ShaderProperty } from "../shader";
import { Shader } from "../shader/Shader";
Expand All @@ -20,6 +20,11 @@ export class PBRMaterial extends PBRBaseMaterial {

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);

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

/**
* The iridescence intensity factor, from 0.0 to 1.0.
* @defaultValue `0.0`
*/
get iridescence(): number {
return this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp).x;
}

set iridescence(value: number) {
value = Math.max(0, Math.min(1, value));
const iridescenceInfo = this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp);
if (!!iridescenceInfo.x !== !!value) {
if (value === 0) {
this.shaderData.disableMacro("MATERIAL_ENABLE_IRIDESCENCE");
} else {
this.shaderData.enableMacro("MATERIAL_ENABLE_IRIDESCENCE");
}
}
iridescenceInfo.x = value;
}

/**
* The iridescence intensity texture, sampling red channel, and multiply 'iridescence'.
*/
get iridescenceTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRMaterial._iridescenceTextureProp);
}

set iridescenceTexture(value: Texture2D) {
this.shaderData.setTexture(PBRMaterial._iridescenceTextureProp, value);

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

/**
* The index of refraction of the dielectric thin-film layer, greater than or equal to 1.0.
* @defaultValue `1.3`
*/
get iridescenceIOR(): number {
return this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp).y;
}

set iridescenceIOR(value: number) {
const iridescenceInfo = this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp);
iridescenceInfo.y = Math.max(value, 1.0);
}

/**
* The range of iridescence thickness, x is minimum, y is maximum.
* @defaultValue `[100, 400]`.
*/
get iridescenceThicknessRange(): Vector2 {
return this._iridescenceRange;
}

set iridescenceThicknessRange(value: Vector2) {
if (this._iridescenceRange !== value) {
this._iridescenceRange.copyFrom(value);
}
}

/**
* The thickness texture of the thin-film layer, sampling green channel.
* @remarks
* If iridescenceThicknessTexture is defined, iridescence thickness between the 'iridescenceThicknessRange'.
* If iridescenceThicknessTexture is not defined, iridescence thickness will use only 'iridescenceThicknessRange.y'.
*/
get iridescenceThicknessTexture(): Texture2D {
return <Texture2D>this.shaderData.getTexture(PBRMaterial._iridescenceThicknessTextureProp);
}

set iridescenceThicknessTexture(value: Texture2D) {
this.shaderData.setTexture(PBRMaterial._iridescenceThicknessTextureProp, value);

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

/**
* Create a pbr metallic-roughness workflow material instance.
* @param engine - Engine to which the material belongs
Expand All @@ -144,6 +234,15 @@ export class PBRMaterial extends PBRBaseMaterial {
shaderData.setFloat(PBRMaterial._roughnessProp, 1);
shaderData.setFloat(PBRMaterial._iorProp, 1.5);
shaderData.setVector3(PBRMaterial._anisotropyInfoProp, new Vector3(1, 0, 0));
shaderData.setVector4(PBRMaterial._iridescenceInfoProp, new Vector4(0, 1.3, 100, 400));
// @ts-ignore
this._iridescenceRange._onValueChanged = this._onIridescenceRangeChanged.bind(this);
}

private _onIridescenceRangeChanged(): void {
const iridescenceInfo = this.shaderData.getVector4(PBRMaterial._iridescenceInfoProp);
iridescenceInfo.z = this._iridescenceRange.x;
iridescenceInfo.w = this._iridescenceRange.y;
}

/**
Expand Down
23 changes: 18 additions & 5 deletions packages/loader/src/gltf/extensions/GLTFExtensionSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ export interface IKHRLightsPunctual {
* Interfaces from the KHR_materials_clearcoat extension
*/
export interface IKHRMaterialsClearcoat {
clearcoatFactor: number;
clearcoatTexture: ITextureInfo;
clearcoatRoughnessFactor: number;
clearcoatRoughnessTexture: ITextureInfo;
clearcoatNormalTexture: IMaterialNormalTextureInfo;
clearcoatFactor?: number;
clearcoatTexture?: ITextureInfo;
clearcoatRoughnessFactor?: number;
clearcoatRoughnessTexture?: ITextureInfo;
clearcoatNormalTexture?: IMaterialNormalTextureInfo;
}

/**
Expand Down Expand Up @@ -176,6 +176,18 @@ export interface IGalaceanAnimation {
}[];
}

/**
* Interfaces from the KHR_materials_iridescence extension
*/
export interface IKHRMaterialsIridescence {
iridescenceFactor?: number;
iridescenceTexture?: ITextureInfo;
iridescenceIor?: number;
iridescenceThicknessMinimum?: number;
iridescenceThicknessMaximum?: number;
iridescenceThicknessTexture?: ITextureInfo;
}

export type GLTFExtensionSchema =
| IKHRLightsPunctual_Light
| IKHRMaterialsClearcoat
Expand All @@ -194,4 +206,5 @@ export type GLTFExtensionSchema =
| IKHRXmp
| IKHRXmp_Node
| IGalaceanAnimation
| IKHRMaterialsIridescence
| Object;
39 changes: 39 additions & 0 deletions packages/loader/src/gltf/extensions/KHR_materials_iridescence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { PBRMaterial, Texture2D } 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 { IKHRMaterialsIridescence } from "./GLTFExtensionSchema";

@registerGLTFExtension("KHR_materials_iridescence", GLTFExtensionMode.AdditiveParse)
class KHR_materials_iridescence extends GLTFExtensionParser {
override additiveParse(context: GLTFParserContext, material: PBRMaterial, schema: IKHRMaterialsIridescence): void {
const {
iridescenceFactor = 0,
iridescenceTexture,
iridescenceIor = 1.3,
iridescenceThicknessMinimum = 100,
iridescenceThicknessMaximum = 400,
iridescenceThicknessTexture
} = schema;

material.iridescence = iridescenceFactor;
material.iridescenceIOR = iridescenceIor;
material.iridescenceThicknessRange.set(iridescenceThicknessMinimum, iridescenceThicknessMaximum);

if (iridescenceTexture) {
GLTFMaterialParser._checkOtherTextureTransform(iridescenceTexture, "Iridescence texture");

context.get<Texture2D>(GLTFParserType.Texture, iridescenceTexture.index).then((texture) => {
material.iridescenceTexture = texture;
});
}
if (iridescenceThicknessTexture) {
GLTFMaterialParser._checkOtherTextureTransform(iridescenceThicknessTexture, "IridescenceThickness texture");

context.get<Texture2D>(GLTFParserType.Texture, iridescenceThicknessTexture.index).then((texture) => {
material.iridescenceThicknessTexture = texture;
});
}
}
}
1 change: 1 addition & 0 deletions packages/loader/src/gltf/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import "./GALACEAN_materials_remap";
import "./GALACEAN_animation_event";
import "./EXT_meshopt_compression";
import "./KHR_materials_anisotropy";
import "./KHR_materials_iridescence";
import "./EXT_texture_webp";

export { GLTFExtensionParser, GLTFExtensionMode } from "./GLTFExtensionParser";
Expand Down

0 comments on commit 9a2b42f

Please sign in to comment.