2017-06-13 1 views
0

J'ai les textures que je peux sans problème effectuer le rendu de manière régulière dans OpenGL. Mais maintenant je veux rendre les textures dans GLSL et c'est là que j'ai rencontré des problèmes avec actuellement. Je n'ai aucun problème avec le rendu d'une couleur vectorielle constante mais de toute façon il ne détecte pas la texture que j'envoie à GLSL.Impossible de rendre la texture SDL via GLSL

Voici le code:

GLunit wipeoutTexID; 

int main(int argc, char* args[]) { 

    // Start up SDL and create window 
    if (!init()) 
    { 
     printf("Failed to initialize!\n"); 
    } 
    else 
    { 
     // Main loop flag 
     bool quit = false; 

     // Event handler 
     SDL_Event e; 

     // Enable text input 
     SDL_StartTextInput(); 

     // While application is running 
     while (!quit) { 

      // Handle events on queue 
      while (SDL_PollEvent(&e) != 0) 
      { 
       // User requests quit 
       if (e.type == SDL_QUIT) { 
        quit = true; 
       } 
       // Handle keypress with current mouse position 
       else if (e.type == SDL_TEXTINPUT) 
       { 
        int x = 0, y = 0; 
        SDL_GetMouseState(&x, &y); 
        handleKeys(e.text.text[0], x, y); 
       } 
      } 

      // Update objects 
      update(); 

      // Render quad 
      render(); 

      // Update screen 
      SDL_GL_SwapWindow(gWindow); 

     } 

     // Disable text input 
     SDL_StopTextInput(); 

    } 

    // Free resources and close SDL 
    close(); 

    return 0; 

} 

bool init() { 

    .... 

    // Initialization flag 
    bool success = true; 

    .... 

    if(!initGL()) { 
     success = false; 
    } else 
    { 
     .... 

     wipeoutTexID = glLoadTexture(resPath + "wipeout.bmp"); 
     if(wipeoutTexID == NULL) 
     { 
      success = false; 
     } 

     .... 
    } 

    .... 

    return success; 

} 

bool initGL() 
{ 
// Success flag 
bool success = true; 

// Generate program 
gProgramID = glCreateProgram(); 

// Create vertex shader 
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 

// Get vertex source 
const GLchar* vertexShaderSource[] = 
{ 
    "#version 140\nin vec3 aPos; void main() { vec4(aPos.x, aPos.y, aPos.z, 1.0); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_MultiTexCoord0; }" 
}; 

// Set vertex source 
glShaderSource(vertexShader, 1, vertexShaderSource, NULL); 

// Compile vertex source 
glCompileShader(vertexShader); 

// Check vertex shader for errors 
GLint vShaderCompiled = GL_FALSE; 
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vShaderCompiled); 
if (vShaderCompiled != GL_TRUE) 
{ 
    printf("Unable to compile vertex shader %d!\n", vertexShader); 
    printShaderLog(vertexShader); 
    success = false; 
} 
else 
{ 
    // Attach vertex shader to program 
    glAttachShader(gProgramID, vertexShader); 

    // Create fragment shader 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 

    // Get fragment source 
    const GLchar* fragmentShaderSource[] = 
    { 
     "#version 140\nuniform sampler2D tex; uniform vec4 ourColor; void main() { vec4 color = texture2D(tex, gl_TexCoord[0].xy); gl_FragColor = mix(ourColor, color, 0.5); }" 
    }; 

    // Set fragment source 
    glShaderSource(fragmentShader, 1, fragmentShaderSource, NULL); 

    // Compile fragment source 
    glCompileShader(fragmentShader); 

    // Check fragment shader for errors 
    GLint fShaderCompiled = GL_FALSE; 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fShaderCompiled); 
    if (fShaderCompiled != GL_TRUE) 
    { 
     printf("Unable to compile fragment shader %d!\n", fragmentShader); 
     printShaderLog(fragmentShader); 
     success = false; 
    } 
    else 
    { 
     // Attach fragment shader to program 
     glAttachShader(gProgramID, fragmentShader); 

     // Link program 
     glLinkProgram(gProgramID); 

     // Check for errors 
     GLint programSuccess = GL_TRUE; 
     glGetProgramiv(gProgramID, GL_LINK_STATUS, &programSuccess); 
     if (programSuccess != GL_TRUE) 
     { 
      printf("Error linking program %d!\n", gProgramID); 
      printProgramLog(gProgramID); 
      success = false; 
     } 
     else 
     { 
      // Get vertex attribute location 
      gVertexPos2DLocation = glGetAttribLocation(gProgramID, "aPos"); 
      if (gVertexPos2DLocation == -1) 
      { 
       printf("LVertexPos2D is not a valid glsl program variable!\n"); 
       success = false; 
      } 
      else 
      { 
       // Initialize clear color 
       glClearColor(0.f, 0.f, 0.f, 1.f); 

       // VBO data 
       GLfloat vertexData[] = 
       { 
        0.0f, 0.0f, 
        0.0f, 1.0f, 
        1.0f, 1.0f, 
        0.0f, 1.0f 

       }; 

       // IBO data 
       GLuint indexData[] = { 0, 1, 2, 3 }; 

       // Create VBO 
       glGenBuffers(1, &gVBO); 
       glBindBuffer(GL_ARRAY_BUFFER, gVBO); 
       glBufferData(GL_ARRAY_BUFFER, /*2 * 4 * sizeof(GLfloat)*/ sizeof(vertexData), vertexData, GL_STATIC_DRAW); 

       // Create IBO 
       glGenBuffers(1, &gIBO); 
       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
       glBufferData(GL_ELEMENT_ARRAY_BUFFER, /*4 * sizeof(GLuint)*/ sizeof(indexData), indexData, GL_STATIC_DRAW); 
      } 
     } 
    } 
} 

