`
icheng
  • 浏览: 882254 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
文章分类
社区版块
存档分类
最新评论

Win32 OpenGL编程(13) 隐藏表面消除(深度测试)及雾效果

 
阅读更多

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

隐藏表面消除(深度测试)

其实这是个滞后的话题了,事实上应该在光照一节就应该详述的,但是因为光照的内容本来就多,所以当时并没有再牵涉此内容。

在我们填充三维物体时,与平面绘制不同,因为牵涉到了前面物体遮挡后面物体的问题,假如没有一个很好的内置机制,我们就只能通过程序记住每个物体的Z轴(其实也不一定是Z轴,看当时的观察方向),然后按顺序将远的物体先绘制,然后再绘制离我们近的,通过这种方式,可以让离我们近的物体绘制在后面,覆盖掉远的物体。

当然,假如觉得不麻烦的话,这样做倒也不是不行,但是假如这些事情是由硬件实现的话,效率可是会上一个层次的,所以OpenGL也提供了此方法,被称作深度测试。(Depth Test)使用方法那是相当简单,仅仅需要通过glEnable启用就可以了,我们现在看看使用前后的区别。

我们通过以下函数绘制一大一小两个球

void 
DrawBigRedSphere
()
{
    GLfloat mat_specular
[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_shininess
[] = { 50.0 };
    GLfloat mat_ambient
[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_diffuse
[] = { 1.0, 0.0, 0.0, 1.0 };

    glMaterialfv
(GL_FRONT
, GL_SPECULAR
, mat_specular
);
    glMaterialfv
(GL_FRONT
, GL_SHININESS
, mat_shininess
);
    glMaterialfv
(GL_FRONT
, GL_AMBIENT
, mat_ambient
);
    glMaterialfv
(GL_FRONT
, GL_DIFFUSE
, mat_diffuse
);

    glutSolidSphere
(0.5, 32, 32);
}

void 
DrawSmallBlueSphere
()
{
    GLfloat mat_specular
[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_shininess
[] = { 50.0 };
    GLfloat mat_ambient
[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_diffuse
[] = { 0.0, 0.0, 1.0, 1.0 };

    glMaterialfv
(GL_FRONT
, GL_SPECULAR
, mat_specular
);
    glMaterialfv
(GL_FRONT
, GL_SHININESS
, mat_shininess
);
    glMaterialfv
(GL_FRONT
, GL_AMBIENT
, mat_ambient
);
    glMaterialfv
(GL_FRONT
, GL_DIFFUSE
, mat_diffuse
);

    glutSolidSphere
(0.3, 32, 32);
}

DrawBigRedSphere绘制的是大的红球,DrawSmallBlueSphere绘制的是小的蓝球,绘制的时候都采用默认坐标,即绘制在屏幕的中央,并且Z轴也不动,那么,从理论上来讲,大球会包含小球,小球就被大球遮掩了,我们显示要的应该也是这种效果。

看一下未开启深度测试情况下的情况我们先绘制大球,再绘制小球的和用相反顺序再绘制的情形:

代码如下:

void 
SceneShow
(GLvoid
)        
{
    glClear
(GL_COLOR_BUFFER_BIT 
| GL_DEPTH_BUFFER_BIT
);    

    glPushMatrix
();
    glTranslatef
(-0.5, 0.0, 0.0);
    DrawBigRedSphere
();
    DrawSmallBlueSphere
();
    glPopMatrix
();

    glPushMatrix
();
    glTranslatef
(0.5, 0.0, 0.0);
    DrawSmallBlueSphere
();
    DrawBigRedSphere
();
    glPopMatrix
();

    glFlush
();
}  

image

我们会观察到很明显的绘制顺序导致的问题,左边的图因为先绘制大球再绘制小球,小的篮球竟然覆盖掉了应该在其外部的红球。实际使用中,我们可以都自己判断,然后用右边的正确绘制方式,随着图形的增多,会增加一定的计算量,OpenGL提供的深度测试就是为我们提供了更简便高效的方式,事实上,由于OpenGL使用的方式因为可以在测试后,直接绘制出最终图形而忽略绘制被覆盖掉的图形,效率上比覆盖绘制会更高一些(需要硬件支持)。

上述代码,仅仅需要添加一行,

glEnable(GL_DEPTH_TEST);

以启用深度测试,效果大不一样:

image

天下至简之事莫过于此:)

为节省篇幅仅贴出关键片段,完整源代码见我博客源代码的2009-11-12/glDepthTest/ 目录,获取方式见文章最后关于获取博客完整源代码的说明。

扇子驱不散大雾 -- 阿拉伯谚语

像云像雾 又像风 -- 某电视剧名

雾作为一种常见的天气现象,OpenGL中有所模拟体现也算是正常,但是在OpenGL中雾的作用却又不止这些,事实上,雾效果还用于实现模糊效果,用于关于模拟模糊,薄雾,烟,污染。

使用步骤非常简单,一如OpenGL惯例,首先通过glEnable开启,然后又有一个glFog*这个用于设置雾效果的函数可以使用,呵呵,OpenGL学多了,会发现除了概念不一样,基本上的使用步骤都差不多,开始觉得OpenGL的这种一个函数通过pname参数去决定函数作用的方式不太符合好的API的设计哲学,(可以参考《设计Qt风格的C++API【转】 》)但是想来,API的设计还不一定有绝对意义上的好坏,这样的设计倒是在一定程度上减少了API的数量,并且查找时会稍微方便一点,虽然同时增加了查文档看参数作用的负担,这些又是题外话了。

首先看没有雾效果时,我用OpenGL绘制的3个红球,红球的Z轴是依次向内。

主要代码如下:

void 
DrawRedSphere
()
{
    GLfloat mat_specular
[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_shininess
[] = { 50.0 };
    GLfloat mat_ambient
[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_diffuse
[] = { 1.0, 0.0, 0.0, 1.0 };

    glMaterialfv
(GL_FRONT
, GL_SPECULAR
, mat_specular
);
    glMaterialfv
(GL_FRONT
, GL_SHININESS
, mat_shininess
);
    glMaterialfv
(GL_FRONT
, GL_AMBIENT
, mat_ambient
);
    glMaterialfv
(GL_FRONT
, GL_DIFFUSE
, mat_diffuse
);

    glutSolidSphere
(0.25, 32, 32);
}

//这里进行所有的绘图工作

void 
SceneShow
(GLvoid
)        
{
    glClear
(GL_COLOR_BUFFER_BIT 
| GL_DEPTH_BUFFER_BIT
);    

    glPushMatrix
();
    glTranslatef
(-0.75, 0.0, 0.0);
    DrawRedSphere
();
    glPopMatrix
();

    glPushMatrix
();
    glTranslatef
(0.0, 0.0, -1.0);
    DrawRedSphere
();
    glPopMatrix
();

    glPushMatrix
();
    glTranslatef
(0.75, 0.0, -2.0);
    DrawRedSphere
();
    glPopMatrix
();

    glFlush
();
}  

image

从图形上效果上看不出Z轴的变化,因为使用的是正投影方式。现在我们启用雾效果来试一下。

添加进如下语句:

glEnable
(GL_FOG
);
GLfloat fogColor
[4] = {1.0, 1.0, 1.0, 1.0};

glFogi 
(GL_FOG_MODE
, GL_EXP
);
glFogfv 
(GL_FOG_COLOR
, fogColor
);
glFogf 
(GL_FOG_DENSITY
, 0.5);
效果如下:
image
因为雾的颜色为白色,第3个红球基本上已经全白了。。。。大家可以调整上述代码中的参数以获取不同的效果。
比如说,偏蓝色的雾:
glEnable
(GL_FOG
);
GLfloat fogColor
[4] = {0.0, 0.0, 0.5, 1.0};

glFogi 
(GL_FOG_MODE
, GL_EXP
);
glFogfv 
(GL_FOG_COLOR
, fogColor
);
glFogf 
(GL_FOG_DENSITY
, 0.5);

image

为节省篇幅仅贴出关键片段,完整源代码见我博客源代码的2009-11-12/glFogSample/ 目录,获取方式见文章最后关于获取博客完整源代码的说明。

主要函数其实也就一个glFog*,但是参数那是相当的多啊,留待大家自己尝试了。

OpenGL Reference Manual 》:

glFog — specify fog parameters
C Specification
void glFogf( GLenum pname,
GLfloat param);
void glFogi( GLenum pname,
GLint param);
Parameters

pname

Specifies a single-valued fog parameter.
GL_FOG_MODE,
GL_FOG_DENSITY,
GL_FOG_START,
GL_FOG_END,
GL_FOG_INDEX, and
GL_FOG_COORD_SRC
are accepted.
param

Specifies the value that pname will be set to.

C Specification
void glFogfv( GLenum pname,
const GLfloat * params);
void glFogiv( GLenum pname,
const GLint * params);
Parameters

pname

Specifies a fog parameter.
GL_FOG_MODE,
GL_FOG_DENSITY,
GL_FOG_START,
GL_FOG_END,
GL_FOG_INDEX,
GL_FOG_COLOR, and
GL_FOG_COORD_SRC
are accepted.
params

Specifies the value or values to be assigned to pname.
GL_FOG_COLOR requires an array of four values.
All other parameters accept an array containing only a single value.

Description

Fog is initially disabled.
While enabled, fog affects rasterized geometry,
bitmaps, and pixel blocks, but not buffer clear operations. To enable
and disable fog, call glEnable and glDisable with argument
GL_FOG.

glFog assigns the value or values in params to the fog parameter
specified by pname.
The following values are accepted for pname:

GL_FOG_MODE

params is a single integer or floating-point value that specifies
the equation to be used to compute the fog blend factor,
f.
Three symbolic constants are accepted:
GL_LINEAR,
GL_EXP,
and GL_EXP2.
The equations corresponding to these symbolic constants are defined below.
The initial fog mode is GL_EXP.
GL_FOG_DENSITY

params is a single integer or floating-point value that specifies
density,
the fog density used in both exponential fog equations.
Only nonnegative densities are accepted.
The initial fog density is 1.
GL_FOG_START

params is a single integer or floating-point value that specifies
start,
the near distance used in the linear fog equation.
The initial near distance is 0.
GL_FOG_END

params is a single integer or floating-point value that specifies
end,
the far distance used in the linear fog equation.
The initial far distance is 1.
GL_FOG_INDEX

params is a single integer or floating-point value that specifies
i
f
,
the fog color index.
The initial fog index is 0.
GL_FOG_COLOR

params contains four integer or floating-point values that specify
C
f
,
the fog color.
Integer values are mapped linearly such that the most positive representable
value maps to 1.0,
and the most negative representable value maps to
-1.0
.
Floating-point values are mapped directly.
After conversion,
all color components are clamped to the range
0
1
.
The initial fog color is (0, 0, 0, 0).
GL_FOG_COORD_SRC

params contains either of the following symbolic constants:
GL_FOG_COORD or GL_FRAGMENT_DEPTH. GL_FOG_COORD
specifies that the current fog coordinate should be used as distance value
in the fog color computation. GL_FRAGMENT_DEPTH specifies that the
current fragment depth should be used as distance value in the fog
computation.

本系列其他文章见OpenGL专题 《Win32 OpenGL系列专题

参考资料

1. 《OpenGL Reference Manual 》,OpenGL参考手册

2. 《OpenGL 编程指南》(《OpenGL Programming Guide 》),Dave Shreiner,Mason Woo,Jackie Neider,Tom Davis 著,徐波译,机械工业出版社

3. 《Nehe OpenGL Tutorials》,Nehe著,在http://nehe.gamedev.net/ 上可以找到教程及相关的代码下载,(有PDF版本教程下载)Nehe自己还做了一个面向对象的框架,作为演示程序来说,这样的框架非常合适。也有中文版 ,各取所需吧。

4. 《OpenGL入门学习》 ,eastcowboy著,这是我在网上找到的一个比较好的教程,较为完善,而且非常通俗。这是第一篇的地址:http://bbs.pfan.cn/post-184355.html

完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

分享到:
评论

相关推荐

    win32 opengl的例子

    这个"win32 OpenGL的例子"提供了一组基于Win32 API编写的示例,帮助开发者了解如何在Windows环境下使用OpenGL 1.0进行图形渲染。Win32 API是Windows操作系统的核心组件,它提供了丰富的功能,包括窗口管理、事件处理...

    OpenGL Win32 OpenGL Win32 OpenGL Win32

    当我们谈论“OpenGL Win32”,我们实际上是在讨论如何在Windows平台上利用OpenGL进行图形编程。 OpenGL是一种跨语言、跨平台的编程接口,用于渲染2D、3D矢量图形。它由Khronos Group维护,该组织负责更新和扩展标准...

    WIN32 opengl缩放图形

    "WIN32 OpenGL 缩放图形"这个主题涉及到如何在Win32应用程序中使用OpenGL来改变图形的大小,实现缩放效果。 在OpenGL中,缩放通常是通过矩阵变换来实现的。在3D空间中,图形由顶点定义,而顶点的位置可以通过将它们...

    OpenGL Win32 AppWizard

    OpenGL Win32 AppWizard 是一个专门针对Visual C++(VC)环境设计的工具,它为开发者提供了一种...通过阅读和实践,你可以快速掌握OpenGL编程的基础,并逐步提升到更高级的主题,如光照、纹理、深度测试和着色器等。

    win32 opengl画线

    "win32 opengl画线"这个主题涉及到了在Microsoft Windows环境下,利用OpenGL库来创建和显示简单的线条。OpenGL是一个跨语言、跨平台的编程接口,用于生成2D和3D图像。在Visual Studio 2012这样的IDE中,我们可以配置...

    在Win32程序中应用OpenGL进行多窗口显示

    在Win32程序中应用OpenGL进行多窗口显示是一项复杂但有趣的任务,这涉及到Windows API的深入理解和OpenGL图形库的熟练运用。在这个过程中,开发者需要创建多个窗口,每个窗口都独立地渲染OpenGL图形,并且可能还需要...

    一个纯净的WIN32+OPENGL框架

    2. **OpenGL上下文**:理解OpenGL上下文是如何在Win32窗口中创建的,以及如何设置其属性,如颜色深度、深度测试等。 3. **OpenGL版本和扩展**:可能涉及到选择合适的OpenGL版本,以及如何检测和使用扩展函数。 4. **...

    Platform SDK( OpenGL Win32 WinUI)

    OpenGL的主要特性包括顶点处理、纹理映射、着色器、帧缓冲对象、深度和模板测试等。通过OpenGL SDK,开发者可以获得头文件、库文件以及示例代码,帮助他们理解和使用OpenGL函数。 Win32 API(Application ...

    Opengl编程指南8学习使用的环境

    OpenGL编程指南第8版的学习环境搭建是初学者进入图形学领域的关键步骤。OpenGL是一个跨语言、跨平台的编程接口,用于渲染2D、3D矢量图形。在本指南中,我们将专注于使用Visual Studio 2013作为开发环境来实践OpenGL...

    基于 WIN32 和 OPENGL 的五子棋的简单实现

    在本文中,我们将深入探讨如何基于WIN32 API和OpenGL技术实现一个简单的五子棋游戏。五子棋,又称连珠,是一种双人...而对于有经验的开发者来说,这个项目也可以作为进一步研究WIN32 API和OpenGL深度集成的一个起点。

    3D赛车游戏源码_OpenGL_Win32

    【3D赛车游戏源码】基于OpenGL和Win32 API的3D赛车游戏是一个学习图形编程和游戏开发的宝贵资源。对于初学者来说,通过分析和理解这些源代码,可以深入掌握3D图形渲染和游戏逻辑的核心概念。 1. **OpenGL**:OpenGL...

    一个简单的Opengl测试程序代码,VC++源码

    这个“一个简单的Opengl测试程序代码,VC++源码”提供了一个基础的教程,适合那些刚开始学习OpenGL编程的开发者。让我们深入了解一下OpenGL编程的核心概念以及如何在VC++环境下设置和运行OpenGL程序。 首先,OpenGL...

    opengl 界面编程的例子(很好的资料)

    8. **深度测试**:为了避免物体在视觉上重叠,OpenGL提供了深度测试功能,根据物体距离摄像头的远近来决定哪个物体应该在前面。 9. **缓冲交换**:OpenGL使用双缓冲技术来避免闪烁,当一帧渲染完成时,会交换前后两...

    JAVA JOGL OPENGL 编程基础实例

    1. **窗口系统绑定**:JOGL需要与特定的操作系统窗口系统集成,如Windows的Win32,Mac OS X的Cocoa,或Linux的GLX。这使得OpenGL上下文可以在Java应用程序中创建和管理。 2. **GLProfile**:这是JOGL中的一个类,...

    OpenGL库文件工具包(opengl32.lib glu32.lib glaux.lib glew32.lib)

    这个工具包包含了四个重要的库文件:opengl32.lib、glu32.lib、glaux.lib和glew32.lib,它们各自在OpenGL编程中扮演着关键角色。 1. **opengl32.lib**:这是OpenGL的主要库文件,提供了与硬件交互的基本接口,允许...

    用Visual C++ 6实现OpenGL编程.rar_opengl

    本教程的"用Visual C++ 6实现OpenGL编程"很可能是包含了示例代码和说明文档,帮助学习者逐步理解并实践OpenGL编程。"www.pudn.com.txt"可能是一个网址或者注释,指向更多资源或作者的网站。 总之,学习OpenGL编程...

    用vc实现opengl编程

    1. **创建新项目**:在Visual Studio中,选择“新建项目”-> “Win32控制台应用程序”。在向导中,选择“空项目”,确保选中“附加选项”下的“生成解决方案配置”和“生成调试信息”。 2. **添加库依赖**:在项目...

    VC中OpenGL编程实现虚拟现实

    OpenGL是计算机图形学中...总的来说,在VC中使用OpenGL编程实现虚拟现实涉及设置开发环境、创建OpenGL窗口、定义渲染逻辑、处理用户输入以及应用高级图形技术。通过不断实践和学习,你将能够创建出引人入胜的虚拟世界。

    opengl es pc dgles win

    总的来说,OpenGL ES PC dgles win 是关于在Windows环境下模拟和开发OpenGL ES应用的技术,对于移动平台的图形编程和跨平台开发具有重要意义。通过使用类似dgles的工具,开发者可以更加方便地进行OpenGL ES应用的...

    glWinSimple_Opengl编程例子_opengl三维_

    OpenGL编程例子——glWinSimple在Microsoft VC++环境中的应用 OpenGL是一种广泛应用的图形库,它为程序员提供了在各种操作系统和硬件平台上的二维和三维图形渲染功能。本篇将深入探讨如何在Microsoft Visual C++...

Global site tag (gtag.js) - Google Analytics