OpenGL将颜色发送到着色器

OpenGL send color to shader

本文关键字:颜色 OpenGL      更新时间:2023-10-16

我正在学习以下教程:http://www.opengl-tutorial.org自己尝试了一些事情。

目前,我的程序可以创建三角形作为类对象,变换它们的大小和位置,并为它们设置动画(我只是在玩非常简单的代码)。但是,当我尝试将"缓冲区阵列"的颜色值传递给着色器时,我的三角形不会进行渲染。

我会在这里传递相关代码,并努力使其易于理解,希望有人能在这里帮助我!

代码:

#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
using namespace glm;
#include "loadShader.h"
#include "model.h"
int _screenWidth = 1024;
int _screenHeight = 768;

int main()
{
    //START GLFW
    if (!glfwInit())
    {
        fprintf(stderr, "Failed to initialize GLFWn");
        return -1;
    }
    //GLFW SETTINGS
    glfwWindowHint(GLFW_SAMPLES, 4); //4x antialiasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //OPENGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Mac compatible?
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    //open window                                                              
    GLFWwindow* window;
    window = glfwCreateWindow(_screenWidth, _screenHeight, "Tutorial 01", NULL, NULL);
    if (window == NULL) {
        fprintf(stderr, "Failed to open GLFW window. Make sure your GPU is openGL 3.3 compatible!n");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    //INITIALIZE GLEW
    glewExperimental = true; //needed in core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW.n");
        return -1;
    }
    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    glClearColor(0.125f, 0.0f, 0.3725f, 0.0f);
    //Enable Depth test
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
    // Create and compile GLSL program from the shaders
    GLuint programID = LoadShaders("Shaders/vertexShaders.vert", "Shaders/fragmentShaders.frag");
    //get handle for MVP uniform
    GLuint MatrixID = glGetUniformLocation(programID, "MVP");

    /////////////////////
    //MODEL//////////////
    /////////////////////
    //two triangles
    int nVertices = 6;
    //created through model class
    model object1, object2;
    object1.createTriangle();
    object2.createTriangle();
    //initialize buffer data arrays
    GLfloat g_vertex_buffer_data[12*3];    
    // One color for each vertex
    static const GLfloat g_color_buffer_data[] = {
        0.583f,  0.771f,  0.014f,
        0.609f,  0.115f,  0.436f,
        0.327f,  0.483f,  0.844f,
        0.822f,  0.569f,  0.201f,
        0.435f,  0.602f,  0.223f,
        0.310f,  0.747f,  0.185f };
    //////////////////////////
    //////////////////////////
    //////////////////////////
    //CREATE BUFFER
    //This will identify our vertex and color buffer
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    GLuint colorbuffer;
    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    //counters
    float time          = 0.0f;
    int counter         = 0;
    int counterStep     = 100;

    do {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        time        = time + 0.01;
        counter     = counter + 1;

        //TRANSFORM MY TRIANGLES (its working)
        glm::vec3 rotationAxis(0.0f, 0.0f, 1.0f);
        glm::vec3 translation(0.0f, 0.0f, 0.025f);
        float rotationAngle = 0.25f;
        object1.rotate(rotationAngle, rotationAxis);
        //object2.rotate(0.5*rotationAngle, rotationAxis);
        object1.translate(translation);
        //Update coordinates in vertex buffer (both triangles)
        for (int i = 0; i < 3; i++)
        {
            g_vertex_buffer_data[i * 3]         = object1.transformedPosition[i].x;
            g_vertex_buffer_data[i * 3 + 1]     = object1.transformedPosition[i].y;
            g_vertex_buffer_data[i * 3 + 2]     = object1.transformedPosition[i].z;
        }
        for (int i = 0; i < 3; i++)
        {
            g_vertex_buffer_data[i * 3 + 9]     = object2.transformedPosition[i].x;
            g_vertex_buffer_data[i * 3 + 10]    = object2.transformedPosition[i].y;
            g_vertex_buffer_data[i * 3 + 11]    = object2.transformedPosition[i].z;
        }

        //Model matrix
        glm::mat4 modelM = glm::mat4(1.0f);
        //Projection matrix:
        glm::mat4 projectionM = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
        //Camera matrix:
        glm::mat4 viewM = lookAt(
            glm::vec3(8, 2, 2+10*time),
            glm::vec3(0, 0, 0),
            glm::vec3(0, 1, 0));
        //MODEL VIEW PROJECTION MATRIX:
        glm::mat4 mvpM = projectionM * viewM * modelM;
        //Give our vertices and colors to OpenGL
        glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
        glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
        /////////////////////////////////////////////
        //USE SHADERS
        glUseProgram(programID);
        //Send our transformation to the currently bound shader, MVP uniform
        glUniformMatrix4fv(MatrixID, 1, 0, &mvpM[0][0]);
        //1rst attribute buffer: vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,          //attribute 0, no particular reason, but must match the layout in the shader
            3,          //size
            GL_FLOAT,   //type
            GL_FALSE,   //normalized?
            0,          //stride
            (void*)0    //array buffer offset
            );
        //2nd attribute buffer: colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
        glVertexAttribPointer(
            1,          //attribute number
            3,          //size
            GL_FLOAT,   //type
            GL_FALSE,   //normalized?
            0,          //stride
            (void*)0    //array buffer offset
            );

        //Draw the triangle
        glDrawArrays(GL_TRIANGLES, 0, nVertices); //Starting from vertex 0; 3 vertices total
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);


    // Cleanup VBO
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteBuffers(1, &colorbuffer);
    glDeleteProgram(programID);
    glDeleteVertexArrays(1, &VertexArrayID);
    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;
}

