博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenGL学习三十:深度缓冲区与掩码
阅读量:4213 次
发布时间:2019-05-26

本文共 9222 字,大约阅读时间需要 30 分钟。

深度缓冲区进行三维混合

多边形的绘图顺序极大地影响了最终的混合效果。为了应对不同深度的图形显示我们要开启深度缓冲区

glEnable(GL_DEPTH_TEST);
对已开启深度缓冲区的图形来说,如果一个不透明的物理如果举例观察点较近,那么它所遮挡的部分就不会进行绘制
对于存在透明度的图形来说要复杂一些,如果一个透明的物体靠近距离观察点较近。那么它所遮挡的部分也是需要绘制的
对于透明的图形绘制需要设置深度缓冲区的可读性
glDepthMask(GL_TRUE|GL_FALSE)
GL_TRUE:代表深度缓冲区为可读写
GL_FALSE:代表深度缓冲区为只读
对于透明的3D图形绘制需要设置深度缓冲区步骤为:
1.glDepthMask(GL_FALSE)
2.绘制透明图形
3.glDepthMask(GL_TRUE)

 

以下对混合的深度理解

接下来通过实例说明 启用深度缓冲区,设置深度缓冲区掩码,以及三维图形混合的技巧

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  glLoadIdentity();           glEnable(GL_DEPTH_TEST);   //glDisable(GL_DEPTH_TEST);   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);   glBindTexture(GL_TEXTURE_2D, texture[filter]);   glPushMatrix();     glTranslatef(1.2f,0.5f,sphere);     glColor4f(1,1,0,1);     glutSolidSphere (0.8, 32, 32);   glPopMatrix();     glEnable(GL_TEXTURE_2D);   //glEnable(GL_BLEND);   //glDepthMask(GL_FALSE);   glPushMatrix();     glTranslatef(0.0f,0.0f,quadz);     glColor4f(1.0f, 1.0f, 1.0f, 0.5f);         glBegin(GL_QUADS);      .............     glEnd();   glPopMatrix();   //glDepthMask(GL_TRUE);   //glDisable(GL_BLEND);   glDisable(GL_TEXTURE_2D)

通过上面的代码可以看出,这里我先绘制了一个球体,然后绘制了一个立方体,球体的Z值-5,立方体Z值为-6,由此可知球体距离观察点更近一些

1.当启用深度缓冲区时效果见右图1(D键按下)
2.当未启用深度缓冲区时效果见右图2(d键按下)
(黑色加粗字体为是否启用缓冲区的)
对比可知当我们启用深度缓冲区时Z值决定哪个物体在前面,不启用深度缓冲区时,绘画顺序决定前后关系

                           

新添加功能,启用深度缓冲区时当按下A键时 球体Z值-6 立方体Z值-5 ;当按下B键时 球体Z值-5 立方体Z值-6

1.I键按下时:左图1(demo 按键I)
2.i键按下时 右图2(demo 按键i)

                             

新添加功能,启用深度缓冲区(D键按下) 在绘制立方体时启用A混合(B键按下)

1.i键按下左图1,
1.I键按下右图2
分析:此时由于启用深度缓冲区,那么Z直决定了物体先后顺序。同时存在混合,可以看出图2,当立体图具体观察点较近时,由于它是透明的,因此可以看到后面的实心球体,有图1可以看处,当实心球体靠近观察点时,实心后面的部分是看不见的,被遮挡的,同时立方体内部是不透明的

                                

新添加功能,禁用深度缓冲区(d键按下),在绘制立方体是启用A混合(B键按下)

1.i键按下右图1,
1.I键按下右图2
分析,此时由于禁用深度缓冲区,那么绘画顺序决定了物体先后顺序(立方体后画,显示在最前面),可以看出实心球体始终是在后面,前面的立方体整体存在透明度

                             

新添加功能,启用深度缓冲区(D键按下),启用深度缓冲区掩码(M键按下),在绘制立方体是启用A混合(B键按下)

1.i键按下右图1,
1.I键按下右图2
分析:此时由于启用深度缓冲区,那么Z直决定了物体先后顺序,有图1可以看处,当实心球体靠近观察点时,实心后面的部分是看不见的,被遮挡的,同时立方体内部是不透明的, 启动了深度缓冲区掩码因此立方体内部也是可见的。

                            

 

在绘制多个三维图形透明效果是,应把具有A的物体后画,先画实心物体

