1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > OpenGL-剪裁测试-alpha测试-模板测试-深度测试

OpenGL-剪裁测试-alpha测试-模板测试-深度测试

时间:2018-11-04 12:39:13

相关推荐

OpenGL-剪裁测试-alpha测试-模板测试-深度测试

片测试:就是测试每一个像素,只有通过测试的像素才会被绘制。没有通过则不能绘制。如果使用了深度测试,OpenGL会记录这个像素的深度(景深),如果有新的像素即将覆盖原来的像素时,深度测试会检查更新新的深度时否会比原来的深度值小。如果是,则覆盖像素,绘制成功,如果不是,则不会覆盖原来的像素,绘制被取消。

1. 剪裁测试

剪裁测试用于绘制区域,我们可以指定一个矩形剪裁窗口,当启用剪裁测试后,只有在这个窗口之内的像素才能被绘制,其他像素会被丢弃。剪裁窗口以外的像素将不会被修改。启用剪裁测试glEnable(GL_SCISSOR_TEST);禁用剪裁测试glDisable(GL_SCISSOR_TEST);指定剪裁窗口glScissor(x,y,width,height); // 位置(x,y) 宽度为 width, 高度为 height 的窗口注意 OpenGL 窗口坐标左下角 为(0,0), 右上角为(width,height)的,这与Windows 系统窗口有所不同。

2. alpha 测试

alpha 可以用于混合操作,也可以用于alpha 测试。如果启动了alpha 测试,OpenGL 会检查alpha值,只有alpha 值满足条件的像素才会进行绘制。(这个条件可以使: 始终通过(默认情况),始终不通过,大于设定值则通过,小于设定值则通过,等于设定值通过,大于等于设定值则通过,小于等于设定值则通过、不等于设定值则通过)启用alpha 测试glEnable(GL_ALPHA_TEST)禁用alpha 测试glDisable(GL_ALPHA_TEST)设置alpha 测试条件为 大于 0.5 则通过glAlphaFunc(GL_GREATER,0.5f);该函数的第二个参数表示设定值,用于进行比较。第一个参数是比较方式GL_LESS 小于则通过GL_ALWAYS 始终通过GL_NEVER 始终不通过GL_LESS 小于则通过GL_LEQUAL 小于等于则通过GL_EQUAL 等于则通过GL_GEQUAL 大于等于则通过GL_NOTEQUAL 不等于则通过

相框那副图片中,所有需要透明的位置都是白色,所以在程序中设置所

有白色的像素为 alpha 值为0.0,设置其他像素 alpha 为1.0,然后设置

alpha 测试的条件 为 大于 0.5 则通过

