@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
301 lines (300 loc) • 10.7 kB
JavaScript
"use strict";
import { BaseGlShaderAssembler } from "../_Base";
import TemplateDefault from "../../templates/cloth/Default.glsl";
import { AttributeGlNode } from "../../../Attribute";
import { TextureAllocationsController } from "../../utils/TextureAllocationsController";
import { ThreeToGl } from "../../../../../../core/ThreeToGl";
import { OutputGlNode } from "../../../Output";
import { GlConnectionPointType, GlConnectionPoint } from "../../../../utils/io/connections/Gl";
import { SubnetOutputGlNode } from "../../../SubnetOutput";
import { GlNodeTraverser } from "../../../../utils/shaders/GlNodeTraverser";
export class ShaderAssemblerCloth extends BaseGlShaderAssembler {
templateShader() {
return void 0;
}
_template_shader_for_shader_name(shader_name) {
return TemplateDefault;
}
// async get_shaders(){
// await this.update_shaders()
// return this._shaders_by_name
// }
compile() {
this.setup_shader_names_and_variables();
this._updateShaders();
}
rootNodesByShaderName(shader_name, rootNodes) {
var _a, _b;
const list = [];
for (const node of rootNodes) {
switch (node.type()) {
case SubnetOutputGlNode.type():
case OutputGlNode.type(): {
list.push(node);
break;
}
case AttributeGlNode.type(): {
const attrib_name = node.attributeName();
const variable = (_a = this._textureAllocationsController) == null ? void 0 : _a.variable(attrib_name);
if (variable && variable.allocation()) {
const allocation_shader_name = (_b = variable.allocation()) == null ? void 0 : _b.shaderName();
if (allocation_shader_name == shader_name) {
list.push(node);
}
}
break;
}
}
}
return list;
}
// override leaf_nodes_by_shader_name(shader_name: ShaderName): BaseGlNodeType[] {
// const list = [];
// for (let node of this._leaf_nodes) {
// switch (node.type()) {
// case GlobalsGlNode.type(): {
// list.push(node);
// break;
// }
// case AttributeGlNode.type(): {
// const attrib_name: string = (node as AttributeGlNode).attributeName();
// const variable = this._textureAllocationsController?.variable(attrib_name);
// if (variable && variable.allocation()) {
// const allocation_shader_name = variable.allocation()?.shaderName();
// if (allocation_shader_name == shader_name) {
// list.push(node);
// }
// }
// break;
// }
// }
// }
// return list;
// }
setup_shader_names_and_variables() {
var _a;
const node_traverser_shallow = new GlNodeTraverser(
this.currentGlParentNode(),
this.shaderNames(),
(root_node, shader_name) => {
return this.inputNamesForShaderName(root_node, shader_name);
}
);
const node_traverser_deep = new GlNodeTraverser(
this.currentGlParentNode(),
this.shaderNames(),
(root_node, shader_name) => {
return this.inputNamesForShaderName(root_node, shader_name);
},
{ traverseChildren: true }
);
this._leaf_nodes = node_traverser_shallow.leavesFromNodes(this._root_nodes);
const leafNodesForTextureAllocations = node_traverser_deep.leavesFromNodes(this._root_nodes);
this._textureAllocationsController = new TextureAllocationsController();
this._textureAllocationsController.allocateConnectionsFromRootNodes(
this._root_nodes,
leafNodesForTextureAllocations
);
if (this.globalsHandler()) {
(_a = this.globalsHandler()) == null ? void 0 : _a.set_texture_allocations_controller(
this._textureAllocationsController
);
}
this._reset_shader_configs();
}
_updateShaders() {
this._shaders_by_name.clear();
this._lines.clear();
for (const shader_name of this.shaderNames()) {
const template = this._template_shader_for_shader_name(shader_name);
this._lines.set(shader_name, template.split("\n"));
}
if (this._root_nodes.length > 0) {
this._resetCodeBuilder();
this.buildCodeFromNodes(this._root_nodes);
this._buildLines();
}
for (const shader_name of this.shaderNames()) {
const lines = this._lines.get(shader_name);
if (lines) {
this._shaders_by_name.set(shader_name, lines.join("\n"));
}
}
}
//
//
// CHILDREN NODES PARAMS
//
//
add_output_inputs(output_child) {
output_child.io.inputs.setNamedInputConnectionPoints([
new GlConnectionPoint("position", GlConnectionPointType.VEC3)
// new GlConnectionPoint('velocity', GlConnectionPointType.VEC3),
]);
}
add_globals_outputs(globals_node) {
globals_node.io.outputs.setNamedOutputConnectionPoints([
new GlConnectionPoint("position", GlConnectionPointType.VEC3),
// new GlConnectionPoint('velocity', GlConnectionPointType.VEC3),
new GlConnectionPoint("time", GlConnectionPointType.FLOAT),
new GlConnectionPoint("timeDelta", GlConnectionPointType.FLOAT)
]);
}
allow_attribute_exports() {
return false;
}
textureAllocationsController() {
return this._textureAllocationsController = this._textureAllocationsController || new TextureAllocationsController();
}
//
//
// CONFIGS
//
//
create_shader_configs() {
var _a;
return ((_a = this._textureAllocationsController) == null ? void 0 : _a.createShaderConfigs()) || [];
}
create_variable_configs() {
return [
// new VariableConfig('position', {
// default: 'vec3( position )',
// prefix: 'vec3 transformed = '
// }),
];
}
shaderNames() {
return this.textureAllocationsController().shaderNames() || [];
}
inputNamesForShaderName(root_node, shader_name) {
return this.textureAllocationsController().inputNamesForShaderName(root_node, shader_name) || [];
}
//
//
// TEMPLATE HOOKS
//
//
insertDefineAfter(shader_name) {
return "// INSERT DEFINE";
}
insertBodyAfter(shader_name) {
return "// INSERT BODY";
}
linesToRemove(shader_name) {
return ["// INSERT DEFINE", "// INSERT BODY"];
}
//
//
// TEMPLATE CODE REPLACEMENT
//
//
add_export_body_line(exportNode, inputName, input, variableName, linesController) {
var _a;
if (input) {
const var_input = exportNode.variableForInput(inputName);
const new_var = ThreeToGl.vector3(var_input);
if (new_var) {
const texture_variable = this.textureAllocationsController().variable(variableName);
const shader_name = linesController.currentShaderName();
if (texture_variable && ((_a = texture_variable.allocation()) == null ? void 0 : _a.shaderName()) == shader_name) {
const component = texture_variable.component();
const line = `${inputName}.${component} = ${new_var}`;
linesController.addBodyLines(exportNode, [line], shader_name);
}
}
}
}
set_node_lines_output(outputNode, linesController) {
const shaderName = linesController.currentShaderName();
const inputNames = this.textureAllocationsController().inputNamesForShaderName(outputNode, shaderName);
if (inputNames) {
for (let inputName of inputNames) {
const input = outputNode.io.inputs.named_input(inputName);
if (input) {
const variable_name = inputName;
this.add_export_body_line(outputNode, inputName, input, variable_name, linesController);
} else {
}
}
}
}
setNodeLinesAttribute(attributeNode, linesController) {
var _a, _b;
if (attributeNode.isImporting()) {
const gl_type = attributeNode.glType();
const attribute_name = attributeNode.attributeName();
const new_value = (_a = this.globalsHandler()) == null ? void 0 : _a.readAttribute(
attributeNode,
gl_type,
attribute_name,
linesController
);
const var_name = attributeNode.glVarName(attributeNode.outputName());
const body_line = `${gl_type} ${var_name} = ${new_value}`;
linesController.addBodyLines(attributeNode, [body_line]);
const texture_variable = this.textureAllocationsController().variable(attribute_name);
const shader_name = linesController.currentShaderName();
if (texture_variable && ((_b = texture_variable.allocation()) == null ? void 0 : _b.shaderName()) == shader_name) {
const variable = this.textureAllocationsController().variable(attribute_name);
if (variable) {
const component = variable.component();
const body_line2 = `gl_FragColor.${component} = ${var_name}`;
linesController.addBodyLines(attributeNode, [body_line2]);
}
}
}
if (attributeNode.isExporting()) {
const input = attributeNode.connected_input_node();
if (input) {
const variable_name = attributeNode.attributeName();
this.add_export_body_line(
attributeNode,
attributeNode.inputName(),
input,
variable_name,
linesController
);
}
}
}
set_node_lines_globals(globals_node, linesController) {
for (let outputName of globals_node.io.outputs.used_output_names()) {
switch (outputName) {
case "time": {
this._handleGlobalsUniform(globals_node, outputName, linesController);
break;
}
case "timeDelta": {
this._handleGlobalsUniform(globals_node, outputName, linesController);
break;
}
case "position": {
this._handleGlobalsPosition(globals_node, outputName, linesController);
break;
}
default: {
this._handleGlobalsPosition(globals_node, outputName, linesController);
break;
}
}
}
}
_handleGlobalsUniform(globalsNode, outputName, linesController) {
const varName = globalsNode.glVarName(outputName);
const bodyLine = `float ${varName} = ${outputName}`;
linesController.addBodyLines(globalsNode, [bodyLine]);
this.setUniformsTimeDependent();
}
_handleGlobalsPosition(globalsNode, outputName, linesController) {
const output_connection_point = globalsNode.io.outputs.namedOutputConnectionPointsByName(outputName);
if (output_connection_point) {
const glType = output_connection_point.type();
const attribRead = "position";
if (attribRead) {
const varName = globalsNode.glVarName(outputName);
const bodyLine = `${glType} ${varName} = ${attribRead}`;
linesController.addBodyLines(globalsNode, [bodyLine]);
}
}
}
}