OpenGL Shader in OpenCASCADE

系统 1817 0

OpenGL Shader in OpenCASCADE

eryar@163.com

Abstract. As implementation of one of the strategic steps in OpenCASCADE visualization component development road-map, support for GLSL shader programs has been added in OpenCASCADE Technology 6.7.0. 

Key Words. OpenCASCADE, GLSL, Shader, Gooch Shader

1. Introduction

OpenCASCADE从6.7.0之后,Shader程序也成了源码的一部分。程序开发者可以为实现各种特效提供自己的Shader程序。在TKOpenGl库中就有Shader相关的类,如下图所示:

wps_clip_image-16881 wps_clip_image-26090

OpenCASCADE中的Shader管理是完全自动完成的,和其他OpenGL的资源一样。仔细看看这几个类相关的函数,会发现与Qt中的Shader比较类似。对比使用,会加快对OpenGL Shader程序的理解。

在 OCCT6.7.0版本中的Shader程序还有一些局限性,如不能使用GLSL1.40版本或更新版本的功能。为了克服这个局限性,OCCT为了实现一 些shader的操作定义了一些uniform的变量,这样Shader程序就不依赖于GLSL1.30定义的一些变量了,使程序的兼容性更好。在源文件 的Shaders文件夹中的Declarations.glsl中定义了这些变量,摘抄部分如下所示:

        
          //
        
        
           Vertex attributes
        
        
          #ifdef VERTEX_SHADER

  attribute vec4 occVertex;

  attribute vec3 occNormal;

  attribute vec4 occTexCoord;

  attribute vec4 occVertColor;


        
        
          #endif
        
        
          //
        
        
           Matrix state
        
        

uniform mat4 occWorldViewMatrix;  
        
          //
        
        
          !< World-view  matrix
        
        

uniform mat4 occProjectionMatrix; 
        
          //
        
        
          !< Projection  matrix
        
        

uniform mat4 occModelWorldMatrix; 
        
          //
        
        
          !< Model-world matrix
        
        
          

uniform mat4 occWorldViewMatrixInverse;    
        
        
          //
        
        
          !< Inverse of the world-view  matrix
        
        

uniform mat4 occProjectionMatrixInverse;   
        
          //
        
        
          !< Inverse of the projection  matrix
        
        

uniform mat4 occModelWorldMatrixInverse;   
        
          //
        
        
          !< Inverse of the model-world matrix
        
        
          

uniform mat4 occWorldViewMatrixTranspose;  
        
        
          //
        
        
          !< Transpose of the world-view  matrix
        
        

uniform mat4 occProjectionMatrixTranspose; 
        
          //
        
        
          !< Transpose of the projection  matrix
        
        

uniform mat4 occModelWorldMatrixTranspose; 
        
          //
        
        
          !< Transpose of the model-world matrix
        
        
          

uniform mat4 occWorldViewMatrixInverseTranspose;  
        
        
          //
        
        
          !< Transpose of the inverse of the world-view  matrix
        
        

uniform mat4 occProjectionMatrixInverseTranspose; 
        
          //
        
        
          !< Transpose of the inverse of the projection  matrix
        
        

uniform mat4 occModelWorldMatrixInverseTranspose; 
        
          //
        
        
          !< Transpose of the inverse of the model-world matrix
        
      

与OpenGL的内置uniform变量对比会发现,主要内容都是类似的:

        
          //


        
        
          uniform mat4  gl_ModelViewMatrix;

uniform mat4  gl_ProjectionMatrix;

uniform mat4  gl_ModelViewProjectionMatrix;

uniform mat4  gl_TextureMatrix[gl_MaxTextureCoords];




        
        
          //
        
        
          //
        
        
           Derived matrix state that provides inverse and transposed versions


        
        
          //
        
        
           of the matrices above. Poorly conditioned matrices may result


        
        
          //
        
        
           in unpredictable values in their inverse forms.


        
        
          //


        
        uniform mat3  gl_NormalMatrix; 
        
          //
        
        
           transpose of the inverse of the upper

                               
        
        
          //
        
        
           leftmost 3x3 of gl_ModelViewMatrix
        
        
          

