@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
94 lines (84 loc) • 3.55 kB
text/typescript
import {Constructor} from '../../../../types/GlobalTypes';
import {BaseController} from './_BaseController';
import {TypedMatNode} from '../_Base';
import {Material} from 'three';
import {ShaderMaterial} from 'three';
import {NodeParamsConfig, ParamConfig} from '../../utils/params/ParamsConfig';
import {CustomMaterialName, ShaderMaterialWithCustomMaterials} from '../../../../core/geometry/Material';
import {isBooleanTrue} from '../../../../core/BooleanValue';
import {ParamsValueAccessorType} from '../../utils/params/ParamsValueAccessor';
export interface UniformsTransparencyControllers {
uniformTransparency: UniformsTransparencyController;
}
export function UniformsTransparencyParamConfig<TBase extends Constructor>(Base: TBase) {
return class Mixin extends Base {
/** @param sets the material to transparent */
transparent = ParamConfig.BOOLEAN(0);
/** @param sets the material opacity */
opacity = ParamConfig.FLOAT(1);
/** @param sets the min alpha below which the material is invisible */
alphaTest = ParamConfig.FLOAT(0);
};
}
type TransparencyMaterial = Material;
// class TransparencyMaterial extends Material {
// // transparent!: boolean;
// // depthTest!: boolean;
// // alphaTest!: number;
// // uniforms!: IUniforms;
// }
class TransparencyParamsConfig extends UniformsTransparencyParamConfig(NodeParamsConfig) {}
class TransparencyMatNode extends TypedMatNode<TransparencyMaterial, TransparencyParamsConfig> {
async material() {
const container = await this.compute();
return container.material() as TransparencyMaterial | undefined;
}
controllers!: UniformsTransparencyControllers;
}
export class UniformsTransparencyController extends BaseController {
constructor(protected override node: TransparencyMatNode) {
super(node);
}
static async update(node: TransparencyMatNode) {
const material = await node.material();
if (!material) {
return;
}
node.controllers.uniformTransparency.updateMaterial(material);
}
override updateMaterial(material: TransparencyMaterial) {
const pv = this.node.pv;
this._updateTransparency(material, pv);
}
private _updateTransparency(mat: TransparencyMaterial, pv: ParamsValueAccessorType<TransparencyParamsConfig>) {
// transparent is currently only changed for the main material,
// not for the customMaterials,
// as that currently makes them disappear.
// Also, we do not use the alternative condition || pv.opacity < 1;
// to set a material transparent, as this can be useful to have those params independent,
// especially for shadow materials
mat.transparent = isBooleanTrue(pv.transparent);
this._updateCommon(mat, pv);
}
private _updateCommon(mat: TransparencyMaterial, pv: ParamsValueAccessorType<TransparencyParamsConfig>) {
const shaderMaterial = mat as ShaderMaterial;
if (shaderMaterial.uniforms && shaderMaterial.uniforms.opacity) {
shaderMaterial.uniforms.opacity.value = pv.opacity;
}
mat.opacity = pv.opacity;
if (shaderMaterial.uniforms && shaderMaterial.uniforms.alphaTest) {
shaderMaterial.uniforms.alphaTest.value = pv.alphaTest;
}
mat.alphaTest = pv.alphaTest;
const customMaterials = (mat as ShaderMaterialWithCustomMaterials).customMaterials;
if (customMaterials) {
const customNames: CustomMaterialName[] = Object.keys(customMaterials) as CustomMaterialName[];
for (const customName of customNames) {
const customMaterial = customMaterials[customName];
if (customMaterial) {
this._updateCommon(customMaterial as ShaderMaterial, pv);
}
}
}
}
}