2010-02-06 179 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()。