@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
178 lines (163 loc) • 6.59 kB
text/typescript
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;
}
}