@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
127 lines (126 loc) • 4.41 kB
JavaScript
"use strict";
import {
WebGLRenderTarget,
NearestFilter,
RGBAFormat,
FloatType,
WebGLRenderer,
Scene,
NoToneMapping,
NoColorSpace,
DepthTexture,
UnsignedInt248Type
} from "three";
import { coreGetDefaultCamera } from "./CoreGetDefautCamera";
import { setupDepthReadScene, updateDepthSetup } from "./DepthRead";
export function coreCursorToUv(cursor, target) {
target.x = 0.5 * (cursor.x + 1);
target.y = 0.5 * (1 - cursor.y);
}
function _createDepthTexture() {
const texture = new DepthTexture(1, 1);
texture.type = UnsignedInt248Type;
return texture;
}
export class RenderPixelController {
constructor() {
// Note for this to work on iOS:
// The materials used for picking should have their transparency OFF.
// This could potentially be done automatically by traversing the scene first.
this._colorWriteRenderTarget = new WebGLRenderTarget(1, 1, {
minFilter: NearestFilter,
magFilter: NearestFilter,
format: RGBAFormat,
type: FloatType,
colorSpace: NoColorSpace,
depthTexture: _createDepthTexture()
});
this._depthReadRenderTarget = new WebGLRenderTarget(1, 1, {
minFilter: NearestFilter,
magFilter: NearestFilter,
format: RGBAFormat,
type: FloatType,
colorSpace: NoColorSpace
});
this._renderScene = new Scene();
this._depthReadSetup = setupDepthReadScene();
this._restoreContext = {
object: {
parent: null
},
// scene: {
// overrideMaterial: null,
// },
renderer: {
toneMapping: NoToneMapping,
outputColorSpace: NoColorSpace
}
};
this._read = new Float32Array(4);
}
renderColor(scene, object3D, material, camera, backgroundColor, uv, target) {
this._doRender(scene, object3D, camera, material, backgroundColor, uv, target, false);
return target;
}
renderDepth(scene, object3D, camera, backgroundColor, uv, target) {
this._doRender(scene, object3D, camera, null, backgroundColor, uv, target, true);
return target;
}
_doRender(scene, object3D, camera, material, backgroundColor, uv, target, renderDepth) {
const renderer = scene.renderersRegister.lastRegisteredRenderer();
if (!renderer) {
return target;
}
if (!(renderer instanceof WebGLRenderer)) {
console.log("renderPixel: renderer found is not WebGLRenderer");
return target;
}
if (camera == null) {
camera = coreGetDefaultCamera(scene);
}
this._prepare(object3D, material, backgroundColor, renderer);
this._render(uv, camera, renderer, target, renderDepth);
this._restore(object3D, renderer);
return target;
}
_prepare(object3D, material, backgroundColor, renderer) {
this._restoreContext.renderer.outputColorSpace = renderer.outputColorSpace;
this._restoreContext.renderer.toneMapping = renderer.toneMapping;
this._restoreContext.object.parent = object3D.parent;
this._renderScene.background = backgroundColor;
this._renderScene.overrideMaterial = material || null;
this._renderScene.attach(object3D);
renderer.toneMapping = NoToneMapping;
renderer.outputColorSpace = NoColorSpace;
}
_render(uv, camera, renderer, target, readDepth) {
camera.setViewOffset(
renderer.domElement.width,
renderer.domElement.height,
uv.x * renderer.domElement.width,
uv.y * renderer.domElement.height,
1,
1
);
renderer.setRenderTarget(this._colorWriteRenderTarget);
renderer.clear();
renderer.render(this._renderScene, camera);
if (readDepth) {
updateDepthSetup(this._depthReadSetup, camera, this._colorWriteRenderTarget);
renderer.setRenderTarget(this._depthReadRenderTarget);
renderer.render(this._depthReadSetup.scene, this._depthReadSetup.camera);
renderer.readRenderTargetPixels(this._depthReadRenderTarget, 0, 0, 1, 1, this._read);
} else {
renderer.readRenderTargetPixels(this._colorWriteRenderTarget, 0, 0, 1, 1, this._read);
}
renderer.setRenderTarget(null);
camera.clearViewOffset();
target.fromArray(this._read);
}
_restore(object3D, renderer) {
var _a;
renderer.outputColorSpace = this._restoreContext.renderer.outputColorSpace;
renderer.toneMapping = this._restoreContext.renderer.toneMapping;
(_a = this._restoreContext.object.parent) == null ? void 0 : _a.attach(object3D);
}
}