@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
276 lines (275 loc) • 11.5 kB
JavaScript
"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}`;
}
}
}