当前位置:首页 » 文件管理 » opengl深度缓存

opengl深度缓存

发布时间: 2022-11-05 11:06:47

1. opengl中glreadpixels读取深度缓存的值为啥都是零呀谢谢

WebGL1.0的文档中对于readPixels方法有明确的说明:The data returned from readPixels must be up-to-date as of the most recently sent drawing command.
也就是说该方法必须在渲染完一帧的页面之后立即调用才有效果,否则取不到值,比如这样调用:
gl.viewport(0,0,World.canvas.width,World.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
scene.draw(camera);
var a = new Uint8Array(4);
gl.readPixels(0,0,1,1,gl.RGBA,gl.UNSIGNED_BYTE,a);
console.log(a);
此处一帧的绘制(scene.draw(camera))完全完成之后再读取就可以获取准确值了,你自己可以试一下。

2. OpenGL入门-4

图像存储空间 = 图像的高度 * 图像宽度 * 每个像素的字节数

RGB(8位),宽度:199像素点。图片每行需要多少存储空间?
199 * 3 * 8 = 597字节

tga(纹理文件)。1个字节1个字节。
OpenGL纹理文件:.tga文件.

OpenGL ES! 压缩图片文件.png/jpeg压缩
当纹理来使用。

//改变像素存储方式
void glPixelStorei(GLenum pname, GLint param);
//恢复像素存储方式
void glPixelStoref(GLenum pname,GLfloat param);
//举例:
//参数1:GL_UNPACK_ALTGNMENT 指定OpenGL 如何从数据缓存区中解包图像数据
//参数2:表示参数GL_UNPACK_ALIGNMENT 设置的值

//GL_UNPACK_ALIGNMENT 指内存中每个像素行起点的排列请求,允许设置为1(byte排列)、2(排列为偶数btye的行)、4(字word排列)、8(行从双字节边界开始)
glPixelStorei(GL_UNPACK_ALIGNMENT,1);

参数1:x,矩形左下角的窗口坐标
参数2:y,矩形左下角的窗口坐标
参数3:width,矩形的宽,以像素为单位
参数4:height,矩形的高,以像素为单位
参数5:format,OpenGL的像素格式
参数6:type,解释参数pixels指向的数据,告诉OpenGL 使用缓存区中的什么数据类型来存储颜色分量,像素数据的数据类型。
参数7:pixels,指向图形数据的指针
void glReadPixls(GLint x, GLint y, GLSizei width, GLSizei height, GLenum format, GLenum type, const void *pixels);

glReadBuffer(mode); ->指定读取的缓存
glWriteBuffer(mode); -> 指定写入的缓存

void glTexImage1D(GLenum target,GLint level, GLint internalformat,GLsizei width, GLint border, GLenum format, GLenum type, void *data);

void glTextImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint bordr, GLenum format, GLenum type,void *data);

void glTextImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,GLsizei depth, GLint bordr, GLenum format, GLenum type,void *data);

void glTexSubImage1D(GLenum target, GLint level, GLint xOffset, GLsizei width, GLenum format, GLenum type, const GLvoid *data);

void glTexSubImage2D(GLenum target, GLint level, GLint xOffset,GLint yOffset,GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data);

void glTexSubImage3D(GLenum target, GLint level, GLint xOffset,GLint yOffset,GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *data);

void glCopyTexSubImage1D(GLenum target, GLint level, GLint xOffset, GLint x, GLint y, GLsizei width);

void glCopyTexSubImage2D(GLenum target,GLint level,GLint xOffset, GLint yOffset,GLint x, GLint y,GLsizei width, GLsizei height);

void glCopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width, GLsizei height);

void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformt, GLint x, GLint y, GLsizei width, GLint border);

void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformt, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);

x,y在颜色缓存区中指定了开始读取纹理数据的位置;缓存区里的数据,是源缓存区通过glReadBuffer设置的。

//使用函数分配纹理对象
//指定纹理对象的数量 和 指针(指针指向一个屋符号整形数组,由纹理对象标识符填充)。
void glGenTextures(GLsizei n, GLint *texTures);

//绑定纹理状态
//参数target: GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
//参数texture:需要绑定的纹理对象
void glBindTexture(GLenum target, GLunit texture);

//删除绑定纹理对象
//纹理对象 以及 纹理对象指针(指针指向一个无符号整形数组,由纹理对象标识符填充)。
void glDeleteTexture(GLsizei n, GLint *textures);

