UNPKG

polygonjs-engine

Version:

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

167 lines (150 loc) 6.41 kB
import {UniformsUtils} from 'three/src/renderers/shaders/UniformsUtils'; import {ShaderMaterial} from 'three/src/materials/ShaderMaterial'; import {BaseShaderAssemblerVolume} from './_BaseVolume'; import {ShaderName} from '../../../../utils/shaders/ShaderName'; import {OutputGlNode} from '../../../Output'; import {GlConnectionPointType, GlConnectionPoint} from '../../../../utils/io/connections/Gl'; import {FrontSide} from 'three/src/constants'; import {CoreMaterial} from '../../../../../../core/geometry/Material'; import {VolumeController} from '../../../../mat/utils/VolumeController'; import {ShaderConfig} from '../../configs/ShaderConfig'; import {VariableConfig} from '../../configs/VariableConfig'; import {GlobalsGlNode} from '../../../Globals'; import {ShadersCollectionController} from '../../utils/ShadersCollectionController'; import {BaseGLDefinition, UniformGLDefinition} from '../../../utils/GLDefinition'; import {MapUtils} from '../../../../../../core/MapUtils'; import VERTEX from '../../../gl/volume/vert.glsl'; import FRAGMENT from '../../../gl/volume/frag.glsl'; import {VOLUME_UNIFORMS} from '../../../gl/volume/uniforms'; const INSERT_BODY_AFTER_MAP: Map<ShaderName, string> = new Map([ [ShaderName.VERTEX, '// start builder body code'], [ShaderName.FRAGMENT, '// start builder body code'], ]); const LINES_TO_REMOVE_MAP: Map<ShaderName, string[]> = new Map([[ShaderName.FRAGMENT, []]]); export class ShaderAssemblerVolume extends BaseShaderAssemblerVolume { get _template_shader() { return { vertexShader: VERTEX, fragmentShader: FRAGMENT, uniforms: UniformsUtils.clone(VOLUME_UNIFORMS), }; } create_material() { const template_shader = this._template_shader; const material = new ShaderMaterial({ vertexShader: template_shader.vertexShader, fragmentShader: template_shader.fragmentShader, side: FrontSide, transparent: true, depthTest: true, uniforms: UniformsUtils.clone(template_shader.uniforms), }); CoreMaterial.add_user_data_render_hook(material, VolumeController.render_hook.bind(VolumeController)); this._add_custom_materials(material); return material; } // static add_output_inputs(output_child: OutputGlNode) { // // adding the color here would require to understand how to have the color affect the light in raymarch_light // // output_child.params.add_param(ParamType.COLOR, 'color', [1, 1, 1], {hidden: true}); // // output_child.params.add_param(ParamType.VECTOR3, 'position', [0, 0, 0], {hidden: true}); // // output_child.params.add_param(ParamType.FLOAT, 'density', 1, {hidden: true}); // } add_output_inputs(output_child: OutputGlNode) { output_child.io.inputs.setNamedInputConnectionPoints([ new GlConnectionPoint('density', GlConnectionPointType.FLOAT, 1), ]); } static create_globals_node_output_connections() { return [ new GlConnectionPoint('position', GlConnectionPointType.VEC3), new GlConnectionPoint('pos_normalized', GlConnectionPointType.VEC3), new GlConnectionPoint('time', GlConnectionPointType.FLOAT), ]; } create_globals_node_output_connections() { return ShaderAssemblerVolume.create_globals_node_output_connections(); } protected insert_body_after(shader_name: ShaderName): string | undefined { return INSERT_BODY_AFTER_MAP.get(shader_name); } protected lines_to_remove(shader_name: ShaderName): string[] | undefined { return LINES_TO_REMOVE_MAP.get(shader_name); } create_shader_configs(): ShaderConfig[] { return [ new ShaderConfig(ShaderName.VERTEX, [], []), new ShaderConfig(ShaderName.FRAGMENT, [/*'color', */ 'density'], [ShaderName.VERTEX]), ]; } static create_variable_configs() { return [ new VariableConfig('position', { // default_from_attribute: true, // prefix: 'vec3 transformed = ', }), // new VariableConfig('color', { // prefix: 'BUILDER_color.xyz = ', // }), new VariableConfig('density', { prefix: 'density *= ', }), ]; } create_variable_configs(): VariableConfig[] { return ShaderAssemblerVolume.create_variable_configs(); } set_node_lines_globals(globals_node: GlobalsGlNode, shaders_collection_controller: ShadersCollectionController) { const body_lines = []; const shader_name = shaders_collection_controller.current_shader_name; const shader_config = this.shader_config(shader_name); if (!shader_config) { return; } const dependencies = shader_config.dependencies(); const definitions_by_shader_name: Map<ShaderName, BaseGLDefinition[]> = new Map(); const body_lines_by_shader_name: Map<ShaderName, string[]> = new Map(); let definition; let body_line; for (let output_name of globals_node.io.outputs.used_output_names()) { const var_name = globals_node.gl_var_name(output_name); const globals_shader_name = shaders_collection_controller.current_shader_name; switch (output_name) { case 'time': definition = new UniformGLDefinition(globals_node, GlConnectionPointType.FLOAT, output_name); if (globals_shader_name) { MapUtils.push_on_array_at_entry(definitions_by_shader_name, globals_shader_name, definition); } body_line = `float ${var_name} = ${output_name}`; for (let dependency of dependencies) { MapUtils.push_on_array_at_entry(definitions_by_shader_name, dependency, definition); MapUtils.push_on_array_at_entry(body_lines_by_shader_name, dependency, body_line); } body_lines.push(body_line); this.set_uniforms_time_dependent(); break; // case 'gl_FragCoord': // this.handle_gl_FragCoord(body_lines, shader_name, var_name); // break; case 'position': if (shader_name == ShaderName.FRAGMENT) { body_lines.push(`vec3 ${var_name} = position_for_step`); } break; case 'pos_normalized': if (shader_name == ShaderName.FRAGMENT) { body_lines.push( `vec3 ${var_name} = (position_for_step - u_BoundingBoxMax) / (u_BoundingBoxMax - u_BoundingBoxMin)` ); } break; } } definitions_by_shader_name.forEach((definitions, shader_name) => { shaders_collection_controller.add_definitions(globals_node, definitions, shader_name); }); body_lines_by_shader_name.forEach((body_lines, shader_name) => { shaders_collection_controller.add_body_lines(globals_node, body_lines, shader_name); }); shaders_collection_controller.add_body_lines(globals_node, body_lines); } }