UNPKG

@polygonjs/polygonjs

Version:

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

276 lines (275 loc) 11.5 kB
"use strict"; import { rangeWithEnd } from "../../../core/ArrayUtils"; import { TypedGlNode } from "./_Base"; import { GlConnectionPoint, GlConnectionPointComponentsCountMap, GlConnectionPointType } from "../utils/io/connections/Gl"; import NoiseCommon from "./gl/noise/common.glsl"; import classicnoise2D from "./gl/noise/classicnoise2D.glsl"; import classicnoise3D from "./gl/noise/classicnoise3D.glsl"; import classicnoise4D from "./gl/noise/classicnoise4D.glsl"; import noise2D from "./gl/noise/noise2D.glsl"; import noise3D from "./gl/noise/noise3D.glsl"; import noise4D from "./gl/noise/noise4D.glsl"; export var NoiseName = /* @__PURE__ */ ((NoiseName2) => { NoiseName2["CLASSIC_PERLIN_2D"] = "Classic Perlin 2D"; NoiseName2["CLASSIC_PERLIN_3D"] = "Classic Perlin 3D"; NoiseName2["CLASSIC_PERLIN_4D"] = "Classic Perlin 4D"; NoiseName2["NOISE_2D"] = "noise2D"; NoiseName2["NOISE_3D"] = "noise3D"; NoiseName2["NOISE_4D"] = "noise4D"; return NoiseName2; })(NoiseName || {}); export const NOISE_NAMES = [ "Classic Perlin 2D" /* CLASSIC_PERLIN_2D */, "Classic Perlin 3D" /* CLASSIC_PERLIN_3D */, "Classic Perlin 4D" /* CLASSIC_PERLIN_4D */, "noise2D" /* NOISE_2D */, "noise3D" /* NOISE_3D */, "noise4D" /* NOISE_4D */ ]; const IMPORT_BY_NOISE_NAME = { ["Classic Perlin 2D" /* CLASSIC_PERLIN_2D */]: classicnoise2D, ["Classic Perlin 3D" /* CLASSIC_PERLIN_3D */]: classicnoise3D, ["Classic Perlin 4D" /* CLASSIC_PERLIN_4D */]: classicnoise4D, ["noise2D" /* NOISE_2D */]: noise2D, ["noise3D" /* NOISE_3D */]: noise3D, ["noise4D" /* NOISE_4D */]: noise4D }; const INPUT_TYPES_BY_NOISE_NAME = { ["Classic Perlin 2D" /* CLASSIC_PERLIN_2D */]: GlConnectionPointType.VEC2, ["Classic Perlin 3D" /* CLASSIC_PERLIN_3D */]: GlConnectionPointType.VEC3, ["Classic Perlin 4D" /* CLASSIC_PERLIN_4D */]: GlConnectionPointType.VEC4, ["noise2D" /* NOISE_2D */]: GlConnectionPointType.VEC2, ["noise3D" /* NOISE_3D */]: GlConnectionPointType.VEC3, ["noise4D" /* NOISE_4D */]: GlConnectionPointType.VEC4 }; const OUTPUT_TYPE_BY_NOISE_NAME = { ["Classic Perlin 2D" /* CLASSIC_PERLIN_2D */]: GlConnectionPointType.FLOAT, ["Classic Perlin 3D" /* CLASSIC_PERLIN_3D */]: GlConnectionPointType.FLOAT, ["Classic Perlin 4D" /* CLASSIC_PERLIN_4D */]: GlConnectionPointType.FLOAT, ["noise2D" /* NOISE_2D */]: GlConnectionPointType.FLOAT, ["noise3D" /* NOISE_3D */]: GlConnectionPointType.FLOAT, ["noise4D" /* NOISE_4D */]: GlConnectionPointType.FLOAT }; const METHOD_NAMES_BY_NOISE_NAME = { ["Classic Perlin 2D" /* CLASSIC_PERLIN_2D */]: "cnoise", ["Classic Perlin 3D" /* CLASSIC_PERLIN_3D */]: "cnoise", ["Classic Perlin 4D" /* CLASSIC_PERLIN_4D */]: "cnoise", ["noise2D" /* NOISE_2D */]: "snoise", ["noise3D" /* NOISE_3D */]: "snoise", ["noise4D" /* NOISE_4D */]: "snoise" }; export var NoiseOutputType = /* @__PURE__ */ ((NoiseOutputType2) => { NoiseOutputType2[NoiseOutputType2["NoChange"] = 0] = "NoChange"; NoiseOutputType2[NoiseOutputType2["Float"] = 1] = "Float"; NoiseOutputType2[NoiseOutputType2["Vec2"] = 2] = "Vec2"; NoiseOutputType2[NoiseOutputType2["Vec3"] = 3] = "Vec3"; NoiseOutputType2[NoiseOutputType2["Vec4"] = 4] = "Vec4"; return NoiseOutputType2; })(NoiseOutputType || {}); const OUTPUT_TYPES = [ 0 /* NoChange */, 1 /* Float */, 2 /* Vec2 */, 3 /* Vec3 */, 4 /* Vec4 */ ]; const OUTPUT_TYPE_LABEL = { [0 /* NoChange */]: "Same as noise", [1 /* Float */]: "Float", [2 /* Vec2 */]: "Vec2", [3 /* Vec3 */]: "Vec3", [4 /* Vec4 */]: "Vec4" }; const CONNECTION_TYPE_BY_OUTPUT_TYPE = { [0 /* NoChange */]: GlConnectionPointType.FLOAT, [1 /* Float */]: GlConnectionPointType.FLOAT, [2 /* Vec2 */]: GlConnectionPointType.VEC2, [3 /* Vec3 */]: GlConnectionPointType.VEC3, [4 /* Vec4 */]: GlConnectionPointType.VEC4 }; const ALL_COMPONENTS = ["x", "y", "z", "w"]; const OUTPUT_NAME = "noise"; const default_noise_type = NOISE_NAMES.indexOf("noise3D" /* NOISE_3D */); const default_output_type = 0 /* NoChange */; const DefaultValues = { amp: 1, freq: 1 }; var NoiseGlNodeInputName = /* @__PURE__ */ ((NoiseGlNodeInputName2) => { NoiseGlNodeInputName2["AMP"] = "amp"; NoiseGlNodeInputName2["POSITION"] = "position"; NoiseGlNodeInputName2["FREQ"] = "freq"; NoiseGlNodeInputName2["OFFSET"] = "offset"; return NoiseGlNodeInputName2; })(NoiseGlNodeInputName || {}); import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { ThreeToGl } from "../../../core/ThreeToGl"; import { FunctionGLDefinition } from "./utils/GLDefinition"; import { GlType } from "../../poly/registers/nodes/types/Gl"; class NoiseGlParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.type = ParamConfig.INTEGER(default_noise_type, { menu: { entries: NOISE_NAMES.map((noise_name, i) => { const noise_output_type = OUTPUT_TYPE_BY_NOISE_NAME[noise_name]; const name = `${noise_name} (output: ${noise_output_type})`; return { name, value: i }; }) } }); this.outputType = ParamConfig.INTEGER(default_output_type, { menu: { entries: OUTPUT_TYPES.map((output_type) => { const val = OUTPUT_TYPES[output_type]; const name = OUTPUT_TYPE_LABEL[val]; return { name, value: val }; }) } }); this.octaves = ParamConfig.INTEGER(3, { range: [1, 10], rangeLocked: [true, false] }); this.ampAttenuation = ParamConfig.FLOAT(0.5, { range: [0, 1] }); this.freqIncrease = ParamConfig.FLOAT(2, { range: [0, 10], separatorAfter: true }); } } const ParamsConfig = new NoiseGlParamsConfig(); export class NoiseGlNode extends TypedGlNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; } static type() { return GlType.NOISE; } // public readonly gl_connections_controller: GlConnectionsController = new GlConnectionsController(this); initializeNode() { super.initializeNode(); this.io.connection_points.initializeNode(); this.io.connection_points.spare_params.setInputlessParamNames(["octaves", "ampAttenuation", "freqIncrease"]); this.io.outputs.setNamedOutputConnectionPoints([ new GlConnectionPoint(OUTPUT_NAME, GlConnectionPointType.FLOAT) ]); this.io.connection_points.set_expected_input_types_function(this._expected_input_types.bind(this)); this.io.connection_points.set_expected_output_types_function(this._expected_output_types.bind(this)); this.io.connection_points.set_input_name_function(this._gl_input_name.bind(this)); this.io.connection_points.set_output_name_function(() => OUTPUT_NAME); } setNoiseName(noiseName) { this.p.type.set(NOISE_NAMES.indexOf(noiseName)); } setOutputType(outputType) { this.p.outputType.set(OUTPUT_TYPES.indexOf(outputType)); } _gl_input_name(index) { return [ "amp" /* AMP */, "position" /* POSITION */, "freq" /* FREQ */, "offset" /* OFFSET */ ][index]; } paramDefaultValue(name) { return DefaultValues[name]; } _expected_input_types() { const noiseName = NOISE_NAMES[this.pv.type]; const amplitudeType = this._expected_output_types()[0]; const type = INPUT_TYPES_BY_NOISE_NAME[noiseName]; return [amplitudeType, type, type, type]; } _expected_output_types() { const noise_name = NOISE_NAMES[this.pv.type]; const output_type = OUTPUT_TYPES[this.pv.outputType]; if (output_type == 0 /* NoChange */) { return [INPUT_TYPES_BY_NOISE_NAME[noise_name]]; } else { return [CONNECTION_TYPE_BY_OUTPUT_TYPE[output_type]]; } } setLines(shaders_collection_controller) { const function_declaration_lines = []; const body_lines = []; const noise_name = NOISE_NAMES[this.pv.type]; const noise_function = IMPORT_BY_NOISE_NAME[noise_name]; const noise_output_gl_type = OUTPUT_TYPE_BY_NOISE_NAME[noise_name]; function_declaration_lines.push(new FunctionGLDefinition(this, NoiseCommon)); function_declaration_lines.push(new FunctionGLDefinition(this, noise_function)); function_declaration_lines.push(new FunctionGLDefinition(this, this.fbmFunction())); const output_gl_type = this._expected_output_types()[0]; if (output_gl_type == noise_output_gl_type) { const line = this.singleNoiseLine(); body_lines.push(line); } else { const requested_components_count = GlConnectionPointComponentsCountMap[output_gl_type]; const lines_count_required = requested_components_count; const assembly_args = []; const noise = this.glVarName(OUTPUT_NAME); for (let i = 0; i < lines_count_required; i++) { const component = ALL_COMPONENTS[i]; assembly_args.push(`${noise}${component}`); const input_type = INPUT_TYPES_BY_NOISE_NAME[noise_name]; const offset_gl_type = input_type; const offset_components_count = GlConnectionPointComponentsCountMap[offset_gl_type]; const offset_values = rangeWithEnd(offset_components_count).map((j) => ThreeToGl.float(1e3 * i)).join(", "); const offset2 = `${offset_gl_type}(${offset_values})`; const line = this.singleNoiseLine(component, component, offset2); body_lines.push(line); } const joined_args = assembly_args.join(", "); const assembly_line = `vec${lines_count_required} ${noise} = vec${lines_count_required}(${joined_args})`; body_lines.push(assembly_line); } shaders_collection_controller.addDefinitions(this, function_declaration_lines); shaders_collection_controller.addBodyLines(this, body_lines); } fbmMethodName() { const noiseName = NOISE_NAMES[this.pv.type]; const methodName = METHOD_NAMES_BY_NOISE_NAME[noiseName]; return `fbm_${methodName}${this.path().replace(/\//g, "_")}`; } fbmFunction() { const noiseName = NOISE_NAMES[this.pv.type]; const methodName = METHOD_NAMES_BY_NOISE_NAME[noiseName]; const inputType = INPUT_TYPES_BY_NOISE_NAME[noiseName]; return ` float ${this.fbmMethodName()}(in ${inputType} st) { float value = 0.0; float amplitude = 1.0; for (int i = 0; i < ${ThreeToGl.integer(this.pv.octaves)}; i++) { value += amplitude * ${methodName}(st); st *= ${ThreeToGl.float(this.pv.freqIncrease)}; amplitude *= ${ThreeToGl.float(this.pv.ampAttenuation)}; } return value; } `; } singleNoiseLine(output_name_suffix, component, offset2) { const method_name = this.fbmMethodName(); const amp = ThreeToGl.any(this.variableForInput("amp" /* AMP */)); const position = ThreeToGl.any(this.variableForInput("position" /* POSITION */)); const freq = ThreeToGl.any(this.variableForInput("freq" /* FREQ */)); let offset = ThreeToGl.any(this.variableForInput("offset" /* OFFSET */)); if (offset2) { offset = `(${offset}+${offset2})`; } const args = [`(${position}*${freq})+${offset}`]; const joinedArgs = args.join(", "); const noise = this.glVarName(OUTPUT_NAME); const rightHand = `${amp}*${method_name}(${joinedArgs})`; if (component) { return `float ${noise}${output_name_suffix} = (${rightHand}).${component}`; } else { const namedOutputConnectionPoints = this.io.outputs.namedOutputConnectionPoints(); const outputType = namedOutputConnectionPoints ? namedOutputConnectionPoints[0].type() : GlConnectionPointType.FLOAT; return `${outputType} ${noise} = ${rightHand}`; } } }