UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

125 lines (118 loc) 4.63 kB
import {Constructor} from '../../../../types/GlobalTypes'; import {TypedMatNode} from '../_Base'; import {BaseTextureMapController, BooleanParamOptions, NodePathOptions} from './_BaseTextureController'; import {Material, MeshBasicMaterial} from 'three'; import {NodeParamsConfig, ParamConfig} from '../../utils/params/ParamsConfig'; import {MultiplyOperation, MixOperation, AddOperation} from 'three'; import {CopType} from '../../../poly/registers/nodes/types/Cop'; import {MeshLambertMaterial} from 'three'; import {MeshPhongMaterial} from 'three'; import {MaterialTexturesRecord, SetParamsTextureNodesRecord} from './_BaseController'; enum CombineOperation { MULT = 'mult', ADD = 'add', MIX = 'mix', } const COMBINE_OPERATIONS: CombineOperation[] = [CombineOperation.MULT, CombineOperation.ADD, CombineOperation.MIX]; const OperationByName = { [CombineOperation.MULT]: MultiplyOperation, [CombineOperation.ADD]: AddOperation, [CombineOperation.MIX]: MixOperation, }; const NameByOperation = { [MultiplyOperation]: CombineOperation.MULT, [AddOperation]: CombineOperation.ADD, [MixOperation]: CombineOperation.MIX, }; export function EnvMapSimpleParamConfig<TBase extends Constructor>(Base: TBase) { return class Mixin extends Base { /** @param toggle if you want to use an environment map */ useEnvMap = ParamConfig.BOOLEAN(0, { separatorBefore: true, ...BooleanParamOptions(TextureEnvMapSimpleController), }); /** @param specify the environment map COP node. Note that this only works with CubeCamera */ envMap = ParamConfig.NODE_PATH( '', NodePathOptions(TextureEnvMapSimpleController, 'useEnvMap', { types: [CopType.CUBE_MAP, CopType.CUBE_MAP_FROM_SCENE, CopType.CUBE_CAMERA], }) ); /** @param defines how the env map is combined with the color */ combine = ParamConfig.INTEGER(0, { visibleIf: {useEnvMap: 1}, menu: { entries: COMBINE_OPERATIONS.map((name, value) => { return {name, value}; }), }, }); /** @param environment intensity */ reflectivity = ParamConfig.FLOAT(1, {visibleIf: {useEnvMap: 1}}); /** @param refraction ratio */ refractionRatio = ParamConfig.FLOAT(0.98, { range: [-1, 1], rangeLocked: [false, false], visibleIf: {useEnvMap: 1}, }); }; } type TextureEnvMapSimpleCurrentMaterial = MeshBasicMaterial | MeshLambertMaterial | MeshPhongMaterial; function _isValidMaterial(material?: Material): material is TextureEnvMapSimpleCurrentMaterial { if (!material) { return false; } return (material as MeshBasicMaterial).reflectivity != null; } class TextureEnvMapSimpleParamsConfig extends EnvMapSimpleParamConfig(NodeParamsConfig) {} export interface TextureEnvMapSimpleControllers { envMap: TextureEnvMapSimpleController; } abstract class TextureEnvMapSimpleMatNode extends TypedMatNode< TextureEnvMapSimpleCurrentMaterial, TextureEnvMapSimpleParamsConfig > { controllers!: TextureEnvMapSimpleControllers; async material() { const container = await this.compute(); return container.material() as TextureEnvMapSimpleCurrentMaterial | undefined; } } export class TextureEnvMapSimpleController extends BaseTextureMapController { constructor(protected override node: TextureEnvMapSimpleMatNode) { super(node); } override initializeNode() { this.add_hooks(this.node.p.useEnvMap, this.node.p.envMap); } static override async update(node: TextureEnvMapSimpleMatNode) { node.controllers.envMap.update(); } override async update() { const material = await this.node.material(); if (!_isValidMaterial(material)) { return; } await this.updateMaterial(material); } override async updateMaterial(material: TextureEnvMapSimpleCurrentMaterial) { await this._update(material, 'envMap', this.node.p.useEnvMap, this.node.p.envMap); const combine = OperationByName[COMBINE_OPERATIONS[this.node.pv.combine]]; material.combine = combine; material.reflectivity = this.node.pv.reflectivity; material.refractionRatio = this.node.pv.refractionRatio; } override getTextures(material: TextureEnvMapSimpleCurrentMaterial, record: MaterialTexturesRecord) { record.set('envMap', material.envMap); } override setParamsFromMaterial(material: TextureEnvMapSimpleCurrentMaterial, record: SetParamsTextureNodesRecord) { const mapNode = record.get('envMap'); this.node.p.useEnvMap.set(mapNode != null); if (mapNode) { this.node.p.envMap.setNode(mapNode, {relative: true}); } this.node.p.combine.set(COMBINE_OPERATIONS.indexOf(NameByOperation[material.combine])); this.node.p.reflectivity.set(material.reflectivity); this.node.p.refractionRatio.set(material.refractionRatio); } }