【问题标题】:OpenGL send color to shaderOpenGL将颜色发送到着色器
【发布时间】:2016-03-02 08:39:36
【问题描述】:

我正在学习来自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 GLFW\n");
        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;
}

顶点着色器:

#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_and_Fragment_Shaders_%28C_/_SDL%29 解决了我的问题。

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

我阅读并了解了更多内容并更改了一些代码,现在它正在运行,我现在很满意:)

【问题讨论】:

  • 查看complete GL+VAO/VBO+GLSL+shaders example in C++ 并尝试它是否适用于您的设置。如果没有,gfx 驱动程序或您的某些库可能有问题。如果可行,请尝试找出差异(抱歉,懒得比较这么多代码……)

标签: c++ opengl colors buffer


【解决方案1】:

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

应该是

 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);

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

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

【讨论】:

  • 好的,谢谢,让我检查一下。因此,即使顶点位置在循环(动画)期间发生变化,我也不需要在循环中调用 glBufferData(..) 来让着色器知道我改变了什么? (如果这样的话)
  • 如果确实需要单独更改顶点,则需要在循环中调用 glbufferdata()。但在大多数情况下,一个简单的统一变换就足够了。
  • 即使是动画网格,典型的方法是做顶点蒙皮,使用矩阵数组来生成动画。但是,这取决于你,只要记住将数据从 cpu 传输到 gpu 的成本是非常重要的
  • 好吧,我一直在想,顶点着色器中的每一个变换都会影响所见的整体(移动相机并移动世界)。但是假设我有 5 个三角形在移动,我如何在顶点着色器中将它们的位置转换为相同的?
猜你喜欢
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多