Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-09-20 |
2 | // Created by: Sergey ZERCHANINOV | |
973c2be1 | 3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
b311480e | 15 | |
c357e426 | 16 | #include <OpenGl_View.hxx> |
5f8b738e | 17 | |
c357e426 | 18 | #include <Aspect_RenderingContext.hxx> |
19 | #include <Aspect_Window.hxx> | |
cfb54c0c | 20 | #include <Aspect_XRSession.hxx> |
c357e426 | 21 | #include <Graphic3d_AspectFillArea3d.hxx> |
22 | #include <Graphic3d_Texture2Dmanual.hxx> | |
23 | #include <Graphic3d_TextureEnv.hxx> | |
24 | #include <Graphic3d_Mat4d.hxx> | |
cfb54c0c | 25 | #include <Image_AlienPixMap.hxx> |
26 | #include <OpenGl_ArbFBO.hxx> | |
1220d98e | 27 | #include <OpenGl_BackgroundArray.hxx> |
bf75be98 | 28 | #include <OpenGl_Context.hxx> |
78c4e836 | 29 | #include <OpenGl_DepthPeeling.hxx> |
c357e426 | 30 | #include <OpenGl_FrameBuffer.hxx> |
30f0ad28 | 31 | #include <OpenGl_GlCore11.hxx> |
32 | #include <OpenGl_GraduatedTrihedron.hxx> | |
392ac980 | 33 | #include <OpenGl_GraphicDriver.hxx> |
30f0ad28 | 34 | #include <OpenGl_ShaderManager.hxx> |
d84e8669 | 35 | #include <OpenGl_ShadowMap.hxx> |
bf75be98 | 36 | #include <OpenGl_Texture.hxx> |
c357e426 | 37 | #include <OpenGl_Window.hxx> |
30f0ad28 | 38 | #include <OpenGl_Workspace.hxx> |
f5b72419 | 39 | #include <OSD_Parallel.hxx> |
c357e426 | 40 | #include <Standard_CLocaleSentry.hxx> |
2166f0fa | 41 | |
f5b72419 | 42 | #include "../Graphic3d/Graphic3d_Structure.pxx" |
cfb54c0c | 43 | #include "../Textures/Textures_EnvLUT.pxx" |
44 | ||
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 | } | |
1220d98e | 71 | |
72 | //! Chooses compatible internal color format for OIT frame buffer. | |
73 | static bool chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext, | |
74 | const Standard_Integer theConfigIndex, | |
75 | OpenGl_ColorFormats& theFormats) | |
76 | { | |
77 | theFormats.Clear(); | |
78 | switch (theConfigIndex) | |
79 | { | |
80 | case 0: // choose best applicable color format combination | |
81 | { | |
82 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); | |
83 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_R16F : GL_R32F); | |
84 | return true; | |
85 | } | |
86 | case 1: // choose non-optimal applicable color format combination | |
87 | { | |
88 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); | |
89 | theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); | |
90 | return true; | |
91 | } | |
92 | } | |
93 | return false; // color combination does not exist | |
94 | } | |
cfb54c0c | 95 | } |
f5b72419 | 96 | |
92efcf78 | 97 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView) |
98 | ||
c357e426 | 99 | // ======================================================================= |
100 | // function : Constructor | |
101 | // purpose : | |
102 | // ======================================================================= | |
103 | OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr, | |
104 | const Handle(OpenGl_GraphicDriver)& theDriver, | |
105 | const Handle(OpenGl_Caps)& theCaps, | |
c357e426 | 106 | OpenGl_StateCounter* theCounter) |
107 | : Graphic3d_CView (theMgr), | |
108 | myDriver (theDriver.operator->()), | |
109 | myCaps (theCaps), | |
c357e426 | 110 | myWasRedrawnGL (Standard_False), |
c357e426 | 111 | myToShowGradTrihedron (false), |
f5b72419 | 112 | myZLayers (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1), |
c357e426 | 113 | myStateCounter (theCounter), |
992ed6b3 | 114 | myCurrLightSourceState (theCounter->Increment()), |
115 | myLightsRevision (0), | |
0b0320e7 | 116 | myLastLightSourceState (0, 0), |
ba00aab7 | 117 | mySRgbState (-1), |
118 | myFboColorFormat (GL_SRGB8_ALPHA8), // note that GL_SRGB8 is not required to be renderable, unlike GL_RGB8, GL_RGBA8, GL_SRGB8_ALPHA8 | |
3c4b62a4 | 119 | myFboDepthFormat (GL_DEPTH24_STENCIL8), |
120 | myToFlipOutput (Standard_False), | |
b40cdc2b | 121 | // |
c357e426 | 122 | myFrameCounter (0), |
123 | myHasFboBlit (Standard_True), | |
a1073ae2 | 124 | myToDisableOIT (Standard_False), |
125 | myToDisableOITMSAA (Standard_False), | |
7ccf8676 | 126 | myToDisableMSAA (Standard_False), |
c357e426 | 127 | myTransientDrawToFront (Standard_True), |
128 | myBackBufferRestored (Standard_False), | |
129 | myIsImmediateDrawn (Standard_False), | |
956d9157 | 130 | myTextureParams (new OpenGl_Aspects()), |
131 | myCubeMapParams (new OpenGl_Aspects()), | |
132 | myColoredQuadParams (new OpenGl_Aspects()), | |
133 | myPBREnvState (OpenGl_PBREnvState_NONEXISTENT), | |
134 | myPBREnvRequest (Standard_False), | |
91c60b57 | 135 | // ray-tracing fields initialization |
c357e426 | 136 | myRaytraceInitStatus (OpenGl_RT_NONE), |
137 | myIsRaytraceDataValid (Standard_False), | |
91c60b57 | 138 | myIsRaytraceWarnTextures (Standard_False), |
f5b72419 | 139 | myRaytraceBVHBuilder (new BVH_BinnedBuilder<Standard_ShortReal, 3, BVH_Constants_NbBinsBest> (BVH_Constants_LeafNodeSizeAverage, |
140 | BVH_Constants_MaxTreeDepth, | |
141 | Standard_False, | |
142 | OSD_Parallel::NbLogicalProcessors() + 1)), | |
143 | myRaytraceSceneRadius (0.0f), | |
144 | myRaytraceSceneEpsilon (1.0e-6f), | |
91c60b57 | 145 | myToUpdateEnvironmentMap (Standard_False), |
b27ab03d | 146 | myRaytraceLayerListState (0), |
147 | myPrevCameraApertureRadius(0.f), | |
148 | myPrevCameraFocalPlaneDist(0.f) | |
2166f0fa | 149 | { |
077a220c | 150 | for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i) |
151 | { | |
152 | myBackgrounds[i] = new OpenGl_BackgroundArray(Graphic3d_TypeOfBackground(i)); | |
153 | } | |
154 | ||
c357e426 | 155 | myWorkspace = new OpenGl_Workspace (this, NULL); |
2166f0fa | 156 | |
06d40093 | 157 | Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TypeOfLightSource_Ambient); |
992ed6b3 | 158 | aLight->SetColor (Quantity_NOC_WHITE); |
8445efca | 159 | myLights = new Graphic3d_LightSet(); |
992ed6b3 | 160 | myNoShadingLight = new Graphic3d_LightSet(); |
161 | myNoShadingLight->Add (aLight); | |
016e5959 | 162 | |
a1073ae2 | 163 | myMainSceneFbos[0] = new OpenGl_FrameBuffer(); |
164 | myMainSceneFbos[1] = new OpenGl_FrameBuffer(); | |
165 | myMainSceneFbosOit[0] = new OpenGl_FrameBuffer(); | |
166 | myMainSceneFbosOit[1] = new OpenGl_FrameBuffer(); | |
167 | myImmediateSceneFbos[0] = new OpenGl_FrameBuffer(); | |
168 | myImmediateSceneFbos[1] = new OpenGl_FrameBuffer(); | |
169 | myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer(); | |
170 | myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer(); | |
b40cdc2b | 171 | myXrSceneFbo = new OpenGl_FrameBuffer(); |
a1073ae2 | 172 | myOpenGlFBO = new OpenGl_FrameBuffer(); |
173 | myOpenGlFBO2 = new OpenGl_FrameBuffer(); | |
174 | myRaytraceFBO1[0] = new OpenGl_FrameBuffer(); | |
175 | myRaytraceFBO1[1] = new OpenGl_FrameBuffer(); | |
176 | myRaytraceFBO2[0] = new OpenGl_FrameBuffer(); | |
177 | myRaytraceFBO2[1] = new OpenGl_FrameBuffer(); | |
78c4e836 | 178 | myDepthPeelingFbos = new OpenGl_DepthPeeling(); |
d84e8669 | 179 | myShadowMaps = new OpenGl_ShadowMapArray(); |
c357e426 | 180 | } |
181 | ||
182 | // ======================================================================= | |
183 | // function : Destructor | |
184 | // purpose : | |
185 | // ======================================================================= | |
0b0320e7 | 186 | OpenGl_View::~OpenGl_View() |
2166f0fa | 187 | { |
bf75be98 | 188 | ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context |
077a220c | 189 | for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i) |
190 | { | |
191 | OpenGl_Element::Destroy(NULL, myBackgrounds[i]); | |
192 | } | |
193 | ||
0b0320e7 | 194 | OpenGl_Element::Destroy (NULL, myTextureParams); |
077a220c | 195 | OpenGl_Element::Destroy (NULL, myCubeMapParams); |
956d9157 | 196 | OpenGl_Element::Destroy (NULL, myColoredQuadParams); |
bf75be98 | 197 | } |
198 | ||
c357e426 | 199 | // ======================================================================= |
ba00aab7 | 200 | // function : releaseSrgbResources |
c357e426 | 201 | // purpose : |
202 | // ======================================================================= | |
ba00aab7 | 203 | void OpenGl_View::releaseSrgbResources (const Handle(OpenGl_Context)& theCtx) |
bf75be98 | 204 | { |
ba00aab7 | 205 | myRenderParams.RebuildRayTracingShaders = true; |
30f0ad28 | 206 | |
bf75be98 | 207 | if (!myTextureEnv.IsNull()) |
208 | { | |
ad67e367 | 209 | if (!theCtx.IsNull()) |
cc8cbabe | 210 | { |
ad67e367 | 211 | for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next()) |
212 | { | |
213 | theCtx->DelayedRelease (aTextureIter.ChangeValue()); | |
214 | aTextureIter.ChangeValue().Nullify(); | |
215 | } | |
cc8cbabe | 216 | } |
bf75be98 | 217 | myTextureEnv.Nullify(); |
218 | } | |
0b0320e7 | 219 | |
220 | if (myTextureParams != NULL) | |
221 | { | |
ad67e367 | 222 | myTextureParams->Release (theCtx.get()); |
0b0320e7 | 223 | } |
077a220c | 224 | |
225 | if (myCubeMapParams != NULL) | |
0b0320e7 | 226 | { |
077a220c | 227 | myCubeMapParams->Release (theCtx.get()); |
0b0320e7 | 228 | } |
077a220c | 229 | |
230 | for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i) | |
bf75be98 | 231 | { |
077a220c | 232 | if (myBackgrounds[i] != NULL) |
233 | { | |
234 | myBackgrounds[i]->Release (theCtx.get()); | |
235 | } | |
bf75be98 | 236 | } |
91c60b57 | 237 | |
ad67e367 | 238 | myMainSceneFbos[0] ->Release (theCtx.get()); |
239 | myMainSceneFbos[1] ->Release (theCtx.get()); | |
240 | myMainSceneFbosOit[0] ->Release (theCtx.get()); | |
241 | myMainSceneFbosOit[1] ->Release (theCtx.get()); | |
242 | myImmediateSceneFbos[0] ->Release (theCtx.get()); | |
243 | myImmediateSceneFbos[1] ->Release (theCtx.get()); | |
244 | myImmediateSceneFbosOit[0]->Release (theCtx.get()); | |
245 | myImmediateSceneFbosOit[1]->Release (theCtx.get()); | |
b40cdc2b | 246 | myXrSceneFbo ->Release (theCtx.get()); |
78c4e836 | 247 | myDepthPeelingFbos ->Release (theCtx.get()); |
ad67e367 | 248 | myOpenGlFBO ->Release (theCtx.get()); |
249 | myOpenGlFBO2 ->Release (theCtx.get()); | |
250 | myFullScreenQuad .Release (theCtx.get()); | |
251 | myFullScreenQuadFlip .Release (theCtx.get()); | |
d84e8669 | 252 | myShadowMaps->Release (theCtx.get()); |
c357e426 | 253 | |
ba00aab7 | 254 | // Technically we should also re-initialize all sRGB/RGB8 color textures. |
255 | // But for now consider this sRGB disabling/enabling to be done at application start-up | |
256 | // and re-create dynamically only frame buffers. | |
257 | } | |
258 | ||
259 | // ======================================================================= | |
260 | // function : ReleaseGlResources | |
261 | // purpose : | |
262 | // ======================================================================= | |
263 | void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) | |
264 | { | |
265 | myGraduatedTrihedron.Release (theCtx.get()); | |
266 | myFrameStatsPrs.Release (theCtx.get()); | |
267 | ||
268 | releaseSrgbResources (theCtx); | |
269 | ||
91c60b57 | 270 | releaseRaytraceResources (theCtx); |
67312b79 | 271 | |
272 | if (!myPBREnvironment.IsNull()) | |
273 | { | |
274 | myPBREnvironment->Release (theCtx.get()); | |
275 | } | |
b40cdc2b | 276 | ReleaseXR(); |
bf75be98 | 277 | } |
2166f0fa | 278 | |
c357e426 | 279 | // ======================================================================= |
280 | // function : Remove | |
281 | // purpose : | |
282 | // ======================================================================= | |
283 | void OpenGl_View::Remove() | |
bf75be98 | 284 | { |
c357e426 | 285 | if (IsRemoved()) |
bf75be98 | 286 | { |
c357e426 | 287 | return; |
bf75be98 | 288 | } |
289 | ||
c357e426 | 290 | myDriver->RemoveView (this); |
291 | myWindow.Nullify(); | |
292 | ||
293 | Graphic3d_CView::Remove(); | |
294 | } | |
295 | ||
7c3ef2f7 | 296 | // ======================================================================= |
297 | // function : SetLocalOrigin | |
298 | // purpose : | |
299 | // ======================================================================= | |
300 | void OpenGl_View::SetLocalOrigin (const gp_XYZ& theOrigin) | |
301 | { | |
302 | myLocalOrigin = theOrigin; | |
303 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
304 | if (!aCtx.IsNull()) | |
305 | { | |
306 | aCtx->ShaderManager()->SetLocalOrigin (theOrigin); | |
307 | } | |
308 | } | |
309 | ||
c357e426 | 310 | // ======================================================================= |
311 | // function : SetTextureEnv | |
312 | // purpose : | |
313 | // ======================================================================= | |
314 | void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv) | |
315 | { | |
316 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
317 | if (!aCtx.IsNull() && !myTextureEnv.IsNull()) | |
318 | { | |
cc8cbabe | 319 | for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next()) |
320 | { | |
321 | aCtx->DelayedRelease (aTextureIter.ChangeValue()); | |
322 | aTextureIter.ChangeValue().Nullify(); | |
323 | } | |
c357e426 | 324 | } |
325 | ||
326 | myToUpdateEnvironmentMap = Standard_True; | |
327 | myTextureEnvData = theTextureEnv; | |
328 | myTextureEnv.Nullify(); | |
329 | initTextureEnv (aCtx); | |
330 | } | |
331 | ||
332 | // ======================================================================= | |
333 | // function : initTextureEnv | |
334 | // purpose : | |
335 | // ======================================================================= | |
336 | void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext) | |
337 | { | |
338 | if (myTextureEnvData.IsNull() | |
339 | || theContext.IsNull() | |
340 | || !theContext->MakeCurrent()) | |
bf75be98 | 341 | { |
342 | return; | |
343 | } | |
344 | ||
72f6dc61 | 345 | Handle(OpenGl_Texture) aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams()); |
faff3767 | 346 | if (Handle(Image_PixMap) anImage = myTextureEnvData->GetImage (theContext->SupportedTextureFormats())) |
c357e426 | 347 | { |
ba00aab7 | 348 | aTextureEnv->Init (theContext, *anImage, myTextureEnvData->Type(), true); |
c357e426 | 349 | } |
72f6dc61 | 350 | myTextureEnv = new OpenGl_TextureSet (aTextureEnv); |
351 | myTextureEnv->ChangeTextureSetBits() = Graphic3d_TextureSetBits_BaseColor; | |
c357e426 | 352 | } |
e276548b | 353 | |
c357e426 | 354 | // ======================================================================= |
355 | // function : SetImmediateModeDrawToFront | |
356 | // purpose : | |
357 | // ======================================================================= | |
358 | Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) | |
359 | { | |
360 | const Standard_Boolean aPrevMode = myTransientDrawToFront; | |
361 | myTransientDrawToFront = theDrawToFrontBuffer; | |
362 | return aPrevMode; | |
e276548b | 363 | } |
364 | ||
1220d98e | 365 | // ======================================================================= |
366 | // function : Window | |
367 | // purpose : | |
368 | // ======================================================================= | |
369 | Handle(Aspect_Window) OpenGl_View::Window() const | |
370 | { | |
371 | return myWindow->PlatformWindow(); | |
372 | } | |
373 | ||
c357e426 | 374 | // ======================================================================= |
375 | // function : SetWindow | |
376 | // purpose : | |
377 | // ======================================================================= | |
378 | void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow, | |
a521d90d | 379 | const Aspect_RenderingContext theContext) |
e276548b | 380 | { |
c357e426 | 381 | myWindow = myDriver->CreateRenderWindow (theWindow, theContext); |
382 | Standard_ASSERT_RAISE (!myWindow.IsNull(), | |
383 | "OpenGl_View::SetWindow, " | |
384 | "Failed to create OpenGl window."); | |
e276548b | 385 | |
c357e426 | 386 | myWorkspace = new OpenGl_Workspace (this, myWindow); |
387 | myWorldViewProjState.Reset(); | |
91c60b57 | 388 | myToUpdateEnvironmentMap = Standard_True; |
c357e426 | 389 | myHasFboBlit = Standard_True; |
390 | Invalidate(); | |
391 | ||
392 | // Environment texture resource does not support lazy initialization. | |
393 | initTextureEnv (myWorkspace->GetGlContext()); | |
394 | } | |
395 | ||
396 | // ======================================================================= | |
397 | // function : Resized | |
398 | // purpose : | |
399 | // ======================================================================= | |
400 | void OpenGl_View::Resized() | |
401 | { | |
402 | if (myWindow.IsNull()) | |
403 | return; | |
404 | ||
405 | myWindow->Resize(); | |
406 | } | |
407 | ||
c357e426 | 408 | // ======================================================================= |
409 | // function : SetMinMaxValuesCallback | |
410 | // purpose : | |
411 | // ======================================================================= | |
412 | static void SetMinMaxValuesCallback (Graphic3d_CView* theView) | |
413 | { | |
414 | OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView); | |
415 | if (aView == NULL) | |
416 | return; | |
417 | ||
418 | Bnd_Box aBox = theView->MinMaxValues(); | |
419 | if (!aBox.IsVoid()) | |
2166f0fa | 420 | { |
c357e426 | 421 | gp_Pnt aMin = aBox.CornerMin(); |
422 | gp_Pnt aMax = aBox.CornerMax(); | |
423 | ||
424 | Graphic3d_Vec3 aMinVec ((Standard_ShortReal )aMin.X(), (Standard_ShortReal )aMin.Y(), (Standard_ShortReal )aMin.Z()); | |
425 | Graphic3d_Vec3 aMaxVec ((Standard_ShortReal )aMax.X(), (Standard_ShortReal )aMax.Y(), (Standard_ShortReal )aMax.Z()); | |
426 | aView->GraduatedTrihedronMinMaxValues (aMinVec, aMaxVec); | |
2166f0fa SK |
427 | } |
428 | } | |
429 | ||
c357e426 | 430 | // ======================================================================= |
431 | // function : GraduatedTrihedronDisplay | |
432 | // purpose : | |
433 | // ======================================================================= | |
434 | void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData) | |
435 | { | |
436 | myGTrihedronData = theTrihedronData; | |
1b5eb2be | 437 | myGTrihedronData.SetCubicAxesCallback (SetMinMaxValuesCallback); |
c357e426 | 438 | myGraduatedTrihedron.SetValues (myGTrihedronData); |
439 | myToShowGradTrihedron = true; | |
440 | } | |
2166f0fa | 441 | |
c357e426 | 442 | // ======================================================================= |
443 | // function : GraduatedTrihedronErase | |
444 | // purpose : | |
445 | // ======================================================================= | |
446 | void OpenGl_View::GraduatedTrihedronErase() | |
2166f0fa | 447 | { |
c357e426 | 448 | myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->()); |
449 | myToShowGradTrihedron = false; | |
2166f0fa SK |
450 | } |
451 | ||
c357e426 | 452 | // ======================================================================= |
453 | // function : GraduatedTrihedronMinMaxValues | |
454 | // purpose : | |
455 | // ======================================================================= | |
456 | void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax) | |
457 | { | |
458 | myGraduatedTrihedron.SetMinMax (theMin, theMax); | |
459 | } | |
2166f0fa | 460 | |
c357e426 | 461 | // ======================================================================= |
462 | // function : BufferDump | |
463 | // purpose : | |
464 | // ======================================================================= | |
465 | Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType) | |
466 | { | |
38d90bb3 | 467 | if (theBufferType != Graphic3d_BT_RGB_RayTraceHdrLeft) |
468 | { | |
469 | return myWorkspace->BufferDump(myFBO, theImage, theBufferType); | |
470 | } | |
471 | ||
472 | if (!myRaytraceParameters.AdaptiveScreenSampling) | |
473 | { | |
474 | return myWorkspace->BufferDump(myAccumFrames % 2 ? myRaytraceFBO2[0] : myRaytraceFBO1[0], theImage, theBufferType); | |
475 | } | |
476 | ||
477 | #if defined(GL_ES_VERSION_2_0) | |
478 | return false; | |
479 | #else | |
480 | if (theImage.Format() != Image_Format_RGBF) | |
481 | { | |
482 | return false; | |
483 | } | |
484 | ||
485 | const GLuint aW = myRaytraceOutputTexture[0]->SizeX(); | |
486 | const GLuint aH = myRaytraceOutputTexture[0]->SizeY(); | |
487 | if (aW / 3 != theImage.SizeX() || aH / 2 != theImage.SizeY()) | |
488 | { | |
489 | return false; | |
490 | } | |
491 | ||
492 | std::vector<GLfloat> aValues; | |
493 | try | |
494 | { | |
495 | aValues.resize (aW * aH); | |
496 | } | |
497 | catch (const std::bad_alloc&) | |
498 | { | |
499 | return false; | |
500 | } | |
501 | ||
502 | glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[0]->TextureId()); | |
503 | glGetTexImage (GL_TEXTURE_RECTANGLE, 0, OpenGl_TextureFormat::Create<GLfloat, 1>().Format(), GL_FLOAT, &aValues[0]); | |
504 | glBindTexture (GL_TEXTURE_RECTANGLE, 0); | |
505 | for (unsigned int aRow = 0; aRow < aH; aRow += 2) | |
506 | { | |
507 | for (unsigned int aCol = 0; aCol < aW; aCol += 3) | |
508 | { | |
509 | float* anImageValue = theImage.ChangeValue<float[3]> ((aH - aRow) / 2 - 1, aCol / 3); | |
510 | float aInvNbSamples = 1.f / aValues[aRow * aW + aCol + aW]; | |
511 | anImageValue[0] = aValues[aRow * aW + aCol] * aInvNbSamples; | |
512 | anImageValue[1] = aValues[aRow * aW + aCol + 1] * aInvNbSamples; | |
513 | anImageValue[2] = aValues[aRow * aW + aCol + 1 + aW] * aInvNbSamples; | |
514 | } | |
515 | } | |
516 | ||
517 | return true; | |
518 | #endif | |
c357e426 | 519 | } |
520 | ||
c357e426 | 521 | // ======================================================================= |
522 | // function : GradientBackground | |
523 | // purpose : | |
524 | // ======================================================================= | |
525 | Aspect_GradientBackground OpenGl_View::GradientBackground() const | |
526 | { | |
527 | Quantity_Color aColor1, aColor2; | |
077a220c | 528 | aColor1.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).r(), |
529 | myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).g(), | |
530 | myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).b(), Quantity_TOC_RGB); | |
531 | aColor2.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).r(), | |
532 | myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).g(), | |
533 | myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).b(), Quantity_TOC_RGB); | |
534 | return Aspect_GradientBackground (aColor1, aColor2, myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod()); | |
c357e426 | 535 | } |
2166f0fa | 536 | |
c357e426 | 537 | // ======================================================================= |
538 | // function : SetGradientBackground | |
539 | // purpose : | |
540 | // ======================================================================= | |
541 | void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground) | |
2166f0fa | 542 | { |
c357e426 | 543 | Quantity_Color aColor1, aColor2; |
544 | theBackground.Colors (aColor1, aColor2); | |
077a220c | 545 | myBackgrounds[Graphic3d_TOB_GRADIENT]->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod()); |
956d9157 | 546 | if (theBackground.BgGradientFillMethod() >= Aspect_GradientFillMethod_Corner1 |
547 | && theBackground.BgGradientFillMethod() <= Aspect_GradientFillMethod_Corner4) | |
548 | { | |
549 | if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext()) | |
550 | { | |
551 | myColoredQuadParams->Aspect()->SetShaderProgram(aCtx->ShaderManager()->GetColoredQuadProgram()); | |
552 | myColoredQuadParams->Aspect()->ShaderProgram()->PushVariableVec3 ("uColor1", aColor1.Rgb()); | |
553 | myColoredQuadParams->Aspect()->ShaderProgram()->PushVariableVec3 ("uColor2", aColor2.Rgb()); | |
554 | } | |
555 | } | |
077a220c | 556 | myBackgroundType = Graphic3d_TOB_GRADIENT; |
c357e426 | 557 | } |
558 | ||
559 | // ======================================================================= | |
560 | // function : SetBackgroundImage | |
561 | // purpose : | |
562 | // ======================================================================= | |
99289bed | 563 | void OpenGl_View::SetBackgroundImage (const Handle(Graphic3d_TextureMap)& theTextureMap, |
564 | Standard_Boolean theToUpdatePBREnv) | |
c357e426 | 565 | { |
3e9cb806 | 566 | Handle(Graphic3d_TextureMap) aNewMap = theTextureMap; |
99289bed | 567 | if (theTextureMap.IsNull() |
568 | || !theTextureMap->IsDone()) | |
3e9cb806 | 569 | { |
570 | if (!theTextureMap.IsNull()) | |
571 | { | |
572 | Message::SendFail ("Error: unable to set image background"); | |
573 | } | |
574 | aNewMap.Nullify(); | |
575 | } | |
576 | ||
577 | Handle(Graphic3d_CubeMap) aCubeMap = Handle(Graphic3d_CubeMap)::DownCast (aNewMap); | |
578 | if (theToUpdatePBREnv) | |
579 | { | |
580 | // update PBR environment | |
581 | const TCollection_AsciiString anIdOld = !myCubeMapIBL.IsNull() | |
582 | ? myCubeMapIBL->GetId() | |
583 | : TCollection_AsciiString(); | |
584 | const TCollection_AsciiString anIdNew = !aCubeMap.IsNull() | |
585 | ? aCubeMap->GetId() | |
586 | : TCollection_AsciiString(); | |
587 | if (anIdNew != anIdOld) | |
588 | { | |
589 | myPBREnvRequest = true; | |
590 | } | |
591 | myCubeMapIBL = aCubeMap; | |
592 | } | |
593 | ||
594 | if (aNewMap.IsNull()) | |
99289bed | 595 | { |
596 | if (myBackgroundType == Graphic3d_TOB_TEXTURE | |
597 | || myBackgroundType == Graphic3d_TOB_CUBEMAP) | |
598 | { | |
599 | myBackgroundType = Graphic3d_TOB_NONE; | |
99289bed | 600 | } |
601 | return; | |
602 | } | |
603 | ||
c357e426 | 604 | Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d(); |
3e9cb806 | 605 | Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (aNewMap); |
c357e426 | 606 | anAspect->SetInteriorStyle (Aspect_IS_SOLID); |
7fd4958d | 607 | anAspect->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided); |
13b36bb1 | 608 | anAspect->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit); |
99289bed | 609 | anAspect->SetTextureSet (aTextureSet); |
610 | anAspect->SetTextureMapOn (true); | |
611 | ||
3e9cb806 | 612 | if (Handle(Graphic3d_Texture2D) aTextureMap = Handle(Graphic3d_Texture2D)::DownCast (aNewMap)) |
2166f0fa | 613 | { |
99289bed | 614 | myTextureParams->SetAspect (anAspect); |
615 | myBackgroundType = Graphic3d_TOB_TEXTURE; | |
616 | myBackgroundImage = aTextureMap; | |
617 | return; | |
2166f0fa | 618 | } |
99289bed | 619 | |
3e9cb806 | 620 | if (!aCubeMap.IsNull()) |
2166f0fa | 621 | { |
99289bed | 622 | aCubeMap->SetMipmapsGeneration (Standard_True); |
623 | if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext()) | |
624 | { | |
625 | anAspect->SetShaderProgram (aCtx->ShaderManager()->GetBgCubeMapProgram()); | |
626 | } | |
627 | ||
628 | myCubeMapParams->SetAspect (anAspect); | |
629 | ||
630 | const OpenGl_Aspects* anAspectsBackup = myWorkspace->SetAspects (myCubeMapParams); | |
631 | myWorkspace->ApplyAspects(); | |
632 | myWorkspace->SetAspects (anAspectsBackup); | |
633 | myWorkspace->ApplyAspects(); | |
634 | ||
635 | myBackgroundType = Graphic3d_TOB_CUBEMAP; | |
3e9cb806 | 636 | myCubeMapBackground = aCubeMap; |
c357e426 | 637 | return; |
638 | } | |
2166f0fa | 639 | |
99289bed | 640 | throw Standard_ProgramError ("OpenGl_View::SetBackgroundImage() - invalid texture map set for background"); |
c357e426 | 641 | } |
2166f0fa | 642 | |
c357e426 | 643 | // ======================================================================= |
3e9cb806 | 644 | // function : SetImageBasedLighting |
c357e426 | 645 | // purpose : |
646 | // ======================================================================= | |
3e9cb806 | 647 | void OpenGl_View::SetImageBasedLighting (Standard_Boolean theToEnableIBL) |
c357e426 | 648 | { |
3e9cb806 | 649 | if (!theToEnableIBL |
650 | || myBackgroundType != Graphic3d_TOB_CUBEMAP) | |
651 | { | |
652 | if (!myCubeMapIBL.IsNull()) | |
653 | { | |
654 | myPBREnvRequest = true; | |
655 | myCubeMapIBL.Nullify(); | |
656 | } | |
657 | return; | |
658 | } | |
659 | ||
660 | const TCollection_AsciiString anIdOld = !myCubeMapIBL.IsNull() | |
661 | ? myCubeMapIBL->GetId() | |
662 | : TCollection_AsciiString(); | |
663 | const TCollection_AsciiString anIdNew = !myCubeMapBackground.IsNull() | |
664 | ? myCubeMapBackground->GetId() | |
665 | : TCollection_AsciiString(); | |
666 | if (anIdNew != anIdOld) | |
667 | { | |
668 | myPBREnvRequest = true; | |
669 | } | |
670 | myCubeMapIBL = myCubeMapBackground; | |
2166f0fa SK |
671 | } |
672 | ||
c357e426 | 673 | // ======================================================================= |
3e9cb806 | 674 | // function : BackgroundImageStyle |
c357e426 | 675 | // purpose : |
676 | // ======================================================================= | |
3e9cb806 | 677 | Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const |
c357e426 | 678 | { |
3e9cb806 | 679 | return myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod(); |
077a220c | 680 | } |
681 | ||
682 | // ======================================================================= | |
3e9cb806 | 683 | // function : SetBackgroundImageStyle |
077a220c | 684 | // purpose : |
685 | // ======================================================================= | |
3e9cb806 | 686 | void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle) |
077a220c | 687 | { |
3e9cb806 | 688 | myBackgrounds[Graphic3d_TOB_TEXTURE]->SetTextureFillMethod (theFillStyle); |
077a220c | 689 | } |
67312b79 | 690 | |
691 | // ======================================================================= | |
692 | // function : SpecIBLMapLevels | |
693 | // purpose : | |
694 | // ======================================================================= | |
695 | unsigned int OpenGl_View::SpecIBLMapLevels() const | |
696 | { | |
697 | return myPBREnvironment.IsNull() ? 0 : myPBREnvironment->SpecMapLevelsNumber(); | |
698 | } | |
2166f0fa | 699 | |
c357e426 | 700 | //======================================================================= |
1c728f2d | 701 | //function : InsertLayerBefore |
c357e426 | 702 | //purpose : |
703 | //======================================================================= | |
1c728f2d | 704 | void OpenGl_View::InsertLayerBefore (const Graphic3d_ZLayerId theLayerId, |
077a220c | 705 | const Graphic3d_ZLayerSettings& theSettings, |
706 | const Graphic3d_ZLayerId theLayerAfter) | |
2166f0fa | 707 | { |
1c728f2d | 708 | myZLayers.InsertLayerBefore (theLayerId, theSettings, theLayerAfter); |
709 | } | |
710 | ||
711 | //======================================================================= | |
712 | //function : InsertLayerAfter | |
713 | //purpose : | |
714 | //======================================================================= | |
715 | void OpenGl_View::InsertLayerAfter (const Graphic3d_ZLayerId theLayerId, | |
077a220c | 716 | const Graphic3d_ZLayerSettings& theSettings, |
717 | const Graphic3d_ZLayerId theLayerBefore) | |
1c728f2d | 718 | { |
719 | myZLayers.InsertLayerAfter (theLayerId, theSettings, theLayerBefore); | |
2166f0fa SK |
720 | } |
721 | ||
c357e426 | 722 | //======================================================================= |
723 | //function : RemoveZLayer | |
724 | //purpose : | |
725 | //======================================================================= | |
726 | void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId) | |
727 | { | |
728 | myZLayers.RemoveLayer (theLayerId); | |
729 | } | |
2166f0fa | 730 | |
c357e426 | 731 | //======================================================================= |
732 | //function : SetZLayerSettings | |
733 | //purpose : | |
734 | //======================================================================= | |
735 | void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId theLayerId, | |
736 | const Graphic3d_ZLayerSettings& theSettings) | |
2166f0fa | 737 | { |
c357e426 | 738 | myZLayers.SetLayerSettings (theLayerId, theSettings); |
2166f0fa SK |
739 | } |
740 | ||
50d06d8f | 741 | //======================================================================= |
742 | //function : ZLayerMax | |
743 | //purpose : | |
744 | //======================================================================= | |
745 | Standard_Integer OpenGl_View::ZLayerMax() const | |
746 | { | |
747 | Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default; | |
1c728f2d | 748 | for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myZLayers.Layers()); aLayerIter.More(); aLayerIter.Next()) |
50d06d8f | 749 | { |
1c728f2d | 750 | aLayerMax = Max (aLayerMax, aLayerIter.Value()->LayerId()); |
50d06d8f | 751 | } |
50d06d8f | 752 | return aLayerMax; |
753 | } | |
754 | ||
755 | //======================================================================= | |
1c728f2d | 756 | //function : Layers |
757 | //purpose : | |
758 | //======================================================================= | |
759 | const NCollection_List<Handle(Graphic3d_Layer)>& OpenGl_View::Layers() const | |
760 | { | |
761 | return myZLayers.Layers(); | |
762 | } | |
763 | ||
764 | //======================================================================= | |
765 | //function : Layer | |
50d06d8f | 766 | //purpose : |
767 | //======================================================================= | |
1c728f2d | 768 | Handle(Graphic3d_Layer) OpenGl_View::Layer (const Graphic3d_ZLayerId theLayerId) const |
50d06d8f | 769 | { |
1c728f2d | 770 | Handle(Graphic3d_Layer) aLayer; |
771 | if (theLayerId != Graphic3d_ZLayerId_UNKNOWN) | |
50d06d8f | 772 | { |
1c728f2d | 773 | myZLayers.LayerIDs().Find (theLayerId, aLayer); |
50d06d8f | 774 | } |
1c728f2d | 775 | return aLayer; |
50d06d8f | 776 | } |
777 | ||
778 | //======================================================================= | |
1c728f2d | 779 | //function : MinMaxValues |
50d06d8f | 780 | //purpose : |
781 | //======================================================================= | |
1c728f2d | 782 | Bnd_Box OpenGl_View::MinMaxValues (const Standard_Boolean theToIncludeAuxiliary) const |
50d06d8f | 783 | { |
1c728f2d | 784 | if (!IsDefined()) |
50d06d8f | 785 | { |
1c728f2d | 786 | return Bnd_Box(); |
50d06d8f | 787 | } |
788 | ||
1c728f2d | 789 | Bnd_Box aBox = base_type::MinMaxValues (theToIncludeAuxiliary); |
790 | ||
71d8ccc7 | 791 | return aBox; |
50d06d8f | 792 | } |
793 | ||
794 | //======================================================================= | |
c357e426 | 795 | //function : FBO |
796 | //purpose : | |
797 | //======================================================================= | |
b128c892 | 798 | Handle(Standard_Transient) OpenGl_View::FBO() const |
c357e426 | 799 | { |
b128c892 | 800 | return Handle(Standard_Transient)(myFBO); |
c357e426 | 801 | } |
2166f0fa | 802 | |
c357e426 | 803 | //======================================================================= |
804 | //function : SetFBO | |
805 | //purpose : | |
806 | //======================================================================= | |
b128c892 | 807 | void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo) |
2166f0fa | 808 | { |
b128c892 | 809 | myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); |
2166f0fa SK |
810 | } |
811 | ||
c357e426 | 812 | //======================================================================= |
813 | //function : FBOCreate | |
814 | //purpose : | |
815 | //======================================================================= | |
b128c892 | 816 | Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth, |
817 | const Standard_Integer theHeight) | |
c357e426 | 818 | { |
819 | return myWorkspace->FBOCreate (theWidth, theHeight); | |
820 | } | |
2166f0fa | 821 | |
c357e426 | 822 | //======================================================================= |
823 | //function : FBORelease | |
824 | //purpose : | |
825 | //======================================================================= | |
b128c892 | 826 | void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo) |
2166f0fa | 827 | { |
b128c892 | 828 | Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); |
829 | if (aFrameBuffer.IsNull()) | |
830 | { | |
831 | return; | |
832 | } | |
833 | ||
834 | myWorkspace->FBORelease (aFrameBuffer); | |
835 | theFbo.Nullify(); | |
c357e426 | 836 | } |
837 | ||
838 | //======================================================================= | |
839 | //function : FBOGetDimensions | |
840 | //purpose : | |
841 | //======================================================================= | |
b128c892 | 842 | void OpenGl_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo, |
c357e426 | 843 | Standard_Integer& theWidth, |
844 | Standard_Integer& theHeight, | |
845 | Standard_Integer& theWidthMax, | |
846 | Standard_Integer& theHeightMax) | |
847 | { | |
b128c892 | 848 | const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); |
849 | if (aFrameBuffer.IsNull()) | |
850 | { | |
851 | return; | |
852 | } | |
853 | ||
c357e426 | 854 | theWidth = aFrameBuffer->GetVPSizeX(); // current viewport size |
855 | theHeight = aFrameBuffer->GetVPSizeY(); | |
856 | theWidthMax = aFrameBuffer->GetSizeX(); // texture size | |
857 | theHeightMax = aFrameBuffer->GetSizeY(); | |
858 | } | |
859 | ||
860 | //======================================================================= | |
861 | //function : FBOChangeViewport | |
862 | //purpose : | |
863 | //======================================================================= | |
b128c892 | 864 | void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo, |
c357e426 | 865 | const Standard_Integer theWidth, |
866 | const Standard_Integer theHeight) | |
867 | { | |
b128c892 | 868 | const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo); |
869 | if (aFrameBuffer.IsNull()) | |
870 | { | |
871 | return; | |
872 | } | |
873 | ||
c357e426 | 874 | aFrameBuffer->ChangeViewport (theWidth, theHeight); |
875 | } | |
876 | ||
c357e426 | 877 | //======================================================================= |
878 | //function : displayStructure | |
879 | //purpose : | |
880 | //======================================================================= | |
881 | void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure, | |
882 | const Standard_Integer thePriority) | |
883 | { | |
7d47ebdb | 884 | const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get()); |
c357e426 | 885 | const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer(); |
886 | myZLayers.AddStructure (aStruct, aZLayer, thePriority); | |
887 | } | |
888 | ||
889 | //======================================================================= | |
890 | //function : eraseStructure | |
891 | //purpose : | |
892 | //======================================================================= | |
893 | void OpenGl_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure) | |
894 | { | |
7d47ebdb | 895 | const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get()); |
c357e426 | 896 | myZLayers.RemoveStructure (aStruct); |
897 | } | |
898 | ||
899 | //======================================================================= | |
900 | //function : changeZLayer | |
901 | //purpose : | |
902 | //======================================================================= | |
903 | void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure, | |
904 | const Graphic3d_ZLayerId theNewLayerId) | |
905 | { | |
906 | const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer(); | |
7d47ebdb | 907 | const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get()); |
c357e426 | 908 | myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId); |
cfece3ef | 909 | Update (anOldLayer); |
910 | Update (theNewLayerId); | |
c357e426 | 911 | } |
912 | ||
913 | //======================================================================= | |
914 | //function : changePriority | |
915 | //purpose : | |
916 | //======================================================================= | |
917 | void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure, | |
918 | const Standard_Integer theNewPriority) | |
919 | { | |
920 | const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer(); | |
7d47ebdb | 921 | const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get()); |
c357e426 | 922 | myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority); |
2166f0fa | 923 | } |
26d9c835 | 924 | |
925 | //======================================================================= | |
926 | //function : DiagnosticInformation | |
927 | //purpose : | |
928 | //======================================================================= | |
929 | void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict, | |
930 | Graphic3d_DiagnosticInfo theFlags) const | |
931 | { | |
b40cdc2b | 932 | base_type::DiagnosticInformation (theDict, theFlags); |
26d9c835 | 933 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
934 | if (!myWorkspace->Activate() | |
935 | || aCtx.IsNull()) | |
936 | { | |
937 | return; | |
938 | } | |
939 | ||
940 | aCtx->DiagnosticInformation (theDict, theFlags); | |
941 | if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0) | |
942 | { | |
943 | TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio()); | |
944 | theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio; | |
945 | } | |
946 | } | |
79b544e6 | 947 | |
948 | //======================================================================= | |
949 | //function : StatisticInformation | |
950 | //purpose : | |
951 | //======================================================================= | |
952 | void OpenGl_View::StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const | |
953 | { | |
954 | if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext()) | |
955 | { | |
956 | const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats(); | |
957 | const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams(); | |
958 | aStats->FormatStats (theDict, aRendParams.CollectedStats); | |
959 | } | |
960 | } | |
961 | ||
962 | //======================================================================= | |
963 | //function : StatisticInformation | |
964 | //purpose : | |
965 | //======================================================================= | |
966 | TCollection_AsciiString OpenGl_View::StatisticInformation() const | |
967 | { | |
968 | if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext()) | |
969 | { | |
970 | const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats(); | |
971 | const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams(); | |
972 | return aStats->FormatStats (aRendParams.CollectedStats); | |
973 | } | |
974 | return TCollection_AsciiString(); | |
975 | } | |
cfb54c0c | 976 | |
977 | //======================================================================= | |
978 | //function : drawBackground | |
979 | //purpose : | |
980 | //======================================================================= | |
981 | void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace, | |
982 | Graphic3d_Camera::Projection theProjection) | |
983 | { | |
984 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); | |
4b52faa5 | 985 | const bool wasUsedZBuffer = theWorkspace->SetUseZBuffer (false); |
cfb54c0c | 986 | if (wasUsedZBuffer) |
987 | { | |
988 | aCtx->core11fwd->glDisable (GL_DEPTH_TEST); | |
989 | } | |
990 | ||
4b52faa5 | 991 | #ifdef GL_DEPTH_CLAMP |
992 | const bool wasDepthClamped = aCtx->arbDepthClamp && glIsEnabled (GL_DEPTH_CLAMP); | |
993 | if (aCtx->arbDepthClamp && !wasDepthClamped) | |
994 | { | |
995 | // make sure background is always drawn (workaround skybox rendering on some hardware) | |
996 | aCtx->core11fwd->glEnable (GL_DEPTH_CLAMP); | |
997 | } | |
998 | #endif | |
999 | ||
cfb54c0c | 1000 | if (myBackgroundType == Graphic3d_TOB_CUBEMAP) |
1001 | { | |
3e9cb806 | 1002 | myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uZCoeff", myCubeMapBackground->ZIsInverted() ? -1 : 1); |
1003 | myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uYCoeff", myCubeMapBackground->IsTopDown() ? 1 : -1); | |
cfb54c0c | 1004 | const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myCubeMapParams); |
1005 | ||
1006 | myBackgrounds[Graphic3d_TOB_CUBEMAP]->Render (theWorkspace, theProjection); | |
1007 | ||
1008 | theWorkspace->SetAspects (anOldAspectFace); | |
1009 | } | |
1010 | else if (myBackgroundType == Graphic3d_TOB_GRADIENT | |
1011 | || myBackgroundType == Graphic3d_TOB_TEXTURE) | |
1012 | { | |
1013 | // Drawing background gradient if: | |
9af0d66b | 1014 | // - gradient fill type is not Aspect_GradientFillMethod_None and |
cfb54c0c | 1015 | // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode |
1016 | if (myBackgrounds[Graphic3d_TOB_GRADIENT]->IsDefined() | |
1017 | && (!myTextureParams->Aspect()->ToMapTexture() | |
1018 | || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_CENTERED | |
1019 | || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_NONE)) | |
1020 | { | |
956d9157 | 1021 | if (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod() >= Aspect_GradientFillMethod_Corner1 |
1022 | && myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod() <= Aspect_GradientFillMethod_Corner4) | |
1023 | { | |
1024 | const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myColoredQuadParams); | |
1025 | ||
1026 | myBackgrounds[Graphic3d_TOB_GRADIENT]->Render (theWorkspace, theProjection); | |
1027 | ||
1028 | theWorkspace->SetAspects (anOldAspectFace); | |
1029 | } | |
1030 | else | |
1031 | { | |
1032 | myBackgrounds[Graphic3d_TOB_GRADIENT]->Render (theWorkspace, theProjection); | |
1033 | } | |
cfb54c0c | 1034 | } |
1035 | ||
1036 | // Drawing background image if it is defined | |
1037 | // (texture is defined and fill type is not Aspect_FM_NONE) | |
1038 | if (myBackgrounds[Graphic3d_TOB_TEXTURE]->IsDefined() | |
1039 | && myTextureParams->Aspect()->ToMapTexture()) | |
1040 | { | |
1041 | aCtx->core11fwd->glDisable (GL_BLEND); | |
1042 | ||
1043 | const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myTextureParams); | |
1044 | myBackgrounds[Graphic3d_TOB_TEXTURE]->Render (theWorkspace, theProjection); | |
1045 | theWorkspace->SetAspects (anOldAspectFace); | |
1046 | } | |
1047 | } | |
1048 | ||
1049 | if (wasUsedZBuffer) | |
1050 | { | |
1051 | theWorkspace->SetUseZBuffer (Standard_True); | |
1052 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); | |
1053 | } | |
4b52faa5 | 1054 | #ifdef GL_DEPTH_CLAMP |
1055 | if (aCtx->arbDepthClamp && !wasDepthClamped) | |
1056 | { | |
1057 | aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); | |
1058 | } | |
1059 | #endif | |
cfb54c0c | 1060 | } |
1061 | ||
1062 | //======================================================================= | |
1063 | //function : prepareFrameBuffers | |
1064 | //purpose : | |
1065 | //======================================================================= | |
1066 | bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) | |
1067 | { | |
1068 | theProj = myCamera->ProjectionType(); | |
1069 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
1070 | ||
1071 | Standard_Integer aSizeX = 0, aSizeY = 0; | |
1072 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); | |
1073 | if (aFrameBuffer != NULL) | |
1074 | { | |
1075 | aSizeX = aFrameBuffer->GetVPSizeX(); | |
1076 | aSizeY = aFrameBuffer->GetVPSizeY(); | |
1077 | } | |
1078 | else if (IsActiveXR()) | |
1079 | { | |
1080 | aSizeX = myXRSession->RecommendedViewport().x(); | |
1081 | aSizeY = myXRSession->RecommendedViewport().y(); | |
1082 | } | |
1083 | else | |
1084 | { | |
1085 | aSizeX = myWindow->Width(); | |
1086 | aSizeY = myWindow->Height(); | |
1087 | } | |
1088 | ||
1220d98e | 1089 | const Graphic3d_Vec2i aRendSize (Standard_Integer(myRenderParams.RenderResolutionScale * aSizeX + 0.5f), |
1090 | Standard_Integer(myRenderParams.RenderResolutionScale * aSizeY + 0.5f)); | |
cfb54c0c | 1091 | if (aSizeX < 1 |
1092 | || aSizeY < 1 | |
1220d98e | 1093 | || aRendSize.x() < 1 |
1094 | || aRendSize.y() < 1) | |
cfb54c0c | 1095 | { |
1096 | myBackBufferRestored = Standard_False; | |
1097 | myIsImmediateDrawn = Standard_False; | |
1098 | return false; | |
1099 | } | |
1100 | ||
1101 | // determine multisampling parameters | |
1220d98e | 1102 | Standard_Integer aNbSamples = !myToDisableMSAA && aSizeX == aRendSize.x() |
cfb54c0c | 1103 | ? Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0) |
1104 | : 0; | |
1105 | if (aNbSamples != 0) | |
1106 | { | |
1107 | aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); | |
1108 | } | |
1109 | ||
78c4e836 | 1110 | bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED |
cfb54c0c | 1111 | && checkOitCompatibility (aCtx, aNbSamples > 0); |
1112 | ||
1113 | const bool toInitImmediateFbo = myTransientDrawToFront | |
1114 | && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures())); | |
1115 | ||
1116 | if ( aFrameBuffer == NULL | |
1117 | && !aCtx->DefaultFrameBuffer().IsNull() | |
1118 | && aCtx->DefaultFrameBuffer()->IsValid()) | |
1119 | { | |
1120 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); | |
1121 | } | |
1122 | ||
1123 | if (myHasFboBlit | |
1124 | && (myTransientDrawToFront | |
1125 | || theProj == Graphic3d_Camera::Projection_Stereo | |
1126 | || aNbSamples != 0 | |
1127 | || toUseOit | |
1220d98e | 1128 | || aSizeX != aRendSize.x())) |
cfb54c0c | 1129 | { |
1220d98e | 1130 | if (myMainSceneFbos[0]->GetVPSize() != aRendSize |
1131 | || myMainSceneFbos[0]->NbSamples() != aNbSamples) | |
cfb54c0c | 1132 | { |
1133 | if (!myTransientDrawToFront) | |
1134 | { | |
1135 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); | |
1136 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); | |
1137 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); | |
1138 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); | |
1139 | } | |
1140 | ||
1141 | // prepare FBOs containing main scene | |
1142 | // for further blitting and rendering immediate presentations on top | |
1143 | if (aCtx->core20fwd != NULL) | |
1144 | { | |
1220d98e | 1145 | const bool wasFailedMain0 = checkWasFailedFbo (myMainSceneFbos[0], aRendSize.x(), aRendSize.y(), aNbSamples); |
1146 | if (!myMainSceneFbos[0]->Init (aCtx, aRendSize, myFboColorFormat, myFboDepthFormat, aNbSamples) | |
cfb54c0c | 1147 | && !wasFailedMain0) |
1148 | { | |
1149 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO " | |
1150 | + printFboFormat (myMainSceneFbos[0]) + " initialization has failed"; | |
1151 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1152 | } | |
1153 | } | |
1154 | } | |
78c4e836 | 1155 | |
cfb54c0c | 1156 | if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid())) |
1157 | { | |
1158 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); | |
1159 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) | |
1160 | && !wasFailedImm0) | |
1161 | { | |
1162 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO " | |
1163 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; | |
1164 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1165 | } | |
1166 | } | |
1167 | } | |
1168 | else | |
1169 | { | |
1170 | myMainSceneFbos [0]->Release (aCtx.operator->()); | |
1171 | myMainSceneFbos [1]->Release (aCtx.operator->()); | |
1172 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); | |
1173 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); | |
1174 | myXrSceneFbo ->Release (aCtx.operator->()); | |
1175 | myMainSceneFbos [0]->ChangeViewport (0, 0); | |
1176 | myMainSceneFbos [1]->ChangeViewport (0, 0); | |
1177 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); | |
1178 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); | |
1179 | myXrSceneFbo ->ChangeViewport (0, 0); | |
1180 | } | |
1181 | ||
1182 | bool hasXRBlitFbo = false; | |
1183 | if (theProj == Graphic3d_Camera::Projection_Stereo | |
1184 | && IsActiveXR() | |
1185 | && myMainSceneFbos[0]->IsValid()) | |
1186 | { | |
1187 | if (aNbSamples != 0 | |
1220d98e | 1188 | || aSizeX != aRendSize.x()) |
cfb54c0c | 1189 | { |
1220d98e | 1190 | hasXRBlitFbo = myXrSceneFbo->InitLazy (aCtx, Graphic3d_Vec2i (aSizeX, aSizeY), myFboColorFormat, myFboDepthFormat, 0); |
cfb54c0c | 1191 | if (!hasXRBlitFbo) |
1192 | { | |
1193 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! VR FBO " | |
1194 | + printFboFormat (myXrSceneFbo) + " initialization has failed"; | |
1195 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1196 | } | |
1197 | } | |
1198 | } | |
1199 | else if (theProj == Graphic3d_Camera::Projection_Stereo | |
1200 | && myMainSceneFbos[0]->IsValid()) | |
1201 | { | |
1202 | const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]); | |
1203 | if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) | |
1204 | && !wasFailedMain1) | |
1205 | { | |
1206 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) " | |
1207 | + printFboFormat (myMainSceneFbos[1]) + " initialization has failed"; | |
1208 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1209 | } | |
1210 | if (!myMainSceneFbos[1]->IsValid()) | |
1211 | { | |
1212 | // no enough memory? | |
1213 | theProj = Graphic3d_Camera::Projection_Perspective; | |
1214 | } | |
1215 | else if (!myTransientDrawToFront) | |
1216 | { | |
1217 | // | |
1218 | } | |
1219 | else if (!aCtx->HasStereoBuffers() | |
1220 | || myRenderParams.StereoMode != Graphic3d_StereoMode_QuadBuffer) | |
1221 | { | |
1222 | const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); | |
1223 | const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]); | |
1224 | if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) | |
1225 | && !wasFailedImm0) | |
1226 | { | |
1227 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " | |
1228 | + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; | |
1229 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1230 | } | |
1231 | if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) | |
1232 | && !wasFailedImm1) | |
1233 | { | |
1234 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " | |
1235 | + printFboFormat (myImmediateSceneFbos[1]) + " initialization has failed"; | |
1236 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); | |
1237 | } | |
1238 | if (!myImmediateSceneFbos[0]->IsValid() | |
1239 | || !myImmediateSceneFbos[1]->IsValid()) | |
1240 | { | |
1241 | theProj = Graphic3d_Camera::Projection_Perspective; | |
1242 | } | |
1243 | } | |
1244 | } | |
1245 | if (!hasXRBlitFbo) | |
1246 | { | |
1247 | myXrSceneFbo->Release (aCtx.get()); | |
1248 | myXrSceneFbo->ChangeViewport (0, 0); | |
1249 | } | |
1250 | ||
1251 | // process PBR environment | |
13b36bb1 | 1252 | if (myRenderParams.ShadingModel == Graphic3d_TypeOfShadingModel_Pbr |
1253 | || myRenderParams.ShadingModel == Graphic3d_TypeOfShadingModel_PbrFacet) | |
cfb54c0c | 1254 | { |
1255 | if (!myPBREnvironment.IsNull() | |
1256 | && myPBREnvironment->SizesAreDifferent (myRenderParams.PbrEnvPow2Size, | |
1257 | myRenderParams.PbrEnvSpecMapNbLevels)) | |
1258 | { | |
1259 | myPBREnvironment->Release (aCtx.get()); | |
1260 | myPBREnvironment.Nullify(); | |
1261 | myPBREnvState = OpenGl_PBREnvState_NONEXISTENT; | |
3e9cb806 | 1262 | myPBREnvRequest = true; |
cfb54c0c | 1263 | ++myLightsRevision; |
1264 | } | |
1265 | ||
1266 | if (myPBREnvState == OpenGl_PBREnvState_NONEXISTENT | |
1267 | && aCtx->HasPBR()) | |
1268 | { | |
1269 | myPBREnvironment = OpenGl_PBREnvironment::Create (aCtx, myRenderParams.PbrEnvPow2Size, myRenderParams.PbrEnvSpecMapNbLevels); | |
1270 | myPBREnvState = myPBREnvironment.IsNull() ? OpenGl_PBREnvState_UNAVAILABLE : OpenGl_PBREnvState_CREATED; | |
1271 | if (myPBREnvState == OpenGl_PBREnvState_CREATED) | |
1272 | { | |
1273 | Handle(OpenGl_Texture) anEnvLUT; | |
1274 | static const TCollection_AsciiString THE_SHARED_ENV_LUT_KEY("EnvLUT"); | |
1275 | if (!aCtx->GetResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT)) | |
1276 | { | |
1ac837b2 | 1277 | bool toConvertHalfFloat = false; |
1278 | #if defined(GL_ES_VERSION_2_0) | |
1279 | // GL_RG32F is not texture-filterable format in OpenGL ES without OES_texture_float_linear extension. | |
1280 | // GL_RG16F is texture-filterable since OpenGL ES 3.0 or OpenGL ES 2.0 + OES_texture_half_float_linear. | |
1281 | // OpenGL ES 3.0 allows initialization of GL_RG16F from 32-bit float data, but OpenGL ES 2.0 + OES_texture_half_float does not. | |
1282 | // Note that it is expected that GL_RG16F has enough precision for this table, so that it can be used also on desktop OpenGL. | |
1283 | const bool hasHalfFloat = aCtx->IsGlGreaterEqual (3, 0) || aCtx->CheckExtension ("GL_OES_texture_half_float_linear"); | |
1284 | toConvertHalfFloat = !aCtx->IsGlGreaterEqual (3, 0) && hasHalfFloat; | |
1285 | #endif | |
1286 | Image_Format anImgFormat = Image_Format_UNKNOWN; | |
8f8fe4a9 | 1287 | if (aCtx->arbTexRG) |
1ac837b2 | 1288 | { |
1289 | anImgFormat = toConvertHalfFloat ? Image_Format_RGF_half : Image_Format_RGF; | |
1290 | } | |
1291 | else | |
1292 | { | |
1293 | anImgFormat = toConvertHalfFloat ? Image_Format_RGBAF_half : Image_Format_RGBAF; | |
1294 | } | |
1295 | ||
1296 | Handle(Image_PixMap) aPixMap = new Image_PixMap(); | |
1297 | if (anImgFormat == Image_Format_RGF) | |
8f8fe4a9 | 1298 | { |
1299 | aPixMap->InitWrapper (Image_Format_RGF, (Standard_Byte*)Textures_EnvLUT, Textures_EnvLUTSize, Textures_EnvLUTSize); | |
1300 | } | |
1301 | else | |
1302 | { | |
1ac837b2 | 1303 | aPixMap->InitZero (anImgFormat, Textures_EnvLUTSize, Textures_EnvLUTSize); |
8f8fe4a9 | 1304 | Image_PixMap aPixMapRG; |
1305 | aPixMapRG.InitWrapper (Image_Format_RGF, (Standard_Byte*)Textures_EnvLUT, Textures_EnvLUTSize, Textures_EnvLUTSize); | |
8f8fe4a9 | 1306 | for (Standard_Size aRowIter = 0; aRowIter < aPixMapRG.SizeY(); ++aRowIter) |
1307 | { | |
1308 | for (Standard_Size aColIter = 0; aColIter < aPixMapRG.SizeX(); ++aColIter) | |
1309 | { | |
1310 | const Image_ColorRGF& aPixelRG = aPixMapRG.Value<Image_ColorRGF> (aRowIter, aColIter); | |
1ac837b2 | 1311 | if (toConvertHalfFloat) |
1312 | { | |
1313 | NCollection_Vec2<uint16_t>& aPixelRGBA = aPixMap->ChangeValue<NCollection_Vec2<uint16_t>> (aRowIter, aColIter); | |
1314 | aPixelRGBA.x() = Image_PixMap::ConvertToHalfFloat (aPixelRG.r()); | |
1315 | aPixelRGBA.y() = Image_PixMap::ConvertToHalfFloat (aPixelRG.g()); | |
1316 | } | |
1317 | else | |
1318 | { | |
1319 | Image_ColorRGBAF& aPixelRGBA = aPixMap->ChangeValue<Image_ColorRGBAF> (aRowIter, aColIter); | |
1320 | aPixelRGBA.r() = aPixelRG.r(); | |
1321 | aPixelRGBA.g() = aPixelRG.g(); | |
1322 | } | |
8f8fe4a9 | 1323 | } |
1324 | } | |
1325 | } | |
1326 | ||
cfb54c0c | 1327 | OpenGl_TextureFormat aTexFormat = OpenGl_TextureFormat::FindFormat (aCtx, aPixMap->Format(), false); |
1328 | #if defined(GL_ES_VERSION_2_0) | |
1ac837b2 | 1329 | if (aTexFormat.IsValid() |
1330 | && hasHalfFloat) | |
1331 | { | |
1332 | aTexFormat.SetInternalFormat (aCtx->arbTexRG ? GL_RG16F : GL_RGBA16F); | |
1333 | } | |
cfb54c0c | 1334 | #endif |
1ac837b2 | 1335 | |
1336 | Handle(Graphic3d_TextureParams) aParams = new Graphic3d_TextureParams(); | |
1337 | aParams->SetFilter (Graphic3d_TOTF_BILINEAR); | |
1338 | aParams->SetRepeat (Standard_False); | |
1339 | aParams->SetTextureUnit (aCtx->PBREnvLUTTexUnit()); | |
1340 | anEnvLUT = new OpenGl_Texture(THE_SHARED_ENV_LUT_KEY, aParams); | |
cfb54c0c | 1341 | if (!aTexFormat.IsValid() |
1342 | || !anEnvLUT->Init (aCtx, aTexFormat, Graphic3d_Vec2i((Standard_Integer)Textures_EnvLUTSize), Graphic3d_TOT_2D, aPixMap.get())) | |
1343 | { | |
1344 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed allocation of LUT for PBR"); | |
1345 | anEnvLUT.Nullify(); | |
1346 | } | |
1347 | aCtx->ShareResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT); | |
1348 | } | |
1349 | if (!anEnvLUT.IsNull()) | |
1350 | { | |
1351 | anEnvLUT->Bind (aCtx); | |
1352 | } | |
1353 | myWorkspace->ApplyAspects(); | |
1354 | } | |
1355 | } | |
3e9cb806 | 1356 | updatePBREnvironment (aCtx); |
cfb54c0c | 1357 | } |
1358 | ||
1359 | // create color and coverage accumulation buffers required for OIT algorithm | |
78c4e836 | 1360 | if (toUseOit |
1361 | && myRenderParams.TransparencyMethod == Graphic3d_RTM_DEPTH_PEELING_OIT) | |
1362 | { | |
1220d98e | 1363 | if (myDepthPeelingFbos->BlendBackFboOit()->GetSize() != aRendSize) |
78c4e836 | 1364 | { |
1220d98e | 1365 | if (myDepthPeelingFbos->BlendBackFboOit()->Init (aCtx, aRendSize, GL_RGBA16F, 0)) |
78c4e836 | 1366 | { |
1367 | for (int aPairIter = 0; aPairIter < 2; ++aPairIter) | |
1368 | { | |
1369 | OpenGl_ColorFormats aColorFormats; | |
1370 | aColorFormats.Append (GL_RG32F); | |
1371 | aColorFormats.Append (GL_RGBA16F); | |
1372 | aColorFormats.Append (GL_RGBA16F); | |
1220d98e | 1373 | myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->Init (aCtx, aRendSize, aColorFormats, 0); |
78c4e836 | 1374 | |
1375 | NCollection_Sequence<Handle(OpenGl_Texture)> anAttachments; | |
1376 | anAttachments.Append (myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->ColorTexture (1)); | |
1377 | anAttachments.Append (myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->ColorTexture (2)); | |
1378 | myDepthPeelingFbos->FrontBackColorFbosOit()[aPairIter]->InitWrapper (aCtx, anAttachments); | |
1379 | } | |
1380 | } | |
1381 | else | |
1382 | { | |
1383 | toUseOit = false; | |
1384 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, | |
1385 | "Initialization of float texture framebuffer for use with\n" | |
1386 | " Depth-Peeling order-independent transparency rendering algorithm has failed."); | |
1387 | } | |
1388 | } | |
1389 | } | |
1390 | if (!toUseOit) | |
1391 | { | |
1392 | myDepthPeelingFbos->Release (aCtx.operator->()); | |
1393 | } | |
1394 | ||
1395 | if (toUseOit | |
1396 | && myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT) | |
cfb54c0c | 1397 | { |
1398 | Standard_Integer anFboIt = 0; | |
1399 | for (; anFboIt < 2; ++anFboIt) | |
1400 | { | |
1401 | Handle(OpenGl_FrameBuffer)& aMainSceneFbo = myMainSceneFbos [anFboIt]; | |
1402 | Handle(OpenGl_FrameBuffer)& aMainSceneFboOit = myMainSceneFbosOit [anFboIt]; | |
1403 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFbo = myImmediateSceneFbos [anFboIt]; | |
1404 | Handle(OpenGl_FrameBuffer)& anImmediateSceneFboOit = myImmediateSceneFbosOit[anFboIt]; | |
1405 | if (aMainSceneFbo->IsValid() | |
1220d98e | 1406 | && (aMainSceneFboOit->GetVPSize() != aRendSize |
1407 | || aMainSceneFboOit->NbSamples() != aNbSamples)) | |
cfb54c0c | 1408 | { |
1409 | Standard_Integer aColorConfig = 0; | |
1410 | for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED) | |
1411 | { | |
1412 | if (myFboOitColorConfig.IsEmpty()) | |
1413 | { | |
1414 | if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig)) | |
1415 | { | |
1416 | break; | |
1417 | } | |
1418 | } | |
1220d98e | 1419 | if (aMainSceneFboOit->Init (aCtx, aRendSize, myFboOitColorConfig, aMainSceneFbo->DepthStencilTexture(), aNbSamples)) |
cfb54c0c | 1420 | { |
1421 | break; | |
1422 | } | |
1423 | myFboOitColorConfig.Clear(); | |
1424 | } | |
1425 | if (!aMainSceneFboOit->IsValid()) | |
1426 | { | |
1427 | break; | |
1428 | } | |
1429 | } | |
1430 | else if (!aMainSceneFbo->IsValid()) | |
1431 | { | |
1432 | aMainSceneFboOit->Release (aCtx.operator->()); | |
1433 | aMainSceneFboOit->ChangeViewport (0, 0); | |
1434 | } | |
1435 | ||
1436 | if (anImmediateSceneFbo->IsValid() | |
1220d98e | 1437 | && (anImmediateSceneFboOit->GetVPSize() != aRendSize |
1438 | || anImmediateSceneFboOit->NbSamples() != aNbSamples)) | |
cfb54c0c | 1439 | { |
1220d98e | 1440 | if (!anImmediateSceneFboOit->Init (aCtx, aRendSize, myFboOitColorConfig, |
cfb54c0c | 1441 | anImmediateSceneFbo->DepthStencilTexture(), aNbSamples)) |
1442 | { | |
1443 | break; | |
1444 | } | |
1445 | } | |
1446 | else if (!anImmediateSceneFbo->IsValid()) | |
1447 | { | |
1448 | anImmediateSceneFboOit->Release (aCtx.operator->()); | |
1449 | anImmediateSceneFboOit->ChangeViewport (0, 0); | |
1450 | } | |
1451 | } | |
1452 | if (anFboIt == 0) // only the first OIT framebuffer is mandatory | |
1453 | { | |
1454 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, | |
1455 | "Initialization of float texture framebuffer for use with\n" | |
1456 | " blended order-independent transparency rendering algorithm has failed.\n" | |
1457 | " Blended order-independent transparency will not be available.\n"); | |
1458 | if (aNbSamples > 0) | |
1459 | { | |
1460 | myToDisableOITMSAA = Standard_True; | |
1461 | } | |
1462 | else | |
1463 | { | |
1464 | myToDisableOIT = Standard_True; | |
1465 | } | |
1466 | toUseOit = false; | |
1467 | } | |
1468 | } | |
1469 | if (!toUseOit && myMainSceneFbosOit[0]->IsValid()) | |
1470 | { | |
78c4e836 | 1471 | myDepthPeelingFbos->Release (aCtx.operator->()); |
cfb54c0c | 1472 | myMainSceneFbosOit [0]->Release (aCtx.operator->()); |
1473 | myMainSceneFbosOit [1]->Release (aCtx.operator->()); | |
1474 | myImmediateSceneFbosOit[0]->Release (aCtx.operator->()); | |
1475 | myImmediateSceneFbosOit[1]->Release (aCtx.operator->()); | |
1476 | myMainSceneFbosOit [0]->ChangeViewport (0, 0); | |
1477 | myMainSceneFbosOit [1]->ChangeViewport (0, 0); | |
1478 | myImmediateSceneFbosOit[0]->ChangeViewport (0, 0); | |
1479 | myImmediateSceneFbosOit[1]->ChangeViewport (0, 0); | |
1480 | } | |
1481 | ||
d84e8669 | 1482 | // allocate shadow maps |
13b36bb1 | 1483 | const Handle(Graphic3d_LightSet)& aLights = myRenderParams.ShadingModel == Graphic3d_TypeOfShadingModel_Unlit ? myNoShadingLight : myLights; |
d84e8669 | 1484 | if (!aLights.IsNull()) |
1485 | { | |
1486 | aLights->UpdateRevision(); | |
1487 | } | |
1488 | bool toUseShadowMap = myRenderParams.IsShadowEnabled | |
1489 | && myRenderParams.ShadowMapResolution > 0 | |
1490 | && !myLights.IsNull() | |
1491 | && myLights->NbCastShadows() > 0 | |
1492 | && myRenderParams.Method != Graphic3d_RM_RAYTRACING; | |
1493 | if (toUseShadowMap) | |
1494 | { | |
1495 | if (myShadowMaps->Size() != myLights->NbCastShadows()) | |
1496 | { | |
1497 | myShadowMaps->Release (aCtx.get()); | |
1498 | myShadowMaps->Resize (0, myLights->NbCastShadows() - 1, true); | |
1499 | } | |
1500 | ||
1501 | const GLint aSamplFrom = GLint(aCtx->ShadowMapTexUnit()) - myLights->NbCastShadows() + 1; | |
1502 | for (Standard_Integer aShadowIter = 0; aShadowIter < myShadowMaps->Size(); ++aShadowIter) | |
1503 | { | |
1504 | Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->ChangeValue (aShadowIter); | |
1505 | if (aShadow.IsNull()) | |
1506 | { | |
1507 | aShadow = new OpenGl_ShadowMap(); | |
1508 | } | |
1509 | aShadow->SetShadowMapBias (myRenderParams.ShadowMapBias); | |
1510 | aShadow->Texture()->Sampler()->Parameters()->SetTextureUnit ((Graphic3d_TextureUnit )(aSamplFrom + aShadowIter)); | |
1511 | ||
1512 | const Handle(OpenGl_FrameBuffer)& aShadowFbo = aShadow->FrameBuffer(); | |
1513 | if (aShadowFbo->GetVPSizeX() != myRenderParams.ShadowMapResolution | |
1514 | && toUseShadowMap) | |
1515 | { | |
1516 | OpenGl_ColorFormats aDummy; | |
1220d98e | 1517 | if (!aShadowFbo->Init (aCtx, Graphic3d_Vec2i (myRenderParams.ShadowMapResolution), aDummy, myFboDepthFormat, 0)) |
d84e8669 | 1518 | { |
1519 | toUseShadowMap = false; | |
1520 | } | |
1521 | } | |
1522 | } | |
1523 | } | |
1524 | if (!toUseShadowMap && myShadowMaps->IsValid()) | |
1525 | { | |
1526 | myShadowMaps->Release (aCtx.get()); | |
1527 | } | |
1528 | ||
cfb54c0c | 1529 | return true; |
1530 | } | |
1531 | ||
1532 | //======================================================================= | |
1533 | //function : Redraw | |
1534 | //purpose : | |
1535 | //======================================================================= | |
1536 | void OpenGl_View::Redraw() | |
1537 | { | |
1538 | const Standard_Boolean wasDisabledMSAA = myToDisableMSAA; | |
1539 | const Standard_Boolean hadFboBlit = myHasFboBlit; | |
1540 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING | |
1541 | && !myCaps->vboDisable | |
1542 | && !myCaps->keepArrayData) | |
1543 | { | |
1544 | // caps are shared across all views, thus we need to invalidate all of them | |
1545 | // if (myWasRedrawnGL) { myStructureManager->SetDeviceLost(); } | |
1546 | myDriver->setDeviceLost(); | |
1547 | myCaps->keepArrayData = Standard_True; | |
1548 | } | |
1549 | ||
1550 | if (!myWorkspace->Activate()) | |
1551 | { | |
1552 | return; | |
1553 | } | |
1554 | ||
1555 | // implicitly disable VSync when using HMD composer (can be mirrored in window for debugging) | |
1556 | myWindow->SetSwapInterval (IsActiveXR()); | |
1557 | ||
1558 | ++myFrameCounter; | |
1559 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
1560 | aCtx->FrameStats()->FrameStart (myWorkspace->View(), false); | |
1561 | aCtx->SetLineFeather (myRenderParams.LineFeather); | |
1562 | ||
1563 | const Standard_Integer anSRgbState = aCtx->ToRenderSRGB() ? 1 : 0; | |
1564 | if (mySRgbState != -1 | |
1565 | && mySRgbState != anSRgbState) | |
1566 | { | |
1567 | releaseSrgbResources (aCtx); | |
1568 | initTextureEnv (aCtx); | |
1569 | } | |
1570 | mySRgbState = anSRgbState; | |
1571 | aCtx->ShaderManager()->UpdateSRgbState(); | |
1572 | ||
1573 | // release pending GL resources | |
1574 | aCtx->ReleaseDelayed(); | |
1575 | ||
1576 | // fetch OpenGl context state | |
1577 | aCtx->FetchState(); | |
1578 | ||
1579 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; | |
1580 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); | |
1581 | if (!prepareFrameBuffers (aProjectType)) | |
1582 | { | |
1583 | myBackBufferRestored = Standard_False; | |
1584 | myIsImmediateDrawn = Standard_False; | |
1585 | return; | |
1586 | } | |
1587 | ||
d84e8669 | 1588 | // draw shadow maps |
1589 | if (myShadowMaps->IsValid()) | |
1590 | { | |
1591 | Standard_Integer aShadowIndex = myShadowMaps->Lower(); | |
1592 | for (Graphic3d_LightSet::Iterator aLightIter (myLights, Graphic3d_LightSet::IterationFilter_ActiveShadowCasters); | |
1593 | aLightIter.More(); aLightIter.Next()) | |
1594 | { | |
1595 | const Handle(Graphic3d_CLight)& aLight = aLightIter.Value(); | |
1596 | if (aLight->ToCastShadows()) | |
1597 | { | |
1598 | const Handle(OpenGl_ShadowMap)& aShadowMap = myShadowMaps->ChangeValue (aShadowIndex); | |
1599 | aShadowMap->SetLightSource (aLight); | |
1600 | renderShadowMap (aShadowMap); | |
1601 | ++aShadowIndex; | |
1602 | } | |
1603 | } | |
1604 | for (; aShadowIndex <= myShadowMaps->Upper(); ++aShadowIndex) | |
1605 | { | |
1606 | myShadowMaps->ChangeValue (aShadowIndex)->SetLightSource (Handle(Graphic3d_CLight)()); | |
1607 | } | |
1608 | } | |
1609 | ||
cfb54c0c | 1610 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); |
1611 | bool toSwap = aCtx->IsRender() | |
1612 | && !aCtx->caps->buffersNoSwap | |
1613 | && aFrameBuffer == NULL | |
1614 | && (!IsActiveXR() || myRenderParams.ToMirrorComposer); | |
1615 | if ( aFrameBuffer == NULL | |
1616 | && !aCtx->DefaultFrameBuffer().IsNull() | |
1617 | && aCtx->DefaultFrameBuffer()->IsValid()) | |
1618 | { | |
1619 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); | |
1620 | } | |
1621 | ||
1622 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) | |
1623 | { | |
1624 | OpenGl_FrameBuffer* aMainFbos[2] = | |
1625 | { | |
1626 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, | |
1627 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL | |
1628 | }; | |
1629 | OpenGl_FrameBuffer* aMainFbosOit[2] = | |
1630 | { | |
1631 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL, | |
1632 | myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() : | |
1633 | myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL | |
1634 | }; | |
1635 | ||
1636 | OpenGl_FrameBuffer* anImmFbos[2] = | |
1637 | { | |
1638 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, | |
1639 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL | |
1640 | }; | |
1641 | OpenGl_FrameBuffer* anImmFbosOit[2] = | |
1642 | { | |
1643 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, | |
1644 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : | |
1645 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL | |
1646 | }; | |
1647 | ||
1648 | if (IsActiveXR()) | |
1649 | { | |
1650 | // use single frame for both views - caching main scene content makes no sense | |
1651 | // when head position is expected to be updated each frame redraw with high accuracy | |
1652 | aMainFbos[1] = aMainFbos[0]; | |
1653 | aMainFbosOit[1] = aMainFbosOit[0]; | |
1654 | anImmFbos[0] = aMainFbos[0]; | |
1655 | anImmFbos[1] = aMainFbos[1]; | |
1656 | anImmFbosOit[0] = aMainFbosOit[0]; | |
1657 | anImmFbosOit[1] = aMainFbosOit[1]; | |
1658 | } | |
1659 | else if (!myTransientDrawToFront) | |
1660 | { | |
1661 | anImmFbos [0] = aMainFbos [0]; | |
1662 | anImmFbos [1] = aMainFbos [1]; | |
1663 | anImmFbosOit[0] = aMainFbosOit[0]; | |
1664 | anImmFbosOit[1] = aMainFbosOit[1]; | |
1665 | } | |
1666 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip | |
1667 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) | |
1668 | { | |
1669 | anImmFbos [0] = NULL; | |
1670 | anImmFbos [1] = NULL; | |
1671 | anImmFbosOit[0] = NULL; | |
1672 | anImmFbosOit[1] = NULL; | |
1673 | } | |
1674 | ||
1675 | #if !defined(GL_ES_VERSION_2_0) | |
1676 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); | |
1677 | #endif | |
1678 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1679 | aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1680 | ||
1681 | redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]); | |
1682 | myBackBufferRestored = Standard_True; | |
1683 | myIsImmediateDrawn = Standard_False; | |
1684 | #if !defined(GL_ES_VERSION_2_0) | |
1685 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); | |
1686 | #endif | |
1687 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1688 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1689 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0])) | |
1690 | { | |
1691 | toSwap = false; | |
1692 | } | |
1693 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) | |
1694 | { | |
1695 | aCtx->SwapBuffers(); | |
1696 | } | |
1697 | ||
1698 | if (IsActiveXR()) | |
1699 | { | |
1700 | // push Left frame to HMD display composer | |
1701 | OpenGl_FrameBuffer* anXRFbo = myXrSceneFbo->IsValid() ? myXrSceneFbo.get() : aMainFbos[0]; | |
1702 | if (anXRFbo != aMainFbos[0]) | |
1703 | { | |
1704 | blitBuffers (aMainFbos[0], anXRFbo); // resize or resolve MSAA samples | |
1705 | } | |
1706 | #if !defined(GL_ES_VERSION_2_0) | |
1707 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGL; | |
1708 | #else | |
1709 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGLES; | |
1710 | #endif | |
1711 | myXRSession->SubmitEye ((void* )(size_t )anXRFbo->ColorTexture()->TextureId(), | |
1712 | aGraphicsLib, Aspect_ColorSpace_sRGB, Aspect_Eye_Left); | |
1713 | } | |
1714 | ||
1715 | #if !defined(GL_ES_VERSION_2_0) | |
1716 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); | |
1717 | #endif | |
1718 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1719 | aMainFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1720 | ||
1721 | redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]); | |
1722 | myBackBufferRestored = Standard_True; | |
1723 | myIsImmediateDrawn = Standard_False; | |
1724 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1725 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1726 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1])) | |
1727 | { | |
1728 | toSwap = false; | |
1729 | } | |
1730 | ||
1731 | if (IsActiveXR()) | |
1732 | { | |
1733 | // push Right frame to HMD display composer | |
1734 | OpenGl_FrameBuffer* anXRFbo = myXrSceneFbo->IsValid() ? myXrSceneFbo.get() : aMainFbos[1]; | |
1735 | if (anXRFbo != aMainFbos[1]) | |
1736 | { | |
1737 | blitBuffers (aMainFbos[1], anXRFbo); // resize or resolve MSAA samples | |
1738 | } | |
1739 | #if !defined(GL_ES_VERSION_2_0) | |
1740 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGL; | |
1741 | #else | |
1742 | const Aspect_GraphicsLibrary aGraphicsLib = Aspect_GraphicsLibrary_OpenGLES; | |
1743 | #endif | |
1744 | myXRSession->SubmitEye ((void* )(size_t )anXRFbo->ColorTexture()->TextureId(), | |
1745 | aGraphicsLib, Aspect_ColorSpace_sRGB, Aspect_Eye_Right); | |
43eddb47 | 1746 | aCtx->core11fwd->glFinish(); |
cfb54c0c | 1747 | |
1748 | if (myRenderParams.ToMirrorComposer) | |
1749 | { | |
1750 | blitBuffers (anXRFbo, aFrameBuffer, myToFlipOutput); | |
1751 | } | |
1752 | } | |
1753 | else if (anImmFbos[0] != NULL) | |
1754 | { | |
1755 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), 1.0f); | |
1756 | drawStereoPair (aFrameBuffer); | |
1757 | } | |
1758 | } | |
1759 | else | |
1760 | { | |
1761 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer; | |
1762 | OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL; | |
1763 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; | |
1764 | OpenGl_FrameBuffer* anImmFboOit = NULL; | |
1765 | if (!myTransientDrawToFront) | |
1766 | { | |
1767 | anImmFbo = aMainFbo; | |
1768 | anImmFboOit = aMainFboOit; | |
1769 | } | |
1770 | else if (myImmediateSceneFbos[0]->IsValid()) | |
1771 | { | |
1772 | anImmFbo = myImmediateSceneFbos[0].operator->(); | |
1773 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; | |
1774 | } | |
1775 | ||
1776 | #if !defined(GL_ES_VERSION_2_0) | |
1777 | if (aMainFbo == NULL) | |
1778 | { | |
1779 | aCtx->SetReadDrawBuffer (GL_BACK); | |
1780 | } | |
1781 | #endif | |
1782 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1783 | aMainFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); | |
1784 | ||
1785 | redraw (aProjectType, aMainFbo, aMainFboOit); | |
1786 | myBackBufferRestored = Standard_True; | |
1787 | myIsImmediateDrawn = Standard_False; | |
1788 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1789 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); | |
1790 | if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit)) | |
1791 | { | |
1792 | toSwap = false; | |
1793 | } | |
1794 | ||
1795 | if (anImmFbo != NULL | |
1796 | && anImmFbo != aFrameBuffer) | |
1797 | { | |
1798 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); | |
1799 | } | |
1800 | } | |
1801 | ||
1802 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING | |
1803 | && myRenderParams.IsGlobalIlluminationEnabled) | |
1804 | { | |
1805 | myAccumFrames++; | |
1806 | } | |
1807 | ||
1808 | // bind default FBO | |
1809 | bindDefaultFbo(); | |
1810 | ||
1811 | if (wasDisabledMSAA != myToDisableMSAA | |
1812 | || hadFboBlit != myHasFboBlit) | |
1813 | { | |
1814 | // retry on error | |
1815 | Redraw(); | |
1816 | } | |
1817 | ||
1818 | // reset state for safety | |
1819 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
1820 | if (aCtx->caps->ffpEnable) | |
1821 | { | |
1822 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); | |
1823 | } | |
1824 | ||
1825 | // Swap the buffers | |
1826 | if (toSwap) | |
1827 | { | |
1828 | aCtx->SwapBuffers(); | |
1829 | if (!myMainSceneFbos[0]->IsValid()) | |
1830 | { | |
1831 | myBackBufferRestored = Standard_False; | |
1832 | } | |
1833 | } | |
1834 | else | |
1835 | { | |
1836 | aCtx->core11fwd->glFlush(); | |
1837 | } | |
1838 | ||
1839 | // reset render mode state | |
1840 | aCtx->FetchState(); | |
1841 | aCtx->FrameStats()->FrameEnd (myWorkspace->View(), false); | |
1842 | ||
1843 | myWasRedrawnGL = Standard_True; | |
1844 | } | |
1845 | ||
1846 | // ======================================================================= | |
1847 | // function : RedrawImmediate | |
1848 | // purpose : | |
1849 | // ======================================================================= | |
1850 | void OpenGl_View::RedrawImmediate() | |
1851 | { | |
1852 | if (!myWorkspace->Activate()) | |
1853 | return; | |
1854 | ||
1855 | // no special handling of HMD display, since it will force full Redraw() due to no frame caching (myBackBufferRestored) | |
1856 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
1857 | if (!myTransientDrawToFront | |
1858 | || !myBackBufferRestored | |
1859 | || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) | |
1860 | { | |
1861 | Redraw(); | |
1862 | return; | |
1863 | } | |
1864 | ||
1865 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; | |
1866 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); | |
1867 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); | |
1868 | aCtx->FrameStats()->FrameStart (myWorkspace->View(), true); | |
1869 | ||
1870 | if ( aFrameBuffer == NULL | |
1871 | && !aCtx->DefaultFrameBuffer().IsNull() | |
1872 | && aCtx->DefaultFrameBuffer()->IsValid()) | |
1873 | { | |
1874 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); | |
1875 | } | |
1876 | ||
1877 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) | |
1878 | { | |
1879 | if (myMainSceneFbos[0]->IsValid() | |
1880 | && !myMainSceneFbos[1]->IsValid()) | |
1881 | { | |
1882 | aProjectType = Graphic3d_Camera::Projection_Perspective; | |
1883 | } | |
1884 | } | |
1885 | ||
1886 | bool toSwap = false; | |
1887 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) | |
1888 | { | |
1889 | OpenGl_FrameBuffer* aMainFbos[2] = | |
1890 | { | |
1891 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, | |
1892 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL | |
1893 | }; | |
1894 | OpenGl_FrameBuffer* anImmFbos[2] = | |
1895 | { | |
1896 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, | |
1897 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL | |
1898 | }; | |
1899 | OpenGl_FrameBuffer* anImmFbosOit[2] = | |
1900 | { | |
1901 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL, | |
1902 | myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() : | |
1903 | myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL | |
1904 | }; | |
1905 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip | |
1906 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) | |
1907 | { | |
1908 | anImmFbos[0] = NULL; | |
1909 | anImmFbos[1] = NULL; | |
1910 | anImmFbosOit[0] = NULL; | |
1911 | anImmFbosOit[1] = NULL; | |
1912 | } | |
1913 | ||
1914 | if (aCtx->arbFBO != NULL) | |
1915 | { | |
1916 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
1917 | } | |
1918 | #if !defined(GL_ES_VERSION_2_0) | |
1919 | if (anImmFbos[0] == NULL) | |
1920 | { | |
1921 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); | |
1922 | } | |
1923 | #endif | |
1924 | ||
1925 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1926 | anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1927 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, | |
1928 | aMainFbos[0], | |
1929 | anImmFbos[0], | |
1930 | anImmFbosOit[0], | |
1931 | Standard_True) || toSwap; | |
1932 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip | |
1933 | && toSwap | |
655e883c | 1934 | && myFBO.get() == NULL |
cfb54c0c | 1935 | && !aCtx->caps->buffersNoSwap) |
1936 | { | |
1937 | aCtx->SwapBuffers(); | |
1938 | } | |
1939 | ||
1940 | if (aCtx->arbFBO != NULL) | |
1941 | { | |
1942 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
1943 | } | |
1944 | #if !defined(GL_ES_VERSION_2_0) | |
1945 | if (anImmFbos[1] == NULL) | |
1946 | { | |
1947 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); | |
1948 | } | |
1949 | #endif | |
1950 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1951 | anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f); | |
1952 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, | |
1953 | aMainFbos[1], | |
1954 | anImmFbos[1], | |
1955 | anImmFbosOit[1], | |
1956 | Standard_True) || toSwap; | |
1957 | if (anImmFbos[0] != NULL) | |
1958 | { | |
1959 | drawStereoPair (aFrameBuffer); | |
1960 | } | |
1961 | } | |
1962 | else | |
1963 | { | |
1964 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; | |
1965 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; | |
1966 | OpenGl_FrameBuffer* anImmFboOit = NULL; | |
1967 | if (myImmediateSceneFbos[0]->IsValid()) | |
1968 | { | |
1969 | anImmFbo = myImmediateSceneFbos[0].operator->(); | |
1970 | anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL; | |
1971 | } | |
1972 | #if !defined(GL_ES_VERSION_2_0) | |
1973 | if (aMainFbo == NULL) | |
1974 | { | |
1975 | aCtx->SetReadDrawBuffer (GL_BACK); | |
1976 | } | |
1977 | #endif | |
1978 | aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), | |
1979 | anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f); | |
1980 | toSwap = redrawImmediate (aProjectType, | |
1981 | aMainFbo, | |
1982 | anImmFbo, | |
1983 | anImmFboOit, | |
1984 | Standard_True) || toSwap; | |
1985 | if (anImmFbo != NULL | |
1986 | && anImmFbo != aFrameBuffer) | |
1987 | { | |
1988 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); | |
1989 | } | |
1990 | } | |
1991 | ||
1992 | // bind default FBO | |
1993 | bindDefaultFbo(); | |
1994 | ||
1995 | // reset state for safety | |
1996 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
1997 | if (aCtx->caps->ffpEnable) | |
1998 | { | |
1999 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); | |
2000 | } | |
2001 | ||
655e883c | 2002 | if (toSwap |
2003 | && myFBO.get() == NULL | |
2004 | && !aCtx->caps->buffersNoSwap) | |
cfb54c0c | 2005 | { |
2006 | aCtx->SwapBuffers(); | |
2007 | } | |
2008 | else | |
2009 | { | |
2010 | aCtx->core11fwd->glFlush(); | |
2011 | } | |
2012 | aCtx->FrameStats()->FrameEnd (myWorkspace->View(), true); | |
2013 | ||
2014 | myWasRedrawnGL = Standard_True; | |
2015 | } | |
2016 | ||
2017 | // ======================================================================= | |
2018 | // function : redraw | |
2019 | // purpose : | |
2020 | // ======================================================================= | |
2021 | void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, | |
2022 | OpenGl_FrameBuffer* theReadDrawFbo, | |
2023 | OpenGl_FrameBuffer* theOitAccumFbo) | |
2024 | { | |
2025 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
2026 | if (theReadDrawFbo != NULL) | |
2027 | { | |
2028 | theReadDrawFbo->BindBuffer (aCtx); | |
2029 | theReadDrawFbo->SetupViewport (aCtx); | |
2030 | } | |
2031 | else | |
2032 | { | |
2033 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; | |
2034 | aCtx->ResizeViewport (aViewport); | |
2035 | } | |
2036 | ||
2037 | // request reset of material | |
2038 | aCtx->ShaderManager()->UpdateMaterialState(); | |
2039 | ||
2040 | myWorkspace->UseZBuffer() = Standard_True; | |
2041 | myWorkspace->UseDepthWrite() = Standard_True; | |
2042 | GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; | |
2043 | aCtx->core11fwd->glDepthFunc (GL_LEQUAL); | |
2044 | aCtx->core11fwd->glDepthMask (GL_TRUE); | |
2045 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); | |
2046 | ||
2047 | aCtx->core11fwd->glClearDepth (1.0); | |
2048 | ||
2049 | const OpenGl_Vec4 aBgColor = aCtx->Vec4FromQuantityColor (myBgColor); | |
2050 | aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha | |
2051 | aCtx->core11fwd->glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), aCtx->caps->buffersOpaqueAlpha ? 1.0f : 0.0f); | |
2052 | aCtx->core11fwd->glClear (toClear); | |
2053 | aCtx->SetColorMask (true); // restore default alpha component write state | |
2054 | ||
2055 | render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False); | |
2056 | } | |
2057 | ||
2058 | // ======================================================================= | |
d84e8669 | 2059 | // function : redrawImmediate |
cfb54c0c | 2060 | // purpose : |
2061 | // ======================================================================= | |
2062 | bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, | |
2063 | OpenGl_FrameBuffer* theReadFbo, | |
2064 | OpenGl_FrameBuffer* theDrawFbo, | |
2065 | OpenGl_FrameBuffer* theOitAccumFbo, | |
2066 | const Standard_Boolean theIsPartialUpdate) | |
2067 | { | |
2068 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
2069 | GLboolean toCopyBackToFront = GL_FALSE; | |
2070 | if (theDrawFbo == theReadFbo | |
2071 | && theDrawFbo != NULL | |
2072 | && theDrawFbo->IsValid()) | |
2073 | { | |
2074 | myBackBufferRestored = Standard_False; | |
2075 | theDrawFbo->BindBuffer (aCtx); | |
2076 | } | |
2077 | else if (theReadFbo != NULL | |
2078 | && theReadFbo->IsValid() | |
2079 | && aCtx->IsRender()) | |
2080 | { | |
2081 | if (!blitBuffers (theReadFbo, theDrawFbo)) | |
2082 | { | |
2083 | return true; | |
2084 | } | |
2085 | } | |
2086 | else if (theDrawFbo == NULL) | |
2087 | { | |
2088 | #if !defined(GL_ES_VERSION_2_0) | |
2089 | aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); | |
2090 | #endif | |
2091 | if (toCopyBackToFront | |
2092 | && myTransientDrawToFront) | |
2093 | { | |
2094 | if (!HasImmediateStructures() | |
2095 | && !theIsPartialUpdate) | |
2096 | { | |
2097 | // prefer Swap Buffers within Redraw in compatibility mode (without FBO) | |
2098 | return true; | |
2099 | } | |
2100 | if (!copyBackToFront()) | |
2101 | { | |
2102 | toCopyBackToFront = GL_FALSE; | |
2103 | myBackBufferRestored = Standard_False; | |
2104 | } | |
2105 | } | |
2106 | else | |
2107 | { | |
2108 | toCopyBackToFront = GL_FALSE; | |
2109 | myBackBufferRestored = Standard_False; | |
2110 | } | |
2111 | } | |
2112 | else | |
2113 | { | |
2114 | myBackBufferRestored = Standard_False; | |
2115 | } | |
2116 | myIsImmediateDrawn = Standard_True; | |
2117 | ||
2118 | myWorkspace->UseZBuffer() = Standard_True; | |
2119 | myWorkspace->UseDepthWrite() = Standard_True; | |
43eddb47 | 2120 | aCtx->core11fwd->glDepthFunc (GL_LEQUAL); |
2121 | aCtx->core11fwd->glDepthMask (GL_TRUE); | |
2122 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); | |
2123 | aCtx->core11fwd->glClearDepth (1.0); | |
cfb54c0c | 2124 | |
2125 | render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True); | |
2126 | ||
2127 | return !toCopyBackToFront; | |
2128 | } | |
2129 | ||
d84e8669 | 2130 | //======================================================================= |
2131 | //function : renderShadowMap | |
2132 | //purpose : | |
2133 | //======================================================================= | |
2134 | void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) | |
2135 | { | |
2136 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
2137 | if (!theShadowMap->UpdateCamera (*this)) | |
2138 | { | |
2139 | return; | |
2140 | } | |
2141 | ||
2142 | myBVHSelector.SetViewVolume (theShadowMap->Camera()); | |
2143 | myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); | |
2144 | myBVHSelector.CacheClipPtsProjections(); | |
2145 | ||
2146 | myLocalOrigin.SetCoord (0.0, 0.0, 0.0); | |
2147 | aCtx->SetCamera (theShadowMap->Camera()); | |
2148 | aCtx->ProjectionState.SetCurrent (theShadowMap->Camera()->ProjectionMatrixF()); | |
2149 | aCtx->ApplyProjectionMatrix(); | |
2150 | ||
2151 | aCtx->ShaderManager()->UpdateMaterialState(); | |
2152 | aCtx->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); | |
13b36bb1 | 2153 | aCtx->ShaderManager()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit); |
d84e8669 | 2154 | |
2155 | const Handle(OpenGl_FrameBuffer)& aShadowBuffer = theShadowMap->FrameBuffer(); | |
2156 | aShadowBuffer->BindBuffer (aCtx); | |
2157 | aShadowBuffer->SetupViewport (aCtx); | |
2158 | ||
2159 | aCtx->SetColorMask (false); | |
2160 | aCtx->SetAllowSampleAlphaToCoverage (false); | |
2161 | aCtx->SetSampleAlphaToCoverage (false); | |
2162 | ||
2163 | myWorkspace->UseZBuffer() = true; | |
2164 | myWorkspace->UseDepthWrite() = true; | |
2165 | aCtx->core11fwd->glDepthFunc (GL_LEQUAL); | |
2166 | aCtx->core11fwd->glDepthMask (GL_TRUE); | |
2167 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); | |
2168 | aCtx->core11fwd->glClearDepth (1.0); | |
2169 | aCtx->core11fwd->glClear (GL_DEPTH_BUFFER_BIT); | |
2170 | ||
2171 | renderScene (Graphic3d_Camera::Projection_Orthographic, aShadowBuffer.get(), NULL, false); | |
2172 | ||
2173 | aCtx->SetColorMask (true); | |
2174 | myWorkspace->ResetAppliedAspect(); | |
2175 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
2176 | ||
2177 | //Image_AlienPixMap anImage; anImage.InitZero (Image_Format_Gray, aShadowBuffer->GetVPSizeX(), aShadowBuffer->GetVPSizeY()); | |
2178 | //OpenGl_FrameBuffer::BufferDump (aCtx, aShadowBuffer, anImage, Graphic3d_BT_Depth); | |
2179 | //anImage.Save (TCollection_AsciiString ("shadow") + theShadowMap->Texture()->Sampler()->Parameters()->TextureUnit() + ".png"); | |
2180 | ||
2181 | bindDefaultFbo(); | |
2182 | } | |
2183 | ||
cfb54c0c | 2184 | //======================================================================= |
2185 | //function : Render | |
2186 | //purpose : | |
2187 | //======================================================================= | |
2188 | void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, | |
2189 | OpenGl_FrameBuffer* theOutputFBO, | |
2190 | OpenGl_FrameBuffer* theOitAccumFbo, | |
2191 | const Standard_Boolean theToDrawImmediate) | |
2192 | { | |
2193 | // ================================== | |
2194 | // Step 1: Prepare for render | |
2195 | // ================================== | |
2196 | ||
2197 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); | |
2198 | aContext->SetAllowSampleAlphaToCoverage (myRenderParams.ToEnableAlphaToCoverage | |
2199 | && theOutputFBO != NULL | |
2200 | && theOutputFBO->NbSamples() != 0); | |
2201 | ||
2202 | #if !defined(GL_ES_VERSION_2_0) | |
2203 | // Disable current clipping planes | |
43eddb47 | 2204 | if (aContext->core11ffp != NULL) |
cfb54c0c | 2205 | { |
2206 | const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes(); | |
2207 | for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId) | |
2208 | { | |
2209 | aContext->core11fwd->glDisable (aClipPlaneId); | |
2210 | } | |
2211 | } | |
2212 | #endif | |
2213 | ||
2214 | // update states of OpenGl_BVHTreeSelector (frustum culling algorithm); | |
2215 | // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale | |
2216 | myBVHSelector.SetViewVolume (myCamera); | |
2217 | myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); | |
2218 | myBVHSelector.CacheClipPtsProjections(); | |
2219 | ||
2220 | const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); | |
13b36bb1 | 2221 | const Handle(Graphic3d_LightSet)& aLights = myRenderParams.ShadingModel == Graphic3d_TypeOfShadingModel_Unlit ? myNoShadingLight : myLights; |
cfb54c0c | 2222 | Standard_Size aLightsRevision = 0; |
2223 | if (!aLights.IsNull()) | |
2224 | { | |
2225 | aLightsRevision = aLights->UpdateRevision(); | |
2226 | } | |
2227 | if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState | |
2228 | || aLightsRevision != myLightsRevision) | |
2229 | { | |
2230 | myLightsRevision = aLightsRevision; | |
d84e8669 | 2231 | aManager->UpdateLightSourceStateTo (aLights, SpecIBLMapLevels(), myShadowMaps->IsValid() ? myShadowMaps : Handle(OpenGl_ShadowMapArray)()); |
cfb54c0c | 2232 | myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); |
2233 | } | |
2234 | ||
2235 | // Update matrices if camera has changed. | |
2236 | Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); | |
2237 | if (myWorldViewProjState != aWVPState) | |
2238 | { | |
2239 | myAccumFrames = 0; | |
2240 | myWorldViewProjState = aWVPState; | |
2241 | } | |
2242 | ||
2243 | myLocalOrigin.SetCoord (0.0, 0.0, 0.0); | |
2244 | aContext->SetCamera (myCamera); | |
2245 | if (aManager->ModelWorldState().Index() == 0) | |
2246 | { | |
2247 | aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); | |
2248 | } | |
2249 | ||
2250 | // ==================================== | |
2251 | // Step 2: Redraw background | |
2252 | // ==================================== | |
2253 | ||
2254 | // Render background | |
2255 | if (!theToDrawImmediate) | |
2256 | { | |
2257 | drawBackground (myWorkspace, theProjection); | |
2258 | } | |
2259 | ||
2260 | #if !defined(GL_ES_VERSION_2_0) | |
2261 | // Switch off lighting by default | |
43eddb47 | 2262 | if (aContext->core11ffp != NULL |
cfb54c0c | 2263 | && aContext->caps->ffpEnable) |
2264 | { | |
43eddb47 | 2265 | aContext->core11fwd->glDisable (GL_LIGHTING); |
cfb54c0c | 2266 | } |
2267 | #endif | |
2268 | ||
2269 | // ================================= | |
2270 | // Step 3: Redraw main plane | |
2271 | // ================================= | |
2272 | ||
cfb54c0c | 2273 | #if !defined(GL_ES_VERSION_2_0) |
2274 | // if the view is scaled normal vectors are scaled to unit | |
2275 | // length for correct displaying of shaded objects | |
2276 | const gp_Pnt anAxialScale = aContext->Camera()->AxialScale(); | |
2277 | if (anAxialScale.X() != 1.F || | |
2278 | anAxialScale.Y() != 1.F || | |
2279 | anAxialScale.Z() != 1.F) | |
2280 | { | |
2281 | aContext->SetGlNormalizeEnabled (Standard_True); | |
2282 | } | |
2283 | else | |
2284 | { | |
2285 | aContext->SetGlNormalizeEnabled (Standard_False); | |
2286 | } | |
2287 | #endif | |
2288 | ||
114db5a5 | 2289 | aManager->SetShadingModel (OpenGl_ShaderManager::PBRShadingModelFallback (myRenderParams.ShadingModel, checkPBRAvailability())); |
cfb54c0c | 2290 | |
2291 | // Redraw 3d scene | |
2292 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) | |
2293 | { | |
2294 | aContext->ProjectionState.SetCurrent (aContext->Camera()->ProjectionStereoLeftF()); | |
2295 | aContext->ApplyProjectionMatrix(); | |
2296 | } | |
2297 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) | |
2298 | { | |
2299 | aContext->ProjectionState.SetCurrent (aContext->Camera()->ProjectionStereoRightF()); | |
2300 | aContext->ApplyProjectionMatrix(); | |
2301 | } | |
2302 | ||
2303 | myWorkspace->SetEnvironmentTexture (myTextureEnv); | |
2304 | ||
d84e8669 | 2305 | const bool hasShadowMap = aContext->ShaderManager()->LightSourceState().HasShadowMaps(); |
2306 | if (hasShadowMap) | |
2307 | { | |
2308 | for (Standard_Integer aShadowIter = myShadowMaps->Lower(); aShadowIter <= myShadowMaps->Upper(); ++aShadowIter) | |
2309 | { | |
2310 | const Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->Value (aShadowIter); | |
2311 | aShadow->Texture()->Bind (aContext); | |
2312 | } | |
2313 | } | |
2314 | ||
cfb54c0c | 2315 | renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate); |
2316 | ||
d84e8669 | 2317 | if (hasShadowMap) |
2318 | { | |
2319 | for (Standard_Integer aShadowIter = myShadowMaps->Lower(); aShadowIter <= myShadowMaps->Upper(); ++aShadowIter) | |
2320 | { | |
2321 | const Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->Value (aShadowIter); | |
2322 | aShadow->Texture()->Unbind (aContext); | |
2323 | } | |
2324 | if (aContext->core15fwd != NULL) | |
2325 | { | |
2326 | aContext->core15fwd->glActiveTexture (GL_TEXTURE0); | |
2327 | } | |
2328 | } | |
2329 | ||
cfb54c0c | 2330 | myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); |
2331 | ||
2332 | // =============================== | |
2333 | // Step 4: Trihedron | |
2334 | // =============================== | |
2335 | ||
2336 | // Resetting GL parameters according to the default aspects | |
2337 | // in order to synchronize GL state with the graphic driver state | |
2338 | // before drawing auxiliary stuff (trihedrons, overlayer) | |
2339 | myWorkspace->ResetAppliedAspect(); | |
2340 | ||
2341 | // Render trihedron | |
2342 | if (!theToDrawImmediate) | |
2343 | { | |
2344 | renderTrihedron (myWorkspace); | |
cfb54c0c | 2345 | } |
2346 | else | |
2347 | { | |
2348 | renderFrameStats(); | |
2349 | } | |
2350 | ||
2351 | myWorkspace->ResetAppliedAspect(); | |
2352 | aContext->SetAllowSampleAlphaToCoverage (false); | |
2353 | aContext->SetSampleAlphaToCoverage (false); | |
2354 | ||
2355 | // reset FFP state for safety | |
2356 | aContext->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
2357 | if (aContext->caps->ffpEnable) | |
2358 | { | |
2359 | aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); | |
2360 | } | |
cfb54c0c | 2361 | } |
2362 | ||
2363 | // ======================================================================= | |
2364 | // function : InvalidateBVHData | |
2365 | // purpose : | |
2366 | // ======================================================================= | |
2367 | void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) | |
2368 | { | |
2369 | myZLayers.InvalidateBVHData (theLayerId); | |
2370 | } | |
2371 | ||
2372 | //======================================================================= | |
2373 | //function : renderStructs | |
2374 | //purpose : | |
2375 | //======================================================================= | |
2376 | void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection, | |
2377 | OpenGl_FrameBuffer* theReadDrawFbo, | |
2378 | OpenGl_FrameBuffer* theOitAccumFbo, | |
2379 | const Standard_Boolean theToDrawImmediate) | |
2380 | { | |
2381 | myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate); | |
2382 | if ( myZLayers.NbStructures() <= 0 ) | |
2383 | return; | |
2384 | ||
2385 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
2386 | Standard_Boolean toRenderGL = theToDrawImmediate || | |
2387 | myRenderParams.Method != Graphic3d_RM_RAYTRACING || | |
2388 | myRaytraceInitStatus == OpenGl_RT_FAIL || | |
2389 | aCtx->IsFeedback(); | |
2390 | ||
2391 | if (!toRenderGL) | |
2392 | { | |
1220d98e | 2393 | const Graphic3d_Vec2i aSizeXY = theReadDrawFbo != NULL |
2394 | ? theReadDrawFbo->GetVPSize() | |
2395 | : Graphic3d_Vec2i (myWindow->Width(), myWindow->Height()); | |
cfb54c0c | 2396 | |
1220d98e | 2397 | toRenderGL = !initRaytraceResources (aSizeXY.x(), aSizeXY.y(), aCtx) |
cfb54c0c | 2398 | || !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx); |
2399 | ||
2400 | toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL | |
2401 | ||
2402 | if (!toRenderGL) | |
2403 | { | |
1220d98e | 2404 | myOpenGlFBO ->InitLazy (aCtx, aSizeXY, myFboColorFormat, myFboDepthFormat, 0); |
cfb54c0c | 2405 | if (theReadDrawFbo != NULL) |
1220d98e | 2406 | { |
cfb54c0c | 2407 | theReadDrawFbo->UnbindBuffer (aCtx); |
1220d98e | 2408 | } |
cfb54c0c | 2409 | |
2410 | // Prepare preliminary OpenGL output | |
2411 | if (aCtx->arbFBOBlit != NULL) | |
2412 | { | |
2413 | // Render bottom OSD layer | |
2414 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo); | |
2415 | ||
2416 | const Standard_Integer aPrevFilter = myWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_NonRaytraceableOnly); | |
2417 | myWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_NonRaytraceableOnly); | |
2418 | { | |
2419 | if (theReadDrawFbo != NULL) | |
2420 | { | |
2421 | theReadDrawFbo->BindDrawBuffer (aCtx); | |
2422 | } | |
2423 | else | |
2424 | { | |
2425 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); | |
2426 | aCtx->SetFrameBufferSRGB (false); | |
2427 | } | |
2428 | ||
2429 | // Render non-polygonal elements in default layer | |
2430 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_RayTracable, theReadDrawFbo, theOitAccumFbo); | |
2431 | } | |
2432 | myWorkspace->SetRenderFilter (aPrevFilter); | |
2433 | } | |
2434 | ||
2435 | if (theReadDrawFbo != NULL) | |
2436 | { | |
2437 | theReadDrawFbo->BindBuffer (aCtx); | |
2438 | } | |
2439 | else | |
2440 | { | |
2441 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0); | |
2442 | aCtx->SetFrameBufferSRGB (false); | |
2443 | } | |
2444 | ||
2445 | // Reset OpenGl aspects state to default to avoid enabling of | |
2446 | // backface culling which is not supported in ray-tracing. | |
2447 | myWorkspace->ResetAppliedAspect(); | |
2448 | ||
2449 | // Ray-tracing polygonal primitive arrays | |
1220d98e | 2450 | raytrace (aSizeXY.x(), aSizeXY.y(), theProjection, theReadDrawFbo, aCtx); |
cfb54c0c | 2451 | |
2452 | // Render upper (top and topmost) OpenGL layers | |
2453 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo); | |
2454 | } | |
2455 | } | |
2456 | ||
2457 | // Redraw 3D scene using OpenGL in standard | |
2458 | // mode or in case of ray-tracing failure | |
2459 | if (toRenderGL) | |
2460 | { | |
2461 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo); | |
2462 | ||
2463 | // Set flag that scene was redrawn by standard pipeline | |
2464 | myWasRedrawnGL = Standard_True; | |
2465 | } | |
2466 | } | |
2467 | ||
2468 | //======================================================================= | |
2469 | //function : renderTrihedron | |
2470 | //purpose : | |
2471 | //======================================================================= | |
2472 | void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace) | |
2473 | { | |
2474 | if (myToShowGradTrihedron) | |
2475 | { | |
2476 | myGraduatedTrihedron.Render (theWorkspace); | |
2477 | } | |
2478 | } | |
2479 | ||
2480 | //======================================================================= | |
2481 | //function : renderFrameStats | |
2482 | //purpose : | |
2483 | //======================================================================= | |
2484 | void OpenGl_View::renderFrameStats() | |
2485 | { | |
2486 | if (myRenderParams.ToShowStats | |
2487 | && myRenderParams.CollectedStats != Graphic3d_RenderingParams::PerfCounters_NONE) | |
2488 | { | |
2489 | myFrameStatsPrs.Update (myWorkspace); | |
2490 | myFrameStatsPrs.Render (myWorkspace); | |
2491 | } | |
2492 | } | |
2493 | ||
2494 | // ======================================================================= | |
2495 | // function : Invalidate | |
2496 | // purpose : | |
2497 | // ======================================================================= | |
2498 | void OpenGl_View::Invalidate() | |
2499 | { | |
2500 | myBackBufferRestored = Standard_False; | |
2501 | } | |
2502 | ||
2503 | //======================================================================= | |
2504 | //function : renderScene | |
2505 | //purpose : | |
2506 | //======================================================================= | |
2507 | void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, | |
2508 | OpenGl_FrameBuffer* theReadDrawFbo, | |
2509 | OpenGl_FrameBuffer* theOitAccumFbo, | |
2510 | const Standard_Boolean theToDrawImmediate) | |
2511 | { | |
2512 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); | |
2513 | ||
2514 | // Specify clipping planes in view transformation space | |
2515 | aContext->ChangeClipping().Reset (myClipPlanes); | |
2516 | if (!myClipPlanes.IsNull() | |
2517 | && !myClipPlanes->IsEmpty()) | |
2518 | { | |
2519 | aContext->ShaderManager()->UpdateClippingState(); | |
2520 | } | |
2521 | ||
2522 | renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate); | |
2523 | aContext->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); | |
2524 | ||
2525 | // Apply restored view matrix. | |
2526 | aContext->ApplyWorldViewMatrix(); | |
2527 | ||
2528 | aContext->ChangeClipping().Reset (Handle(Graphic3d_SequenceOfHClipPlane)()); | |
2529 | if (!myClipPlanes.IsNull() | |
2530 | && !myClipPlanes->IsEmpty()) | |
2531 | { | |
2532 | aContext->ShaderManager()->RevertClippingState(); | |
2533 | } | |
2534 | } | |
2535 | ||
2536 | // ======================================================================= | |
2537 | // function : bindDefaultFbo | |
2538 | // purpose : | |
2539 | // ======================================================================= | |
2540 | void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) | |
2541 | { | |
2542 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
2543 | OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) | |
2544 | ? theCustomFbo | |
2545 | : (!aCtx->DefaultFrameBuffer().IsNull() | |
2546 | && aCtx->DefaultFrameBuffer()->IsValid() | |
2547 | ? aCtx->DefaultFrameBuffer().operator->() | |
2548 | : NULL); | |
2549 | if (anFbo != NULL) | |
2550 | { | |
2551 | anFbo->BindBuffer (aCtx); | |
2552 | anFbo->SetupViewport (aCtx); | |
2553 | } | |
2554 | else | |
2555 | { | |
2556 | #if !defined(GL_ES_VERSION_2_0) | |
2557 | aCtx->SetReadDrawBuffer (GL_BACK); | |
2558 | #else | |
2559 | if (aCtx->arbFBO != NULL) | |
2560 | { | |
2561 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
2562 | } | |
2563 | #endif | |
2564 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; | |
2565 | aCtx->ResizeViewport (aViewport); | |
2566 | } | |
2567 | } | |
2568 | ||
2569 | // ======================================================================= | |
2570 | // function : initBlitQuad | |
2571 | // purpose : | |
2572 | // ======================================================================= | |
2573 | OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip) | |
2574 | { | |
2575 | OpenGl_VertexBuffer* aVerts = NULL; | |
2576 | if (!theToFlip) | |
2577 | { | |
2578 | aVerts = &myFullScreenQuad; | |
2579 | if (!aVerts->IsValid()) | |
2580 | { | |
2581 | OpenGl_Vec4 aQuad[4] = | |
2582 | { | |
2583 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), | |
2584 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), | |
2585 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), | |
2586 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) | |
2587 | }; | |
2588 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); | |
2589 | } | |
2590 | } | |
2591 | else | |
2592 | { | |
2593 | aVerts = &myFullScreenQuadFlip; | |
2594 | if (!aVerts->IsValid()) | |
2595 | { | |
2596 | OpenGl_Vec4 aQuad[4] = | |
2597 | { | |
2598 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), | |
2599 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), | |
2600 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), | |
2601 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) | |
2602 | }; | |
2603 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); | |
2604 | } | |
2605 | } | |
2606 | return aVerts; | |
2607 | } | |
2608 | ||
2609 | // ======================================================================= | |
2610 | // function : blitBuffers | |
2611 | // purpose : | |
2612 | // ======================================================================= | |
2613 | bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, | |
2614 | OpenGl_FrameBuffer* theDrawFbo, | |
2615 | const Standard_Boolean theToFlip) | |
2616 | { | |
2617 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); | |
2618 | const Standard_Integer aReadSizeX = theReadFbo != NULL ? theReadFbo->GetVPSizeX() : myWindow->Width(); | |
2619 | const Standard_Integer aReadSizeY = theReadFbo != NULL ? theReadFbo->GetVPSizeY() : myWindow->Height(); | |
2620 | const Standard_Integer aDrawSizeX = theDrawFbo != NULL ? theDrawFbo->GetVPSizeX() : myWindow->Width(); | |
2621 | const Standard_Integer aDrawSizeY = theDrawFbo != NULL ? theDrawFbo->GetVPSizeY() : myWindow->Height(); | |
2622 | if (theReadFbo == NULL || aCtx->IsFeedback()) | |
2623 | { | |
2624 | return false; | |
2625 | } | |
2626 | else if (theReadFbo == theDrawFbo) | |
2627 | { | |
2628 | return true; | |
2629 | } | |
2630 | ||
2631 | // clear destination before blitting | |
2632 | if (theDrawFbo != NULL | |
2633 | && theDrawFbo->IsValid()) | |
2634 | { | |
2635 | theDrawFbo->BindBuffer (aCtx); | |
2636 | } | |
2637 | else | |
2638 | { | |
2639 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
2640 | aCtx->SetFrameBufferSRGB (false); | |
2641 | } | |
2642 | const Standard_Integer aViewport[4] = { 0, 0, aDrawSizeX, aDrawSizeY }; | |
2643 | aCtx->ResizeViewport (aViewport); | |
2644 | ||
2645 | aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha | |
2646 | aCtx->core20fwd->glClearDepth (1.0); | |
57357010 | 2647 | aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, aCtx->caps->buffersOpaqueAlpha ? 1.0f : 0.0f); |
cfb54c0c | 2648 | aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
2649 | aCtx->SetColorMask (true); // restore default alpha component write state | |
2650 | ||
2651 | const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB(); | |
2652 | if (aCtx->arbFBOBlit != NULL | |
2653 | && !toApplyGamma | |
2654 | && theReadFbo->NbSamples() != 0) | |
2655 | { | |
2656 | GLbitfield aCopyMask = 0; | |
2657 | theReadFbo->BindReadBuffer (aCtx); | |
2658 | if (theDrawFbo != NULL | |
2659 | && theDrawFbo->IsValid()) | |
2660 | { | |
2661 | theDrawFbo->BindDrawBuffer (aCtx); | |
2662 | if (theDrawFbo->HasColor() | |
2663 | && theReadFbo->HasColor()) | |
2664 | { | |
2665 | aCopyMask |= GL_COLOR_BUFFER_BIT; | |
2666 | } | |
2667 | if (theDrawFbo->HasDepth() | |
2668 | && theReadFbo->HasDepth()) | |
2669 | { | |
2670 | aCopyMask |= GL_DEPTH_BUFFER_BIT; | |
2671 | } | |
2672 | } | |
2673 | else | |
2674 | { | |
2675 | if (theReadFbo->HasColor()) | |
2676 | { | |
2677 | aCopyMask |= GL_COLOR_BUFFER_BIT; | |
2678 | } | |
2679 | if (theReadFbo->HasDepth()) | |
2680 | { | |
2681 | aCopyMask |= GL_DEPTH_BUFFER_BIT; | |
2682 | } | |
2683 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
2684 | aCtx->SetFrameBufferSRGB (false); | |
2685 | } | |
2686 | ||
2687 | // we don't copy stencil buffer here... does it matter for performance? | |
2688 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aReadSizeX, aReadSizeY, | |
2689 | 0, 0, aDrawSizeX, aDrawSizeY, | |
2690 | aCopyMask, GL_NEAREST); | |
a46ab511 | 2691 | const int anErr = aCtx->core11fwd->glGetError(); |
cfb54c0c | 2692 | if (anErr != GL_NO_ERROR) |
2693 | { | |
2694 | // glBlitFramebuffer() might fail in several cases: | |
2695 | // - Both FBOs have MSAA and they are samples number does not match. | |
2696 | // OCCT checks that this does not happen, | |
2697 | // however some graphics drivers provide an option for overriding MSAA. | |
2698 | // In this case window MSAA might be non-zero (and application can not check it) | |
2699 | // and might not match MSAA of our offscreen FBOs. | |
2700 | // - Pixel formats of FBOs do not match. | |
2701 | // This also might happen with window has pixel format, | |
2702 | // e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion. | |
a46ab511 | 2703 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error " + OpenGl_Context::FormatGlError (anErr) + "]\n" |
cfb54c0c | 2704 | + " Please check your graphics driver settings or try updating driver."; |
2705 | if (theReadFbo->NbSamples() != 0) | |
2706 | { | |
2707 | myToDisableMSAA = true; | |
2708 | aMsg += "\n MSAA settings should not be overridden by driver!"; | |
2709 | } | |
a46ab511 | 2710 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); |
cfb54c0c | 2711 | } |
2712 | ||
2713 | if (theDrawFbo != NULL | |
2714 | && theDrawFbo->IsValid()) | |
2715 | { | |
2716 | theDrawFbo->BindBuffer (aCtx); | |
2717 | } | |
2718 | else | |
2719 | { | |
2720 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); | |
2721 | aCtx->SetFrameBufferSRGB (false); | |
2722 | } | |
2723 | } | |
2724 | else | |
2725 | { | |
2726 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); | |
2727 | aCtx->core20fwd->glDepthMask (GL_TRUE); | |
2728 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); | |
2729 | #if defined(GL_ES_VERSION_2_0) | |
2730 | if (!aCtx->IsGlGreaterEqual (3, 0) | |
2731 | && !aCtx->extFragDepth) | |
2732 | { | |
2733 | aCtx->core20fwd->glDisable (GL_DEPTH_TEST); | |
2734 | } | |
2735 | #endif | |
2736 | ||
2737 | aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); | |
2738 | ||
2739 | const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR; | |
2740 | const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR; | |
2741 | ||
2742 | OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); | |
2743 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); | |
2744 | if (aVerts->IsValid() | |
2745 | && aManager->BindFboBlitProgram (theReadFbo != NULL ? theReadFbo->NbSamples() : 0, toApplyGamma)) | |
2746 | { | |
2747 | aCtx->SetSampleAlphaToCoverage (false); | |
2748 | theReadFbo->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); | |
2749 | if (theReadFbo->ColorTexture()->Sampler()->Parameters()->Filter() != aFilter) | |
2750 | { | |
2751 | theReadFbo->ColorTexture()->Sampler()->Parameters()->SetFilter (aFilter); | |
2752 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); | |
2753 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); | |
2754 | } | |
2755 | ||
2756 | theReadFbo->DepthStencilTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); | |
2757 | if (theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->Filter() != aFilter) | |
2758 | { | |
2759 | theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->SetFilter (aFilter); | |
2760 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl); | |
2761 | aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl); | |
2762 | } | |
2763 | ||
2764 | aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); | |
2765 | ||
2766 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | |
2767 | ||
2768 | aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS); | |
2769 | theReadFbo->DepthStencilTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); | |
2770 | theReadFbo->ColorTexture() ->Unbind (aCtx, Graphic3d_TextureUnit_0); | |
2771 | aCtx->BindProgram (NULL); | |
2772 | } | |
2773 | else | |
2774 | { | |
2775 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() | |
2776 | + "Error! FBO blitting has failed"; | |
2777 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, | |
2778 | GL_DEBUG_TYPE_ERROR, | |
2779 | 0, | |
2780 | GL_DEBUG_SEVERITY_HIGH, | |
2781 | aMsg); | |
2782 | myHasFboBlit = Standard_False; | |
2783 | theReadFbo->Release (aCtx.operator->()); | |
2784 | return true; | |
2785 | } | |
2786 | } | |
2787 | return true; | |
2788 | } | |
2789 | ||
2790 | // ======================================================================= | |
2791 | // function : drawStereoPair | |
2792 | // purpose : | |
2793 | // ======================================================================= | |
2794 | void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) | |
2795 | { | |
2796 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
2797 | bindDefaultFbo (theDrawFbo); | |
2798 | OpenGl_FrameBuffer* aPair[2] = | |
2799 | { | |
2800 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, | |
2801 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL | |
2802 | }; | |
2803 | if (aPair[0] == NULL | |
2804 | || aPair[1] == NULL | |
2805 | || !myTransientDrawToFront) | |
2806 | { | |
2807 | aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; | |
2808 | aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; | |
2809 | } | |
2810 | ||
2811 | if (aPair[0] == NULL | |
2812 | || aPair[1] == NULL) | |
2813 | { | |
2814 | return; | |
2815 | } | |
2816 | ||
2817 | if (aPair[0]->NbSamples() != 0) | |
2818 | { | |
2819 | // resolve MSAA buffers before drawing | |
1220d98e | 2820 | if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSize(), myFboColorFormat, myFboDepthFormat, 0) |
2821 | || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSize(), myFboColorFormat, 0, 0)) | |
cfb54c0c | 2822 | { |
2823 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, | |
2824 | GL_DEBUG_TYPE_ERROR, | |
2825 | 0, | |
2826 | GL_DEBUG_SEVERITY_HIGH, | |
2827 | "Error! Unable to allocate FBO for blitting stereo pair"); | |
2828 | bindDefaultFbo (theDrawFbo); | |
2829 | return; | |
2830 | } | |
2831 | ||
2832 | if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False) | |
2833 | || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False)) | |
2834 | { | |
2835 | bindDefaultFbo (theDrawFbo); | |
2836 | return; | |
2837 | } | |
2838 | ||
2839 | aPair[0] = myOpenGlFBO .operator->(); | |
2840 | aPair[1] = myOpenGlFBO2.operator->(); | |
2841 | bindDefaultFbo (theDrawFbo); | |
2842 | } | |
2843 | ||
2844 | struct | |
2845 | { | |
2846 | Standard_Integer left; | |
2847 | Standard_Integer top; | |
2848 | Standard_Integer right; | |
2849 | Standard_Integer bottom; | |
2850 | Standard_Integer dx() { return right - left; } | |
2851 | Standard_Integer dy() { return bottom - top; } | |
2852 | } aGeom; | |
2853 | ||
2854 | myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom); | |
2855 | ||
2856 | Standard_Boolean toReverse = myRenderParams.ToReverseStereo; | |
2857 | const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1; | |
2858 | const Standard_Boolean isOddX = aGeom.left % 2 == 1; | |
2859 | if (isOddY | |
2860 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced | |
2861 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) | |
2862 | { | |
2863 | toReverse = !toReverse; | |
2864 | } | |
2865 | if (isOddX | |
2866 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced | |
2867 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) | |
2868 | { | |
2869 | toReverse = !toReverse; | |
2870 | } | |
2871 | ||
2872 | if (toReverse) | |
2873 | { | |
2874 | std::swap (aPair[0], aPair[1]); | |
2875 | } | |
2876 | ||
2877 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); | |
2878 | aCtx->core20fwd->glDepthMask (GL_TRUE); | |
2879 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); | |
2880 | ||
2881 | aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); | |
2882 | OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); | |
2883 | ||
2884 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); | |
2885 | if (aVerts->IsValid() | |
2886 | && aManager->BindStereoProgram (myRenderParams.StereoMode)) | |
2887 | { | |
2888 | if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) | |
2889 | { | |
2890 | OpenGl_Mat4 aFilterL, aFilterR; | |
2891 | aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); | |
2892 | aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); | |
2893 | switch (myRenderParams.AnaglyphFilter) | |
2894 | { | |
2895 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: | |
2896 | { | |
2897 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); | |
2898 | aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); | |
2899 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); | |
2900 | break; | |
2901 | } | |
2902 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: | |
2903 | { | |
2904 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); | |
2905 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); | |
2906 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); | |
2907 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); | |
2908 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); | |
2909 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); | |
2910 | aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); | |
2911 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); | |
2912 | break; | |
2913 | } | |
2914 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: | |
2915 | { | |
2916 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); | |
2917 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); | |
2918 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); | |
2919 | break; | |
2920 | } | |
2921 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: | |
2922 | { | |
2923 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); | |
2924 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); | |
2925 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); | |
2926 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); | |
2927 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); | |
2928 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); | |
2929 | aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); | |
2930 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); | |
2931 | break; | |
2932 | } | |
2933 | case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: | |
2934 | { | |
2935 | aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); | |
2936 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); | |
2937 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); | |
2938 | break; | |
2939 | } | |
2940 | case Graphic3d_RenderingParams::Anaglyph_UserDefined: | |
2941 | { | |
2942 | aFilterL = myRenderParams.AnaglyphLeft; | |
2943 | aFilterR = myRenderParams.AnaglyphRight; | |
2944 | break; | |
2945 | } | |
2946 | } | |
2947 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL); | |
2948 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR); | |
2949 | } | |
2950 | ||
2951 | aPair[0]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0); | |
2952 | aPair[1]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_1); | |
2953 | aVerts->BindVertexAttrib (aCtx, 0); | |
2954 | ||
2955 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | |
2956 | ||
2957 | aVerts->UnbindVertexAttrib (aCtx, 0); | |
2958 | aPair[1]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1); | |
2959 | aPair[0]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_0); | |
2960 | } | |
2961 | else | |
2962 | { | |
2963 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() | |
2964 | + "Error! Anaglyph has failed"; | |
2965 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, | |
2966 | GL_DEBUG_TYPE_ERROR, | |
2967 | 0, | |
2968 | GL_DEBUG_SEVERITY_HIGH, | |
2969 | aMsg); | |
2970 | } | |
2971 | } | |
2972 | ||
2973 | // ======================================================================= | |
2974 | // function : copyBackToFront | |
2975 | // purpose : | |
2976 | // ======================================================================= | |
2977 | bool OpenGl_View::copyBackToFront() | |
2978 | { | |
2979 | myIsImmediateDrawn = Standard_False; | |
2980 | #if !defined(GL_ES_VERSION_2_0) | |
2981 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); | |
43eddb47 | 2982 | if (aCtx->core11ffp == NULL) |
cfb54c0c | 2983 | { |
2984 | return false; | |
2985 | } | |
2986 | ||
2987 | OpenGl_Mat4 aProjectMat; | |
2988 | Graphic3d_TransformUtils::Ortho2D (aProjectMat, | |
2989 | 0.0f, static_cast<GLfloat> (myWindow->Width()), | |
2990 | 0.0f, static_cast<GLfloat> (myWindow->Height())); | |
2991 | ||
2992 | aCtx->WorldViewState.Push(); | |
2993 | aCtx->ProjectionState.Push(); | |
2994 | ||
2995 | aCtx->WorldViewState.SetIdentity(); | |
2996 | aCtx->ProjectionState.SetCurrent (aProjectMat); | |
2997 | ||
2998 | aCtx->ApplyProjectionMatrix(); | |
2999 | aCtx->ApplyWorldViewMatrix(); | |
3000 | ||
3001 | // synchronize FFP state before copying pixels | |
3002 | aCtx->BindProgram (Handle(OpenGl_ShaderProgram)()); | |
3003 | aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); | |
3004 | aCtx->DisableFeatures(); | |
3005 | ||
3006 | switch (aCtx->DrawBuffer()) | |
3007 | { | |
3008 | case GL_BACK_LEFT: | |
3009 | { | |
3010 | aCtx->SetReadBuffer (GL_BACK_LEFT); | |
3011 | aCtx->SetDrawBuffer (GL_FRONT_LEFT); | |
3012 | break; | |
3013 | } | |
3014 | case GL_BACK_RIGHT: | |
3015 | { | |
3016 | aCtx->SetReadBuffer (GL_BACK_RIGHT); | |
3017 | aCtx->SetDrawBuffer (GL_FRONT_RIGHT); | |
3018 | break; | |
3019 | } | |
3020 | default: | |
3021 | { | |
3022 | aCtx->SetReadBuffer (GL_BACK); | |
3023 | aCtx->SetDrawBuffer (GL_FRONT); | |
3024 | break; | |
3025 | } | |
3026 | } | |
3027 | ||
43eddb47 | 3028 | aCtx->core11ffp->glRasterPos2i (0, 0); |
3029 | aCtx->core11ffp->glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR); | |
3030 | //aCtx->core11ffp->glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); | |
cfb54c0c | 3031 | |
3032 | aCtx->EnableFeatures(); | |
3033 | ||
3034 | aCtx->WorldViewState.Pop(); | |
3035 | aCtx->ProjectionState.Pop(); | |
3036 | aCtx->ApplyProjectionMatrix(); | |
3037 | ||
3038 | // read/write from front buffer now | |
3039 | aCtx->SetReadBuffer (aCtx->DrawBuffer()); | |
3040 | return true; | |
3041 | #else | |
3042 | return false; | |
3043 | #endif | |
3044 | } | |
3045 | ||
3046 | // ======================================================================= | |
3047 | // function : checkOitCompatibility | |
3048 | // purpose : | |
3049 | // ======================================================================= | |
3050 | Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext, | |
3051 | const Standard_Boolean theMSAA) | |
3052 | { | |
3053 | // determine if OIT is supported by current OpenGl context | |
3054 | Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT; | |
3055 | if (aToDisableOIT) | |
3056 | { | |
3057 | return Standard_False; | |
3058 | } | |
3059 | ||
3060 | TCollection_ExtendedString aCompatibilityMsg; | |
3061 | if (theGlContext->hasFloatBuffer == OpenGl_FeatureNotAvailable | |
3062 | && theGlContext->hasHalfFloatBuffer == OpenGl_FeatureNotAvailable) | |
3063 | { | |
3064 | aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n"; | |
3065 | } | |
3066 | if (theMSAA && theGlContext->hasSampleVariables == OpenGl_FeatureNotAvailable) | |
3067 | { | |
3068 | aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n"; | |
3069 | } | |
3070 | if (theGlContext->hasDrawBuffers == OpenGl_FeatureNotAvailable) | |
3071 | { | |
3072 | aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n"; | |
3073 | } | |
3074 | if (aCompatibilityMsg.IsEmpty()) | |
3075 | { | |
3076 | return Standard_True; | |
3077 | } | |
3078 | ||
3079 | aCompatibilityMsg += " Blended order-independent transparency will not be available.\n"; | |
3080 | theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, | |
3081 | GL_DEBUG_TYPE_ERROR, | |
3082 | 0, | |
3083 | GL_DEBUG_SEVERITY_HIGH, | |
3084 | aCompatibilityMsg); | |
3085 | ||
3086 | aToDisableOIT = Standard_True; | |
3087 | return Standard_False; | |
3088 | } | |
3089 | ||
cfb54c0c | 3090 | // ======================================================================= |
3091 | // function : checkPBRAvailability | |
3092 | // purpose : | |
3093 | // ======================================================================= | |
3094 | Standard_Boolean OpenGl_View::checkPBRAvailability() const | |
3095 | { | |
3096 | return myWorkspace->GetGlContext()->HasPBR() | |
3097 | && !myPBREnvironment.IsNull(); | |
3098 | } | |
3099 | ||
3100 | // ======================================================================= | |
3e9cb806 | 3101 | // function : updatePBREnvironment |
cfb54c0c | 3102 | // purpose : |
3103 | // ======================================================================= | |
3e9cb806 | 3104 | void OpenGl_View::updatePBREnvironment (const Handle(OpenGl_Context)& theCtx) |
cfb54c0c | 3105 | { |
3e9cb806 | 3106 | if (myPBREnvState != OpenGl_PBREnvState_CREATED |
3107 | || !myPBREnvRequest) | |
3108 | { | |
3109 | myPBREnvRequest = false; | |
3110 | return; | |
3111 | } | |
3112 | ||
3113 | myPBREnvRequest = false; | |
3114 | ||
3115 | Handle(OpenGl_TextureSet) aGlTextureSet; | |
3116 | OpenGl_Aspects* aTmpGlAspects = NULL; | |
3117 | if (!myCubeMapIBL.IsNull() | |
3118 | && myCubeMapIBL == myCubeMapBackground) | |
3119 | { | |
3120 | aGlTextureSet = myCubeMapParams->TextureSet (theCtx); | |
3121 | } | |
3122 | else if (!myCubeMapIBL.IsNull()) | |
3123 | { | |
3124 | myCubeMapIBL->SetMipmapsGeneration (Standard_True); | |
3125 | ||
3126 | Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d(); | |
3127 | { | |
3128 | Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (myCubeMapIBL); | |
3129 | anAspect->SetInteriorStyle (Aspect_IS_SOLID); | |
3130 | anAspect->SetTextureSet (aTextureSet); | |
3131 | anAspect->SetTextureMapOn (true); | |
3132 | } | |
3133 | ||
3134 | aTmpGlAspects = new OpenGl_Aspects(); | |
3135 | aTmpGlAspects->SetAspect (anAspect); | |
3136 | aGlTextureSet = aTmpGlAspects->TextureSet (theCtx); | |
3137 | } | |
3138 | ||
3139 | if (!aGlTextureSet.IsNull() | |
3140 | && !aGlTextureSet->IsEmpty()) | |
cfb54c0c | 3141 | { |
3142 | myPBREnvironment->Bake (theCtx, | |
3e9cb806 | 3143 | aGlTextureSet->First(), |
3144 | myCubeMapIBL->ZIsInverted(), | |
3145 | myCubeMapIBL->IsTopDown(), | |
cfb54c0c | 3146 | myRenderParams.PbrEnvBakingDiffNbSamples, |
3147 | myRenderParams.PbrEnvBakingSpecNbSamples, | |
3148 | myRenderParams.PbrEnvBakingProbability); | |
3149 | } | |
3150 | else | |
3151 | { | |
3152 | myPBREnvironment->Clear (theCtx); | |
3153 | } | |
3e9cb806 | 3154 | aGlTextureSet.Nullify(); |
3155 | OpenGl_Element::Destroy (theCtx.get(), aTmpGlAspects); | |
cfb54c0c | 3156 | } |