2016-09-24 3 views
1

Ich versuche, eine Textur in OpenGL zu laden, aber alles, was ich bekomme, ist schwarz. Ich habe überprüft, dass die Shader GL_TRUE beim Kompilieren zurückgeben. Also, ich glaube nicht, das ist die Frage ...Warum kann ich in OpenGL keine Textur anzeigen?

einige Dinge zu beachten:

Ich habe genommen und modifizierte Code https://open.gl/content/code/c3_multitexture.txt. Dies war ein Tutorial von https://open.gl/textures

Die Textur, die ich versuche zu laden ist aus einer 640 x 400 PGM-Datei. Sie können davon ausgehen, dass der Loader pgmImage die Datei korrekt lädt (ich habe es in GDB verifiziert). PGM ist 8-Bit B & W Daten. Hier versuche ich es einfach als roten Kanal zu verwenden, obwohl ich es auch gerne als B & W anzeigen lassen könnte.

Wohin gehe ich falsch?

Danke!

Code kompiliert mit: -lglut -lGLU -lGL -lm -lGLEW Flags in g ++ (einige sind nicht notwendig, ich weiß).

#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <math.h> 

// Include GLEW 
#include <GL/glew.h> 

//Glut 
#include <GL/glut.h> 

#include "shader.hpp" 
#include "PGM.hpp" 

GLuint programID; 
GLuint output_image; 

// Shader sources 
const GLchar* vertexSource = 
    "#version 450 core\n" 
    "in vec2 position;" 
    "in vec2 texcoord;" 
    "out vec2 Texcoord;" 
    "void main()" 
    "{" 
    " Texcoord = texcoord;" 
    " gl_Position = vec4(position, 0.0, 1.0);" 
    "}"; 
const GLchar* fragmentSource = 
    "#version 450 core\n" 
    "in vec2 Texcoord;" 
    "out vec4 outColor;" 
    "uniform sampler2D texData;" 
    "void main()" 
    "{" 
    " outColor = texture(texData, Texcoord);" 
    "}"; 



void display() 
{ 

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

    glClear(GL_COLOR_BUFFER_BIT); 

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 

    glFlush(); 
    glutSwapBuffers(); 

}  


void reshape(int width,int height) 
{ 
    double w2h = (height>0) ? (double)width/height : 1; 
    // Set viewport as entire window 
    glViewport(0,0, width,height); 

} 



int main(int argc, char** argv) 
{ 
    // Image setup 

    PGM pgmImage; 
    pgmImage.ReadFile("test.pgm"); 

    // Window Setup 

    glutInitWindowSize(640, 400); 
    glutInitWindowPosition (140, 140); 
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 
    glutInit(&argc, argv); 

    glutCreateWindow("OpenGL Application"); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 

    glewExperimental = true; // Needed for core profile 
    if (glewInit() != GLEW_OK) { 
     fprintf(stderr, "Failed to initialize GLEW\n"); 
     return -1; 
    } 

    // Vertices & texture init 

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

    GLuint vbo; 
    glGenBuffers(1, &vbo); 

    GLfloat vertices[] = { 
     // X Y  S T 
     -0.5f, 0.5f, 0.0f, 0.0f, // Top-left 
     0.5f, 0.5f, 1.0f, 0.0f, // Top-right 
     0.5f, -0.5f, 1.0f, 1.0f, // Bottom-right 
     -0.5f, -0.5f, 0.0f, 1.0f // Bottom-left 
    }; 

    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

    GLuint ebo; 
    glGenBuffers(1, &ebo); 

    GLuint elements[] = { 
     0, 1, 2, 
     2, 3, 0 
    }; 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); 

    // Create shaders 

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexSource, NULL); 
    glCompileShader(vertexShader); 


    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL); 
    glCompileShader(fragmentShader); 

    GLuint shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glBindFragDataLocation(shaderProgram, 0, "outColor"); 
    glLinkProgram(shaderProgram); 
    glUseProgram(shaderProgram); 

    // Vertex data specification 
    GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); 
    glEnableVertexAttribArray(posAttrib); 
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); 

    GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord"); 
    glEnableVertexAttribArray(texAttrib); 
    glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat))); 

    // Load Textures 

    //TODO: don't really need 2 textures, but just following along with example source code for now... 
    GLuint textures[2]; 
    unsigned char* image; 

    int width, height; 

    width = pgmImage.GetWidth(); 
    height = pgmImage.GetHeight(); 
    image = (unsigned char *)pgmImage.GetData(); 

    glGenTextures(2, textures); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, textures[0]); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, image); 


    glUniform1i(glGetUniformLocation(shaderProgram, "texData"), 0); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    // Start program 

    glutMainLoop(); 

    // Teardown 

    glDeleteTextures(2, textures); 

    glDeleteProgram(shaderProgram); 
    glDeleteShader(fragmentShader); 
    glDeleteShader(vertexShader); 

    glDeleteBuffers(1, &ebo); 
    glDeleteBuffers(1, &vbo); 

    glDeleteVertexArrays(1, &vao); 

    return 0; 
} 
+0

Irgendwann mussten Texturgrößen Potenzen von 2 sein; nicht sicher, ob dies in einigen Kontexten heute noch relevant ist. Haben Sie versucht, glGetError nach glTexImage2D zu überprüfen? Haben Sie stattdessen einen konstanten Farbfragment-Shader probiert, um zu überprüfen, ob die Koordinaten auf dem Bildschirm angezeigt werden? –

+0

Danke für die Antwort! Koordinaten sind auf dem Bildschirm. Ich bekomme einen blauen Hintergrund mit einer schwarzen Box, wo mein Quad ist. Du hast recht mit den Potenzen von 2, aber ich habe gelesen, dass dies in OpenGL 4.5 nicht von Bedeutung ist (könnte falsch sein). Ich werde mir ansehen, was GlError sagt und antworten. – Maxthecat

+0

Beim Aufruf von glTexImage2D ist ein ungültiger Vorgang aufgetreten. Das Format und die internen Formatparameter, die für die Übereinstimmung erforderlich sind. Ich setze das Format auf GL_R8UI, was den Fehler beseitigt, aber ich bekomme immer noch ein schwarzes Quad (keine Textur). – Maxthecat

Antwort

4

Wie Sie bereits gefunden hatten, das internalFormat und Format Ihren glTexImage2D() Anruf nicht kompatibel ist:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, image); 

GL_RED_INTEGER ist für Integer-Textur-Typen. Für 1-Komponenten-Texturdaten mit normierten Texturen, ist das richtige Format GL_RED:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, image); 

für neuen Code, würde ich immer dimensionierte Typen zu verwenden empfehlen, auch wenn unsized interne Typen wie GL_RGB für die Rückwärtskompatibilität noch gültig sind . Also für eine normalisierte Textur mit 3 8-Bit-Komponenten:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, image); 

Ihr Versuch GL_R8UI als das interne Format bei Verwendung schlug fehl, da Texturen ganze Zahl mit zusätzlichen Änderungen erfordert, insbesondere im Shader-Code, in dem Sie usampler2D verwenden müssten als Sampler-Typ, und befassen sich mit dem Abrufen ganzzahliger Werte beim Sampling der Texturen. Aber in deinem Fall war das nicht wirklich das, was du von Anfang an wolltest.