@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
242 lines (224 loc) • 9.24 kB
text/typescript
import {GlobalsBaseController} from './_Base';
import {GlobalsGlNode} from '../../Globals';
import {AttributeGlNode} from '../../Attribute';
// import {Definition} from '../../Definition/_Module';
// import {DefinitionBaseConfig} from '../Config/DefinitionBaseConfig';
// import {BaseGlNodeType} from '../../_Base';
import {VaryingGLDefinition, AttributeGLDefinition} from '../../utils/GLDefinition';
import {GlConnectionPointType} from '../../../utils/io/connections/Gl';
// import {TypeAssert} from '../../../../poly/Assert';
import {pushOnArrayAtEntry} from '../../../../../core/MapUtils';
import {ShaderName} from '../../../utils/shaders/ShaderName';
import {BaseGlNodeType} from '../../_Base';
import {ShadersCollectionController} from '../utils/ShadersCollectionController';
import {PolyDictionary} from '../../../../../types/GlobalTypes';
import {GlobalsOutput} from '../assemblers/materials/common/GlobalOutput';
import {GlobalsBaseControllerType} from './Common';
const VARIABLE_CONFIG_DEFAULT_BY_NAME: PolyDictionary<string> = {
position: 'vec3( position )',
};
export class GlobalsGeometryHandler extends GlobalsBaseController {
static PRE_DEFINED_ATTRIBUTES = [
'position',
'color',
'normal',
'uv',
'uv2',
'morphTarget0',
'morphTarget1',
'morphTarget2',
'morphTarget3',
'skinIndex',
'skinWeight',
];
static IF_RULE = {
uv: 'defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )',
};
type() {
return GlobalsBaseControllerType.GEOMETRY;
}
override handleGlobalsNode(
globals_node: GlobalsGlNode,
output_name: string,
shaders_collection_controller: ShadersCollectionController
// definitions_by_shader_name: Map<ShaderName, BaseGLDefinition[]>,
// body_lines_by_shader_name: Map<ShaderName, string[]>,
// body_lines: string[],
// dependencies: ShaderName[],
// shader_name: ShaderName
): void {
const connection_point = globals_node.io.outputs.namedOutputConnectionPointsByName(output_name);
if (!connection_point) {
return;
}
const glType = connection_point.type();
this.handleGlobalVar(globals_node, output_name, glType, shaders_collection_controller);
}
override handleGlobalVar(
globals_node: BaseGlNodeType,
output_name: string,
glType: GlConnectionPointType,
shaders_collection_controller: ShadersCollectionController
): void {
const var_name = globals_node.glVarName(output_name);
const definition = new VaryingGLDefinition(globals_node, glType, var_name);
// push_on_array_at_entry(definitions_by_shader_name, shader_name, definition);
shaders_collection_controller.addDefinitions(globals_node, [definition]);
// definitions_by_shader_name.get(shader_name)!.push(definition);
const assembler = globals_node.materialNode()?.assemblerController()?.assembler;
if (!assembler) {
return;
}
const shader_config = assembler.shader_config(shaders_collection_controller.currentShaderName());
if (!shader_config) {
return;
}
const dependencies = shader_config.dependencies();
const body_lines: string[] = [];
const worldPositionLine = `${var_name} = modelMatrix * vec4( position, 1.0 )`;
const worldNormalLine = `${var_name} = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal )`;
// const ILine = `${var_name} = worldPosition.xyz - cameraPosition`;
switch (output_name) {
case GlobalsOutput.WORLD_POSITION: {
body_lines.push(worldPositionLine);
break;
}
case GlobalsOutput.WORLD_NORMAL: {
body_lines.push(worldNormalLine);
break;
}
// case 'I': {
// body_lines.push(worldPositionLine);
// body_lines.push(ILine);
// break;
// }
default: {
body_lines.push(`${var_name} = ${glType}(${output_name})`);
}
}
for (const dependency of dependencies) {
// push_on_array_at_entry(definitions_by_shader_name, dependency, definition);
// push_on_array_at_entry(body_lines_by_shader_name, dependency, body_line);
shaders_collection_controller.addDefinitions(globals_node, [definition], dependency);
shaders_collection_controller.addBodyLines(globals_node, body_lines, dependency);
}
if (dependencies.length == 0) {
// body_lines.push(body_line);
shaders_collection_controller.addBodyLines(globals_node, body_lines);
}
}
static variable_config_default(variable_name: string): string | undefined {
return VARIABLE_CONFIG_DEFAULT_BY_NAME[variable_name];
}
variable_config_default(variable_name: string): string | undefined {
return GlobalsGeometryHandler.variable_config_default(variable_name);
}
// variable_config_required_definitions(variable_name:string):DefinitionBaseConfig[]{
// return null
// }
readAttribute(
node: BaseGlNodeType,
gl_type: GlConnectionPointType,
attrib_name: string,
shaders_collection_controller: ShadersCollectionController
) {
return GlobalsGeometryHandler.readAttribute(node, gl_type, attrib_name, shaders_collection_controller);
}
static readAttribute(
node: BaseGlNodeType,
gl_type: GlConnectionPointType,
attrib_name: string,
shaders_collection_controller: ShadersCollectionController
): string | undefined {
if (GlobalsGeometryHandler.PRE_DEFINED_ATTRIBUTES.indexOf(attrib_name) < 0) {
shaders_collection_controller.addDefinitions(
node,
[new AttributeGLDefinition(node, gl_type, attrib_name)],
ShaderName.VERTEX
);
} else {
// const if_rule = GlobalsGeometryHandler.IF_RULE[attrib_name]
// if(if_rule){
// const definition = new Definition.Attribute(node, gl_type, attrib_name)
// definition.set_if_rule(if_rule)
// node.addDefinitions([definition])
// }
}
// if (!shader_name) {
// throw 'no shader name';
// }
const shader_name = shaders_collection_controller.currentShaderName();
switch (shader_name) {
case ShaderName.VERTEX: {
return attrib_name;
}
case ShaderName.FRAGMENT: {
// let's assume it can only be an attribute gl node
if (!(node instanceof AttributeGlNode)) {
return;
}
const attribNode = node as AttributeGlNode;
const var_name = attribNode.varyingName(); //'varying_' + node.glVarName(node.outputName());
const varying_definition = new VaryingGLDefinition(node, gl_type, var_name);
const definitions_by_shader_name: Map<ShaderName, VaryingGLDefinition[]> = new Map();
// definitions_by_shader_name.set(ShaderName.VERTEX, [])
definitions_by_shader_name.set(ShaderName.FRAGMENT, []);
// {
// [ShaderName.VERTEX]: [],
// [ShaderName.FRAGMENT]: [],
// };
const body_lines_by_shader_name: Map<ShaderName, string[]> = new Map();
// body_lines_by_shader_name.set(ShaderName.VERTEX, [])
body_lines_by_shader_name.set(ShaderName.FRAGMENT, []);
pushOnArrayAtEntry(definitions_by_shader_name, shader_name, varying_definition);
const set_varying_body_line = `${var_name} = ${gl_type}(${attrib_name})`;
const shader_config = node.materialNode()?.assemblerController()?.assembler.shader_config(shader_name);
if (shader_config) {
const dependencies = shader_config.dependencies();
for (const dependency of dependencies) {
pushOnArrayAtEntry(definitions_by_shader_name, dependency, varying_definition);
pushOnArrayAtEntry(body_lines_by_shader_name, dependency, set_varying_body_line);
}
definitions_by_shader_name.forEach((definitions, shader_name) => {
shaders_collection_controller.addDefinitions(node, definitions, shader_name);
});
body_lines_by_shader_name.forEach((body_lines, shader_name) => {
shaders_collection_controller.addBodyLines(node, body_lines, shader_name);
});
}
return var_name;
}
}
// TypeAssert.unreachable(shader_name);
// const shader_name = node._shader_name // TODO: this is hack
// const varying_definition = new Definition.Varying(node, gl_type, attrib_name)
// const var_name = varying_definition.name()
// definitions_by_shader_name[shader_name].push(varying_definition)
// const shader_config = node.shader_config(shader_name)
// const dependencies = shader_config.dependencies()
// const body_line = `${var_name} = ${gl_type}(${attrib_name})`
// for(let dependency of dependencies){
// definitions_by_shader_name[dependency].push(varying_definition)
// body_lines_by_shader_name[dependency].push(body_line)
// }
// // if(dependencies.length == 0){
// // body_lines.push(body_line)
// node.addBodyLines([body_line])
// // }
// for(let shader_name of Object.keys(definitions_by_shader_name)){
// node.addDefinitions(definitions_by_shader_name[shader_name], shader_name)
// }
// for(let shader_name of Object.keys(body_lines_by_shader_name)){
// node.addBodyLines(body_lines_by_shader_name[shader_name], shader_name)
// }
// node.addBodyLines(body_lines)
}
handle_attribute_node(
node: AttributeGlNode,
gl_type: GlConnectionPointType,
attrib_name: string,
shaders_collection_controller: ShadersCollectionController
) {
return GlobalsGeometryHandler.readAttribute(node, gl_type, attrib_name, shaders_collection_controller);
}
}