return success; 
} 


GLuint glLoadTexture(const std::string &file) { 

GLuint tex; 
glGenTextures(1, &tex); 

glBindTexture(GL_TEXTURE_2D, tex); 

float color[] = {1.0f, 0.0f, 0.0f, 1.0f}; 
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color); 

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

glGenerateMipmap(GL_TEXTURE_2D); 

gSurface = NULL; 
gSurface = SDL_LoadBMP(file.c_str()); 

if (gSurface == NULL) 
{ 
    return NULL; 
} 
else 
{ 
    std::cout << "Image height: " << gSurface->h << std::endl; 
    std::cout << "Image width: " << gSurface->w << std::endl; 
    std::cout << "Images Pixels: " << gSurface->pixels << std::endl; 
    std::cout << "Images BitsPerPixel: " << gSurface->format->BitsPerPixel << std::endl; 
    std::cout << "Images Rmask: " << gSurface->format->Rmask << std::endl; 
    std::cout << "Images Surface: " << gSurface << std::endl; 

    int mode = GL_RGB; 

    if (gSurface->format->BitsPerPixel == 4) 
    { 
     mode = GL_RGBA; 
    } 

    GLenum data_fmt = mode; 
    Uint8 test = SDL_MapRGB(gSurface->format, 0xAA, 0xBB, 0xCC) & 0xFF; 
    if (test == 0xAA) data_fmt = GL_RGB; 
    else if (test == 0xCC) data_fmt = 0x80E0;//GL_BGR; 
    else { 
     printf("Error: \"Loaded surface was neither RGB or BGR!\""); 
     return NULL; 
    } 

    glTexImage2D(GL_TEXTURE_2D, 0, mode, gSurface->w, gSurface->h, 0, data_fmt, GL_UNSIGNED_BYTE, gSurface->pixels); 
    SDL_FreeSurface(gSurface); 

    return tex; 
} 

} 

void render() { 

    // Clear color buffer 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    glActiveTexture(GL_TEXTURE0 + 0); 
    glBindTexture(GL_TEXTURE_2D, wipeoutTexID); 
    glUniform1i(glGetUniformLocation(gProgramID, "tex"), 0); 

    // Bind program 
    glUseProgram(gProgramID); 

    // Enable vertex position 
    glEnableVertexAttribArray(gVertexPos2DLocation); 

    // Set vertex data 
    glBindBuffer(GL_ARRAY_BUFFER, gVBO); 
    glVertexAttribPointer(gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), BUFFER_OFFSET(6 * sizeof(float))); 

    float timeValue = SDL_GetTicks(); 
    float greenValue = 0.8f - 0.2f * abs(sin(0.001f*timeValue)); 
    int vertexColorLocation = glGetUniformLocation(gProgramID, "ourColor"); 
    glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); 

    // Set index data and render 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
    glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL); 

    // Disable vertex position 
    glDisableVertexAttribArray(gVertexPos2DLocation); 

    // Unbind program 
    glUseProgram(NULL); 

    glColor4f(1.f, 1.f, 1.f, 0.f); 
} 