//测试纹理对象是否有效
//如果texture是一个已经分配空间的纹理对象。那么这个函数会返回GL_TRUE,否则返回GL_FALSE.
GLboolean glIsTexture(GLuint texture);

glTexParameterf(GLenum target, GLenum pname, GLFloat param);
glTexParameteri(GLenum target, GLenum pname, GLint param);
glTexParameterfv(GLenum target, GLenum pname,GLint param);
glTexParameteriv(GLenum target, GLenum pname, GLint *param);

参数1:target,指定这些参数将要应用在那个纹理模式上,比如GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D。
参数2:pname,指定需要设置那个纹理参数。
参数3:param,设定特定的纹理参数值。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//纹理缩小时,使用邻近过滤

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GLLINEAR)
//纹理放大时,使用线性过滤

参数1:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
参数2:GL_TEXTURE_WRAP_S、GL_TEXTURE_T、GL_TEXTURE_R,针对s,t,r坐标
参数3:GL_REPEAT、GL_CLAMP、GL_CLAMP_TO_EDGE、GL_CLAMP_TO_BORDER
GL_REPEAT:OpenGL在纹理坐标超过1.0的方向上对纹理进行重复;
GL_CLAMP:所需要的纹理单元取自纹理边界或TEXTURE_BORDER_COLOR.
GL_CLAMP_TO_EDGE环绕模式强制对范围之外的纹理坐标沿着合法的纹理单元的最后一行或者最后一列来进行采样。
GL_CLAMP_TO_BORDER:在纹理坐标在0.0到1.0范围之外的只使用边界纹理单元。边界纹理单元是作为围绕基本图像的额外的行和列,并与基本纹理图像一起加载的。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAR_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_T,GL_CLAMP_TO_EDGE);

OpenGL像素格式

像素数据的数据类型

//设置mip贴图基层
glTexParamteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
//设置mip贴图最大层
glTexParamteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_LEVEL,0);

GLint comFlag;
//判断纹理是否被成功压缩
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_COMPRESSED,&comFlag);

//根据选择的压缩纹理格式,选择最快、最优、自行选择的算法方式选择压缩格式
glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST);
glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST);
glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE);

void glCompressedTexImage1D(GLenum target,GLint level,Glenum internalFormat,GLsizei width,GLint border, GLsizei imageSize, void *data);

void glCompressedTexImage2D(GLenum target,GLint level, GLenum internalFormat, GLsizei width, GLint height, GLint border, GLsizei imageSize, void *data);

void glCompressedTextImage3D(GLenum target, Glint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,GLint border, GLsizei imageSize,void *data);

target: GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D.
level:指定所加载的mip贴图层次。一般我们都把这个参数设置为0.
internalformat:每个纹理单元中存储多少颜色成分
width、height、depth参数:指加载纹理底层的宽度、高度、深度。注意:这些值必须是2的整数次方。(这是因为旧版本上遗留下的一个要求。当然现在已经可以支持不是2的整数次方。但是开发者还是习惯使用2的整数次方去设置参数)
border参数:允许为纹理贴图指定一个边界宽度。
format、type、data参数:与我们在讲glDrawPixels函数对应的参数相同

3. 为openGL的选择缓冲区分配内存时要考虑什么因素

你说的缓冲区是指哪个? 是framebuffer吗? 这个大小是固定的, 和你的分辨率有关。 如果是顶点缓存, 那么都是按量来分的, 一个模型一个缓存, 这样不可能出现额外开销吧。 opengl有深度缓存, 重叠模型的信息在这个缓存内,这个也是大小预设的。 一般来说opengl很少有大规模连续缓存(除了framebuffer, 这个同时存在于显卡或内存(可选)中),其他的缓冲区不用动态改变大小。 而且cpu和gpu是协同关系, 若cpu实时追踪gpu信息,会浪费大量计算去轮询, 从理论和效率上来讲是不推荐的。 一般所有缓冲区的大小都不应该改变, 这样会导致同步问题, 比如你的刚读出去一些数据, 按照你的思路, 可能缓冲的大小就要减半, 可是万一这个数据之后还有程序要读的数据,这样就发生segerror了, 特别是显卡的工作方式对显存的分配有着严格要求, 不能随便改变大小的。 最后可能是我理解有问题, 欢迎随时交流

4. openGL里面那个深度缓存是什么东西啊.. 还有那个深度测试又是什么呢

