Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GLD元件中的OpenGL SegFault_C++_Opengl - Fatal编程技术网

C++ GLD元件中的OpenGL SegFault

C++ GLD元件中的OpenGL SegFault,c++,opengl,C++,Opengl,我对glpaurements的调用产生了一个分段错误。如果我废弃索引并使用glDrawArrays顶点缓冲区中的所有内容都将被绘制。因此,我的假设是,错误出现在我填充GL\u元素\u数组\u缓冲区的过程中,但我看不出问题所在 我有一个球体类,它为球体生成顶点和索引。然后,我只需使用以下代码来设置vbo、vao等: GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); g

我对
glpaurements
的调用产生了一个分段错误。如果我废弃索引并使用
glDrawArrays
顶点缓冲区中的所有内容都将被绘制。因此,我的假设是,错误出现在我填充
GL\u元素\u数组\u缓冲区的过程中,但我看不出问题所在

我有一个球体类,它为球体生成顶点和索引。然后,我只需使用以下代码来设置vbo、vao等:

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(struct VertexData) * sphere.GetVertices()->size(), sphere.GetVertices()->data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    GLuint vao;
    glGenVertexArrays(1,&vao);
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, position));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, color));
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, normal));
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, tcoords));

    GLuint ibo;
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * sphere.GetIndices()->size(), sphere.GetIndices()->data(), GL_STATIC_DRAW);
    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
…我看不出有什么不对劲

我的画是这样画的:

glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

float t = watch.GetElapsedTimePeriod().count();
float rotation = 0.5/1000.0*t;
rotationMatrix = glm::rotate(rotationMatrix,rotation,glm::vec3(0,1,0));
glm::mat4 modelMatrix = perspectiveMatrix * viewMatrix * rotationMatrix * identitymatrix;

glUseProgram(shaderprogram);
glUniformMatrix4fv(glGetUniformLocation(shaderprogram, "mvpmatrix"), 1, GL_FALSE, glm::value_ptr(modelMatrix));

glBindVertexArray(vao);
std::shared_ptr<std::vector<GLushort>> p = sphere.GetIndices();
size_t tt = p->size();
glDrawElements(GL_TRIANGLES,tt,GL_UNSIGNED_SHORT,0);
//glDrawArrays(GL_POINTS,0,(*sphere.GetVertices()).size());
glBindVertexArray(0);

glUseProgram(0);

SDL_GL_SwapWindow(sdlglHandler);
struct VertexData
{
    GLdouble position[4];
    GLfloat color[3];
    GLfloat normal[3];
    GLfloat tcoords[2];
};
大规模编辑 我已经删除了所有的C++封装,并生成了同样的错误代码。我完全不知道在哪里尝试访问私有内存,对我来说,没有任何东西看起来是溢出的:

#include <exception>
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <string>
#include <algorithm>
#include <functional>

#include <utilities.hpp>

#include <GL/glew.h>
#include <SDL2/sdl.h>
#define GLM_FORCE_RADIANS
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>

struct VertexData
{
    GLdouble position[4];
    GLfloat color[3];
    GLfloat normal[3];
    GLfloat tcoords[2];
};

