2010-02-06 151 views
4

我在使用OpenGL正确地将几何贴图映射到几何时遇到了问题。事实上,我似乎甚至打破了过去一直正常工作的颜色插值。我在C99中创建了一个使用SDL,GLee和SOIL的测试用例。在OpenGL中将纹理映射到VBO

#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 2010-02-06 11:09:59

1

着色器包括子表达式

texture2D(sampler0, _texcoord) * 0.01 

这将使你的纹理上大多数显示器基本上是看不见的,是不是?

+0

啊是的,但这不是问题。这是从我周围玩耍,看看颜色来自哪里。 – jsimmons 2010-02-06 05:34:49

0

Afaik您需要在为VBO绑定纹理之前使用glClientActiveTexture()。