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 | |
a577aaab | 16 | #include <OpenGl_GlCore15.hxx> |
5f8b738e | 17 | |
2166f0fa SK |
18 | #include <InterfaceGraphic.hxx> |
19 | ||
2166f0fa SK |
20 | #include <OpenGl_AspectLine.hxx> |
21 | #include <OpenGl_AspectFace.hxx> | |
22 | #include <OpenGl_AspectMarker.hxx> | |
23 | #include <OpenGl_AspectText.hxx> | |
bf75be98 | 24 | #include <OpenGl_Context.hxx> |
679ecdee | 25 | #include <OpenGl_Element.hxx> |
a174a3c5 | 26 | #include <OpenGl_FrameBuffer.hxx> |
679ecdee | 27 | #include <OpenGl_Structure.hxx> |
25ef750e | 28 | #include <OpenGl_Sampler.hxx> |
bf75be98 | 29 | #include <OpenGl_Texture.hxx> |
c827ea3a | 30 | #include <OpenGl_Utils.hxx> |
e276548b | 31 | #include <OpenGl_View.hxx> |
a174a3c5 | 32 | #include <OpenGl_Workspace.hxx> |
2166f0fa | 33 | |
bf75be98 | 34 | #include <Graphic3d_TextureParams.hxx> |
2166f0fa | 35 | |
58655684 | 36 | #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) |
a174a3c5 | 37 | #include <OpenGl_AVIWriter.hxx> |
38 | #endif | |
39 | ||
2166f0fa SK |
40 | IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window) |
41 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window) | |
42 | ||
43 | namespace | |
44 | { | |
0adbd30f | 45 | static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } }; |
46 | static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); | |
2166f0fa SK |
47 | |
48 | static const OpenGl_AspectLine myDefaultAspectLine; | |
49 | static const OpenGl_AspectFace myDefaultAspectFace; | |
50 | static const OpenGl_AspectMarker myDefaultAspectMarker; | |
51 | static const OpenGl_AspectText myDefaultAspectText; | |
52 | ||
53 | static const OpenGl_TextParam myDefaultTextParam = | |
54 | { | |
55 | 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM | |
56 | }; | |
57 | ||
58 | static const OpenGl_Matrix myDefaultMatrix = | |
59 | { | |
60 | {{ 1.0F, 0.0F, 0.0F, 0.0F }, | |
61 | { 0.0F, 1.0F, 0.0F, 0.0F }, | |
62 | { 0.0F, 0.0F, 1.0F, 0.0F }, | |
63 | { 0.0F, 0.0F, 0.0F, 1.0F }} | |
64 | }; | |
bf75be98 | 65 | |
2166f0fa SK |
66 | }; |
67 | ||
0adbd30f | 68 | // ======================================================================= |
69 | // function : Init | |
70 | // purpose : | |
71 | // ======================================================================= | |
72 | void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) | |
73 | { | |
74 | // ambient component | |
75 | if (theProp.color_mask & OPENGL_AMBIENT_MASK) | |
76 | { | |
77 | const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb; | |
78 | Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb, | |
79 | aSrcAmb[1] * theProp.amb, | |
80 | aSrcAmb[2] * theProp.amb, | |
81 | 1.0f); | |
82 | } | |
83 | else | |
84 | { | |
85 | Ambient = THE_BLACK_COLOR; | |
86 | } | |
87 | ||
88 | // diffusion component | |
89 | if (theProp.color_mask & OPENGL_DIFFUSE_MASK) | |
90 | { | |
91 | const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb; | |
92 | Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff, | |
93 | aSrcDif[1] * theProp.diff, | |
94 | aSrcDif[2] * theProp.diff, | |
95 | 1.0f); | |
96 | } | |
97 | else | |
98 | { | |
99 | Diffuse = THE_BLACK_COLOR; | |
100 | } | |
101 | ||
102 | // specular component | |
103 | if (theProp.color_mask & OPENGL_SPECULAR_MASK) | |
104 | { | |
105 | const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb; | |
106 | Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec, | |
107 | aSrcSpe[1] * theProp.spec, | |
108 | aSrcSpe[2] * theProp.spec, | |
109 | 1.0f); | |
110 | } | |
111 | else | |
112 | { | |
113 | Specular = THE_BLACK_COLOR; | |
114 | } | |
115 | ||
116 | // emission component | |
117 | if (theProp.color_mask & OPENGL_EMISSIVE_MASK) | |
118 | { | |
119 | const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb; | |
120 | Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv, | |
121 | aSrcEms[1] * theProp.emsv, | |
122 | aSrcEms[2] * theProp.emsv, | |
123 | 1.0f); | |
124 | } | |
125 | else | |
126 | { | |
127 | Emission = THE_BLACK_COLOR; | |
128 | } | |
129 | ||
130 | ChangeShine() = theProp.shine; | |
131 | ChangeTransparency() = theProp.trans; | |
132 | } | |
133 | ||
2166f0fa SK |
134 | // ======================================================================= |
135 | // function : OpenGl_Workspace | |
136 | // purpose : | |
137 | // ======================================================================= | |
25b97fac | 138 | OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver, |
2166f0fa | 139 | const CALL_DEF_WINDOW& theCWindow, |
5e27df78 | 140 | Aspect_RenderingContext theGContext, |
58655684 | 141 | const Handle(OpenGl_Caps)& theCaps, |
5e27df78 | 142 | const Handle(OpenGl_Context)& theShareCtx) |
25b97fac | 143 | : OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx), |
a174a3c5 | 144 | NamedStatus (0), |
0adbd30f | 145 | HighlightColor (&THE_WHITE_COLOR), |
a174a3c5 | 146 | // |
fc73a202 | 147 | myComputeInitStatus (OpenGl_RT_NONE), |
148 | myIsRaytraceDataValid (Standard_False), | |
25ef750e | 149 | myIsRaytraceWarnTextures (Standard_False), |
fc73a202 | 150 | myViewModificationStatus (0), |
151 | myLayersModificationStatus (0), | |
152 | // | |
a89742cf | 153 | myRaytraceFilter (new OpenGl_RaytraceFilter()), |
154 | myToRedrawGL (Standard_True), | |
73192b37 | 155 | myAntiAliasingMode (3), |
a174a3c5 | 156 | myTransientDrawToFront (Standard_True), |
679ecdee | 157 | myBackBufferRestored (Standard_False), |
158 | myIsImmediateDrawn (Standard_False), | |
2166f0fa SK |
159 | myUseZBuffer (Standard_False), |
160 | myUseDepthTest (Standard_True), | |
161 | myUseGLLight (Standard_True), | |
b7cd4ba7 | 162 | myIsCullingEnabled (Standard_False), |
a89742cf | 163 | myFrameCounter (0), |
2166f0fa | 164 | // |
2166f0fa SK |
165 | AspectLine_set (&myDefaultAspectLine), |
166 | AspectLine_applied (NULL), | |
167 | AspectFace_set (&myDefaultAspectFace), | |
168 | AspectFace_applied (NULL), | |
169 | AspectMarker_set (&myDefaultAspectMarker), | |
170 | AspectMarker_applied (NULL), | |
171 | AspectText_set (&myDefaultAspectText), | |
172 | AspectText_applied (NULL), | |
173 | TextParam_set (&myDefaultTextParam), | |
174 | TextParam_applied (NULL), | |
175 | ViewMatrix_applied (&myDefaultMatrix), | |
176 | StructureMatrix_applied (&myDefaultMatrix), | |
3b1817a9 | 177 | myCullingMode (TelCullUndefined), |
0f8c0fb8 | 178 | myModelViewMatrix (myDefaultMatrix), |
550f3b8b | 179 | PolygonOffset_applied (THE_DEFAULT_POFFSET) |
2166f0fa | 180 | { |
73192b37 | 181 | myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); |
182 | ||
183 | if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs)) | |
184 | { | |
185 | // share and register for release once the resource is no longer used | |
186 | myLineAttribs = new OpenGl_LineAttributes(); | |
187 | myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs); | |
188 | myLineAttribs->Init (myGlContext); | |
189 | } | |
2166f0fa SK |
190 | |
191 | // General initialization of the context | |
192 | ||
ca3c13d1 | 193 | #if !defined(GL_ES_VERSION_2_0) |
2166f0fa SK |
194 | // Eviter d'avoir les faces mal orientees en noir. |
195 | // Pourrait etre utiliser pour detecter les problemes d'orientation | |
bf75be98 | 196 | glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); |
2166f0fa SK |
197 | |
198 | // Optimisation pour le Fog et l'antialiasing | |
199 | glHint (GL_FOG_HINT, GL_FASTEST); | |
200 | glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); | |
201 | glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); | |
202 | glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); | |
ca3c13d1 | 203 | #endif |
2166f0fa | 204 | |
73192b37 | 205 | // AA mode |
206 | const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE"); | |
207 | if (anAaEnv != NULL) | |
208 | { | |
209 | int v; | |
210 | if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v; | |
211 | } | |
2166f0fa SK |
212 | } |
213 | ||
1981cb22 | 214 | // ======================================================================= |
215 | // function : SetImmediateModeDrawToFront | |
216 | // purpose : | |
217 | // ======================================================================= | |
218 | Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) | |
219 | { | |
220 | const Standard_Boolean aPrevMode = myTransientDrawToFront; | |
221 | myTransientDrawToFront = theDrawToFrontBuffer; | |
222 | return aPrevMode; | |
223 | } | |
224 | ||
2166f0fa SK |
225 | // ======================================================================= |
226 | // function : ~OpenGl_Workspace | |
227 | // purpose : | |
228 | // ======================================================================= | |
229 | OpenGl_Workspace::~OpenGl_Workspace() | |
230 | { | |
73192b37 | 231 | if (!myLineAttribs.IsNull()) |
232 | { | |
233 | myLineAttribs.Nullify(); | |
234 | myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True); | |
235 | } | |
236 | ||
fc73a202 | 237 | ReleaseRaytraceResources(); |
2166f0fa SK |
238 | } |
239 | ||
240 | // ======================================================================= | |
241 | // function : Activate | |
242 | // purpose : | |
243 | // ======================================================================= | |
244 | Standard_Boolean OpenGl_Workspace::Activate() | |
245 | { | |
246 | if (!OpenGl_Window::Activate()) | |
247 | return Standard_False; | |
248 | ||
2166f0fa SK |
249 | ViewMatrix_applied = &myDefaultMatrix; |
250 | StructureMatrix_applied = &myDefaultMatrix; | |
26395493 | 251 | |
252 | ResetAppliedAspect(); | |
253 | ||
254 | return Standard_True; | |
2166f0fa SK |
255 | } |
256 | ||
26395493 | 257 | //======================================================================= |
258 | //function : ResetAppliedAspect | |
259 | //purpose : Sets default values of GL parameters in accordance with default aspects | |
260 | //======================================================================= | |
261 | void OpenGl_Workspace::ResetAppliedAspect() | |
262 | { | |
bf75be98 | 263 | NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0; |
0adbd30f | 264 | HighlightColor = &THE_WHITE_COLOR; |
26395493 | 265 | AspectLine_set = &myDefaultAspectLine; |
266 | AspectLine_applied = NULL; | |
267 | AspectFace_set = &myDefaultAspectFace; | |
268 | AspectFace_applied = NULL; | |
269 | AspectMarker_set = &myDefaultAspectMarker; | |
270 | AspectMarker_applied = NULL; | |
271 | AspectText_set = &myDefaultAspectText; | |
272 | AspectText_applied = NULL; | |
273 | TextParam_set = &myDefaultTextParam; | |
274 | TextParam_applied = NULL; | |
550f3b8b | 275 | PolygonOffset_applied = THE_DEFAULT_POFFSET; |
3b1817a9 | 276 | myCullingMode = TelCullUndefined; |
26395493 | 277 | |
278 | AspectLine(Standard_True); | |
279 | AspectFace(Standard_True); | |
280 | AspectMarker(Standard_True); | |
281 | AspectText(Standard_True); | |
282 | } | |
bf75be98 | 283 | |
284 | // ======================================================================= | |
285 | // function : DisableTexture | |
286 | // purpose : | |
287 | // ======================================================================= | |
288 | Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture() | |
289 | { | |
290 | if (myTextureBound.IsNull()) | |
291 | { | |
292 | return myTextureBound; | |
293 | } | |
294 | ||
ca3c13d1 | 295 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 296 | // reset texture matrix because some code may expect it is identity |
297 | GLint aMatrixMode = GL_TEXTURE; | |
298 | glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); | |
299 | glMatrixMode (GL_TEXTURE); | |
300 | glLoadIdentity(); | |
301 | glMatrixMode (aMatrixMode); | |
ca3c13d1 | 302 | #endif |
bf75be98 | 303 | |
304 | myTextureBound->Unbind (myGlContext); | |
305 | switch (myTextureBound->GetTarget()) | |
306 | { | |
ca3c13d1 | 307 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 308 | case GL_TEXTURE_1D: |
309 | { | |
ca3c13d1 | 310 | |
bf75be98 | 311 | if (myTextureBound->GetParams()->GenMode() != GL_NONE) |
312 | { | |
313 | glDisable (GL_TEXTURE_GEN_S); | |
314 | } | |
315 | glDisable (GL_TEXTURE_1D); | |
316 | break; | |
317 | } | |
ca3c13d1 | 318 | #endif |
bf75be98 | 319 | case GL_TEXTURE_2D: |
320 | { | |
ca3c13d1 | 321 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 322 | if (myTextureBound->GetParams()->GenMode() != GL_NONE) |
323 | { | |
324 | glDisable (GL_TEXTURE_GEN_S); | |
325 | glDisable (GL_TEXTURE_GEN_T); | |
a577aaab | 326 | if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE) |
327 | { | |
328 | glDisable (GL_POINT_SPRITE); | |
329 | } | |
bf75be98 | 330 | } |
331 | glDisable (GL_TEXTURE_2D); | |
05e2200b | 332 | #endif |
bf75be98 | 333 | break; |
334 | } | |
335 | default: break; | |
336 | } | |
337 | ||
338 | Handle(OpenGl_Texture) aPrevTexture = myTextureBound; | |
339 | myTextureBound.Nullify(); | |
340 | return aPrevTexture; | |
341 | } | |
342 | ||
343 | // ======================================================================= | |
344 | // function : setTextureParams | |
345 | // purpose : | |
346 | // ======================================================================= | |
347 | void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture, | |
348 | const Handle(Graphic3d_TextureParams)& theParams) | |
349 | { | |
350 | const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams; | |
351 | if (aParams.IsNull()) | |
352 | { | |
353 | return; | |
354 | } | |
355 | ||
ca3c13d1 | 356 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 357 | GLint aMatrixMode = GL_TEXTURE; |
358 | glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); | |
359 | ||
360 | // setup texture matrix | |
361 | glMatrixMode (GL_TEXTURE); | |
c827ea3a | 362 | OpenGl_Mat4 aTextureMat; |
bf75be98 | 363 | const Graphic3d_Vec2& aScale = aParams->Scale(); |
364 | const Graphic3d_Vec2& aTrans = aParams->Translation(); | |
c827ea3a | 365 | OpenGl_Utils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); |
366 | OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); | |
367 | OpenGl_Utils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f); | |
368 | glLoadMatrixf (aTextureMat); | |
bf75be98 | 369 | |
076ca35c | 370 | GLint anEnvMode = GL_MODULATE; // lighting mode |
371 | if (!aParams->IsModulate()) | |
372 | { | |
373 | anEnvMode = GL_DECAL; | |
374 | if (theTexture->GetFormat() == GL_ALPHA | |
375 | || theTexture->GetFormat() == GL_LUMINANCE) | |
376 | { | |
377 | anEnvMode = GL_REPLACE; | |
378 | } | |
379 | } | |
380 | ||
bf75be98 | 381 | // setup generation of texture coordinates |
382 | switch (aParams->GenMode()) | |
383 | { | |
384 | case Graphic3d_TOTM_OBJECT: | |
385 | { | |
386 | glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | |
387 | glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData()); | |
388 | if (theTexture->GetTarget() != GL_TEXTURE_1D) | |
389 | { | |
390 | glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | |
391 | glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData()); | |
392 | } | |
393 | break; | |
394 | } | |
395 | case Graphic3d_TOTM_SPHERE: | |
396 | { | |
397 | glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); | |
398 | if (theTexture->GetTarget() != GL_TEXTURE_1D) | |
399 | { | |
400 | glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); | |
401 | } | |
402 | break; | |
403 | } | |
404 | case Graphic3d_TOTM_EYE: | |
405 | { | |
c827ea3a | 406 | myGlContext->WorldViewState.Push(); |
407 | ||
408 | myGlContext->WorldViewState.SetIdentity(); | |
409 | myGlContext->ApplyWorldViewMatrix(); | |
bf75be98 | 410 | |
411 | glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); | |
412 | glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData()); | |
413 | ||
414 | if (theTexture->GetTarget() != GL_TEXTURE_1D) | |
415 | { | |
416 | glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); | |
417 | glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData()); | |
418 | } | |
c827ea3a | 419 | |
420 | myGlContext->WorldViewState.Pop(); | |
421 | ||
bf75be98 | 422 | break; |
423 | } | |
a577aaab | 424 | case Graphic3d_TOTM_SPRITE: |
425 | { | |
426 | if (GetGlContext()->core20 != NULL) | |
427 | { | |
428 | glEnable (GL_POINT_SPRITE); | |
429 | glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); | |
076ca35c | 430 | anEnvMode = GL_REPLACE; |
a577aaab | 431 | GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); |
432 | } | |
433 | break; | |
434 | } | |
bf75be98 | 435 | case Graphic3d_TOTM_MANUAL: |
436 | default: break; | |
437 | } | |
438 | ||
439 | // setup lighting | |
076ca35c | 440 | glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode); |
ca3c13d1 | 441 | #endif |
bf75be98 | 442 | |
25ef750e | 443 | // get active sampler object to override default texture parameters |
444 | const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); | |
445 | ||
bf75be98 | 446 | // setup texture filtering and wrapping |
447 | //if (theTexture->GetParams() != theParams) | |
448 | const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR; | |
ca3c13d1 | 449 | const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp(); |
bf75be98 | 450 | switch (theTexture->GetTarget()) |
451 | { | |
ca3c13d1 | 452 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 453 | case GL_TEXTURE_1D: |
454 | { | |
25ef750e | 455 | if (aSampler.IsNull() || !aSampler->IsValid()) |
456 | { | |
457 | glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); | |
458 | glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); | |
459 | glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); | |
460 | } | |
461 | else | |
462 | { | |
463 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); | |
464 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter); | |
465 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); | |
466 | } | |
467 | ||
bf75be98 | 468 | break; |
469 | } | |
ca3c13d1 | 470 | #endif |
bf75be98 | 471 | case GL_TEXTURE_2D: |
472 | { | |
473 | GLenum aFilterMin = aFilter; | |
474 | if (theTexture->HasMipmaps()) | |
475 | { | |
476 | aFilterMin = GL_NEAREST_MIPMAP_NEAREST; | |
477 | if (aParams->Filter() == Graphic3d_TOTF_BILINEAR) | |
478 | { | |
479 | aFilterMin = GL_LINEAR_MIPMAP_NEAREST; | |
480 | } | |
481 | else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR) | |
482 | { | |
483 | aFilterMin = GL_LINEAR_MIPMAP_LINEAR; | |
484 | } | |
485 | ||
486 | if (myGlContext->extAnis) | |
487 | { | |
488 | // setup degree of anisotropy filter | |
489 | const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy(); | |
25ef750e | 490 | GLint aDegree; |
bf75be98 | 491 | switch (aParams->AnisoFilter()) |
492 | { | |
493 | case Graphic3d_LOTA_QUALITY: | |
494 | { | |
25ef750e | 495 | aDegree = aMaxDegree; |
bf75be98 | 496 | break; |
497 | } | |
498 | case Graphic3d_LOTA_MIDDLE: | |
499 | { | |
25ef750e | 500 | aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2); |
bf75be98 | 501 | break; |
502 | } | |
503 | case Graphic3d_LOTA_FAST: | |
504 | { | |
25ef750e | 505 | aDegree = 2; |
bf75be98 | 506 | break; |
507 | } | |
508 | case Graphic3d_LOTA_OFF: | |
509 | default: | |
510 | { | |
25ef750e | 511 | aDegree = 1; |
bf75be98 | 512 | break; |
513 | } | |
514 | } | |
25ef750e | 515 | |
516 | if (aSampler.IsNull() || !aSampler->IsValid()) | |
517 | { | |
518 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); | |
519 | } | |
520 | else | |
521 | { | |
522 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); | |
523 | } | |
bf75be98 | 524 | } |
525 | } | |
25ef750e | 526 | |
527 | if (aSampler.IsNull() || !aSampler->IsValid()) | |
528 | { | |
529 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); | |
530 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); | |
531 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); | |
532 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); | |
533 | } | |
534 | else | |
535 | { | |
536 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin); | |
537 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); | |
538 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); | |
539 | aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode); | |
540 | } | |
541 | ||
bf75be98 | 542 | break; |
543 | } | |
544 | default: break; | |
545 | } | |
546 | ||
547 | switch (theTexture->GetTarget()) | |
548 | { | |
ca3c13d1 | 549 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 550 | case GL_TEXTURE_1D: |
551 | { | |
552 | if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) | |
553 | { | |
554 | glEnable (GL_TEXTURE_GEN_S); | |
555 | } | |
556 | glEnable (GL_TEXTURE_1D); | |
557 | break; | |
558 | } | |
ca3c13d1 | 559 | #endif |
bf75be98 | 560 | case GL_TEXTURE_2D: |
561 | { | |
ca3c13d1 | 562 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 563 | if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) |
564 | { | |
565 | glEnable (GL_TEXTURE_GEN_S); | |
566 | glEnable (GL_TEXTURE_GEN_T); | |
567 | } | |
568 | glEnable (GL_TEXTURE_2D); | |
05e2200b | 569 | #endif |
bf75be98 | 570 | break; |
571 | } | |
572 | default: break; | |
573 | } | |
574 | ||
ca3c13d1 | 575 | #if !defined(GL_ES_VERSION_2_0) |
bf75be98 | 576 | glMatrixMode (aMatrixMode); // turn back active matrix |
ca3c13d1 | 577 | #endif |
bf75be98 | 578 | theTexture->SetParams (aParams); |
579 | } | |
580 | ||
581 | // ======================================================================= | |
582 | // function : EnableTexture | |
583 | // purpose : | |
584 | // ======================================================================= | |
585 | Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture, | |
586 | const Handle(Graphic3d_TextureParams)& theParams) | |
587 | { | |
588 | if (theTexture.IsNull() || !theTexture->IsValid()) | |
589 | { | |
590 | return DisableTexture(); | |
591 | } | |
592 | ||
bca1d6e2 | 593 | if (myTextureBound == theTexture |
594 | && (theParams.IsNull() || theParams == theTexture->GetParams())) | |
bf75be98 | 595 | { |
bca1d6e2 | 596 | // already bound |
597 | return myTextureBound; | |
bf75be98 | 598 | } |
599 | ||
600 | Handle(OpenGl_Texture) aPrevTexture = DisableTexture(); | |
601 | myTextureBound = theTexture; | |
602 | myTextureBound->Bind (myGlContext); | |
603 | setTextureParams (myTextureBound, theParams); | |
604 | ||
25ef750e | 605 | // If custom sampler object is available it will be |
606 | // used for overriding default texture parameters | |
607 | const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); | |
608 | ||
609 | if (!aSampler.IsNull() && aSampler->IsValid()) | |
610 | { | |
611 | aSampler->Bind (*myGlContext); | |
612 | } | |
613 | ||
bf75be98 | 614 | return aPrevTexture; |
615 | } | |
a174a3c5 | 616 | |
617 | // ======================================================================= | |
618 | // function : Redraw | |
619 | // purpose : | |
620 | // ======================================================================= | |
621 | void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, | |
622 | const Aspect_CLayer2d& theCUnderLayer, | |
623 | const Aspect_CLayer2d& theCOverLayer) | |
624 | { | |
625 | if (!Activate()) | |
626 | { | |
627 | return; | |
628 | } | |
629 | ||
a89742cf | 630 | ++myFrameCounter; |
b7cd4ba7 | 631 | myIsCullingEnabled = theCView.IsCullingEnabled; |
632 | ||
a174a3c5 | 633 | // release pending GL resources |
634 | Handle(OpenGl_Context) aGlCtx = GetGlContext(); | |
635 | aGlCtx->ReleaseDelayed(); | |
636 | ||
b5ac8292 | 637 | // fetch OpenGl context state |
638 | aGlCtx->FetchState(); | |
a174a3c5 | 639 | |
25b97fac | 640 | Tint toSwap = (aGlCtx->IsRender() && !aGlCtx->caps->buffersNoSwap) ? 1 : 0; // swap buffers |
a174a3c5 | 641 | OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO; |
642 | if (aFrameBuffer != NULL) | |
643 | { | |
fd4a6963 | 644 | aFrameBuffer->SetupViewport (aGlCtx); |
a174a3c5 | 645 | toSwap = 0; // no need to swap buffers |
646 | } | |
e3573bb9 | 647 | else |
648 | { | |
649 | aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight); | |
650 | } | |
a174a3c5 | 651 | |
a89742cf | 652 | myToRedrawGL = Standard_True; |
653 | if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING | |
654 | && myComputeInitStatus != OpenGl_RT_FAIL) | |
e276548b | 655 | { |
a89742cf | 656 | if (UpdateRaytraceGeometry (OpenGl_GUM_CHECK) && myIsRaytraceDataValid) |
657 | { | |
658 | myToRedrawGL = Standard_False; | |
659 | ||
660 | // Only non-raytracable structures should be rendered in OpenGL mode. | |
661 | Handle(OpenGl_RenderFilter) aRenderFilter = GetRenderFilter(); | |
662 | myRaytraceFilter->SetPrevRenderFilter (aRenderFilter); | |
663 | SetRenderFilter (myRaytraceFilter); | |
664 | ||
665 | Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; | |
666 | Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; | |
667 | ||
668 | if (myOpenGlFBO.IsNull()) | |
669 | { | |
670 | myOpenGlFBO = new OpenGl_FrameBuffer(); | |
671 | } | |
672 | if (myOpenGlFBO->GetVPSizeX() != aSizeX | |
673 | || myOpenGlFBO->GetVPSizeY() != aSizeY) | |
674 | { | |
675 | myOpenGlFBO->Init (aGlCtx, aSizeX, aSizeY); | |
676 | } | |
677 | ||
678 | // OverLayer and UnderLayer shouldn't be drawn by OpenGL. | |
679 | // They will be drawn during ray-tracing. | |
680 | Aspect_CLayer2d anEmptyCLayer; | |
681 | anEmptyCLayer.ptrLayer = NULL; | |
682 | ||
683 | myOpenGlFBO->BindBuffer (aGlCtx); | |
684 | redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0); | |
685 | myOpenGlFBO->UnbindBuffer (aGlCtx); | |
686 | ||
687 | const Standard_Boolean isImmediate = !myView->ImmediateStructures().IsEmpty(); | |
688 | Raytrace (theCView, aSizeX, aSizeY, isImmediate ? 0 : toSwap, | |
689 | theCOverLayer, theCUnderLayer, aFrameBuffer); | |
690 | ||
691 | if (isImmediate) | |
692 | { | |
693 | RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True); | |
694 | } | |
695 | ||
696 | SetRenderFilter (aRenderFilter); | |
697 | ||
698 | theCView.WasRedrawnGL = Standard_False; | |
699 | } | |
700 | } | |
701 | ||
702 | if (myToRedrawGL) | |
703 | { | |
704 | // draw entire frame using normal OpenGL pipeline | |
705 | if (aFrameBuffer != NULL) | |
706 | { | |
707 | aFrameBuffer->BindBuffer (aGlCtx); | |
708 | } | |
709 | ||
679ecdee | 710 | const Standard_Boolean isImmediate = !myView->ImmediateStructures().IsEmpty(); |
711 | redraw1 (theCView, theCUnderLayer, theCOverLayer, isImmediate ? 0 : toSwap); | |
712 | if (isImmediate) | |
e276548b | 713 | { |
679ecdee | 714 | RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True); |
e276548b | 715 | } |
716 | ||
717 | theCView.WasRedrawnGL = Standard_True; | |
e276548b | 718 | } |
a174a3c5 | 719 | |
720 | if (aFrameBuffer != NULL) | |
721 | { | |
722 | aFrameBuffer->UnbindBuffer (aGlCtx); | |
723 | // move back original viewport | |
e3573bb9 | 724 | aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight); |
a174a3c5 | 725 | } |
726 | ||
679ecdee | 727 | #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) |
a174a3c5 | 728 | if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow)) |
729 | { | |
730 | GLint params[4]; | |
731 | glGetIntegerv (GL_VIEWPORT, params); | |
732 | int nWidth = params[2] & ~0x7; | |
733 | int nHeight = params[3] & ~0x7; | |
734 | ||
735 | const int nBitsPerPixel = 24; | |
736 | GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8]; | |
737 | ||
738 | glPixelStorei (GL_PACK_ALIGNMENT, 1); | |
739 | glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData); | |
740 | OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel); | |
741 | delete[] aDumpData; | |
742 | } | |
743 | #endif | |
744 | ||
745 | // reset render mode state | |
b5ac8292 | 746 | aGlCtx->FetchState(); |
a174a3c5 | 747 | } |
679ecdee | 748 | |
749 | // ======================================================================= | |
750 | // function : redraw1 | |
751 | // purpose : | |
752 | // ======================================================================= | |
753 | void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView, | |
754 | const Aspect_CLayer2d& theCUnderLayer, | |
755 | const Aspect_CLayer2d& theCOverLayer, | |
756 | const int theToSwap) | |
757 | { | |
73192b37 | 758 | if (myView.IsNull()) |
679ecdee | 759 | { |
760 | return; | |
761 | } | |
762 | ||
763 | // request reset of material | |
764 | NamedStatus |= OPENGL_NS_RESMAT; | |
765 | ||
679ecdee | 766 | GLbitfield toClear = GL_COLOR_BUFFER_BIT; |
767 | if (myUseZBuffer) | |
768 | { | |
769 | glDepthFunc (GL_LEQUAL); | |
770 | glDepthMask (GL_TRUE); | |
771 | if (myUseDepthTest) | |
772 | { | |
773 | glEnable (GL_DEPTH_TEST); | |
774 | } | |
775 | else | |
776 | { | |
777 | glDisable (GL_DEPTH_TEST); | |
778 | } | |
779 | ||
ca3c13d1 | 780 | #if !defined(GL_ES_VERSION_2_0) |
679ecdee | 781 | glClearDepth (1.0); |
ca3c13d1 | 782 | #else |
783 | glClearDepthf (1.0f); | |
784 | #endif | |
679ecdee | 785 | toClear |= GL_DEPTH_BUFFER_BIT; |
786 | } | |
787 | else | |
788 | { | |
789 | glDisable (GL_DEPTH_TEST); | |
790 | } | |
791 | ||
a89742cf | 792 | if (!ToRedrawGL()) |
679ecdee | 793 | { |
a89742cf | 794 | // set background to black |
795 | glClearColor (0.0f, 0.0f, 0.0f, 0.0f); | |
796 | toClear |= GL_DEPTH_BUFFER_BIT; // | |
679ecdee | 797 | } |
798 | else | |
799 | { | |
a89742cf | 800 | if (NamedStatus & OPENGL_NS_WHITEBACK) |
801 | { | |
802 | // set background to white | |
803 | glClearColor (1.0f, 1.0f, 1.0f, 1.0f); | |
804 | toClear |= GL_DEPTH_BUFFER_BIT; | |
805 | } | |
806 | else | |
807 | { | |
808 | glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f); | |
809 | } | |
679ecdee | 810 | } |
811 | glClear (toClear); | |
812 | ||
813 | Handle(OpenGl_Workspace) aWS (this); | |
814 | myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer); | |
815 | ||
816 | // swap the buffers | |
817 | if (theToSwap) | |
818 | { | |
819 | GetGlContext()->SwapBuffers(); | |
820 | myBackBufferRestored = Standard_False; | |
821 | myIsImmediateDrawn = Standard_False; | |
822 | } | |
823 | else | |
824 | { | |
a89742cf | 825 | glFlush(); // |
826 | myBackBufferRestored = Standard_True;// | |
827 | myIsImmediateDrawn = Standard_False;// | |
679ecdee | 828 | } |
829 | } | |
830 | ||
831 | // ======================================================================= | |
832 | // function : copyBackToFront | |
833 | // purpose : | |
834 | // ======================================================================= | |
835 | void OpenGl_Workspace::copyBackToFront() | |
836 | { | |
ca3c13d1 | 837 | #if !defined(GL_ES_VERSION_2_0) |
ca3c13d1 | 838 | |
c827ea3a | 839 | OpenGl_Mat4 aProjectMat; |
840 | OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat, | |
841 | 0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight)); | |
842 | ||
843 | myGlContext->WorldViewState.Push(); | |
844 | myGlContext->ProjectionState.Push(); | |
845 | ||
846 | myGlContext->WorldViewState.SetIdentity(); | |
847 | myGlContext->ProjectionState.SetCurrent (aProjectMat); | |
848 | ||
849 | myGlContext->ApplyProjectionMatrix(); | |
850 | myGlContext->ApplyWorldViewMatrix(); | |
679ecdee | 851 | |
852 | DisableFeatures(); | |
853 | ||
854 | glDrawBuffer (GL_FRONT); | |
855 | glReadBuffer (GL_BACK); | |
856 | ||
857 | glRasterPos2i (0, 0); | |
858 | glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR); | |
859 | ||
860 | EnableFeatures(); | |
861 | ||
c827ea3a | 862 | myGlContext->WorldViewState.Pop(); |
863 | myGlContext->ProjectionState.Pop(); | |
864 | myGlContext->ApplyProjectionMatrix(); | |
679ecdee | 865 | glDrawBuffer (GL_BACK); |
866 | ||
ca3c13d1 | 867 | #endif |
679ecdee | 868 | myIsImmediateDrawn = Standard_False; |
869 | } | |
870 | ||
871 | // ======================================================================= | |
872 | // function : DisplayCallback | |
873 | // purpose : | |
874 | // ======================================================================= | |
875 | void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView, | |
876 | Standard_Integer theReason) | |
877 | { | |
878 | if (theCView.GDisplayCB == NULL) | |
879 | { | |
880 | return; | |
881 | } | |
882 | ||
883 | Aspect_GraphicCallbackStruct aCallData; | |
884 | aCallData.reason = theReason; | |
885 | aCallData.glContext = GetGlContext(); | |
886 | aCallData.wsID = theCView.WsId; | |
887 | aCallData.viewID = theCView.ViewId; | |
888 | theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData); | |
889 | } | |
890 | ||
891 | // ======================================================================= | |
892 | // function : RedrawImmediate | |
893 | // purpose : | |
894 | // ======================================================================= | |
895 | void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, | |
896 | const Aspect_CLayer2d& theCUnderLayer, | |
897 | const Aspect_CLayer2d& theCOverLayer, | |
898 | const Standard_Boolean theToForce) | |
899 | { | |
900 | if (!Activate()) | |
901 | { | |
902 | return; | |
903 | } | |
904 | ||
905 | GLboolean isDoubleBuffer = GL_FALSE; | |
ca3c13d1 | 906 | #if !defined(GL_ES_VERSION_2_0) |
679ecdee | 907 | glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer); |
ca3c13d1 | 908 | #endif |
679ecdee | 909 | if (myView->ImmediateStructures().IsEmpty()) |
910 | { | |
911 | if (theToForce | |
912 | || !myIsImmediateDrawn) | |
913 | { | |
914 | myIsImmediateDrawn = Standard_False; | |
915 | return; | |
916 | } | |
917 | ||
918 | if (myBackBufferRestored | |
919 | && isDoubleBuffer) | |
920 | { | |
921 | copyBackToFront(); | |
65812bd0 | 922 | glFlush(); |
679ecdee | 923 | } |
924 | else | |
925 | { | |
926 | Redraw (theCView, theCUnderLayer, theCOverLayer); | |
927 | } | |
928 | return; | |
929 | } | |
930 | ||
931 | if (isDoubleBuffer && myTransientDrawToFront) | |
932 | { | |
933 | if (!myBackBufferRestored) | |
934 | { | |
935 | Redraw (theCView, theCUnderLayer, theCOverLayer); | |
936 | return; | |
937 | } | |
938 | copyBackToFront(); | |
939 | MakeFrontBufCurrent(); | |
940 | } | |
941 | else | |
942 | { | |
943 | myBackBufferRestored = Standard_False; | |
944 | } | |
945 | myIsImmediateDrawn = Standard_True; | |
946 | ||
947 | NamedStatus |= OPENGL_NS_IMMEDIATE; | |
948 | ///glDisable (GL_LIGHTING); | |
949 | glDisable (GL_DEPTH_TEST); | |
950 | ||
951 | Handle(OpenGl_Workspace) aWS (this); | |
952 | for (OpenGl_SequenceOfStructure::Iterator anIter (myView->ImmediateStructures()); | |
953 | anIter.More(); anIter.Next()) | |
954 | { | |
955 | const OpenGl_Structure* aStructure = anIter.Value(); | |
956 | aStructure->Render (aWS); | |
957 | } | |
958 | ||
959 | NamedStatus &= ~OPENGL_NS_IMMEDIATE; | |
960 | ||
961 | if (isDoubleBuffer && myTransientDrawToFront) | |
962 | { | |
963 | glFlush(); | |
964 | MakeBackBufCurrent(); | |
965 | } | |
966 | } |