int main(int argc, char* argv[])
{
    try
    {
        SDL_Window* window;
        SDL_GLContext context;
        if(SDL_Init(SDL_INIT_VIDEO) < 0)
            throw std::runtime_error("unable to initialise video");

        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);

        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

        window = SDL_CreateWindow("SpaceEngine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        800, 800, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
        if(!window)
            throw std::runtime_error("unable to create window");

        context = SDL_GL_CreateContext(window);

        SDL_GL_SetSwapInterval(1);

        GLenum glewErr = glewInit();
        if(glewErr != GLEW_OK)
        {
            SDL_GL_DeleteContext(context);
            SDL_DestroyWindow(window);
            SDL_Quit();
            throw std::runtime_error(reinterpret_cast<const char*>(glewGetErrorString(glewErr)));
        }

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);

        std::vector<VertexData> vertices;
        std::vector<GLushort> indices;
        int rings = 200;
        int sectors = 200;
        float radius = 1.0;

        if(rings < 2)
            rings = 2;
        if(sectors < 2)
            sectors = 2;
        while(rings * sectors >= std::numeric_limits<GLushort>::max())
        {
            rings /= 2;
            sectors /= 2;
        }

        const GLuint polyCountXPitch = rings+1;

        GLuint level = 0;

        for(GLuint p1 = 0; p1 < sectors-1; ++p1)
        {
            for(GLuint p2 = 0; p2 < rings-1; ++p2)
            {
                GLuint curr = level + p2;
                indices.push_back(curr + polyCountXPitch);
                indices.push_back(curr);
                indices.push_back(curr + 1);
                indices.push_back(curr + polyCountXPitch);
                indices.push_back(curr + 1);
                indices.push_back(curr + 1 + polyCountXPitch);
            }

            indices.push_back(level + rings - 1 + polyCountXPitch);
            indices.push_back(level + rings - 1);
            indices.push_back(level + rings);

            indices.push_back(level + rings - 1 + polyCountXPitch);
            indices.push_back(level + rings);
            indices.push_back(level + rings + polyCountXPitch);

            level += polyCountXPitch;
        }

        const GLuint polyCountSq = polyCountXPitch * sectors;           //top point
        const GLuint polyCountSq1 = polyCountSq + 1;                    //bottom point
        const GLuint polyCountSqM1 = (sectors - 1) * polyCountXPitch;   //last rows first index

        for(GLuint p2 = 0; p2 < rings - 1; ++p2)
        {
            indices.push_back(polyCountSq);
            indices.push_back(p2 + 1);
            indices.push_back(p2);

            indices.push_back(polyCountSqM1 + p2);
            indices.push_back(polyCountSqM1 + p2 + 1);
            indices.push_back(polyCountSq1);
        }

        indices.push_back(polyCountSq);
        indices.push_back(rings);
        indices.push_back(rings - 1);

        indices.push_back(polyCountSqM1 + rings - 1);
        indices.push_back(polyCountSqM1);
        indices.push_back(polyCountSq1);

        const GLdouble angleX = 2 * pi() / rings;
        const GLdouble angleY = pi() / sectors;

        GLuint i = 0;
        GLdouble axz;
        GLdouble ay = 0;

        vertices.resize(polyCountXPitch * sectors + 2);
        for(GLuint y = 0; y < sectors; ++y)
        {
            ay += angleY;
            const GLdouble sinay = std::sin(ay);
            axz = 0;

            for(GLuint xz = 0; xz < rings; ++xz)
            {
                const glm::vec3 pos((radius * std::cos(axz) * sinay),radius * std::cos(ay), radius * std::sin(axz) * sinay);
                glm::vec3 normal = pos;
                normal = glm::normalize(normal);

                GLuint tu = 0.5f;
                if(y == 0)
                {
                    if(normal.y != -1.0f && normal.y != 1.0f)
                        tu = std::acos(glm::clamp<GLdouble>(normal.x/sinay, -1.0f, 1.0f)) * 0.5 * (1.0f/pi());
                    if(normal.z < 0.0f)
                        tu = 1 - tu;
                }
                else
                    tu = vertices[i-polyCountXPitch].tcoords[0];

                VertexData v;
                v.color[0] = 1;
                v.color[1] = 1;
                v.color[2] = 1;
                v.position[0] = pos.x;
                v.position[1] = pos.y;
                v.position[2] = pos.z;
                v.position[3] = 1.0f;
                v.normal[0] = normal.x;
                v.normal[1] = normal.y;
                v.normal[2] = normal.z;
                v.tcoords[0] = tu;
                v.tcoords[1] = ay * (1.0f/pi());
                vertices.at(i) = v;

                ++i;
                axz += angleX;
            }

            vertices.at(i) = vertices.at(i - rings);
            vertices.at(i).tcoords[0] = 1.0f;
            ++i;
        }

        VertexData v;
        v.color[0] = 1;
        v.color[1] = 1;
        v.color[2] = 1;
        v.position[0] = 0;
        v.position[1] = radius;
        v.position[2] = 0;
        v.position[3] = 1.0f;
        v.normal[0] = 0;
        v.normal[1] = 1;
        v.normal[2] = 0;
        v.tcoords[0] = 0.5f;
        v.tcoords[1] = 0.0f;
        vertices.at(i) = v;
        ++i;
        v.position[1] = -radius;
        v.normal[1] = -1.0f;
        v.tcoords[1] = 1.0f;
        vertices.at(i) = v;

        GLuint vao;
        glGenVertexArrays(1,&vao);
        glBindVertexArray(vao);

        GLuint vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(struct VertexData) * vertices.size(), vertices.data(), GL_STATIC_DRAW);

        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, position));
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, color));
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, normal));
        glEnableVertexAttribArray(3);
        glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(struct VertexData), (const GLvoid*)offsetof(struct VertexData, tcoords));

        GLuint ibo;
        glGenBuffers(1, &ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), indices.data(), GL_STATIC_DRAW);

        glBindVertexArray(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        GLuint shader1,shader2;
        std::ifstream file("tutorial2.vert");
        if(!file)
            throw std::runtime_error("The file tutorial2.vert was not opened");
        else
        {
            std::string fileContents((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());

            shader1 = glCreateShader(GL_VERTEX_SHADER);
            std::string fail = "glCreateShader failed using " + GL_VERTEX_SHADER;

            if(!shader1)
                throw std::runtime_error(fail.c_str());

            const GLchar* contents[1];
            contents[0] = fileContents.c_str();
            glShaderSource(shader1, 1, contents, NULL);

            glCompileShader(shader1);
            int compiled;
            glGetShaderiv(shader1, GL_COMPILE_STATUS, &compiled);
            if(compiled == 0)
            {
                int maxLength;
                glGetShaderiv(shader1, GL_INFO_LOG_LENGTH, &maxLength);
                char* vertexInfoLog = new char[maxLength];
                glGetShaderInfoLog(shader1, maxLength, &maxLength, vertexInfoLog);
                throw std::runtime_error("Shader failed to compile:\n>\t" + std::string(vertexInfoLog));
            }
        }
        std::ifstream file2("tutorial2.frag");
        if(!file2)
            throw std::runtime_error("The file tutorial2.frag was not opened");
        else
        {
            std::string fileContents((std::istreambuf_iterator<char>(file2)),std::istreambuf_iterator<char>());

            shader2 = glCreateShader(GL_FRAGMENT_SHADER);
            std::string fail = "glCreateShader failed using " + GL_FRAGMENT_SHADER;
            if(!shader2)
                throw std::runtime_error(fail.c_str());

            const GLchar* contents[1];
            contents[0] = fileContents.c_str();
            glShaderSource(shader2, 1, contents, NULL);

            glCompileShader(shader2);
            int compiled;
            glGetShaderiv(shader2, GL_COMPILE_STATUS, &compiled);
            if(compiled == 0)
            {
                int maxLength;
                glGetShaderiv(shader2, GL_INFO_LOG_LENGTH, &maxLength);
                char* vertexInfoLog = new char[maxLength];
                glGetShaderInfoLog(shader2, maxLength, &maxLength, vertexInfoLog);
                throw std::runtime_error("Shader failed to compile:\n>\t" + std::string(vertexInfoLog));
            }
        }

        GLuint program = glCreateProgram();
        if(!program)
            throw std::runtime_error("glCreateProgram failed");

        glAttachShader(program, shader1);
        glAttachShader(program, shader2);

        glBindAttribLocation(program, 0, "in_Position");
        glBindAttribLocation(program, 1, "in_Color");
        glBindAttribLocation(program, 2, "in_Normal");
        glBindAttribLocation(program, 3, "in_UV");

        glLinkProgram(program);
        int IsLinked;
        glGetProgramiv(program, GL_LINK_STATUS, (int *)&IsLinked);
        if(IsLinked == 0)
        {
           int maxLength;
           glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
           char* shaderProgramInfoLog = new char[maxLength];
           glGetProgramInfoLog(program, maxLength, &maxLength, shaderProgramInfoLog);
           throw std::runtime_error("Program failed to link:\n>\t" + std::string(shaderProgramInfoLog) + "");
        }

        glDetachShader(program, shader1);
        glDetachShader(program, shader2);

        bool done = false;

        while(!done)
        {
            SDL_Event event;
            while(SDL_PollEvent(&event))
            {
                switch(event.type)
                {
                case SDL_WINDOWEVENT:
                    switch(event.window.event)
                    {
                    case SDL_WINDOWEVENT_CLOSE:
                        done = true;
                        break;
                    }
                    break;
                }
            }

            glClearColor(0.0, 0.0, 0.0, 1.0);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            glUseProgram(program);

            glBindVertexArray(vao);

            glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSIGNED_SHORT,0);

            glBindVertexArray(0);

            glUseProgram(0);

            SDL_GL_SwapWindow(window);
            }

        glUseProgram(0);
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glDeleteProgram(program);
        glDeleteBuffers(1, &vbo);
        glDeleteVertexArrays(1, &vao);

        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();

        std::cout << "all good in the hood" << std::endl;
    }
    catch(const std::exception& e)
    {
        std::cout << "ERROR:\t" << e.what() << std::endl;
    }
    catch(...)
    {
        std::cout << "ERROR" << std::endl;
    }
    exit(EXIT_SUCCESS);
}
还有我的Frag着色器:

