分段故障glDrawArrays()

Segmentation Fault glDrawArrays()

本文关键字:glDrawArrays 故障 分段      更新时间:2023-10-16

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

我可能说错了,或者我的高度图可能有太多的顶点不适合我的说法。

我将在下面链接我的代码,并在segfault行旁边添加注释。

/**
 * 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 GLEWn");
        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;
}

glVertexAttribPointer()size参数必须是1、2、3或4。你在这里通过5:

#define VALS_PER_VERT_HEIGHT 5
...
glVertexAttribPointer(vertLocHeight, VALS_PER_VERT_HEIGHT, GL_FLOAT, GL_FALSE, 0, 0);

如果渲染出现问题,则应始终调用glGetError()。上面的调用将立即给您一个GL_INVALID_VALUE错误。

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