uniform mat4  gl_ModelViewMatrixInverse;

uniform mat4  gl_ProjectionMatrixInverse;

uniform mat4  gl_ModelViewProjectionMatrixInverse;

uniform mat4  gl_TextureMatrixInverse[gl_MaxTextureCoords];



uniform mat4  gl_ModelViewMatrixTranspose;

uniform mat4  gl_ProjectionMatrixTranspose;

uniform mat4  gl_ModelViewProjectionMatrixTranspose;

uniform mat4  gl_TextureMatrixTranspose[gl_MaxTextureCoords]



uniform mat4  gl_ModelViewMatrixInverseTranspose;

uniform mat4  gl_ProjectionMatrixInverseTranspose;

uniform mat4  gl_ModelViewProjectionMatrixInverseTranspose;

uniform mat4  gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords]
        
      

看样子OpenCASCADE为了GLSL版本兼容性也是动了些脑筋啊!

2.Test Shader

为 了方便在OpenCASCADE中测试自定义的Shader程序,OpenCASCADE在Draw Test Harness中提供了一个vshaderprog命令。如下图所示为在Draw Test Harness中使用命令vshaderprog产生的Gouraud Shading和Phong Shading效果:

wps_clip_image-4915

Figure 2.1 Gouraud Shading(Left) and Phong Shading(right) by OCCT

在Draw Test Harness中使用vshaderprog命令很简单,如下图所示:

wps_clip_image-1384

Figure 2.2 vshaderprog usage

为指定的模型指定顶点着色器和片段着色器即可。

3.Gooch Shader

Gooch着色属于非真实性图像着色,主要用于绘制各种手册、技术图书上的示意图。1998年,Bruce和Amy Gooch、Peter Shirley以及Elaine Cohen对示意图进行了调查并提出了使用喷枪和画笔绘制的彩色示意图特征:

v 表面边界、轮廓边缘及对象表面的不连续处通常是使用黑色曲线绘制;

v 使用一个单独的光源,它会在对象上产生白色的高光;

v 光源通常位于对象的上方,这样在对象的可见区域上,漫反射部分会在[0,1]中变化;

v ……

wps_clip_image-12173

Figure 3.1 Gooch Shader Effect

上图所示为Gooch着色器渲染出来的效果,看上去是不是很有感觉啊!以上图片来自Amy Gooch, Bruce Gooch, Peter Shirley和Elaine Cohen的论文:

A Non-Photorealistic Lighting Model For Automatic Technical Illustration.

Department of Computer Science University of Utah. Utah大学还有著名的Utah Teapot。

在《OpenGL Shading Language》一书中发现了Gooch着色器的相关实现代码,如下所示:

顶点着色器Gooch.vs:

        
          //
        
        
          //
        
        
           Vertex shader for Gooch shading


        
        
          //
        
        
          //
        
        
           Author: Randi Rost


        
        
          //
        
        
          //
        
        
           Copyright (c) 2002-2005 3Dlabs Inc. Ltd. 


        
        
          //
        
        
          //
        
        
           See 3Dlabs-License.txt for license information


        
        
          //


        
        
          

uniform vec3  LightPosition;  
        
        
          //
        
        
           (0.0, 10.0, 4.0) 
        
        
          

varying 
        
        
          float
        
        
           NdotL;

varying vec3  ReflectVec;

varying vec3  ViewVec;




        
        
          void
        
        
           main()

{

    LightPosition 
        
        = vec3(
        
          0.0
        
        , 
        
          10.0
        
        , 
        
          4.0
        
        
          );

    

    vec3 ecPos      
        
        = vec3(gl_ModelViewMatrix *
        
           gl_Vertex);

    vec3 tnorm      
        
        = normalize(gl_NormalMatrix *
        
           gl_Normal);

    vec3 lightVec   
        
        = normalize(LightPosition -
        
           ecPos);

    ReflectVec      
        
        = normalize(reflect(-
        
          lightVec, tnorm));

    ViewVec         
        
        = normalize(-
        
          ecPos);

    NdotL           
        
        = (dot(lightVec, tnorm) + 
        
          1.0
        
        ) * 
        
          0.5
        
        
          ;

    gl_Position     
        
        =
        
           ftransform();

}
        
      

 

