void ScnViewComponent::bind( RsFrame* pFrame, RsRenderSort Sort ) { RsContext* pContext = pFrame->getContext(); // Calculate the viewport. BcF32 Width = static_cast< BcF32 >( pContext->getWidth() ); BcF32 Height = static_cast< BcF32 >( pContext->getHeight() ); // If we're using a render target, we want to use it for dimensions. if( RenderTarget_.isValid() ) { Width = static_cast< BcF32 >( RenderTarget_->getWidth() ); Height = static_cast< BcF32 >( RenderTarget_->getHeight() ); } const BcF32 ViewWidth = Width_ * Width; const BcF32 ViewHeight = Height_ * Height; const BcF32 Aspect = ViewWidth / ViewHeight; // Setup the viewport. Viewport_.viewport( static_cast< BcU32 >( X_ * Width ), static_cast< BcU32 >( Y_ * Height ), static_cast< BcU32 >( ViewWidth ), static_cast< BcU32 >( ViewHeight ), Near_, Far_ ); // Create appropriate projection matrix. if( HorizontalFOV_ > 0.0f ) { ViewUniformBlock_.ProjectionTransform_.perspProjectionHorizontal( HorizontalFOV_, Aspect, Near_, Far_ ); } else { ViewUniformBlock_.ProjectionTransform_.perspProjectionVertical( VerticalFOV_, 1.0f / Aspect, Near_, Far_ ); } ViewUniformBlock_.InverseProjectionTransform_ = ViewUniformBlock_.ProjectionTransform_; ViewUniformBlock_.InverseProjectionTransform_.inverse(); // Setup view matrix. ViewUniformBlock_.InverseViewTransform_ = getParentEntity()->getWorldMatrix(); ViewUniformBlock_.ViewTransform_ = ViewUniformBlock_.InverseViewTransform_; ViewUniformBlock_.ViewTransform_.inverse(); // Clip transform. ViewUniformBlock_.ClipTransform_ = ViewUniformBlock_.ViewTransform_ * ViewUniformBlock_.ProjectionTransform_; // Upload uniforms. RsCore::pImpl()->updateBuffer( ViewUniformBuffer_, 0, sizeof( ViewUniformBlock_ ), RsResourceUpdateFlags::ASYNC, [ this ]( RsBuffer* Buffer, const RsBufferLock& Lock ) { BcMemCopy( Lock.Buffer_, &ViewUniformBlock_, sizeof( ViewUniformBlock_ ) ); } ); // Build frustum planes. // TODO: revisit this later as we don't need to do it I don't think. FrustumPlanes_[ 0 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][0]) ); FrustumPlanes_[ 1 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][0] ) ); FrustumPlanes_[ 2 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 3 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 4 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][2] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][2] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][2] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][2] ) ); FrustumPlanes_[ 5 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] ), ( ViewUniformBlock_.ClipTransform_[1][3] ), ( ViewUniformBlock_.ClipTransform_[2][3] ), ( ViewUniformBlock_.ClipTransform_[3][3] ) ); // Normalise frustum planes. for ( BcU32 i = 0; i < 6; ++i ) { MaVec3d Normal = FrustumPlanes_[ i ].normal(); BcF32 Scale = 1.0f / -Normal.magnitude(); FrustumPlanes_[ i ] = MaPlane( FrustumPlanes_[ i ].normal().x() * Scale, FrustumPlanes_[ i ].normal().y() * Scale, FrustumPlanes_[ i ].normal().z() * Scale, FrustumPlanes_[ i ].d() * Scale ); } // Setup render node to set the frame buffer, viewport, and clear colour. // TODO: Pass this in with the draw commands down the line. ScnViewComponentViewport* pRenderNode = pFrame->newObject< ScnViewComponentViewport >(); pRenderNode->Sort_ = Sort; pRenderNode->FrameBuffer_ = FrameBuffer_.get(); pRenderNode->Viewport_ = Viewport_; pRenderNode->ClearColour_ = ClearColour_; pRenderNode->EnableClearColour_ = EnableClearColour_; pRenderNode->EnableClearDepth_ = EnableClearDepth_; pRenderNode->EnableClearStencil_ = EnableClearStencil_; pFrame->addRenderNode( pRenderNode ); }
////////////////////////////////////////////////////////////////////////// // bind void ScnViewComponent::bind( RsFrame* pFrame, RsRenderSort Sort ) { RsContext* pContext = pFrame->getContext(); // Calculate the viewport. BcF32 Width = static_cast< BcF32 >( pContext->getWidth() ); BcF32 Height = static_cast< BcF32 >( pContext->getHeight() ); // If we're using a render target, we want to use it for dimensions. if( RenderTarget_.isValid() ) { Width = static_cast< BcF32 >( RenderTarget_->getWidth() ); Height = static_cast< BcF32 >( RenderTarget_->getHeight() ); } const BcF32 ViewWidth = Width_ * Width; const BcF32 ViewHeight = Height_ * Height; const BcF32 Aspect = ViewWidth / ViewHeight; // Setup the viewport. Viewport_.viewport( static_cast< BcU32 >( X_ * Width ), static_cast< BcU32 >( Y_ * Height ), static_cast< BcU32 >( ViewWidth ), static_cast< BcU32 >( ViewHeight ), Near_, Far_ ); // Setup matrices in view uniform block. if( ViewUniformBuffer_->lock() ) { // Create appropriate projection matrix. if( HorizontalFOV_ > 0.0f ) { ViewUniformBlock_.ProjectionTransform_.perspProjectionHorizontal( HorizontalFOV_, Aspect, Near_, Far_ ); } else { ViewUniformBlock_.ProjectionTransform_.perspProjectionVertical( VerticalFOV_, 1.0f / Aspect, Near_, Far_ ); } ViewUniformBlock_.InverseProjectionTransform_ = ViewUniformBlock_.ProjectionTransform_; ViewUniformBlock_.InverseProjectionTransform_.inverse(); // Setup view matrix. ViewUniformBlock_.InverseViewTransform_ = getParentEntity()->getWorldMatrix(); ViewUniformBlock_.ViewTransform_ = ViewUniformBlock_.InverseViewTransform_; ViewUniformBlock_.ViewTransform_.inverse(); // Clip transform. ViewUniformBlock_.ClipTransform_ = ViewUniformBlock_.ViewTransform_ * ViewUniformBlock_.ProjectionTransform_; ViewUniformBuffer_->unlock(); } // Build frustum planes. // TODO: revisit this later as we don't need to do it I don't think. FrustumPlanes_[ 0 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][0]) ); FrustumPlanes_[ 1 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][0] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][0] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][0] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][0] ) ); FrustumPlanes_[ 2 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 3 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][1] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][1] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][1] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][1] ) ); FrustumPlanes_[ 4 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][2] ), ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][2] ), ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][2] ), ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][2] ) ); FrustumPlanes_[ 5 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] ), ( ViewUniformBlock_.ClipTransform_[1][3] ), ( ViewUniformBlock_.ClipTransform_[2][3] ), ( ViewUniformBlock_.ClipTransform_[3][3] ) ); // Normalise frustum planes. for ( BcU32 i = 0; i < 6; ++i ) { MaVec3d Normal = FrustumPlanes_[ i ].normal(); BcF32 Scale = 1.0f / -Normal.magnitude(); FrustumPlanes_[ i ] = MaPlane( FrustumPlanes_[ i ].normal().x() * Scale, FrustumPlanes_[ i ].normal().y() * Scale, FrustumPlanes_[ i ].normal().z() * Scale, FrustumPlanes_[ i ].d() * Scale ); } // Set render target. if( RenderTarget_.isValid() ) { RenderTarget_->bind( pFrame ); } else { pFrame->setRenderTarget( NULL ); } // Set viewport. pFrame->setViewport( Viewport_ ); }