对于以下等等内容不属于矩阵内容,因此PUSH POP 对此无用,
 glEnable(GL_DEPTH_TEST);
 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
 glBindTexture(GL_TEXTURE_2D, texture[filter]);

 

 

深度缓冲区掩码的理解

glDepthMask();
通过启用深度测试 glEnable(GL_DEPTH_TEST); 可以控制多个物体间先后顺序,如果近观察点的物体是不透的那么它所遮盖的物体也不会绘制。但是假如这俩个物体时立体时,比如是立方体,立方体6个面,是有先后顺序的,如前,后面,假如立方体存在透明度,我们希望的是透过立方体的前面能看到立方体的后面,由于混合式针对物体间,立方体6个面之间不能存在混合,所以我们看到的效果是立方体前面遮盖住了立方体后面(由于启用深度测试,后面Z值在后,因此不会绘画)如果此时我们关闭GL_DEPTH_TEST,就会让立方体的每个面都进行绘画,哪怕他们的Z序是被遮挡的。 glDepthMask();就是解决这个问题,它相当于在立方体之间调用了glEnable/glDisable(GL_DEPTH_TEST),(GL_DEPTH_TEST不能再begin end 之间调用,不起作用) 下面两段代码的作用是一样的

glDisable(GL_DEPTH_TEST); glBegin(GL_QUADS);  glNormal3f( 0.0f, 0.0f, 1.0f);  glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  glEnd();glBegin(GL_QUADS);  // Back Face  glNormal3f( 0.0f, 0.0f,-1.0f);  glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glEnd();glEnable(GL_DEPTH_TEST);

glDepthMask(GL_FALSE); glBegin(GL_QUADS);  glNormal3f( 0.0f, 0.0f, 1.0f);  glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);  glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);  glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);  // Back Face  glNormal3f( 0.0f, 0.0f,-1.0f);  glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);  glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);  glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glEnd(); glDepthMask(GL_TRUE);

深度测试

当我们开启深度测试时,距离观察点远的物体如被遮盖着则不会进行绘画,简单的说,当绘制一个图元,会将它的Z值存储到深度缓冲区,当绘制下一个图元时,源片断的Z值和深度缓冲区的对应的值比较如果小于则不被替换,简单的说就是不会被绘画,这个“小于”的规则是可以更改。比如我们科室设置为”大于“

void glDepthFunc(Glenum func)

func:GL_NEVER 从来不能通过
      GL_ALWAYS 永远可以通过(默认值)
      GL_LESS 小于参考值可以通过
      GL_LEQUAL 小于或者等于可以通过
      GL_EQUAL 等于通过
      GL_GEQUAL 大于等于通过
      GL_GREATER 大于通过
      GL_NOTEQUAL 不等于通过

