简体   繁体   English

OpenGL无法从我的顶点数组正确读取颜色

[英]OpenGL does not read the colour correctly from my vertex array

With OpenGL shaders, I want to draw a triangle on the screen, where the vertex colours are specified in the data structure alongside the vertex coordinates. 使用OpenGL着色器时,我想在屏幕上绘制一个三角形,其中顶点颜色在数据结构中与顶点坐标一起指定。 The structure has 7 floats for each vertex -- 3 for coordinates, followed by 4 for colour: 该结构的每个顶点有7个浮点-3个坐标,然后是4个颜色:

static std::vector<GLfloat> vertices = {
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
    };

I then tell OpenGL how to interpret this structure by using glVertexAttribPointer(): 然后,我告诉OpenGL如何使用glVertexAttribPointer()解释此结构:

// Vertex coordinates
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
// Vertex colour
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));

And then tell my vertex shader to read the coordinates and colour: 然后告诉我的顶点着色器读取坐标和颜色:

layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;

However, no matter what values I use for the colour component, the triangle is always drawn in red. 但是,无论我为颜色分量使用什么值,三角形始终以红色绘制。 Changing the coordinates in the structure affects the image as expected, but changing the colour in the structure does nothing. 更改结构中的坐标会按预期影响图像,但是更改结构中的颜色则无效。

I believe that this is a problem with my C++ code, rather than the shader code, because I have debugged the shader and it is always reading (1.0, 0.0, 0.0, 1.0) for the colour, even though I am passing it (0.0, 0.0, 1.0, 1.0) for each vertex. 我相信这是我的C ++代码而不是着色器代码的问题,因为我已经调试了着色器,并且即使我传递了(0.0,0.0,0.0,0.0,1.0,1.0)颜色也总是读取(1.0,0.0,0.0,1.0) ,0.0、1.0、1.0)。

Any ideas on what I'm doing wrong? 关于我在做什么错的任何想法吗?

Here is my complete code: 这是我完整的代码:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <assert.h>
#include <vector>

#include <GL/glew.h>
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/ext.hpp>

GLuint buffer;
GLuint projection_matrix_location;
GLuint view_matrix_location;
glm::mat4 view_matrix;
glm::mat4 projection_matrix;
int num_vertices = 0;

static void RenderScene()
{
    // Clear the buffers.
    glClear(GL_COLOR_BUFFER_BIT);
    glClear(GL_DEPTH_BUFFER_BIT);

    // Set the matrices
    glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(projection_matrix));
    glUniformMatrix4fv(view_matrix_location, 1, GL_FALSE, glm::value_ptr(view_matrix));

    // Specify how to read the vertex buffer
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    // Vertex coordinates
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), 0);
    // Vertex colour
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3 * sizeof(float)));

    // Draw the vertex buffer
    glDrawArrays(GL_TRIANGLES, 0, num_vertices);
    glDisableVertexAttribArray(0);

    // Swap the buffers
    glutSwapBuffers();
}

static void MakeBuffers()
{
    // Set the vertices
    static std::vector<GLfloat> vertices = {
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
    };
    num_vertices = (1.0 / 7.0) * vertices.size();

    // Fill the buffer with the vertices
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, num_vertices * 7 * sizeof(GL_FLOAT), &vertices[0], GL_STATIC_DRAW);
}


static GLuint MakeShader(GLenum shader_type, std::string shader_filename)
{
    // Load the source code
    std::ifstream file_in;
    file_in.open(&shader_filename[0]);
    std::stringstream file_stream;
    file_stream << file_in.rdbuf();
    std::string file_string = file_stream.str();
    const GLchar* ptr_file_string = &file_string[0];
    const GLchar** ptr_file_strings = &ptr_file_string;
    int string_lengths[] = {(int)file_string.length()};

    // Compile the shader
    GLuint shader = glCreateShader(shader_type);
    glShaderSource(shader, 1, ptr_file_strings, &string_lengths[0]);
    glCompileShader(shader);

    // Check
    GLint is_success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &is_success);
    if (!is_success)
    {
        std::cerr << "Error" << std::endl;
        return -1;
    }

    return shader;
}


