将不同类型的值传递给着色器
Posted
技术标签:
【中文标题】将不同类型的值传递给着色器【英文标题】:Passing values of different types to shader 【发布时间】:2021-02-17 18:51:59 【问题描述】:我正在使用 GLEW32 和 GLFW 并在 C++ 上编写代码。我在将值传递给着色器时遇到了一些问题。我已经成功传递vec2, uvec3
等。现在我想为每个顶点传递多个值:
uvec2
(或vec2
- 不是很重要)- X 和 Y 位置;
uvec4
- RGBA 颜色。我也可以使用int
从int32解码RGBA,但uvec4
会更方便:)
但还有一个问题:我可以使用glVertexAttribIPointer()
或glVertexAttribPointer()
设置不同的属性类型:
glVertexAttribIPointer(0, 2, GL_UNSIGNED_SHORT, ...);
glEnableVertexAttribArray(0);
glVertexAttribIPointer(1, 4, GL_UNSIGNED_BYTE, ...);
glEnableVertexAttribArray(1);
但我不能将不同类型的值传递给glBufferData()
:
glBufferData(GL_ARRAY_BUFFER, sizeof(array), array, GL_DYNAMIC_DRAW); // Just one array!!!
我尝试使用制服来做到这一点,但代码过于庞大且效率低下,我放弃了它。有没有办法“正确”地进行这种操作?
【问题讨论】:
"但是我不能将不同类型的值传递给 glBufferData():" - 当然可以。glBufferData
的参数只是一个一定大小的缓冲区,但缓冲区没有类型。
你的意思是我可以将所需信息的字节编码为单个字节吗?
“编码为单字节”是什么意思?一切都是字节
例如,我有 2 个浮点数,每个浮点数占用 4 个字节和 4 个 uchar,每个浮点数占用 1 个字节(总共 12 个字节)。我可以以某种方式将所有数据转换为字节并传递它。或者我可以使用 union 使值占用相同的内存地址。还是我理解错了?...
我可以以某种方式将所有数据转换为字节 - 什么?你的浮点数是已经是字节了..你不需要做任何事情来把任何东西变成字节...... glBufferData函数的数据参数的参数类型是const void*
,所以你可以提供它例如一个指向结构的指针,它只包含你所有的每个顶点数据..
【参考方案1】:
我在Kai Burjack 的评论中找到了解决方案。我制作了一个结构来保存数据并发送它。代码是:
struct dataToSend
GLushort x, y;
GLubyte r, g, b, a;
...
glVertexAttribIPointer(0, 2, GL_UNSIGNED_SHORT, sizeof(dataToSend), (GLvoid *) 0);
glEnableVertexAttribArray(0);
glVertexAttribIPointer(1, 4, GL_UNSIGNED_BYTE, sizeof(dataToSend), (GLvoid *) (2 * sizeof(GLushort)));
glEnableVertexAttribArray(1);
...
// (pixels) x y r g b a
dataToSend data [4] = width, height, 255, 255, 0, 255, // Corner 1 (Up-Right)
width, 0, 255, 0, 255, 255, // Corner 2 (Down-Right)
0, 0, 0, 255, 0, 0, // Corner 3 (Down-Left)
0, height, 0, 255, 255, 255; // Corner 4 (Up-Left)
glBufferData(GL_ARRAY_BUFFER, sizeof(data), (GLvoid *) data, GL_DYNAMIC_DRAW);
使用 GLvoid 并指向一个结构而不是数组是一种奇怪的体验,但这让我们可以将几乎所有数据传递给着色器。结果图像在这里: Rendered image
【讨论】:
以上是关于将不同类型的值传递给着色器的主要内容,如果未能解决你的问题,请参考以下文章
将 UInt8 组件类型的纹理传递给 Metal 计算着色器