混合、抗锯齿、雾、多边形偏移及显示列表(openGL)

来源:互联网 发布:java基础培训 编辑:程序博客网 时间:2024/05/19 13:55

0.混合

在正常情况下,opengl渲染时会把颜色值输入到颜色缓冲区中,深度值输入到深度缓冲区中。如果我们关闭深度测试,那么新的颜色值会简单的覆盖在旧的颜色值上。当开启深度测试时,颜色段只有在通过深度测试时,才会覆盖已经存在于颜色缓冲区中的值。

混合,当开启混合时,输入的颜色值将会和已经存在于颜色缓冲区中的颜色进行组合。至于如何组合取决于rgba中的alpha。混合时在场景进行了光栅化并转换为像素之后,但是在最终的像素绘制到帧缓冲区之前发生的。混合时诸如透明化、数字合成、油漆这类技巧的核心。

a.源因子和目标因子、源颜色和目标颜色

源颜色:新片段的颜色值S

目标颜色:当前已经存储的对应像素的颜色值D

源因子:vectorS(Sr,Sg,Sb,Sa)

目标因子:vectorD(Dr,Dg,Db,Da)

则最后计算所得为(S*vectorS+D*vectorD)

可以选择两种不同的方式来指定混合因子:glBlendFunc(GLenum S, GLenum D);和glBendFuncSeparate()

下面是glBlendFunc(GLenum S, GLenum D)中S与D的取值表


b.栗子

栗子源于:http://my.oschina.net/sweetdark/blog/169668?fromerr=u57CPqzi

#include"grapg.h"GLfloat lightpos[4]={-100.0f,100.0f,50.0f,1.0f};GLfloat lightposmirror[4]={-100.0f,-100.0f,50.0f,1.0f};GLfloat fnolight[] = { 0.0f, 0.0f, 0.0f, 0.0f };GLfloat flowlight[] = { 0.25f, 0.25f, 0.25f, 1.0f };GLfloat fbrightlight[] = { 1.0f, 1.0f, 1.0f, 1.0f };void drawground(){GLfloat fextent=20.0f;GLfloat fstep=0.5f;GLfloat y=0.0f;bool ibounce=false;glShadeModel(GL_FLAT);for(GLfloat istrip=-fextent;istrip<=fextent;istrip+=fstep){glBegin(GL_TRIANGLE_STRIP);for(GLfloat irun=fextent;irun>=-fextent;irun-=fstep){GLfloat fcolor;if(ibounce){fcolor=1.0f;}else{fcolor=0.0f;}glColor4f(fcolor,fcolor,fcolor,0.5f);glVertex3f(istrip,y,irun);glVertex3f(istrip+fstep,y,irun);ibounce=!ibounce;}glEnd();}}void DrawWorld(){glColor3f(1.0f,1.0f,0.0f);glPushMatrix();glTranslatef(0.0f,0.5f,-3.5f);glutWireTorus(0.25,0.08,68,37);glPopMatrix();}void reshape_blend(int w,int h){if(h == 0)    h = 1;  glViewport(0, 0, w, h);//视口大小设置   glMatrixMode(GL_PROJECTION);//设置投影   glLoadIdentity(); GLfloat faspect = (GLfloat) w / (GLfloat) h;  gluPerspective(35.0f, faspect, 1.0f, 50.0f);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  glTranslatef(0.0f, -0.4f, 0.0f);  glutPostRedisplay();}void setrc_blend(){glClearColor(0.0f,0.0f,0.0f,1.0f);glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);glCullFace(GL_BACK);glFrontFace(GL_CCW);glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT,fnolight);//全局环境光 glLightfv(GL_LIGHT0, GL_AMBIENT, flowlight);glLightfv(GL_LIGHT0,GL_DIFFUSE,fbrightlight);  glLightfv(GL_LIGHT0, GL_SPECULAR, fbrightlight);  glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);//材质属性设置 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);glMateriali(GL_FRONT, GL_SHININESS, 128);}void blend(){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glEnable(GL_DEPTH_TEST);glPushMatrix();glLightfv(GL_LIGHT0,GL_POSITION,lightposmirror);//设置光照位置glPushMatrix();//绘制镜像 glFrontFace(GL_CW);//因为是镜像所以要反着来 glScalef(1.0f,-1.0f,1.0f);DrawWorld();glFrontFace(GL_CCW);glPopMatrix();    glDisable(GL_LIGHTING);//画地面时,关闭光源, 地面可见并均匀着色。    glEnable(GL_BLEND);//打开混合    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//设置混合因子        drawground();//画地面        glDisable(GL_BLEND);//关闭混合效果    glEnable(GL_LIGHTING);  glPopMatrix();  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);//设置光源在左上角  DrawWorld();glutSwapBuffers();}int main_blend(){  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);  glutInitWindowSize(800, 600);  glutCreateWindow("test");  glutDisplayFunc(blend);  glutReshapeFunc(reshape_blend);  setrc_blend();  glutMainLoop();  return 0;}

