2010-02-06 5 views
4

Je n'arrive pas à obtenir une texture à mapper correctement sur la géométrie avec OpenGL. En fait, il semble que j'ai même cassé l'interpolation de couleur qui fonctionnait bien. J'ai créé un cas de test dans C99 qui utilise SDL, GLee et SOIL.Problème de mappage des textures à VBO dans OpenGL

#include <stdbool.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

#include <SDL/SDL.h> 
#include <GL/GLee.h> 
#include <SOIL/SOIL.h> 

static const char *vertex_source = " \ 
uniform mat4 projection; \ 
uniform mat4 view_model; \ 
\ 
attribute vec2 vertex; \ 
attribute vec2 texcoord; \ 
attribute vec4 colour; \ 
\ 
varying vec2 _texcoord; \ 
\ 
void main() \ 
{ \ 
    gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \ 
    _texcoord = texcoord; \ 
    gl_FrontColor = colour; \ 
} "; 

static const char *fragment_source = " \ 
uniform sampler2D sampler0; \ 
\ 
varying vec2 _texcoord; \ 
\ 
void main() \ 
{ \ 
    gl_FragColor = texture2D(sampler0, _texcoord) * 0.01 + gl_Color; \ 
} "; 

typedef struct 
{ 
    GLfloat position[2]; 
    GLfloat texcoord[2]; 
    GLubyte colour[4]; 
} Vertex; 

static Vertex verts[] = { 
     { 
      .position = { 1, 1 }, 
      .texcoord = { 1, 1 }, 
      .colour = { 255, 0, 0, 255 }, 
     }, 
     { 
      .position = { -1, 1 }, 
      .texcoord = { 0, 1 }, 
      .colour = { 0, 255, 0, 255 }, 
     }, 
     { 
      .position = { -1, -1 }, 
      .texcoord = { 0, 0 }, 
      .colour = { 0, 0, 255, 255 }, 
     }, 
     { 
      .position = { 1, -1 }, 
      .texcoord = { 1, 0 }, 
      .colour = { 255, 255, 0, 255 }, 
     }, 
    }; 

static GLuint vertex, fragment, program, vbo, texture; 
static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc; 

static void init() 
{ 
    SDL_Init(SDL_INIT_EVERYTHING); 
    SDL_SetVideoMode(800, 800, 0, SDL_OPENGL); 

    glClearColor(1, 0, 0, 0); 

    glMatrixMode(GL_PROJECTION); 
    glOrtho(-1, 1, -1, 1, -1, 1); 

    /* Shaders */ 
    vertex = glCreateShader(GL_VERTEX_SHADER); 
    assert(vertex != 0); 
    fragment = glCreateShader(GL_FRAGMENT_SHADER); 
    assert(fragment != 0); 

    GLint length = strlen(vertex_source); 
    glShaderSource(vertex, 1, &vertex_source, &length); 
    length = strlen(fragment_source); 
    glShaderSource(fragment, 1, &fragment_source, &length); 

    glCompileShader(vertex); 
    glCompileShader(fragment); 

    program = glCreateProgram(); 

    glAttachShader(program, vertex); 
    glAttachShader(program, fragment); 

    glLinkProgram(program); 

    sampler_loc = glGetUniformLocation(program, "sampler0"); 
    vertex_loc = glGetAttribLocation(program, "vertex"); 
    texcoord_loc = glGetAttribLocation(program, "texcoord"); 
    colour_loc = glGetAttribLocation(program, "colour"); 

    /* VBO */ 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts[0], GL_STATIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    /* Texture */ 
    texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y); 
    assert(texture != 0); 
} 

static void draw() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    glUseProgram(program); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glUniform1i(sampler_loc, 0); 

    glMatrixMode(GL_MODELVIEW); 
    glPushMatrix(); 
    glScalef(.5, .5, .5); 

    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    glEnableVertexAttribArray(0); 

    glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position)); 
    glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord)); 
    glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour)); 

    glDrawArrays(GL_QUADS, 0, 4); 

    glDisableVertexAttribArray(0); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    glBindTexture(GL_TEXTURE_2D, 0); 
    glPopMatrix(); 

    glUseProgram(0); 
} 