Vertexshader:

#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
uniform mat4 MVP;
out vec3 fragmentColor;
void main(){
    gl_Position = MVP * vec4(vertexPosition_modelspace,1.0);
    fragmentColor = vertexColor;
}   

碎片整理器:

#version 330 core
in vec3 fragmentColor;
out vec3 color;

void main(){
    color = fragmentColor;
}

如果我删除:

glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);

和:

        //2nd attribute buffer: colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
        glVertexAttribPointer(
            1,          //attribute number
            3,          //size
            GL_FLOAT,   //type
            GL_FALSE,   //normalized?
            0,          //stride
            (void*)0    //array buffer offset
            );

从主函数中,三角形进行渲染。

编辑这里只有相关的代码,这是我认为有问题的地方:

    //FIRST DO THIS: (but not sure why..)
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
    //initialize buffer data arrays
    GLfloat g_vertex_buffer_data[]  = { something };
    GLfloat g_color_buffer_data[]   = { something };
    //CREATE BUFFER
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    GLuint colorbuffer;
    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    //LOOP
    do {
        //UPDATE BUFFER DATA
        GLfloat g_vertex_buffer_data[]  = { something new };
        GLfloat g_color_buffer_data[]   = { something new };
        //SEND NEW BUFFER DATA TO SHADERS
        glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
        glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
        //USE SHADERS
        glUseProgram(programID);
        //1rst attribute buffer: vertices positions
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,          //attribute 0, no particular reason, but must match the layout in the shader
            3,          //size
            GL_FLOAT,   //type
            GL_FALSE,   //normalized?
            0,          //stride
            (void*)0    //array buffer offset
            );
            //2nd attribute buffer: colors
            glEnableVertexAttribArray(1);
            glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
            glVertexAttribPointer(
                1,          //attribute number
                3,          //size
                GL_FLOAT,   //type
                GL_FALSE,   //normalized?
                0,          //stride
                (void*)0    //array buffer offset
                );
        //Draw the triangles
        glDrawArrays(GL_TRIANGLES, 0, nVertices); //Starting from vertex 0; 3 vertices total
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);


    // Cleanup VBO
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteBuffers(1, &colorbuffer);
    glDeleteProgram(programID);
    glDeleteVertexArrays(1, &VertexArrayID);
    // Close OpenGL window and terminate GLFW
    glfwTerminate();
    return 0;
}

解决方案

我通过看这个教程解决了我的问题https://www.opengl.org/wiki/Tutorial2%3a_VAOs、_VBOs、_Vertex和_Fragment_Shaders_%28C_SDL%29。

基本上,我只是将bufferBinding和bufferData函数移到了循环之外。不知怎么的,以前顶点位置是可以的,但顶点颜色不是。。。

我阅读和学习了更多,并更改了一些代码,现在它正在工作,我现在对此感到满意:)

在缓冲数据之前,您应该绑定要发送数据的缓冲区。

应该是

 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); 
 glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
 glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
 glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);

您发送的代码没有向顶点位置缓冲区发送任何数据。

Ps。为了提高效率,您应该生成缓冲区,并在循环之前提交数据。