OpenGL 半透明效果的实现(混合)、雾效果 和 圆滑(抗锯齿)

时间:2022-09-21 19:07:04

在前面的glColor总是忽略最后一个参数alpha,今天就来学习下这个参数的使用
在早上的光照球体的例子基础上进行演示,早上的例子是在白色的地面上有几个彩色的球体和一个类似于玉镯子的模型,利用半透明效果来模拟具有反射性质的地面,也就是说在地面上可以看到以上各个模型的倒影。
首先要启用融合效果glEnable(GL_BLEND),这会对颜色缓冲区产生影响,在未启用融合效果时,新的颜色会用某种算法(未启用深度测试时,新的颜色简单地覆盖原有的颜色缓冲区已经存在的值;开启深度测试时,新的颜色只有在被认定比原来的颜色更接近于临近的裁剪平面才会替换原来的颜色值)对颜色缓冲区的颜色进行替换,而启用融合效果后,新的颜色会以程序员指定的方式与颜色缓冲区的颜色进行组合,这样就可以产生半透明的效果
打开融合效果后,现在需要指定颜色的混合方式,是通过这个函数来指定的glBlendFunc(GLenum S,GLenum D);参数都是枚举值,需要的时候到网上去搜,今天用一个常见的混合方式glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);实现半透明的倒影的代码如下:

glPushMatrix();
glEnable(GL_BLEND);//启用融合效果
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//设置融合方式

glColor4f(1.0f,1.0f,0.0f,0.4f); //颜色,最后一个参数是alpha值,0.4有透明效果
glTranslatef(30.0f,-20.0f,-50.0f);
glutSolidSphere(5.0f,40,40);

glTranslatef(-30.0f,0.0f,0.0f);
glColor4f(1.0f,0.0f,0.0f,0.4f);
glutSolidSphere(3.5f,40,40);
glColor4f(0.0f,0.95f,0.24f,0.4f);
glRotatef(angle_x++,0.0f,1.0f,0.0f);
glutSolidTorus(1,8,30,40);
glDisable(GL_BLEND); //关闭融合效果
glPopMatrix();


抗锯齿效果的实现,锯齿总是出现在两中颜色的分界线上,让渲染的模型看起来很不自然,可以通过融合效果,让两种颜色在交界处进行融合来消除这种锯齿效果,因为用到了融合的原理所以在启用抗锯齿功能必须先启用融合,在这个例子中做了演示,效果还是很明显的,对直线进行了抗锯齿操作,屏幕左面的线条经过了抗锯齿功能的处理,右面的线条没有经过任何处理,对比两条线可以很清楚的看到抗锯齿的效果,代码如下:


//演示抗锯齿效果
glEnable(GL_BLEND);//启用融合效果
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//设置融合方式
glTranslatef(0.0f,0.0f,-50.0f);

glBegin(GL_LINES);//屏幕左面的线未用抗锯齿
    glVertex2f(20.0f,0.0f);
    glVertex2f(40.0f,80.0f);
glEnd();

glEnable(GL_POINT_SMOOTH);//对点进行平滑处理
glEnable(GL_LINE_SMOOTH);//对线进行平滑处理

glBegin(GL_LINES);
    glVertex2f(-20.0f,0.0f);
    glVertex2f(-40.0f,80.0f);
glEnd();

glDisable(GL_BLEND);

雾特效
可以使渲染的环境更为真实,远处的物体产生朦胧的效果。
实现的方法比较简单
glEnable(GL_FOG);//打开雾效果
glFogfv(GL_FOG_COLOR,f);//设置雾颜色,f是一个指定颜色的数组float f[4]
glFogf(GL_FOG_START,50.0f);//设置雾从多远开始
glFogf(GL_FOG_END,100.0f);//设置雾从多远结束
glFogi(GL_FOG_MODE,GL_LINEAR);//设置使用哪种雾,共有三中雾化模式
这样雾就设置完毕

下面是效果图

OpenGL 半透明效果的实现(混合)、雾效果 和 圆滑(抗锯齿)

以下是半透明效果  抗锯齿效果和雾化的程序代码:

#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glut.h>

GLfloat position_x = -25.0f;
GLfloat position_y = 25.0f;
GLfloat change_x = 0.1f;
GLfloat change_y = 0.1f;
GLfloat Height = 100.0f;
GLfloat Width = 100.0f;