static void MakeShaderProgram()
{
    // Make the shaders
    GLuint vertex_shader = MakeShader(GL_VERTEX_SHADER, "../src/vertex-shader.glsl");
    GLuint fragment_shader = MakeShader(GL_FRAGMENT_SHADER, "../src/fragment-shader.glsl");

    // Create the program
    GLuint program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);

    // Check
    GLint is_success = 0;
    glGetProgramiv(program, GL_LINK_STATUS, &is_success);
    if (!is_success)
    {
        std::cout << "Error" << std::endl;
        return;
    }
    glValidateProgram(program);
    glGetProgramiv(program, GL_VALIDATE_STATUS, &is_success);
    if (!is_success)
    {
        std::cout << "Error" << std::endl;
        return;
    }

    // Use the program
    glUseProgram(program);

    // Get the location of the uniform variables
    view_matrix_location = glGetUniformLocation(program, "view_matrix");
    assert(view_matrix_location != 0xFFFFFFFF);
    projection_matrix_location = glGetUniformLocation(program, "projection_matrix");
    assert(projection_matrix_location != 0xFFFFFFFF);
}


int main(int argc, char** argv)
{
    // Initialize GLUT
    glutInit(&argc, argv);

    // Configure some GLUT display options:
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

    // Specify the GLUT window parameters and create the window
    glutInitWindowSize(1000, 750);
    glutInitWindowPosition(500, 200);
    glutCreateWindow("Test");

    // Specify the display callback
    glutDisplayFunc(RenderScene);

    // Initialize GLEW, which must be done after GLUT is initialized.
    GLenum glut_result = glewInit();
    if (glut_result != GLEW_OK)
    {
        std::cout << "Error" << std::endl;
        return -1;
    }

    // Set the clear colour.
    glClearColor(0.5f, 0.5f, 0.5f, 0.0f);

    // Enable depth testing so that only the nearest vertex is sent to the colour buffer (also needed to read the depth of each pixel using glReadPixels())).
    glEnable(GL_DEPTH_TEST);

    // Make the vertex and index buffers.
    MakeBuffers();

    // Make the shader program.
    MakeShaderProgram();

    // Create the view matrix.
    glm::vec3 eye(0.0f, 0.0f, -3.0f);
    glm::vec3 centre(0.0f, 0.0f, 0.0f);
    glm::vec3 up(0.0f, 1.0f, 0.0f);
    view_matrix = glm::lookAt(eye, centre, up);

    // Create the projection matrix.
    float fov_y = 45.0;
    float aspect_ratio = 1.5;
    float near_clip = 1;
    float far_clip = 1000;
    projection_matrix = glm::perspective(fov_y, aspect_ratio, near_clip, far_clip);

    // Start the GLUT internal loop.
    glutMainLoop();
}

And here is my shader code: 这是我的着色器代码:

// Vertex shader

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec4 vertex_colour;

uniform mat4 projection_matrix;
uniform mat4 view_matrix;

out vec4 frag_colour;

void main()
{
    gl_Position = projection_matrix * view_matrix * vec4(position, 1.0f);
    frag_colour = vertex_colour;
}


// Fragment shader

#version 330

in vec4 frag_colour;

void main()
{
    gl_FragColor = frag_colour;
}

I can't debug your code now,but based on what I see here you forgot to enable second attribute array.See this example for reference. 我现在无法调试您的代码,但是基于我在此处看到的内容,您忘记启用第二个属性数组。请参见此示例以供参考。 But even if I am wrong,I would like to point you to some bad practices you have in your code.You are using GL 3.3 which is good.This is modern OpenGL baseline.But you are still mixing old API (pre 3.3) with the new one.From the end: 但是,即使我错了,我还是想向您指出代码中的一些错误做法。您使用的是GL 3.3,这很好。这是现代的OpenGL基准。但是您仍然将旧的API(3.3之前的版本)与新的从最后开始:

In your fragment shader you should use custom output attribute rather than the GLSL built in gl_FragColor. 在片段着色器中,应该使用自定义输出属性,而不要使用gl_FragColor内置的GLSL。

 #version 330

 in smooth vec4 frag_colour;
 out vec4 frag_out;

 void main()
 {
    frag_out = frag_colour;
 }

Now,regarding your OpenGL commands.You shouldn't bind vertex buffers directly but use VAO and bind it to the context.In fact some driver version (I experienced on NVIDIA) produce no rendering results at all when VAO is not used with core profile. 现在,关于您的OpenGL命令。您不应该直接绑定顶点缓冲区,而应使用VAO并将其绑定到上下文。实际上,当不将VAO与核心配置文件一起使用时,某些驱动程序版本(我在NVIDIA上经验丰富)完全不会产生渲染结果。 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM