C++ 如何将矩阵数组更新为glsl着色器

C++ 如何将矩阵数组更新为glsl着色器,c++,opengl,matrix,glsl,vertex-shader,C++,Opengl,Matrix,Glsl,Vertex Shader,我目前正在处理骨骼动画,我真的很快就能让它工作了。目前,我有一个结构,它的矩阵有100个点(这样我最多可以有100个关节),如下所示: struct skelShader { glm::mat4 currentJointTrans[100]; }; 结构应该绑定在着色器中,我是这样做的: glGenBuffers(1, &sksBuff); glBindBuffer(GL_UNIFORM_BUFFER, sksBuff); // bind buffer to work fu

我目前正在处理骨骼动画,我真的很快就能让它工作了。目前,我有一个结构,它的矩阵有100个点(这样我最多可以有100个关节),如下所示:

struct skelShader {

glm::mat4 currentJointTrans[100];

};
结构应该绑定在着色器中,我是这样做的:

    glGenBuffers(1, &sksBuff);
glBindBuffer(GL_UNIFORM_BUFFER, sksBuff);
// bind buffer to work further with it...
// allocate memory for the buffer in the GPU
glBufferData(GL_UNIFORM_BUFFER, sizeof(skelShader), NULL, GL_STATIC_DRAW);
// because we hard-coded "binding=3" in the shader code we can do this:
// bind Uniform Buffer to binding point 3 (without caring about index of UBO)
glBindBufferBase(GL_UNIFORM_BUFFER, 4, sksBuff);
// good practice, unbind buffer
glBindBuffer(GL_UNIFORM_BUFFER, 0);
    for (int i = 0; i < skeleton.size(); i++) {

    globalSkelInfo.currentJointTrans[i] = skeleton[i]->transformMat[currentFrame - 1] * skeleton[i]->globalBindPosMat;

}
#version 440

const int maxJoints = 100;
const int maxWeights = 4;

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_UV;
layout(location = 2) in vec3 vertex_normal;

layout(location = 3) in vec4 vertex_weight;
layout(location = 4) in ivec4 vertex_controllers;


out vec2 outUVs;
out vec3 outNorm;

layout(binding = 3 , std140) uniform uniformBlock
{
    vec3 camPos;
    mat4 world;
    mat4 LookAt;
    mat4 projection;
    mat4 MVP;
};

layout(binding = 4 , std140) uniform animationStruct
{
    mat4 currentJointTrans[maxJoints];
};

void main() {


vec4 finalModelPos = vec4(0.0);
vec4 finalNormal = vec4(0.0);

for (int i = 0; i < 4; i++) {

    mat4 jointTrans = currentJointTrans[vertex_controllers[i]];
    vec4 posePos = jointTrans * vec4(vertex_position, 1.0);
    finalModelPos += posePos * vertex_weight[i];

    vec4 worldNormal = jointTrans * vec4(vertex_normal, 0.0);
    finalNormal += worldNormal * vertex_weight[i];

}

gl_Position = MVP * finalModelPos;
outNorm = finalNormal.xyz;

outUVs = vertex_UV;
}
sksBuff只是一个胶点

我在每个经过的渲染/帧中用新值填充该数组,这些值是关节的新变换。我是这样做的:

    glGenBuffers(1, &sksBuff);
glBindBuffer(GL_UNIFORM_BUFFER, sksBuff);
// bind buffer to work further with it...
// allocate memory for the buffer in the GPU
glBufferData(GL_UNIFORM_BUFFER, sizeof(skelShader), NULL, GL_STATIC_DRAW);
// because we hard-coded "binding=3" in the shader code we can do this:
// bind Uniform Buffer to binding point 3 (without caring about index of UBO)
glBindBufferBase(GL_UNIFORM_BUFFER, 4, sksBuff);
// good practice, unbind buffer
glBindBuffer(GL_UNIFORM_BUFFER, 0);
    for (int i = 0; i < skeleton.size(); i++) {

    globalSkelInfo.currentJointTrans[i] = skeleton[i]->transformMat[currentFrame - 1] * skeleton[i]->globalBindPosMat;

}
#version 440

const int maxJoints = 100;
const int maxWeights = 4;

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_UV;
layout(location = 2) in vec3 vertex_normal;

layout(location = 3) in vec4 vertex_weight;
layout(location = 4) in ivec4 vertex_controllers;


out vec2 outUVs;
out vec3 outNorm;

layout(binding = 3 , std140) uniform uniformBlock
{
    vec3 camPos;
    mat4 world;
    mat4 LookAt;
    mat4 projection;
    mat4 MVP;
};

layout(binding = 4 , std140) uniform animationStruct
{
    mat4 currentJointTrans[maxJoints];
};

