通过glUniform将GLM的矢量类型传递给OpenGL

时间:2018-03-30 20:15:17

标签: c++ opengl glm-math

背景

我目前正在编写一个关于OpenGL的glUniform函数的包装器,以便使它们类型安全。我有一堆set_uniform函数被重载以接受OpenGL POD(GLintGLuintGLfloat)或任何GLM向量和矩阵类型。< / p>

我认为到目前为止一切都很直接,但后来我遇到了布尔类型的问题。 GLSL提供了boolbec2bvec3bvec4,因此我必须为set_uniform提供GLboolean重载以及GLM布尔向量类型。

根据OpenGL手册,没有glUniform函数接受GLboolean或指向GLboolean数组的指针。我必须通过GLintGLuintGLfloat,然后驱动程序会为我进行转换。

  

i,ui或f变体可用于为bool,bvec2,bvec3,bvec4或其数组的均匀变量提供值。如果输入值为0或0.0f,则uniform变量将设置为false,否则将设置为true。

在传递之前将GLboolean转换为GLint很容易,但GLM矢量类型证明更加困难。我进入实施的深度越深,我就越了解这个库。

问题

将GLM向量类型传递给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期望void指向某些GLint s。 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_ttypedef而不是int而不是GLint但也许这可以归结为图书馆设计师知道尺寸是相同的。#/ p>

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

我在这里遗漏了什么吗? GLM库与OpenGL一起被广泛使用,它甚至被列在Khronos&#39;自己的维基。然而,它为将结构传递给OpenGL所提供的功能,即glm::value_ptr,并没有努力确保它传递的类型实际上与OpenGL期望的类型相同,并且完全忽略任何填充。可能存在。 GLM库是否在类型大小和结构填充方面做了一些隐藏的技巧,以便发送到OpenGL的数据有效或者这个库有一些严重的基本问题吗?

1 个答案:

答案 0 :(得分:4)

  

GLM库是否在类型大小和结构填充方面做了一些隐藏的技巧,以便发送到OpenGL的数据有效或者这个库有一些严重的基本问题吗?

都不是。它只是简单地制作了其他人对结构布局和指针算法的行为所做的same assumptions

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

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

  

我对此不是100%满意,因为glm::ivec3的值类型为glm::detail::mediump_int_ttypedef而不是int而不是GLint但也许这可以归结为图书馆设计师知道尺寸是相同的。#/ p>

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

因此,您可以假设ivec3&#39; value_type与[{1}}的类型相同(您甚至可以编写GLint来验证它)或者你可以做出自己的变化。毕竟,GLM是模板化的:

static_assert