12.4 OpenGL顶点后处理:图元裁剪

2024-02-11 23:52

本文主要是介绍12.4 OpenGL顶点后处理:图元裁剪,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图元裁剪 Primitive Clipping

Primitive Clipping(图元裁剪)是图形渲染管线中的一个重要步骤,发生在顶点处理之后、光栅化之前。这个阶段主要目的是去除位于视体(View Volume)之外或者被用户自定义裁剪平面(Clip Planes)裁剪掉的图元(如点、线段和三角形),以减少不必要的渲染计算。

在OpenGL中,原始图元裁剪过程首先会根据视口坐标系(Viewport)、近裁剪面(Near Clip Plane)、远裁剪面(Far Clip Plane)以及可能存在的额外用户定义裁剪平面来确定有效视体。接着,对每个传入的图元进行裁剪操作:

  1. 如果整个图元都在视体内,则保留该图元。
  2. 如果部分图元在视体内,则通过线性插值算法生成新的顶点,并根据这些顶点重新构造出一个位于视体内的新图元。
  3. 如果整个图元都在视体外或被用户定义裁剪平面裁剪,则丢弃该图元。

此外,可以通过查询对象追踪经过原始图元裁剪阶段处理的图元数量(CLIPPING_INPUT_PRIMITIVES)以及成功通过裁剪并进一步由光栅化阶段处理的图元数量(CLIPPING_OUTPUT_PRIMITIVES)。同时,启用RASTERIZER_DISCARD状态时,实现可能会直接在裁剪阶段后丢弃图元,这可能导致裁剪输入和输出计数器不增加。

控制裁剪空间坐标的原点和深度范围

void glClipControl( enum origin, enum depth );

允许开发者控制裁剪空间坐标的原点和深度范围。这对于精确的投影和深度测试至关重要,尤其是在需要与某些渲染API进行兼容性调整时。

  • origin 参数指定裁剪空间坐标系的原点位置:

    • GL_LOWER_LEFT: 原点位于左下角,这是默认值,符合传统OpenGL坐标系统。
    • GL_UPPER_LEFT: 原点位于左上角,这更符合Direct3D等其他API的习惯。
  • depth 参数定义裁剪空间深度范围:

    • GL_NEGATIVE_ONE_TO_ONE: 深度范围从-1到1,这是OpenGL的传统深度缓冲范围。
    • GL_ZERO_TO_ONE: 深度范围从0到1,这与某些其他图形API如Vulkan和Direct3D中的深度范围一致。

通过调用这个函数,开发者可以根据自己的需求来匹配不同API的深度缓冲区设置,以及根据不同的坐标系统原点来确保跨平台应用的一致性。

裁剪和剔除过程

几何体(primitives)在渲染过程中需要经过裁剪和剔除阶段以确保只有位于视口可见区域内的部分被绘制。以下是该过程的详细说明:

  1. Culling Against Cull Volume

    • 用户可以通过gl_CullDistance数组定义多个自定义剔除半空间,并且系统允许的最大数量由MAX_CULL_DISTANCES决定。
    • 在顶点着色器阶段结束后,每个几何体根据其顶点对应的cull距离与用户定义的cull半空间进行比较。如果一个几何体的所有顶点相对于任何启用的cull半空间的距离均为负值,则该几何体会被剔除,不会进入后续的渲染流程。
  2. Clipping to Clip Volume

    • 视口视锥体(view volume)是按照特定坐标范围定义的(例如:-wc ≤ xc ≤ wc, -wc ≤ yc ≤ wc, zmin ≤ zc ≤ wc),其中zmin取决于深度裁剪模式(NEGATIVE_ONE_TO_ONE或ZERO_TO_ONE)。
    • 除了视口视锥体之外,还可以结合多达MAX_CLIP_DISTANCES个客户端定义的裁剪半空间来形成最终的裁剪体积(clip volume)。如果没有启用自定义裁剪半空间,那么裁剪体积就是视口视锥体本身。
    • 最后一个顶点处理阶段通过gl_ClipDistance[]数组为每个启用的裁剪半空间写入相应的裁剪距离。当顶点P满足ci§ ≥ 0时,它位于裁剪半空间i内,对于点、线段和三角形,裁剪距离会进行适当的插值计算。
  3. Clipping Process for Different Primitives

    • 对于不同类型的几何体,裁剪过程有不同的处理方式:
      • 点:若点位于近裁剪平面和远裁剪平面之间及所有启用的半空间内,则保留;否则可能被丢弃。此外,实现也可以选择丢弃超出视口视锥体的点。
      • 线段:完全位于裁剪体积内的线段不做处理;完全位于体积外则丢弃;部分位于内外则会被裁剪,并根据裁剪算法计算新的顶点坐标。
      • 多边形:多边形需保证所有边缘都在裁剪体积内才能被完整保留;否则将进行裁剪操作。裁剪后的多边形可能会导致边缘被裁剪,为了保持多边形连接性,会在裁剪边界上添加新的边缘,这可能导致引入新顶点。
  4. Depth Clamping

    • 深度钳制功能通过调用Enable或Disable并指定DEPTH_CLAMP目标来开启或关闭。如果开启深度钳制,系统将在裁剪阶段忽略视锥体关于深度坐标的限制(即不再有明确的近/远裁剪平面)。
  5. Complementarity Criterion and Initial State

    • 使用用户定义半空间裁剪的几何体必须满足互补准则,即无论何时更改裁剪距离符号,都不能导致像素丢失或重复绘制。
    • 初始状态下,裁剪控制原点设为LOWER_LEFT,深度模式默认为NEGATIVE_ONE_TO_ONE,所有用户定义的半空间均未启用。
  6. Implementation Considerations

    • 实现可以灵活地处理输入几何体,即使在某些情况下不改变几何体或者因为实现依赖的原因将一个输入几何体输出为多个裁剪后的几何体,只要保证最终渲染结果不变即可。

