import RnObject from '../core/RnObject' ; import Entity from '../core/Entity' ; import FrameBuffer from './FrameBuffer' ; import SceneGraphComponent from '../components/SceneGraphComponent' ; import MeshComponent from '../components/MeshComponent' ; import Vector4 from '../math/Vector4' ; import CameraComponent from '../components/CameraComponent' ; import { EntityUID } from '../../types/CommonTypes' ; import Material from '../materials/core/Material' ; import { WebGLStrategy } from '../../webgl/main' ; import System from '../system/System' ; import ModuleManager from '../system/ModuleManager' ; import WebGLResourceRepository from '../../webgl/WebGLResourceRepository' ; import { Primitive } from '../geometry/Primitive' ; import MutableVector4 from '../math/MutableVector4' ; import { IVector4 } from '../math/IVector' ; /**
 * A render pass is a collection of the resources which is used in rendering process.
 */ export default class RenderPass extends RnObject { private __entities : Entity [ ] = [ ] ; private __sceneGraphDirectlyAdded : SceneGraphComponent [ ] = [ ] ; private __topLevelSceneGraphComponents ? : SceneGraphComponent [ ] = [ ] ; private __meshComponents ? : MeshComponent [ ] ; private __frameBuffer ? : FrameBuffer ; private __resolveFrameBuffer ? : FrameBuffer ; private __viewport ? : MutableVector4 ; public toClearColorBuffer = false ; public toClearDepthBuffer = true ; public toClearStencilBuffer = false ; public isDepthTest = true ; public clearColor = Vector4 . fromCopyArray ( [ 1 , 1 , 1 , 1 ] ) ; public clearDepth = 1 ; public clearStencil = 0 ; public cameraComponent ? : CameraComponent ; public cullFrontFaceCCW = true ; private __material ? : Material ; private __primitiveMaterial : Map < Primitive , Material > = new Map ( ) ; private __webglRenderingStrategy ? : WebGLStrategy ; public isVrRendering = true ; public isOutputForVr = false ; private __preRenderFunc ? : Function ; private static __tmp_Vector4_0 = MutableVector4 . zero ( ) ; constructor ( ) { super ( ) ; } setPreRenderFunction ( func ) { this . __preRenderFunc = func ; } unsetPreRenderFunction ( ) { this . __preRenderFunc = void 0 ; } doPreRender ( ) { if ( this . __preRenderFunc != null ) { this . __preRenderFunc ( ) ; } } param entities addEntities ( entities ) { for ( const entity of entities ) { const sceneGraphComponent = entity . getSceneGraph ( ) ; this . __sceneGraphDirectlyAdded . push ( sceneGraphComponent ) ; const collectedSgComponents = SceneGraphComponent . flattenHierarchy ( sceneGraphComponent , false ) ; const collectedEntities = collectedSgComponents . map ( ( sg ) => { return sg . entity ; } ) ; const map = this . __entities . concat ( collectedEntities ) . reduce ( ( map , entity ) => { map . set ( entity . entityUID , entity ) ; return map ; } , new Map ( ) ) ; this . __entities = Array . from ( map . values ( ) ) ; } this . __meshComponents = void 0 ; this . __topLevelSceneGraphComponents = void 0 ; this . __collectMeshComponents ( ) ; this . __collectTopLevelSceneGraphComponents ( ) ; } return get entities ( ) : Entity [ ] { return this . __entities ; } /**
     * Clear entities on this render pass.
     */ clearEntities ( ) { this . __meshComponents = void 0 ; this . __topLevelSceneGraphComponents = void 0 ; this . __entities = [ ] ; } private __collectTopLevelSceneGraphComponents ( ) { if ( this . __topLevelSceneGraphComponents == null ) { const goToTopLevel = ( sg ) => { if ( sg . parent ) { goToTopLevel ( sg . parent ) ; } return sg ; } ; this . __topLevelSceneGraphComponents = this . __sceneGraphDirectlyAdded . map ( ( sg ) => { return goToTopLevel ( sg ) ; } ) ; const set = new Set ( this . __topLevelSceneGraphComponents ) ; this . __topLevelSceneGraphComponents = Array . from ( set ) ; } } private __collectMeshComponents ( ) { if ( this . __meshComponents == null ) { this . __meshComponents = [ ] ; this . __entities . filter ( entity => { const meshComponent = entity . getMesh ( ) ; if ( meshComponent ) { this . __meshComponents ! . push ( meshComponent ) ; } } ) ; } } return get meshComponents ( ) { this . __collectMeshComponents ( ) ; return this . __meshComponents ; } return get sceneTopLevelGraphComponents ( ) : SceneGraphComponent [ ] { this . __collectTopLevelSceneGraphComponents ( ) ; return this . __topLevelSceneGraphComponents != null ? this . __topLevelSceneGraphComponents : [ ] ; } param framebuffer setFramebuffer ( framebuffer ) { this . __frameBuffer = framebuffer ; if ( framebuffer != null ) { this . setViewport ( Vector4 . fromCopyArray ( [ 0 , 0 , framebuffer . width , framebuffer . height ] ) ) ; } else { this . __viewport = undefined ; } } return getFramebuffer ( ) { return this . __frameBuffer ; } param vec setViewport ( vec ) { if ( this . __viewport != null ) { this . __viewport . copyComponents ( vec ) ; } else { this . __viewport = MutableVector4 . fromCopyArray ( [ vec . x , vec . y , vec . z , vec . w , ] ) ; } } return getViewport ( ) { let viewport = this . __viewport ; if ( viewport != null ) { viewport = RenderPass . __tmp_Vector4_0 . copyComponents ( viewport ) ; } return viewport ; } setResolveFramebuffer ( framebuffer ) { const repo = WebGLResourceRepository . getInstance ( ) ; const glw = repo . currentWebGLContextWrapper ! ; if ( ! glw || ! glw . isWebGL2 ) { console . error ( 'resolve framebuffer is unavailable in this webgl context' ) ; return ; } this . __resolveFrameBuffer = framebuffer ; } getResolveFramebuffer ( ) { return this . __resolveFrameBuffer ; } copyFramebufferToResolveFramebuffer ( ) { const repo = WebGLResourceRepository . getInstance ( ) ; const webGLResourceFrameBuffer = repo . getWebGLResource ( this . __frameBuffer ! . cgApiResourceUid ) as WebGLFramebuffer ; const webGLResourceResolveFramebuffer = repo . getWebGLResource ( this . __resolveFrameBuffer ! . cgApiResourceUid ) as WebGLFramebuffer ; const glw = repo . currentWebGLContextWrapper ! ; const gl = glw . getRawContextAsWebGL2 ( ) ; gl . bindFramebuffer ( gl . READ_FRAMEBUFFER , webGLResourceFrameBuffer ) ; gl . bindFramebuffer ( gl . DRAW_FRAMEBUFFER , webGLResourceResolveFramebuffer ) ; gl . blitFramebuffer ( 0 , 0 , this . __frameBuffer ! . width , this . __frameBuffer ! . height , 0 , 0 , this . __resolveFrameBuffer ! . width , this . __resolveFrameBuffer ! . height , gl . COLOR_BUFFER_BIT , gl . NEAREST ) ; gl . bindFramebuffer ( gl . READ_FRAMEBUFFER , null ) ; gl . bindFramebuffer ( gl . DRAW_FRAMEBUFFER , null ) ; } private __setupMaterial ( material ) { if ( material . isEmptyMaterial ( ) ) return ; const webglRenderingStrategy = this . __setWebglRenderingStrategyIfNotYet ( this . __webglRenderingStrategy ) ; webglRenderingStrategy . setupShaderForMaterial ( material ) ; } param material param primitive setMaterialForPrimitive ( material , primitive ) { this . __primitiveMaterial . set ( primitive , material ) ; this . __setupMaterial ( material ) ; } param material setMaterial ( material ) { this . __material = material ; this . __setupMaterial ( material ) ; } get material ( ) { return this . __material ; } private __setWebglRenderingStrategyIfNotYet ( webglRenderingStrategy ? ) { if ( webglRenderingStrategy != null ) { return webglRenderingStrategy ; } const system = System . getInstance ( ) ; const processApproach = system . processApproach ; const moduleManager = ModuleManager . getInstance ( ) ; const moduleName = 'webgl' ; const webglModule = moduleManager . getModule ( moduleName ) ! as any ; const newWebglRenderingStrategyRef = webglModule . getRenderingStrategy ( processApproach ) ; this . __webglRenderingStrategy = newWebglRenderingStrategyRef ; return newWebglRenderingStrategyRef ; } private __getMaterialOf ( primitive ) { return this . __primitiveMaterial . get ( primitive ) ; } private __hasMaterialOf ( primitive ) { return this . __primitiveMaterial . has ( primitive ) ; } getAppropriateMaterial ( primitive , defaultMaterial ) { let material ; if ( this . __hasMaterialOf ( primitive ) ) { material = this . __getMaterialOf ( primitive ) as Material ; } else if ( this . material != null ) { material = this . material ; } else { material = defaultMaterial ; } return material ; } }