static void shutdown() 
{ 
    SDL_Quit(); 
} 

int main() 
{ 
    init(); 
    atexit(shutdown); 

    while(true) 
    { 
     static SDL_Event event; 
     while(SDL_PollEvent(&event)) 
     { 
      switch(event.type) 
      { 
       case SDL_QUIT: 
        exit(0); 
        break; 

       default: 
        break; 
      } 
     } 

     draw(); 

     SDL_GL_SwapBuffers(); 

     if(glGetError() != GL_NO_ERROR) 
     { 
      printf("Error\n"); 
      exit(1); 
     } 
    } 

    return 0; 
} 

La seule chose qui rend est un carré bleu uni sur le dessus de la glClearColor.

Toute aide très appréciée.

Merci pour les réponses, j'ai joint un code fixe pour l'exhaustivité.

#include <stdbool.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

#include <SDL/SDL.h> 
#include <GL/GLee.h> 
#include <SOIL/SOIL.h> 

static const char *vertex_source = " \ 
uniform mat4 projection; \ 
uniform mat4 view_model; \ 
\ 
attribute vec2 vertex; \ 
attribute vec2 texcoord; \ 
attribute vec4 colour; \ 
\ 
varying vec2 _texcoord; \ 
\ 
void main() \ 
{ \ 
    gl_Position = gl_ModelViewProjectionMatrix * vec4(vertex, 0, 1); \ 
    _texcoord = texcoord; \ 
    gl_FrontColor = colour; \ 
} "; 

static const char *fragment_source = " \ 
uniform sampler2D sampler0; \ 
\ 
varying vec2 _texcoord; \ 
\ 
void main() \ 
{ \ 
    gl_FragColor = texture2D(sampler0, _texcoord) + gl_Color; \ 
} "; 

typedef struct 
{ 
    GLfloat position[2]; 
    GLfloat texcoord[2]; 
    GLubyte colour[4]; 
} Vertex; 

static Vertex verts[] = { 
     { 
      .position = { 1, 1 }, 
      .texcoord = { 1, 1 }, 
      .colour = { 255, 0, 0, 255 }, 
     }, 
     { 
      .position = { -1, 1 }, 
      .texcoord = { 0, 1 }, 
      .colour = { 0, 255, 0, 255 }, 
     }, 
     { 
      .position = { -1, -1 }, 
      .texcoord = { 0, 0 }, 
      .colour = { 0, 0, 255, 255 }, 
     }, 
     { 
      .position = { 1, -1 }, 
      .texcoord = { 1, 0 }, 
      .colour = { 255, 255, 0, 255 }, 
     }, 
    }; 

static GLuint vertex, fragment, program, vbo, texture; 
static GLint sampler_loc, vertex_loc, texcoord_loc, colour_loc; 

static void init() 
{ 
    SDL_Init(SDL_INIT_EVERYTHING); 
    SDL_SetVideoMode(800, 800, 0, SDL_OPENGL); 

    glClearColor(1, 0, 0, 0); 

    glMatrixMode(GL_PROJECTION); 
    glOrtho(-1, 1, -1, 1, -1, 1); 

    /* Shaders */ 
    vertex = glCreateShader(GL_VERTEX_SHADER); 
    assert(vertex != 0); 
    fragment = glCreateShader(GL_FRAGMENT_SHADER); 
    assert(fragment != 0); 

    GLint length = strlen(vertex_source); 
    glShaderSource(vertex, 1, &vertex_source, &length); 
    length = strlen(fragment_source); 
    glShaderSource(fragment, 1, &fragment_source, &length); 

    glCompileShader(vertex); 
    glCompileShader(fragment); 

    program = glCreateProgram(); 

    glAttachShader(program, vertex); 
    glAttachShader(program, fragment); 

    glLinkProgram(program); 

    sampler_loc = glGetUniformLocation(program, "sampler0"); 
    vertex_loc = glGetAttribLocation(program, "vertex"); 
    texcoord_loc = glGetAttribLocation(program, "texcoord"); 
    colour_loc = glGetAttribLocation(program, "colour"); 

    glUseProgram(program); 
    glUniform1i(sampler_loc, 0); 
    glUseProgram(0); 

    /* VBO */ 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts[0], GL_STATIC_DRAW); 
    glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, position)); 
    glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texcoord)); 
    glVertexAttribPointer(colour_loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), offsetof(Vertex, colour)); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    /* Texture */ 
    texture = SOIL_load_OGL_texture("test.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y); 
    assert(texture != 0); 
} 

