c357e426 |
1 | // Created on: 2011-09-20 |
2 | // Created by: Sergey ZERCHANINOV |
3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <stdio.h> |
17 | #include <stdlib.h> |
18 | |
19 | #include <OpenGl_GlCore11.hxx> |
c357e426 |
20 | |
b40cdc2b |
21 | #include <Aspect_XRSession.hxx> |
c357e426 |
22 | #include <Graphic3d_GraphicDriver.hxx> |
851dacdb |
23 | #include <Graphic3d_StructureManager.hxx> |
c357e426 |
24 | #include <Graphic3d_TextureParams.hxx> |
25 | #include <Graphic3d_Texture2Dmanual.hxx> |
26 | #include <Graphic3d_TransformUtils.hxx> |
27 | #include <Image_AlienPixMap.hxx> |
28 | |
29 | #include <NCollection_Mat4.hxx> |
30 | |
c357e426 |
31 | #include <OpenGl_Context.hxx> |
15669413 |
32 | #include <OpenGl_FrameStats.hxx> |
c357e426 |
33 | #include <OpenGl_Matrix.hxx> |
34 | #include <OpenGl_Workspace.hxx> |
35 | #include <OpenGl_View.hxx> |
c357e426 |
36 | #include <OpenGl_GraduatedTrihedron.hxx> |
37 | #include <OpenGl_PrimitiveArray.hxx> |
c357e426 |
38 | #include <OpenGl_ShaderManager.hxx> |
39 | #include <OpenGl_ShaderProgram.hxx> |
40 | #include <OpenGl_Structure.hxx> |
41 | #include <OpenGl_ArbFBO.hxx> |
42 | |
67312b79 |
43 | #include "../Textures/Textures_EnvLUT.pxx" |
44 | |
a0b49de4 |
45 | namespace |
46 | { |
47 | //! Format Frame Buffer format for logging messages. |
48 | static TCollection_AsciiString printFboFormat (const Handle(OpenGl_FrameBuffer)& theFbo) |
49 | { |
50 | return TCollection_AsciiString() + theFbo->GetInitVPSizeX() + "x" + theFbo->GetInitVPSizeY() + "@" + theFbo->NbSamples(); |
51 | } |
52 | |
53 | //! Return TRUE if Frame Buffer initialized has failed with the same parameters. |
54 | static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck, |
55 | Standard_Integer theSizeX, |
56 | Standard_Integer theSizeY, |
57 | Standard_Integer theNbSamples) |
58 | { |
59 | return !theFboToCheck->IsValid() |
60 | && theFboToCheck->GetInitVPSizeX() == theSizeX |
61 | && theFboToCheck->GetInitVPSizeY() == theSizeY |
62 | && theFboToCheck->NbSamples() == theNbSamples; |
63 | } |
64 | |
65 | //! Return TRUE if Frame Buffer initialized has failed with the same parameters. |
66 | static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck, |
67 | const Handle(OpenGl_FrameBuffer)& theFboRef) |
68 | { |
69 | return checkWasFailedFbo (theFboToCheck, theFboRef->GetVPSizeX(), theFboRef->GetVPSizeY(), theFboRef->NbSamples()); |
70 | } |
71 | } |
72 | |
c357e426 |
73 | //======================================================================= |
a521d90d |
74 | //function : drawBackground |
c357e426 |
75 | //purpose : |
76 | //======================================================================= |
cdc54fb0 |
77 | void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace, |
78 | Graphic3d_Camera::Projection theProjection) |
c357e426 |
79 | { |
80 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
c357e426 |
81 | const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False); |
82 | if (wasUsedZBuffer) |
83 | { |
84 | aCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
85 | } |
86 | |
077a220c |
87 | if (myBackgroundType == Graphic3d_TOB_CUBEMAP) |
c357e426 |
88 | { |
077a220c |
89 | myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uZCoeff", myBackgroundCubeMap->ZIsInverted() ? -1 : 1); |
90 | myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uYCoeff", myBackgroundCubeMap->IsTopDown() ? 1 : -1); |
91 | const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myCubeMapParams); |
c357e426 |
92 | |
cdc54fb0 |
93 | myBackgrounds[Graphic3d_TOB_CUBEMAP]->Render (theWorkspace, theProjection); |
c357e426 |
94 | |
077a220c |
95 | theWorkspace->SetAspects (anOldAspectFace); |
96 | } |
97 | else if (myBackgroundType == Graphic3d_TOB_GRADIENT |
98 | || myBackgroundType == Graphic3d_TOB_TEXTURE) |
99 | { |
100 | // Drawing background gradient if: |
101 | // - gradient fill type is not Aspect_GFM_NONE and |
102 | // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode |
103 | if (myBackgrounds[Graphic3d_TOB_GRADIENT]->IsDefined() |
104 | && (!myTextureParams->Aspect()->ToMapTexture() |
105 | || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_CENTERED |
106 | || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_NONE)) |
c357e426 |
107 | { |
cdc54fb0 |
108 | myBackgrounds[Graphic3d_TOB_GRADIENT]->Render(theWorkspace, theProjection); |
c357e426 |
109 | } |
c357e426 |
110 | |
077a220c |
111 | // Drawing background image if it is defined |
112 | // (texture is defined and fill type is not Aspect_FM_NONE) |
113 | if (myBackgrounds[Graphic3d_TOB_TEXTURE]->IsDefined() |
114 | && myTextureParams->Aspect()->ToMapTexture()) |
115 | { |
116 | aCtx->core11fwd->glDisable (GL_BLEND); |
c357e426 |
117 | |
077a220c |
118 | const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myTextureParams); |
cdc54fb0 |
119 | myBackgrounds[Graphic3d_TOB_TEXTURE]->Render (theWorkspace, theProjection); |
077a220c |
120 | theWorkspace->SetAspects (anOldAspectFace); |
121 | } |
c357e426 |
122 | } |
123 | |
c357e426 |
124 | if (wasUsedZBuffer) |
125 | { |
126 | theWorkspace->SetUseZBuffer (Standard_True); |
127 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); |
128 | } |
129 | } |
130 | |
131 | //======================================================================= |
132 | //function : Redraw |
133 | //purpose : |
134 | //======================================================================= |
135 | void OpenGl_View::Redraw() |
136 | { |
7ccf8676 |
137 | const Standard_Boolean wasDisabledMSAA = myToDisableMSAA; |
138 | const Standard_Boolean hadFboBlit = myHasFboBlit; |
c357e426 |
139 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
140 | && !myCaps->vboDisable |
141 | && !myCaps->keepArrayData) |
142 | { |
851dacdb |
143 | // caps are shared across all views, thus we need to invalidate all of them |
144 | // if (myWasRedrawnGL) { myStructureManager->SetDeviceLost(); } |
145 | myDriver->setDeviceLost(); |
c357e426 |
146 | myCaps->keepArrayData = Standard_True; |
147 | } |
148 | |
149 | if (!myWorkspace->Activate()) |
150 | { |
151 | return; |
152 | } |
153 | |
b40cdc2b |
154 | // implicitly disable VSync when using HMD composer (can be mirrored in window for debugging) |
155 | myWindow->SetSwapInterval (IsActiveXR()); |
c357e426 |
156 | |
157 | ++myFrameCounter; |
7c3ef2f7 |
158 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
159 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
ba00aab7 |
160 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
5e30547b |
161 | aCtx->FrameStats()->FrameStart (myWorkspace->View(), false); |
2a332745 |
162 | aCtx->SetLineFeather (myRenderParams.LineFeather); |
c357e426 |
163 | |
ba00aab7 |
164 | const Standard_Integer anSRgbState = aCtx->ToRenderSRGB() ? 1 : 0; |
165 | if (mySRgbState != -1 |
166 | && mySRgbState != anSRgbState) |
167 | { |
168 | releaseSrgbResources (aCtx); |
169 | initTextureEnv (aCtx); |
170 | } |
171 | mySRgbState = anSRgbState; |
172 | aCtx->ShaderManager()->UpdateSRgbState(); |
173 | |
c357e426 |
174 | // release pending GL resources |
175 | aCtx->ReleaseDelayed(); |
176 | |
177 | // fetch OpenGl context state |
178 | aCtx->FetchState(); |
179 | |
ad67e367 |
180 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); |
c357e426 |
181 | bool toSwap = aCtx->IsRender() |
182 | && !aCtx->caps->buffersNoSwap |
b40cdc2b |
183 | && aFrameBuffer == NULL |
184 | && (!IsActiveXR() || myRenderParams.ToMirrorComposer); |
185 | |
186 | Standard_Integer aSizeX = myWindow->Width(); |
187 | Standard_Integer aSizeY = myWindow->Height(); |
188 | if (aFrameBuffer != NULL) |
189 | { |
190 | aSizeX = aFrameBuffer->GetVPSizeX(); |
191 | aSizeY = aFrameBuffer->GetVPSizeY(); |
192 | } |
193 | else if (IsActiveXR()) |
194 | { |
195 | aSizeX = myXRSession->RecommendedViewport().x(); |
196 | aSizeY = myXRSession->RecommendedViewport().y(); |
197 | } |
c357e426 |
198 | |
d918208a |
199 | const Standard_Integer aRendSizeX = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeX + 0.5f); |
200 | const Standard_Integer aRendSizeY = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeY + 0.5f); |
201 | if (aSizeX < 1 |
202 | || aSizeY < 1 |
203 | || aRendSizeX < 1 |
204 | || aRendSizeY < 1) |
205 | { |
206 | myBackBufferRestored = Standard_False; |
207 | myIsImmediateDrawn = Standard_False; |
208 | return; |
209 | } |
c357e426 |
210 | |
3c4b62a4 |
211 | // determine multisampling parameters |
56689b27 |
212 | Standard_Integer aNbSamples = !myToDisableMSAA && aSizeX == aRendSizeX |
7ccf8676 |
213 | ? Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0) |
214 | : 0; |
3c4b62a4 |
215 | if (aNbSamples != 0) |
216 | { |
217 | aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); |
218 | } |
219 | |
a1073ae2 |
220 | bool toUseOit = myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT |
221 | && checkOitCompatibility (aCtx, aNbSamples > 0); |
222 | |
223 | const bool toInitImmediateFbo = myTransientDrawToFront |
224 | && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures())); |
225 | |
c357e426 |
226 | if ( aFrameBuffer == NULL |
227 | && !aCtx->DefaultFrameBuffer().IsNull() |
228 | && aCtx->DefaultFrameBuffer()->IsValid()) |
229 | { |
230 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
231 | } |
232 | |
233 | if (myHasFboBlit |
3c4b62a4 |
234 | && (myTransientDrawToFront |
235 | || aProjectType == Graphic3d_Camera::Projection_Stereo |
56689b27 |
236 | || aNbSamples != 0 |
a1073ae2 |
237 | || toUseOit |
56689b27 |
238 | || aSizeX != aRendSizeX)) |
c357e426 |
239 | { |
56689b27 |
240 | if (myMainSceneFbos[0]->GetVPSizeX() != aRendSizeX |
241 | || myMainSceneFbos[0]->GetVPSizeY() != aRendSizeY |
3c4b62a4 |
242 | || myMainSceneFbos[0]->NbSamples() != aNbSamples) |
c357e426 |
243 | { |
521b0d7f |
244 | if (!myTransientDrawToFront) |
245 | { |
246 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
247 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
248 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
249 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
250 | } |
251 | |
c357e426 |
252 | // prepare FBOs containing main scene |
253 | // for further blitting and rendering immediate presentations on top |
254 | if (aCtx->core20fwd != NULL) |
255 | { |
a0b49de4 |
256 | const bool wasFailedMain0 = checkWasFailedFbo (myMainSceneFbos[0], aRendSizeX, aRendSizeY, aNbSamples); |
257 | if (!myMainSceneFbos[0]->Init (aCtx, aRendSizeX, aRendSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples) |
258 | && !wasFailedMain0) |
259 | { |
260 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO " |
261 | + printFboFormat (myMainSceneFbos[0]) + " initialization has failed"; |
262 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
263 | } |
c357e426 |
264 | } |
a1073ae2 |
265 | } |
266 | if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid())) |
267 | { |
a0b49de4 |
268 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); |
269 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) |
270 | && !wasFailedImm0) |
271 | { |
272 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO " |
273 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; |
274 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
275 | } |
c357e426 |
276 | } |
277 | } |
278 | else |
279 | { |
280 | myMainSceneFbos [0]->Release (aCtx.operator->()); |
281 | myMainSceneFbos [1]->Release (aCtx.operator->()); |
282 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
283 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
b40cdc2b |
284 | myXrSceneFbo ->Release (aCtx.operator->()); |
c357e426 |
285 | myMainSceneFbos [0]->ChangeViewport (0, 0); |
286 | myMainSceneFbos [1]->ChangeViewport (0, 0); |
287 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
288 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
b40cdc2b |
289 | myXrSceneFbo ->ChangeViewport (0, 0); |
c357e426 |
290 | } |
291 | |
b40cdc2b |
292 | bool hasXRBlitFbo = false; |
c357e426 |
293 | if (aProjectType == Graphic3d_Camera::Projection_Stereo |
b40cdc2b |
294 | && IsActiveXR() |
c357e426 |
295 | && myMainSceneFbos[0]->IsValid()) |
b40cdc2b |
296 | { |
297 | if (aNbSamples != 0 |
298 | || aSizeX != aRendSizeX) |
299 | { |
300 | hasXRBlitFbo = myXrSceneFbo->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0); |
301 | if (!hasXRBlitFbo) |
302 | { |
303 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! VR FBO " |
304 | + printFboFormat (myXrSceneFbo) + " initialization has failed"; |
305 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
306 | } |
307 | } |
308 | } |
309 | else if (aProjectType == Graphic3d_Camera::Projection_Stereo |
310 | && myMainSceneFbos[0]->IsValid()) |
c357e426 |
311 | { |
a0b49de4 |
312 | const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]); |
313 | if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) |
314 | && !wasFailedMain1) |
315 | { |
316 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) " |
317 | + printFboFormat (myMainSceneFbos[1]) + " initialization has failed"; |
318 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
319 | } |
c357e426 |
320 | if (!myMainSceneFbos[1]->IsValid()) |
321 | { |
322 | // no enough memory? |
323 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
324 | } |
325 | else if (!myTransientDrawToFront) |
326 | { |
327 | // |
328 | } |
329 | else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer) |
330 | { |
a0b49de4 |
331 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); |
332 | const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]); |
333 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) |
334 | && !wasFailedImm0) |
335 | { |
336 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " |
337 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; |
338 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
339 | } |
340 | if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) |
341 | && !wasFailedImm1) |
342 | { |
343 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " |
344 | + printFboFormat (myImmediateSceneFbos[1]) + " initialization has failed"; |
345 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
346 | } |
c357e426 |
347 | if (!myImmediateSceneFbos[0]->IsValid() |
348 | || !myImmediateSceneFbos[1]->IsValid()) |
349 | { |
350 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
351 | } |
352 | } |
353 | } |
b40cdc2b |
354 | if (!hasXRBlitFbo) |
355 | { |
356 | myXrSceneFbo->Release (aCtx.get()); |
357 | myXrSceneFbo->ChangeViewport (0, 0); |
358 | } |
c357e426 |
359 | |
67312b79 |
360 | // process PBR environment |
361 | if (myShadingModel == Graphic3d_TOSM_PBR |
362 | || myShadingModel == Graphic3d_TOSM_PBR_FACET) |
363 | { |
364 | if (!myPBREnvironment.IsNull() |
365 | && myPBREnvironment->SizesAreDifferent (myRenderParams.PbrEnvPow2Size, |
366 | myRenderParams.PbrEnvSpecMapNbLevels)) |
367 | { |
368 | myPBREnvironment->Release (aCtx.get()); |
369 | myPBREnvironment.Nullify(); |
370 | myPBREnvState = OpenGl_PBREnvState_NONEXISTENT; |
371 | myPBREnvRequest = OpenGl_PBREnvRequest_BAKE; |
372 | ++myLightsRevision; |
373 | } |
374 | |
375 | if (myPBREnvState == OpenGl_PBREnvState_NONEXISTENT |
376 | && aCtx->HasPBR()) |
377 | { |
378 | myPBREnvironment = OpenGl_PBREnvironment::Create (aCtx, myRenderParams.PbrEnvPow2Size, myRenderParams.PbrEnvSpecMapNbLevels); |
379 | myPBREnvState = myPBREnvironment.IsNull() ? OpenGl_PBREnvState_UNAVAILABLE : OpenGl_PBREnvState_CREATED; |
380 | if (myPBREnvState == OpenGl_PBREnvState_CREATED) |
381 | { |
382 | Handle(OpenGl_Texture) anEnvLUT; |
383 | static const TCollection_AsciiString THE_SHARED_ENV_LUT_KEY("EnvLUT"); |
384 | if (!aCtx->GetResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT)) |
385 | { |
386 | Handle(Graphic3d_TextureParams) aParams = new Graphic3d_TextureParams(); |
387 | aParams->SetFilter (Graphic3d_TOTF_BILINEAR); |
388 | aParams->SetRepeat (Standard_False); |
389 | aParams->SetTextureUnit (aCtx->PBREnvLUTTexUnit()); |
390 | anEnvLUT = new OpenGl_Texture(THE_SHARED_ENV_LUT_KEY, aParams); |
391 | Handle(Image_PixMap) aPixMap = new Image_PixMap(); |
392 | aPixMap->InitWrapper (Image_Format_RGF, (Standard_Byte*)Textures_EnvLUT, Textures_EnvLUTSize, Textures_EnvLUTSize); |
393 | OpenGl_TextureFormat aTexFormat = OpenGl_TextureFormat::FindFormat (aCtx, aPixMap->Format(), false); |
394 | #if defined(GL_ES_VERSION_2_0) |
395 | // GL_RG32F is not texture-filterable format on OpenGL ES without OES_texture_float_linear extension. |
396 | // GL_RG16F is texture-filterable since OpenGL ES 3.0 and can be initialized from 32-bit floats. |
397 | // Note that it is expected that GL_RG16F has enough precision for this table, so that it can be used also on desktop OpenGL. |
398 | //if (!aCtx->hasTexFloatLinear) |
399 | aTexFormat.SetInternalFormat (GL_RG16F); |
400 | #endif |
401 | if (!aTexFormat.IsValid() |
402 | || !anEnvLUT->Init (aCtx, aTexFormat, Graphic3d_Vec2i((Standard_Integer)Textures_EnvLUTSize), Graphic3d_TOT_2D, aPixMap.get())) |
403 | { |
404 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed allocation of LUT for PBR"); |
405 | anEnvLUT.Nullify(); |
406 | } |
407 | aCtx->ShareResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT); |
408 | } |
409 | if (!anEnvLUT.IsNull()) |
410 | { |
411 | anEnvLUT->Bind (aCtx); |
412 | } |
413 | myWorkspace->ApplyAspects(); |
414 | } |
415 | } |
416 | processPBREnvRequest (aCtx); |
417 | } |
418 | |
a1073ae2 |
419 | // create color and coverage accumulation buffers required for OIT algorithm |
420 | if (toUseOit) |
421 | { |
422 | Standard_Integer anFboIt = 0; |
423 | for (; anFboIt < 2; ++anFboIt) |
424 | { |
425 | Handle(OpenGl_FrameBuffer)& aMainSceneFbo = myMainSceneFbos [anFboIt]; |
426 | Handle(OpenGl_FrameBuffer)& aMainSceneFboOit = myMainSceneFbosOit [anFboIt]; |
427 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFbo = myImmediateSceneFbos [anFboIt]; |
428 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFboOit = myImmediateSceneFbosOit[anFboIt]; |
429 | if (aMainSceneFbo->IsValid() |
430 | && (aMainSceneFboOit->GetVPSizeX() != aRendSizeX |
431 | || aMainSceneFboOit->GetVPSizeY() != aRendSizeY |
432 | || aMainSceneFboOit->NbSamples() != aNbSamples)) |
433 | { |
434 | Standard_Integer aColorConfig = 0; |
435 | for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED) |
436 | { |
437 | if (myFboOitColorConfig.IsEmpty()) |
438 | { |
439 | if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig)) |
440 | { |
441 | break; |
442 | } |
443 | } |
444 | if (aMainSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, aMainSceneFbo->DepthStencilTexture(), aNbSamples)) |
445 | { |
446 | break; |
447 | } |
448 | myFboOitColorConfig.Clear(); |
449 | } |
450 | if (!aMainSceneFboOit->IsValid()) |
451 | { |
452 | break; |
453 | } |
454 | } |
455 | else if (!aMainSceneFbo->IsValid()) |
456 | { |
457 | aMainSceneFboOit->Release (aCtx.operator->()); |
458 | aMainSceneFboOit->ChangeViewport (0, 0); |
459 | } |
460 | |
461 | if (anImmediateSceneFbo->IsValid() |
462 | && (anImmediateSceneFboOit->GetVPSizeX() != aRendSizeX |
463 | || anImmediateSceneFboOit->GetVPSizeY() != aRendSizeY |
464 | || anImmediateSceneFboOit->NbSamples() != aNbSamples)) |
465 | { |
466 | if (!anImmediateSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, |
467 | anImmediateSceneFbo->DepthStencilTexture(), aNbSamples)) |
468 | { |
469 | break; |
470 | } |
471 | } |
472 | else if (!anImmediateSceneFbo->IsValid()) |
473 | { |
474 | anImmediateSceneFboOit->Release (aCtx.operator->()); |
475 | anImmediateSceneFboOit->ChangeViewport (0, 0); |
476 | } |
477 | } |
478 | if (anFboIt == 0) // only the first OIT framebuffer is mandatory |
479 | { |
480 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
481 | "Initialization of float texture framebuffer for use with\n" |
482 | " blended order-independent transparency rendering algorithm has failed.\n" |
483 | " Blended order-independent transparency will not be available.\n"); |
484 | if (aNbSamples > 0) |
485 | { |
486 | myToDisableOITMSAA = Standard_True; |
487 | } |
488 | else |
489 | { |
490 | myToDisableOIT = Standard_True; |
491 | } |
492 | toUseOit = false; |
493 | } |
494 | } |
495 | if (!toUseOit && myMainSceneFbosOit[0]->IsValid()) |
496 | { |
497 | myMainSceneFbosOit [0]->Release (aCtx.operator->()); |
498 | myMainSceneFbosOit [1]->Release (aCtx.operator->()); |
499 | myImmediateSceneFbosOit[0]->Release (aCtx.operator->()); |
500 | myImmediateSceneFbosOit[1]->Release (aCtx.operator->()); |
501 | myMainSceneFbosOit [0]->ChangeViewport (0, 0); |
502 | myMainSceneFbosOit [1]->ChangeViewport (0, 0); |
503 | myImmediateSceneFbosOit[0]->ChangeViewport (0, 0); |
504 | myImmediateSceneFbosOit[1]->ChangeViewport (0, 0); |
505 | } |
506 | |
c357e426 |
507 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
508 | { |
509 | OpenGl_FrameBuffer* aMainFbos[2] = |
510 | { |
511 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
512 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
513 | }; |
a1073ae2 |
514 | OpenGl_FrameBuffer* aMainFbosOit[2] = |
515 | { |
516 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL, |
517 | myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() : |
518 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL |
519 | }; |
520 | |
c357e426 |
521 | OpenGl_FrameBuffer* anImmFbos[2] = |
522 | { |
523 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
524 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
525 | }; |
a1073ae2 |
526 | OpenGl_FrameBuffer* anImmFbosOit[2] = |
527 | { |
528 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, |
529 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : |
530 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL |
531 | }; |
c357e426 |
532 | |
b40cdc2b |
533 | if (IsActiveXR()) |
534 | { |
535 | // use single frame for both views - caching main scene content makes no sense |
536 | // when head position is expected to be updated each frame redraw with high accuracy |
537 | aMainFbos[1] = aMainFbos[0]; |
538 | aMainFbosOit[1] = aMainFbosOit[0]; |
539 | anImmFbos[0] = aMainFbos[0]; |
540 | anImmFbos[1] = aMainFbos[1]; |
541 | anImmFbosOit[0] = aMainFbosOit[0]; |
542 | anImmFbosOit[1] = aMainFbosOit[1]; |
543 | } |
544 | else if (!myTransientDrawToFront) |
c357e426 |
545 | { |
a1073ae2 |
546 | anImmFbos [0] = aMainFbos [0]; |
547 | anImmFbos [1] = aMainFbos [1]; |
548 | anImmFbosOit[0] = aMainFbosOit[0]; |
549 | anImmFbosOit[1] = aMainFbosOit[1]; |
c357e426 |
550 | } |
551 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
552 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
553 | { |
a1073ae2 |
554 | anImmFbos [0] = NULL; |
555 | anImmFbos [1] = NULL; |
556 | anImmFbosOit[0] = NULL; |
557 | anImmFbosOit[1] = NULL; |
c357e426 |
558 | } |
559 | |
560 | #if !defined(GL_ES_VERSION_2_0) |
561 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
562 | #endif |
56689b27 |
563 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
564 | aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
565 | |
a1073ae2 |
566 | redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]); |
c357e426 |
567 | myBackBufferRestored = Standard_True; |
568 | myIsImmediateDrawn = Standard_False; |
569 | #if !defined(GL_ES_VERSION_2_0) |
570 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
571 | #endif |
56689b27 |
572 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
573 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
574 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0])) |
c357e426 |
575 | { |
576 | toSwap = false; |
577 | } |
578 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) |
579 | { |
580 | aCtx->SwapBuffers(); |
581 | } |
582 | |
b40cdc2b |
583 | if (IsActiveXR()) |
584 | { |
585 | // push Left frame to HMD display composer |
586 | OpenGl_FrameBuffer* anXRFbo = hasXRBlitFbo ? myXrSceneFbo.get() : aMainFbos[0]; |
587 | if (anXRFbo != aMainFbos[0]) |
588 | { |
589 | blitBuffers (aMainFbos[0], anXRFbo); // resize or resolve MSAA samples |
590 | } |
591 | #if !defined(GL_ES_VERSION_2_0) |
592 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGL; |
593 | #else |
594 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGLES; |
595 | #endif |
596 | myXRSession->SubmitEye ((void* )(size_t )anXRFbo->ColorTexture()->TextureId(), |
597 | aGraphicsLib, Aspect_ColorSpace_sRGB, Aspect_Eye_Left); |
598 | } |
599 | |
c357e426 |
600 | #if !defined(GL_ES_VERSION_2_0) |
601 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
602 | #endif |
56689b27 |
603 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
604 | aMainFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
605 | |
a1073ae2 |
606 | redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]); |
c357e426 |
607 | myBackBufferRestored = Standard_True; |
608 | myIsImmediateDrawn = Standard_False; |
56689b27 |
609 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
610 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
611 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1])) |
c357e426 |
612 | { |
613 | toSwap = false; |
614 | } |
615 | |
b40cdc2b |
616 | if (IsActiveXR()) |
617 | { |
618 | // push Right frame to HMD display composer |
619 | OpenGl_FrameBuffer* anXRFbo = hasXRBlitFbo ? myXrSceneFbo.get() : aMainFbos[1]; |
620 | if (anXRFbo != aMainFbos[1]) |
621 | { |
622 | blitBuffers (aMainFbos[1], anXRFbo); // resize or resolve MSAA samples |
623 | } |
624 | #if !defined(GL_ES_VERSION_2_0) |
625 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGL; |
626 | #else |
627 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGLES; |
628 | #endif |
629 | myXRSession->SubmitEye ((void* )(size_t )anXRFbo->ColorTexture()->TextureId(), |
630 | aGraphicsLib, Aspect_ColorSpace_sRGB, Aspect_Eye_Right); |
631 | ::glFinish(); |
632 | |
633 | if (myRenderParams.ToMirrorComposer) |
634 | { |
635 | blitBuffers (anXRFbo, aFrameBuffer, myToFlipOutput); |
636 | } |
637 | } |
638 | else if (anImmFbos[0] != NULL) |
c357e426 |
639 | { |
56689b27 |
640 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), 1.0f); |
3c4b62a4 |
641 | drawStereoPair (aFrameBuffer); |
c357e426 |
642 | } |
643 | } |
644 | else |
645 | { |
a1073ae2 |
646 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer; |
647 | OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL; |
648 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
649 | OpenGl_FrameBuffer* anImmFboOit = NULL; |
650 | if (!myTransientDrawToFront) |
c357e426 |
651 | { |
a1073ae2 |
652 | anImmFbo = aMainFbo; |
653 | anImmFboOit = aMainFboOit; |
c357e426 |
654 | } |
a1073ae2 |
655 | else if (myImmediateSceneFbos[0]->IsValid()) |
521b0d7f |
656 | { |
a1073ae2 |
657 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
658 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; |
521b0d7f |
659 | } |
c357e426 |
660 | |
661 | #if !defined(GL_ES_VERSION_2_0) |
3bffef55 |
662 | if (aMainFbo == NULL) |
c357e426 |
663 | { |
664 | aCtx->SetReadDrawBuffer (GL_BACK); |
665 | } |
666 | #endif |
56689b27 |
667 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
668 | aMainFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
669 | |
670 | redraw (aProjectType, aMainFbo, aMainFboOit); |
c357e426 |
671 | myBackBufferRestored = Standard_True; |
672 | myIsImmediateDrawn = Standard_False; |
56689b27 |
673 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
674 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
a1073ae2 |
675 | if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit)) |
c357e426 |
676 | { |
677 | toSwap = false; |
678 | } |
679 | |
680 | if (anImmFbo != NULL |
681 | && anImmFbo != aFrameBuffer) |
682 | { |
683 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
684 | } |
685 | } |
686 | |
bf02aa7d |
687 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
688 | && myRenderParams.IsGlobalIlluminationEnabled) |
689 | { |
690 | myAccumFrames++; |
691 | } |
692 | |
c357e426 |
693 | // bind default FBO |
694 | bindDefaultFbo(); |
695 | |
7ccf8676 |
696 | if (wasDisabledMSAA != myToDisableMSAA |
697 | || hadFboBlit != myHasFboBlit) |
698 | { |
699 | // retry on error |
700 | Redraw(); |
701 | } |
702 | |
8613985b |
703 | // reset state for safety |
704 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
705 | if (aCtx->caps->ffpEnable) |
706 | { |
707 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
708 | } |
8613985b |
709 | |
c357e426 |
710 | // Swap the buffers |
711 | if (toSwap) |
712 | { |
713 | aCtx->SwapBuffers(); |
714 | if (!myMainSceneFbos[0]->IsValid()) |
715 | { |
716 | myBackBufferRestored = Standard_False; |
717 | } |
718 | } |
719 | else |
720 | { |
721 | aCtx->core11fwd->glFlush(); |
722 | } |
723 | |
724 | // reset render mode state |
725 | aCtx->FetchState(); |
5e30547b |
726 | aCtx->FrameStats()->FrameEnd (myWorkspace->View(), false); |
c357e426 |
727 | |
728 | myWasRedrawnGL = Standard_True; |
729 | } |
730 | |
731 | // ======================================================================= |
732 | // function : RedrawImmediate |
733 | // purpose : |
734 | // ======================================================================= |
735 | void OpenGl_View::RedrawImmediate() |
736 | { |
737 | if (!myWorkspace->Activate()) |
738 | return; |
739 | |
b40cdc2b |
740 | // no special handling of HMD display, since it will force full Redraw() due to no frame caching (myBackBufferRestored) |
c357e426 |
741 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
742 | if (!myTransientDrawToFront |
743 | || !myBackBufferRestored |
744 | || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) |
745 | { |
746 | Redraw(); |
747 | return; |
748 | } |
749 | |
750 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
751 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
ad67e367 |
752 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); |
5e30547b |
753 | aCtx->FrameStats()->FrameStart (myWorkspace->View(), true); |
c357e426 |
754 | |
755 | if ( aFrameBuffer == NULL |
756 | && !aCtx->DefaultFrameBuffer().IsNull() |
757 | && aCtx->DefaultFrameBuffer()->IsValid()) |
758 | { |
759 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
760 | } |
761 | |
762 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
763 | { |
764 | if (myMainSceneFbos[0]->IsValid() |
765 | && !myMainSceneFbos[1]->IsValid()) |
766 | { |
767 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
768 | } |
769 | } |
770 | |
771 | bool toSwap = false; |
772 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
773 | { |
774 | OpenGl_FrameBuffer* aMainFbos[2] = |
775 | { |
776 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
777 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
778 | }; |
779 | OpenGl_FrameBuffer* anImmFbos[2] = |
780 | { |
781 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
782 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
783 | }; |
a1073ae2 |
784 | OpenGl_FrameBuffer* anImmFbosOit[2] = |
785 | { |
786 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, |
787 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : |
788 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL |
789 | }; |
c357e426 |
790 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
791 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
792 | { |
a1073ae2 |
793 | anImmFbos[0] = NULL; |
794 | anImmFbos[1] = NULL; |
795 | anImmFbosOit[0] = NULL; |
796 | anImmFbosOit[1] = NULL; |
c357e426 |
797 | } |
798 | |
799 | if (aCtx->arbFBO != NULL) |
800 | { |
801 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
802 | } |
803 | #if !defined(GL_ES_VERSION_2_0) |
804 | if (anImmFbos[0] == NULL) |
805 | { |
806 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
807 | } |
808 | #endif |
56689b27 |
809 | |
810 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
811 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
812 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, |
813 | aMainFbos[0], |
814 | anImmFbos[0], |
a1073ae2 |
815 | anImmFbosOit[0], |
c357e426 |
816 | Standard_True) || toSwap; |
817 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
818 | && toSwap |
819 | && !aCtx->caps->buffersNoSwap) |
820 | { |
821 | aCtx->SwapBuffers(); |
822 | } |
823 | |
824 | if (aCtx->arbFBO != NULL) |
825 | { |
826 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
827 | } |
828 | #if !defined(GL_ES_VERSION_2_0) |
829 | if (anImmFbos[1] == NULL) |
830 | { |
831 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
832 | } |
833 | #endif |
56689b27 |
834 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
835 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
836 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, |
837 | aMainFbos[1], |
838 | anImmFbos[1], |
a1073ae2 |
839 | anImmFbosOit[1], |
c357e426 |
840 | Standard_True) || toSwap; |
841 | if (anImmFbos[0] != NULL) |
842 | { |
3c4b62a4 |
843 | drawStereoPair (aFrameBuffer); |
c357e426 |
844 | } |
845 | } |
846 | else |
847 | { |
848 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
849 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
a1073ae2 |
850 | OpenGl_FrameBuffer* anImmFboOit = NULL; |
851 | if (myImmediateSceneFbos[0]->IsValid()) |
c357e426 |
852 | { |
a1073ae2 |
853 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
854 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; |
c357e426 |
855 | } |
856 | #if !defined(GL_ES_VERSION_2_0) |
857 | if (aMainFbo == NULL) |
858 | { |
859 | aCtx->SetReadDrawBuffer (GL_BACK); |
860 | } |
861 | #endif |
56689b27 |
862 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), |
863 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); |
c357e426 |
864 | toSwap = redrawImmediate (aProjectType, |
865 | aMainFbo, |
866 | anImmFbo, |
a1073ae2 |
867 | anImmFboOit, |
c357e426 |
868 | Standard_True) || toSwap; |
869 | if (anImmFbo != NULL |
870 | && anImmFbo != aFrameBuffer) |
871 | { |
872 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
873 | } |
874 | } |
875 | |
876 | // bind default FBO |
877 | bindDefaultFbo(); |
878 | |
8613985b |
879 | // reset state for safety |
880 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
881 | if (aCtx->caps->ffpEnable) |
882 | { |
883 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
884 | } |
8613985b |
885 | |
c357e426 |
886 | if (toSwap && !aCtx->caps->buffersNoSwap) |
887 | { |
888 | aCtx->SwapBuffers(); |
889 | } |
890 | else |
891 | { |
892 | aCtx->core11fwd->glFlush(); |
893 | } |
5e30547b |
894 | aCtx->FrameStats()->FrameEnd (myWorkspace->View(), true); |
c357e426 |
895 | |
896 | myWasRedrawnGL = Standard_True; |
897 | } |
898 | |
899 | // ======================================================================= |
900 | // function : redraw |
901 | // purpose : |
902 | // ======================================================================= |
a1073ae2 |
903 | void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, |
904 | OpenGl_FrameBuffer* theReadDrawFbo, |
905 | OpenGl_FrameBuffer* theOitAccumFbo) |
c357e426 |
906 | { |
907 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
908 | if (theReadDrawFbo != NULL) |
909 | { |
910 | theReadDrawFbo->BindBuffer (aCtx); |
911 | theReadDrawFbo->SetupViewport (aCtx); |
912 | } |
913 | else |
914 | { |
3bffef55 |
915 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
916 | aCtx->ResizeViewport (aViewport); |
c357e426 |
917 | } |
918 | |
919 | // request reset of material |
8613985b |
920 | aCtx->ShaderManager()->UpdateMaterialState(); |
921 | |
c357e426 |
922 | myWorkspace->UseZBuffer() = Standard_True; |
923 | myWorkspace->UseDepthWrite() = Standard_True; |
924 | GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; |
925 | glDepthFunc (GL_LEQUAL); |
926 | glDepthMask (GL_TRUE); |
927 | glEnable (GL_DEPTH_TEST); |
928 | |
929 | #if !defined(GL_ES_VERSION_2_0) |
930 | glClearDepth (1.0); |
931 | #else |
932 | glClearDepthf (1.0f); |
933 | #endif |
934 | |
ba00aab7 |
935 | const OpenGl_Vec4 aBgColor = aCtx->Vec4FromQuantityColor (myBgColor); |
8613985b |
936 | glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f); |
c357e426 |
937 | |
938 | glClear (toClear); |
939 | |
a1073ae2 |
940 | render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False); |
c357e426 |
941 | } |
942 | |
943 | // ======================================================================= |
944 | // function : redrawMonoImmediate |
945 | // purpose : |
946 | // ======================================================================= |
947 | bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, |
a1073ae2 |
948 | OpenGl_FrameBuffer* theReadFbo, |
949 | OpenGl_FrameBuffer* theDrawFbo, |
950 | OpenGl_FrameBuffer* theOitAccumFbo, |
951 | const Standard_Boolean theIsPartialUpdate) |
c357e426 |
952 | { |
1202160b |
953 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
c357e426 |
954 | GLboolean toCopyBackToFront = GL_FALSE; |
521b0d7f |
955 | if (theDrawFbo == theReadFbo |
b40cdc2b |
956 | && theDrawFbo != NULL |
957 | && theDrawFbo->IsValid()) |
c357e426 |
958 | { |
959 | myBackBufferRestored = Standard_False; |
b40cdc2b |
960 | theDrawFbo->BindBuffer (aCtx); |
c357e426 |
961 | } |
962 | else if (theReadFbo != NULL |
963 | && theReadFbo->IsValid() |
964 | && aCtx->IsRender()) |
965 | { |
966 | if (!blitBuffers (theReadFbo, theDrawFbo)) |
967 | { |
968 | return true; |
969 | } |
970 | } |
971 | else if (theDrawFbo == NULL) |
972 | { |
973 | #if !defined(GL_ES_VERSION_2_0) |
974 | aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); |
975 | #endif |
6cde53c4 |
976 | if (toCopyBackToFront |
977 | && myTransientDrawToFront) |
c357e426 |
978 | { |
979 | if (!HasImmediateStructures() |
980 | && !theIsPartialUpdate) |
981 | { |
982 | // prefer Swap Buffers within Redraw in compatibility mode (without FBO) |
983 | return true; |
984 | } |
a0b49de4 |
985 | if (!copyBackToFront()) |
986 | { |
987 | toCopyBackToFront = GL_FALSE; |
988 | myBackBufferRestored = Standard_False; |
989 | } |
c357e426 |
990 | } |
991 | else |
992 | { |
1202160b |
993 | toCopyBackToFront = GL_FALSE; |
c357e426 |
994 | myBackBufferRestored = Standard_False; |
995 | } |
996 | } |
997 | else |
998 | { |
999 | myBackBufferRestored = Standard_False; |
1000 | } |
1001 | myIsImmediateDrawn = Standard_True; |
1002 | |
1003 | myWorkspace->UseZBuffer() = Standard_True; |
1004 | myWorkspace->UseDepthWrite() = Standard_True; |
1005 | glDepthFunc (GL_LEQUAL); |
1006 | glDepthMask (GL_TRUE); |
1007 | glEnable (GL_DEPTH_TEST); |
1008 | #if !defined(GL_ES_VERSION_2_0) |
1009 | glClearDepth (1.0); |
1010 | #else |
1011 | glClearDepthf (1.0f); |
1012 | #endif |
1013 | |
a1073ae2 |
1014 | render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True); |
c357e426 |
1015 | |
1016 | return !toCopyBackToFront; |
1017 | } |
1018 | |
1019 | //======================================================================= |
1020 | //function : Render |
1021 | //purpose : |
1022 | //======================================================================= |
1023 | void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, |
1024 | OpenGl_FrameBuffer* theOutputFBO, |
a1073ae2 |
1025 | OpenGl_FrameBuffer* theOitAccumFbo, |
c357e426 |
1026 | const Standard_Boolean theToDrawImmediate) |
1027 | { |
1028 | // ================================== |
1029 | // Step 1: Prepare for render |
1030 | // ================================== |
1031 | |
1032 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
2a332745 |
1033 | aContext->SetAllowSampleAlphaToCoverage (myRenderParams.ToEnableAlphaToCoverage |
1034 | && theOutputFBO != NULL |
1035 | && theOutputFBO->NbSamples() != 0); |
c357e426 |
1036 | |
1037 | #if !defined(GL_ES_VERSION_2_0) |
1038 | // Disable current clipping planes |
1039 | if (aContext->core11 != NULL) |
1040 | { |
1041 | const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes(); |
1042 | for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId) |
1043 | { |
1044 | aContext->core11fwd->glDisable (aClipPlaneId); |
1045 | } |
1046 | } |
1047 | #endif |
1048 | |
4ecf34cc |
1049 | // update states of OpenGl_BVHTreeSelector (frustum culling algorithm); |
1050 | // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale |
c357e426 |
1051 | myBVHSelector.SetViewVolume (myCamera); |
4ecf34cc |
1052 | myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); |
2b8832bb |
1053 | myBVHSelector.CacheClipPtsProjections(); |
c357e426 |
1054 | |
992ed6b3 |
1055 | const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); |
dc89236f |
1056 | const Handle(Graphic3d_LightSet)& aLights = myShadingModel == Graphic3d_TOSM_UNLIT ? myNoShadingLight : myLights; |
992ed6b3 |
1057 | Standard_Size aLightsRevision = 0; |
1058 | if (!aLights.IsNull()) |
c357e426 |
1059 | { |
992ed6b3 |
1060 | aLightsRevision = aLights->UpdateRevision(); |
1061 | } |
1062 | if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState |
1063 | || aLightsRevision != myLightsRevision) |
1064 | { |
1065 | myLightsRevision = aLightsRevision; |
67312b79 |
1066 | aManager->UpdateLightSourceStateTo (aLights, SpecIBLMapLevels()); |
c357e426 |
1067 | myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); |
1068 | } |
1069 | |
1070 | // Update matrices if camera has changed. |
1071 | Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); |
7c3ef2f7 |
1072 | if (myWorldViewProjState != aWVPState) |
c357e426 |
1073 | { |
bf02aa7d |
1074 | myAccumFrames = 0; |
7c3ef2f7 |
1075 | myWorldViewProjState = aWVPState; |
c357e426 |
1076 | } |
1077 | |
7c3ef2f7 |
1078 | myLocalOrigin.SetCoord (0.0, 0.0, 0.0); |
b40cdc2b |
1079 | aContext->SetCamera (myCamera); |
c357e426 |
1080 | if (aManager->ModelWorldState().Index() == 0) |
1081 | { |
1082 | aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); |
1083 | } |
1084 | |
c357e426 |
1085 | // ==================================== |
1086 | // Step 2: Redraw background |
1087 | // ==================================== |
1088 | |
1089 | // Render background |
1090 | if (!theToDrawImmediate) |
1091 | { |
cdc54fb0 |
1092 | drawBackground (myWorkspace, theProjection); |
c357e426 |
1093 | } |
1094 | |
1095 | #if !defined(GL_ES_VERSION_2_0) |
1096 | // Switch off lighting by default |
dd1ae9df |
1097 | if (aContext->core11 != NULL |
1098 | && aContext->caps->ffpEnable) |
c357e426 |
1099 | { |
1100 | glDisable(GL_LIGHTING); |
1101 | } |
1102 | #endif |
1103 | |
1104 | // ================================= |
1105 | // Step 3: Redraw main plane |
1106 | // ================================= |
1107 | |
1108 | // Setup face culling |
1109 | GLboolean isCullFace = GL_FALSE; |
1110 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
1111 | { |
1112 | isCullFace = glIsEnabled (GL_CULL_FACE); |
1113 | if (myBackfacing == Graphic3d_TOBM_DISABLE) |
1114 | { |
1115 | glEnable (GL_CULL_FACE); |
1116 | glCullFace (GL_BACK); |
1117 | } |
1118 | else |
1119 | glDisable (GL_CULL_FACE); |
1120 | } |
1121 | |
1122 | #if !defined(GL_ES_VERSION_2_0) |
1123 | // if the view is scaled normal vectors are scaled to unit |
1124 | // length for correct displaying of shaded objects |
b40cdc2b |
1125 | const gp_Pnt anAxialScale = aContext->Camera()->AxialScale(); |
c357e426 |
1126 | if (anAxialScale.X() != 1.F || |
1127 | anAxialScale.Y() != 1.F || |
1128 | anAxialScale.Z() != 1.F) |
1129 | { |
1130 | aContext->SetGlNormalizeEnabled (Standard_True); |
1131 | } |
1132 | else |
1133 | { |
1134 | aContext->SetGlNormalizeEnabled (Standard_False); |
1135 | } |
c357e426 |
1136 | #endif |
1137 | |
67312b79 |
1138 | aManager->SetShadingModel (OpenGl_ShaderManager::PBRShadingModelFallback (myShadingModel, checkPBRAvailability())); |
c357e426 |
1139 | |
1140 | // Redraw 3d scene |
1141 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) |
1142 | { |
b40cdc2b |
1143 | aContext->ProjectionState.SetCurrent (aContext->Camera()->ProjectionStereoLeftF()); |
c357e426 |
1144 | aContext->ApplyProjectionMatrix(); |
1145 | } |
1146 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) |
1147 | { |
b40cdc2b |
1148 | aContext->ProjectionState.SetCurrent (aContext->Camera()->ProjectionStereoRightF()); |
c357e426 |
1149 | aContext->ApplyProjectionMatrix(); |
1150 | } |
83da37b1 |
1151 | |
1152 | myWorkspace->SetEnvironmentTexture (myTextureEnv); |
1153 | |
a1073ae2 |
1154 | renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate); |
c357e426 |
1155 | |
cc8cbabe |
1156 | myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); |
83da37b1 |
1157 | |
c357e426 |
1158 | // =============================== |
1159 | // Step 4: Trihedron |
1160 | // =============================== |
1161 | |
1162 | // Resetting GL parameters according to the default aspects |
1163 | // in order to synchronize GL state with the graphic driver state |
1164 | // before drawing auxiliary stuff (trihedrons, overlayer) |
c357e426 |
1165 | myWorkspace->ResetAppliedAspect(); |
1166 | |
c357e426 |
1167 | // Render trihedron |
1168 | if (!theToDrawImmediate) |
1169 | { |
1170 | renderTrihedron (myWorkspace); |
1171 | |
1172 | // Restore face culling |
1173 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
1174 | { |
1175 | if (isCullFace) |
1176 | { |
1177 | glEnable (GL_CULL_FACE); |
1178 | glCullFace (GL_BACK); |
1179 | } |
1180 | else |
1181 | glDisable (GL_CULL_FACE); |
1182 | } |
1183 | } |
15669413 |
1184 | else |
1185 | { |
1186 | renderFrameStats(); |
1187 | } |
c357e426 |
1188 | |
c40eb6b9 |
1189 | myWorkspace->ResetAppliedAspect(); |
2a332745 |
1190 | aContext->SetAllowSampleAlphaToCoverage (false); |
c40eb6b9 |
1191 | aContext->SetSampleAlphaToCoverage (false); |
1192 | |
8613985b |
1193 | // reset FFP state for safety |
1194 | aContext->BindProgram (Handle(OpenGl_ShaderProgram)()); |
dd1ae9df |
1195 | if (aContext->caps->ffpEnable) |
1196 | { |
1197 | aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
1198 | } |
8613985b |
1199 | |
c357e426 |
1200 | // ============================================================== |
1201 | // Step 6: Keep shader manager informed about last View |
1202 | // ============================================================== |
1203 | |
1204 | if (!aManager.IsNull()) |
1205 | { |
1206 | aManager->SetLastView (this); |
1207 | } |
1208 | } |
1209 | |
1210 | // ======================================================================= |
1211 | // function : InvalidateBVHData |
1212 | // purpose : |
1213 | // ======================================================================= |
1214 | void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) |
1215 | { |
1216 | myZLayers.InvalidateBVHData (theLayerId); |
1217 | } |
1218 | |
1219 | //======================================================================= |
1220 | //function : renderStructs |
1221 | //purpose : |
1222 | //======================================================================= |
bf02aa7d |
1223 | void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection, |
1224 | OpenGl_FrameBuffer* theReadDrawFbo, |
a1073ae2 |
1225 | OpenGl_FrameBuffer* theOitAccumFbo, |
bf02aa7d |
1226 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1227 | { |
0de16e29 |
1228 | myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate); |
c357e426 |
1229 | if ( myZLayers.NbStructures() <= 0 ) |
1230 | return; |
1231 | |
1232 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
c357e426 |
1233 | Standard_Boolean toRenderGL = theToDrawImmediate || |
1234 | myRenderParams.Method != Graphic3d_RM_RAYTRACING || |
1235 | myRaytraceInitStatus == OpenGl_RT_FAIL || |
1236 | aCtx->IsFeedback(); |
1237 | |
1238 | if (!toRenderGL) |
1239 | { |
66d1cdc6 |
1240 | const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width(); |
1241 | const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height(); |
1242 | |
1243 | toRenderGL = !initRaytraceResources (aSizeX, aSizeY, aCtx) |
1244 | || !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx); |
c357e426 |
1245 | |
1246 | toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL |
1247 | |
1248 | if (!toRenderGL) |
1249 | { |
3c4b62a4 |
1250 | myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0); |
c357e426 |
1251 | |
c357e426 |
1252 | if (theReadDrawFbo != NULL) |
1253 | theReadDrawFbo->UnbindBuffer (aCtx); |
1254 | |
1255 | // Prepare preliminary OpenGL output |
1256 | if (aCtx->arbFBOBlit != NULL) |
1257 | { |
1258 | // Render bottom OSD layer |
a1073ae2 |
1259 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1260 | |
1b661a81 |
1261 | const Standard_Integer aPrevFilter = myWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_NonRaytraceableOnly); |
1262 | myWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_NonRaytraceableOnly); |
c357e426 |
1263 | { |
1264 | if (theReadDrawFbo != NULL) |
1265 | { |
3a9b5dc8 |
1266 | theReadDrawFbo->BindDrawBuffer (aCtx); |
c357e426 |
1267 | } |
1268 | else |
1269 | { |
3a9b5dc8 |
1270 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); |
ba00aab7 |
1271 | aCtx->SetFrameBufferSRGB (false); |
c357e426 |
1272 | } |
1273 | |
c357e426 |
1274 | // Render non-polygonal elements in default layer |
1c728f2d |
1275 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_RayTracable, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1276 | } |
1b661a81 |
1277 | myWorkspace->SetRenderFilter (aPrevFilter); |
c357e426 |
1278 | } |
1279 | |
1280 | if (theReadDrawFbo != NULL) |
1281 | { |
1282 | theReadDrawFbo->BindBuffer (aCtx); |
1283 | } |
1284 | else |
1285 | { |
1286 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0); |
ba00aab7 |
1287 | aCtx->SetFrameBufferSRGB (false); |
c357e426 |
1288 | } |
1289 | |
f55ba97f |
1290 | // Reset OpenGl aspects state to default to avoid enabling of |
1291 | // backface culling which is not supported in ray-tracing. |
1292 | myWorkspace->ResetAppliedAspect(); |
1293 | |
c357e426 |
1294 | // Ray-tracing polygonal primitive arrays |
bf02aa7d |
1295 | raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx); |
c357e426 |
1296 | |
1297 | // Render upper (top and topmost) OpenGL layers |
a1073ae2 |
1298 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1299 | } |
1300 | } |
1301 | |
1302 | // Redraw 3D scene using OpenGL in standard |
1303 | // mode or in case of ray-tracing failure |
1304 | if (toRenderGL) |
1305 | { |
a1073ae2 |
1306 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo); |
c357e426 |
1307 | |
1308 | // Set flag that scene was redrawn by standard pipeline |
1309 | myWasRedrawnGL = Standard_True; |
1310 | } |
1311 | } |
1312 | |
1313 | //======================================================================= |
1314 | //function : renderTrihedron |
1315 | //purpose : |
1316 | //======================================================================= |
1317 | void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace) |
1318 | { |
c357e426 |
1319 | if (myToShowGradTrihedron) |
1320 | { |
1321 | myGraduatedTrihedron.Render (theWorkspace); |
1322 | } |
1323 | } |
1324 | |
15669413 |
1325 | //======================================================================= |
1326 | //function : renderFrameStats |
1327 | //purpose : |
1328 | //======================================================================= |
1329 | void OpenGl_View::renderFrameStats() |
1330 | { |
1331 | if (myRenderParams.ToShowStats |
1332 | && myRenderParams.CollectedStats != Graphic3d_RenderingParams::PerfCounters_NONE) |
1333 | { |
1334 | myFrameStatsPrs.Update (myWorkspace); |
1335 | myFrameStatsPrs.Render (myWorkspace); |
1336 | } |
1337 | } |
1338 | |
c357e426 |
1339 | // ======================================================================= |
1340 | // function : Invalidate |
1341 | // purpose : |
1342 | // ======================================================================= |
1343 | void OpenGl_View::Invalidate() |
1344 | { |
1345 | myBackBufferRestored = Standard_False; |
1346 | } |
1347 | |
1348 | //======================================================================= |
1349 | //function : renderScene |
1350 | //purpose : |
1351 | //======================================================================= |
bf02aa7d |
1352 | void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, |
1353 | OpenGl_FrameBuffer* theReadDrawFbo, |
a1073ae2 |
1354 | OpenGl_FrameBuffer* theOitAccumFbo, |
bf02aa7d |
1355 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1356 | { |
1357 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
1358 | |
c357e426 |
1359 | // Specify clipping planes in view transformation space |
25c35042 |
1360 | aContext->ChangeClipping().Reset (myClipPlanes); |
3202bf1e |
1361 | if (!myClipPlanes.IsNull() |
1362 | && !myClipPlanes->IsEmpty()) |
c357e426 |
1363 | { |
deb02f86 |
1364 | aContext->ShaderManager()->UpdateClippingState(); |
c357e426 |
1365 | } |
1366 | |
a1073ae2 |
1367 | renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate); |
72f6dc61 |
1368 | aContext->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
c357e426 |
1369 | |
c357e426 |
1370 | // Apply restored view matrix. |
1371 | aContext->ApplyWorldViewMatrix(); |
1372 | |
25c35042 |
1373 | aContext->ChangeClipping().Reset (Handle(Graphic3d_SequenceOfHClipPlane)()); |
3202bf1e |
1374 | if (!myClipPlanes.IsNull() |
1375 | && !myClipPlanes->IsEmpty()) |
deb02f86 |
1376 | { |
1377 | aContext->ShaderManager()->RevertClippingState(); |
deb02f86 |
1378 | } |
c357e426 |
1379 | } |
1380 | |
1381 | // ======================================================================= |
1382 | // function : bindDefaultFbo |
1383 | // purpose : |
1384 | // ======================================================================= |
1385 | void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) |
1386 | { |
1387 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1388 | OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) |
1389 | ? theCustomFbo |
1390 | : (!aCtx->DefaultFrameBuffer().IsNull() |
1391 | && aCtx->DefaultFrameBuffer()->IsValid() |
1392 | ? aCtx->DefaultFrameBuffer().operator->() |
1393 | : NULL); |
1394 | if (anFbo != NULL) |
1395 | { |
1396 | anFbo->BindBuffer (aCtx); |
521b0d7f |
1397 | anFbo->SetupViewport (aCtx); |
c357e426 |
1398 | } |
1399 | else |
1400 | { |
1401 | #if !defined(GL_ES_VERSION_2_0) |
1402 | aCtx->SetReadDrawBuffer (GL_BACK); |
1403 | #else |
1404 | if (aCtx->arbFBO != NULL) |
1405 | { |
1406 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1407 | } |
1408 | #endif |
3bffef55 |
1409 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
1410 | aCtx->ResizeViewport (aViewport); |
c357e426 |
1411 | } |
c357e426 |
1412 | } |
1413 | |
1414 | // ======================================================================= |
1415 | // function : initBlitQuad |
1416 | // purpose : |
1417 | // ======================================================================= |
1418 | OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip) |
1419 | { |
1420 | OpenGl_VertexBuffer* aVerts = NULL; |
1421 | if (!theToFlip) |
1422 | { |
1423 | aVerts = &myFullScreenQuad; |
1424 | if (!aVerts->IsValid()) |
1425 | { |
1426 | OpenGl_Vec4 aQuad[4] = |
1427 | { |
1428 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), |
1429 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), |
1430 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), |
1431 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) |
1432 | }; |
1433 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1434 | } |
1435 | } |
1436 | else |
1437 | { |
1438 | aVerts = &myFullScreenQuadFlip; |
1439 | if (!aVerts->IsValid()) |
1440 | { |
1441 | OpenGl_Vec4 aQuad[4] = |
1442 | { |
1443 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), |
1444 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), |
1445 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), |
1446 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) |
1447 | }; |
1448 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1449 | } |
1450 | } |
1451 | return aVerts; |
1452 | } |
1453 | |
1454 | // ======================================================================= |
1455 | // function : blitBuffers |
1456 | // purpose : |
1457 | // ======================================================================= |
1458 | bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, |
1459 | OpenGl_FrameBuffer* theDrawFbo, |
1460 | const Standard_Boolean theToFlip) |
1461 | { |
1462 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
56689b27 |
1463 | const Standard_Integer aReadSizeX = theReadFbo != NULL ? theReadFbo->GetVPSizeX() : myWindow->Width(); |
1464 | const Standard_Integer aReadSizeY = theReadFbo != NULL ? theReadFbo->GetVPSizeY() : myWindow->Height(); |
1465 | const Standard_Integer aDrawSizeX = theDrawFbo != NULL ? theDrawFbo->GetVPSizeX() : myWindow->Width(); |
1466 | const Standard_Integer aDrawSizeY = theDrawFbo != NULL ? theDrawFbo->GetVPSizeY() : myWindow->Height(); |
c357e426 |
1467 | if (theReadFbo == NULL || aCtx->IsFeedback()) |
1468 | { |
1469 | return false; |
1470 | } |
1471 | else if (theReadFbo == theDrawFbo) |
1472 | { |
1473 | return true; |
1474 | } |
1475 | |
1476 | // clear destination before blitting |
1477 | if (theDrawFbo != NULL |
1478 | && theDrawFbo->IsValid()) |
1479 | { |
1480 | theDrawFbo->BindBuffer (aCtx); |
1481 | } |
1482 | else |
1483 | { |
1484 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
ba00aab7 |
1485 | aCtx->SetFrameBufferSRGB (false); |
c357e426 |
1486 | } |
56689b27 |
1487 | const Standard_Integer aViewport[4] = { 0, 0, aDrawSizeX, aDrawSizeY }; |
1488 | aCtx->ResizeViewport (aViewport); |
1489 | |
c357e426 |
1490 | #if !defined(GL_ES_VERSION_2_0) |
1491 | aCtx->core20fwd->glClearDepth (1.0); |
1492 | #else |
1493 | aCtx->core20fwd->glClearDepthf (1.0f); |
1494 | #endif |
1495 | aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
1496 | |
ba00aab7 |
1497 | const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB(); |
3c4b62a4 |
1498 | if (aCtx->arbFBOBlit != NULL |
ba00aab7 |
1499 | && !toApplyGamma |
1500 | && theReadFbo->NbSamples() != 0) |
c357e426 |
1501 | { |
3c4b62a4 |
1502 | GLbitfield aCopyMask = 0; |
c357e426 |
1503 | theReadFbo->BindReadBuffer (aCtx); |
1504 | if (theDrawFbo != NULL |
1505 | && theDrawFbo->IsValid()) |
1506 | { |
1507 | theDrawFbo->BindDrawBuffer (aCtx); |
3c4b62a4 |
1508 | if (theDrawFbo->HasColor() |
1509 | && theReadFbo->HasColor()) |
1510 | { |
1511 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1512 | } |
1513 | if (theDrawFbo->HasDepth() |
1514 | && theReadFbo->HasDepth()) |
1515 | { |
1516 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1517 | } |
c357e426 |
1518 | } |
1519 | else |
1520 | { |
3c4b62a4 |
1521 | if (theReadFbo->HasColor()) |
1522 | { |
1523 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1524 | } |
1525 | if (theReadFbo->HasDepth()) |
1526 | { |
1527 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1528 | } |
c357e426 |
1529 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
ba00aab7 |
1530 | aCtx->SetFrameBufferSRGB (false); |
c357e426 |
1531 | } |
3c4b62a4 |
1532 | |
c357e426 |
1533 | // we don't copy stencil buffer here... does it matter for performance? |
56689b27 |
1534 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aReadSizeX, aReadSizeY, |
1535 | 0, 0, aDrawSizeX, aDrawSizeY, |
3c4b62a4 |
1536 | aCopyMask, GL_NEAREST); |
7ccf8676 |
1537 | const int anErr = ::glGetError(); |
1538 | if (anErr != GL_NO_ERROR) |
1539 | { |
1540 | // glBlitFramebuffer() might fail in several cases: |
1541 | // - Both FBOs have MSAA and they are samples number does not match. |
1542 | // OCCT checks that this does not happen, |
1543 | // however some graphics drivers provide an option for overriding MSAA. |
1544 | // In this case window MSAA might be non-zero (and application can not check it) |
1545 | // and might not match MSAA of our offscreen FBOs. |
1546 | // - Pixel formats of FBOs do not match. |
1547 | // This also might happen with window has pixel format, |
1548 | // e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion. |
1549 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error #" + anErr + "]\n" |
1550 | + " Please check your graphics driver settings or try updating driver."; |
1551 | if (theReadFbo->NbSamples() != 0) |
1552 | { |
1553 | myToDisableMSAA = true; |
1554 | aMsg += "\n MSAA settings should not be overridden by driver!"; |
1555 | } |
1556 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1557 | GL_DEBUG_TYPE_ERROR, |
1558 | 0, |
1559 | GL_DEBUG_SEVERITY_HIGH, |
1560 | aMsg); |
1561 | } |
1562 | |
c357e426 |
1563 | if (theDrawFbo != NULL |
3c4b62a4 |
1564 | && theDrawFbo->IsValid()) |
c357e426 |
1565 | { |
1566 | theDrawFbo->BindBuffer (aCtx); |
1567 | } |
1568 | else |
1569 | { |
1570 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
ba00aab7 |
1571 | aCtx->SetFrameBufferSRGB (false); |
c357e426 |
1572 | } |
1573 | } |
1574 | else |
c357e426 |
1575 | { |
1576 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1577 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1578 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1ce0716b |
1579 | #if defined(GL_ES_VERSION_2_0) |
1580 | if (!aCtx->IsGlGreaterEqual (3, 0) |
1581 | && !aCtx->extFragDepth) |
1582 | { |
1583 | aCtx->core20fwd->glDisable (GL_DEPTH_TEST); |
1584 | } |
1585 | #endif |
c357e426 |
1586 | |
72f6dc61 |
1587 | aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
c357e426 |
1588 | |
56689b27 |
1589 | const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR; |
1590 | const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR; |
1591 | |
c357e426 |
1592 | OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); |
1593 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1594 | if (aVerts->IsValid() |
ba00aab7 |
1595 | && aManager->BindFboBlitProgram (theReadFbo != NULL ? theReadFbo->NbSamples() : 0, toApplyGamma)) |
c357e426 |
1596 | { |
bf5f0ca2 |
1597 | aCtx->SetSampleAlphaToCoverage (false); |
cc8cbabe |
1598 | theReadFbo->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); |
1599 | if (theReadFbo->ColorTexture()->Sampler()->Parameters()->Filter() != aFilter) |
56689b27 |
1600 | { |
cc8cbabe |
1601 | theReadFbo->ColorTexture()->Sampler()->Parameters()->SetFilter (aFilter); |
56689b27 |
1602 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); |
1603 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); |
1604 | } |
1605 | |
cc8cbabe |
1606 | theReadFbo->DepthStencilTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); |
1607 | if (theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->Filter() != aFilter) |
56689b27 |
1608 | { |
cc8cbabe |
1609 | theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->SetFilter (aFilter); |
56689b27 |
1610 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); |
1611 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); |
1612 | } |
1613 | |
c357e426 |
1614 | aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1615 | |
1616 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1617 | |
1618 | aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
cc8cbabe |
1619 | theReadFbo->DepthStencilTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); |
1620 | theReadFbo->ColorTexture() ->Unbind (aCtx, Graphic3d_TextureUnit_0); |
a521d90d |
1621 | aCtx->BindProgram (NULL); |
c357e426 |
1622 | } |
1623 | else |
1624 | { |
1625 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1626 | + "Error! FBO blitting has failed"; |
3b523c4c |
1627 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1628 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1629 | 0, |
3b523c4c |
1630 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1631 | aMsg); |
1632 | myHasFboBlit = Standard_False; |
1633 | theReadFbo->Release (aCtx.operator->()); |
1634 | return true; |
1635 | } |
1636 | } |
1637 | return true; |
1638 | } |
1639 | |
1640 | // ======================================================================= |
1641 | // function : drawStereoPair |
1642 | // purpose : |
1643 | // ======================================================================= |
3c4b62a4 |
1644 | void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) |
c357e426 |
1645 | { |
3c4b62a4 |
1646 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1647 | bindDefaultFbo (theDrawFbo); |
c357e426 |
1648 | OpenGl_FrameBuffer* aPair[2] = |
1649 | { |
1650 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
1651 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
1652 | }; |
1653 | if (aPair[0] == NULL |
1654 | || aPair[1] == NULL |
1655 | || !myTransientDrawToFront) |
1656 | { |
1657 | aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
1658 | aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; |
1659 | } |
1660 | |
1661 | if (aPair[0] == NULL |
1662 | || aPair[1] == NULL) |
1663 | { |
1664 | return; |
1665 | } |
1666 | |
3c4b62a4 |
1667 | if (aPair[0]->NbSamples() != 0) |
1668 | { |
1669 | // resolve MSAA buffers before drawing |
1670 | if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0) |
1671 | || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0)) |
1672 | { |
82f443b6 |
1673 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1674 | GL_DEBUG_TYPE_ERROR, |
3c4b62a4 |
1675 | 0, |
82f443b6 |
1676 | GL_DEBUG_SEVERITY_HIGH, |
3c4b62a4 |
1677 | "Error! Unable to allocate FBO for blitting stereo pair"); |
1678 | bindDefaultFbo (theDrawFbo); |
1679 | return; |
1680 | } |
1681 | |
1682 | if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False) |
1683 | || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False)) |
1684 | { |
1685 | bindDefaultFbo (theDrawFbo); |
1686 | return; |
1687 | } |
1688 | |
1689 | aPair[0] = myOpenGlFBO .operator->(); |
1690 | aPair[1] = myOpenGlFBO2.operator->(); |
1691 | bindDefaultFbo (theDrawFbo); |
1692 | } |
1693 | |
c357e426 |
1694 | struct |
1695 | { |
1696 | Standard_Integer left; |
1697 | Standard_Integer top; |
1698 | Standard_Integer right; |
1699 | Standard_Integer bottom; |
1700 | Standard_Integer dx() { return right - left; } |
1701 | Standard_Integer dy() { return bottom - top; } |
1702 | } aGeom; |
1703 | |
1704 | myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom); |
1705 | |
1706 | Standard_Boolean toReverse = myRenderParams.ToReverseStereo; |
1707 | const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1; |
1708 | const Standard_Boolean isOddX = aGeom.left % 2 == 1; |
1709 | if (isOddY |
1710 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced |
1711 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1712 | { |
1713 | toReverse = !toReverse; |
1714 | } |
1715 | if (isOddX |
1716 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced |
1717 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1718 | { |
1719 | toReverse = !toReverse; |
1720 | } |
1721 | |
1722 | if (toReverse) |
1723 | { |
1724 | std::swap (aPair[0], aPair[1]); |
1725 | } |
1726 | |
c357e426 |
1727 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1728 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1729 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1730 | |
72f6dc61 |
1731 | aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
c357e426 |
1732 | OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); |
1733 | |
1734 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1735 | if (aVerts->IsValid() |
1736 | && aManager->BindStereoProgram (myRenderParams.StereoMode)) |
1737 | { |
1738 | if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) |
1739 | { |
1740 | OpenGl_Mat4 aFilterL, aFilterR; |
1741 | aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1742 | aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1743 | switch (myRenderParams.AnaglyphFilter) |
1744 | { |
1745 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: |
1746 | { |
1747 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1748 | aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1749 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1750 | break; |
1751 | } |
1752 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: |
1753 | { |
1754 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); |
1755 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); |
1756 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); |
1757 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1758 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); |
1759 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); |
1760 | aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); |
1761 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1762 | break; |
1763 | } |
1764 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: |
1765 | { |
1766 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1767 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1768 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1769 | break; |
1770 | } |
1771 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: |
1772 | { |
1773 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); |
1774 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); |
1775 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); |
1776 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1777 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); |
1778 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); |
1779 | aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); |
1780 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1781 | break; |
1782 | } |
1783 | case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: |
1784 | { |
1785 | aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1786 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1787 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1788 | break; |
1789 | } |
1790 | case Graphic3d_RenderingParams::Anaglyph_UserDefined: |
1791 | { |
1792 | aFilterL = myRenderParams.AnaglyphLeft; |
1793 | aFilterR = myRenderParams.AnaglyphRight; |
1794 | break; |
1795 | } |
1796 | } |
1797 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL); |
1798 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR); |
1799 | } |
1800 | |
cc8cbabe |
1801 | aPair[0]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); |
1802 | aPair[1]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); |
c357e426 |
1803 | aVerts->BindVertexAttrib (aCtx, 0); |
1804 | |
1805 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1806 | |
1807 | aVerts->UnbindVertexAttrib (aCtx, 0); |
cc8cbabe |
1808 | aPair[1]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); |
1809 | aPair[0]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_0); |
c357e426 |
1810 | } |
1811 | else |
1812 | { |
1813 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1814 | + "Error! Anaglyph has failed"; |
3b523c4c |
1815 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1816 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1817 | 0, |
3b523c4c |
1818 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1819 | aMsg); |
1820 | } |
1821 | } |
1822 | |
1823 | // ======================================================================= |
1824 | // function : copyBackToFront |
1825 | // purpose : |
1826 | // ======================================================================= |
a0b49de4 |
1827 | bool OpenGl_View::copyBackToFront() |
c357e426 |
1828 | { |
a0b49de4 |
1829 | myIsImmediateDrawn = Standard_False; |
c357e426 |
1830 | #if !defined(GL_ES_VERSION_2_0) |
a0b49de4 |
1831 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1832 | if (aCtx->core11 == NULL) |
1833 | { |
1834 | return false; |
1835 | } |
c357e426 |
1836 | |
1837 | OpenGl_Mat4 aProjectMat; |
1838 | Graphic3d_TransformUtils::Ortho2D (aProjectMat, |
8613985b |
1839 | 0.0f, static_cast<GLfloat> (myWindow->Width()), |
1840 | 0.0f, static_cast<GLfloat> (myWindow->Height())); |
1841 | |
c357e426 |
1842 | aCtx->WorldViewState.Push(); |
1843 | aCtx->ProjectionState.Push(); |
1844 | |
1845 | aCtx->WorldViewState.SetIdentity(); |
1846 | aCtx->ProjectionState.SetCurrent (aProjectMat); |
1847 | |
1848 | aCtx->ApplyProjectionMatrix(); |
1849 | aCtx->ApplyWorldViewMatrix(); |
1850 | |
8613985b |
1851 | // synchronize FFP state before copying pixels |
1852 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); |
1853 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); |
c357e426 |
1854 | aCtx->DisableFeatures(); |
1855 | |
1856 | switch (aCtx->DrawBuffer()) |
1857 | { |
1858 | case GL_BACK_LEFT: |
1859 | { |
1860 | aCtx->SetReadBuffer (GL_BACK_LEFT); |
1861 | aCtx->SetDrawBuffer (GL_FRONT_LEFT); |
1862 | break; |
1863 | } |
1864 | case GL_BACK_RIGHT: |
1865 | { |
1866 | aCtx->SetReadBuffer (GL_BACK_RIGHT); |
1867 | aCtx->SetDrawBuffer (GL_FRONT_RIGHT); |
1868 | break; |
1869 | } |
1870 | default: |
1871 | { |
1872 | aCtx->SetReadBuffer (GL_BACK); |
1873 | aCtx->SetDrawBuffer (GL_FRONT); |
1874 | break; |
1875 | } |
1876 | } |
1877 | |
a0b49de4 |
1878 | aCtx->core11->glRasterPos2i (0, 0); |
1879 | aCtx->core11->glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR); |
1880 | //aCtx->core11->glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); |
c357e426 |
1881 | |
1882 | aCtx->EnableFeatures(); |
1883 | |
1884 | aCtx->WorldViewState.Pop(); |
1885 | aCtx->ProjectionState.Pop(); |
1886 | aCtx->ApplyProjectionMatrix(); |
1887 | |
1888 | // read/write from front buffer now |
1889 | aCtx->SetReadBuffer (aCtx->DrawBuffer()); |
a0b49de4 |
1890 | return true; |
1891 | #else |
1892 | return false; |
c357e426 |
1893 | #endif |
c357e426 |
1894 | } |
a1073ae2 |
1895 | |
1896 | // ======================================================================= |
1897 | // function : checkOitCompatibility |
1898 | // purpose : |
1899 | // ======================================================================= |
1900 | Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext, |
1901 | const Standard_Boolean theMSAA) |
1902 | { |
1903 | // determine if OIT is supported by current OpenGl context |
1904 | Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT; |
1905 | if (aToDisableOIT) |
1906 | { |
1907 | return Standard_False; |
1908 | } |
1909 | |
1910 | TCollection_ExtendedString aCompatibilityMsg; |
177781da |
1911 | if (theGlContext->hasFloatBuffer == OpenGl_FeatureNotAvailable |
1912 | && theGlContext->hasHalfFloatBuffer == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1913 | { |
1914 | aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n"; |
1915 | } |
177781da |
1916 | if (theMSAA && theGlContext->hasSampleVariables == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1917 | { |
1918 | aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n"; |
1919 | } |
177781da |
1920 | if (theGlContext->hasDrawBuffers == OpenGl_FeatureNotAvailable) |
a1073ae2 |
1921 | { |
1922 | aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n"; |
1923 | } |
1924 | if (aCompatibilityMsg.IsEmpty()) |
1925 | { |
1926 | return Standard_True; |
1927 | } |
1928 | |
1929 | aCompatibilityMsg += " Blended order-independent transparency will not be available.\n"; |
1930 | theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1931 | GL_DEBUG_TYPE_ERROR, |
1932 | 0, |
1933 | GL_DEBUG_SEVERITY_HIGH, |
1934 | aCompatibilityMsg); |
1935 | |
1936 | aToDisableOIT = Standard_True; |
1937 | return Standard_False; |
1938 | } |
1939 | |
1940 | // ======================================================================= |
1941 | // function : chooseOitColorConfiguration |
1942 | // purpose : |
1943 | // ======================================================================= |
1944 | bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext, |
1945 | const Standard_Integer theConfigIndex, |
1946 | OpenGl_ColorFormats& theFormats) |
1947 | { |
1948 | theFormats.Clear(); |
1949 | switch (theConfigIndex) |
1950 | { |
1951 | case 0: // choose best applicable color format combination |
1952 | { |
177781da |
1953 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
1954 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_R16F : GL_R32F); |
a1073ae2 |
1955 | return true; |
1956 | } |
1957 | case 1: // choose non-optimal applicable color format combination |
1958 | { |
177781da |
1959 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
1960 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); |
a1073ae2 |
1961 | return true; |
1962 | } |
1963 | } |
1964 | return false; // color combination does not exist |
1965 | } |
67312b79 |
1966 | |
1967 | // ======================================================================= |
1968 | // function : checkPBRAvailability |
1969 | // purpose : |
1970 | // ======================================================================= |
1971 | Standard_Boolean OpenGl_View::checkPBRAvailability() const |
1972 | { |
1973 | return myWorkspace->GetGlContext()->HasPBR() |
1974 | && !myPBREnvironment.IsNull(); |
1975 | } |
1976 | |
1977 | // ======================================================================= |
1978 | // function : bakePBREnvironment |
1979 | // purpose : |
1980 | // ======================================================================= |
1981 | void OpenGl_View::bakePBREnvironment (const Handle(OpenGl_Context)& theCtx) |
1982 | { |
1983 | const Handle(OpenGl_TextureSet)& aTextureSet = myCubeMapParams->TextureSet (theCtx); |
1984 | if (!aTextureSet.IsNull() |
1985 | && !aTextureSet->IsEmpty()) |
1986 | { |
1987 | myPBREnvironment->Bake (theCtx, |
1988 | aTextureSet->First(), |
1989 | myBackgroundCubeMap->ZIsInverted(), |
1990 | myBackgroundCubeMap->IsTopDown(), |
1991 | myRenderParams.PbrEnvBakingDiffNbSamples, |
1992 | myRenderParams.PbrEnvBakingSpecNbSamples, |
1993 | myRenderParams.PbrEnvBakingProbability); |
1994 | } |
1995 | else |
1996 | { |
1997 | myPBREnvironment->Clear (theCtx); |
1998 | } |
1999 | } |
2000 | |
2001 | // ======================================================================= |
2002 | // function : clearPBREnvironment |
2003 | // purpose : |
2004 | // ======================================================================= |
2005 | void OpenGl_View::clearPBREnvironment (const Handle(OpenGl_Context)& theCtx) |
2006 | { |
2007 | myPBREnvironment->Clear (theCtx); |
2008 | } |
2009 | |
2010 | // ======================================================================= |
2011 | // function : clearPBREnvironment |
2012 | // purpose : |
2013 | // ======================================================================= |
2014 | void OpenGl_View::processPBREnvRequest (const Handle(OpenGl_Context)& theCtx) |
2015 | { |
2016 | if (myPBREnvState == OpenGl_PBREnvState_CREATED) |
2017 | { |
2018 | switch (myPBREnvRequest) |
2019 | { |
2020 | case OpenGl_PBREnvRequest_NONE: return; |
2021 | case OpenGl_PBREnvRequest_BAKE: bakePBREnvironment (theCtx); break; |
2022 | case OpenGl_PBREnvRequest_CLEAR: clearPBREnvironment (theCtx); break; |
2023 | } |
2024 | } |
2025 | myPBREnvRequest = OpenGl_PBREnvRequest_NONE; |
2026 | } |