读书人

OpenGL上实现Alpha混合

发布时间: 2012-12-19 14:13:15 作者: rapoo

OpenGL下实现Alpha混合

OpenGL下实现Alpha混合

有很久都没有使用OpenGL了。一直都只是看书,一旦实践起来就会发现比想象起来困难得多。不过我还是实现了OpenGL下面一个小小的效果:Alpha混合。

以前在DirectX上做过,所以赶紧回去看了看自己以前写的文章。果然像一些高手说得一样,Direct3D和OpenGL其实是相通的。像Direct3D中要实现此功能要这么写:

m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

在OpenGL中则是这么写:

glEnable( GL_BLEND );glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

此外曾经令我头疼的还有如果使用glEnable(GL_TEXTURE_2D);开启了纹理贴图,那么没有贴图的所有几何图形都是黑色的,哪些glColor()相关的函数全都失效。所以在渲染的时候要善于关闭纹理贴图,这样glColor才能起到作用。

在glTexEnvi()函数中,可以传值设置不同的混合模式。比如说这样:

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

意思是用纹理的颜色替换顶点的颜色,此外还可以设置GL_MODULATE,即调制模式,其实就是将纹理的颜色和顶点的颜色进行叠加。还有GL_DECAL,在纹理图不具有Alpha成分的时候是和GL_REPLACE是一样的。这些就是我编程以来学到的。

此外我还学习到了选择模式渲染,通过glRenderMode(GL_SELECT );设置。这些知识可能要一个新的日志来描述了。好了,将自己的成果分享一下,下面有一张图片链接,点击下载我的程序。

OpenGL上实现Alpha混合

演示程序可以在Windows下和Linux下运行,下面是截图:


OpenGL上实现Alpha混合

OpenGL上实现Alpha混合

下面我说一说怎样操作吧。

[w][s][a][d]键:控制最中间的方块移动。

[F1~F5]键:设置背景颜色,其中F2~F5的背景颜色可以掩盖一个方块。

[Esc]键:退出。


Windows下可能出现的错误:

1、无法定位程序输入点-except-handler4-commom于动态链接库msvcrt.dll上。

这种错误是由于新版msvcrt.dll含有异常处理机制,而老的msvcrt.dll没有。你可能需要更换一个msvcrt.dll,试试可以运行程序的计算机,找到Windows/system32/msvcrt.dll,复制粘贴到无法运行程序的计算机的相同位置即可。

2、无法找到glu32.dll、opengl32.dll,同上所述,将响应的动态链接库复制到对应的位置即可。

Linux下可能出现的错误:

1、没有为可执行文件 文件类型安装应用程序。

权限问题,将可执行属性加上。

2、如果找不到相关的动态库,需要安装。具体问题可以到http://blog.csdn.net/jiangcaiyang123上向我留言。

如果你发现程序中的方块运动过快或者过慢,那么请自行编译程序并且更改相关数据。程序在Windows使用minGW编译。我的开发环境是:

Windows:Windows8+QtCreator2.6+QtSDK4.8.4+minGW4.4.1。

Linux:Ubuntu11.10+QtCreator2.4+QtSDK4.8.1+gcc4.4

2楼goteet昨天 14:17
如果是OpenGL和DirectX都要用的话,可以尝试抽象接口嘛。nnenum KEY{n RS_BLEND, RS_BLEND_FUNCn}nenum Value{n RS_BLEND_ON, RS_BLEND_OFF, n RS_BELND_SRC, RS_BELND_ONE_MINUS_SRCn}nIDevice{n virutal SetRenderState(key, value) = 0;n}nnDevD3D : public IDevice{n SetRenderState(){n m_DevD3D->SetRenderState( RSToD3Dxx(key), RSToD3Dxx2(value);n }n}nnnDevGL : IDevice{n SetRenderState{n if(RSIsSwitch)glBegin(RSToGLxxxxx(key));//glDisablen else glxxxxx(toGLasdf(key), toGL123(value));n}nenum SYS{n OpenGL, D3D,n}nIDevice* CreateDevice( system i){n switch(i)n {n case return new DevGL;n case return new DevD3D;n }n}
1楼jiangcaiyang123昨天 13:33
回复goteetn谢谢。我也是新学OpenGL的,还没有怎么考虑统一接口的问题。n目前我觉得Direct3D的风格沿袭了微软的COM,而OpenGL则是开创了一种编码风格,现在被OpenAL等库沿袭着。n我明年再接触一些游戏引擎,看看它们是如何统一渲染器的。
Re: goteet昨天 13:40
回复jiangcaiyang123n这还不是渲染器啦,这个是只是渲染设备的抽象,渲染器还涉及到 render queue, mesh, material 之类的抽象。不是同一级别的,我也在看别人的代码学习,所以现在水平也不能和你探讨太多。不过设备接口可以考虑抽象一下。
Re: jiangcaiyang123昨天 13:42
回复goteetn不过你刚才的代码是什么语言?不像是C++?能告诉我好吗?
Re: goteet昨天 13:46
回复jiangcaiyang123n伪代码,你可以在c++下用纯虚基类来完成这个工作啊

读书人网 >编程

热点推荐