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

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的取值表

混合、抗锯齿、雾、多边形偏移及显示列表(openGL)_第1张图片

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;
}

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

混合、抗锯齿、雾、多边形偏移及显示列表(openGL)_第2张图片

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=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;
}
话说抗锯齿,就抗出个这?

混合、抗锯齿、雾、多边形偏移及显示列表(openGL)_第3张图片混合、抗锯齿、雾、多边形偏移及显示列表(openGL)_第4张图片混合、抗锯齿、雾、多边形偏移及显示列表(openGL)_第5张图片


你可能感兴趣的:(计算机图形学,图像处理,计算机视觉)