Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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 无法在OpenGL中绘制三角形_C_Opengl - Fatal编程技术网

C 无法在OpenGL中绘制三角形

C 无法在OpenGL中绘制三角形,c,opengl,C,Opengl,我最近开始学习OpenGL,并编写了一些代码在SDL窗口中绘制一个简单的白色三角形。我已经反复阅读了我的代码,并将其与几个opengl教程中提出的内容进行了对比,但我无法使其正常工作。我知道opengl与SDL的绑定是正确的,因为我可以用glClearColor更改窗口背景色,但我无法显示那个该死的三角形 我很乐意提供更多信息,但老实说,我不知道问题的确切来源,所以下面是我编写的代码: int init() { if(SDL_Init(SDL_INIT_VIDEO) < 0)

我最近开始学习OpenGL,并编写了一些代码在SDL窗口中绘制一个简单的白色三角形。我已经反复阅读了我的代码,并将其与几个opengl教程中提出的内容进行了对比,但我无法使其正常工作。我知道opengl与SDL的绑定是正确的,因为我可以用glClearColor更改窗口背景色,但我无法显示那个该死的三角形

我很乐意提供更多信息,但老实说,我不知道问题的确切来源,所以下面是我编写的代码:

int init()
{
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        fprintf(stderr, "SDL error : %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    gWindow = SDL_CreateWindow("Test OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINWIDTH, WINHEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if (gWindow == NULL)
    {
        fprintf(stderr, "Failed to create window. SDL error : %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    gGLContext = SDL_GL_CreateContext(gWindow);
    if (gGLContext == 0)
    {
        fprintf(stderr, "Failed to create OpenGL context. SDL error : %s\n", SDL_GetError());
        SDL_DestroyWindow(gWindow);
        SDL_Quit();
        return -1;
    }

    GLenum glewInitResult = glewInit();
    if (glewInitResult != GLEW_OK)
    {
        fprintf(stderr, "Failed to initialize glew. Glew error : %s\n", glewGetErrorString(glewInitResult));
        SDL_GL_DeleteContext(gGLContext);
        SDL_DestroyWindow(gWindow);
        SDL_Quit();
        return -1;
    }
    glEnable(GL_DEPTH_TEST);

    return 0;
}

int loadShader(char *filename, GLint *shader)
{
    long sz;
    const GLchar *code;
    FILE *fp = fopen(filename, "rb");
    if( !fp ) perror(filename),exit(1);

    fseek( fp , 0L , SEEK_END);
    sz = ftell( fp );
    rewind( fp );

    code = calloc( 1, sz+1 );
    if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);

    if( 1!=fread( code , sz, 1 , fp) )
      fclose(fp),free(code),fputs("entire read fails",stderr),exit(1);

    fclose(fp);
    char *dot = strrchr(filename, '.');
    GLenum type;
    if (dot)
        type = !strcmp(dot, ".vs") ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &code, NULL);
    glCompileShader(*shader);
    GLint status;
    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);

    char buffer[512];
    glGetShaderInfoLog(*shader, sizeof(buffer), NULL, buffer);
    fprintf(stderr, buffer);
    if (status != GL_TRUE)
        return -1;
    return 0;
}

void printError(char *message)
{
#define TEST(ERR) case ERR: fprintf(stderr, "%s : " #ERR "\n", message); break;
    int error;
    if ((error = glGetError()))
        switch (error)
        {
        TEST(GL_INVALID_ENUM)
        TEST(GL_INVALID_VALUE)
        TEST(GL_INVALID_OPERATION)
        TEST(GL_STACK_OVERFLOW)
        TEST(GL_STACK_UNDERFLOW)
        TEST(GL_OUT_OF_MEMORY)
        TEST(GL_INVALID_FRAMEBUFFER_OPERATION)
        TEST(GL_TABLE_TOO_LARGE)
    default:
        fprintf(stderr, "Unknown error\n");
        }
#undef TEST
}

int main(int argc, char *argv[])
{
    if (init() != 0)
        return -1;

    float vertices[] = {0.0,  0.5,
                        0.5, -0.5,
                        -.5, -0.5};
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint vShader;
    GLuint fShader;
    if (loadShader("plain_2d.vs", &vShader) < 0)
        return -1;
    if (loadShader("plain_2d.fs", &fShader) < 0)
        return -1;
    GLint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vShader);
    glAttachShader(shaderProgram, fShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

    printError("Before entering the loop");

    SDL_Event e;
    int quit = 0;
    while (!quit)
    {
        printError("In the loop");
        while (SDL_PollEvent(&e))
        {
            switch (e.type)
            {
            case SDL_QUIT:
                quit = 1;
            }
        }

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        SDL_GL_SwapWindow(gWindow);
    }
    return 0;
}
片段着色器

#version 150

out vec4 outColor;

void main()
{
    outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
我很抱歉,这是含糊不清的,但我做了我的研究,真的没有发现我的代码中有任何错误,所以我希望一个更有经验的人能够找到问题


提前谢谢

您没有生成和绑定顶点数组对象,只是一个顶点缓冲区。基本上,您已经创建了一个数据源(VBO),但数据无处可去,因此在调用
glEnableVertexAttribArray(posAttrib)时没有绑定数组对象

在生成和绑定缓冲区之前,请添加以下内容:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
编辑:只有在启用兼容配置文件时,3.1及更新版本中才有默认VAO可用-核心配置文件要求您手动执行


另外,请显示
loadShader()

的源代码。您尚未生成并绑定顶点数组对象,只是一个顶点缓冲区。基本上,您已经创建了一个数据源(VBO),但数据无处可去,因此在调用
glEnableVertexAttribArray(posAttrib)时没有绑定数组对象

在生成和绑定缓冲区之前,请添加以下内容:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
编辑:只有在启用兼容配置文件时,3.1及更新版本中才有默认VAO可用-核心配置文件要求您手动执行


另外,请显示
loadShader()

的源。通常,创建着色器时,必须指定着色器类型:

GLuint vertexShader, fragmentShader;

vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

我在你的代码中没有看到这些。loadShader是否基于扩展进行此检测?如果不是,则最有可能出现问题。

通常,在创建着色器时,必须指定着色器类型:

GLuint vertexShader, fragmentShader;

vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

我在你的代码中没有看到这些。loadShader是否基于扩展进行此检测?如果不是的话,那可能是最有可能出现的问题。

我对您的代码进行了一些检查。有几件事是错误的:

  • 您没有请求核心配置文件
  • 你没有检查你的链接
  • 您正在滥用逗号运算符
  • 您没有启用glewExperimental
  • 你没有清除你的深度位
以下是您与上下文的区别(来自修改后的版本,因为您没有包含标题或定义):


结果是:

我对您的代码进行了一些检查。有几件事是错误的:

  • 您没有请求核心配置文件
  • 你没有检查你的链接
  • 您正在滥用逗号运算符
  • 您没有启用glewExperimental
  • 你没有清除你的深度位
以下是您与上下文的区别(来自修改后的版本,因为您没有包含标题或定义):


结果是:

为什么您认为您的
loadShader
函数工作正常?问题很可能就在这里。你应该定期检查你的opengl错误。您也从不检查着色器是否在编译时没有警告(loadShader中发生的情况除外),也从不检查程序是否存在链接器错误。请尝试在循环中调用
glGetErrors()
。如果If激发,请找到触发它的确切行。我会检查错误,无论是在加载着色器时(这就是我说它加载正确的原因),还是在使用
printError(char*message)
执行程序期间。上面的代码没有错误,这就是为什么我很难找出它的错误。如果你想查看的话,我在我的原始帖子中添加了这两个函数的代码。你为什么认为你的
loadShader
函数工作正常?问题很可能就在这里。你应该定期检查你的opengl错误。您也从不检查着色器是否在编译时没有警告(loadShader中发生的情况除外),也从不检查程序是否存在链接器错误。请尝试在循环中调用
glGetErrors()
。如果If激发,请找到触发它的确切行。我会检查错误,无论是在加载着色器时(这就是我说它加载正确的原因),还是在使用
printError(char*message)
执行程序期间。上面的代码没有错误,这就是为什么我很难找出它的错误。如果您想查看的话,我将这两个函数的代码都添加到了我的原始帖子中。考虑到从一开始就有一个默认的VAO绑定,我不确定这是否会有很大的不同。@Taywee我在本地测试了它,尽管是用glfw而不是sdl。IIUC取决于GL版本-如果您处于兼容模式,则默认VAO仅适用于core>=3.1。@HolyBlackCat更正afaik,nvidia可能会有一些奇怪之处(不符合规范?)谢谢您的快速回复,我已经添加了您编写的代码,但我仍然会得到一个黑色屏幕,或者我选择的任何颜色的屏幕。我还对VBO和VAO感到困惑。如果我理解正确,VBO是在图形卡中存储vertice信息的低级数组,而VAO是存储有关渲染内容和方式的信息的“配置文件”——这是正确的,还是有点接近现实?至于
loadShader()
,我将代码添加到我的帖子中。@Toctave这或多或少是正确的。VAO管理客户端(即不在GPU上)状态,如顶点布局,以及绘制阵列时要使用的VBO。学习OpenGL是相当困难的,因为你基本上是在迎头赶上