反向画个相同物体,参上倒影与背景的混合,就成了镜像。


1.抗锯齿/反走样

说白了就是画图过程中边界上会产生锯齿(像素说到底是个有大小的小方块?),

解决方案:

a.利用与背景混合把锯齿磨平。(和平滑是不是一个道理?)

glEnable(GL_LINE_SMOOTH);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//alpha值越大,抗锯齿效果更加明显 

b.多重采样

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_MULTISAMPLE)//打开多重采样缓冲区 GLint buff,samples;glGetIntegerv(GL_SAMPLE_BUFFERS,&buff);//测试多重采样是否可用 glGetIntegerv(GL_SAMPLES,&samples);//buff==1&&samples>1则可以使用 多重采样 glEnable(GL_MULTISAMPLE);//启用多重采样 }

对于多边形而言,多重采样更好。点线都行

2.雾

a.使用雾

glEnable(GL_FOG);//开启雾效果,以下均是用glfog*设置雾的一些属性 glFogfv(GL_FOG_COLOR,flowLight);//设置雾的颜色 glFogf(GL_FOG_START,5.0f);//设置雾开始于结束 glFogf(GL_FOG_END,30.0f);glFogi(GL_FOG_MODE,GL_LINEAR);//设置雾方程 
b.雾方程

c.雾坐标

我们不一定要OpenGL计算雾距离,也可以自己设置雾距离。通过手工调用glFogCoordf:void glFogCoordf(GLfoat fFogDistance);
使用雾坐标的前提是,要调用下面的函数更改雾的来源:glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
打开OpenGl产生的雾值:glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);

3.多边形偏移

glEnable(GL_POLYGON_OFFSET_FILL);//...glDisable(GL_POLYGON_OFFSET_FILL); 

4.显示列表

a.创建

theTorus=glGenLists(1);glNewList(theTorus,GL_COMPILE);torus(8,25);glEndList();
b.使用
glCallList(theTorus);//显示列表
c.功用

提高效率

d.适用

状态变量、绘制都行

5.显示列表和抗锯齿的综合栗子

#include "grapg.h"GLuint theTorus;void torus(int numc,int numt){glColor4f(0.0,1.0,0.0,0.5);glPointSize(30);glBegin(GL_POINTS);glVertex3f(0.0,0.0,0.0);glEnd();for(int i=0;i<numc;i++){glColor4f(0.0,1.0,1.0,0.5);glBegin(GL_QUAD_STRIP);for(int j=0;j<=numt;j++){for(int k=1;k>=0;k--){double s=(i+k)%numc+0.5;double t=j%numt;double x=(1+0.1*cos(s*GL_PI*2/numc))*cos(t*GL_PI*2/numt);double y=(1+0.1*cos(s*GL_PI*2/numc))*sin(t*GL_PI*2/numt);double z=0.1*sin(s*GL_PI*2/numc);glVertex3f(x,y,z);}}glEnd();}}void init_calllist(){theTorus=glGenLists(1);glNewList(theTorus,GL_COMPILE);torus(8,25);glEndList();glShadeModel(GL_FLAT);glClearColor(0.0,0.0,0.0,0.0);//glEnable(GL_MULTISAMPLE);//启用多重采样 glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_POLYGON_SMOOTH);glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);glEnable(GL_POINT_SMOOTH); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);}void calllist(){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,1.0,1.0);glCallList(theTorus);//显示列表 glFlush();}void reshape_calllist(int w,int h){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(30,(GLfloat)w/(GLfloat)h,1.0,100.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0,0,10,0,0,0,0,1,0);}void speciakey_calllist(int key,int x,int y)//处理特殊键按键事件 {if(key==GLUT_KEY_UP){glRotatef(30.0f,1.0f,0.0f,0.0f);}if(key==GLUT_KEY_DOWN){glRotatef(30.0f,0.0f,1.0f,0.0f);}if(key==GLUT_KEY_LEFT){glLoadIdentity();gluLookAt(0,0,10,0,0,0,0,1,0);}glutPostRedisplay();}int main_calllist(){glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_MULTISAMPLE);  glutInitWindowPosition(200, 200);glutInitWindowSize(500, 500);glutCreateWindow("test");init_calllist();  glutSpecialFunc(speciakey_calllist);//和glutKeyboardFunc一起接受键盘事件。glutSpecialFunc处理的几个特殊键的按键事件 glutReshapeFunc(reshape_calllist);glutDisplayFunc(calllist);glutMainLoop();return 0;}
话说抗锯齿,就抗出个这?




0 0
原创粉丝点击