UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

132 lines (131 loc) 4.46 kB
"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(); } }