片段着色器Gooch.fs:

        
          //
        
        
          //
        
        
           Fragment shader for Gooch shading


        
        
          //
        
        
          //
        
        
           Author: Randi Rost


        
        
          //
        
        
          //
        
        
           Copyright (c) 2002-2005 3Dlabs Inc. Ltd. 


        
        
          //
        
        
          //
        
        
           See 3Dlabs-License.txt for license information


        
        
          //


        
        
          

uniform vec3  SurfaceColor; 
        
        
          //
        
        
           (0.75, 0.75, 0.75)
        
        

uniform vec3  WarmColor;    
        
          //
        
        
           (0.6, 0.6, 0.0)
        
        

uniform vec3  CoolColor;    
        
          //
        
        
           (0.0, 0.0, 0.6)
        
        

uniform 
        
          float
        
         DiffuseWarm;  
        
          //
        
        
           0.45
        
        

uniform 
        
          float
        
         DiffuseCool;  
        
          //
        
        
           0.45
        
        
          

varying 
        
        
          float
        
        
           NdotL;

varying vec3  ReflectVec;

varying vec3  ViewVec;




        
        
          void
        
        
           main()

{

    SurfaceColor 
        
        = vec3(
        
          0.75
        
        , 
        
          0.75
        
        , 
        
          0.75
        
        
          );

    WarmColor 
        
        = vec3(
        
          0.6
        
        , 
        
          0.6
        
        , 
        
          0.0
        
        
          );

    CoolColor 
        
        = vec3(
        
          0.0
        
        , 
        
          0.0
        
        , 
        
          0.6
        
        
          );

    DiffuseWarm 
        
        = 
        
          0.45
        
        
          ;

    DiffuseCool 
        
        = 
        
          0.45
        
        
          ;

    

    vec3 kcool    
        
        = min(CoolColor + DiffuseCool * SurfaceColor, 
        
          1.0
        
        
          );

    vec3 kwarm    
        
        = min(WarmColor + DiffuseWarm * SurfaceColor, 
        
          1.0
        
        
          ); 

    vec3 kfinal   
        
        =
        
           mix(kcool, kwarm, NdotL);



    vec3 nreflect 
        
        =
        
           normalize(ReflectVec);

    vec3 nview    
        
        =
        
           normalize(ViewVec);



    
        
        
          float
        
         spec    = max(dot(nreflect, nview), 
        
          0.0
        
        
          );

    spec          
        
        = pow(spec, 
        
          32.0
        
        
          );



    gl_FragColor 
        
        = vec4(min(kfinal + spec, 
        
          1.0
        
        ), 
        
          1.0
        
        
          );

}
        
      

将它们加载到OpenCASCADE中,显示效果如下图所示:

wps_clip_image-8706

Figure 3.2 A Main Engine in Draw Test Harness

wps_clip_image-24159

Figure 3.3 Use Gooch Shader Program

由上图可知,Shader有一定的作用,但效果不是很理想。还需要学习相关的知识,才能完善。如果在OpenCASCADE中只修改下shader就可以得到各种特效,岂不快哉!

4.Conclusion

综上所述,OpenGL的Shader是个很好玩的东西,所以OpenCASCADE中引入了这个。为了保证GLSL的兼容性,OpenCASCADE也定义了一些变量。

在不改变程序源码的情况下,只换上不同的shader,就可以得到各种炫丽的特效,这些特效主要是利用GPU的资源完成,不占用CPU。看OpenGL最新的规格书中,GLSL已经越来越Fashion了!

5. References

1. Randi J. Rost. OpenGL Shading Language. Addison Wesley. 2006

2. Amy Gooch, Bruce Gooch, Peter Shirley, Elaine Cohen. A Non-Photorealistic Lighting Model For Automatic Technical Illustration. Department of Computer Science University of Utah.

3. San, Shader support in OCCT6.7.0. http://dev.opencascade.org/index.php?q=node/902

 

PDF version and Gooch Shader OpenGL Shader in OpenCASCADE

OpenGL Shader in OpenCASCADE


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论