簡體   English   中英

無法在OpenGL中繪制三角形

[英]Cannot draw a triangle in OpenGL

我最近開始學習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;
}

printError和loadShader是我編寫的幫助程序函數,可以肯定地正常工作。 這是頂點和片段着色器的代碼,這很基本,我看不到那里可能出什么毛病:

頂點着色器

#version 150

in vec2 position;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
}

片段着色器

#version 150

out vec4 outColor;

void main()
{
    outColor = vec4(1.0, 1.0, 1.0, 1.0);
}

抱歉,這很模糊,但是我進行了研究,但實際上在代碼中找不到任何錯誤,因此希望有經驗的人能夠找到問題。

提前致謝!

您沒有生成和綁定頂點數組對象,而只是生成了頂點緩沖區。 本質上,您已經創建了一個數據源(VBO),但是沒有數據可以存儲,因此調用glEnableVertexAttribArray(posAttrib);時沒有綁定數組對象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是否基於擴展名執行此檢測? 如果沒有的話,那將是最可能的問題。

我對您的代碼進行了檢查。 一些錯誤的地方:

  • 您不要求核心資料
  • 您不檢查鏈接
  • 您正在濫用逗號運算符
  • 您不啟用glewExperimental
  • 你不會清除你的深度

這是您與上下文之間的差異(由於您未包含標頭或定義,因此是經過修改的版本):

@@ -22,6 +22,7 @@

     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
@@ -43,6 +44,7 @@
         return -1;
     }

+    glewExperimental = GL_TRUE;
     GLenum glewInitResult = glewInit();
     if (glewInitResult != GLEW_OK)
     {
@@ -69,10 +71,10 @@
     rewind( fp );

     code = calloc( 1, sz+1 );
-    if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(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);free(code);fputs("entire read fails",stderr);exit(1);}

     fclose(fp);
     char *dot = strrchr(filename, '.');
@@ -122,6 +124,10 @@
     float vertices[] = {0.0,  0.5,
                         0.5, -0.5,
                         -.5, -0.5};
+    GLuint vao;
+    glGenVertexArrays(1, &vao);
+    glBindVertexArray(vao);
+
     GLuint vbo;
     glGenBuffers(1, &vbo);
     glBindBuffer(GL_ARRAY_BUFFER, vbo);
@@ -160,7 +166,7 @@
         }

         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-        glClear(GL_COLOR_BUFFER_BIT);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

         glDrawArrays(GL_TRIANGLES, 0, 3);

結果: 三角形

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM