2010-02-06 5 views
4

У меня возникли проблемы с получением текстуры для правильной карты на геометрию с OpenGL. На самом деле я, кажется, даже сломал интерполяцию цвета, которая использовалась для работы. Я создал тестовый пример на C99, который использует SDL, GLee и SOIL.Проблема отображения текстур в VBO в 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; 
} 

Единственное, что оказывает это простой синий квадрат на вершине glClearColor.

Любая помощь очень ценится.

Спасибо за ответы, я приложил исправленный код для полноты.

#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; 
} 

ответ

5

Неправильно назначены массивы атрибутов вершин.

  • включения 0, которая не может быть даже то, что вы используете (ну, на практике, это, вероятно, vertex_loc, но вы не должны полагаться на него)
  • вы игнорируете другие 2 массивы

Попробуйте следующее:

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

Изменить, чтобы добавить: я мог бы также указать на другие детали:

  • Я установил местоположение пробоотборника только один раз. установка его приводит к дополнительной работе в драйвере, и поскольку вы будете устанавливать ее только на одну и ту же единицу текстуры каждый раз, вы также можете сделать это при инициализации.

  • Неверное место, которое вы вызываете glBindBuffer(GL_ARRAY_BUFFER, 0), но я бы поместил его сразу после вызовов VertexAttribPointer. В настоящий момент связанный буфер действительно является дополнительным аргументом для этих вызовов ... И это не влияет на вызов glDrawArrays.

+0

Я исправился. Большое спасибо. (Я обновил первое сообщение своим новым кодом) – jsimmons

1

Ваш шейдер включает подвыражению

texture2D(sampler0, _texcoord) * 0.01 

Что бы сделать вашу текстуру по существу невидим на большинстве дисплеев, не так ли?

+0

Ах да, но это не проблема. Это осталось от меня, чтобы посмотреть, откуда пришли цвета. – jsimmons

0

Afaik Вам необходимо использовать glClientActiveTexture() перед связыванием текстуры для VBO.