#version 150

precision highp float;

in  vec3 ex_Color;
out vec4 gl_FragColor;

void main(void) 
{
    gl_FragColor = vec4(ex_Color,1.0);
}
EDIT2 我甚至尝试过将一行文本输出到一个文件中,然后逐个遍历索引中的每个三角形。如果我运行它几次,就会发现segfault发生在索引数组中的不同点上。索引正在查找的顶点在我的顶点数组的范围内

for(int i = 0; i < tt; i+=3)
{
    file << "attempting " << i/3 << std::endl;
    glDrawElements(GL_TRIANGLES,i,GL_UNSIGNED_SHORT,0);
    SDL_GL_SwapWindow(sdlglHandler);
}
for(int i=0;ifile您对VAOs的使用看起来是正确的。不过,我建议您在执行GLDraweElements调用之前,在索引缓冲区上显式添加一个glBindBuffer,即

std::shared_ptr<std::vector<GLushort>> p = sphere.GetIndices();
size_t tt = p->size();

glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES,tt,GL_UNSIGNED_SHORT,0);
glBindVertexArray(0);
std::shared_ptr p=sphere.getIndexs();
size_t tt=p->size();
glBindVertexArray(vao);
glBindBuffer(GL_元素数组缓冲区,ibo);
GLD元素(GL_三角形,tt,GL_无符号_短,0);
glBindVertexArray(0);


