UNPKG

@polygonjs/polygonjs

Version:

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

178 lines (163 loc) 6.59 kB
import {GlType} from './../../../../../poly/registers/nodes/types/Gl'; import {BackSide, UniformsUtils, ShaderMaterial, ShaderLib, Material} from 'three'; import {BaseShaderAssemblerRayMarchingAbstract} from './_BaseRayMarchingAbstract'; import {ShaderName} from '../../../../utils/shaders/ShaderName'; import {OutputGlNode} from '../../../Output'; import {GlConnectionPointType, GlConnectionPoint} from '../../../../utils/io/connections/Gl'; // import {CoreMaterial} from '../../../../../../core/geometry/Material'; // import {RayMarchingController} from '../../../../mat/utils/RayMarchingController'; import {ShaderConfig} from '../../configs/ShaderConfig'; import {VariableConfig} from '../../configs/VariableConfig'; import VERTEX from '../../../gl/raymarching/vert.glsl'; import FRAGMENT from '../../../gl/raymarching/frag.glsl'; import {RAYMARCHING_UNIFORMS} from '../../../gl/raymarching/uniforms'; import {AssemblerGlControllerNode} from '../../Controller'; import {ShaderAssemblerRayMarchingApplyMaterial} from './RayMarchingApplyMaterial'; const INSERT_BODY_AFTER_MAP: Map<ShaderName, string> = new Map([ // [ShaderName.VERTEX, '// start builder body code'], [ShaderName.FRAGMENT, '// start GetDist builder body code'], ]); const INSERT_DEFINE_AFTER_MAP: Map<ShaderName, string> = new Map([ // [ShaderName.VERTEX, '#include <common>'], [ShaderName.FRAGMENT, '// start raymarching builder define code'], ]); const LINES_TO_REMOVE_MAP: Map<ShaderName, string[]> = new Map([[ShaderName.FRAGMENT, []]]); const SDF_CONTEXT_INPUT_NAME = GlConnectionPointType.SDF_CONTEXT; export class BaseShaderAssemblerRayMarchingRendered extends BaseShaderAssemblerRayMarchingAbstract { constructor(protected override _gl_parent_node: AssemblerGlControllerNode) { super(_gl_parent_node); this._addFilterFragmentShaderCallback('applyMaterialAssembler', (fragmentShader) => this.applyMaterialAssemblerFilterFragmentShader(fragmentShader) ); } override templateShader() { return { vertexShader: VERTEX, fragmentShader: FRAGMENT, uniforms: UniformsUtils.clone(RAYMARCHING_UNIFORMS), }; } override createMaterial() { const templateShader = this.templateShader(); const material = new ShaderMaterial({ vertexShader: templateShader.vertexShader, fragmentShader: templateShader.fragmentShader, side: BackSide, transparent: true, depthTest: true, alphaTest: 0.5, lights: true, uniforms: { ...UniformsUtils.clone(ShaderLib.standard.uniforms), ...UniformsUtils.clone(templateShader.uniforms), }, }); this._gl_parent_node.scene().sceneTraverser.addLightsRayMarchingUniform(material.uniforms); // CoreMaterial.addUserDataRenderHook(material, RayMarchingController.renderHook.bind(RayMarchingController)); this._addCustomMaterials(material); return material; } protected override _raymarchingLightsWorldCoordsDependent() { return true; } override add_output_inputs(output_child: OutputGlNode) { output_child.io.inputs.setNamedInputConnectionPoints([ new GlConnectionPoint( SDF_CONTEXT_INPUT_NAME, GlConnectionPointType.SDF_CONTEXT, 'SDFContext(0.0, 0, 0, 0, 0.)' ), ]); } static override create_globals_node_output_connections() { return [ new GlConnectionPoint('position', GlConnectionPointType.VEC3), new GlConnectionPoint('time', GlConnectionPointType.FLOAT), new GlConnectionPoint('cameraPosition', GlConnectionPointType.VEC3), ]; } override create_globals_node_output_connections() { return BaseShaderAssemblerRayMarchingRendered.create_globals_node_output_connections(); } protected override insertBodyAfter(shaderName: ShaderName): string | undefined { return INSERT_BODY_AFTER_MAP.get(shaderName); } protected override insertDefineAfter(shaderName: ShaderName): string | undefined { return INSERT_DEFINE_AFTER_MAP.get(shaderName); } protected override linesToRemove(shaderName: ShaderName): string[] | undefined { return LINES_TO_REMOVE_MAP.get(shaderName); } override create_shader_configs(): ShaderConfig[] { return [ new ShaderConfig(ShaderName.VERTEX, [], []), new ShaderConfig(ShaderName.FRAGMENT, [/*'color', */ SDF_CONTEXT_INPUT_NAME], [ShaderName.VERTEX]), ]; } static override create_variable_configs() { return [ // new VariableConfig('position', { // // default_from_attribute: true, // // prefix: 'vec3 transformed = ', // }), // new VariableConfig('cameraPosition', { // // default_from_attribute: true, // // prefix: 'vec3 transformed = ', // }), // new VariableConfig('color', { // prefix: 'BUILDER_color.xyz = ', // }), new VariableConfig(SDF_CONTEXT_INPUT_NAME, { prefix: 'sdfContext = ', }), ]; } override create_variable_configs(): VariableConfig[] { return BaseShaderAssemblerRayMarchingRendered.create_variable_configs(); } // // // // // private _applyMaterialAssembler: ShaderAssemblerRayMarchingApplyMaterial = new ShaderAssemblerRayMarchingApplyMaterial(this._gl_parent_node); private _applyMaterialMaterial = new ShaderMaterial(); override setGlParentNode(gl_parent_node: AssemblerGlControllerNode) { super.setGlParentNode(gl_parent_node); this._applyMaterialAssembler.setGlParentNode(gl_parent_node); } override compileMaterial(material: Material) { this._applyMaterialAssembler.updateShaders(); this._applyMaterialAssembler.prepareOnBeforeCompileData(this._applyMaterialMaterial); this.codeBuilder().nodeTraverser().setBlockedInputNames(GlType.SDF_CONTEXT, ['material']); super.compileMaterial(material, { otherFragmentShaderCollectionController: this._applyMaterialAssembler .codeBuilder() .shadersCollectionController(), }); } applyMaterialAssemblerFilterFragmentShader(fragmentShader: string) { const applyMaterial = this._applyMaterialAssembler.onBeforeCompileData()?.fragmentShader; if (applyMaterial) { const elements = applyMaterial.split('// --- applyMaterial SPLIT ---'); // const applyMaterialConstants = elements[0]; const applyMaterialFunctionDefinition = elements[1]; // fragmentShader = fragmentShader.replace( // '// --- applyMaterial constants definition', // applyMaterialConstants // ); fragmentShader = fragmentShader.replace( '// --- applyMaterial function definition', applyMaterialFunctionDefinition ); } if (this._applyMaterialAssembler.uniformsTimeDependent()) { this.setUniformsTimeDependent(); } if (this._applyMaterialAssembler.uniformsResolutionDependent()) { this.setUniformsResolutionDependent(); } return fragmentShader; } }