将不同类型的值传递给着色器

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 计算着色器

OpenGL:将随机位置传递给顶点着色器

SCNProgram - 如何将“mat4”类型的制服传递给自定义着色器?

将无符号整数输入属性传递给顶点着色器

将顶点保存到纹理并传递给着色器