@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
240 lines (239 loc) • 8.19 kB
JavaScript
;
import { GlType } from "./../../../../../poly/registers/nodes/types/Gl";
import { BackSide, UniformsUtils, ShaderMaterial, ShaderLib } from "three";
import { BaseShaderAssemblerRayMarchingAbstract } from "./_BaseRayMarchingAbstract";
import { ShaderName } from "../../../../utils/shaders/ShaderName";
import { GlConnectionPointType, GlConnectionPoint } from "../../../../utils/io/connections/Gl";
import { ShaderConfig } from "../../configs/ShaderConfig";
import { VariableConfig } from "../../configs/VariableConfig";
import VERTEX from "../../../gl/raymarching/vert.glsl";
import FRAGMENT from "../../../gl/raymarching/fragApplyMaterial.glsl";
import { RAYMARCHING_UNIFORMS } from "../../../gl/raymarching/uniforms";
const INSERT_DEFINE_AFTER_MAP = /* @__PURE__ */ new Map([
// [ShaderName.VERTEX, '#include <common>'],
[ShaderName.FRAGMENT, "// start applyMaterial builder define code"]
]);
const INSERT_BODY_AFTER_MAP = /* @__PURE__ */ new Map([
// [ShaderName.VERTEX, '// start builder body code'],
[ShaderName.FRAGMENT, "// start applyMaterial builder body code"]
]);
const LINES_TO_REMOVE_MAP = /* @__PURE__ */ new Map([[ShaderName.FRAGMENT, []]]);
const SDF_CONTEXT_INPUT_NAME = GlConnectionPointType.SDF_CONTEXT;
const REFLECTION_NOT_ALLOWED = {
START: "// --- REFLECTION NOT ALLOWED - START",
END: "// --- REFLECTION NOT ALLOWED - END"
};
const REFLECTION = {
START: "// --- REFLECTION - START",
END: "// --- REFLECTION - END"
};
const REFRACTION_NOT_ALLOWED = {
START: "// --- REFRACTION NOT ALLOWED - START",
END: "// --- REFRACTION NOT ALLOWED - END"
};
const REFRACTION = {
START: "// --- REFRACTION - START",
END: "// --- REFRACTION - END"
};
export class ShaderAssemblerRayMarchingApplyMaterial extends BaseShaderAssemblerRayMarchingAbstract {
templateShader() {
return {
vertexShader: VERTEX,
fragmentShader: FRAGMENT,
uniforms: UniformsUtils.clone(RAYMARCHING_UNIFORMS)
};
}
createMaterial() {
const templateShader = this.templateShader();
const material = new ShaderMaterial({
vertexShader: templateShader.vertexShader,
fragmentShader: templateShader.fragmentShader,
side: BackSide,
transparent: true,
depthTest: true,
alphaTest: 0.5,
lights: true,
uniforms: {
...UniformsUtils.clone(ShaderLib.standard.uniforms),
...UniformsUtils.clone(templateShader.uniforms)
}
});
return material;
}
// static add_output_inputs(output_child: OutputGlNode) {
// // adding the color here would require to understand how to have the color affect the light in raymarch_light
// // output_child.params.add_param(ParamType.COLOR, 'color', [1, 1, 1], {hidden: true});
// // output_child.params.add_param(ParamType.VECTOR3, 'position', [0, 0, 0], {hidden: true});
// // output_child.params.add_param(ParamType.FLOAT, 'density', 1, {hidden: true});
// }
add_output_inputs(output_child) {
output_child.io.inputs.setNamedInputConnectionPoints([
new GlConnectionPoint(
SDF_CONTEXT_INPUT_NAME,
GlConnectionPointType.SDF_CONTEXT,
"SDFContext(0.0, 0, 0, 0, 0.)"
)
]);
}
static create_globals_node_output_connections() {
return [
new GlConnectionPoint("position", GlConnectionPointType.VEC3),
new GlConnectionPoint("time", GlConnectionPointType.FLOAT),
new GlConnectionPoint("cameraPosition", GlConnectionPointType.VEC3)
];
}
create_globals_node_output_connections() {
return ShaderAssemblerRayMarchingApplyMaterial.create_globals_node_output_connections();
}
insertDefineAfter(shaderName) {
return INSERT_DEFINE_AFTER_MAP.get(shaderName);
}
insertBodyAfter(shaderName) {
return INSERT_BODY_AFTER_MAP.get(shaderName);
}
linesToRemove(shaderName) {
return LINES_TO_REMOVE_MAP.get(shaderName);
}
create_shader_configs() {
return [
new ShaderConfig(ShaderName.VERTEX, [], []),
new ShaderConfig(
ShaderName.FRAGMENT,
[
/*'color', */
"color",
/* lighting */
"diffuse",
"emissive",
/* envMap */
"envMapTint",
"envMapIntensity",
"envMapRoughness",
"envMapFresnel",
"envMapFresnelPower",
/* reflection */
"reflectionTint",
"reflectionDepth",
"reflectivity",
"reflectionBiasMult",
/* refraction */
"refractionTint",
"refractionDepth",
"ior",
"iorOffset",
"transmission",
"absorption",
"refractionBiasMult"
],
[]
)
];
}
static create_variable_configs() {
return [
// new VariableConfig('position', {
// // default_from_attribute: true,
// // prefix: 'vec3 transformed = ',
// }),
// new VariableConfig('cameraPosition', {
// // default_from_attribute: true,
// // prefix: 'vec3 transformed = ',
// }),
// new VariableConfig('color', {
// prefix: 'BUILDER_color.xyz = ',
// }),
new VariableConfig(SDF_CONTEXT_INPUT_NAME, {
prefix: "sdfContext = "
})
];
}
create_variable_configs() {
return ShaderAssemblerRayMarchingApplyMaterial.create_variable_configs();
}
//
//
//
//
//
updateShaders() {
this._shaders_by_name.clear();
this._lines.clear();
for (const shaderName of this.shaderNames()) {
const template = this._template_shader_for_shader_name(shaderName);
if (template) {
this._lines.set(shaderName, template.split("\n"));
}
}
const rootNodes = this.currentGlParentNode().nodesByType(GlType.SDF_MATERIAL);
if (rootNodes.length > 0) {
this.buildCodeFromNodes(rootNodes);
this._buildLines();
}
for (const shaderName of this.shaderNames()) {
const lines = this._lines.get(shaderName);
if (lines) {
this._shaders_by_name.set(shaderName, lines.join("\n"));
}
}
this._removeNestedReflection();
this._removeNestedRefraction();
}
_removeNestedReflection() {
const fragmentShader = this._shaders_by_name.get(ShaderName.FRAGMENT);
if (!fragmentShader) {
return;
}
const lines = fragmentShader.split("\n");
const newLines = [];
let inNotAllowed = false;
let inAllowed = false;
for (const line of lines) {
if (line.includes(REFLECTION_NOT_ALLOWED.START)) {
inNotAllowed = true;
}
if (line.includes(REFLECTION_NOT_ALLOWED.END)) {
inNotAllowed = false;
}
if (line.includes(REFLECTION.START)) {
inAllowed = true;
}
if (line.includes(REFLECTION.END)) {
inAllowed = false;
}
if (!(inNotAllowed && inAllowed) && !line.includes(REFLECTION_NOT_ALLOWED.START) && !line.includes(REFLECTION_NOT_ALLOWED.END) && !line.includes(REFLECTION.START) && !line.includes(REFLECTION.END)) {
newLines.push(line);
}
}
const newFragmentShader = newLines.join("\n");
this._shaders_by_name.set(ShaderName.FRAGMENT, newFragmentShader);
}
_removeNestedRefraction() {
const fragmentShader = this._shaders_by_name.get(ShaderName.FRAGMENT);
if (!fragmentShader) {
return;
}
const lines = fragmentShader.split("\n");
const newLines = [];
let inNotAllowed = false;
let inAllowed = false;
for (const line of lines) {
if (line.includes(REFRACTION_NOT_ALLOWED.START)) {
inNotAllowed = true;
}
if (line.includes(REFRACTION_NOT_ALLOWED.END)) {
inNotAllowed = false;
}
if (line.includes(REFRACTION.START)) {
inAllowed = true;
}
if (line.includes(REFRACTION.END)) {
inAllowed = false;
}
if (!(inNotAllowed && inAllowed) && !line.includes(REFRACTION_NOT_ALLOWED.START) && !line.includes(REFRACTION_NOT_ALLOWED.END) && !line.includes(REFRACTION.START) && !line.includes(REFRACTION.END)) {
newLines.push(line);
}
}
const newFragmentShader = newLines.join("\n");
this._shaders_by_name.set(ShaderName.FRAGMENT, newFragmentShader);
}
}