#include "header.h"bool	light;				bool    blend;				bool	mask;			static int maxZ=-5;static int minZ=-6;int quadz=-6;int sphere=-5;GLuint	texture[1];			LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);	AUX_RGBImageRec *LoadBMP(char *Filename)				{	FILE *File=NULL;										if (!Filename)											{		return NULL;										}	File=fopen(Filename,"r");								if (File)												{		fclose(File);											return auxDIBImageLoad(Filename);					}	return NULL;										}int LoadGLTextures()									{	int Status=FALSE;									AUX_RGBImageRec *TextureImage[1];					memset(TextureImage,0,sizeof(void *)*1);           		if (TextureImage[0]=LoadBMP("Data/glass.bmp"))	{		Status=TRUE;											glGenTextures(1, &texture[0]);						// Create Nearest Filtered Texture		glBindTexture(GL_TEXTURE_2D, texture[0]);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);		glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);	}	if (TextureImage[0])								{		if (TextureImage[0]->data)								{			free(TextureImage[0]->data);						}		free(TextureImage[0]);								}	return Status;									}void ReSizeGLScene(GLsizei width, GLsizei height)		{	if (height==0)											{		height=1;											}	glViewport(0,0,width,height);							glMatrixMode(GL_PROJECTION);							glLoadIdentity();										// Calculate The Aspect Ratio Of The Window	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);	glMatrixMode(GL_MODELVIEW);							glLoadIdentity();								}int InitGL(GLvoid)										{	if (!LoadGLTextures())								{		return FALSE;										}	glShadeModel(GL_SMOOTH);								glClearColor(0.0f,0.0f, 0.0f, 1.0f);			glClearDepth(1.0f);										glEnable(GL_DEPTH_TEST);							glDepthFunc(GL_LEQUAL);									glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);		return TRUE;										}void DrawGLScene(GLvoid)								{	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		glLoadIdentity();										glPushMatrix();	glTranslatef(1.2f,0.5f,sphere);	glColor4f(1,1,0,1);	glutSolidSphere (0.8, 32, 32);	glPopMatrix();	if (blend)	{		glEnable(GL_BLEND);	}	if (mask)	{		glDepthMask(GL_FALSE);	}		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);    glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture[0]);	glPushMatrix();	glColor4f(1.0f, 1.0f, 1.0f, 0.5f);						glTranslatef(0.0f,0.0f,quadz);	glBegin(GL_QUADS);		glNormal3f( 0.0f, 0.0f, 1.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);		// Back Face		glNormal3f( 0.0f, 0.0f,-1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);		// Top Face		glNormal3f( 0.0f, 1.0f, 0.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);		// Bottom Face		glNormal3f( 0.0f,-1.0f, 0.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);		// Right face		glNormal3f( 1.0f, 0.0f, 0.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);		// Left Face		glNormal3f(-1.0f, 0.0f, 0.0f);		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	glEnd();	glPopMatrix();		glDisable(GL_TEXTURE_2D);	if (mask)	{		glDepthMask(GL_TRUE);	}		if (blend)	{	   glDisable(GL_BLEND);	}	glFlush();				}void keyboard (unsigned char key, int x, int y){	switch (key) {	  case 'i':		  sphere=maxZ;		  quadz=minZ;		  break;	  case 'I':		  sphere=minZ;		  quadz=maxZ;		  break;	  case 'd':		  		  glDisable(GL_DEPTH_TEST); 		  break;	  case 'D':		  glEnable(GL_DEPTH_TEST); 		  break;	  case 'B':		 blend=true;		  break;	  case 'b':		 blend=false;		  break;	  case 'M':		  mask=true;		  break;	  case 'm':		  mask=false;		  break;	  	}	glutPostRedisplay();}int main(int argc, char** argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);	glutCreateWindow("深度缓冲区与掩码");	glutReshapeFunc(ReSizeGLScene);	glutDisplayFunc(DrawGLScene);	glutKeyboardFunc(keyboard);	InitGL();	glutMainLoop();	return 0;}

转载地址:http://cfumi.baihongyu.com/

你可能感兴趣的文章
ASM Concepts Quick Overview [ID 1086199.1]
查看>>
PowerDesigner 业务处理模型( BPM ) 说明
查看>>
PowerDesigner 企业架构模型 ( EAM ) 说明
查看>>
PowerDesigner 正向工程 和 逆向工程 说明
查看>>
PowerDesigner 模型文档 说明
查看>>
PowerDesigner 系列 小结
查看>>
Oracle 升级10.2.0.5.4 OPatch 报错Patch 12419392 Optional component(s) missing 解决方法
查看>>
Oracle sessions,processes 和 transactions 参数 关系 说明
查看>>
RMAN 备份报错 RMAN-06207 RMAN-06208 解决方法
查看>>
[INS-35172] Target database memory (XXMB) exceeds the systems available shared memory ({0}MB) 解决方法
查看>>
深入理解 OUI(Oracle Universal Installer)
查看>>
ORA-00600:[32695], [hash aggregation can't be done] 解决方法
查看>>
Oracle SQL中使用正则表达式 执行报ORA-07445 [_intel_fast_memcpy.A()+10] 错误
查看>>
Oracle TABLE ACCESS BY INDEX ROWID 说明
查看>>
ORA-00600 [kmgs_parameter_update_timeout_1], [27072] ORA-27072 解决方法
查看>>
Oracle 11g alert log 新增消息 opiodr aborting process unknown ospid (1951) as a result of ORA-28 说明
查看>>
Linux Context , Interrupts 和 Context Switching 说明
查看>>
《Oracle数据库问题解决方案和故障排除手册》终于发售了
查看>>
Oracle alert log ALTER SYSTEM SET service_names='','SYS$SYS.KUPC$C_...' SCOPE=MEMORY SID='' 说明
查看>>
Oracle latch:library cache 导致 数据库挂起 故障
查看>>