Kann jemand entziffern, warum diese OpenGL Hallo Welt ein schwarzes Fenster zieht?

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

  •  27-09-2019
  •  | 
  •  

Frage

Bitte entschuldigen Sie die Länge (und die Breite, es ist aus Gründen der Übersichtlichkeit auf eine IDE). Aber ich dachte an die volle Länge des Codes zeigt, da der Zweck ein einfaches Hallo Welt in der modernen VBO und GLSL ist

Es wurde ursprünglich basierend auf http: // Menschen .freedesktop.org / ~ idr / OpenGL_tutorials / 02-GLSL-hallo-world.pdf

Der wichtigste Punkt ist keine einzelne Fehlermeldung oder Warnung ausgegeben wird - und Sie können die printfs zu sehen sind viel (eigentlich fast der gesamte Code wird versucht, auf Fehler gefangen werden).

Die Zusammenstellung erfolgt auf -std = c99 -pedantic -O0 -g -Wall (ohne Warnungen) so nicht viel Raum für Compiler-Fehler auch nicht.

Ich habe Stift meine Aufmerksamkeit darauf zu

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

und

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

(letzteres ist der einzige Teil des Codes ich voll und ganz verstehe noch nicht, die meisten obskure func ‚je‘)

Das Info log druckt nicht alles und es einen gesunden Text normalerweise nicht gedruckt werden, wenn die Shadern absichtlich ungültig gemacht werden. Daher ist es weder die Shadern String Zuordnung oder deren Zusammenstellung.

Können Sie etwas sehen, dass es druckt einen leeren Bildschirm machen könnte?

Es macht einen einzigen Punkt in der Mitte gedruckt, wenn glDrawArrays mit GL_POINTS verwendet wird, und es macht die Farbe wechseln, wenn glClear mit einem geeigneten glClearColor vorangestellt ist.

#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();
}
War es hilfreich?

Lösung

Die Erweiterung auf Calvin1602 Antwort:

ftransform setzt Matrizen, die Sie nicht verwenden. gl_Vertex sollte in Ordnung, hier sein, das endgültige Ergebnis in Anbetracht sollte das sein [-1: 1] ^ 3 Würfel und seine Daten in diesem Intervall. Nun sollte es sein gl_VertexAttrib [0], wenn Sie wirklich alle GL3.1 gehen wollen, aber gl_Vertex und gl_VertexAttrib [0] alias (siehe unten).

Wie für die Freigabe. Sie verwenden Vertex attrib 0, so benötigen Sie:

glEnableVertexAttribArray (0)

Eine Beratung über Sachen aus im Allgemeinen herauszufinden. Nicht zu schwarz löschen, es macht das Leben schwierig, herauszufinden, ob etwas schwarz gezeichnet wird, oder wenn nichts gezogen wird (Verwendung glClearColor zu ändern, dass)

Auf der pedantischen Seite, Ihre glShaderSource Anrufe verdächtig, wie Sie Zeiger um gegossen. Ich würde es aufzuräumen mit

glShaderSource(fs, 1, fragment_shader_code, NULL);

Der Grund, warum es derzeit mit & fragment_shader_code arbeitet, ist interessant , aber hier, ich sehe nicht, warum Sie vereinfachen nicht.

== bearbeiten hinzuzufügen ==

Gah, nicht sicher, was ich mit gl_VertexAttrib dachte. Es ist ein gewesen, während ich nicht auf diese aussehen, und ich nur meine eigene Funktion gemacht ...

Die Standardmethode nicht-integrierte Attribute zu schaffen ist eigentlich nicht-trivial bis 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 schließlich unterstützt die Lage direkt im Shader angibt.

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

Andere Tipps

  • Im Vertex-Shader: gl_Position = ftransform (); statt gl_Vertex. Dadurch wird der Eingangsvektor von dem Model-View-Matrix (was dem Punkt in Kameraraum), und dann durch die Transformationsmatrix (was den Punkt in normalisierten Vorrichtungskoordinaten, das heißt seine Position auf dem Bildschirm)
  • vervielfachen
  • glEnable (GL_VERTEX_ARRAY); vor dem Rendering. cf der glDrawArray Referenz : „Wenn GL_VERTEX_ARRAY nicht aktiviert ist, keine geometrische Primitive erzeugt werden. "

... Ich sehe nicht, etwas anderes

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top