このOpenGL Hello Worldが黒い窓を描く理由を解読できますか?

StackOverflow https://stackoverflow.com/questions/3465226

  •  27-09-2019
  •  | 
  •  

質問

長さ(および幅、IDEの明確さのためです)を許してください。しかし、目的は現代のVBOとGLSLのシンプルなHello Worldであるため、コードの全長を表示することを考えました。

最初はに基づいていました http://people.freedesktop.org/~idr/opengl_tutorials/02-glsl-hello-world.pdf

主なポイントは、単一のエラーメッセージまたは警告が印刷されていないことです - そして、printfsがたくさんあることがわかります(実際、コードのほとんどすべてがエラーのためにキャッチされようとします)。

コンパイルは-std = c99 -pedantic -o0 -g -wall(警告なし)で行われるため、コンパイラエラーの余地もありません。

私はピンが私の注意を向けています

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

(後者は私がまだ完全に理解していないコードの唯一の部分です。最もあいまいな機能「これまで」)

情報ログには何も印刷されず、シェーダーが意図的に無効にされている場合、通常は健全なテキストを印刷します。したがって、それはシェーダー弦の割り当てでもそのコンピレーションでもありません。

空白の画面を印刷できるものが見えますか?

GLDRAWARRAYSがGL_POINTSで使用されている場合、中央に単一のドットを印刷し、GLCLEARの前に適切なGLCLEARCOLORが付いている場合、色が変化します。

#include "SDL.h" // Window and program management
#include "Glee.h" // OpenGL management; Notice SDL's OpenGL header is not included
#include <stdbool.h> // C99 bool

void initGL(void);
void drawGL(void);

int main (int argc, char **argv) {

    //  Load the SDL library; Initialize the Video Subsystem
    if (SDL_Init(SDL_INIT_VIDEO) < 0 ) printf("SDL_Init fail: %s\n", SDL_GetError()); 

    /*  Video Subsystem: set up width, height, bits per pixel (0 = current display's);
        Create an OpenGL rendering context */
    if (SDL_SetVideoMode(800, 600, 0, SDL_OPENGL) == NULL) printf("SDL_SetVideoMode fail: %s\n", SDL_GetError()); 

    // Title and icon text of window
    SDL_WM_SetCaption("gl", NULL);

    // Initialize OpenGL ..
    initGL();

    bool done = false;

    // Loop indefinitely unless user quits
    while (!done) { 

        // Draw OpenGL ..
        drawGL();

        // Deal with SDL events
        SDL_Event sdl_event;
        do {
            if (    sdl_event.type == SDL_QUIT || (sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.sym == SDLK_ESCAPE)) {
                    done = true;
                    break;
            }
        } while (SDL_PollEvent(&sdl_event));    

    }

    // Clean SDL initialized systems, unload library and return.
    SDL_Quit(); 
    return 0;
}

