Up until now there is only one type of output buffer you've made use of, the color buffer. This chapter will discuss two additional types, the depth buffer and the stencil buffer. For each of these a problem will be presented and subsequently solved with that specific buffer.

Preparations

To best demonstrate the use of these buffers, let's draw a cube instead of a flat shape. The vertex shader needs to be modified to accept a third coordinate:

in vec3 position;
...
gl_Position = proj * view * model * vec4(position, 1.0);

We're also going to need to alter the color again later in this chapter, so make sure the fragment shader multiplies the texture color by the color attribute:

vec4 texColor = mix(texture(texKitten, Texcoord),
texture(texPuppy, Texcoord), 0.5);
outColor = vec4(Color, 1.0) * texColor;

Vertices are now 8 floats in size, so you'll have to update the vertex attribute offsets and strides as well. Finally, add the extra coordinate to the vertex array:

float vertices[] = {
// X Y Z R G B U V
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f
};

Confirm that you've made all the required changes by running your program and checking if it still draws a flat spinning image of a kitten blended with a puppy. A single cube consists of 36 vertices (6 sides * 2 triangles * 3 vertices), so I will ease your life by providing the array here.

glDrawArrays(GL_TRIANGLES, 0, 36);

We will not make use of element buffers for drawing this cube, so you can use glDrawArrays to draw it. If you were confused by this explanation, you can compare your program to this reference code.

It immediately becomes clear that the cube is not rendered as expected when seeing the output. The sides of the cube are being drawn, but they overlap each other in strange ways! The problem here is that when OpenGL draws your cube triangle-by-triangle, it will simply write over pixels even though something else may have been drawn there before. In this case OpenGL will happily draw triangles in the back over triangles at the front.

Luckily OpenGL offers ways of telling it when to draw over a pixel and when not to. I'll go over the two most important ways of doing that, depth testing and stencilling, in this chapter.

Depth buffer

Z-buffering is a way of keeping track of the depth of every pixel on the screen. The depth is proportional to the distance between the screen plane and a fragment that has been drawn. That means that the fragments on the sides of the cube further away from the viewer have a higher depth value, whereas fragments closer have a lower depth value.

If this depth is stored along with the color when a fragment is written, fragments drawn later can compare their depth to the existing depth to determine if the new fragment is closer to the viewer than the old fragment. If that is the case, it should be drawn over and otherwise it can simply be discarded. This is known as depth testing.

OpenGL offers a way to store these depth values in an extra buffer, called the depth buffer, and perform the required check for fragments automatically. The fragment shader will not run for fragments that are invisible, which can have a significant impact on performance. This functionality can be enabled by calling glEnable.

glEnable(GL_DEPTH_TEST);

If you enable this functionality now and run your application, you'll notice that you get a black screen. That happens because the depth buffer is filled with 0 depth for each pixel by default. Since no fragments will ever be closer than that they are all discarded.

The depth buffer can be cleared along with the color buffer by extending the glClear call:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

The default clear value for the depth is 1.0f, which is equal to the depth of your far clipping plane and thus the furthest depth that can be represented. All fragments will be closer than that, so they will no longer be discarded.

With the depth test capability enabled, the cube is now rendered correctly. Just like the color buffer, the depth buffer has a certain amount of bits of precision which can be specified by you. Less bits of precision reduce the extra memory use, but can introduce rendering errors in more complex scenes.  

 出自 : https://open.gl/depthstencils  重要
 