深度缓存中存储着每个象素点(绘制在屏幕上的)的深度值! 深度测试决定了是否绘制较远的象素点(或较近的象素点),通常选用较近的, 而较远优先能实现透视的效果! 补充: 如同在真实的世界中,我们只能看见距离自己较近的东西,而较远的东西会被较近的东西掩盖,使我们无法看见! 追问: 如果我不启用深度测试 被覆盖的东西能被显示出来么~?~? 回答: 不能,因为OpenGl本身为你开启了较近优先的深度检测,除非你自己开启较远优先的深度检测,

5. openGL里面那个深度缓存是什么东西啊.. 还有那个深度测试又是什么呢

就是里边存的是深度的信息,用来决定哪个东西画在前面,哪个东西画在后面,具体的可以看《OPENGL编程指南》,就是红宝书。

6. OpenGL -- 对深度测试的理解

例如上图中两个图形混合 混合部分会进行重新渲染

深度缓冲区和颜⾊缓存区是对应的。颜⾊缓存区存储像素的颜⾊信息,而深度缓冲区存储像素的深度信息。

在决定是否绘制⼀个物体表⾯时,首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏⽐较。如果大于深度缓冲区中的值,则丢弃这部分;否则利⽤这个像素对应的深度值和颜⾊值,分别更新深度缓冲区和颜色缓存区。这个过程称为深度测试。

fa和near是提供到投影矩阵设置可见视图截锥的远近值。

非线性深度缓存
在实践中可以减少使用这样的线性深度缓冲区。正确的投影特性的非线性深度方程是和1/z成正比,由于非线性方程和1/z成正比,例如1.0和2.0之间的z值,将变为1.0到0.5之间,将z非常小的时候给了我们很高的精度。方程式如下图

在深度缓冲区的值不是线性的屏幕空间(它们在视图空间投影应用之间是线性)。值为0.5的深度缓冲区并不意味着该对象的z值投影上边的平头解体的中间;顶点的z值是实际上徐娘当接近平面!可以看到z值和产生深度缓冲区的值在下列图标中的线性关系

屏幕空间的深度值是非线性如他们在z很小的时候有很高的精度,较大的z值有较低的精度。该片段的深度值会迅速增加,几乎所有顶点的深度值接近1.0。如果我们⼩小⼼心的靠近物体,你最终可能会看到的色彩越来越暗,意味着它们的值越来越小,这清楚地表明深度值的非线性特性。近的物体相对远的物体对的深度值比对象较大的影响。只移动几英寸就能让暗色完全变亮。但是我们可以让深度值变换回线性。要实现这一⽬标我们需要让点应⽤用投影变换逆的逆变换,成为单独的深度值的过程。这意味着我 们必须⾸首先􏰁新变换范围 [0,1] 中的深度值为单位化的设备坐标(normalized device coordinates)范围内 [-1,1] (裁剪空间(clip space))。然后,我们想要反转⾮非线性⽅方程 。

开启深度测试

在绘制场景前,清除颜⾊缓存区,深度缓冲。清除深度缓冲区默认值为1.0。

指定深度测试判断模式

深度缓冲区写入开关

7. OpenGL 渲染技巧:正背面剔除、深度测试、多边形偏移、 混合

在绘制3D场景时,我们需要决定哪些部分是对观察者可⻅的,或者哪些部分是不可见的。对于不可⻅的部分,应该及早丢弃,这种做法叫做 隐藏⾯消除

先绘制红色部分,再绘制⻩色部分,最后再绘制灰⾊部分,即可解决隐藏面消除的问题。即将场景按照物理距离和观察者的距离远近排序,由远及近的绘制即可。

弊端: 如果三个三⻆形是相互重叠的,油画算法将⽆法处理。

从任何⼀个⽅向去观察一个立方体,最多可以看到3个⾯。如果我们能以某种⽅式去丢弃这部分数据。OpenGL在渲染的性能即可提高超过50%。

任何平⾯都有2个⾯:正⾯和背面,⼀个时刻我们只能看到一面。 通过分析顶点数据的顺序 ,OpenGL可以做到检查所有正面朝向观察者的面,并渲染它们;从⽽丢弃背面朝向的面。

⚠️注意: 正⾯和背⾯是有三角形的顶点定义顺序和观察者方向共同决定的。若观察者的观察⽅向发生改变,正⾯和背面也会发生相应的改变。

弊端: 如果前后两个点都是正面或是背面,这时OpenGL无法区分哪个面在前,哪个面在后,就可能出现下图所示的问题。

深度,就是像素点在3D世界中距离摄像机的距离,即Z值。

深度缓存区,就是⼀块内存区域,专门存储每个像素点的深度值。深度值(Z值)越⼤,则离摄像机就越远。

为什么需要深度缓冲区?

