OPENGL的特殊效果,融合,雾化,反走样(转)

原创 2007年10月08日 11:33:00

1 融合
前面从未接触过透明或半透明的物体,因为我们从未启用过融合处理 所谓融合就是假设在RGBA模式下,源色为(Rs,Gs,Bs,As),目标色为 (Rd,Gd,Bd,Ad),源因子为(Sr,Sg,Sb,Sa),目的因子为(Dr,Dg,Db,Da)
则融合的最终效果为:(Rs*Sr+Rd*Dr,Gs*Sg+Gd*Dg,Bs*Sb+Bd*Db,As*Sa+Ad*Da)
然后再归一。公式挺复杂,不过仔细看看,跟平常的融合倒是定性一致。
关键就是如何设定融合因子(Sr,Sg,Sb,Sa)(Dr,Dg,Db,Da)来实现不同的融合效果
利用函数:
void glBlendFunc(GLenum sfactor,GLenum dfactor);
其中两个参数可以取下面值:

取值 相关因子 计算后融合因子
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)-min(As,1-Ad)

还要利用glEnable(GL_BLEND) glDisable(gl_blend)来启用、关闭融合处理。
////////////////////////////////////////////////
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);


void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

//设置融合效果并启用
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// glDepthFunc(GL_LESS);
// glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
gluOrtho2D(0.0,1.0,0.0,1.0*(GLfloat)h/(GLfloat)w);
else
gluOrtho2D(0.0,1.0*(GLfloat)w/(GLfloat)h,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
}

void CALLBACK display(void)
{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//三个不同颜色和透明度的方块重合,颜色融合的效果
glColor4f(1.0,0.0,0.0,0.7);
glRectf(0.25,0.4,0.75,0.9);

glColor4f(0.0,1.0,0.0,1.0);
glRectf(0.1,0.1,0.6,0.6);

glColor4f(0.0,0.0,1.0,0.3);
glRectf(0.4,0.1,0.9,0.6);

glFlush();

}
void main(void)
{
myinit();

auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
/////////////////////////////////////////////////////////
你可以试试调节参数大小,体会一下个参数的含义。

2 反走样Anti-aliasing
由于计算机以离散点生成图形,生成图形必然与真实景物存在差距,这种差距表现为:直线或光滑曲面的锯齿、花纹失去原有色彩形状、细小物体在画面的消失等。统统叫做走样。反走样可以减少这种情况。粗略设想一下,就是把原来边界的地方锯齿部分用低饱和度的点补上,这样既不影响整体轮廓,又获得较好的平滑效果。反走样前提供“提示”采用函数:

void glHint(GLenum target,GLenum hint);
其中hint可以是:GL_FASTEST 给出最有效的选择
GL_NICEST 给出最高质量的选择
GL_DONT_CARE 没有选择

target 意义

GL_POINT_SMOOTH_HINT 指定点、
GL_LINE_SMOOTH_HINT 线、
GL_POLYGON_SMOOTH_HINT 多边形的采样质量

GL_FOG_HINT 指出雾化计算是按每个象素进行(GL_NICEST)
还是按每个顶点进行(GL_FASTEST)

GL_PERSPECTIVE_CORRECTION_HINT 指定颜色纹理插值的质量
其中GL_PERSPECTIVE_CORRECTION_HINT用以纠正单纯线性插值带来的观察错误。

当然最主要的工作还是glEnable()来完成的。

先给出一个点、线反走样的例子。需要说明的是这个工作最好在RGBA模式下进行,首先利用glEnable()(参数为GL_POINT_SMOOTH GL_LINE_SMOOTH或 GL_POLYGON_SMOOTH)启用反走样。在RGBA模式下启用反走样,必须启用融合处理。
而且最常用的融合因子分别是:GL_SRC_ALPHA(源)和GL_ONE_MINUS_SRC_ALPHA
或GL_ONE(目的)。

比较采用反走样后的结果,可以明显看出多变形直线边界出锯齿得到了平滑。

3 雾化
最后来介绍雾化,雾化不但可以使景物更加真实,而且大大减少计算量,开过F22的玩家不会忘记雾化的远近直接影响游戏的速度吧。一般的雾化模型是考虑把物体实际颜色和雾化颜色向融合。具体雾化的浓淡有定义的数学模型来决定包括线性变化、指数变化和指数平方变化等。定义雾化也很简单,只要遵循下面步骤:
一 启用雾化 glEnable(GL_FOG);
二 控制雾化 glFog*()
void glFog{if}[v](GLenum,TYPE param);

当GLenum是GL_FOG MODE时,param可以是GL_EXP(指数)
GL_EXP2(指数平方)
GL_LINEAR(线性)

当GLenum是GL_FOG_DENSITY GL_FOG_START GL_FOG_END时,param分别指定不同
雾化数学模型下不同计算公式的参量,具体可以参阅连机手册。

当GLenum时GL_FOG_COLOR时,param是指向颜色向量的指针
三 必要时可以用glHint(GL_FOG_HINT,XX)指定雾化效果
下面给出例子:
///////////////////////////////////////////////////////////////////
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);