裁剪着色器输出 Clipping Shader Outputs

在图形渲染管线中,顶点着色器输出值的裁剪阶段紧随顶点处理阶段之后。对于位于裁剪体积内的顶点,其关联的输出值不受裁剪影响。

然而,如果一个图元(如三角形、线段等)被裁剪了,那么由裁剪产生的新顶点所对应的输出值会受到裁剪的影响。例如:

假设未裁剪边P1和P2上的两个顶点分别具有输出值c1和c2。对于被裁剪点P,我们可以通过计算出的t值,按照以下方式获取与点P相关的输出值c:

c = t c1 + (1 − t) c2

这里的乘法操作意味着每个输出分量x、y、z和w都会与标量t进行相应的乘法运算。

当进行多边形裁剪时,可能会在线框与裁剪体积边界相交的地方创建新的裁剪顶点。这种情况通过观察到多边形裁剪是沿着单个半空间逐一进行的来处理。同样地,输出值的裁剪也按此方式进行,确保裁剪点总是出现在已裁剪或未裁剪的多边形边缘与裁剪体积边界的交点上。

对于最后一级顶点着色器指定不采用透视校正插值(使用noperspective限定符)的输出值,在计算与点P相关联的输出值时,所使用的t值会被调整以保证结果在屏幕空间内呈线性变化。

另外,实现无需支持整型或无符号整型类型的输出值插值,因为所有这类属性必须采用平面着色技术,即同一图元的所有片段共享同一个顶点属性值,而不是在片段间进行插值计算。

图元裁剪查询 Primitive Clipping Queries

,以及。

调用 glBeginQuery,并设置目标如下值时:

  1. CLIPPING_INPUT_PRIMITIVES 查询
    跟踪经过原始图元裁剪阶段处理的图元数量。

  2. CLIPPING_OUTPUT_PRIMITIVES 查询
    通过原始图元裁剪阶段并进一步由光栅化阶段处理的图元数量。对于特定输入图元,实际通过裁剪阶段输出的图元数量依赖于具体实现,但必须满足以下条件:

    • 如果输入图元至少有一个顶点位于裁剪体积内,则计数器至少增加1。
    • 否则,计数器可能增加0或更多。
  3. RASTERIZER_DISCARD 状态的影响
    当启用 GL_RASTERIZER_DISCARD 标志时,实施允许在可选的变换反馈状态之后立即丢弃图元(参见第14.1节)。因此,如果启用了 RASTERIZER_DISCARD,裁剪输入和输出图元的计数器可能不会递增。这意味着在这种情况下,即使图元通过了裁剪阶段,也可能因为光栅化阶段被忽略而不计入相关计数器中。

这篇关于12.4 OpenGL顶点后处理:图元裁剪的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/701155

相关文章

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

POJ3041 最小顶点覆盖

N*N的矩阵,有些格子有物体,每次消除一行或一列,最少要几次消灭完。 行i - >列j 连边,表示(i,j)处有物体,即 边表示 物体。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;impo

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

通用内存快照裁剪压缩库Tailor介绍及源码分析(一)

背景 我们知道内存快照是治理 OOM 问题及其他类型的内存问题的重要数据源,内存快照中保存了进程虚拟机的完整的堆内存数据,很多时候也是调查其他类型异常的重要参考。但是dump出来的堆转储文件.hprof往往很大,以 LargeHeap 应用为例,其 OOM 时的内存快照大小通常在512M左右,要有效的存储和获取都是一个问题。 线下拿到hprof文件相对容易,也可以预防OOM,但覆盖的场景十分有

Windows11电脑上自带的画图软件修改照片大小(不裁剪尺寸的情况下)

针对一张图片,有时候上传的图片有大小限制,那么在这种情况下如何修改其大小呢,在不裁剪尺寸的情况下 步骤如下: 1.选定一张图片,右击->打开方式->画图,如下: 第二步:打开图片后,我们可以看到图片的大小为82.1kb,点击上面工具栏的“重设大小和倾斜”进行调整,如下: 第三步:修改水平和垂直的数字,此处我修改为分别都修改为50,然后保存,可以看到大小变成63.5kb,如下:

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL雾(fog)

使用fog步骤: 1. enable. glEnable(GL_FOG); // 使用雾气 2. 设置雾气颜色。glFogfv(GL_FOG_COLOR, fogColor); 3. 设置雾气的模式. glFogi(GL_FOG_MODE, GL_EXP); // 还可以选择GL_EXP2或GL_LINEAR 4. 设置雾的密度. glFogf(GL_FOG_DENSITY, 0

opengl纹理操作

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是只显示几个多边形那样单调了。——但是这还不够。虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求。例如要将一幅世界地图绘制到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的。OpenGL纹理映射功能支持将

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。   1. 顶点着色器(Vert