OpenGL模板缓冲区与模板测试

帧缓冲区有许多缓冲区构成,这些缓冲区大致分为:

  颜色缓冲区:用于绘图的缓冲区,它包含了颜色索引或者RGBA颜色数据。

  深度缓冲区:存储每个像素的深度值,当启动深度测试时,片段像素深度值和深度缓冲区深度值进行比较,决定片段哪些像素点数据可以替换到颜色缓冲区中。

  模板缓冲区:就像使用纸板和喷漆一样精确的混图一样,当启动模板测试时,通过模板测试的片段像素点会被替换到颜色缓冲区中,从而显示出来,未通过的则不会保存到颜色缓冲区中,从而达到了过滤的功能。

  累积缓冲区:累积缓冲区允许你把渲染到颜色缓冲区的值,拷贝到累积缓冲区。在多次拷贝操作到累积缓冲区时,可以用不同方式的把颜色缓冲区内容和当前累积缓冲区的内容进行重复混合

  模板测试

  模板测试只有存在模板缓冲区的情况下进行,模板测试把像素存储在模板缓冲区的点与一个参考值进行比较(glStencilFunc),根据测试结果,对模板缓冲区的值进行响应的修改glStencilOp

  void glStencilFunc (GLenum func, GLint ref, GLuint mask);

  func:GL_NEVER 从来不能通过

  GL_ALWAYS 永远可以通过(默认值)

  GL_LESS 小于参考值可以通过

  GL_LEQUAL 小于或者等于可以通过

  GL_EQUAL 等于通过

  GL_GEQUAL 大于等于通过

  GL_GREATER 大于通过

  GL_NOTEQUAL 不等于通过

  ref: 参考值

  mask:掩码,书上说模板测试只在哪些对应为1的位上进行。(不是很确定具体作用)

  举例:glStencilFunc (GL_LESS, 1.0, 1.0);模板缓冲区对应的像素点的值如果小于1.0,则通过模板测试

  void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);

  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(按位取反)

  未启用模板缓冲区


glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0, 0, -20);

glColor3f(1.0f,1.0f,1.0f);

dRadius = 5.0*(sqrt(2.0)/2.0);

glBegin(GL_LINE_STRIP);

for (dAngel=0;dAngel<380.0;dAngel+=0.1)

{

glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));

dRadius*=1.003;

}

glEnd();

glColor3f(1.0f,0.0f,0.0f);

glRectf(-5,-5,5,5);

初始清除背景填充颜色为蓝色

  以上这部分代码可以用如下3张图表示绘制的过程

  开启模板缓冲区


void init()

{

glClearColor(0,0,1.0,0);

glClearStencil(0);

glClearDepth(1.0f);

glEnable(GL_STENCIL_TEST);

}

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);//1

glLoadIdentity();

glTranslatef(0, 0, -20);

glStencilFunc(GL_NEVER,0x0,0xFF);  //2

glStencilOp(GL_INCR,GL_INCR,GL_INCR);//3

glColor3f(1.0f,1.0f,1.0f);

dRadius = 5.0*(sqrt(2.0)/2.0);

glBegin(GL_LINE_STRIP);

for (dAngel=0;dAngel<380.0;dAngel+=0.1)

{

glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));

dRadius*=1.003;

}

glEnd();

glStencilFunc(GL_NOTEQUAL,0x1,0xFF);  //4

glStencilOp(GL_KEEP,GL_KEEP,KEEP); //5

glColor3f(1.0f,0.0f,0.0f);

glRectf(-5,-5,5,5);

  当执行到1处,3个缓冲区都被清空

  颜色缓冲区:每个像素点颜色都是蓝色

  深度缓冲区:每个像素点深度都是1.0

  模板缓冲区:每个像素点模板值都是0

  执行到2,3处,模板测试条件是从不通过测试,如果不通过测试结果是模板值+1

  接着应用模板测试进行绘制一组点,由于模板测试条件是从不通过测试,所以颜色缓冲器值不会变化,但是绘制的点对应的像素点的模板值变为1,此时

  颜色缓冲区:每个像素点颜色都是蓝色

  深度缓冲区:每个像素点深度都是1.0

  模板缓冲区:点数组对应的模板值是1,其他区域像素点的模板值还是0

  执行到4,5处,模板测试条件是模板值不一定1则通过测试,如果不通过测试结果是模板值+1

  接着应用刚才的模板测试进行绘制一个(-5,-5,5,5)的矩形,在这个矩形区域内,像素点的模板值分为2中,值为1的是上1步的点数组。值为0的是上一步非的点数组像素点。那个根据模板测试条件,模板值为0的像素点通过测试,可以进行替换颜色缓冲区的值(替换成红色),模板值为0的像素点不能通过测试,因此不能改变颜色缓冲区的值

  颜色缓冲区:(-5,-5,5,5)区域内 模板值为0的像素点为红色,其他区域都为蓝色

  深度缓冲区:每个像素点深度都是1.0

  模板缓冲区:点数组对应的模板值是1,其他区域像素点的模板值还是0

模板查询

  可以用glGetInteger函数获取与模板相关的参数值


#include "header.h"

float dRadius =0;

float dAngel;

float aspect=0;

void init()