void main() {


vec4 finalModelPos = vec4(0.0);
vec4 finalNormal = vec4(0.0);

for (int i = 0; i < 4; i++) {

    mat4 jointTrans = currentJointTrans[vertex_controllers[i]];
    vec4 posePos = jointTrans * vec4(vertex_position, 1.0);
    finalModelPos += posePos * vertex_weight[i];

    vec4 worldNormal = jointTrans * vec4(vertex_normal, 0.0);
    finalNormal += worldNormal * vertex_weight[i];

}

gl_Position = MVP * finalModelPos;
outNorm = finalNormal.xyz;

outUVs = vertex_UV;
}
for(int i=0;itransformMat[currentFrame-1]*骨架[i]>globalBindPosMat;
}
这对根关节正常工作,但其余关节/网格仍保持绑定姿势。问题应该在我更新阵列的地方。目前,在完成每个关节的乘法后,我在渲染函数中这样做:

    for (int i = 0; i < skeleton.size(); i++) {
    glUniformMatrix4fv(glGetUniformLocation(aShaderProgram, ("currentJointTrans[" + std::to_string(i) + "]").c_str()),
        1, GL_FALSE, glm::value_ptr(globalSkelInfo.currentJointTrans[i]));
}
for(int i=0;i
在这之后我画画。根关节值似乎正确移动,但网格的其余部分处于bindpose且不移动。在顶点着色器中,我尝试如下更新矩阵:

    glGenBuffers(1, &sksBuff);
glBindBuffer(GL_UNIFORM_BUFFER, sksBuff);
// bind buffer to work further with it...
// allocate memory for the buffer in the GPU
glBufferData(GL_UNIFORM_BUFFER, sizeof(skelShader), NULL, GL_STATIC_DRAW);
// because we hard-coded "binding=3" in the shader code we can do this:
// bind Uniform Buffer to binding point 3 (without caring about index of UBO)
glBindBufferBase(GL_UNIFORM_BUFFER, 4, sksBuff);
// good practice, unbind buffer
glBindBuffer(GL_UNIFORM_BUFFER, 0);
    for (int i = 0; i < skeleton.size(); i++) {

    globalSkelInfo.currentJointTrans[i] = skeleton[i]->transformMat[currentFrame - 1] * skeleton[i]->globalBindPosMat;

}
#version 440

const int maxJoints = 100;
const int maxWeights = 4;

layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_UV;
layout(location = 2) in vec3 vertex_normal;

layout(location = 3) in vec4 vertex_weight;
layout(location = 4) in ivec4 vertex_controllers;


out vec2 outUVs;
out vec3 outNorm;

layout(binding = 3 , std140) uniform uniformBlock
{
    vec3 camPos;
    mat4 world;
    mat4 LookAt;
    mat4 projection;
    mat4 MVP;
};

layout(binding = 4 , std140) uniform animationStruct
{
    mat4 currentJointTrans[maxJoints];
};

void main() {


vec4 finalModelPos = vec4(0.0);
vec4 finalNormal = vec4(0.0);

for (int i = 0; i < 4; i++) {

    mat4 jointTrans = currentJointTrans[vertex_controllers[i]];
    vec4 posePos = jointTrans * vec4(vertex_position, 1.0);
    finalModelPos += posePos * vertex_weight[i];

    vec4 worldNormal = jointTrans * vec4(vertex_normal, 0.0);
    finalNormal += worldNormal * vertex_weight[i];

}

gl_Position = MVP * finalModelPos;
outNorm = finalNormal.xyz;

outUVs = vertex_UV;
}
#版本440
常量int maxJoints=100;
const int maxWeights=4;
vec3顶点位置的布局(位置=0);
vec2顶点中的布局(位置=1);
vec3顶点_法线中的布局(位置=2);
vec4顶点权重中的布局(位置=3);
ivec4 vertex_控制器中的布局(位置=4);
输出vec2输出uvs;
3例失范;
布局(装订=3,std140)统一单块
{
vec3坎波斯;
mat4世界;
mat4注视;
mat4投影;
mat4mvp;
};
布局(绑定=4,std140)统一动画结构
{
mat4 currentJointTrans[maxJoints];
};
void main(){
vec4最终模型=vec4(0.0);
vec4最终正常值=vec4(0.0);
对于(int i=0;i<4;i++){
mat4 jointTrans=当前jointTrans[顶点控制器[i];
vec4 posePos=jointTrans*vec4(顶点位置,1.0);
finalModelPos+=posePos*顶点权重[i];
vec4 worldNormal=jointTrans*vec4(顶点_法线,0.0);
最终法线+=世界法线*顶点权重[i];
}
gl_位置=MVP*最终模型;
outNorm=最终正常值.xyz;
outUVs=顶点_UV;
}

我的理论是用我的currentJointTrans数组更新struct skelShader是不正确的。有没有关于如何执行此操作的提示?

glUniform*
调用无法在中设置数据。实际上,统一缓冲区的全部要点是统一数据来自缓冲区对象。这就是为什么你必须创造一个


因此,如果要为统一块设置统一数据,请将该数据设置到缓冲区对象中。

谢谢您的帮助!你说的话很有用,让我更仔细地研究了一下。我这样做就解决了这个问题:
for(inti=0;I<100;I++){glUniformMatrix4fv(glGetUniformLocation(aShaderProgram,(“currentJointTrans[“+std::to_string(I)+“]).c_str 1,GL_FALSE,glm::value_ptr(currentJointTrans[I]);glm::mat4 test=currentJointTrans[I]}
@Haplue:这不可能解决它,因为您无法通过
glUniform
调用设置统一块数据。如果这样做有效的话,那要么是因为你停止使用统一的块体,要么是纯粹的意外。那些
glGetUniformLocation
调用中的每一个都应该返回-1。对不起,我很忙,所以我忘了提到我在glsl顶点着色器中将mat4设置为仅一个unifom mat4,没有结构之类的。最近发生了很多事情,所以我真的希望我没有忘记提及我改变的其他事情。我再次道歉,谢谢你!