GLM mat4x4 到布局限定符
GLM mat4x4 to layout qualifier
我目前正在为一个业余项目学习 OpenGL,我已经到了想用实例化做一些粒子效果的地步。
为了让我的每个粒子都有自己的变换,我正在构建一个带有变换矩阵的向量并使用缓冲区的值:
glBindBuffer(GL_ARRAY_BUFFER, particleEffect->getTransformationBufferID());
std::vector<glm::mat4x4> particleTransformations;
const std::vector<Particle>& particles = particleEffect->getParticles();
for(std::vector<Particle>::const_iterator particleIt = particles.cbegin();
particleIt != particles.cend();
++ particleIt)
{
particleTransformations.push_back(particleIt->getTransformation());
}
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(particleTransformations[0]) * particles.size(), particleTransformations.data());
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 16, GL_FLOAT, GL_FALSE, 0, 0);
我正在以这种方式初始化我的转换缓冲区:
glGenBuffers(1, &transformationBufferID_);
glBindBuffer(GL_ARRAY_BUFFER, transformationBufferID_);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4x4) * particles_.size(), nullptr, GL_STREAM_DRAW);
我使用这个简单的绘制代码:
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 0);
glVertexAttribDivisor(2, 0);
glVertexAttribDivisor(3, 0);
glVertexAttribDivisor(4, 1); //(4, 1), because each particle has its own transformation matrix at (layout location = 4)?!
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, particleEffect->getVertices().size(), particleEffect->getParticles().size());//getVertices() are the same vertices for each particle
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
我的顶点着色器 header 看起来像这样:
#version 430 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 normals;
layout(location = 2) in vec4 colors;
layout(location = 3) in vec2 uvCoordinates;
layout(location = 4) in mat4 transformation;
这会导致 glError 1281 崩溃,但前提是我使用 glEnableVertexAttribArray(4)。否则这不会崩溃。当我使用单位矩阵而不是变换矩阵时,我也能够绘制我的简单粒子网格。
我使用 glGetAttribLocation(programID, "transformation") 来确定位置是否正确。没错,没错。
您的问题实际上根本不是 layout
限定符,您需要了解顶点属性的一些细微差别。
在 GPU 上,每个顶点属性都是一个 4 分量向量,无论您将其声明为 float
、vec2
、vec3
还是 vec4
。这适用于我刚才提到的所有类型,该 4 分量向量的未使用部分分别分配为 0,0,1。
然而,对于 mat4
,情况却大不相同。 mat4
实际上是一个包含四个 vec4
的数组,这意味着 layout(location = 4) in mat4 transformation;
实际上占据了 4 个不同的位置(所有顺序)。
transformation
由分配给位置 4、5、 的四个 4 分量向量组成6 和 7。 glVertexAttribPointer(4, 16, GL_FLOAT, GL_FALSE, 0, 0);
是错误的,需要像这样分成多个调用:
// Setup 4 different vertex attributes (one for each column of your matrix).
// Each matrix has a stride of 64-bytes and each column of the matrix advances 16-bytes
glVertexAttribPointer (4, 4, GL_FLOAT, GL_FALSE, 64, 0);
glVertexAttribPointer (5, 4, GL_FLOAT, GL_FALSE, 64, 16);
glVertexAttribPointer (6, 4, GL_FLOAT, GL_FALSE, 64, 32);
glVertexAttribPointer (7, 4, GL_FLOAT, GL_FALSE, 64, 48);
您还需要为所有四个属性位置启用、禁用和设置顶点属性除数,以使您的代码正常工作。
我目前正在为一个业余项目学习 OpenGL,我已经到了想用实例化做一些粒子效果的地步。
为了让我的每个粒子都有自己的变换,我正在构建一个带有变换矩阵的向量并使用缓冲区的值:
glBindBuffer(GL_ARRAY_BUFFER, particleEffect->getTransformationBufferID());
std::vector<glm::mat4x4> particleTransformations;
const std::vector<Particle>& particles = particleEffect->getParticles();
for(std::vector<Particle>::const_iterator particleIt = particles.cbegin();
particleIt != particles.cend();
++ particleIt)
{
particleTransformations.push_back(particleIt->getTransformation());
}
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(particleTransformations[0]) * particles.size(), particleTransformations.data());
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 16, GL_FLOAT, GL_FALSE, 0, 0);
我正在以这种方式初始化我的转换缓冲区:
glGenBuffers(1, &transformationBufferID_);
glBindBuffer(GL_ARRAY_BUFFER, transformationBufferID_);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4x4) * particles_.size(), nullptr, GL_STREAM_DRAW);
我使用这个简单的绘制代码:
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 0);
glVertexAttribDivisor(2, 0);
glVertexAttribDivisor(3, 0);
glVertexAttribDivisor(4, 1); //(4, 1), because each particle has its own transformation matrix at (layout location = 4)?!
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, particleEffect->getVertices().size(), particleEffect->getParticles().size());//getVertices() are the same vertices for each particle
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
我的顶点着色器 header 看起来像这样:
#version 430 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 normals;
layout(location = 2) in vec4 colors;
layout(location = 3) in vec2 uvCoordinates;
layout(location = 4) in mat4 transformation;
这会导致 glError 1281 崩溃,但前提是我使用 glEnableVertexAttribArray(4)。否则这不会崩溃。当我使用单位矩阵而不是变换矩阵时,我也能够绘制我的简单粒子网格。
我使用 glGetAttribLocation(programID, "transformation") 来确定位置是否正确。没错,没错。
您的问题实际上根本不是 layout
限定符,您需要了解顶点属性的一些细微差别。
在 GPU 上,每个顶点属性都是一个 4 分量向量,无论您将其声明为 float
、vec2
、vec3
还是 vec4
。这适用于我刚才提到的所有类型,该 4 分量向量的未使用部分分别分配为 0,0,1。
然而,对于 mat4
,情况却大不相同。 mat4
实际上是一个包含四个 vec4
的数组,这意味着 layout(location = 4) in mat4 transformation;
实际上占据了 4 个不同的位置(所有顺序)。
transformation
由分配给位置 4、5、 的四个 4 分量向量组成6 和 7。 glVertexAttribPointer(4, 16, GL_FLOAT, GL_FALSE, 0, 0);
是错误的,需要像这样分成多个调用:
// Setup 4 different vertex attributes (one for each column of your matrix).
// Each matrix has a stride of 64-bytes and each column of the matrix advances 16-bytes
glVertexAttribPointer (4, 4, GL_FLOAT, GL_FALSE, 64, 0);
glVertexAttribPointer (5, 4, GL_FLOAT, GL_FALSE, 64, 16);
glVertexAttribPointer (6, 4, GL_FLOAT, GL_FALSE, 64, 32);
glVertexAttribPointer (7, 4, GL_FLOAT, GL_FALSE, 64, 48);
您还需要为所有四个属性位置启用、禁用和设置顶点属性除数,以使您的代码正常工作。