@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
124 lines (110 loc) • 4.99 kB
text/typescript
/**
* computes displacement based on a texture.
*
* @remarks
*
* Normals are computed based on the UV.
*
*
*
*/
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {ShadersCollectionController} from './code/utils/ShadersCollectionController';
import {ThreeToGl} from '../../../core/ThreeToGl';
import {GlConnectionPoint, GlConnectionPointType} from '../utils/io/connections/Gl';
import {GlType} from '../../poly/registers/nodes/types/Gl';
import {TypedGlNode} from './_Base';
import {ParamConfigsController} from '../utils/code/controllers/ParamConfigsController';
import {GlParamConfig} from './code/utils/GLParamConfig';
import {ParamType} from '../../poly/ParamType';
import {UNIFORM_TEXTURE_PREFIX} from '../../../core/material/uniform';
import {BaseGLDefinition, FunctionGLDefinition, UniformGLDefinition} from './utils/GLDefinition';
import TEXTURE_DISPLACEMENT_4PTS from './gl/textureDisplacement_4pts.glsl';
import TEXTURE_DISPLACEMENT_8PTS from './gl/textureDisplacement_8pts.glsl';
import TEXTURE_DISPLACEMENT_RESULT from './gl/textureDisplacementResult.glsl';
export enum DisplacementTextureOutput {
P = 'P',
N = 'N',
}
const COMPONENTS = ['x', 'y', 'z', 'w'];
class TextureDisplacementGlParamsConfig extends NodeParamsConfig {
paramName = ParamConfig.STRING('');
computeAllNeighbours = ParamConfig.BOOLEAN(0);
position = ParamConfig.VECTOR3([0, 0, 0]);
normal = ParamConfig.VECTOR3([0, 0, 0]);
uv = ParamConfig.VECTOR2([0, 0]);
amount = ParamConfig.FLOAT(1, {
range: [-1, 1],
rangeLocked: [false, false],
});
textureSize = ParamConfig.VECTOR2([512, 512]);
tangentsPosOffset = ParamConfig.VECTOR2([0.01, 0.01]);
textureComponent = ParamConfig.INTEGER(0, {
range: [0, 3],
rangeLocked: [true, true],
});
}
const ParamsConfig = new TextureDisplacementGlParamsConfig();
export class TextureDisplacementGlNode extends TypedGlNode<TextureDisplacementGlParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return GlType.TEXTURE_DISPLACEMENT;
}
override initializeNode() {
this.addPostDirtyHook('_setMatToRecompile', this._setMatToRecompile.bind(this));
this.lifecycle.onAfterAdded(this._setMatToRecompile.bind(this));
this.lifecycle.onBeforeDeleted(this._setMatToRecompile.bind(this));
this.io.outputs.setNamedOutputConnectionPoints([
new GlConnectionPoint(DisplacementTextureOutput.P, GlConnectionPointType.VEC3),
new GlConnectionPoint(DisplacementTextureOutput.N, GlConnectionPointType.VEC3),
]);
this.io.connection_points.spare_params.setInputlessParamNames(['computeAllNeighbours', 'textureComponent']);
}
override setLines(linesController: ShadersCollectionController) {
const map = this.uniformName();
const uv = ThreeToGl.vector2(this.variableForInputParam(this.p.uv));
const textureSize = ThreeToGl.vector2(this.variableForInputParam(this.p.textureSize));
const amount = ThreeToGl.float(this.variableForInputParam(this.p.amount));
const position = ThreeToGl.vector3(this.variableForInputParam(this.p.position));
const normal = ThreeToGl.vector3(this.variableForInputParam(this.p.normal));
const tangentsPosOffset = ThreeToGl.vector3(this.variableForInputParam(this.p.tangentsPosOffset));
const component = COMPONENTS[this.pv.textureComponent];
const template = this.pv.computeAllNeighbours ? TEXTURE_DISPLACEMENT_8PTS : TEXTURE_DISPLACEMENT_4PTS;
const textureDisplacementFunctionDeclaration = template.replace(/__COMPONENT__/g, component);
const textureDisplacementFunctionName = `textureDisplacement__COMPONENT__`.replace(/__COMPONENT__/g, component);
const out = this.glVarName('out');
const outPosition = this.glVarName(DisplacementTextureOutput.P);
const outNormal = this.glVarName(DisplacementTextureOutput.N);
const definitions: BaseGLDefinition[] = [
new UniformGLDefinition(this, GlConnectionPointType.SAMPLER_2D, map),
new FunctionGLDefinition(this, TEXTURE_DISPLACEMENT_RESULT),
new FunctionGLDefinition(this, textureDisplacementFunctionDeclaration),
];
const args = [map, uv, textureSize, amount, position, normal, tangentsPosOffset];
const functionCall = `${textureDisplacementFunctionName}(${args.join(', ')})`;
const bodyLines: string[] = [
`TextureDisplacementResult ${out} = ${functionCall}`,
`vec3 ${outPosition} = ${out}.position`,
`vec3 ${outNormal} = ${out}.normal`,
];
linesController.addDefinitions(this, definitions);
linesController.addBodyLines(this, bodyLines);
}
override paramsGenerating() {
return true;
}
override setParamConfigs() {
this._param_configs_controller = this._param_configs_controller || new ParamConfigsController();
this._param_configs_controller.reset();
const param_config = new GlParamConfig(
ParamType.NODE_PATH,
this.pv.paramName,
'', //this.pv.defaultValue,
this.uniformName()
);
this._param_configs_controller.push(param_config);
}
uniformName() {
return `${UNIFORM_TEXTURE_PREFIX}${this.pv.paramName}`;
}
}