void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

GLfloat mat_ambient[]={0.0,0.1,0.8,1.0};
GLfloat mat_diffuse[]={0.0,0.3,0.6,1.0};
GLfloat mat_specular[]={1.0,0.0,1.0,1.0};
GLfloat mat_shininess[]={15.0};
GLfloat position[]={5.0,5.0,5.0,0.0};
GLfloat fogColor[4]={0.6,0.6,0.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);
glLightfv(GL_LIGHT0,GL_POSITION,position);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glFrontFace(GL_CW);
// glEnable(GL_POLYGON_SMOOTH);
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA,GL_ONE);

glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);

//启用雾化处理
glEnable(GL_FOG);
{
//采用线性变化的雾化效果
glFogi(GL_FOG_MODE,GL_LINEAR);
//指定雾化颜色(黄色)
glFogfv(GL_FOG_COLOR,fogColor);
//指定按线性变化时计算公式的参量
glFogf(GL_FOG_START,3.0);
glFogf(GL_FOG_END,15.0);
//规定雾化效果的质量
glHint(GL_FOG_HINT,GL_DONT_CARE);
}
// glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{

glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if(w<=h*3)
glOrtho(-6.0,6.0,-2.0*(GLfloat)h*3/(GLfloat)w,
2.0*(GLfloat)h*3/(GLfloat)w,0.0,10.0);
else
glOrtho(-6.0*(GLfloat)h/(GLfloat)w,
6.0*(GLfloat)h/(GLfloat)w,-2.0,2.0,0.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}


void CALLBACK display(void)
{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//在不同远近(Z方向)绘制同样大小、颜色的环,显示雾化的效果
glPushMatrix();
glTranslatef(-3.0,-1.5,-3.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glPushMatrix();
glTranslatef(-0.5,-0.5,-6.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glPushMatrix();
glTranslatef(2.0,0.5,-8.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glFlush();


}
void main(void)
{
myinit();

auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
////////////////////////////////////////////////////////////////////

OpenGL: 雾化效果

#include #pragma comment(lib, "glut32.lib") #define MODE_NONE 0 #define MODE_LINEAR 1 #define MODE...
  • Augusdi
  • Augusdi
  • 2014-03-04 23:38:14
  • 4011

openGL之雾效果---openGL学习笔记(十二)

雾效果:使所绘制物体距离观察者越远越看的不清晰。     步骤:首先启用雾,然后设置雾颜色,再指定从多远开始到多远结束,最后指定使用哪种雾方程式。   注:指定雾开始结束只针对线性雾的方程式...
  • a358333644
  • a358333644
  • 2016-03-15 17:39:19
  • 1334

OpenGL如何实现雾化效果

作为一个OpenGL新手,我今天就跟大家分享一下我学习
  • u012706792
  • u012706792
  • 2014-09-07 19:16:54
  • 1315

学习OpenGL(八)混色和雾化

在本文将ji
  • kezunhai
  • kezunhai
  • 2014-08-16 12:25:27
  • 1295

OpenGL ES 雾化效果

  • 2011年10月08日 12:59
  • 14KB
  • 下载

[OpenGL] 雪景火焰特效demo

很久之前的代码了,项目用的是vs2013,编译器套件可以在项目属性中修改。          代码地址:点击打开链接 模型导入   此处使用了开源代码。 自己...
  • ZJU_fish1996
  • ZJU_fish1996
  • 2017-05-20 13:27:27
  • 2049

OpenGL ES入门09-GLSL实现常见特效

本文转自简书,原文地址http://www.jianshu.com/p/e4a8c83cd373 前言 本文是关于OpenGL ES的系统性学习过程,记录了自己在学习OpenGL ES时的...
  • qq_30513483
  • qq_30513483
  • 2017-03-03 17:28:00
  • 1057

openGL ES进阶教程(六)美颜滤镜之美白,磨皮,红润

网上搜罗了一堆的美颜滤镜效果,可惜尽不如人意。最后偶然看到ios上提供了一个用OC写的美颜滤镜,好吧,改写成Java的试试。好在大学时期搞过一段时间IOS开发,用自己的半吊子的水平,没想到还真改成功了...
  • King1425
  • King1425
  • 2017-09-01 20:17:12
  • 3066

openGL特效动画集合

  • 2017年07月02日 14:52
  • 2.96MB
  • 下载

使用OpenGL实现遮罩效果

本文适合于Cocos2d-X等使用OpenGL API的渲染框架一般实现自定义遮罩效果主要介绍以下几种: 使用Stencil Buffer 使用GL_SCISSOR_TEST(适合矩形区域) 使用Sh...
  • jaryguo
  • jaryguo
  • 2016-09-22 20:32:12
  • 2431
收藏助手
不良信息举报
您举报文章:OPENGL的特殊效果,融合,雾化,反走样(转)
举报原因:
原因补充:

(最多只允许输入30个字)