@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
132 lines (131 loc) • 4.46 kB
JavaScript
"use strict";
import { NodeContext } from "../../../../poly/NodeContext";
import {
WebGLRenderer,
WebGLRenderTarget,
LinearFilter,
NearestFilter,
RGBAFormat,
FloatType,
NoToneMapping,
NoColorSpace
} from "three";
import { isBooleanTrue } from "../../../../../core/Type";
import { BaseRaycastController } from "./BaseRaycastController";
export class RaycastGPUController extends BaseRaycastController {
constructor(_node) {
super();
this._node = _node;
this._resolvedMaterial = null;
this._restoreContext = {
scene: {
overrideMaterial: null,
background: null
},
renderer: {
toneMapping: NoToneMapping,
outputColorSpace: NoColorSpace
}
};
// private _mouse: Vector2 = new Vector2();
this._cursorArray = [0, 0];
this._read = new Float32Array(4);
this._paramColor = [0, 0, 0];
this._paramAlpha = 0;
}
updateMouse(eventContext) {
this._cursorHelper.setCursorForGPU(eventContext, this._cursor);
if (isBooleanTrue(this._node.pv.tmouse)) {
this._cursor.toArray(this._cursorArray);
this._node.p.mouse.set(this._cursorArray);
}
}
processEvent(context) {
var _a, _b;
const canvas = (_a = context.viewer) == null ? void 0 : _a.canvas();
const camera = (_b = context.viewer) == null ? void 0 : _b.camera();
if (!(canvas && camera)) {
return;
}
this._renderTarget = this._renderTarget || new WebGLRenderTarget(1, 1, {
minFilter: LinearFilter,
magFilter: NearestFilter,
format: RGBAFormat,
type: FloatType
});
const scene = this._node.scene().threejsScene();
const renderer = this._node.scene().renderersRegister.lastRegisteredRenderer();
if (!renderer) {
return;
}
if (!(renderer instanceof WebGLRenderer)) {
console.log("renderer found is not WebGLRenderer");
return;
}
this._modifySceneAndRenderer(scene, renderer);
camera.setViewOffset(
canvas.offsetWidth,
canvas.offsetHeight,
this._cursor.x * canvas.offsetWidth,
(1 - this._cursor.y) * canvas.offsetHeight,
1,
1
);
renderer.setRenderTarget(this._renderTarget);
renderer.clear();
renderer.render(scene, camera);
renderer.setRenderTarget(null);
camera.clearViewOffset();
this._restoreSceneAndRenderer(scene, renderer);
renderer.readRenderTargetPixels(this._renderTarget, 0, 0, 1, 1, this._read);
this._paramColor[0] = this._read[0];
this._paramColor[1] = this._read[1];
this._paramColor[2] = this._read[2];
this._paramAlpha = this._read[3];
this._node.scene().batchUpdates(() => {
this._node.p.pixelColor.set(this._paramColor);
this._node.p.pixelAlpha.set(this._paramAlpha);
});
if (this._node.pv.pixelColor.r > this._node.pv.hitThreshold) {
this._node.triggerHit(context);
} else {
this._node.triggerMiss(context);
}
}
_modifySceneAndRenderer(scene, renderer) {
this._restoreContext.scene.overrideMaterial = scene.overrideMaterial;
this._restoreContext.scene.background = scene.background;
this._restoreContext.renderer.outputColorSpace = renderer.outputColorSpace;
this._restoreContext.renderer.toneMapping = renderer.toneMapping;
if (isBooleanTrue(this._node.pv.overrideMaterial)) {
if (this._resolvedMaterial == null) {
this._updateMaterial();
}
scene.overrideMaterial = this._resolvedMaterial;
}
scene.background = null;
renderer.toneMapping = NoToneMapping;
renderer.outputColorSpace = NoColorSpace;
}
_restoreSceneAndRenderer(scene, renderer) {
scene.overrideMaterial = this._restoreContext.scene.overrideMaterial;
scene.background = this._restoreContext.scene.background;
renderer.outputColorSpace = this._restoreContext.renderer.outputColorSpace;
renderer.toneMapping = this._restoreContext.renderer.toneMapping;
}
async _updateMaterial() {
const node = this._node.pv.material.nodeWithContext(NodeContext.MAT, this._node.states.error);
if (node) {
if (node.context() == NodeContext.MAT) {
this._resolvedMaterial = await node.material() || null;
} else {
this._node.states.error.set("material is not a mat node");
}
} else {
this._node.states.error.set("no override material found");
}
}
static PARAM_CALLBACK_updateMaterial(node) {
node.gpuController._updateMaterial();
}
}