无法读取传递给顶点着色器的值

Cannot Read Values Passed to Vertex Shader

我正在努力研究 OpenGL 中各种类型的 GLSL 着色器。 目前,我正在为 2d layered-tile 实现而苦苦挣扎。出于某种原因,传递到我的着色器中的 int 值始终为 0(或更可能为 null)。

我目前有一个由 20x20 块组成的 2048x2048px 二维纹理。我正在尝试用它对一个四边形进行纹理化,并根据我传递给顶点着色器的整数块更改图块的索引。

我正在为四边形的位置传递一个 vec2 浮点数(实际上是一个 TRIANGLE_STRIP)。我还试图传递 6 个整数,它们将代表 6 层瓷砖。

我的输入:

// Build and compile our shader program
Shader ourShader("b_vertex.vertexShader", "b_fragment.fragmentShader");

const int floatsPerPosition = 2;
const int intsPerTriangle = 6;
const int numVertices = 4;
const int sizeOfPositions = sizeof(float) * numVertices * floatsPerPosition;
const int sizeOfColors = sizeof(int) * numVertices * intsPerTriangle;
const int numIndices = 4;
const int sizeOfIndices = sizeof(int) * numIndices;

float positions[numVertices][floatsPerPosition] =
{
    { -1, 1 },
    { -1, -1 },
    { 1, 1 },
    { 1, -1 },
};

// ints indicating Tile Index
int colors[numVertices][intsPerTriangle] =
{
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
};

// Indexes on CPU
int indices[numVertices] =
{
    0, 1, 2, 3,
}; 

我的设置:

GLuint vao, vbo1, vbo2, ebo; // Identifiers of OpenGL objects

glGenVertexArrays(1, &vao); // Create new VAO
                            // Binded VAO will store connections between VBOs and attributes
glBindVertexArray(vao);

glGenBuffers(1, &vbo1); // Create new VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo1); // Bind vbo1 as current vertex buffer
                                     // initialize vertex buffer, allocate memory, fill it with data
glBufferData(GL_ARRAY_BUFFER, sizeOfPositions, positions, GL_STATIC_DRAW);
// indicate that current VBO should be used with vertex attribute with index 0
glEnableVertexAttribArray(0);
// indicate how vertex attribute 0 should interpret data in connected VBO
glVertexAttribPointer(0, floatsPerPosition, GL_FLOAT, GL_FALSE, 0, 0);

glGenBuffers(1, &vbo2); // Create new VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo2); // Bind vbo2 as current vertex buffer
                                     // initialize vertex buffer, allocate memory, fill it with data
glBufferData(GL_ARRAY_BUFFER, sizeOfColors, colors, GL_STATIC_DRAW);
// indicate that current VBO should be used with vertex attribute with index 1
glEnableVertexAttribArray(1);
// indicate how vertex attribute 1 should interpret data in connected VBO
glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0);

// Create new buffer that will be used to store indices
glGenBuffers(1, &ebo);
// Bind index buffer to corresponding target
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
// ititialize index buffer, allocate memory, fill it with data
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfIndices, indices, GL_STATIC_DRAW);

// reset bindings for VAO, VBO and EBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);



// Load and create a texture 
GLuint texture1 = loadBMP_custom("uvtemplate3.bmp");

GLuint texture2 = loadBMP_custom("texture1.bmp");

我的抽奖:

// Game loop
while (!glfwWindowShouldClose(window))
{
    // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
    glfwPollEvents();

    // Render
    // Clear the colorbuffer
    glClearColor(1.f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // Activate shader
    ourShader.Use();

    // Bind Textures using texture units
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);

    //add some cool params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    float borderColor[] = { 0.45f, 0.25f, 0.25f, 0.25f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);

    // Draw container
    //glBindVertexArray(VAO);
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(vao);
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glDrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_INT, NULL);

    glBindVertexArray(0);

    // Swap the screen buffers
    glfwSwapBuffers(window);
}

