gpt4 book ai didi

c++ - 通过 glUniform 将 GLM 的 vector 类型传递给 OpenGL

转载 作者:太空狗 更新时间:2023-10-29 20:51:33 24 4
gpt4 key购买 nike

背景

我目前正在围绕 OpenGL 的 glUniform 编写包装器C++ 中的函数,努力使它们类型安全。我有一堆 set_uniform 函数被重载以接受 OpenGL POD(GLintGLuintGLfloat ) 或任何 GLM vector 和矩阵类型。

我认为到目前为止一切都很简单,但后来我遇到了 bool 类型的问题。 GLSL提供了bool, bec2, bvec3 and bvec4 所以我必须提供一个set_uniform 重载 GLboolean 以及 GLM bool vector 类型。

根据 OpenGL 手册,没有 glUniform 函数可以接受 GLboolean 或指向 GLboolean 数组的指针。我必须传递 GLintGLuintGLfloat 驱动程序将为我进行转换。

Either the i, ui or f variants may be used to provide values for uniform variables of type bool, bvec2, bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input value is 0 or 0.0f, and it will be set to true otherwise.

在传递之前将 GLboolean 转换为 GLint 很容易,但事实证明 GLM vector 类型更加困难。我越深入实现,就越担心这个库。

问题

将 GLM vector 类型传递给 OpenGL 的推荐方法是使用 glm::value_ptr:

glm::bvec3 v(true, true, false);
glUniform3iv(some_uniform_id, 1, glm::value_ptr(v));

这段代码有很多问题。

首先,glm::bvec3 is implemented as a struct of 3 bools (不是 GLboolean,而是 C++ bool)。我认为我不应该直接传递它,因为 glUniform3iv 需要一个指向某些 GLintvoid 指针。 C++ 规范不保证 bool 的大小。这意味着 glUniform3iv 可能会读取第二个和第三个组件的垃圾,或者更糟的是,它实际上正在读取数组末尾。

为了纠正这个问题,我在传递给 OpenGL 之前从 glm::bvec3 转换为 glm::ivec3:

glm::bvec3 bv(true, true, false);
glm::ivec3 iv = bv;
glUniform3iv(some_uniform_id, 1, glm::value_ptr(iv));

我对此不是 100% 满意,因为 glm::ivec3 有一个 glm::detail::mediump_int_t 的值类型,它是一个 typedef 用于 int 而不是 GLint 但也许这可以归结为“库设计者知道大小是相同的”。

第二个也是更主要的问题是 glm::value_ptrjust passing the address of the first struct member并将 struct 视为 array,而不考虑填充。

我是不是漏掉了什么? GLM 库与 OpenGL 一起使用非常广泛,它甚至列在 Khronos 自己的 wiki 上。然而,它提供的用于将其结构传递给 OpenGL 的函数,即 glm::value_ptr,没有努力确保它传递的类型实际上与 OpenGL 期望的类型大小相同,并且完全无视任何可能存在的填充。 GLM 库是否在类型大小和结构填充方面做了一些隐藏的欺骗,以便发送到 OpenGL 的数据是有效的,或者这个库是否存在一些严重的基本问题?

最佳答案

Is the GLM library doing some hidden trickery with regard to type sizes and struct padding so that the data sent to OpenGL is valid or does this library have some serious fundamental problems?

都没有。它只是在制作 same assumptions其他人对结构布局和指针算法的行为所做的。

C++ 标准不允许 value_ptr 工作;这显然是未定义的行为。但它也是处理此类事情的常用技术。许多真实的、功能性的代码都假设一个 struct { int x; int y;}; 可以被认为等同于 int[2]。在大多数 C++ 实现下,这一切都将按预期运行。

在处理低级编程时,做出这种性质的假设并非没有道理。


I'm not 100% happy with this since glm::ivec3 has a value type of glm::detail::mediump_int_t which is a typedef for int rather than GLint but maybe this can be chalked up to 'the library designer knows the sizes are the same'.

与此无关。虽然 GLM 被称为“OpenGL 数学”,但它不依赖于 OpenGL 自身。因此,它无法访问 GLint 或任何其他 OpenGL 定义的类型。

因此您可以假设 ivec3value_typeGLint 的类型相同(您甚至可以编写 static_assert s 来验证它)或者你可以做出自己的变化。毕竟,GLM 是模板化的:

using gl_ivec3 = glm::tvec<GLint, 3>;
...
glm::gl_ivec3 iv = bv;
glUniform3iv(some_uniform_id, 1, glm::value_ptr(iv));

关于c++ - 通过 glUniform 将 GLM 的 vector 类型传递给 OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49580872/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com