|
@@ -1,5 +1,14 @@
|
|
|
import { DoubleSide } from '../../constants.js';
|
|
import { DoubleSide } from '../../constants.js';
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Default sorting function for opaque render items.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @function
|
|
|
|
|
+ * @param {Object} a - The first render item.
|
|
|
|
|
+ * @param {Object} b - The second render item.
|
|
|
|
|
+ * @return {Number} A numeric value which defines the sort order.
|
|
|
|
|
+ */
|
|
|
function painterSortStable( a, b ) {
|
|
function painterSortStable( a, b ) {
|
|
|
|
|
|
|
|
if ( a.groupOrder !== b.groupOrder ) {
|
|
if ( a.groupOrder !== b.groupOrder ) {
|
|
@@ -26,6 +35,15 @@ function painterSortStable( a, b ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Default sorting function for transparent render items.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @function
|
|
|
|
|
+ * @param {Object} a - The first render item.
|
|
|
|
|
+ * @param {Object} b - The second render item.
|
|
|
|
|
+ * @return {Number} A numeric value which defines the sort order.
|
|
|
|
|
+ */
|
|
|
function reversePainterSortStable( a, b ) {
|
|
function reversePainterSortStable( a, b ) {
|
|
|
|
|
|
|
|
if ( a.groupOrder !== b.groupOrder ) {
|
|
if ( a.groupOrder !== b.groupOrder ) {
|
|
@@ -48,6 +66,14 @@ function reversePainterSortStable( a, b ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Returns `true` if the given transparent material requires a double pass.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @function
|
|
|
|
|
+ * @param {Material} material - The transparent material.
|
|
|
|
|
+ * @return {Boolean} Whether the given material requires a double pass or not.
|
|
|
|
|
+ */
|
|
|
function needsDoublePass( material ) {
|
|
function needsDoublePass( material ) {
|
|
|
|
|
|
|
|
const hasTransmission = material.transmission > 0 || material.transmissionNode;
|
|
const hasTransmission = material.transmission > 0 || material.transmissionNode;
|
|
@@ -56,28 +82,120 @@ function needsDoublePass( material ) {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * When the renderer analyzes the scene at the beginning of a render call,
|
|
|
|
|
+ * it stores 3D object for further processing in render lists. Depending on the
|
|
|
|
|
+ * properties of a 3D objects (like their transformation or material state), the
|
|
|
|
|
+ * objects are maintained in ordered lists for the actual rendering.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Render lists are unique per scene and camera combination.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @augments Pipeline
|
|
|
|
|
+ */
|
|
|
class RenderList {
|
|
class RenderList {
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Constructs a render list.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Lighting} lighting - The lighting management component.
|
|
|
|
|
+ * @param {Scene} scene - The scene.
|
|
|
|
|
+ * @param {Camera} camera - The camera the scene is rendered with.
|
|
|
|
|
+ */
|
|
|
constructor( lighting, scene, camera ) {
|
|
constructor( lighting, scene, camera ) {
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 3D objects are transformed into render items and stored in this array.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Object>}
|
|
|
|
|
+ */
|
|
|
this.renderItems = [];
|
|
this.renderItems = [];
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The current render items index.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Number}
|
|
|
|
|
+ * @default 0
|
|
|
|
|
+ */
|
|
|
this.renderItemsIndex = 0;
|
|
this.renderItemsIndex = 0;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A list with opaque render items.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Object>}
|
|
|
|
|
+ */
|
|
|
this.opaque = [];
|
|
this.opaque = [];
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A list with transparent render items which require
|
|
|
|
|
+ * double pass rendering (e.g. transmissive objects).
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Object>}
|
|
|
|
|
+ */
|
|
|
this.transparentDoublePass = [];
|
|
this.transparentDoublePass = [];
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A list with transparent render items.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Object>}
|
|
|
|
|
+ */
|
|
|
this.transparent = [];
|
|
this.transparent = [];
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A list with transparent render bundle data.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Object>}
|
|
|
|
|
+ */
|
|
|
this.bundles = [];
|
|
this.bundles = [];
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The render list's lights node. This node is later
|
|
|
|
|
+ * relevant for the actual analytical light nodes which
|
|
|
|
|
+ * compute the scene's lighting in the shader.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {LightsNode}
|
|
|
|
|
+ */
|
|
|
this.lightsNode = lighting.getNode( scene, camera );
|
|
this.lightsNode = lighting.getNode( scene, camera );
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The scene's lights stored in an array. This array
|
|
|
|
|
+ * is used to setup the lights node.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Array<Light>}
|
|
|
|
|
+ */
|
|
|
this.lightsArray = [];
|
|
this.lightsArray = [];
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The scene.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Scene}
|
|
|
|
|
+ */
|
|
|
this.scene = scene;
|
|
this.scene = scene;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * The camera the scene is rendered with.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Camera}
|
|
|
|
|
+ */
|
|
|
this.camera = camera;
|
|
this.camera = camera;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * How many objects perform occlusion query tests.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @type {Number}
|
|
|
|
|
+ * @default 0
|
|
|
|
|
+ */
|
|
|
this.occlusionQueryCount = 0;
|
|
this.occlusionQueryCount = 0;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * This method is called right at the beginning of a render call
|
|
|
|
|
+ * before the scene is analyzed. It prepares the internal data
|
|
|
|
|
+ * structures for the upcoming render lists generation.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return {RenderList} A reference to this render list.
|
|
|
|
|
+ */
|
|
|
begin() {
|
|
begin() {
|
|
|
|
|
|
|
|
this.renderItemsIndex = 0;
|
|
this.renderItemsIndex = 0;
|
|
@@ -95,6 +213,22 @@ class RenderList {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Returns a render item for the giving render item state. The state is defined
|
|
|
|
|
+ * by a series of object-related parameters.
|
|
|
|
|
+ *
|
|
|
|
|
+ * The method avoids object creation by holding render items and reusing them in
|
|
|
|
|
+ * subsequent render calls (just with different property values).
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Object3D} object - The 3D object.
|
|
|
|
|
+ * @param {BufferGeometry} geometry - The 3D object's geometry.
|
|
|
|
|
+ * @param {Material} material - The 3D object's material.
|
|
|
|
|
+ * @param {Number} groupOrder - The current group order.
|
|
|
|
|
+ * @param {Number} z - Th 3D object's depth value (z value in clip space).
|
|
|
|
|
+ * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
|
|
|
|
|
+ * @param {ClippingContext} clippingContext - The current clipping context.
|
|
|
|
|
+ * @return {Object} The render item.
|
|
|
|
|
+ */
|
|
|
getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
|
|
|
|
|
|
let renderItem = this.renderItems[ this.renderItemsIndex ];
|
|
let renderItem = this.renderItems[ this.renderItemsIndex ];
|
|
@@ -135,6 +269,18 @@ class RenderList {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Pushes the given object as a render item to the internal render lists.
|
|
|
|
|
+ * The selected lists depend on the object properties.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Object3D} object - The 3D object.
|
|
|
|
|
+ * @param {BufferGeometry} geometry - The 3D object's geometry.
|
|
|
|
|
+ * @param {Material} material - The 3D object's material.
|
|
|
|
|
+ * @param {Number} groupOrder - The current group order.
|
|
|
|
|
+ * @param {Number} z - Th 3D object's depth value (z value in clip space).
|
|
|
|
|
+ * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
|
|
|
|
|
+ * @param {ClippingContext} clippingContext - The current clipping context.
|
|
|
|
|
+ */
|
|
|
push( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
push( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
|
|
|
|
|
|
const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext );
|
|
const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext );
|
|
@@ -155,6 +301,18 @@ class RenderList {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Inserts the given object as a render item at the start of the internal render lists.
|
|
|
|
|
+ * The selected lists depend on the object properties.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Object3D} object - The 3D object.
|
|
|
|
|
+ * @param {BufferGeometry} geometry - The 3D object's geometry.
|
|
|
|
|
+ * @param {Material} material - The 3D object's material.
|
|
|
|
|
+ * @param {Number} groupOrder - The current group order.
|
|
|
|
|
+ * @param {Number} z - Th 3D object's depth value (z value in clip space).
|
|
|
|
|
+ * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.
|
|
|
|
|
+ * @param {ClippingContext} clippingContext - The current clipping context.
|
|
|
|
|
+ */
|
|
|
unshift( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
unshift( object, geometry, material, groupOrder, z, group, clippingContext ) {
|
|
|
|
|
|
|
|
const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext );
|
|
const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext );
|
|
@@ -173,18 +331,34 @@ class RenderList {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Pushes render bundle group data into the render list.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Object} group - Bundle group data.
|
|
|
|
|
+ */
|
|
|
pushBundle( group ) {
|
|
pushBundle( group ) {
|
|
|
|
|
|
|
|
this.bundles.push( group );
|
|
this.bundles.push( group );
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Pushes a light into the render list.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Light} light - The light.
|
|
|
|
|
+ */
|
|
|
pushLight( light ) {
|
|
pushLight( light ) {
|
|
|
|
|
|
|
|
this.lightsArray.push( light );
|
|
this.lightsArray.push( light );
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Sorts the internal render lists.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Function} customOpaqueSort - A custom sort function for opaque objects.
|
|
|
|
|
+ * @param {Function} customTransparentSort - A custom sort function for transparent objects.
|
|
|
|
|
+ */
|
|
|
sort( customOpaqueSort, customTransparentSort ) {
|
|
sort( customOpaqueSort, customTransparentSort ) {
|
|
|
|
|
|
|
|
if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable );
|
|
if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable );
|
|
@@ -193,6 +367,10 @@ class RenderList {
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * This method performs finalizing tasks right after the render lists
|
|
|
|
|
+ * have been generated.
|
|
|
|
|
+ */
|
|
|
finish() {
|
|
finish() {
|
|
|
|
|
|
|
|
// update lights
|
|
// update lights
|