【问题标题】:OpenGL4 Shader (#version 410) unexpected behaviourOpenGL4 着色器 (#version 410) 意外行为
【发布时间】:2017-04-08 18:14:38
【问题描述】:

我有一个问题,想弄清楚我最简单的着色器中发生了什么。这是我的顶点着色器:

#version 410 core

in vec3 position;
in vec2 textureCoords;
out vec2 color;

void main(void)
{

    gl_Position = vec4(position.x, position.y, position.z, 1.0);
    color = vec2(1.0,0.5);
}

片段着色器:

#version 410 core

in vec2 color;
out vec4 out_color;

void main(void)
{
    out_color = vec4(0.0, 1.0, 0.0, 1.0);
}

注意,从 VS 传递到 FS 的颜色变量实际上并没有做任何事情。这些着色器给了我预期的结果,如下图:

现在,如果我只是使用颜色变量将 textureCoords 从 VS 传递到 FS,而不对 FS 进行任何更改,它会将我的图像向右移动。所以修改后的 VS(以及对着色器的唯一修改)是:

#version 410 core

in vec3 position;
in vec2 textureCoords;
out vec2 color;

void main(void)
{
    gl_Position = vec4(position.x, position.y, position.z, 1.0);
    color = textureCoords;
}

这会产生意想不到的以下渲染(三角形向右上方移动):

我不明白为什么会这样,因为我什至没有在 FS 中使用颜色变量。

为什么会这样?我只是想将 vec2 传递给 FS !我在这里没有看到什么?

以下是一些附加信息: 总帐信息: 支持的GL版本:4.1 NVIDIA-10.16.34 355.10.05.35f05 支持的着色语言:4.10

完整代码在这里: complete code 入口点是tests.cpp

这是我当前的顶点数组:

GLfloat PossibleVertices[] = {
    // Left bottom triangle
     0.0f,  0.5f, 0.0f, // v0
    -0.5f,  -0.5f, 0.0f, // v1
     0.5f,  -0.5f, 0.0f
};

GLuint Indices[] = {
    0, 1, 2
};

GLfloat TextureCoords[] = 
{
    0.5f, 1.0f, // v0
    0.0f, 0.0f, // v1
    1.0f, 0.0f
};

// Load data to VAO
LoadToVAO(PossibleVertices, 9, Indices, 3, TextureCoords, 6);

... 

LoadToVAO
(
    GLfloat Positions[], GLuint PosArrySize,
    GLuint Indices[], GLuint IndArrySize,
    GLfloat TexCoords[], GLuint TCArrySize
)
{
    GLuint VaoID = CreateVAO();
    BindIndicesBufferVBO(Indices, IndArrySize); // Buffer Index - optimization
    StoreDataInAttrList(0, 3, Positions, PosArrySize);
    StoreDataInAttrList(1, 2, TexCoords, TCArrySize);
    UnbindVAO();
    CGCore::RawModel* ret = new CGCore::RawModel(VaoID, IndArrySize);
    return ret;
}

这是实际将数据存储到 VAO 的函数。调用两个顶点数组:

void CGCore::Loader::StoreDataInAttrList(GLuint AttrNumber, GLuint AttrSize, GLfloat Data[], GLuint DataSize)
{
    GLuint VboID; 
    glGenBuffers(1,&VboID);
    VBOContainer.push_back(VboID);
    glBindBuffer(GL_ARRAY_BUFFER, VboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*DataSize, Data, GL_STATIC_DRAW);
    glVertexAttribPointer(AttrNumber, AttrSize, GL_FLOAT, GL_FALSE, 0, (void*) 0); // write to VAO
    glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind current VBO
}

这里是attr绑定代码:

void BindAttributes()
{
    BindAttribute(0, "position");
    BindAttribute(1, "textureCoords"); 
}

// and also ... 

void BindAttribute(int Attrib, const GLchar* VarName)
{
    glBindAttribLocation(ProgramID, Attrib, VarName);
}

最后是渲染代码:

void CGCore::Renderer::Render(CGCore::TexturedModel* TexturedModelObj)
{
    CGCore::RawModel* Model = TexturedModelObj->GetModel();
    glBindVertexArray(Model->GetVaoID());
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glActiveTexture(GL_TEXTURE0);
    glDrawElements( GL_TRIANGLES, Model->GetVertexCount(), GL_UNSIGNED_INT, (void*) 0);
    glBindTexture(GL_TEXTURE_2D, TexturedModelObj->GetTexture()->GetTextureID());
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glBindVertexArray(0);
}

抱歉,帖子太长了。谢谢!

【问题讨论】:

  • 请出示图纸代号。我的猜测是你搞砸了数据或属性指针。
  • 我在 github 链接中编辑了绘图代码。但是,如果没有任何 vec2 被以任何方式使用,如何将 in vec2 分配给 out vec2 移动顶点?为什么不赞成它是合法的 q?
  • 例如,属性位置可能存在问题。如果您不在 VS 中使用textureCoords,则它处于非活动状态,将被优化掉。现在,当您使用它时,它会处于活动状态,并将获得分配的位置。如果您没有在代码中正确处理这些位置,您可能会绘制其他内容。
  • 我从数组的实际传递中添加了代码!我希望这对现在更有帮助
  • 你在调用那个 AFTER 链接。这仅在调用 BEFORE 链接时调用影响位置。请在此处发布所有相关代码。我不会再在你的 repo 中查找内容了。

标签: c++ opengl fragment-shader vertex-shader opengl-4


【解决方案1】:

经过试验,查阅了大量的 OpenGL 文档等,我终于解决了我的问题。与某些 cmets 不同,问题出在顶点着色器中。 IE。 in 变量的声明。 VS 中的以下更改给了我预期的输出:

#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 textureCoords;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(position, 1.0f);
    TexCoord = textureCoords;
}

所以我正在做的是在声明 in 参数时明确指定 in 参数在 VOA 中的位置。我想这与顶点着色器的版本(v4.10)有关,但我不确定。在任何情况下,通过在类型 var_name 中声明类似 layout (location = X) 的 in var 来指定 attr 位置

【讨论】:

  • 您得出错误的结论。 @BDL 的 cmets 很到位。您可以通过使用另一种方法来指定这些位置来解决glBindAttribLocation 的错误用法这一事实并不意味着使用glBindAttribLocation 是错误的,或者GLSL 4.10 在这方面的行为有所不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
相关资源
最近更新 更多