GLuint program;
GLuint buffer;
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
void initGL(void) {

    // Generate 1 buffer object; point its name (in uint form) to *buffer. 
    glGenBuffers(1, &buffer);       if(glGetError()) printf("glGenBuffers error\n");

    /*  bind the named (by a uint (via the previous call)) buffer object to target GL_ARRAY_BUFFER (target for vertices)
        apparently, one object is bound to a target at a time. */
    glBindBuffer(GL_ARRAY_BUFFER, buffer);      if(glGetError()) printf("glBindBuffer error\n");

    /*  Create a data store for the current object bound to GL_ARRAY_BUFFER (from above), of a size 8*size of GLfloat,
        with no initial data in it (NULL) and a hint to the GrLib that data is going to be modified once and used a 
        lot (STATIC), and it's going to be modified by the app and used by the GL for drawing or image specification (DRAW)
        Store is not mapped yet. */
    glBufferData(   GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), NULL, GL_STATIC_DRAW);            if(glGetError()) printf("glBufferData error\n");

    /*  Actually map to the GL client's address space the data store currently bound to GL_ARRAY_BUFFER (from above). 
        Write only. */
    GLfloat *data = (GLfloat *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);            if (!*data) printf("glMapBuffer error1\n"); if(glGetError()) printf("glMapBuffer error2\n");

    // Apparently, write some data on the object.
    data[0] = -0.75f;   data[1] = -0.75f;   data[2] = -0.75f;   data[3] =  0.75f;
    data[4] =  0.75f;   data[5] =  0.75f;   data[6] =  0.75f;   data[7] = -0.75f;

    // Unmap the data store. Required *before* the object is used.
    if(!glUnmapBuffer(GL_ARRAY_BUFFER)) printf("glUnmapBuffer error\n");

    // Specify the location and data format of an array of generic vertex attributes ..
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

    // the shaders source
    GLchar *vertex_shader_code[] =      {   "void main(void) { gl_Position = gl_Vertex; }"};
    GLchar *fragment_shader_code[] =        {   "void main(void) { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }"};

    /*  Create an empty shader object; used to maintain the source string; intended to run 
        on the programmable vertex processor; GL_SHADER_TYPE is set to  GL_VERTEX_SHADER 
        (e.g. for use on glGetShaderiv)*/
    GLuint vs = glCreateShader(GL_VERTEX_SHADER);           if (!vs) printf("glCreateShader fail\n");

    /*  Set the source code in vs; 1 string; GLchar **vertex_shader_code array of pointers to strings,
        length is NULL, i.e. strings assumed null terminated     */
    glShaderSource(vs, 1, (const GLchar **) &vertex_shader_code, NULL);             if(glGetError()) printf("glShaderSource error\n");

    // Actually compile the shader
    glCompileShader(vs);            GLint compile_status;   glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_status); if (compile_status == GL_FALSE) printf("vertex_shader_code compilation fail\n"); if(glGetError()) printf("glGetShaderiv fail\n");

    // same
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);         if (!fs) printf("glCreateShader fail\n");

    // same
    glShaderSource(fs, 1, (const GLchar **) &fragment_shader_code, NULL);           if(glGetError()) printf("glShaderSource error\n");

    // same
    glCompileShader(fs);            glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_status);  if (compile_status == GL_FALSE) printf("fragment_shader_code compilation fail\n"); if(glGetError()) printf("glGetShaderiv fail\n");

    /*  Empty program for later attachment of shaders; it provides management mechanism for them.
        Shaders can be compiled before or after their attachment. */
    program = glCreateProgram();            if(!program) printf("glCreateProgram fail1\n"); if(glGetError()) printf("glCreateProgram fail2\n");

    /*  Attach shaders to program; this could be done before their compilation or their association with code
        Destined to be linked together and form an executable. */
    glAttachShader(program, vs);            if(glGetError()) printf("glAttachShader fail1\n");
    glAttachShader(program, fs);            if(glGetError()) printf("glAttachShader fail2\n");

    //  Link the program; vertex shader objects create an executable for the vertex processor and similarly for fragment shaders.
    glLinkProgram(program);             GLint link_status; glGetProgramiv(program, GL_LINK_STATUS, &link_status); if (!link_status) printf("linking fail\n"); if(glGetError()) printf("glLinkProgram fail\n");

    /*  Get info log, if any (supported by the standard to be empty).
        It does give nice output if compilation or linking fails. */
    GLchar infolog[2048];
    glGetProgramInfoLog(program, 2048, NULL, infolog); printf("%s", infolog); if (glGetError()) printf("glGetProgramInfoLog fail\n");

    /*  Install program to rendering state; one or more executables contained via compiled shaders inclusion. 
        Certain fixed functionalities are disabled for fragment and vertex processors when such executables
        are installed, and executables may reimplement them. See glUseProgram manual page about it. */
    glUseProgram(program);      if(glGetError()) printf("glUseProgram fail\n");
}


void drawGL(void) {
    // Clear color buffer to default value
    glClear(GL_COLOR_BUFFER_BIT);       if(glGetError()) printf("glClear error\n");

    // Render the a primitive triangle 
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);      if(glGetError()) printf("glDrawArrays error\n");

    SDL_GL_SwapBuffers();
}
役に立ちましたか?

解決

Calvin1602の回答を拡大:

FTRANSFORMは、使用しないマトリックスを想定しています。 Gl_vertexはここで問題なくなるはずです。最終結果は[-1:1]^3キューブであると想定されており、彼のデータはその間隔にあります。 これで、GL_VERTEXATTRIB [0]である必要があります。(下記参照)。

有効性については。頂点attrib 0を使用するので、次のことが必要です。

glenablevertexattribarray(0)

一般的なものを理解することに関するアドバイス:黒に明確にしないでください、それは黒いものが描かれているかどうか、または何も描かれていないかどうかを理解するのがより困難になります(それを変更するためにglclearcolorを使用してください)。

Pedantic側では、あなたのGlshaderSourceの呼び出しは、あなたがポインターをキャストするとき、疑わしいように見えます。私はそれをきれいにします

glShaderSource(fs, 1, fragment_shader_code, NULL);

現在&fragment_shader_codeで動作する理由 面白い, 、しかし、ここでは、なぜあなたが単純化しないのかわかりません。

== add ==を編集します

ああ、私がgl_vertexattribで何を考えていたかわからない。しばらく経ちました私はこれを見ていませんでした、そして私はちょうど私自身の機能を作りました...

非ビルドイン属性を提供する標準的な方法は、実際にはGL4.1まで自明ではありません。

// glsl
attribute vec4 myinput;
gl_Position = myinput;

// C-code, rely on linker for location
glLinkProgram(prog);
GLint location = glGetAttribLocation(prog, "myinput");
glEnableVertexAttribArray(location, ...)

// alternative C-code, specify location
glBindAttribLocation(prog, 0, "myinput");
glLinkProgram(prog);
glEnableVertexAttribArray(0, ...)

GL4.1は最後に、シェーダー内の場所を直接指定することをサポートします。

// glsl 4.10
layout (location=0) in vec4 myinput;

他のヒント

  • 頂点シェーダー:gl_position = ftransform(); gl_vertexの代わりに。これにより、入力ベクトルにモデルビューマトリックス(カメラスペースのポイントが与えられます)を掛け、次に変換マトリックス(正規化されたデバイス座標のポイント、つまり画面上の位置)によって掛けられます。
  • Glenable(gl_vertex_array);レンダリングの前。 cf GLDRAWARRAYリファレンス :「gl_vertex_arrayが有効になっていない場合、幾何学的なプリミティブは生成されません。」

...私は他に何も見えません

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top