Depth Buffer的更多相关文章

  1. [Zz] DX depth buffer

    声明:本文完全翻译自DX SDK Documentation depth buffer,通常被称为z-buffer或者w-buffer,是设备的一个属性,用来存储深度信息,被D3D使用.当D3D渲染一 ...

  2. D3D depth buffer的预览

    在使用D3D开发游戏的过程中,很多情况下都会用到depth buffer来完成特定的效果,比如DOF,Shadows,SSAO等等.在这些情况下我们就可能需要预览depth buffer来确定它是正确 ...

  3. 从depth buffer中构建view-space position

    观察透视投影矩阵: 对于x和y,矩阵变换只是一个缩放系数,那么逆变换就是缩放系数的倒数,所以 设Xndc Yndc为NDC空间中的XY坐标,Xview Yview Zview为view space中的 ...

  4. 测试不同格式下depth buffer的精度

    这篇文章主要是参考MJP的“Attack of The Depth Buffer”,测试不同格式下depth buffer的精度. 测试的depth buffer包含两类: 一是非线性的depth b ...

  5. Cesium 中由 Logarithmic Depth Buffer 引起的模型显示不完整的问题

    当 Cesium 单个模型过长时,会遇到某些视角模型显示不完整的问题,如下图所示: 经过在官方论坛上询问,该问题由 viewer.scene.logarithmicDepthBuffer 开启造成,关 ...

  6. Vulkan SDK 之 Depth Buffer

    深度缓冲是可选的,比如渲染一个3D的立方体的时候,就需要用到深度缓冲.Swapchain就算有多个images,此时深度缓冲区也只需要一个.vkCreateSwapchainKHR 会创建所有需要的i ...

  7. depth/stencil buffer的作用 ----------理解模板缓存 opengl

    在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所示,framebuffer中一个像素,有相对应的depth buffer和stencil buf ...

  8. 【D3D12学习手记】4.3.8 Create the Depth/Stencil Buffer and View

    我们现在需要创建深度/模板缓冲区. 如§4.1.5所述,深度缓冲区只是一个2D纹理,用于存储最近的可见对象的深度信息(如果使用模板(stencil),则也会存储模板信息). 纹理是一种GPU资源,因此 ...

  9. Directx11教程(48) depth/stencil buffer的作用

    原文:Directx11教程(48) depth/stencil buffer的作用      在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所 ...

随机推荐

  1. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之_关于接口调用常见的一些问题(401 Unauthorized)

    在之前的博客<EasyNVR H5流媒体服务器方案架构设计之视频能力平台>中我们描述了EasyNVR的定位,作为一个能力平台来进行功能的输出: 也就是说,在通常情况下,我们将一套视频的应用 ...

  2. Python中高层次的数据结构,动态类型和动态绑定,使得它非常适合于快速应用开发,也适合于作为胶水语言连接已有的软件部件。

    https://github.com/jhao104/proxy_pool/blob/master/doc/introduce.md 3.代码模块 Python中高层次的数据结构,动态类型和动态绑定, ...

  3. python使用记录

    #2017-7-17 1.用len()函数可以获得list元素的个数; len()可以获取字符串长度 2. list正向0开始索引,,逆向-1开始索引; 也可以把元素插入到指定的位置,比如索引号为1的 ...

  4. python网络爬虫之初识网络爬虫

    第一次接触到python是一个很偶然的因素,由于经常在网上看连载小说,很多小说都是上几百的连载.因此想到能不能自己做一个工具自动下载这些小说,然后copy到电脑或者手机上,这样在没有网络或者网络信号不 ...

  5. 基于node开发的web应用,负载均衡的简单实践

    集群(cluster)是一组相互独立的.通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理.一个客户与集群相互作用时,集群像是一个独立的服务器. 负载均衡(Load Balance ...

  6. 跟我一起学Git (十) Patches【转】

    本文转载自:http://cs-cjl.com/2014/05/05/learn_git_with_me_10 Git实现了以下三条用于交换patch的命令: git format-patch 用于创 ...

  7. 算法(Algorithms)第4版 练习 1.3.23 1.3.22

    1.3.23 When it comes time to update t.next, x.next is no longer the original node following x, but i ...

  8. RQNOJ 169 最小乘车费用:水dp

    题目链接:https://www.rqnoj.cn/problem/169 题意: 给出行驶1-10公里的费用(所有车一样),可以倒车,问行驶n公里的最小费用. 题解: 大水题... (=´ω`=) ...

  9. fiddler篡改请求数据

    有时需要修改请求或返回结果来验证网站存在的漏洞,因此需要使用到fiddler的断点功能. 如何修改请求前数据? 1.设置请求前断点 Rules--Automatic breakpoints--befo ...

  10. swift的泛型貌似还差点意思

    protocol Container { typealias ItemType mutating func append(item: ItemType) mutating func removelas ...