新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 利用VC+OpenGL实现几种特殊图形效果 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4029 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 利用VC+OpenGL实现几种特殊图形效果 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客楼主
    发贴心情 利用VC+OpenGL实现几种特殊图形效果

    作者: 中国电波传播研究所青岛分所郎锐 出处: 天极网


    引言

      融合(blending)、雾化(fog)与反走样(antialiasing)是OpenGL中的三种特殊效果处理方法。融合提供了一种透明或半透明显示的技术;雾化处理则根据物体距离视点的远近对其进行恰当的模糊处理;反走样则可减少在绘制离散化的图形时所产生的误差走样。

      实现融合特效

      融合可将两种颜色的R、G、B分量按一定比例混在一起形成一种新的颜色,RGBA颜色模式中的A即表示Alpha值,对应于颜色的混合比例。由于只有在RGBA模式中才能对A值进行说明,因此融合不能在颜色索引模式下使用。融合操作可通过源因子(Sr、Sg、Sb、Sa)与目的因子(Dr、Dg、Db、Da)计算锝出,融合结果为(Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)每个元素值都在范围[0, 1]内。可以看出,融合处理的关键就是对融合因子(Sr,Sg,Sb,Sa)和(Dr,Dg,Db,Da)的设定。在OpenGL中,源因子和目的因子通过glBlendFunc()函数产生,其函数形式为:

    void glBlendFunc(GLenum sfactor,GLenum dfactor)  


      
      通过指定参数sfactor和dfactor来分别指出计算源因子和目的因子的方式。具体取值可参见下表。在产生了融合因子值后,还需调用glEnable(GL_BLEND)和glDisable(GL_BLEND)来启用、关闭融合处理。

    常数 相关因子 融合因子结果
    GL_ZERO 源因子或目的因子 (0,0,0,0)
    GL_ONE 源因子或目的因子 (1,1,1,1)
    GL_DST_COLOR  源因子  (Rd,Gd,Bd,Ad)
    GL_SRC_COLOR 目的因子 (Rs,Gs,Bs,As)
    GL_ONE_MINUS_DST_COLOR 源因子  (1,1,1,1)-(Rd,Gd,Bd,Ad)
    GL_ONE_MINUS_SRC_COLOR  目的因子 (1,1,1,1)-(Rs,Gs,Bs,As)
    GL_SRC_ALPHA 源因子或目的因子 (As,As,As,As)
    GL_ONE_MINUS_SRC_ALPHA 源因子或目的因子 (1,1,1,1)-(As,As,As,As)
    GL_DST_ALPHA  源因子或目的因子 (Ad,Ad,Ad,Ad)
    GL_ONE_MINUS_DST_ALPHA  源因子或目的因子  (1,1,1,1)-(Ad,Ad,Ad,Ad)
    GL_SRC_ALPHA_SATURATE 源因子 (f,f,f,1); f=min(As,1-Ad)

      下面是应用了融合技术的一个简单例子,通过图1的绘制结果可以看出在启用了融合处理后在两个具有不同颜色方块的交叠部分颜色发生了变化,该区域即为融合所产生的结果:

    void CALLBACK Display()
    {
      glClear(GL_COLOR_BUFFER_BIT); // 清屏
      glColor4f(0.0, 1.0, 0.0, 0.5); // 绘制矩形
      glRectf(0.1, 0.1, 0.6, 0.6);
      glColor4f(1.0, 1.0, 0.0, 0.7); // 绘制矩形
      glRectf(0.4, 0.3, 0.9, 0.8);
      glFlush(); // 强制绘图完成
    }
    void Init()
    {
      glEnable (GL_BLEND); // 启用融合
      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 产生融合因子
      glShadeModel (GL_FLAT); // 设置平面明暗处理
      glClearColor (0.0, 0.0, 0.0, 0.0); // 清屏
    }



    此主题相关图片如下:
    按此在新窗口浏览图片
    图1 有颜色方块的融合

    雾化特效

      雾化是一种模拟自然界中雾气对场景物体视觉效果产生影响的图形绘制技术。此技术从视点到物体逐渐将物体的绘制颜色淡化,直至背景色。通过雾化处理可较好的表现出物体到视点的距离感。虽然雾化的具体计算非常复杂,但在OpenGL中的使用却非常简单。首先调用glEnable(GL_FOG)以启用雾化处理,启用后离视点较远的物体开始淡化成雾的颜色。然后可通过glFog*()函数来选择控制雾的浓度和颜色的方程,具体形式为:

    void glFog{if}[v](GLenum pname,TYPE param);


      
      该函数设置了雾化参数和函数,在pname为GL_FOG MODE时,参数param可以为GL_EXP(指数)、GL_EXP2(指数平方)和GL_LINEAR(线性);如果参数pname为GL_FOG_DENSITY、GL_FOG_START或GL_FOG_END,参数param将分别指定在不同雾化数学模型下的不同计算公式参量;在参数pname为GL_FOG_COLOR时,param将为一个指向颜色向量的指针。最后,如果有必要,还可以调用函数glHint(GL_FOG_HINT)进一步指定雾化效果。下面给出实现雾化效果的部分具体示例代码及其绘制结果(图2):



    此主题相关图片如下:
    按此在新窗口浏览图片

    图2 雾化效果


    void CALLBACK Display()
    {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清屏
      glPushMatrix(); // 绘制近视点景物
      glTranslatef(-3.0, -1.5, -2.0);
      auxSolidTorus(0.6, 1.5);
      glPopMatrix();
      glPushMatrix(); // 绘制远视点景物
      glTranslatef(2.0, 0.8, -10.0);
      auxSolidTorus(0.6, 1.5);
      glPopMatrix();
      glFlush(); // 强制绘图完成
    }
    void Init()
    {
      GLfloat mat_ambient[] = {0.7, 0.6, 0.0, 1.0}; // 设置光照模型
      GLfloat mat_diffuse[] = {0.7, 0.6, 0.0, 1.0};
      GLfloat mat_specular[] = {1.0, 0.0, 1.0, 1.0};
      GLfloat mat_shininess[] = {50.0};
      GLfloat position[] = {5.0, 5.0, 5.0, 1.0};
      glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
      glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
      glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
      glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
      glEnable(GL_DEPTH_TEST);
      glDepthFunc(GL_LESS);
      glLightfv(GL_LIGHT0, GL_POSITION, position);
      glEnable(GL_LIGHTING);
      glEnable(GL_LIGHT0);
      glFrontFace(GL_CW);
      glEnable(GL_FOG); // 启用雾化处理
      {
      glFogi(GL_FOG_MODE, GL_LINEAR); // 采用线性变化的雾化效果
      GLfloat fogColor[] = {0.3, 0.3, 0.3, 1.0}; // 指定雾化颜色
      glFogfv(GL_FOG_COLOR, fogColor);
      glFogf(GL_FOG_START, 3.0); // 指定按线性变化时计算公式的参量
      glFogf(GL_FOG_END, 15.0);
      glHint(GL_FOG_HINT, GL_DONT_CARE); //规定雾化效果的质量
      }
    }

    实现绘图反走样

      由于在图形绘制到屏幕时,数字化的图像通过离散的象素点来表达,因此所绘制的图元将会在光滑的曲线上产生锯齿,这种锯齿即为走样。反走样也叫做反混淆,它将根据图元的象素区域来确定象素的颜色值,通过这种处理可在一定程度上消除锯齿的影响。在OpenGL中,可通过函数glHint()来对图像质量和绘制速度之间的权衡作一些控制,其函数形式为:

    void glHint(GLenum target,GLenum hint);

      参数target说明控制什么行为,具体的,GL_POINT_SMOOTH_HINT、GL_LINE_SMOOTH_HINT和GL_POLYGON_SMOOTH_HINT分别指定点、线和多边形的采样质量;GL_FOG_HINT指出雾化是按象素进行(GL_NICEST)还是按顶点进行(GL_FASTEST);GL_PERSPECTIVE_CORRECTION_HINT指定了颜色纹理插值的质量并可纠正由单纯线性插值所带来的一些视觉错误。参数hint可以是:GL_FASTEST(给出最有效的选择)、GL_NICEST(给出最高质量的选择)、GL_DONT_CARE(没有选择)。

      虽然在OpenGL的颜色索引模式下也可以实现反走样,但仍建议在RGBA模式下进行。对图元进行反走样时也要先调用glEnable()函数启动反走样(其参数为GL_POINT、GL_LINE_SMOOTH或GL_POLYGON_SMOOTH)。如果是在RGBA模式下进行反走样,还必须与融合配合使用,通常使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA分别作为源和目的因子。下面给出一段在RGBA模式下启用反走样绘制多面体的示例代码,从绘制结果(图3)可以明显看出在多边形的直线边界出现的锯齿得到了较好的平滑:

    void CALLBACK Display()
    {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清屏
      auxWireDodecahedron(1.0); // 绘制二十面体
      glFlush(); // 强制绘图完成
    }
    void Init()
    {
      glEnable(GL_LINE_SMOOTH); // 启用反走样
      glEnable(GL_BLEND); // 启动融合
      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 产生融合因子
      glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);// 权衡图像质量与绘制速度
      glLineWidth(2.0); // 线宽
      glShadeModel(GL_FLAT); // 平面明暗处理
      glClearColor(0.0, 0.0, 0.0, 0.0); // 清屏
      glDepthFunc(GL_LESS); // 激活深度比较
      glEnable(GL_DEPTH_TEST);
    }


    此主题相关图片如下:
    按此在新窗口浏览图片

    图3 反走样多面体


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/14 9:00:00
     
     GoogleAdSense射手座1984-11-30
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/23 1:04:53

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.012ms