c357e426 |
1 | // Created on: 2011-09-20 |
2 | // Created by: Sergey ZERCHANINOV |
3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <stdio.h> |
17 | #include <stdlib.h> |
18 | |
19 | #include <OpenGl_GlCore11.hxx> |
c357e426 |
20 | |
21 | #include <Graphic3d_GraphicDriver.hxx> |
22 | #include <Graphic3d_TextureParams.hxx> |
23 | #include <Graphic3d_Texture2Dmanual.hxx> |
24 | #include <Graphic3d_TransformUtils.hxx> |
25 | #include <Image_AlienPixMap.hxx> |
26 | |
27 | #include <NCollection_Mat4.hxx> |
28 | |
29 | #include <OpenGl_AspectLine.hxx> |
30 | #include <OpenGl_Context.hxx> |
31 | #include <OpenGl_Matrix.hxx> |
32 | #include <OpenGl_Workspace.hxx> |
33 | #include <OpenGl_View.hxx> |
34 | #include <OpenGl_Trihedron.hxx> |
35 | #include <OpenGl_GraduatedTrihedron.hxx> |
36 | #include <OpenGl_PrimitiveArray.hxx> |
c357e426 |
37 | #include <OpenGl_ShaderManager.hxx> |
38 | #include <OpenGl_ShaderProgram.hxx> |
39 | #include <OpenGl_Structure.hxx> |
40 | #include <OpenGl_ArbFBO.hxx> |
41 | |
42 | #define EPSI 0.0001 |
43 | |
44 | namespace |
45 | { |
46 | static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; |
47 | static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f }; |
48 | static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f; |
49 | static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f; |
50 | } |
51 | |
52 | extern void InitLayerProp (const int theListId); //szvgl: defined in OpenGl_GraphicDriver_Layer.cxx |
53 | |
54 | #if !defined(GL_ES_VERSION_2_0) |
55 | |
56 | //======================================================================= |
57 | //function : bindLight |
58 | //purpose : |
59 | //======================================================================= |
60 | static void bindLight (const OpenGl_Light& theLight, |
61 | GLenum& theLightGlId, |
62 | Graphic3d_Vec4& theAmbientColor, |
63 | const Handle(OpenGl_Workspace)& theWorkspace) |
64 | { |
65 | // Only 8 lights in OpenGL... |
66 | if (theLightGlId > GL_LIGHT7) |
67 | { |
68 | return; |
69 | } |
70 | |
71 | if (theLight.Type == Graphic3d_TOLS_AMBIENT) |
72 | { |
73 | // add RGBA intensity of the ambient light |
74 | theAmbientColor += theLight.Color; |
75 | return; |
76 | } |
77 | |
78 | const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext(); |
79 | |
80 | // the light is a headlight? |
81 | if (theLight.IsHeadlight) |
82 | { |
83 | aContext->WorldViewState.Push(); |
84 | aContext->WorldViewState.SetIdentity(); |
85 | |
86 | aContext->ApplyWorldViewMatrix(); |
87 | } |
88 | |
89 | // setup light type |
90 | switch (theLight.Type) |
91 | { |
92 | case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method |
93 | case Graphic3d_TOLS_DIRECTIONAL: |
94 | { |
95 | // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one |
96 | const OpenGl_Vec4 anInfDir = -theLight.Direction; |
97 | |
98 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE. |
99 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
100 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
101 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
102 | glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData()); |
103 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
104 | glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
105 | glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
106 | break; |
107 | } |
108 | case Graphic3d_TOLS_POSITIONAL: |
109 | { |
110 | // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE |
111 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
112 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
113 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
114 | glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData()); |
115 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR); |
116 | glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT); |
117 | glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF); |
118 | glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
119 | glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
120 | glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0); |
121 | break; |
122 | } |
123 | case Graphic3d_TOLS_SPOT: |
124 | { |
125 | glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT); |
126 | glLightfv (theLightGlId, GL_DIFFUSE, theLight.Color.GetData()); |
127 | glLightfv (theLightGlId, GL_SPECULAR, theLight.Color.GetData()); |
128 | glLightfv (theLightGlId, GL_POSITION, theLight.Position.GetData()); |
129 | glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.Direction.GetData()); |
130 | glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f); |
131 | glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI)); |
132 | glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation()); |
133 | glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation()); |
134 | glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f); |
135 | break; |
136 | } |
137 | } |
138 | |
139 | // restore matrix in case of headlight |
140 | if (theLight.IsHeadlight) |
141 | { |
142 | aContext->WorldViewState.Pop(); |
143 | } |
144 | |
145 | glEnable (theLightGlId++); |
146 | } |
147 | #endif |
148 | |
149 | //======================================================================= |
a521d90d |
150 | //function : drawBackground |
c357e426 |
151 | //purpose : |
152 | //======================================================================= |
a521d90d |
153 | void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace) |
c357e426 |
154 | { |
155 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
156 | |
157 | if ((theWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) != 0 // no background |
158 | || (!myBgTextureArray->IsDefined() // no texture |
159 | && !myBgGradientArray->IsDefined())) // no gradient |
160 | { |
161 | return; |
162 | } |
163 | |
164 | const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False); |
165 | if (wasUsedZBuffer) |
166 | { |
167 | aCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
168 | } |
169 | |
c357e426 |
170 | // Drawing background gradient if: |
171 | // - gradient fill type is not Aspect_GFM_NONE and |
172 | // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode |
173 | if (myBgGradientArray->IsDefined() |
b6472664 |
174 | && (!myTextureParams->Aspect()->ToMapTexture() |
c357e426 |
175 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_CENTERED |
176 | || myBgTextureArray->TextureFillMethod() == Aspect_FM_NONE)) |
177 | { |
178 | #if !defined(GL_ES_VERSION_2_0) |
179 | GLint aShadingModelOld = GL_SMOOTH; |
180 | if (aCtx->core11 != NULL) |
181 | { |
182 | aCtx->core11fwd->glDisable (GL_LIGHTING); |
183 | aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld); |
184 | aCtx->core11->glShadeModel (GL_SMOOTH); |
185 | } |
186 | #endif |
187 | |
c357e426 |
188 | myBgGradientArray->Render (theWorkspace); |
189 | |
190 | #if !defined(GL_ES_VERSION_2_0) |
191 | if (aCtx->core11 != NULL) |
192 | { |
193 | aCtx->core11->glShadeModel (aShadingModelOld); |
194 | } |
195 | #endif |
196 | } |
197 | |
198 | // Drawing background image if it is defined |
199 | // (texture is defined and fill type is not Aspect_FM_NONE) |
200 | if (myBgTextureArray->IsDefined() |
b6472664 |
201 | && myTextureParams->Aspect()->ToMapTexture()) |
c357e426 |
202 | { |
203 | aCtx->core11fwd->glDisable (GL_BLEND); |
204 | |
205 | const OpenGl_AspectFace* anOldAspectFace = theWorkspace->SetAspectFace (myTextureParams); |
c357e426 |
206 | myBgTextureArray->Render (theWorkspace); |
c357e426 |
207 | theWorkspace->SetAspectFace (anOldAspectFace); |
208 | } |
209 | |
c357e426 |
210 | if (wasUsedZBuffer) |
211 | { |
212 | theWorkspace->SetUseZBuffer (Standard_True); |
213 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); |
214 | } |
215 | } |
216 | |
217 | //======================================================================= |
218 | //function : Redraw |
219 | //purpose : |
220 | //======================================================================= |
221 | void OpenGl_View::Redraw() |
222 | { |
7ccf8676 |
223 | const Standard_Boolean wasDisabledMSAA = myToDisableMSAA; |
224 | const Standard_Boolean hadFboBlit = myHasFboBlit; |
c357e426 |
225 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
226 | && !myCaps->vboDisable |
227 | && !myCaps->keepArrayData) |
228 | { |
229 | if (myWasRedrawnGL) |
230 | { |
231 | myDeviceLostFlag = Standard_True; |
232 | } |
233 | |
234 | myCaps->keepArrayData = Standard_True; |
235 | } |
236 | |
237 | if (!myWorkspace->Activate()) |
238 | { |
239 | return; |
240 | } |
241 | |
242 | myWindow->SetSwapInterval(); |
243 | |
244 | ++myFrameCounter; |
245 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
246 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
247 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
248 | |
249 | // release pending GL resources |
250 | aCtx->ReleaseDelayed(); |
251 | |
252 | // fetch OpenGl context state |
253 | aCtx->FetchState(); |
254 | |
75c262a9 |
255 | // set resolution ratio |
256 | aCtx->SetResolutionRatio (RenderingParams().ResolutionRatio()); |
257 | |
b128c892 |
258 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->(); |
c357e426 |
259 | bool toSwap = aCtx->IsRender() |
260 | && !aCtx->caps->buffersNoSwap |
261 | && aFrameBuffer == NULL; |
262 | |
263 | Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width(); |
264 | Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height(); |
265 | |
3c4b62a4 |
266 | // determine multisampling parameters |
7ccf8676 |
267 | Standard_Integer aNbSamples = !myToDisableMSAA |
268 | ? Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0) |
269 | : 0; |
3c4b62a4 |
270 | if (aNbSamples != 0) |
271 | { |
272 | aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); |
273 | } |
274 | |
c357e426 |
275 | if ( aFrameBuffer == NULL |
276 | && !aCtx->DefaultFrameBuffer().IsNull() |
277 | && aCtx->DefaultFrameBuffer()->IsValid()) |
278 | { |
279 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
280 | } |
281 | |
282 | if (myHasFboBlit |
3c4b62a4 |
283 | && (myTransientDrawToFront |
284 | || aProjectType == Graphic3d_Camera::Projection_Stereo |
285 | || aNbSamples != 0)) |
c357e426 |
286 | { |
287 | if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX |
3c4b62a4 |
288 | || myMainSceneFbos[0]->GetVPSizeY() != aSizeY |
289 | || myMainSceneFbos[0]->NbSamples() != aNbSamples) |
c357e426 |
290 | { |
521b0d7f |
291 | if (!myTransientDrawToFront) |
292 | { |
293 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
294 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
295 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
296 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
297 | } |
298 | |
c357e426 |
299 | // prepare FBOs containing main scene |
300 | // for further blitting and rendering immediate presentations on top |
301 | if (aCtx->core20fwd != NULL) |
302 | { |
3c4b62a4 |
303 | myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples); |
c357e426 |
304 | } |
521b0d7f |
305 | if (myTransientDrawToFront |
306 | && !aCtx->caps->useSystemBuffer |
307 | && myMainSceneFbos[0]->IsValid()) |
c357e426 |
308 | { |
3c4b62a4 |
309 | myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
310 | } |
311 | } |
312 | } |
313 | else |
314 | { |
315 | myMainSceneFbos [0]->Release (aCtx.operator->()); |
316 | myMainSceneFbos [1]->Release (aCtx.operator->()); |
317 | myImmediateSceneFbos[0]->Release (aCtx.operator->()); |
318 | myImmediateSceneFbos[1]->Release (aCtx.operator->()); |
319 | myMainSceneFbos [0]->ChangeViewport (0, 0); |
320 | myMainSceneFbos [1]->ChangeViewport (0, 0); |
321 | myImmediateSceneFbos[0]->ChangeViewport (0, 0); |
322 | myImmediateSceneFbos[1]->ChangeViewport (0, 0); |
323 | } |
324 | |
325 | if (aProjectType == Graphic3d_Camera::Projection_Stereo |
326 | && myMainSceneFbos[0]->IsValid()) |
327 | { |
3c4b62a4 |
328 | myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
329 | if (!myMainSceneFbos[1]->IsValid()) |
330 | { |
331 | // no enough memory? |
332 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
333 | } |
334 | else if (!myTransientDrawToFront) |
335 | { |
336 | // |
337 | } |
338 | else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer) |
339 | { |
3c4b62a4 |
340 | myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]); |
341 | myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]); |
c357e426 |
342 | if (!myImmediateSceneFbos[0]->IsValid() |
343 | || !myImmediateSceneFbos[1]->IsValid()) |
344 | { |
345 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
346 | } |
347 | } |
348 | } |
349 | |
350 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
351 | { |
352 | OpenGl_FrameBuffer* aMainFbos[2] = |
353 | { |
354 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
355 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
356 | }; |
357 | OpenGl_FrameBuffer* anImmFbos[2] = |
358 | { |
359 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
360 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
361 | }; |
362 | |
363 | if (!myTransientDrawToFront) |
364 | { |
365 | anImmFbos[0] = aMainFbos[0]; |
366 | anImmFbos[1] = aMainFbos[1]; |
367 | } |
368 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
369 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
370 | { |
371 | anImmFbos[0] = NULL; |
372 | anImmFbos[1] = NULL; |
373 | } |
374 | |
375 | #if !defined(GL_ES_VERSION_2_0) |
376 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
377 | #endif |
378 | redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]); |
379 | myBackBufferRestored = Standard_True; |
380 | myIsImmediateDrawn = Standard_False; |
381 | #if !defined(GL_ES_VERSION_2_0) |
382 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
383 | #endif |
b0dc79bc |
384 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0])) |
c357e426 |
385 | { |
386 | toSwap = false; |
387 | } |
388 | else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) |
389 | { |
390 | aCtx->SwapBuffers(); |
391 | } |
392 | |
393 | #if !defined(GL_ES_VERSION_2_0) |
394 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
395 | #endif |
396 | redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]); |
397 | myBackBufferRestored = Standard_True; |
398 | myIsImmediateDrawn = Standard_False; |
b0dc79bc |
399 | if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1])) |
c357e426 |
400 | { |
401 | toSwap = false; |
402 | } |
403 | |
404 | if (anImmFbos[0] != NULL) |
405 | { |
3c4b62a4 |
406 | drawStereoPair (aFrameBuffer); |
c357e426 |
407 | } |
408 | } |
409 | else |
410 | { |
3bffef55 |
411 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer; |
c357e426 |
412 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
413 | if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) |
414 | { |
415 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
416 | } |
521b0d7f |
417 | if (!myTransientDrawToFront) |
418 | { |
419 | anImmFbo = aMainFbo; |
420 | } |
c357e426 |
421 | |
422 | #if !defined(GL_ES_VERSION_2_0) |
3bffef55 |
423 | if (aMainFbo == NULL) |
c357e426 |
424 | { |
425 | aCtx->SetReadDrawBuffer (GL_BACK); |
426 | } |
427 | #endif |
3bffef55 |
428 | redraw (aProjectType, aMainFbo); |
c357e426 |
429 | myBackBufferRestored = Standard_True; |
430 | myIsImmediateDrawn = Standard_False; |
431 | if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo)) |
432 | { |
433 | toSwap = false; |
434 | } |
435 | |
436 | if (anImmFbo != NULL |
437 | && anImmFbo != aFrameBuffer) |
438 | { |
439 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
440 | } |
441 | } |
442 | |
443 | #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) |
444 | if (OpenGl_AVIWriter_AllowWriting (myWindow->PlatformWindow()->NativeHandle())) |
445 | { |
446 | GLint params[4]; |
447 | glGetIntegerv (GL_VIEWPORT, params); |
448 | int nWidth = params[2] & ~0x7; |
449 | int nHeight = params[3] & ~0x7; |
450 | |
451 | const int nBitsPerPixel = 24; |
452 | GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8]; |
453 | |
454 | glPixelStorei (GL_PACK_ALIGNMENT, 1); |
455 | glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData); |
456 | OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel); |
457 | delete[] aDumpData; |
458 | } |
459 | #endif |
460 | |
bf02aa7d |
461 | if (myRenderParams.Method == Graphic3d_RM_RAYTRACING |
462 | && myRenderParams.IsGlobalIlluminationEnabled) |
463 | { |
464 | myAccumFrames++; |
465 | } |
466 | |
c357e426 |
467 | // bind default FBO |
468 | bindDefaultFbo(); |
469 | |
7ccf8676 |
470 | if (wasDisabledMSAA != myToDisableMSAA |
471 | || hadFboBlit != myHasFboBlit) |
472 | { |
473 | // retry on error |
474 | Redraw(); |
475 | } |
476 | |
c357e426 |
477 | // Swap the buffers |
478 | if (toSwap) |
479 | { |
480 | aCtx->SwapBuffers(); |
481 | if (!myMainSceneFbos[0]->IsValid()) |
482 | { |
483 | myBackBufferRestored = Standard_False; |
484 | } |
485 | } |
486 | else |
487 | { |
488 | aCtx->core11fwd->glFlush(); |
489 | } |
490 | |
491 | // reset render mode state |
492 | aCtx->FetchState(); |
493 | |
494 | myWasRedrawnGL = Standard_True; |
495 | } |
496 | |
497 | // ======================================================================= |
498 | // function : RedrawImmediate |
499 | // purpose : |
500 | // ======================================================================= |
501 | void OpenGl_View::RedrawImmediate() |
502 | { |
503 | if (!myWorkspace->Activate()) |
504 | return; |
505 | |
506 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
507 | if (!myTransientDrawToFront |
508 | || !myBackBufferRestored |
509 | || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) |
510 | { |
511 | Redraw(); |
512 | return; |
513 | } |
514 | |
515 | const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode; |
516 | Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType(); |
b128c892 |
517 | OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->(); |
c357e426 |
518 | |
519 | if ( aFrameBuffer == NULL |
520 | && !aCtx->DefaultFrameBuffer().IsNull() |
521 | && aCtx->DefaultFrameBuffer()->IsValid()) |
522 | { |
523 | aFrameBuffer = aCtx->DefaultFrameBuffer().operator->(); |
524 | } |
525 | |
526 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
527 | { |
528 | if (myMainSceneFbos[0]->IsValid() |
529 | && !myMainSceneFbos[1]->IsValid()) |
530 | { |
531 | aProjectType = Graphic3d_Camera::Projection_Perspective; |
532 | } |
533 | } |
534 | |
535 | bool toSwap = false; |
536 | if (aProjectType == Graphic3d_Camera::Projection_Stereo) |
537 | { |
538 | OpenGl_FrameBuffer* aMainFbos[2] = |
539 | { |
540 | myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, |
541 | myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL |
542 | }; |
543 | OpenGl_FrameBuffer* anImmFbos[2] = |
544 | { |
545 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
546 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
547 | }; |
548 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
549 | || aStereoMode == Graphic3d_StereoMode_QuadBuffer) |
550 | { |
551 | anImmFbos[0] = NULL; |
552 | anImmFbos[1] = NULL; |
553 | } |
554 | |
555 | if (aCtx->arbFBO != NULL) |
556 | { |
557 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
558 | } |
559 | #if !defined(GL_ES_VERSION_2_0) |
560 | if (anImmFbos[0] == NULL) |
561 | { |
562 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); |
563 | } |
564 | #endif |
565 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, |
566 | aMainFbos[0], |
567 | anImmFbos[0], |
568 | Standard_True) || toSwap; |
569 | if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip |
570 | && toSwap |
571 | && !aCtx->caps->buffersNoSwap) |
572 | { |
573 | aCtx->SwapBuffers(); |
574 | } |
575 | |
576 | if (aCtx->arbFBO != NULL) |
577 | { |
578 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
579 | } |
580 | #if !defined(GL_ES_VERSION_2_0) |
581 | if (anImmFbos[1] == NULL) |
582 | { |
583 | aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); |
584 | } |
585 | #endif |
586 | toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, |
587 | aMainFbos[1], |
588 | anImmFbos[1], |
589 | Standard_True) || toSwap; |
590 | if (anImmFbos[0] != NULL) |
591 | { |
3c4b62a4 |
592 | drawStereoPair (aFrameBuffer); |
c357e426 |
593 | } |
594 | } |
595 | else |
596 | { |
597 | OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
598 | OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; |
599 | if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) |
600 | { |
601 | anImmFbo = myImmediateSceneFbos[0].operator->(); |
602 | } |
603 | #if !defined(GL_ES_VERSION_2_0) |
604 | if (aMainFbo == NULL) |
605 | { |
606 | aCtx->SetReadDrawBuffer (GL_BACK); |
607 | } |
608 | #endif |
609 | toSwap = redrawImmediate (aProjectType, |
610 | aMainFbo, |
611 | anImmFbo, |
612 | Standard_True) || toSwap; |
613 | if (anImmFbo != NULL |
614 | && anImmFbo != aFrameBuffer) |
615 | { |
616 | blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); |
617 | } |
618 | } |
619 | |
620 | // bind default FBO |
621 | bindDefaultFbo(); |
622 | |
623 | if (toSwap && !aCtx->caps->buffersNoSwap) |
624 | { |
625 | aCtx->SwapBuffers(); |
626 | } |
627 | else |
628 | { |
629 | aCtx->core11fwd->glFlush(); |
630 | } |
631 | |
632 | myWasRedrawnGL = Standard_True; |
633 | } |
634 | |
635 | // ======================================================================= |
636 | // function : redraw |
637 | // purpose : |
638 | // ======================================================================= |
639 | void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo) |
640 | { |
641 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
642 | if (theReadDrawFbo != NULL) |
643 | { |
644 | theReadDrawFbo->BindBuffer (aCtx); |
645 | theReadDrawFbo->SetupViewport (aCtx); |
646 | } |
647 | else |
648 | { |
3bffef55 |
649 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
650 | aCtx->ResizeViewport (aViewport); |
c357e426 |
651 | } |
652 | |
653 | // request reset of material |
654 | myWorkspace->NamedStatus |= OPENGL_NS_RESMAT; |
655 | myWorkspace->UseZBuffer() = Standard_True; |
656 | myWorkspace->UseDepthWrite() = Standard_True; |
657 | GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; |
658 | glDepthFunc (GL_LEQUAL); |
659 | glDepthMask (GL_TRUE); |
660 | glEnable (GL_DEPTH_TEST); |
661 | |
662 | #if !defined(GL_ES_VERSION_2_0) |
663 | glClearDepth (1.0); |
664 | #else |
665 | glClearDepthf (1.0f); |
666 | #endif |
667 | |
668 | if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK) |
669 | { |
670 | // set background to white |
671 | glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
672 | } |
673 | else |
674 | { |
b6472664 |
675 | const OpenGl_Vec4& aBgColor = myBgColor; |
676 | glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f); |
c357e426 |
677 | } |
678 | |
679 | glClear (toClear); |
680 | |
681 | render (theProjection, theReadDrawFbo, Standard_False); |
682 | } |
683 | |
684 | // ======================================================================= |
685 | // function : redrawMonoImmediate |
686 | // purpose : |
687 | // ======================================================================= |
688 | bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, |
689 | OpenGl_FrameBuffer* theReadFbo, |
690 | OpenGl_FrameBuffer* theDrawFbo, |
691 | const Standard_Boolean theIsPartialUpdate) |
692 | { |
693 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
694 | GLboolean toCopyBackToFront = GL_FALSE; |
521b0d7f |
695 | if (theDrawFbo == theReadFbo |
696 | && theDrawFbo != NULL) |
c357e426 |
697 | { |
698 | myBackBufferRestored = Standard_False; |
699 | } |
700 | else if (theReadFbo != NULL |
701 | && theReadFbo->IsValid() |
702 | && aCtx->IsRender()) |
703 | { |
704 | if (!blitBuffers (theReadFbo, theDrawFbo)) |
705 | { |
706 | return true; |
707 | } |
708 | } |
709 | else if (theDrawFbo == NULL) |
710 | { |
711 | #if !defined(GL_ES_VERSION_2_0) |
712 | aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); |
713 | #endif |
714 | if (toCopyBackToFront) |
715 | { |
716 | if (!HasImmediateStructures() |
717 | && !theIsPartialUpdate) |
718 | { |
719 | // prefer Swap Buffers within Redraw in compatibility mode (without FBO) |
720 | return true; |
721 | } |
722 | copyBackToFront(); |
723 | } |
724 | else |
725 | { |
726 | myBackBufferRestored = Standard_False; |
727 | } |
728 | } |
729 | else |
730 | { |
731 | myBackBufferRestored = Standard_False; |
732 | } |
733 | myIsImmediateDrawn = Standard_True; |
734 | |
735 | myWorkspace->UseZBuffer() = Standard_True; |
736 | myWorkspace->UseDepthWrite() = Standard_True; |
737 | glDepthFunc (GL_LEQUAL); |
738 | glDepthMask (GL_TRUE); |
739 | glEnable (GL_DEPTH_TEST); |
740 | #if !defined(GL_ES_VERSION_2_0) |
741 | glClearDepth (1.0); |
742 | #else |
743 | glClearDepthf (1.0f); |
744 | #endif |
745 | |
746 | render (theProjection, theDrawFbo, Standard_True); |
747 | |
748 | return !toCopyBackToFront; |
749 | } |
750 | |
751 | //======================================================================= |
752 | //function : Render |
753 | //purpose : |
754 | //======================================================================= |
755 | void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, |
756 | OpenGl_FrameBuffer* theOutputFBO, |
757 | const Standard_Boolean theToDrawImmediate) |
758 | { |
759 | // ================================== |
760 | // Step 1: Prepare for render |
761 | // ================================== |
762 | |
763 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
764 | |
765 | #if !defined(GL_ES_VERSION_2_0) |
766 | // Disable current clipping planes |
767 | if (aContext->core11 != NULL) |
768 | { |
769 | const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes(); |
770 | for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId) |
771 | { |
772 | aContext->core11fwd->glDisable (aClipPlaneId); |
773 | } |
774 | } |
775 | #endif |
776 | |
777 | // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm). |
778 | myBVHSelector.SetViewVolume (myCamera); |
91d96372 |
779 | myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height()); |
c357e426 |
780 | |
781 | const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); |
782 | if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) |
783 | { |
016e5959 |
784 | aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &myNoShadingLight : &myLights); |
c357e426 |
785 | myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); |
786 | } |
787 | |
788 | // Update matrices if camera has changed. |
789 | Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState(); |
790 | const Standard_Boolean isCameraChanged = myWorldViewProjState != aWVPState; |
791 | const Standard_Boolean isSameView = aManager->IsSameView (this); |
792 | if (isCameraChanged) |
793 | { |
794 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF()); |
795 | aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF()); |
bf02aa7d |
796 | myAccumFrames = 0; |
c357e426 |
797 | } |
798 | |
799 | // Apply new matrix state if camera has changed or this view differs from the one |
800 | // that was previously used for configuring matrices of shader manager |
801 | // (ApplyProjectionMatrix and ApplyWorldViewMatrix will affect the manager). |
802 | if (isCameraChanged || !isSameView) |
803 | { |
804 | aContext->ApplyProjectionMatrix(); |
805 | aContext->ApplyWorldViewMatrix(); |
806 | } |
807 | |
808 | if (aManager->ModelWorldState().Index() == 0) |
809 | { |
810 | aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4()); |
811 | } |
812 | |
813 | myWorldViewProjState = aWVPState; |
814 | |
815 | // ==================================== |
816 | // Step 2: Redraw background |
817 | // ==================================== |
818 | |
819 | // Render background |
820 | if (!theToDrawImmediate) |
821 | { |
a521d90d |
822 | drawBackground (myWorkspace); |
c357e426 |
823 | } |
824 | |
825 | #if !defined(GL_ES_VERSION_2_0) |
826 | // Switch off lighting by default |
827 | if (aContext->core11 != NULL) |
828 | { |
829 | glDisable(GL_LIGHTING); |
830 | } |
831 | #endif |
832 | |
833 | // ================================= |
834 | // Step 3: Redraw main plane |
835 | // ================================= |
836 | |
837 | // Setup face culling |
838 | GLboolean isCullFace = GL_FALSE; |
839 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
840 | { |
841 | isCullFace = glIsEnabled (GL_CULL_FACE); |
842 | if (myBackfacing == Graphic3d_TOBM_DISABLE) |
843 | { |
844 | glEnable (GL_CULL_FACE); |
845 | glCullFace (GL_BACK); |
846 | } |
847 | else |
848 | glDisable (GL_CULL_FACE); |
849 | } |
850 | |
851 | #if !defined(GL_ES_VERSION_2_0) |
852 | // if the view is scaled normal vectors are scaled to unit |
853 | // length for correct displaying of shaded objects |
854 | const gp_Pnt anAxialScale = myCamera->AxialScale(); |
855 | if (anAxialScale.X() != 1.F || |
856 | anAxialScale.Y() != 1.F || |
857 | anAxialScale.Z() != 1.F) |
858 | { |
859 | aContext->SetGlNormalizeEnabled (Standard_True); |
860 | } |
861 | else |
862 | { |
863 | aContext->SetGlNormalizeEnabled (Standard_False); |
864 | } |
865 | |
c357e426 |
866 | // Apply InteriorShadingMethod |
867 | if (aContext->core11 != NULL) |
868 | { |
869 | aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET |
870 | || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH); |
871 | } |
872 | #endif |
873 | |
874 | aManager->SetShadingModel (myShadingModel); |
c357e426 |
875 | |
876 | // Redraw 3d scene |
877 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) |
878 | { |
879 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF()); |
880 | aContext->ApplyProjectionMatrix(); |
881 | } |
882 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) |
883 | { |
884 | aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF()); |
885 | aContext->ApplyProjectionMatrix(); |
886 | } |
83da37b1 |
887 | |
888 | myWorkspace->SetEnvironmentTexture (myTextureEnv); |
889 | |
bf02aa7d |
890 | renderScene (theProjection, theOutputFBO, theToDrawImmediate); |
c357e426 |
891 | |
83da37b1 |
892 | myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)()); |
893 | |
c357e426 |
894 | // =============================== |
895 | // Step 4: Trihedron |
896 | // =============================== |
897 | |
898 | // Resetting GL parameters according to the default aspects |
899 | // in order to synchronize GL state with the graphic driver state |
900 | // before drawing auxiliary stuff (trihedrons, overlayer) |
c357e426 |
901 | myWorkspace->ResetAppliedAspect(); |
902 | |
c357e426 |
903 | |
deb02f86 |
904 | // We need to disable (unbind) all shaders programs to ensure |
905 | // that all objects without specified aspect will be drawn |
906 | // correctly (such as background) |
907 | aContext->BindProgram (NULL); |
c357e426 |
908 | |
909 | // Render trihedron |
910 | if (!theToDrawImmediate) |
911 | { |
912 | renderTrihedron (myWorkspace); |
913 | |
914 | // Restore face culling |
915 | if (myBackfacing != Graphic3d_TOBM_AUTOMATIC) |
916 | { |
917 | if (isCullFace) |
918 | { |
919 | glEnable (GL_CULL_FACE); |
920 | glCullFace (GL_BACK); |
921 | } |
922 | else |
923 | glDisable (GL_CULL_FACE); |
924 | } |
925 | } |
926 | |
c357e426 |
927 | // ============================================================== |
928 | // Step 6: Keep shader manager informed about last View |
929 | // ============================================================== |
930 | |
931 | if (!aManager.IsNull()) |
932 | { |
933 | aManager->SetLastView (this); |
934 | } |
935 | } |
936 | |
937 | // ======================================================================= |
938 | // function : InvalidateBVHData |
939 | // purpose : |
940 | // ======================================================================= |
941 | void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId) |
942 | { |
943 | myZLayers.InvalidateBVHData (theLayerId); |
944 | } |
945 | |
946 | //======================================================================= |
947 | //function : renderStructs |
948 | //purpose : |
949 | //======================================================================= |
bf02aa7d |
950 | void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection, |
951 | OpenGl_FrameBuffer* theReadDrawFbo, |
952 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
953 | { |
954 | if ( myZLayers.NbStructures() <= 0 ) |
955 | return; |
956 | |
957 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
c357e426 |
958 | Standard_Boolean toRenderGL = theToDrawImmediate || |
959 | myRenderParams.Method != Graphic3d_RM_RAYTRACING || |
960 | myRaytraceInitStatus == OpenGl_RT_FAIL || |
961 | aCtx->IsFeedback(); |
962 | |
963 | if (!toRenderGL) |
964 | { |
965 | toRenderGL = !initRaytraceResources (aCtx) || |
966 | !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx); |
967 | |
968 | toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL |
969 | |
970 | if (!toRenderGL) |
971 | { |
972 | const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width(); |
973 | const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height(); |
3c4b62a4 |
974 | myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0); |
c357e426 |
975 | |
976 | if (myRaytraceFilter.IsNull()) |
977 | myRaytraceFilter = new OpenGl_RaytraceFilter; |
978 | |
979 | myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter()); |
980 | |
981 | if (theReadDrawFbo != NULL) |
982 | theReadDrawFbo->UnbindBuffer (aCtx); |
983 | |
984 | // Prepare preliminary OpenGL output |
985 | if (aCtx->arbFBOBlit != NULL) |
986 | { |
987 | // Render bottom OSD layer |
988 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom); |
989 | |
990 | myWorkspace->SetRenderFilter (myRaytraceFilter); |
991 | { |
992 | if (theReadDrawFbo != NULL) |
993 | { |
994 | theReadDrawFbo->BindReadBuffer (aCtx); |
995 | } |
996 | else |
997 | { |
998 | aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0); |
999 | } |
1000 | |
1001 | myOpenGlFBO->BindDrawBuffer (aCtx); |
1002 | |
1003 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY, |
1004 | 0, 0, aSizeX, aSizeY, |
1005 | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, |
1006 | GL_NEAREST); |
1007 | |
1008 | // Render non-polygonal elements in default layer |
1009 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default); |
1010 | } |
1011 | myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter()); |
1012 | } |
1013 | |
1014 | if (theReadDrawFbo != NULL) |
1015 | { |
1016 | theReadDrawFbo->BindBuffer (aCtx); |
1017 | } |
1018 | else |
1019 | { |
1020 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0); |
1021 | } |
1022 | |
f55ba97f |
1023 | // Reset OpenGl aspects state to default to avoid enabling of |
1024 | // backface culling which is not supported in ray-tracing. |
1025 | myWorkspace->ResetAppliedAspect(); |
1026 | |
c357e426 |
1027 | // Ray-tracing polygonal primitive arrays |
bf02aa7d |
1028 | raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx); |
c357e426 |
1029 | |
1030 | // Render upper (top and topmost) OpenGL layers |
1031 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper); |
1032 | } |
1033 | } |
1034 | |
1035 | // Redraw 3D scene using OpenGL in standard |
1036 | // mode or in case of ray-tracing failure |
1037 | if (toRenderGL) |
1038 | { |
1039 | myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All); |
1040 | |
1041 | // Set flag that scene was redrawn by standard pipeline |
1042 | myWasRedrawnGL = Standard_True; |
1043 | } |
1044 | } |
1045 | |
1046 | //======================================================================= |
1047 | //function : renderTrihedron |
1048 | //purpose : |
1049 | //======================================================================= |
1050 | void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace) |
1051 | { |
1052 | // display global trihedron |
1053 | if (myToShowTrihedron) |
1054 | { |
83da37b1 |
1055 | // disable environment texture |
1056 | Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture(); |
1057 | theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)()); |
1058 | |
c357e426 |
1059 | myTrihedron.Render (theWorkspace); |
83da37b1 |
1060 | |
1061 | // restore environment texture |
1062 | theWorkspace->SetEnvironmentTexture (anEnvironmentTexture); |
c357e426 |
1063 | } |
1064 | if (myToShowGradTrihedron) |
1065 | { |
1066 | myGraduatedTrihedron.Render (theWorkspace); |
1067 | } |
1068 | } |
1069 | |
1070 | // ======================================================================= |
1071 | // function : Invalidate |
1072 | // purpose : |
1073 | // ======================================================================= |
1074 | void OpenGl_View::Invalidate() |
1075 | { |
1076 | myBackBufferRestored = Standard_False; |
1077 | } |
1078 | |
1079 | //======================================================================= |
1080 | //function : renderScene |
1081 | //purpose : |
1082 | //======================================================================= |
bf02aa7d |
1083 | void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, |
1084 | OpenGl_FrameBuffer* theReadDrawFbo, |
1085 | const Standard_Boolean theToDrawImmediate) |
c357e426 |
1086 | { |
1087 | const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); |
1088 | |
c357e426 |
1089 | // Specify clipping planes in view transformation space |
3202bf1e |
1090 | aContext->ChangeClipping().Reset (aContext, myClipPlanes); |
1091 | if (!myClipPlanes.IsNull() |
1092 | && !myClipPlanes->IsEmpty()) |
c357e426 |
1093 | { |
deb02f86 |
1094 | aContext->ShaderManager()->UpdateClippingState(); |
c357e426 |
1095 | } |
1096 | |
1097 | #if !defined(GL_ES_VERSION_2_0) |
1098 | // Apply Lights |
1099 | if (aContext->core11 != NULL) |
1100 | { |
1101 | // setup lights |
1102 | Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0], |
1103 | THE_DEFAULT_AMBIENT[1], |
1104 | THE_DEFAULT_AMBIENT[2], |
1105 | THE_DEFAULT_AMBIENT[3]); |
1106 | GLenum aLightGlId = GL_LIGHT0; |
1107 | |
016e5959 |
1108 | OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? myNoShadingLight : myLights); |
c357e426 |
1109 | for (; aLightIt.More(); aLightIt.Next()) |
1110 | { |
1111 | bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace); |
1112 | } |
1113 | |
1114 | // apply accumulated ambient color |
1115 | anAmbientColor.a() = 1.0f; |
1116 | glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData()); |
1117 | |
1118 | if (aLightGlId != GL_LIGHT0) |
1119 | { |
1120 | glEnable (GL_LIGHTING); |
1121 | } |
1122 | // switch off unused lights |
1123 | for (; aLightGlId <= GL_LIGHT7; ++aLightGlId) |
1124 | { |
1125 | glDisable (aLightGlId); |
1126 | } |
1127 | } |
1128 | #endif |
1129 | |
1130 | // Clear status bitfields |
1131 | myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO); |
1132 | |
83da37b1 |
1133 | // First pass |
1134 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
1135 | myWorkspace->DisableTexture(); |
c357e426 |
1136 | |
83da37b1 |
1137 | // Second pass |
1138 | if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) |
c357e426 |
1139 | { |
83da37b1 |
1140 | myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO; |
c357e426 |
1141 | |
83da37b1 |
1142 | // Remember OpenGl properties |
1143 | GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA; |
1144 | GLint aSaveZbuffFunc; |
1145 | GLboolean aSaveZbuffWrite; |
1146 | glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite); |
1147 | glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc); |
1148 | #if !defined(GL_ES_VERSION_2_0) |
1149 | glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst); |
1150 | glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc); |
1151 | #endif |
1152 | GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST); |
1153 | GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND); |
c357e426 |
1154 | |
83da37b1 |
1155 | // Change the properties for second rendering pass |
1156 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
1157 | glEnable (GL_BLEND); |
c357e426 |
1158 | |
83da37b1 |
1159 | glDepthFunc (GL_EQUAL); |
1160 | glDepthMask (GL_FALSE); |
1161 | glEnable (GL_DEPTH_TEST); |
c357e426 |
1162 | |
83da37b1 |
1163 | // Render the view |
1164 | renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate); |
1165 | myWorkspace->DisableTexture(); |
1166 | |
1167 | // Restore properties back |
1168 | glBlendFunc (aSaveBlendSrc, aSaveBlendDst); |
1169 | if (!wasBlendEnabled) |
1170 | glDisable (GL_BLEND); |
1171 | |
1172 | glDepthFunc (aSaveZbuffFunc); |
1173 | glDepthMask (aSaveZbuffWrite); |
1174 | if (!wasZbuffEnabled) |
1175 | glDisable (GL_DEPTH_FUNC); |
c357e426 |
1176 | } |
1177 | |
1178 | // Apply restored view matrix. |
1179 | aContext->ApplyWorldViewMatrix(); |
1180 | |
3202bf1e |
1181 | aContext->ChangeClipping().Reset (aContext, Handle(Graphic3d_SequenceOfHClipPlane)()); |
1182 | if (!myClipPlanes.IsNull() |
1183 | && !myClipPlanes->IsEmpty()) |
deb02f86 |
1184 | { |
1185 | aContext->ShaderManager()->RevertClippingState(); |
deb02f86 |
1186 | } |
c357e426 |
1187 | } |
1188 | |
1189 | // ======================================================================= |
1190 | // function : bindDefaultFbo |
1191 | // purpose : |
1192 | // ======================================================================= |
1193 | void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) |
1194 | { |
1195 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1196 | OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) |
1197 | ? theCustomFbo |
1198 | : (!aCtx->DefaultFrameBuffer().IsNull() |
1199 | && aCtx->DefaultFrameBuffer()->IsValid() |
1200 | ? aCtx->DefaultFrameBuffer().operator->() |
1201 | : NULL); |
1202 | if (anFbo != NULL) |
1203 | { |
1204 | anFbo->BindBuffer (aCtx); |
521b0d7f |
1205 | anFbo->SetupViewport (aCtx); |
c357e426 |
1206 | } |
1207 | else |
1208 | { |
1209 | #if !defined(GL_ES_VERSION_2_0) |
1210 | aCtx->SetReadDrawBuffer (GL_BACK); |
1211 | #else |
1212 | if (aCtx->arbFBO != NULL) |
1213 | { |
1214 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1215 | } |
1216 | #endif |
3bffef55 |
1217 | const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() }; |
1218 | aCtx->ResizeViewport (aViewport); |
c357e426 |
1219 | } |
c357e426 |
1220 | } |
1221 | |
1222 | // ======================================================================= |
1223 | // function : initBlitQuad |
1224 | // purpose : |
1225 | // ======================================================================= |
1226 | OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip) |
1227 | { |
1228 | OpenGl_VertexBuffer* aVerts = NULL; |
1229 | if (!theToFlip) |
1230 | { |
1231 | aVerts = &myFullScreenQuad; |
1232 | if (!aVerts->IsValid()) |
1233 | { |
1234 | OpenGl_Vec4 aQuad[4] = |
1235 | { |
1236 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), |
1237 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), |
1238 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), |
1239 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) |
1240 | }; |
1241 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1242 | } |
1243 | } |
1244 | else |
1245 | { |
1246 | aVerts = &myFullScreenQuadFlip; |
1247 | if (!aVerts->IsValid()) |
1248 | { |
1249 | OpenGl_Vec4 aQuad[4] = |
1250 | { |
1251 | OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), |
1252 | OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), |
1253 | OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), |
1254 | OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) |
1255 | }; |
1256 | aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData()); |
1257 | } |
1258 | } |
1259 | return aVerts; |
1260 | } |
1261 | |
1262 | // ======================================================================= |
1263 | // function : blitBuffers |
1264 | // purpose : |
1265 | // ======================================================================= |
1266 | bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, |
1267 | OpenGl_FrameBuffer* theDrawFbo, |
1268 | const Standard_Boolean theToFlip) |
1269 | { |
1270 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1271 | if (theReadFbo == NULL || aCtx->IsFeedback()) |
1272 | { |
1273 | return false; |
1274 | } |
1275 | else if (theReadFbo == theDrawFbo) |
1276 | { |
1277 | return true; |
1278 | } |
1279 | |
1280 | // clear destination before blitting |
1281 | if (theDrawFbo != NULL |
1282 | && theDrawFbo->IsValid()) |
1283 | { |
1284 | theDrawFbo->BindBuffer (aCtx); |
1285 | } |
1286 | else |
1287 | { |
1288 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1289 | } |
1290 | #if !defined(GL_ES_VERSION_2_0) |
1291 | aCtx->core20fwd->glClearDepth (1.0); |
1292 | #else |
1293 | aCtx->core20fwd->glClearDepthf (1.0f); |
1294 | #endif |
1295 | aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
1296 | |
3c4b62a4 |
1297 | #if !defined(GL_ES_VERSION_2_0) |
1298 | if (aCtx->arbFBOBlit != NULL |
1299 | && theReadFbo->NbSamples() != 0) |
c357e426 |
1300 | { |
3c4b62a4 |
1301 | GLbitfield aCopyMask = 0; |
c357e426 |
1302 | theReadFbo->BindReadBuffer (aCtx); |
1303 | if (theDrawFbo != NULL |
1304 | && theDrawFbo->IsValid()) |
1305 | { |
1306 | theDrawFbo->BindDrawBuffer (aCtx); |
3c4b62a4 |
1307 | if (theDrawFbo->HasColor() |
1308 | && theReadFbo->HasColor()) |
1309 | { |
1310 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1311 | } |
1312 | if (theDrawFbo->HasDepth() |
1313 | && theReadFbo->HasDepth()) |
1314 | { |
1315 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1316 | } |
c357e426 |
1317 | } |
1318 | else |
1319 | { |
3c4b62a4 |
1320 | if (theReadFbo->HasColor()) |
1321 | { |
1322 | aCopyMask |= GL_COLOR_BUFFER_BIT; |
1323 | } |
1324 | if (theReadFbo->HasDepth()) |
1325 | { |
1326 | aCopyMask |= GL_DEPTH_BUFFER_BIT; |
1327 | } |
c357e426 |
1328 | aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1329 | } |
3c4b62a4 |
1330 | |
c357e426 |
1331 | // we don't copy stencil buffer here... does it matter for performance? |
1332 | aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), |
1333 | 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), |
3c4b62a4 |
1334 | aCopyMask, GL_NEAREST); |
7ccf8676 |
1335 | const int anErr = ::glGetError(); |
1336 | if (anErr != GL_NO_ERROR) |
1337 | { |
1338 | // glBlitFramebuffer() might fail in several cases: |
1339 | // - Both FBOs have MSAA and they are samples number does not match. |
1340 | // OCCT checks that this does not happen, |
1341 | // however some graphics drivers provide an option for overriding MSAA. |
1342 | // In this case window MSAA might be non-zero (and application can not check it) |
1343 | // and might not match MSAA of our offscreen FBOs. |
1344 | // - Pixel formats of FBOs do not match. |
1345 | // This also might happen with window has pixel format, |
1346 | // e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion. |
1347 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error #" + anErr + "]\n" |
1348 | + " Please check your graphics driver settings or try updating driver."; |
1349 | if (theReadFbo->NbSamples() != 0) |
1350 | { |
1351 | myToDisableMSAA = true; |
1352 | aMsg += "\n MSAA settings should not be overridden by driver!"; |
1353 | } |
1354 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1355 | GL_DEBUG_TYPE_ERROR, |
1356 | 0, |
1357 | GL_DEBUG_SEVERITY_HIGH, |
1358 | aMsg); |
1359 | } |
1360 | |
c357e426 |
1361 | if (theDrawFbo != NULL |
3c4b62a4 |
1362 | && theDrawFbo->IsValid()) |
c357e426 |
1363 | { |
1364 | theDrawFbo->BindBuffer (aCtx); |
1365 | } |
1366 | else |
1367 | { |
1368 | aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); |
1369 | } |
1370 | } |
1371 | else |
3c4b62a4 |
1372 | #endif |
c357e426 |
1373 | { |
1374 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1375 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1376 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1ce0716b |
1377 | #if defined(GL_ES_VERSION_2_0) |
1378 | if (!aCtx->IsGlGreaterEqual (3, 0) |
1379 | && !aCtx->extFragDepth) |
1380 | { |
1381 | aCtx->core20fwd->glDisable (GL_DEPTH_TEST); |
1382 | } |
1383 | #endif |
c357e426 |
1384 | |
1385 | myWorkspace->DisableTexture(); |
1386 | |
1387 | OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); |
1388 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1389 | if (aVerts->IsValid() |
1390 | && aManager->BindFboBlitProgram()) |
1391 | { |
1392 | theReadFbo->ColorTexture() ->Bind (aCtx, GL_TEXTURE0 + 0); |
1393 | theReadFbo->DepthStencilTexture()->Bind (aCtx, GL_TEXTURE0 + 1); |
1394 | aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1395 | |
1396 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1397 | |
1398 | aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS); |
1399 | theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1); |
1400 | theReadFbo->ColorTexture() ->Unbind (aCtx, GL_TEXTURE0 + 0); |
a521d90d |
1401 | aCtx->BindProgram (NULL); |
c357e426 |
1402 | } |
1403 | else |
1404 | { |
1405 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1406 | + "Error! FBO blitting has failed"; |
3b523c4c |
1407 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1408 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1409 | 0, |
3b523c4c |
1410 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1411 | aMsg); |
1412 | myHasFboBlit = Standard_False; |
1413 | theReadFbo->Release (aCtx.operator->()); |
1414 | return true; |
1415 | } |
1416 | } |
1417 | return true; |
1418 | } |
1419 | |
1420 | // ======================================================================= |
1421 | // function : drawStereoPair |
1422 | // purpose : |
1423 | // ======================================================================= |
3c4b62a4 |
1424 | void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) |
c357e426 |
1425 | { |
3c4b62a4 |
1426 | const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); |
1427 | bindDefaultFbo (theDrawFbo); |
c357e426 |
1428 | OpenGl_FrameBuffer* aPair[2] = |
1429 | { |
1430 | myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, |
1431 | myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL |
1432 | }; |
1433 | if (aPair[0] == NULL |
1434 | || aPair[1] == NULL |
1435 | || !myTransientDrawToFront) |
1436 | { |
1437 | aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; |
1438 | aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; |
1439 | } |
1440 | |
1441 | if (aPair[0] == NULL |
1442 | || aPair[1] == NULL) |
1443 | { |
1444 | return; |
1445 | } |
1446 | |
3c4b62a4 |
1447 | if (aPair[0]->NbSamples() != 0) |
1448 | { |
1449 | // resolve MSAA buffers before drawing |
1450 | if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0) |
1451 | || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0)) |
1452 | { |
82f443b6 |
1453 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1454 | GL_DEBUG_TYPE_ERROR, |
3c4b62a4 |
1455 | 0, |
82f443b6 |
1456 | GL_DEBUG_SEVERITY_HIGH, |
3c4b62a4 |
1457 | "Error! Unable to allocate FBO for blitting stereo pair"); |
1458 | bindDefaultFbo (theDrawFbo); |
1459 | return; |
1460 | } |
1461 | |
1462 | if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False) |
1463 | || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False)) |
1464 | { |
1465 | bindDefaultFbo (theDrawFbo); |
1466 | return; |
1467 | } |
1468 | |
1469 | aPair[0] = myOpenGlFBO .operator->(); |
1470 | aPair[1] = myOpenGlFBO2.operator->(); |
1471 | bindDefaultFbo (theDrawFbo); |
1472 | } |
1473 | |
c357e426 |
1474 | struct |
1475 | { |
1476 | Standard_Integer left; |
1477 | Standard_Integer top; |
1478 | Standard_Integer right; |
1479 | Standard_Integer bottom; |
1480 | Standard_Integer dx() { return right - left; } |
1481 | Standard_Integer dy() { return bottom - top; } |
1482 | } aGeom; |
1483 | |
1484 | myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom); |
1485 | |
1486 | Standard_Boolean toReverse = myRenderParams.ToReverseStereo; |
1487 | const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1; |
1488 | const Standard_Boolean isOddX = aGeom.left % 2 == 1; |
1489 | if (isOddY |
1490 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced |
1491 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1492 | { |
1493 | toReverse = !toReverse; |
1494 | } |
1495 | if (isOddX |
1496 | && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced |
1497 | || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) |
1498 | { |
1499 | toReverse = !toReverse; |
1500 | } |
1501 | |
1502 | if (toReverse) |
1503 | { |
1504 | std::swap (aPair[0], aPair[1]); |
1505 | } |
1506 | |
c357e426 |
1507 | aCtx->core20fwd->glDepthFunc (GL_ALWAYS); |
1508 | aCtx->core20fwd->glDepthMask (GL_TRUE); |
1509 | aCtx->core20fwd->glEnable (GL_DEPTH_TEST); |
1510 | |
1511 | myWorkspace->DisableTexture(); |
1512 | OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); |
1513 | |
1514 | const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); |
1515 | if (aVerts->IsValid() |
1516 | && aManager->BindStereoProgram (myRenderParams.StereoMode)) |
1517 | { |
1518 | if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) |
1519 | { |
1520 | OpenGl_Mat4 aFilterL, aFilterR; |
1521 | aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1522 | aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); |
1523 | switch (myRenderParams.AnaglyphFilter) |
1524 | { |
1525 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: |
1526 | { |
1527 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1528 | aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1529 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1530 | break; |
1531 | } |
1532 | case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: |
1533 | { |
1534 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); |
1535 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); |
1536 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); |
1537 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1538 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); |
1539 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); |
1540 | aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); |
1541 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1542 | break; |
1543 | } |
1544 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: |
1545 | { |
1546 | aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1547 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1548 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1549 | break; |
1550 | } |
1551 | case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: |
1552 | { |
1553 | aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); |
1554 | aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); |
1555 | aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); |
1556 | aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1557 | aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); |
1558 | aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); |
1559 | aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); |
1560 | aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); |
1561 | break; |
1562 | } |
1563 | case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: |
1564 | { |
1565 | aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); |
1566 | aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); |
1567 | aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); |
1568 | break; |
1569 | } |
1570 | case Graphic3d_RenderingParams::Anaglyph_UserDefined: |
1571 | { |
1572 | aFilterL = myRenderParams.AnaglyphLeft; |
1573 | aFilterR = myRenderParams.AnaglyphRight; |
1574 | break; |
1575 | } |
1576 | } |
1577 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL); |
1578 | aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR); |
1579 | } |
1580 | |
1581 | aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0); |
1582 | aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1); |
1583 | aVerts->BindVertexAttrib (aCtx, 0); |
1584 | |
1585 | aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); |
1586 | |
1587 | aVerts->UnbindVertexAttrib (aCtx, 0); |
1588 | aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1); |
1589 | aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0); |
1590 | } |
1591 | else |
1592 | { |
1593 | TCollection_ExtendedString aMsg = TCollection_ExtendedString() |
1594 | + "Error! Anaglyph has failed"; |
3b523c4c |
1595 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, |
1596 | GL_DEBUG_TYPE_ERROR, |
c357e426 |
1597 | 0, |
3b523c4c |
1598 | GL_DEBUG_SEVERITY_HIGH, |
c357e426 |
1599 | aMsg); |
1600 | } |
1601 | } |
1602 | |
1603 | // ======================================================================= |
1604 | // function : copyBackToFront |
1605 | // purpose : |
1606 | // ======================================================================= |
1607 | void OpenGl_View::copyBackToFront() |
1608 | { |
1609 | #if !defined(GL_ES_VERSION_2_0) |
1610 | |
1611 | OpenGl_Mat4 aProjectMat; |
1612 | Graphic3d_TransformUtils::Ortho2D (aProjectMat, |
1613 | 0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height())); |
1614 | |
1615 | Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); |
1616 | aCtx->WorldViewState.Push(); |
1617 | aCtx->ProjectionState.Push(); |
1618 | |
1619 | aCtx->WorldViewState.SetIdentity(); |
1620 | aCtx->ProjectionState.SetCurrent (aProjectMat); |
1621 | |
1622 | aCtx->ApplyProjectionMatrix(); |
1623 | aCtx->ApplyWorldViewMatrix(); |
1624 | |
1625 | aCtx->DisableFeatures(); |
1626 | |
1627 | switch (aCtx->DrawBuffer()) |
1628 | { |
1629 | case GL_BACK_LEFT: |
1630 | { |
1631 | aCtx->SetReadBuffer (GL_BACK_LEFT); |
1632 | aCtx->SetDrawBuffer (GL_FRONT_LEFT); |
1633 | break; |
1634 | } |
1635 | case GL_BACK_RIGHT: |
1636 | { |
1637 | aCtx->SetReadBuffer (GL_BACK_RIGHT); |
1638 | aCtx->SetDrawBuffer (GL_FRONT_RIGHT); |
1639 | break; |
1640 | } |
1641 | default: |
1642 | { |
1643 | aCtx->SetReadBuffer (GL_BACK); |
1644 | aCtx->SetDrawBuffer (GL_FRONT); |
1645 | break; |
1646 | } |
1647 | } |
1648 | |
1649 | glRasterPos2i (0, 0); |
1650 | glCopyPixels (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR); |
1651 | //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); |
1652 | |
1653 | aCtx->EnableFeatures(); |
1654 | |
1655 | aCtx->WorldViewState.Pop(); |
1656 | aCtx->ProjectionState.Pop(); |
1657 | aCtx->ApplyProjectionMatrix(); |
1658 | |
1659 | // read/write from front buffer now |
1660 | aCtx->SetReadBuffer (aCtx->DrawBuffer()); |
1661 | #endif |
1662 | myIsImmediateDrawn = Standard_False; |
1663 | } |