OpenGL 在 GPU 上构建和使用数据

OpenGL constructing and using data on the GPU

我不是图形程序员,我主要使用 C++ 和 C,每次我尝试进入 OpenGL,每本书,每一个资源都是这样开始的:

GLfloat Vertices[] = {
some, numbers, here,
some, more, numbers,
numbers, numbers, numbers
};

或者它们甚至可能是 vec4。

但是你做了这样的事情:

for(int i = 0; i < 10000; i++)
    for(int j = 0; j < 10000; j++)
        make_vertex();

然后你遇到了问题。该循环将花费大量时间来完成 - 如果 make_vertex() 函数类似于 saxpy 或类似的东西,这不仅仅是一个问题......这是一个大问题.例如,假设我希望创建分形地形。对于任何现代图形卡,这都是微不足道的。

我理解范例是这样的:手动编写顶点 -> 将它们发送到 GPU -> GPU 进行顶点处理、几何、光栅化所有好东西。我相信这一切都是有道理的。但为什么我必须执行整个 'Send it over' 步骤? 有没有办法跳过整个中间步骤,只在 GPU 上创建顶点并绘制它们,而没有明显的瓶颈?

我将非常感谢至少在正确方向上的一点。

我也想知道是否有不深入研究计算着色器或 CUDA 的可能解决方案? openGL或GLSL是否没有提供合适的可以并行执行的随机函数?

我认为您所要求的可以通过使用计算着色器生成高度图并将其映射到具有固定间距的网格上来实现,该网格可以很容易地生成。这是我想到的一个可能的解决方案。您可以使用 GL 计算着色器、OpenCL 或 CUDA。可以使用几何和曲面细分着色器生成细节。

至于防止相机剪裁,您可能必须使用变换反馈并每帧进行检查以查看您移动的方向是否会与几何体相交。

你的整个问题似乎建立在一个巨大的误解之上,即顶点是 GPU 唯一需要 "crunched" 的东西。

首先,您应该了解 GPU 在并行性方面远远优于 CPUs(见鬼,GPU 为了并行性牺牲了条件控制跳跃)。其次,着色器和你制作的这些缓冲区都是在CPU上传后存储在GPU上的。您不只是在 GPU 上创建所有顶点的原因是什么?这与为什么从硬盘驱动器加载图像而不是创建原始二维数组并开始用内联像素数据填充它的原因相同。即便如此,您的图像仍将存储在可执行程序文件中,该文件存储在硬盘上,只有在您 运行 时才会加载到内存中。在实际应用程序中,您需要从存储在某处(通常是硬盘驱动器)的资产加载图形。为什么不让 GPU 自己从硬盘加载资源呢? GPU 不直接连接到硬件的存储,而是通过一些总线几乎不连接到系统的主内存。这是因为要直接连接到任何存储,GPU 必须处理由 OS 管理的文件系统。这是 CPU 可以更快完成的事情之一,因为我们正在处理序列化数据。

现在着色器处理的是您上传到 GPU 的数据(顶点、纹理坐标、纹理等)。在古老的 OpenGL 中,没有人必须编写任何着色器。图形驱动程序带有一个内置管道,可以为您处理常规渲染请求。你会为它提供 4 个顶点、4 个纹理坐标和一个纹理等(转换矩阵等),它会在屏幕上为你绘制图形。你可以走得更远,为你的场景添加一些灯光,也许还可以定制一些关于它的东西,但事情仍然很紧张。新的 OpenGL 规范允许开发人员使用着色器重写部分管线,从而为开发人员提供了更多自由。开发人员负责将顶点转换到位并进行与照明等相关的所有其他计算。

I would very much appreciate at least a point in the right direction. I am guessing it has something to do with uniforms, but really, with me skipping pages, I really cannot understand how a shader program runs or what the lifetime of the variables is.

uniforms 是变量,您可以在使用它渲染图形之前从 CPU 每一帧发送到着色器。当您在 Photoshop 或 Gimp 中使用饱和度滑块时,它(可能)将饱和度因子值作为浮点类型的统一发送到着色器。 uniforms 是你用来从你的应用程序向你的着色器传达这些小设置的东西。

要使用着色器程序,您首先必须对其进行设置。一个着色器程序由至少两种链接在一起的着色器组成,一个片段着色器和一个顶点着色器。你使用一些 OpenGL 函数将你的着色器源上传到 GPU,发出编译顺序然后链接,它会给你程序的 ID。要使用此程序,您只需 glUseProgram(programId) 并且此调用后的所有内容都将使用它进行绘图。顶点着色器是 运行 在您发送的顶点上的代码,用于将它们正确定位在屏幕上。在这里您可以对几何体进行变换,如缩放、旋转等。片段着色器 运行s 在之后的某个阶段使用从顶点着色器输出的插值(过渡)值来定义每个单元的颜色和深度片段在你画的东西上。在这里您可以对像素进行 post 处理效果。

无论如何,我希望我能帮助您更清楚地了解一些事情,但我只能告诉您没有捷径可走。 OpenGL 的学习曲线相当陡峭,但一切都相互关联,一段时间后事情就开始变得有意义了。如果您对书籍之类的东西感到厌烦,那么可以考虑从每节课中提取代码片段,编译它们,然后开始摆弄它们,同时尝试合理化。您最终将不得不求助于书面文档,但希望当您对实施组件有一些经验时,事情会更容易融入您的脑海。祝你好运。

编辑: 如果您尝试使用某种算法动态生成顶点,请尝试查看 Geometry Shaders。他们可能会给你你想要的。

您可能希望将 CUDA 用于您习惯于在 C 或 C++ 中执行的操作,并让 OpenGL 访问光栅化程序和其他图形内容。

OpenGL 和 CUDA 以某种方式很好地交互。这里是自定义缓冲区对象内容的一个很好的切入点:http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__OPENGL.html#group__CUDART__OPENGL_1g0fd33bea77ca7b1e69d1619caf44214b,使用 cudaGraphicsGLRegisterBuffer 方法。

您可能还想查看 NVIDIA GPU SDK 示例中的 nbody 示例,这些示例随当前 CUDA 安装一起提供。