55
66namespace Babylon ::Graphics
77{
8- namespace
9- {
10- void SetDefaultClearMode (bgfx::ViewId viewId, bgfx::FrameBufferHandle handle, uint16_t flags, uint32_t rgba, float depth, uint8_t stencil)
11- {
12- bgfx::setViewMode (viewId, bgfx::ViewMode::Sequential);
13- bgfx::setViewClear (viewId, flags, rgba, depth, stencil);
14- bgfx::setViewFrameBuffer (viewId, handle);
15- }
16-
17- void setViewPort (bgfx::ViewId viewId, const ViewPort& viewPort, uint16_t width, uint16_t height)
18- {
19- bgfx::setViewRect (viewId,
20- static_cast <uint16_t >(viewPort.X * width),
21- static_cast <uint16_t >(viewPort.Y * height),
22- static_cast <uint16_t >(viewPort.Width * width),
23- static_cast <uint16_t >(viewPort.Height * height));
24- }
25- }
26-
278 FrameBuffer::FrameBuffer (DeviceContext& context, bgfx::FrameBufferHandle handle, uint16_t width, uint16_t height, bool defaultBackBuffer, bool hasDepth, bool hasStencil)
289 : m_context{context}
2910 , m_handle{handle}
3011 , m_width{width}
3112 , m_height{height}
3213 , m_defaultBackBuffer{defaultBackBuffer}
33- , m_hasDepth(hasDepth)
34- , m_hasStencil(hasStencil)
14+ , m_hasDepth{hasDepth}
15+ , m_hasStencil{hasStencil}
16+ , m_disposed{false }
3517 {
3618 }
3719
@@ -60,20 +42,9 @@ namespace Babylon::Graphics
6042 return m_defaultBackBuffer;
6143 }
6244
63- void FrameBuffer::Bind (bgfx::Encoder& encoder )
45+ void FrameBuffer::Bind (bgfx::Encoder&)
6446 {
65- m_viewId = m_context.AcquireNewViewId (encoder);
66-
67- // Reset view state for next frame.
68- m_viewPort = {0 , 0 , 1 , 1 };
69- m_flags = BGFX_CLEAR_NONE;
70- m_rgba = 0x000000ff ;
71- m_depth = 1 .0f ;
72- m_stencil = 0 ;
73-
74- SetDefaultClearMode (m_viewId, m_handle, BGFX_CLEAR_NONE, 0x000000ff , 1 .0f , 0 );
75- setViewPort (m_viewId, m_viewPort, Width (), Height ());
76- m_hasViewIdBeenUsed = false ;
47+ m_viewId.reset ();
7748 }
7849
7950 void FrameBuffer::Unbind (bgfx::Encoder&)
@@ -82,61 +53,38 @@ namespace Babylon::Graphics
8253
8354 void FrameBuffer::Clear (bgfx::Encoder& encoder, uint16_t flags, uint32_t rgba, float depth, uint8_t stencil)
8455 {
85- m_flags = flags;
86- m_rgba = rgba;
87- m_depth = depth;
88- m_stencil = stencil;
56+ // BGFX requires us to create a new viewID, this will ensure that the view gets cleaned.
57+ m_viewId = m_context.AcquireNewViewId (encoder);
8958
90- if (m_hasViewIdBeenUsed)
91- {
92- m_viewId = m_context.AcquireNewViewId (encoder);
93- SetDefaultClearMode (m_viewId, m_handle, m_flags, m_rgba, m_depth, m_stencil);
94- setViewPort (m_viewId, m_viewPort, Width (), Height ());
95- }
96- else
97- {
98- bgfx::setViewClear (m_viewId, m_flags, m_rgba, m_depth, m_stencil);
99- }
59+ bgfx::setViewMode (m_viewId.value (), bgfx::ViewMode::Sequential);
60+ bgfx::setViewClear (m_viewId.value (), flags, rgba, depth, stencil);
61+ bgfx::setViewFrameBuffer (m_viewId.value (), m_handle);
62+
63+ // BGFX will consider the viewport when cleaning the screen, but WebGL always cleans the entire screen.
64+ // That's why we always set the viewport to {0, 0, 1, 1} when cleaning.
65+ bgfx::setViewRect (m_viewId.value (), 0 , 0 , Width (), Height ());
66+ encoder.touch (m_viewId.value ());
10067
101- m_hasViewIdBeenUsed = true ;
102- encoder.touch (m_viewId);
68+ m_bgfxViewPort = {0 , 0 , 1 , 1 };
10369 }
10470
10571 void FrameBuffer::SetViewPort (bgfx::Encoder& encoder, float x, float y, float width, float height)
10672 {
107- if (m_viewPort.X == x && m_viewPort.Y == y && m_viewPort.Width == width && m_viewPort.Height == height)
108- {
109- return ;
110- }
111-
112- m_viewPort = {x, y, width, height};
113-
114- if (m_hasViewIdBeenUsed)
115- {
116- m_viewId = m_context.AcquireNewViewId (encoder);
117- SetDefaultClearMode (m_viewId, m_handle, m_flags, m_rgba, m_depth, m_stencil);
118- }
119-
120- setViewPort (m_viewId, m_viewPort, Width (), Height ());
121- m_hasViewIdBeenUsed = true ;
73+ m_desiredViewPort = {x, y, width, height};
74+ SetBgfxViewPort (encoder, m_desiredViewPort);
12275 }
12376
12477 void FrameBuffer::Submit (bgfx::Encoder& encoder, bgfx::ProgramHandle programHandle, uint8_t flags)
12578 {
126- encoder. submit (m_viewId, programHandle, 0 , flags );
127- m_hasViewIdBeenUsed = true ;
79+ SetBgfxViewPort (encoder, m_desiredViewPort );
80+ encoder. submit (m_viewId. value (), programHandle, 0 , flags) ;
12881 }
12982
13083 void FrameBuffer::Blit (bgfx::Encoder& encoder, bgfx::TextureHandle dst, uint16_t dstX, uint16_t dstY, bgfx::TextureHandle src, uint16_t srcX, uint16_t srcY, uint16_t width, uint16_t height)
13184 {
132- // 1 blit per view, create a new viewId for each blit
133- // TODO: Really? Why? Is this from the examples or something?
134- m_viewId = m_context.AcquireNewViewId (encoder);
135- SetDefaultClearMode (m_viewId, m_handle, m_flags, m_rgba, m_depth, m_stencil);
136- setViewPort (m_viewId, m_viewPort, Width (), Height ());
137-
138- encoder.blit (m_viewId, dst, dstX, dstY, src, srcX, srcY, width, height);
139- m_hasViewIdBeenUsed = true ;
85+ // In order for Blit to work properly we need to force the creation of a new ViewID.
86+ SetBgfxViewPort (encoder, m_desiredViewPort);
87+ encoder.blit (m_viewId.value (), dst, dstX, dstY, src, srcX, srcY, width, height);
14088 }
14189
14290 void FrameBuffer::SetStencil (bgfx::Encoder& encoder, uint32_t stencilState)
@@ -159,6 +107,27 @@ namespace Babylon::Graphics
159107 m_disposed = true ;
160108 }
161109
110+ void FrameBuffer::SetBgfxViewPort (bgfx::Encoder& encoder, const ViewPort& viewPort)
111+ {
112+ if (m_viewId.has_value () && viewPort.Equals (m_bgfxViewPort))
113+ {
114+ return ;
115+ }
116+
117+ m_viewId = m_context.AcquireNewViewId (encoder);
118+
119+ m_bgfxViewPort = viewPort;
120+
121+ bgfx::setViewMode (m_viewId.value (), bgfx::ViewMode::Sequential);
122+ bgfx::setViewClear (m_viewId.value (), BGFX_CLEAR_NONE, 0 , 1 .0f , 0 );
123+ bgfx::setViewFrameBuffer (m_viewId.value (), m_handle);
124+ bgfx::setViewRect (m_viewId.value (),
125+ static_cast <uint16_t >(m_bgfxViewPort.X * Width ()),
126+ static_cast <uint16_t >(m_bgfxViewPort.Y * Height ()),
127+ static_cast <uint16_t >(m_bgfxViewPort.Width * Width ()),
128+ static_cast <uint16_t >(m_bgfxViewPort.Height * Height ()));
129+ }
130+
162131 bool ViewPort::Equals (const ViewPort& other) const
163132 {
164133 return std::abs (X - other.X ) < std::numeric_limits<float >::epsilon () &&
0 commit comments