分段错误glDrawArrays()

时间:2015-03-20 10:53:53

标签: c++ opengl graphics 3d

我正在尝试从文件生成地形,并在openGL的屏幕上的窗口中显示它。我遇到了一个seg错误,我已将其本地化为我的代码中的glDrawArrays()调用。

我可能会说错了,或者我的高度图可能有太多顶点用于我调用它的方式。

我将链接下面的代码并在段错误行旁边添加注释。

/**
 * A typical program flow and methods for rendering simple polygons
 * using freeglut and openGL + GLSL
 */

#include <stdio.h>
// GLEW loads OpenGL extensions. Required for all OpenGL programs.
#include <GL/glew.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Utility code to load and compile GLSL shader programs
#include "shader.hpp"
#include <iostream>
#include <fstream>
#include <vector>

#define WINDOW_WIDTH    400
#define WINDOW_HEIGHT   400
//#define VALS_PER_VERT 3
//#define VALS_PER_COLOUR 4
//#define NUM_VERTS 3           // Total number of vertices to load/render

#define VALS_PER_VERT_HEIGHT 5
#define VALS_PER_COLOUR_HEIGHT 4
#define HEIGHT_VERTS 5 //height map vertices per line

using namespace std;

// Handle to our VAO generated in setShaderData method
//heightmap

unsigned int vertexVaoHandleHeight;

// Handle to our shader program
unsigned int programID;

/**
 * Sets the shader uniforms and vertex data
 * This happens ONCE only, before any frames are rendered
 * @param id, Shader program object to use
 * @returns 0 for success, error otherwise
 */
int setShaderData(const unsigned int &id) 
{
    /*
     * What we want to draw
     * Each set of 3 vertices (9 floats) defines one triangle
     * You can define more triangles to draw here
     */


    float heightmapVerts[ HEIGHT_VERTS*VALS_PER_VERT_HEIGHT ] = {

            //5    
            -0.9, -0.6, -0.4, -0.6, -0.9,
            -0.2, 0.1, 0.3, 0.1, -0.3,
            0, 0.4, 0.8, 0.4, 0,
            -0.2, 0.1, 0.3, 0.1, -0.3,
            0.5, -0.6, -0.4, -0.6, -0.9,

    };

        std::cout << "1" << endl;

    // Colours for each vertex; red, green, blue and alpha
    // This data is indexed the same order as the vertex data, but reads 4 values
    // Alpha will not be used directly in this example program


    //may cause problems because less numbers
        float heightColours[ HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT ] = {
            0.8f, 0.7f, 0.5f, 1.0f,
            0.3f, 0.7f, 0.1f, 1.0f,
            0.8f, 0.2f, 0.5f, 1.0f,

    };

            std::cout << "2" << endl;

    // heightmap stuff ##################################################

    // Generate storage on the GPU for our triangle and make it current.
    // A VAO is a set of data buffers on the GPU
    glGenVertexArrays(1, &vertexVaoHandleHeight);
    glBindVertexArray(vertexVaoHandleHeight);


            std::cout << "3" << endl;

    // Generate new buffers in our VAO
    // A single data buffer store for generic, per-vertex attributes
    unsigned int bufferHeight[2];
    glGenBuffers(2, bufferHeight);
    // Allocate GPU memory for our vertices and copy them over
    glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_VERT_HEIGHT, heightmapVerts, GL_STATIC_DRAW);
    // Do the same for our vertex colours
    glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*HEIGHT_VERTS*VALS_PER_COLOUR_HEIGHT, heightColours, GL_STATIC_DRAW);

            std::cout << "4" << endl;

    // Now we tell OpenGL how to interpret the data we just gave it
    // Tell OpenGL what shader variable it corresponds to
    // Tell OpenGL how it's formatted (floating point, 3 values per vertex)
    int vertLocHeight = glGetAttribLocation(id, "a_vertex");
    glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[0]);
    glEnableVertexAttribArray(vertLocHeight);
    glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);

            std::cout << "5" << endl;

    // Do the same for the vertex colours
    int colourLocHeight = glGetAttribLocation(id, "a_colour");
    glBindBuffer(GL_ARRAY_BUFFER, bufferHeight[1]);
    glEnableVertexAttribArray(colourLocHeight);
    glVertexAttribPointer(colourLocHeight, VALS_PER_COLOUR_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);
    // heightmap stuff ##################################################

        std::cout << "6" << endl;

    // An argument of zero un-binds all VAO's and stops us
    // from accidentally changing the VAO state
    glBindVertexArray(0);
    // The same is true for buffers, so we un-bind it too
    glBindBuffer(GL_ARRAY_BUFFER, 0);

        std::cout << "7" << endl;
    return 0;   // return success
}