GLfloat temp = 1.0f ;
void TimeFunction(void)
{
glutPostRedisplay();
glutTimerFunc(33,TimeFunction,1);

}
void RenderScene(void)
{
static GLint angle_x = 0;
static GLint angle_y = 0;
static GLint angle_z = 0;
GLint temp_i,temp_j;
angle_x += 1;
angle_y += 2;
angle_z += 4;
 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 glColor3f(0.0f,0.95f,0.24f);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();


glPushMatrix();
 glTranslatef(0.0f,0.0f,-50.0f);
 glRotatef(angle_x++,0.0f,1.0f,0.0f);
 glutSolidTorus(1,8,30,40);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
glPopMatrix();

glPushMatrix();
 glTranslatef(0.0f,0.0f,-50.0f);
    glPushMatrix();
 glTranslatef(-30.0f,10.0f,-20.0f);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
    glPopMatrix();

    glPushMatrix();
 glTranslatef(-30.0f,25.0f,0.0f);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
    glPopMatrix();

glPopMatrix();
glPushMatrix();
 glColor3f(1.0f,1.0f,0.0f);
 glTranslatef(30.0f,0.0f,-50.0f);
 glutSolidSphere(5.0f,40,40);
glPopMatrix();
 //glutSolidSphere(12.0f,40,40);
 //glutSolidTeapot(12.0f);
//以下是地面的绘制
//底色

glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_TRIANGLE_FAN);
    glVertex3f(-1500.0f,-30.5f,0.0f);
    glVertex3f(-1500.0f,-30.5f,-2500.0f);
    glVertex3f(1500.0f,-30.5f,-2500.0f);
    glVertex3f(1500.0f,-30.5f,0.0f);
glEnd();
//以下是透明绘制
glPushMatrix();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//演示抗锯齿效果
glPushMatrix();
glTranslatef(0.0f,0.0f,-50.0f);
glBegin(GL_LINES);//屏幕左面的线未用抗锯齿
glVertex2f(20.0f,0.0f);
glVertex2f(40.0f,80.0f);
glEnd();
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
//glEnable(GL_POLYGON_SMOOTH);
glBegin(GL_LINES);//屏幕右面的线启用了抗锯齿效果
glVertex2f(-20.0f,0.0f);
glVertex2f(-40.0f,80.0f);
glEnd();
glDisable(GL_POINT_SMOOTH);
glDisable(GL_LINE_SMOOTH);
glPopMatrix();


glColor4f(1.0f,1.0f,0.0f,0.4f);
glTranslatef(30.0f,-20.0f,-50.0f);
glutSolidSphere(5.0f,40,40);


glTranslatef(-30.0f,0.0f,0.0f);
glColor4f(1.0f,0.0f,0.0f,0.4f);
glutSolidSphere(3.5f,40,40);
glColor4f(0.0f,0.95f,0.24f,0.4f);
glRotatef(angle_x++,0.0f,1.0f,0.0f);
glutSolidTorus(1,8,30,40);

glDisable(GL_BLEND);
glPopMatrix();
 glutSwapBuffers();
}
void SetupRC(void)
{
 GLfloat amb[] = {0.4f,0.4f,0.4f,1.0f};
 GLfloat dif[] = {0.6f,0.6f,0.6f,1.0f};
 GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};
 GLfloat pos[] = {-50.0f,50.0f,100.0f,1.0f};
 glClearColor(0.0f,0.0f,0.0f,1.0f);
 glEnable(GL_DEPTH_TEST);
 //glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
 glEnable(GL_LIGHTING);
 glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
 glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);
 glLightfv(GL_LIGHT0,GL_SPECULAR,spe);
 glLightfv(GL_LIGHT0,GL_POSITION,pos);
//glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);
 glEnable(GL_LIGHT0);

 glEnable(GL_COLOR_MATERIAL);
 glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);
 glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);
GLfloat h[] = {0.0f,1.0f,0.0f,1.0f};  
 glEnable(GL_FOG);
 glFogfv(GL_FOG_COLOR,h);
 glFogf(GL_FOG_START,50.0f);
 glFogf(GL_FOG_END,100.0f);
 glFogi(GL_FOG_MODE,GL_LINEAR);
}

void ChangeSize(GLsizei w,GLsizei h)
{
GLfloat aspectRatio;
if(h == 0)
 h = 1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
temp = aspectRatio = (GLfloat)w/(GLfloat)h;
    if(w <= h)
 //glOrtho(-100.0,100.0,-100/aspectRatio,100.0/aspectRatio,0.0,100.0);
 gluPerspective(60,temp,0.1f,1000.0f);
    else
 //glOrtho(-100.0*aspectRatio,100.0*aspectRatio,-100.0,100.0,0.0,100.0);
 gluPerspective(60,temp,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc ,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

glutCreateWindow("Fog Blend");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(33,TimeFunction,1);
SetupRC();
glutMainLoop();

return 0;
}


转自:http://hsw625728.blog.163.com/blog/static/3957072820081151014779/