static void draw() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    glUseProgram(program); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture); 

    glMatrixMode(GL_MODELVIEW); 
    glPushMatrix(); 
    glScalef(.5, .5, .5); 

    glEnableVertexAttribArray(vertex_loc); 
    glEnableVertexAttribArray(texcoord_loc); 
    glEnableVertexAttribArray(colour_loc); 

    glDrawArrays(GL_QUADS, 0, 4); 

    glDisableVertexAttribArray(vertex_loc); 
    glDisableVertexAttribArray(texcoord_loc); 
    glDisableVertexAttribArray(colour_loc); 

    glBindTexture(GL_TEXTURE_2D, 0); 
    glPopMatrix(); 

    glUseProgram(0); 
} 

static void shutdown() 
{ 
    SDL_Quit(); 
} 

int main() 
{ 
    init(); 
    atexit(shutdown); 

    while(true) 
    { 
     static SDL_Event event; 
     while(SDL_PollEvent(&event)) 
     { 
      switch(event.type) 
      { 
       case SDL_QUIT: 
        exit(0); 
        break; 

       default: 
        break; 
      } 
     } 

     draw(); 

     SDL_GL_SwapBuffers(); 

     if(glGetError() != GL_NO_ERROR) 
     { 
      printf("Error\n"); 
      exit(1); 
     } 
    } 

    return 0; 
} 

Répondre

5

Vous n'activez pas correctement les matrices d'attribution de sommets.

  • vous activez 0, ce qui ne peut même être quelque chose que vous utilisez (bien, dans la pratique, il est probablement vertex_loc, mais vous ne devriez pas compter sur elle)
  • vous ignorez les 2 autres tableaux

Effectuez les opérations suivantes:

glEnableVertexAttribArray(vertex_loc); 
glEnableVertexAttribArray(texcoord_loc); 
glEnableVertexAttribArray(colour_loc); 

Modifier pour ajouter: Je pourrais aussi bien indiquer d'autres détails:

  • Je ne définirais l'emplacement de l'échantillonneur qu'une seule fois. le paramétrer a tendance à forcer un travail supplémentaire dans le pilote, et puisque vous ne le fixerez qu'à la même unité de texture à chaque fois, vous pourriez aussi bien le faire lors de l'initialisation.

  • L'endroit que vous appelez glBindBuffer(GL_ARRAY_BUFFER, 0) n'est pas faux, mais je le mettrais juste après les appels de VertexAttribPointer. Le tampon actuellement lié est vraiment juste un argument supplémentaire à ces appels ... Et cela n'affecte pas l'appel de glDrawArrays lui-même.

+0

Yay je l'ai réparé. Merci beaucoup. (J'ai mis à jour le premier message avec mon nouveau code) – jsimmons

1

shader comprend la sous-expression

texture2D(sampler0, _texcoord) * 0.01 

qui rendrait votre texture essentiellement invisible sur la plupart des écrans, ne serait-il?

+0

Ah oui, mais ce n'est pas le problème. C'est parti de moi jouant pour voir d'où les couleurs venaient. – jsimmons

0

Afaik vous devez utiliser glClientActiveTexture() avant de lier une texture pour un VBO.

Questions connexes