@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
103 lines (102 loc) • 3.43 kB
JavaScript
;
import { TypedMatNode } from "../_Base";
import { BaseController } from "./_BaseController";
import { NodeParamsConfig, ParamConfig } from "../../utils/params/ParamsConfig";
import { isBooleanTrue } from "../../../../core/BooleanValue";
import PCSS from "./shadows/pcss/glsl/PCSS.glsl";
import PCSSGetShadow from "./shadows/pcss/glsl/PCSSGetShadow.glsl";
import SHADOW_MAP_PARS_FRAGMENT from "three/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl";
import { ThreeToGl } from "../../../../core/ThreeToGl";
export function PCSSParamConfig(Base) {
return class Mixin extends Base {
constructor() {
super(...arguments);
/** @param if on, the material will blur shadows cast on this object. Note that you should adjust the near parameter of the light shadow to get the result visible */
this.shadowPCSS = ParamConfig.BOOLEAN(0, {
callback: (node) => {
PCSSController.PARAM_CALLBACK_setRecompileRequired(node);
},
separatorBefore: true
});
/** @param shadowPCSSFilterSize PCSS Shadow filter size */
this.shadowPCSSFilterSize = ParamConfig.FLOAT(1, {
visibleIf: { shadowPCSS: 1 },
range: [0, 10],
rangeLocked: [true, false]
});
}
};
}
class PCSSParamsConfig extends PCSSParamConfig(NodeParamsConfig) {
}
function isValidMaterial(material) {
if (!material) {
return false;
}
return true;
}
class PCSSMapMatNode extends TypedMatNode {
async material() {
const container = await this.compute();
return container.material();
}
}
export class PCSSController extends BaseController {
constructor(node) {
super(node);
this.node = node;
}
static filterFragmentShader(node, fragmentShader) {
const PCSSWithDefines = `
#define PCSS_FILTER_SIZE ${ThreeToGl.float(node.pv.shadowPCSSFilterSize)}
${PCSS}
`;
let shadowParsFragmentModified = SHADOW_MAP_PARS_FRAGMENT;
shadowParsFragmentModified = shadowParsFragmentModified.replace(
"#ifdef USE_SHADOWMAP",
`#ifdef USE_SHADOWMAP
${PCSSWithDefines}
`
);
shadowParsFragmentModified = shadowParsFragmentModified.replace(
"#if defined( SHADOWMAP_TYPE_PCF )",
`
${PCSSGetShadow}
#if defined( SHADOWMAP_TYPE_PCF )`
);
fragmentShader = fragmentShader.replace("#include <shadowmap_pars_fragment>", shadowParsFragmentModified);
return fragmentShader;
}
static async update(node) {
const material = await node.material();
if (!isValidMaterial(material)) {
return;
}
node.controllers.PCSS.updateMaterial(material);
}
async update() {
PCSSController.update(this.node);
}
updateMaterial(material) {
var _a, _b;
const matNode = this.node;
if (!matNode.assemblerController) {
return;
}
const callbackName = "PCSS";
if (isBooleanTrue(this.node.pv.shadowPCSS)) {
(_a = matNode.assemblerController()) == null ? void 0 : _a.addFilterFragmentShaderCallback(
callbackName,
(fragmentShader) => PCSSController.filterFragmentShader(this.node, fragmentShader)
);
} else {
(_b = matNode.assemblerController()) == null ? void 0 : _b.removeFilterFragmentShaderCallback(callbackName);
}
}
// static async update(node: PCSSMapMatNode) {
// node.controllers.PCSS.update();
// }
static PARAM_CALLBACK_setRecompileRequired(node) {
node.controllers.PCSS.update();
}
}