深度缓冲区和颜⾊缓存区是对应的。颜⾊缓存区存储 像素的颜⾊信息 ,而深度缓冲区存储 像素的深度信息

在决定是否绘制⼀个物体表⾯时,首先要将表面对应的像素的深度值与当前深度缓冲区中的值进⾏⽐较。如果大于深度缓冲区中的值,则丢弃这部分;否则利⽤这个像素对应的深度值和颜⾊值,分别更新深度缓冲区和颜色缓存区。这个过程称为 深度测试

深度值,⼀般由16位、24位或者32位值表示,通常是24位。

使⽤正⾯/背面剔除法和深度测试法解决了OpenGL的渲染效率问题。

由于精度的限制,对于相差非常小的深度值(比如在同一个深度进行2次渲染),就可能出现不能正确区分两个深度值的问题,导致测试的结果随机出现。所以,显示时2个画⾯交错出现,就会出现闪烁问题。

增大重叠或深度值接近的2个图形的深度值差距,使得OpenGL可以区分两个深度值。

步骤三: 关闭Polygon Offset

在OpenGL中提⾼渲染效率的⼀种⽅式。 只刷新屏幕上发⽣变化的部分。

OpenGL渲染时会把颜色值存在颜⾊缓存区中,每个⽚段的深度值也是放在深度缓冲区。

当混合功能被开启时,源颜色和⽬标颜色的组合方式是 混合方程式 控制的。在默认情况下,混合方程式如下所示:

混合函数经常用于实现在其他一些不透明的物体前面绘制一个透明物体的效果。

实际上不止一种颜色混合方程式,OpenGL有5个不同的方程式进行选择。

表中R、G、B、A 分别代表 红、绿、蓝、Alpha
表中下标S、D,分别代表源、⽬标
表中C 代表常量颜⾊(默认⿊色)

下⾯通过一个常见的混合函数组合来说明问题:

如果颜色缓存区已经有一种颜⾊红色(1, 0, 0, 0)
在这上面混合一种alpha为0.6的蓝色(0, 0, 1, 0.6)

最终颜色是以原先的红色(⽬标颜色)与后来的蓝色(源颜色)进⾏组合。源颜色的alpha值越高,添加的蓝色颜色成分越高,⽬标颜⾊所保留的成分就会越少。

8. opengl+获得深度值Z总在变

摘要 在开始介绍深度缓存之前,先了解一下隐藏表面消除。

9. OPENGL怎么读深度缓存区的数据

读取帧缓存中(x,y)点的深度值保存到Depth里
-----
这个(x,y)点和物体的顶点(Vertex)一样是参与了各种变换的(视变换/投影变换),所以可能并不是最终的窗口的(x,y)的位置。如果需要窗口中从(x,y)开始的数据,需要指定(x,y)是位于窗口坐标的.

10. opengl es深度测试是gpu执行吗

在OpenGL ES中默认是不开启深度测试的,不使用深度测试的时候,先绘制较近的物体,然后绘制较远的物体,当远处的物体和近处的物体出现重叠时导致近处的物体被远处的物体遮挡,这不符合实际的现象,也不是我们想要的效果。
深度测试则是可以解决这种问题,开启深度测试后,深度缓存中存储着的每个像素点都包含深度信息,当绘制新的像素时,先和深度缓存中的深度值进行比较,当深度值比深度缓存中的深度值大时(也就是离相机远)则使用原来大颜色值绘制,反之则使用新的颜色值。
现在大部分的GPU都提供一个叫做提前深度测试(Early Depth Testing)的硬件特性。提前深度测试允许深度测试在片段着色器之前运行。只要我们清楚一个片段永远不会是可见的(它在其他物体之后),我们就能提前丢弃这个片段。

热点内容
数据结构对算法的影响 发布:2024-10-06 18:21:28 浏览:32
服务器托管ip不变 发布:2024-10-06 18:21:20 浏览:421
网盘加密软件 发布:2024-10-06 18:16:17 浏览:123
儿童配置保险怎么买 发布:2024-10-06 18:07:32 浏览:733
ipad存储器 发布:2024-10-06 18:00:07 浏览:534
c语言void返回值 发布:2024-10-06 18:00:02 浏览:319
bat执行shell脚本 发布:2024-10-06 17:59:24 浏览:330
sql单引号双引号 发布:2024-10-06 17:41:51 浏览:572
macbookpro选哪个配置 发布:2024-10-06 16:50:01 浏览:141
linux基础命令 发布:2024-10-06 16:37:59 浏览:411