@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
179 lines (156 loc) • 6.6 kB
text/typescript
import {GlobalsBaseController} from './_Base';
import {GlobalsGlNode} from '../../Globals';
import {BaseGlNodeType} from '../../_Base';
// import {Definition} from '../../Definition/_Module'
// import { VariableConfig } from '../Config/VariableConfig';
import {TextureAllocationsController} from '../utils/TextureAllocationsController';
import {GlobalsGeometryHandler} from './Geometry';
import {ShaderName} from '../../../utils/shaders/ShaderName';
import {UniformGLDefinition, AttributeGLDefinition, VaryingGLDefinition} from '../../utils/GLDefinition';
import {GlConnectionPointType} from '../../../utils/io/connections/Gl';
import {ShadersCollectionController} from '../utils/ShadersCollectionController';
import {TextureVariable} from '../utils/TextureVariable';
import {TypeAssert} from '../../../../poly/Assert';
import {GlobalsBaseControllerType} from './Common';
// import {DefinitionBaseConfig} from '../Config/DefinitionBaseConfig'
// import {UniformConfig} from '../Config/UniformConfig'
// import {AttributeConfig} from '../Config/AttributeConfig'
// import { Attribute } from '../../Attribute';
export enum GlobalsTextureHandlerPurpose {
PARTICLES_SHADER = 'particles_shader',
MATERIAL = 'material',
}
export interface GlobalsTextureHandlerData {
textureName: string;
component: string;
uvName: string;
}
export class GlobalsTextureHandler extends GlobalsBaseController {
private _textureAllocationsController: TextureAllocationsController | undefined;
static PARTICLES_SIM_UV_ATTRIB = 'particlesSimUv';
static UV_VARYING = 'particlesSimUvVarying';
static PARTICLE_SIM_UV = 'particleUv';
private _globalsGeometryHandler: GlobalsGeometryHandler | undefined;
constructor(private _uvName: string, private _purpose: GlobalsTextureHandlerPurpose) {
super();
}
type() {
return GlobalsBaseControllerType.TEXTURE;
}
set_texture_allocations_controller(controller: TextureAllocationsController) {
this._textureAllocationsController = controller;
}
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
) {
if (!this._textureAllocationsController) {
return;
}
const connection_point = globals_node.io.outputs.namedOutputConnectionPointsByName(output_name);
const var_name = globals_node.glVarName(output_name);
const variable = this._textureAllocationsController.variable(output_name);
if (variable && connection_point) {
const gl_type = connection_point.type();
const new_value = this.readAttribute(globals_node, gl_type, output_name, shaders_collection_controller);
const body_line = `${gl_type} ${var_name} = ${new_value}`;
shaders_collection_controller.addBodyLines(globals_node, [body_line]);
} else {
this._globalsGeometryHandler = this._globalsGeometryHandler || new GlobalsGeometryHandler();
this._globalsGeometryHandler.handleGlobalsNode(globals_node, output_name, shaders_collection_controller);
}
}
private _textureVariableUsable(textureVariable: TextureVariable) {
switch (this._purpose) {
case GlobalsTextureHandlerPurpose.PARTICLES_SHADER: {
return true;
}
case GlobalsTextureHandlerPurpose.MATERIAL: {
return !textureVariable.readonly();
}
}
TypeAssert.unreachable(this._purpose);
}
attribTextureData(attribName: string): GlobalsTextureHandlerData | undefined {
if (!this._textureAllocationsController) {
console.warn('no texture allocation controller');
return;
}
const textureVariable = this._textureAllocationsController.variable(attribName);
if (textureVariable && this._textureVariableUsable(textureVariable)) {
const allocation = textureVariable.allocation();
if (allocation) {
const component = textureVariable.component();
const attribTextureName = allocation.textureName();
return {
textureName: attribTextureName,
component: component,
uvName: this._uvName,
};
}
}
}
readAttribute(
node: BaseGlNodeType,
gl_type: GlConnectionPointType,
attribName: string,
shadersCollectionController: ShadersCollectionController
) {
if (!this._textureAllocationsController) {
console.warn('no texture allocation controller');
return;
}
// attrib_name = GlobalsTextureHandler.remap_instance_attribute(attrib_name)
const textureVariable = this._textureAllocationsController.variable(attribName);
if (textureVariable && this._textureVariableUsable(textureVariable)) {
this.addParticlesSimUvAttribute(node, shadersCollectionController);
const textureData = this.attribTextureData(attribName);
if (textureData) {
const {textureName, component, uvName} = textureData;
const texture_definition = new UniformGLDefinition(node, GlConnectionPointType.SAMPLER_2D, textureName);
// definitions_by_shader_name[shader_name].push(texture_definition)
shadersCollectionController.addDefinitions(node, [texture_definition]);
const body_line = `texture2D( ${textureName}, ${uvName} ).${component}`;
return body_line;
}
} else {
return GlobalsGeometryHandler.readAttribute(node, gl_type, attribName, shadersCollectionController);
}
}
addParticlesSimUvAttribute(node: BaseGlNodeType, shaders_collection_controller: ShadersCollectionController) {
// const shader_names = ['vertex', 'fragment'];
// const definitions_by_shader_name:Map<ShaderName, BaseGLDefinition[]> = new Map();
// definitions_by_shader_name.set(ShaderName.VERTEX, [])
// definitions_by_shader_name.set(ShaderName.FRAGMENT, [])
// for (let shader_name of shader_names) {
// definitions_by_shader_name[shader_name] = [];
// }
const particlesSimUvAttribDefinition = new AttributeGLDefinition(
node,
GlConnectionPointType.VEC2,
GlobalsTextureHandler.PARTICLES_SIM_UV_ATTRIB
);
const particlesSimUvVaryingDefinition = new VaryingGLDefinition(
node,
GlConnectionPointType.VEC2,
GlobalsTextureHandler.UV_VARYING
);
shaders_collection_controller.addDefinitions(
node,
[particlesSimUvAttribDefinition, particlesSimUvVaryingDefinition],
ShaderName.VERTEX
);
shaders_collection_controller.addDefinitions(node, [particlesSimUvVaryingDefinition], ShaderName.FRAGMENT);
shaders_collection_controller.addBodyLines(
node,
[`${GlobalsTextureHandler.UV_VARYING} = ${GlobalsTextureHandler.PARTICLES_SIM_UV_ATTRIB}`],
ShaderName.VERTEX
);
}
}