void texture_colorkey(GLubyte r,GLubyte g,GLubyte b,GLubyte absolute){/*将当前纹理BGR格式转换为BGRA 格式纹理中像素RGB 值如果与指定 rgb 相差不超过 absolute,则将 alpha 设置为 0.0,否则设置 为1.0*/GLint width, height;GLubyte* pixels = 0;// 获取纹理的大小信息glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);// 分配空间并获得纹理像素pixels = (GLubyte*)malloc(width * height * 4);if(pixels == 0){return ;}glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,pixels);// 修改像素中的 alpha 值// 其中 pixels[i * 4],pixels[ i * 4 + 1],pixels[i * 4 + 2],pixels[i * 4 + 3] 分别表示 第i个像素的蓝、绿、红、alpha四种分量,0 表示最小,255 表示最大{GLint i;GLint count = width * height;{if(abs(pixels[i * 4] - b) <= absolute && abs(pixels[i * 4 + 1] -g) <= absolute && abs(pixels[i * 4 + 2] - r) <= absolute){pixels[i * 4 + 3] = 0;}else{pixels[i * 4 + 3] = 255;}}}// 将修改后的像素重新设置到纹理中,释放内存glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,pixels);free(pixels);}void display(void){/*先绘制相片的纹理,在绘制相框的纹理*/static int initialized = 0;static GLuint texWindow = 0;static GLuint texPicture = 0;// 初始化操作,包括 读取相片,读取相框,相框由BGR 颜色转换为BGRA,启用二维纹理if( !initialized ){texPicture = load_textture("pic.bmp");texWindow = load_texture("window.bmp");glBindTexture(GL_TEXTURE_2D,texWindow);texture_colorkey(255,255,255,10);glEnable(GL_TEXTURE_2D);initialized = 1;}// 清屏glClear(GL_COLOR_BUFFER_BIT);// 绘制相片,此时不需要进行,alpha 测试,所有的像素都进行绘制glBindTexture(GL_TEXTURE_2D,texPicture);glDisable(GL_ALPHA_TEST);glBegin(GL_QUADS);glTexCoord2f(0,0);glVertex2f(-1.0f,-1.0f);glTexCoord2f(0,1);glVertex2f(-1.0f,1.0f);glTexCoord2f(1,1);glVertex2f(1.0f,1.0f);glTexCoord2f(1,0);glVertex2f(1.0f,-1.0f);glEnd();// 绘制相框,此时 进行alpha测试,只绘制不透明部分像素glBindTexture(GL_TEXTURE_2D,texWindow);glEnable(GL_ALPHA_TEST);glAlphaFunc(GL_GREATER,0,5f);glBegin(GL_QUADS);glTexCoord2f(0,0); glVertex2f(-1.0f,-1.0f);glTexCoord2f(0,1); glVertex2f(-1.0f,1.0f);glTexCoord2f(1,1); glVertex2f(1.0f,1.0f);glTexCoord2f(1,0); glVertex2f(1.0f,-1.0f);glEnd();// 交换缓冲区glutSwapBuffers();}/*load_texture 函数参考上一节内容,main 函数也参考上一节*/

3. 模板测试

模板测试需要一个模板缓冲区,缓冲区是在初始化OpenGL时候指定的,如果使用GLUT工具包,可以在调用glutinitDisplayMode 函数时在参数加上 GLUT_STENCIL例如:glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_STENCIL);为了保证程序的通用性,最好明确指定使用模板缓冲区。如果确实没有分配模板缓冲区,则所有进行模板测试的像素全部会通过测试。启用 模板测试glEnable(GL_STENCIL_TEST);禁用模板测试glDisable(GL_STENCIL_TEST);OpenGL在模板缓冲区中为每一个像素保存了一个模板值,当像素需要进行模板测试时候,将设定的模板参考值与该像素的 模板值 进行比较, 符合条件的通过车测试,不符合条件的则被丢弃,不进行绘制。模板测试则是用整数来进行比较,八种情况:始终通过、始终不通过、大于则通过、小于则通过、大于等于则通过、小于等于则通过、等于则通过、不等于则通过。glStencilFunc(GL_LESS,3,mask);上述代码表示 模板测试条件为:小于3则通过。glStenciFunc 的前两个参数意义与glAlphaFunc的两个参数类似,第三个参数含义为:如果比较,只比较mask中二进制为1的位。glClear 函数可以将所有像素的模板值复位。例如:glClear(GL_STENCIL_BUFFER_BIT);可以同时复位颜色值和模板值:glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);glClearColor 函数来指定清空屏幕后的颜色,也可以使用glClearStencil 函数来指定复位后的 模板值。每个像素的 模板值 会根据模板测试的结果和深度测试的结果而进行改变glStencilOp(fail,zfail,zpass);第一个参数表示 模板测试未通过时候该如何变化。第二个参数表示 参数模板测试通过,但深度测试未通过时 该如何变化第三个参数表示 模板测试和深度测试均通过时该如何变化。注意: 如果没有启用模板测试,则认为模板测试总是通过,如果没有启用深度测试,则认为深度测试总是通过变化可以是:GL_KEEP // 不改变,这也是默认值GL_ZERO // 回零GL_REPLACE // 使用测试条件中的设定值来代替当前模板值GL_INCR // 增加1,如果已经是最大值,则保持不变GL_INCR_WRAP // 增加1,但如果已经是最大值,则从零开始GL_DECR // 减少1,但如果已经是零,则保持不变GL_DECR_WRAP // 减少1,但如果已经是零,则重新设置为最大值GL_INVERT // 按位取反新版本的OpenGL中,可以为多边形的正面和背景使用不同的模板测试条件和模板值改变方式,提供glStencilFuncSeparate 函数 和 glStencilOpSeparate 函数 这两个函数分别与 glStencilFunc 和 glStencilOp 类似,只是最前面多了一个参数face,用于指定当前设置的是哪个面。可以选择GL_FRONT,GL_BACK,GL_FRONT_AND_BACK.注意:模板缓冲区与深度缓冲区有一点不同。无论是否启用深度测试,当有像素被绘制时,总会重新设置该像素的深度值(除非设置 glDepthMask(GL_FALSE);)。而模板测试如果不启用,则像素的模板值会保持不变,只有启用模板测试时才有可能修改像素的模板值。

4. 深度测试

深度测试需要深度缓冲区。类似于模板测试需要缓冲区。若使用GLUT 工具包,可以调用 glutInitDisplayMode 函数时在参数加上 GLUT_DEPTH, 这样来明确要求使用深度缓冲区。深度测试和模板测试的原理类似,都在一个缓冲区保存像素的某个值,当需要进行测试时,将保存的值与另一个值进行比较,以确定是否通过测试。区别在于: 模板测试是设定一个值,在测试时用这个设定值与像素的 模板值 进行比较,而深度测试是根据顶点的空间坐标计算深度,用这个深度与像素的 深度值 进行比较。就是说,模板测试需要指定一个值作为比较参考,而深度测试中,这个比较用的参考值是 OpenGL 根据空间坐标自动计算的。启用深度测试glEnable(GL_DEPTH_TEST);禁用深度测试glDisable(GL_DEPTH_TEST);至于通过测试的条件,同样有八种,与 Alpha 测试中的条件设置相同。条件设置是通过 glDepthFunc 函数完成的,默认值是GL_LESS。glDepthFunc(GL_LESS);与模板测试相比,深度测试的应用要频繁得多。几乎所有的三维场景绘制都使用了深度测试

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。