/**
 * Renders a frame of the state and shaders we have set up to the window
 * Executed each time a frame is to be drawn.
 */
void render() 
{
    // Clear the previous pixels we have drawn to the colour buffer (display buffer)
    // Called each frame so we don't draw over the top of everything previous
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(programID);

            std::cout << "8" << endl;

    // HEIGHT MAP STUFF ###################################
    // Make the VAO with our vertex data buffer current
    glBindVertexArray(vertexVaoHandleHeight);
    // Send command to GPU to draw the data in the current VAO as triangles
    std::cout << "8.5" << endl;
    //CRASHES HERE
    glDrawArrays(GL_TRIANGLES, 0, /*HEIGHT_VERTS = 5*/ 3);

    std::cout << "8.75" << endl;
    glBindVertexArray(0);   // Un-bind the VAO

            std::cout << "9" << endl;
    // HEIGHT MAP STUFF ###################################

    glutSwapBuffers();  // Swap the back buffer with the front buffer, showing what has been rendered

    glFlush();  // Guarantees previous commands have been completed before continuing
}


/**
 * Program entry. Sets up OpenGL state, GLSL Shaders and GLUT window and function call backs
 * Takes no arguments
 */
int main(int argc, char **argv) {


    //READ IN FILE//
    std::fstream myfile("heights.csv", std::ios_base::in);
    if(!myfile.good()){cout << "file not found" << endl;}
    std::vector<float> numbers;
    float a;
    while (myfile >> a){/*printf("%f ", a);*/
    numbers.push_back(a);
    }


    //for (int i=0; i<numbers.size();i++){cout << numbers[i] << endl;}

    getchar();
    //READ IN FILE//

    // Set up GLUT window
    glutInit(&argc, argv);              // Starts GLUT systems, passing in command line args
    glutInitWindowPosition(100, 0);     // Positions the window on the screen relative to top left
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);    // Size in pixels

    // Display mode takes bit flags defining properties you want the window to have;
    //  GLUT_RGBA : Set the pixel format to have Red Green Blue and Alpha colour channels
    //  GLUT_DOUBLE : Each frame is drawn to a hidden back buffer hiding the image construction
    //  GLUT_DEPTH : A depth buffer is kept so that polygons can be drawn in-front/behind others (not used in this application)
#ifdef __APPLE__    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_3_2_CORE_PROFILE);
#else
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
#endif

    glutCreateWindow("Hello World!");   // Makes the actual window and displays

    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return -1;
    }

    // Sets the (background) colour for each time the frame-buffer (colour buffer) is cleared
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

    // Set up the shaders we are to use. 0 indicates error.
    programID = LoadShaders("minimal.vert", "minimal.frag");
    if (programID == 0)
        return 1;

    // Set this shader program in use
    // This is an OpenGL state modification and persists unless changed
    glUseProgram(programID);

    // Set the vertex data for the program
    if (setShaderData(programID) != 0)
        return 1;

    // Render call to a function we defined,
    // that is called each time GLUT thinks we need to update
    // the window contents, this method has our drawing logic
    glutDisplayFunc(render);

    // Start an infinite loop where GLUT calls methods (like render)
    // set with glut*Func when needed.
    // Runs until something kills the window
    glutMainLoop();

    return 0;
}

1 个答案:

答案 0 :(得分:1)

size的{​​{1}}参数必须为1,2,3或4.您在此处传递5:

glVertexAttribPointer()

如果您的渲染出现问题,请务必致电#define VALS_PER_VERT_HEIGHT 5 ... glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0); 。上面的调用会立即给您glGetError()错误。

您的代码看起来通常也不一致。在某些地方,你似乎假设你有3个顶点,在其他地方4,在其他地方5.然后,如上所示,你有5个坐标的顶点,这没有任何意义。您可能需要仔细查看自己的代码,并确保所有内容与您尝试的内容保持一致。