0024345: TKOpenGl - GLSL compatibility issues on NV40 (GeForce 6xxx/7xxx)
[occt.git] / src / OpenGl / OpenGl_Workspace_5.cxx
1 // Created on: 2011-08-05
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <OpenGl_GlCore11.hxx>
22
23 #include <OpenGl_Workspace.hxx>
24
25 #include <OpenGl_AspectLine.hxx>
26 #include <OpenGl_AspectFace.hxx>
27 #include <OpenGl_AspectMarker.hxx>
28 #include <OpenGl_AspectText.hxx>
29 #include <OpenGl_Context.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35
36 /* OCC22218 NOTE: project dependency on gl2ps is specified by macro */
37 #ifdef HAVE_GL2PS
38   #include <gl2ps.h>
39   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
40      Pragma comment for gl2ps.lib is defined only here. */
41   #ifdef _MSC_VER
42   #pragma comment( lib, "gl2ps.lib" )
43   #endif
44 #endif
45
46 #include <Aspect_PolygonOffsetMode.hxx>
47 #include <OpenGl_View.hxx>
48
49 /*----------------------------------------------------------------------*/
50
51 static void TelUpdatePolygonOffsets( const TEL_POFFSET_PARAM *pdata )
52 {
53   if ( ( pdata->mode & Aspect_POM_Fill ) == Aspect_POM_Fill )
54     glEnable ( GL_POLYGON_OFFSET_FILL );
55   else
56     glDisable ( GL_POLYGON_OFFSET_FILL );
57
58   if ( ( pdata->mode & Aspect_POM_Line ) == Aspect_POM_Line )
59     glEnable ( GL_POLYGON_OFFSET_LINE );
60   else
61     glDisable( GL_POLYGON_OFFSET_LINE );
62
63   if ( ( pdata->mode & Aspect_POM_Point ) == Aspect_POM_Point )
64     glEnable ( GL_POLYGON_OFFSET_POINT );
65   else
66     glDisable( GL_POLYGON_OFFSET_POINT );
67
68   glPolygonOffset( pdata->factor, pdata->units );
69 }
70
71 /*----------------------------------------------------------------------*/
72
73 void OpenGl_Workspace::UpdateMaterial( const int flag )
74 {
75   // Case of hidden line
76   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
77   {
78     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
79     myAspectFaceHl.ChangeIntFront().matcol     = BackgroundColor();
80     myAspectFaceHl.ChangeIntFront().color_mask = 0;
81     myAspectFaceHl.ChangeIntFront().color_mask = 0;
82
83     AspectFace_set = &myAspectFaceHl;
84     return;
85   }
86
87   const OPENGL_SURF_PROP *prop = NULL;
88   GLenum face = 0;
89   if ( flag == TEL_FRONT_MATERIAL )
90   {
91     prop = &AspectFace_set->IntFront();
92     face = GL_FRONT_AND_BACK;
93   }
94   else
95   {
96     prop = &AspectFace_set->IntBack();
97     face = GL_BACK;
98   }
99
100   // Handling transparency
101   if ( (NamedStatus & OPENGL_NS_2NDPASSDO) == 0 )
102   {
103     if ( myUseTransparency && prop->trans != 1.0F )
104     {
105       // Render transparent
106       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
107       glEnable (GL_BLEND);
108       glDepthMask (GL_FALSE);
109     }
110     else
111     {
112       // Render opaque
113       if ( (NamedStatus & OPENGL_NS_ANTIALIASING) == 0 )
114       {
115         glBlendFunc (GL_ONE, GL_ZERO);
116         glDisable (GL_BLEND);
117       }
118       glDepthMask (GL_TRUE);
119     }
120   }
121
122   // Obtaining reflection mode flags to update GL material properties
123   const unsigned int aReflectionMode = prop->color_mask;
124
125   // Do not update material properties in case of zero reflection mode, 
126   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray()
127   // anyway.
128   if ( !aReflectionMode ) return;
129
130   static float  mAmb[4];
131   static float  mDiff[4];
132   static float  mSpec[4];
133   static float  mEmsv[4];
134   static float  mShin;
135
136   static const float defspeccol[4] = { 1.F, 1.F, 1.F, 1.F };
137
138   // Reset material
139   if ( NamedStatus & OPENGL_NS_RESMAT )
140   {
141     // Ambient component
142     if( aReflectionMode & OPENGL_AMBIENT_MASK )
143     {
144       const float *c = prop->isphysic? prop->ambcol.rgb : prop->matcol.rgb;
145
146       mAmb[0] = prop->amb * c[0];
147       mAmb[1] = prop->amb * c[1];
148       mAmb[2] = prop->amb * c[2];
149     }
150     else
151     {
152       mAmb[0] = 0.F;
153       mAmb[1] = 0.F;
154       mAmb[2] = 0.F;
155     }
156     mAmb[3] = 1.F;
157
158     // Diffusion component
159     if( aReflectionMode & OPENGL_DIFFUSE_MASK )
160     {
161       const float *c = prop->isphysic? prop->difcol.rgb : prop->matcol.rgb;
162
163       mDiff[0] = prop->diff * c[0];
164       mDiff[1] = prop->diff * c[1];
165       mDiff[2] = prop->diff * c[2];
166     }
167     else
168     {
169       mDiff[0] = 0.F;
170       mDiff[1] = 0.F;
171       mDiff[2] = 0.F;
172     }
173     mDiff[3] = 1.F;
174
175     if (NamedStatus & OPENGL_NS_2NDPASSDO)
176     {
177       mDiff[3] = prop->env_reflexion;
178     }
179     else
180     {
181       if (myUseTransparency) mDiff[3] = prop->trans;
182       // If the material reflects the environment scene, the second pass is needed
183       if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
184     }
185
186     // Specular component
187     if( aReflectionMode & OPENGL_SPECULAR_MASK )
188     {
189       const float *c = prop->isphysic? prop->speccol.rgb : defspeccol;
190
191       mSpec[0] = prop->spec * c[0];
192       mSpec[1] = prop->spec * c[1];
193       mSpec[2] = prop->spec * c[2];
194     }
195     else {
196       mSpec[0] = 0.F;
197       mSpec[1] = 0.F;
198       mSpec[2] = 0.F;
199     }
200     mSpec[3] = 1.F;
201
202     // Emissive component
203     if( aReflectionMode & OPENGL_EMISSIVE_MASK )
204     {
205       const float *c = prop->isphysic? prop->emscol.rgb : prop->matcol.rgb;
206
207       mEmsv[0] = prop->emsv * c[0];
208       mEmsv[1] = prop->emsv * c[1];
209       mEmsv[2] = prop->emsv * c[2];
210     }
211     else {
212       mEmsv[0] = 0.F;
213       mEmsv[1] = 0.F;
214       mEmsv[2] = 0.F;
215     }
216     mEmsv[3] = 1.F;
217
218     /* Coeficient de brillance */
219     mShin = prop->shine;
220
221     glMaterialfv(face, GL_AMBIENT, mAmb );
222     glMaterialfv(face, GL_DIFFUSE, mDiff );
223     glMaterialfv(face, GL_SPECULAR, mSpec);
224     glMaterialfv(face, GL_EMISSION, mEmsv);
225     glMaterialf(face, GL_SHININESS, mShin);
226
227     NamedStatus &= ~OPENGL_NS_RESMAT;
228   }
229
230   // Set Material Optimize
231   else
232   {
233     // Ambient component
234     if( aReflectionMode & OPENGL_AMBIENT_MASK )
235     {
236       const float *c = prop->isphysic? prop->ambcol.rgb : prop->matcol.rgb;
237
238       if (mAmb[0] != prop->amb * c[0] ||
239           mAmb[1] != prop->amb * c[1] ||
240           mAmb[2] != prop->amb * c[2] )
241       {
242         mAmb[0] = prop->amb * c[0];
243         mAmb[1] = prop->amb * c[1];
244         mAmb[2] = prop->amb * c[2];
245         mAmb[3] = 1.F;
246
247         glMaterialfv(face, GL_AMBIENT, mAmb);
248       }
249     }
250     else
251     {
252       if ( mAmb[0] != 0.F || mAmb[1] != 0.F || mAmb[2] != 0.F )
253       {
254         mAmb[0] = 0.F;
255         mAmb[1] = 0.F;
256         mAmb[2] = 0.F;
257         mAmb[3] = 1.F;
258
259         glMaterialfv(face, GL_AMBIENT, mAmb);
260       }
261     }
262
263     // Diffusion component
264     if( aReflectionMode & OPENGL_DIFFUSE_MASK )
265     {
266       const float *c = prop->isphysic? prop->difcol.rgb : prop->matcol.rgb;
267
268       if (mDiff[0] != prop->diff * c[0] ||
269           mDiff[1] != prop->diff * c[1] ||
270           mDiff[2] != prop->diff * c[2] ||
271           mDiff[3] != ((NamedStatus & OPENGL_NS_2NDPASSDO)? prop->env_reflexion : (myUseTransparency? prop->trans : 1.0F)))
272       {
273         mDiff[0] = prop->diff * c[0];
274         mDiff[1] = prop->diff * c[1];
275         mDiff[2] = prop->diff * c[2];
276         mDiff[3] = 1.F;
277
278         if (NamedStatus & OPENGL_NS_2NDPASSDO)
279         {
280           mDiff[3] = prop->env_reflexion;
281         }
282         else
283         {
284           if (myUseTransparency) mDiff[3] = prop->trans;
285           // If the material reflects the environment scene, the second pass is needed
286           if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
287         }
288
289         glMaterialfv(face, GL_DIFFUSE, mDiff );
290       }
291     }
292     else
293     {
294       Tfloat newDiff3 = 1.F;
295
296       if (NamedStatus & OPENGL_NS_2NDPASSDO)
297       {
298         newDiff3 = prop->env_reflexion;
299       }
300       else
301       {
302         if (myUseTransparency) newDiff3 = prop->trans;
303         // If the material reflects the environment scene, the second pass is needed
304         if (prop->env_reflexion != 0.0) NamedStatus |= OPENGL_NS_2NDPASSNEED;
305       }
306
307       /* OCC19915: Even if diffuse reflectance is disabled,
308       still trying to update the current transparency if it
309       differs from the previous value  */
310       if ( mDiff[0] != 0.F || mDiff[1] != 0.F || mDiff[2] != 0.F || fabs(mDiff[3] - newDiff3) > 0.01F )
311       {
312         mDiff[0] = 0.F;
313         mDiff[1] = 0.F;
314         mDiff[2] = 0.F;
315         mDiff[3] = newDiff3;
316
317         glMaterialfv(face, GL_DIFFUSE, mDiff);
318       }
319     }
320
321     // Specular component
322     if( aReflectionMode & OPENGL_SPECULAR_MASK )
323     {
324       const float *c = prop->isphysic? prop->speccol.rgb : defspeccol;
325
326       if (mSpec[0] != prop->spec * c[0] ||
327           mSpec[1] != prop->spec * c[1] ||
328           mSpec[2] != prop->spec * c[2])
329       {
330         mSpec[0] = prop->spec * c[0];
331         mSpec[1] = prop->spec * c[1];
332         mSpec[2] = prop->spec * c[2];
333         mSpec[3] = 1.F;
334
335         glMaterialfv(face, GL_SPECULAR, mSpec);
336       }
337     }
338     else
339     {
340       if ( mSpec[0] != 0.F || mSpec[1] != 0.F || mSpec[2] != 0.F )
341       {
342         mSpec[0] = 0.F;
343         mSpec[1] = 0.F;
344         mSpec[2] = 0.F;
345         mSpec[3] = 1.F;
346
347         glMaterialfv(face, GL_SPECULAR, mSpec);
348       }
349     }
350
351     // Emissive component
352     if( aReflectionMode & OPENGL_EMISSIVE_MASK )
353     {
354       const float *c = prop->isphysic? prop->emscol.rgb : prop->matcol.rgb;
355
356       if (mEmsv[0] != prop->emsv * c[0] ||
357           mEmsv[1] != prop->emsv * c[1] ||
358           mEmsv[2] != prop->emsv * c[2])
359       {
360         mEmsv[0] = prop->emsv * c[0];
361         mEmsv[1] = prop->emsv * c[1];
362         mEmsv[2] = prop->emsv * c[2];
363         mEmsv[3] = 1.F;
364
365         glMaterialfv(face, GL_EMISSION, mEmsv);
366       }
367     }
368     else
369     {
370       if ( mEmsv[0] != 0.F || mEmsv[1] != 0.F || mEmsv[2] != 0.F )
371       {
372         mEmsv[0] = 0.F;
373         mEmsv[1] = 0.F;
374         mEmsv[2] = 0.F;
375         mEmsv[3] = 1.F;
376
377         glMaterialfv(face, GL_EMISSION, mEmsv);
378       }
379     }
380
381     // Shining coefficient
382     if( mShin != prop->shine )
383     {
384       mShin = prop->shine;
385       glMaterialf(face, GL_SHININESS, mShin);
386     }
387   }
388 }
389
390 /*----------------------------------------------------------------------*/
391
392 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
393 {
394   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
395   AspectLine_set = AnAspect;
396   return AspectLine_old;
397 }
398
399 /*----------------------------------------------------------------------*/
400
401 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
402 {
403   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
404   AspectFace_set = AnAspect;
405   return AspectFace_old;
406 }
407
408 /*----------------------------------------------------------------------*/
409
410 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
411 {
412   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
413   AspectMarker_set = AnAspect;
414   return AspectMarker_old;
415 }
416
417 /*----------------------------------------------------------------------*/
418
419 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
420 {
421   const OpenGl_AspectText *AspectText_old = AspectText_set;
422   AspectText_set = AnAspect;
423   return AspectText_old;
424 }
425
426 /*----------------------------------------------------------------------*/
427
428 const OpenGl_Matrix * OpenGl_Workspace::SetViewMatrix(const OpenGl_Matrix *AMatrix)
429 {
430   const OpenGl_Matrix *ViewMatrix_old = ViewMatrix_applied;
431   ViewMatrix_applied = AMatrix;
432
433   OpenGl_Matrix lmat;
434   OpenGl_Transposemat3( &lmat, StructureMatrix_applied );
435
436   glMatrixMode (GL_MODELVIEW);
437   OpenGl_Matrix rmat;
438   OpenGl_Multiplymat3 (&rmat, &lmat, ViewMatrix_applied);
439   glLoadMatrixf ((const GLfloat* )rmat.mat);
440
441   return ViewMatrix_old;
442 }
443
444 /*----------------------------------------------------------------------*/
445
446 const OpenGl_Matrix * OpenGl_Workspace::SetStructureMatrix (const OpenGl_Matrix *AMatrix, bool aRevert)
447 {
448   const OpenGl_Matrix *StructureMatrix_old = StructureMatrix_applied;
449   StructureMatrix_applied = AMatrix;
450
451   OpenGl_Matrix lmat;
452   OpenGl_Transposemat3( &lmat, AMatrix );
453
454   glMatrixMode (GL_MODELVIEW);
455   OpenGl_Matrix rmat;
456   OpenGl_Multiplymat3 (&rmat, &lmat, ViewMatrix_applied);
457   glLoadMatrixf ((const GLfloat* )rmat.mat);
458
459   if (!myGlContext->ShaderManager()->IsEmpty())
460   {
461     if (aRevert)
462     {
463       myGlContext->ShaderManager()->RevertModelWorldStateTo (lmat.mat);
464     }
465     else
466     {
467       myGlContext->ShaderManager()->UpdateModelWorldStateTo (lmat.mat);
468     }
469   }
470
471   return StructureMatrix_old;
472 }
473
474 /*----------------------------------------------------------------------*/
475
476 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean WithApply)
477 {
478   if ( WithApply && (AspectLine_set != AspectLine_applied) )
479   {
480     glColor3fv(AspectLine_set->Color().rgb);
481
482     if ( !AspectLine_applied || (AspectLine_set->Type() != AspectLine_applied->Type() ) )
483     {
484       myDisplay->SetTypeOfLine(AspectLine_set->Type());
485     }
486
487     if ( !AspectLine_applied || ( AspectLine_set->Width() != AspectLine_applied->Width() ) )
488     {
489       glLineWidth( (GLfloat)AspectLine_set->Width() );
490 #ifdef HAVE_GL2PS
491       gl2psLineWidth( (GLfloat)AspectLine_set->Width() );
492 #endif
493     }
494
495     AspectLine_applied = AspectLine_set;
496   }
497   return AspectLine_set;
498 }
499
500 /*----------------------------------------------------------------------*/
501
502 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
503 {
504   if (!theToApply || (AspectFace_set == AspectFace_applied))
505   {
506     return AspectFace_set;
507   }
508
509   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
510   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
511   {
512     switch (anIntstyle)
513     {
514       case Aspect_IS_EMPTY:
515       case Aspect_IS_HOLLOW:
516       {
517         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
518         break;
519       }
520       case Aspect_IS_HATCH:
521       {
522         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
523         myDisplay->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
524         break;
525       }
526       case Aspect_IS_SOLID:
527       case Aspect_IS_HIDDENLINE:
528       {
529         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
530         glDisable (GL_POLYGON_STIPPLE);
531         break;
532       }
533       case Aspect_IS_POINT: //szvgl - no corresponding enumeration item Aspect_IS_POINT // = 5
534       {
535         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
536         break;
537       }
538     }
539   }
540
541   if (anIntstyle == Aspect_IS_HATCH)
542   {
543     const Tint hatchstyle = AspectFace_set->Hatch();
544     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
545     {
546       myDisplay->SetTypeOfHatch(hatchstyle);
547     }
548   }
549
550   if (!ActiveView()->Backfacing())
551   {
552     const Tint aCullingMode = AspectFace_set->CullingMode();
553     if (AspectFace_applied == NULL || AspectFace_applied->CullingMode() != aCullingMode)
554     {
555       switch ((TelCullMode )aCullingMode)
556       {
557         case TelCullNone:
558         {
559           glDisable (GL_CULL_FACE);
560           break;
561         }
562         case TelCullFront:
563         {
564           glCullFace (GL_FRONT);
565           glEnable (GL_CULL_FACE);
566           break;
567         }
568         case TelCullBack:
569         {
570           glCullFace (GL_BACK);
571           glEnable (GL_CULL_FACE);
572           break;
573         }
574       }
575     }
576   }
577
578   // Aspect_POM_None means: do not change current settings
579   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
580   {
581     if (PolygonOffset_applied         == NULL
582      || PolygonOffset_applied->mode   != AspectFace_set->PolygonOffset().mode
583      || PolygonOffset_applied->factor != AspectFace_set->PolygonOffset().factor
584      || PolygonOffset_applied->units  != AspectFace_set->PolygonOffset().units)
585     {
586       PolygonOffset_applied = &AspectFace_set->PolygonOffset();
587       TelUpdatePolygonOffsets (PolygonOffset_applied);
588     }
589   }
590
591   UpdateMaterial (TEL_FRONT_MATERIAL);
592   if (AspectFace_set->DistinguishingMode() == TOn)
593   {
594     UpdateMaterial (TEL_BACK_MATERIAL);
595   }
596
597   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
598   {
599     if (AspectFace_set->DoTextureMap())
600     {
601       EnableTexture (AspectFace_set->TextureRes (this),
602                      AspectFace_set->TextureParams());
603     }
604     else
605     {
606       DisableTexture();
607     }
608   }
609
610   AspectFace_applied = AspectFace_set;
611   return AspectFace_set;
612 }
613
614 /*----------------------------------------------------------------------*/
615
616 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
617 {
618   if (theToApply && (AspectMarker_set != AspectMarker_applied))
619   {
620     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
621     {
622       glPointSize (AspectMarker_set->Scale());
623     #ifdef HAVE_GL2PS
624       gl2psPointSize (AspectMarker_set->Scale());
625     #endif
626     }
627     AspectMarker_applied = AspectMarker_set;
628   }
629   return AspectMarker_set;
630 }
631
632 /*----------------------------------------------------------------------*/
633
634 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
635 {
636   if (theWithApply)
637   {
638     AspectText_applied = AspectText_set;
639     TextParam_applied  = TextParam_set;
640   }
641
642   return AspectText_set;
643 }