我的着色器绝对有效,因为我可以通过硬编码来调整输出 来自顶点着色器的值。我怀疑我没有正确/以正确的格式传递值,或者没有在某处指示每个顶点需要包含 int[6]。

我无法从 int Base[6] 中的布局(位置 = 1)中读取任何内容;我已经尝试了几乎所有我能想到的方法。单独声明每个 int,尝试读取两个 ivec3、uint 以及我能想到的其他任何东西,但一切都以 0 返回。

为了完整性,以下是我的顶点和片段着色器:

#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in int Base[6];

out vec2 TexCoord;
out vec2 TexCoord2;
out vec2 TexCoord3;
out vec2 TexCoord4;
out vec2 TexCoord5;
out vec2 TexCoord6;

//  0.5f,  0.5f,// 0.0f,   118.0f, 0.0f, 0.0f,   0.0f, 0.0f, // Top Right
//  0.5f, -0.5f,// 0.0f,   118.0f, 1.0f, 0.0f,   0.0f,0.009765625f, // Bottom Right
//  -0.5f, -0.5f,// 0.0f,   118.0f, 0.0f, 1.0f,   0.009765625f, 0.009765625f, // Bottom Left
//  -0.5f,  0.5f//, 0.0f,   118.0f, 1.0f, 0.0f,   0.009765625f, 0.0f  // Top Left 

void main()
{

int curBase = Base[5];

int curVertex = gl_VertexID % 4;
vec2 texCoord = (curVertex == 0?
vec2(0.0,0.0):(
curVertex == 1?
vec2(0.0,0.009765625):(
curVertex == 2?
vec2(0.009765625,0.0):(
curVertex == 3?
vec2(0.009765625,0.009765625):(
vec2(0.0,0.0)))))
);
gl_Position = vec4(position, 0.0f, 1.0f);

TexCoord = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
//curBase = Base+1;
TexCoord2 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
//curBase = Base+2;
TexCoord3 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
}

片段:

#version 330 core
//in vec3 ourColor;
in vec2 TexCoord;
in vec2 TexCoord2;
in vec2 TexCoord3;
in vec2 TexCoord4;
in vec2 TexCoord5;
in vec2 TexCoord6;

out vec4 color;

// Texture samplers
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
color = (texture(ourTexture2, TexCoord )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord2 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord3 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord4 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord5 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord6 )== vec4(1.0,0.0,1.0,1.0)?
    vec4(0.0f,0.0f,0.0f,0.0f)
:texture(ourTexture2, TexCoord6 ))
:texture(ourTexture2, TexCoord5 ))
:texture(ourTexture2, TexCoord4 ))
:texture(ourTexture2, TexCoord3 ))
:texture(ourTexture2, TexCoord2 ))
:texture(ourTexture2, TexCoord ));
}

这在两个不同的方面是错误的:

glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0);

GL 中的顶点属性可以是标量或 2 到 4 个分量的向量。因此,glVertexAttribPointersize 参数可以取值 1、2、3 或 4。使用不同的值 (intsPerTriangle == 6) 意味着调用将只生成一个 GL_INVALID_VALUE 错误并且没有其他效果,所以你甚至没有设置指针。

如果你想为每个顶点传递 6 个值,你可以使用 6 个不同的标量属性(消耗 6 个属性槽),或者将其打包到一些向量中,例如 2 个 3d 向量(仅消耗 2 个槽)。无论您选择什么包装,您都需要为每个正在使用的属性插槽设置适当的属性指针。

但是,glVertexAttribPointer 也是您用例的错误函数。它正在定义 浮点 属性,这些属性必须在着色器中具有匹配的声明 float/vec*。您可以输入 GL_INT 的事实仅意味着 GPU 可以为您即时转换为浮点数。

如果你想使用 intivec(或它们的未签名对应物)属性,你必须使用 glVertexAttribIPointer(注意 I 在该函数名称中)设置属性时。