Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored the grab pass and scene depth rendering #4244

Merged
merged 3 commits into from May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 17 additions & 12 deletions examples/src/examples/graphics/grab-pass.tsx
Expand Up @@ -26,9 +26,9 @@ void main(void)
'shader.frag': `
precision mediump float;

// use the special texture_grabPass texture, which is a built-in texture. Each time this texture is used
// use the special uSceneColorMap texture, which is a built-in texture. Each time this texture is used
// for rendering, the engine will copy color framebuffer to it which represents already rendered scene
uniform sampler2D texture_grabPass;
uniform sampler2D uSceneColorMap;

// normal map providing offsets
uniform sampler2D uOffsetMap;
Expand Down Expand Up @@ -61,9 +61,9 @@ void main(void)
// get background pixel color with distorted offset
#ifdef GL2
// only webgl2 (and webgl1 extension - not handled here) supports reading specified mipmap
vec3 grabColor = texture2D(texture_grabPass, grabUv + offset, mipmap).rgb;
vec3 grabColor = texture2D(uSceneColorMap, grabUv + offset, mipmap).rgb;
#else
vec3 grabColor = texture2D(texture_grabPass, grabUv + offset).rgb;
vec3 grabColor = texture2D(uSceneColorMap, grabUv + offset).rgb;
#endif

// brighten the refracted texture a little bit
Expand Down Expand Up @@ -101,11 +101,11 @@ void main(void)

app.scene.toneMapping = pc.TONEMAP_ACES;

// Render meshes to immediate layer, which renders after skybox - to include skybox in the refraction.
// Set up front to back sorting for those meshes - so when we get to render the glass,
// object behind it would be rendered already
const immediateLayer = app.scene.layers.getLayerByName("Immediate");
immediateLayer.opaqueSortMode = pc.SORTMODE_BACK2FRONT;
// Depth layer is where the framebuffer is copied to a texture to be used in the following layers.
// Move the depth layer to take place after World and Skydome layers, to capture both of them.
const depthLayer = app.scene.layers.getLayerById(pc.LAYERID_DEPTH);
app.scene.layers.remove(depthLayer);
app.scene.layers.insertOpaque(depthLayer, 2);

// helper function to create a primitive with shape type, position, scale, color
function createPrimitive(primitiveType: string, position: pc.Vec3, scale: pc.Vec3, color: pc.Color) {
Expand All @@ -121,8 +121,7 @@ void main(void)
const primitive = new pc.Entity();
primitive.addComponent('render', {
type: primitiveType,
material: material,
layers: [immediateLayer.id]
material: material
});

// set position and scale and add it to scene
Expand Down Expand Up @@ -154,6 +153,9 @@ void main(void)
camera.setLocalPosition(0, 10, 20);
camera.lookAt(pc.Vec3.ZERO);

// enable the camera to render the scene's color map.
camera.camera.requestSceneColorMap(true);

// create a primitive which uses refraction shader to distort the view behind it
const glass = createPrimitive("box", new pc.Vec3(1, 3, 0), new pc.Vec3(10, 10, 10), new pc.Color(1, 1, 1));
glass.render.castShadows = false;
Expand Down Expand Up @@ -181,7 +183,10 @@ void main(void)
// set roughness map
refractionMaterial.setParameter('uRoughnessMap', assets.roughness.resource);

// refractionMaterial.update();
// transparency
refractionMaterial.blendType = pc.BLEND_NORMAL;
refractionMaterial.update();

app.start();

// update things each frame
Expand Down
8 changes: 4 additions & 4 deletions src/framework/app-base.js
Expand Up @@ -51,7 +51,7 @@ import { script } from './script.js';
import { ApplicationStats } from './stats.js';
import { Entity } from './entity.js';
import { SceneRegistry } from './scene-registry.js';
import { SceneDepth } from './scene-depth.js';
import { SceneGrab } from './scene-grab.js';
import {
FILLMODE_FILL_WINDOW, FILLMODE_KEEP_ASPECT,
RESOLUTION_AUTO, RESOLUTION_FIXED
Expand Down Expand Up @@ -381,8 +381,8 @@ class AppBase extends EventHandler {
id: LAYERID_WORLD
});

this.sceneDepth = new SceneDepth(this);
this.defaultLayerDepth = this.sceneDepth.layer;
this.sceneGrab = new SceneGrab(this);
this.defaultLayerDepth = this.sceneGrab.layer;

this.defaultLayerSkybox = new Layer({
enabled: true,
Expand Down Expand Up @@ -423,7 +423,7 @@ class AppBase extends EventHandler {
layer = list[i];
switch (layer.id) {
case LAYERID_DEPTH:
self.sceneDepth.patch(layer);
self.sceneGrab.patch(layer);
break;
case LAYERID_UI:
layer.passThrough = self.defaultLayerUi.passThrough;
Expand Down
82 changes: 78 additions & 4 deletions src/framework/components/camera/component.js
@@ -1,15 +1,17 @@
import { ASPECT_AUTO, LAYERID_UI } from '../../../scene/constants.js';
import { ASPECT_AUTO, LAYERID_UI, LAYERID_DEPTH } from '../../../scene/constants.js';
import { Camera } from '../../../scene/camera.js';

import { Component } from '../component.js';

import { PostEffectQueue } from './post-effect-queue.js';
import { Debug } from '../../../core/debug.js';

/** @typedef {import('../../../graphics/render-target.js').RenderTarget} RenderTarget */
/** @typedef {import('../../../math/color.js').Color} Color */
/** @typedef {import('../../../math/mat4.js').Mat4} Mat4 */
/** @typedef {import('../../../math/vec3.js').Vec3} Vec3 */
/** @typedef {import('../../../math/vec4.js').Vec4} Vec4 */
/** @typedef {import('../../../scene/layer.js').Layer} Layer */
/** @typedef {import('../../../shape/frustum.js').Frustum} Frustum */
/** @typedef {import('../../../xr/xr-manager.js').XrErrorCallback} XrErrorCallback */
/** @typedef {import('../../entity.js').Entity} Entity */
Expand Down Expand Up @@ -144,6 +146,22 @@ class CameraComponent extends Component {
*/
onPostRender = null;

/**
* A counter of requests of depth map rendering.
*
* @type {number}
mvaligursky marked this conversation as resolved.
Show resolved Hide resolved
* @private
*/
_renderSceneDepthMap = 0;

/**
* A counter of requests of color map rendering.
*
* @type {number}
mvaligursky marked this conversation as resolved.
Show resolved Hide resolved
* @private
*/
_renderSceneColorMap = 0;

/**
* Create a new CameraComponent instance.
*
Expand All @@ -169,7 +187,7 @@ class CameraComponent extends Component {
* Queries the camera component's underlying Camera instance.
*
* @type {Camera}
* @private
* @ignore
*/
get camera() {
return this._camera;
Expand Down Expand Up @@ -234,6 +252,62 @@ class CameraComponent extends Component {
return this._disablePostEffectsLayer;
}

// based on the value, the depth layer's enable counter is incremented or decremented
_enableDepthLayer(value) {
const hasDepthLayer = this.layers.find(layerId => layerId === LAYERID_DEPTH);
if (hasDepthLayer) {

/** @type {Layer} */
const depthLayer = this.system.app.scene.layers.getLayerById(LAYERID_DEPTH);

if (value) {
depthLayer?.incrementCounter();
} else {
depthLayer?.decrementCounter();
}
} else if (value) {
return false;
}

return true;
}

/**
* Request the scene to generate a texture containing the scene color map. Note that this call
* is accummulative, and for each enable request, a disable request need to be called.
*
* @param {boolean} enabled - True to request the generation, false to disable it.
*/
requestSceneColorMap(enabled) {
this._renderSceneColorMap += enabled ? 1 : -1;
const ok = this._enableDepthLayer(enabled);
if (!ok) {
Debug.warnOnce('CameraComponent.requestSceneColorMap was called, but the camera does not have a Depth layer, ignoring.');
}
}

get renderSceneColorMap() {
return this._renderSceneColorMap > 0;
}

/**
* Request the scene to generate a texture containing the scene depth map. Note that this call
* is accummulative, and for each enable request, a disable request need to be called.
*
* @param {boolean} enabled - True to request the generation, false to disable it.
*/
requestSceneDepthMap(enabled) {
this._renderSceneDepthMap += enabled ? 1 : -1;
const ok = this._enableDepthLayer(enabled);
if (!ok) {
Debug.warnOnce('CameraComponent.requestSceneDepthMap was called, but the camera does not have a Depth layer, ignoring.');
}
}

get renderSceneDepthMap() {
return this._renderSceneDepthMap > 0;
}

/**
* Queries the camera's frustum shape.
*
Expand Down Expand Up @@ -503,7 +577,7 @@ class CameraComponent extends Component {
*
* @param {RenderTarget} rt - Render target to which rendering will be performed. Will affect
* camera's aspect ratio, if aspectRatioMode is {@link ASPECT_AUTO}.
* @private
* @ignore
*/
frameBegin(rt) {
if (this.aspectRatioMode === ASPECT_AUTO) {
Expand All @@ -514,7 +588,7 @@ class CameraComponent extends Component {
/**
* End rendering the frame for this camera.
*
* @private
* @ignore
*/
frameEnd() {}

Expand Down
10 changes: 8 additions & 2 deletions src/framework/components/camera/post-effect-queue.js
Expand Up @@ -269,11 +269,17 @@ class PostEffectQueue {

_requestDepthMap() {
if (!depthLayer) depthLayer = this.app.scene.layers.getLayerById(LAYERID_DEPTH);
if (depthLayer) depthLayer.incrementCounter();
if (depthLayer) {
depthLayer.incrementCounter();
this.camera.requestSceneDepthMap(true);
}
}

_releaseDepthMap() {
if (depthLayer) depthLayer.decrementCounter();
if (depthLayer) {
depthLayer.decrementCounter();
this.camera.requestSceneDepthMap(false);
}
}

/**
Expand Down