Pouvez-vous voir où je fais mal?

Vertex shader:

#version 140 
in vec3 aPos; 

void main() 
{ 
    vec4(aPos.x, aPos.y, aPos.z, 1.0); 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
} 

Fragment shaders:

#version 140 
uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() { 
    vec4 color = texture2D(tex, gl_TexCoord[0].xy); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 
+1

S'il vous plaît code postal de shaders de manière plus lisible – Jeka

+0

Essayez faire les coordonnées texture d'affichage couleur pour vérifier si elle correcte. Habituellement, la sortie du vertex shader par coordonnées de texture de vertex est utilisée dans le shader de fragment. Je vois que vous utilisez des variables intégrées, mais je ne suis pas sûr de la façon dont ils fonctionnent – Jeka

+0

Ok, j'ai mis à jour le poste avec le code structuré et lisible de ces shaders. – john13th

Répondre

0

Solution la plus rapide et la plus simple est d'ajouter la texture coord en tant que sortie dans vertex shaders:

Vertex shader:

#version 140 
in vec3 aPos; 
out vec2 uv; 

void main() 
{ 
    uv = gl_Vertex.xy; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
} 

shader Fragment:

#version 140 
in vec2 uv; 
uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() { 
    vec4 color = texture2D(tex, uv); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 

Pour une meilleure compréhension jeter un oeil à quelques tutoriels axés sur OpenGL moderne, vous utilisez des vieilles méthodes dépréciées.

0

Il existe un problème de l'ordre de vos instructions dans la fonction render, car glUniform spécifie la valeur d'une variable uniforme pour l'objet programme en cours.

L'emplacement uniforme peut être récupéré à tout moment par glGetUniformLocation et stocké pour une utilisation ultérieure, après que le programme est lié avec succès (glLinkProgram):

int texLocation = glGetUniformLocation(gProgramID, "tex"); 

Mais pour définir la valeur d'une variable uniforme, la programme doit être le programme actif (glUseProgram). Remarque, il n'y a pas de paramètre pour sélectionner le programme, dans la sinature de glUniform.
Vous devez utiliser le programme,

// Bind program 
glUseProgram(gProgramID); 

avant vous définissez les valeurs des uniformes, parce que les opérations de réglage fonctionne sur le programme actuellement utilisé:

glUniform1i(texLocation, 0 /*texture unit 0*/); 

Dans la fonction render vous avez dans l'ordre inverse.

En outre, la technologie utilisée pour vor l'attribut de texture est obsolète, voir GLSL : common mistakes. Voyez ce que vous faites pour les sommets in vec3 aPos; et faites-le pour la coordonnée de texture.

Vertex shader:

#version 140 

in vec3 aPos; 
in vec2 aTexCoord; 

out vec3 texCoord; 

void main() 
{ 
    texCoord = aTexCoord; 
    gl_Position = gl_ModelViewProjectionMatrix * vec3(aPos, 1.0); 
} 

shader Fragment:

#version 140 

in texCoord; 

uniform sampler2D tex; 
uniform vec4 ourColor; 

void main() 
{ 
    vec4 color = texture2D(tex, texCoord.st); 
    gl_FragColor = mix(ourColor, color, 0.5); 
} 

Créer les tampons de tableau:

GLfloat vertexData[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 
GLfloat texCoordData[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 
GLuint indexData[] = { 0, 1, 2, 3 }; 

GLuint gVBO[2] 
glGenBuffers(2, &(gVBO[0])); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[0]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[1]); 
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoordData), texCoordData, GL_STATIC_DRAW); 
GLuint gIBO; 
glGenBuffers(1, &gIBO); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW); 

Obtenez les indices d'attributs du programme de shaders:

gVertexPos2DLocation = glGetAttribLocation(gProgramID, "aPos"); 
gTexCoordLocation = glGetAttribLocation(gProgramID, "aTexCoord"); 

Spécifiez le sommet des attributs, activez les attributs de sommet et dessiner et le maillage:

glBindBuffer(GL_ARRAY_BUFFER, gVBO[0]); 
glVertexAttribPointer(gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glBindBuffer(GL_ARRAY_BUFFER, gVBO[1]); 
glVertexAttribPointer(gTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); 
glEnableVertexAttribArray(gVertexPos2DLocation); 
glEnableVertexAttribArray(gTexCoordLocation); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIBO); 
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL);