OpenGL无法从我的顶点数组

时间:2015-08-10 11:14:20

标签: opengl graphics glsl shader

使用OpenGL着色器,我想在屏幕上绘制一个三角形,其中顶点颜色在顶点坐标旁边的数据结构中指定。该结构每个顶点有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
    };

然后告诉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)));

然后告诉我的顶点着色器读取坐标和颜色:

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

但是,无论我使用什么值作为颜色分量,三角形总是以红色绘制。更改结构中的坐标会影响图像,但更改结构中的颜色不会产生任何效果。

我认为这是我的C ++代码的问题,而不是着色器代码,因为我调试了着色器,它总是读取(1.0,0.0,0.0,1.0)颜色,即使我正在通过每个顶点都有(0.0,0.0,1.0,1.0)。

关于我做错的任何想法?

这是我的完整代码:

#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();
}

这是我的着色器代码:

// 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;
}

1 个答案:

答案 0 :(得分:2)

我现在无法调试您的代码,但根据我在此处看到的内容,您忘记启用第二个属性数组。请参阅this example以供参考。 但即使我错了,我也想指出你在代码中遇到的一些不好的做法。你使用的是GL 3.3,这很好。这是现代的OpenGL基线。但是你仍在混合旧的API(前3.3)新的。从最后:

在片段着色器中,您应该使用自定义输出属性而不是gl_FragColor中内置的GLSL。

 #version 330

 in smooth vec4 frag_colour;
 out vec4 frag_out;

 void main()
 {
    frag_out = frag_colour;
 }

现在,关于你的OpenGL命令。你不应该直接绑定顶点缓冲区,而是使用VAO并将它绑定到上下文。事实上,一些驱动程序版本(我在NVIDIA上经历过)根本不产生渲染结果VAO不与核心配置文件一起使用。