请注意,即使在今天,VAO也没有得到太多优化,更改VAO绑定可能意味着性能受到影响。例如,Valve对其进行了基准测试,到目前为止,仍然在其源引擎中禁用了使用多个VAO的代码路径。在进行此更改之前,建议的方法是仅绑定缓冲区对象本身,对于OpenGL配置文件,建议t强制VAO在每个上下文中创建和绑定一次,然后在进一步的操作中忽略它。

您对VAO的使用看起来是正确的。不过,我建议您在执行GLDrainElements调用之前,在索引缓冲区上显式添加glBindBuffer,即

std::shared_ptr<std::vector<GLushort>> p = sphere.GetIndices();
size_t tt = p->size();

glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES,tt,GL_UNSIGNED_SHORT,0);
glBindVertexArray(0);
std::shared_ptr p=sphere.getIndexs();
size_t tt=p->size();
glBindVertexArray(vao);
glBindBuffer(GL_元素数组缓冲区,ibo);
GLD元素(GL_三角形,tt,GL_无符号_短,0);
glBindVertexArray(0);


请注意,即使在今天,VAO也没有得到太多优化,更改VAO绑定可能意味着性能受到影响。例如,Valve对其进行了基准测试,到目前为止,仍然在其源引擎中禁用了使用多个VAO的代码路径。在进行此更改之前,建议的方法是仅绑定缓冲区对象本身,对于OpenGL配置文件,建议t强制VAO在每个上下文中创建和绑定一次,然后在进一步的操作中忽略它。

问题在于对顶点使用GL\u DOUBLE。更改为GL\u FLOAT似乎已经解决了问题

使用double时需要使用
glvertexattributelpointer


要有意义地使用glvertexattributelpointer,需要在着色器中重新写入一行(在dvec4中处于\u位置)

问题在于对顶点使用GL\u DOUBLE。更改为GL\u FLOAT似乎已经做到了这一点

使用double时需要使用
glvertexattributelpointer


要有意义地使用glvertexattributelpointer,需要在着色器中重新写入一行(在dvec4的\u位置)

Hi@datenwolf,谢谢你的回复。我已经试过了,因为我认为可能是我误解了openGL文档和VAOs的工作原理。这没有帮助。我不知道VAOs的性能;我会记住这一点。
GL\u元素\u数组\u缓冲区
绑定是VAO状态的一部分,因此绑定是多余的,并且将继续这只会损害性能。@datenwolf,你有Steam关于VAO声明的最新数据链接吗?我想不出为什么使用VAO的速度至少不如手动设置状态的速度快。VAO的整个思想是使状态设置更有效。如果它们得到正确的实现,它就会起作用。@RetoKoradi:Talk“将源代码移植到Linux,经验教训”-幻灯片57。我完全知道重新绑定元素数组缓冲区应该是多余的,但有时您必须尝试这些方法,以消除被驱动程序错误误导的可能性。@DatenWalf:感谢链接。有趣的演示文稿。“所有实现都会变慢。”"不过,这种说法肯定是错误的。要么他们做错了什么,要么他们没有看得太远。@RetoKoradi:嗯,他们有自己的技术,并且与所有GPU开发人员都有很好的联系。我强烈推荐他们将源引擎移植到OpenGL和Linux上的后期研究,因为那时他们与驱动程序d进行了非常独特的合作开发人员对部分开源Linux驱动程序进行了优化,驱动程序开发人员对源代码引擎进行了一些调整。我猜想VAOs的性能在很大程度上取决于使用模式,可能还取决于数据/批处理比率。您好@datenwolf,谢谢您的回复。我已经尝试过了我想可能是我误解了openGL文档和VAOs的工作原理。这没有帮助。我不知道VAOs的性能;我会记住这一点。绑定是VAO状态的一部分,所以绑定它是多余的,只会影响性能。@datenwolf,你有关于这方面的最新数据链接吗来自Steam的VAO声明?我想不出为什么使用VAOs的速度至少不如手动设置状态的速度快。VAOs的全部思想是使状态设置更有效。如果它们得到正确的实现,它会以这种方式工作。@RetoKoradi:Talk“将源代码移植到Linux,经验教训”–幻灯片57。我完全知道重新绑定元素数组缓冲区应该是冗余的