Moment For Technology

ThreeJS WebGLRenderList Artist sort opaque/semi-opaque

Posted on Sept. 23, 2022, 1:37 p.m. by Dr. Russell Brown
Category: The front end Tag: webgl
  • WebGLRenderList class
  • It's basically storing transparent, opaque, and then sort it.
  • Of course, two materialindexes of a mesh will be split into two for judgment
function init() {
    renderItemsIndex = 0;
    opaque.length = 0;
    transparent.length = 0;
}
Copy the code
  • See transparent for transparency
  • And then push it into a different array (Transparent /opaque)
function push( object, geometry, material, groupOrder, z, group ) {
        const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
        ( material.transparent === true ? transparent : opaque ).push( renderItem );
}
Copy the code
  • RenderItems have renderItem, which stores object, Geometry, Material, groupOrder, Z, and Group attributes
function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
        let renderItem = renderItems[ renderItemsIndex ];
        const materialProperties = properties.get( material );
        if ( renderItem === undefined ) {
                renderItem = {
                        id: object.id,
                        object: object,
                        geometry: geometry,
                        material: material,
                        program: materialProperties.program || defaultProgram,
                        groupOrder: groupOrder,
                        renderOrder: object.renderOrder,
                        z: z,
                        group: group
                };
                renderItems[ renderItemsIndex ] = renderItem;
        } else {
                renderItem.id = object.id;
                renderItem.object = object;
                renderItem.geometry = geometry;
                renderItem.material = material;
                renderItem.program = materialProperties.program || defaultProgram;
                renderItem.groupOrder = groupOrder;
                renderItem.renderOrder = object.renderOrder;
                renderItem.z = z;
                renderItem.group = group;
        }
        renderItemsIndex ++;
        return renderItem;
}
Copy the code
  • Opaque use from near to far
  • Transparency is used from far to near
  • Transparent materials do not consider program or MaterialID
function sort( customOpaqueSort, customTransparentSort ) {
        if ( opaque.length  1 ) opaque.sort( customOpaqueSort || painterSortStable );
        if ( transparent.length  1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
}
function painterSortStable( a, b ) {
	if( a.groupOrder ! == b.groupOrder ) {return a.groupOrder - b.groupOrder;
	} else if( a.renderOrder ! == b.renderOrder ) {return a.renderOrder - b.renderOrder;
	} else if( a.program ! == b.program ) {return a.program.id - b.program.id;
	} else if( a.material.id ! == b.material.id ) {return a.material.id - b.material.id; // Be careful when sorting multiple layers of materialId
	} else if( a.z ! == b.z ) {return a.z - b.z;  // The big one is in the back
	} else {
            returna.id - b.id; }}function reversePainterSortStable( a, b ) {
	if( a.groupOrder ! == b.groupOrder ) {return a.groupOrder - b.groupOrder;
	} else if( a.renderOrder ! == b.renderOrder ) {return a.renderOrder - b.renderOrder;
	} else if( a.z ! == b.z ) {return b.z - a.z;
	} else {
            returna.id - b.id; }}Copy the code
  • The original
function WebGLRenderList( properties ) {
	const renderItems = [];
	let renderItemsIndex = 0;
	const opaque = [];
	const transparent = [];
	const defaultProgram = { id: - 1 };
	function init() {
		renderItemsIndex = 0;
		opaque.length = 0;
		transparent.length = 0;
	}
	function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
		let renderItem = renderItems[ renderItemsIndex ];
		const materialProperties = properties.get( material );
		if ( renderItem === undefined ) {
			renderItem = {
				id: object.id,
				object: object,
				geometry: geometry,
				material: material,
				program: materialProperties.program || defaultProgram,
				groupOrder: groupOrder,
				renderOrder: object.renderOrder,
				z: z,
				group: group
			};
			renderItems[ renderItemsIndex ] = renderItem;
		} else {
			renderItem.id = object.id;
			renderItem.object = object;
			renderItem.geometry = geometry;
			renderItem.material = material;
			renderItem.program = materialProperties.program || defaultProgram;
			renderItem.groupOrder = groupOrder;
			renderItem.renderOrder = object.renderOrder;
			renderItem.z = z;
			renderItem.group = group;
		}
		renderItemsIndex ++;
		return renderItem;
	}
	function push( object, geometry, material, groupOrder, z, group ) {
		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
		( material.transparent === true ? transparent : opaque ).push( renderItem );
	}
	function unshift( object, geometry, material, groupOrder, z, group ) {
		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
		( material.transparent === true ? transparent : opaque ).unshift( renderItem );
	}
	function sort( customOpaqueSort, customTransparentSort ) {
		if ( opaque.length  1 ) opaque.sort( customOpaqueSort || painterSortStable );
		if ( transparent.length  1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
	}
	function finish() {
		// Clear references from inactive renderItems in the list
		for ( let i = renderItemsIndex, il = renderItems.length; i  il; i ++ ) {
			const renderItem = renderItems[ i ];
			if ( renderItem.id === null ) break;
			renderItem.id = null;
			renderItem.object = null;
			renderItem.geometry = null;
			renderItem.material = null;
			renderItem.program = null;
			renderItem.group = null; }}return {
		opaque: opaque,
		transparent: transparent,
		init: init,
		push: push,
		unshift: unshift,
		finish: finish,
		sort: sort
	};
}
function WebGLRenderLists( properties ) {
	let lists = new WeakMap(a);function get( scene, renderCallDepth ) {
		let list;
		if ( lists.has( scene ) === false ) {
			list = new WebGLRenderList( properties );
			lists.set( scene, [ list ] );
		} else {
			if ( renderCallDepth = lists.get( scene ).length ) {
				list = new WebGLRenderList( properties );
				lists.get( scene ).push( list );
			} else{ list = lists.get( scene )[ renderCallDepth ]; }}return list;
	}
	function dispose() {
		lists = new WeakMap(a); }return {
		get: get,
		dispose: dispose
	};
}
Copy the code
Search
About
mo4tech.com (Moment For Technology) is a global community with thousands techies from across the global hang out!Passionate technologists, be it gadget freaks, tech enthusiasts, coders, technopreneurs, or CIOs, you would find them all here.