{

glClearColor(0,0,1.0,0);

glClearStencil(0);

glClearDepth(1.0f);

glEnable(GL_STENCIL_TEST);

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

glLoadIdentity();

glTranslatef(0, 0, -20);

////glStencilFunc(GL_ALWAYS, 0,0x00);

glStencilFunc(GL_NEVER,0x0,0xFF);

glStencilOp(GL_INCR,GL_INCR,GL_INCR);

glColor3f(1.0f,1.0f,1.0f);

dRadius = 5.0*(sqrt(2.0)/2.0);

glBegin(GL_LINE_STRIP);

for (dAngel=0;dAngel<380.0;dAngel+=0.1)

{

glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));

dRadius*=1.003;

}

glEnd();

glStencilFunc(GL_NOTEQUAL,0x1,0xFF);

glStencilOp(GL_INCR,GL_INCR,GL_INCR);//

glColor3f(1.0f,0.0f,0.0f);

glRectf(-5,-5,5,5);

glutSwapBuffers();

}

void reshape(int w, int h)

{

glViewport(0,0,w,h);

aspect = (w*1.0)/h;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(60, aspect, 1, 100);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main(int argc, char** argv)

{

glutInit(&argc, argv);

//glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_STENCIL);

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_STENCIL|GLUT_DEPTH);

glutInitWindowPosition(200,200);

glutInitWindowSize(600,600);

glutCreateWindow("模板缓冲区与模板测试");

glewInit();

init();

glutReshapeFunc(reshape);

glutDisplayFunc(display);

glutMainLoop();

return 0;

}

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-03 04:10:45

OpenGL模板缓冲区与模板测试的相关文章

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始

C++函数模板与类模板实例解析_C 语言

本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程(Generic Programming)是一种编程范式,通过将类型参数化来实现在同一份代码上操作多种数据类型,泛型是一般化并可重复使用的意思.泛型编程最初诞生于C++中,目的是为了实现C++的STL(标准模板库). 模板(template)是泛型编程的基础,一个模板就是一个创建类或函数的蓝图或公式.例如,当使用一个vector这样的泛型类型或者find这样的泛型函数

C++模板之函数模板

模板和C#的泛型很相似! 如下代码 代码 #include <iostream>#include <string>using namespace std; template<typename T>T maxValue(T value1,T value2){if(value1>value2) {return value1; }return value2;} int main(){ cout<<maxValue(1,3)<<endl; cout

PHP原生模板引擎 最简单的模板引擎_php模板

复制代码 代码如下: <?php $a = array( 'a','b','c' ); require 'template/demo.php';//引用模板 ?> 模板文件: 复制代码 代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-

模板函数-函数模板在头文件和main函数中应该怎么写

问题描述 函数模板在头文件和main函数中应该怎么写 第一次写,提示找不到标示符max,求指正 解决方案 即便在外部文件中定义了max,也应该在引用文件中extern声明后再使用 另外你的max.h文件中将你的3到10行代码屏蔽了,改为: #ifndef MAX_H #define MAX_H 解决方案二: main函数究竟应该怎么写?main函数究竟应该怎么写?c++模板类/模板函数的声明与定义应该放在头文件里

WordPress的主题编写中获取头部模板和底部模板_php技巧

get_header()(获取头部)引入主题的头部模板,默认会引入当前主题目录里的 header.php 文件.如果指定了一个名称,则引入当前主题目录的 header-{name}.php 文件,如果需要引入的文件不存在则引入 wp-includes/theme-compat/header.php 文件. 用法 get_header( $name ); 参数 $name (字符串)(可选)要引入的文件的名称,如果指定则引入 header-{$name}.php 文件. 例子 <?php get_

ecshop小京东模板切换到smarty3.13之模板函数,用模板函数替换楼层

ecshop小京东的模板中用到了楼层的概念,看下了模板每个楼层都写了一下,用几个楼层就写了几段,个人感觉这样的有点冗余,不如做个函数,直接循环一下 有两种方法,第一种是:写个函数来实现楼层的显示,第二种是直接做一个模板函数,直接在页面上循环,第一种方法,本人觉得麻烦,就试了第二种,居然成功了 smarty2好像不支持 模板函数,下面提供一个官方的例子, {* 定义函数 *} {function name=menu level=0} <ul class="level{$level}"

什么是网页模板,网页模板有什么用?

什么是网页模板? 用搜索引擎搜索一下"什么是网页模板",搜到的答案让我吃惊,什么人给的答案,太不负责任了!我们来看一下搜到的答案是什么: "网页模板是一个预先设计好的网站.利用它可以进行快速和高品质的http://www.aliyun.com/zixun/aggregation/11117.html">网站开发.只需要添加您的文本和图片,就可以得到一个功能完整的高品质网站." 这个答案是不对的的,或者说误导了一部分刚刚接触网页制作的初学者.被误导者认为只要找到一个网页模板,就可以利用它快速

Blitz templates 最快的PHP模板引擎_php模板

简介:Blitz templates 是一个用C语言开发的快速的PHP模板引擎,它是作为一个PHP的扩展功能.它开始作为一个php_templates更换,但发展到更多的工作.它是基于可扩展的模板控制器(自定义视图类在PHP )和简单的逻辑 .基准测试表明,这是最快的一个PHP的模板引擎,使Web应用程序更接近于一个聪明的MVC 结构模型,最大从您的代码分离出HTML. 这是专为大高负荷的有许多复杂的演示文稿的逻辑的互联网项目. 下图是几个模板的性能测试结果: 示例模板代码:index.html