@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
83 lines (66 loc) • 2.9 kB
text/typescript
import type { EffectComposer } from "postprocessing";
import { Camera, Mesh, Object3D, Texture, WebGLRenderer, WebGLRenderTarget } from "three";
import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
import { findResourceUsers } from "./engine_assetdatabase.js";
const _prevVisible = Symbol("previous-visibility");
/**
* A RenderTexture can be used to render a scene to a texture automatically by assigning it to the `Camera` component's `targetTexture` property.
* You can then assign the `RenderTexture.texture` to materials to be displayed
* @example Create a new RenderTexture and assign it to a camera and material
* ```typescript
* // create new RenderTexture with a resolution
* const rt = new RenderTexture(256, 256);
* // assign to a camera
* myCameraComponent.targetTexture = rt;
* // assign to a material
* myMaterial.map = rt.texture;
* ```
*/
export class RenderTexture extends WebGLRenderTarget {
/**
* Render the scene to the texture
* @param scene The scene to render
* @param camera The camera to render from
* @param renderer The renderer or effectcomposer to use
*/
render(scene: Object3D, camera: Camera, renderer: WebGLRenderer | EffectComposer | ThreeEffectComposer) {
const composer = renderer as (EffectComposer | ThreeEffectComposer);
if ("addPass" in composer) {
if (!this["_unsupported_effectcomposer_warning"]) {
console.warn("RenderTexture.render() does not yet support EffectComposer");
this["_unsupported_effectcomposer_warning"] = true;
}
}
else if (renderer instanceof WebGLRenderer) {
this.onBeforeRender();
const prev = renderer.getRenderTarget();
const xr = renderer.xr.enabled;
renderer.xr.enabled = false;
renderer.setRenderTarget(this);
renderer.clear(true, true, true);
renderer.render(scene, camera);
renderer.setRenderTarget(prev);
renderer.xr.enabled = xr;
this.onAfterRender();
}
}
private static _userSet: Set<object> = new Set();
private onBeforeRender() {
RenderTexture._userSet.clear();
const users = findResourceUsers(this.texture, true, null, RenderTexture._userSet);
for (const user of users) {
if (user instanceof Mesh) {
user[_prevVisible] = user.visible;
user.visible = false;
}
}
}
private onAfterRender() {
for (const user of RenderTexture._userSet) {
if (user instanceof Mesh) {
user.visible = user[_prevVisible];
}
}
RenderTexture._userSet.clear();
}
}