2015-12-02 40 views
0

我寫了一些圖形編程已經有一段時間了,我一直在盯着這個相當長的一段時間,無法弄清楚我做錯了什麼。Opengl 330核心創建和使用紋理2D

這是我如何創建我的紋理。

GLuint create_texture(const char* filename) { 
    SDL_Surface* surface; 
    GLenum tex_format; 
    GLint num_colors; 
    GLuint tex_id; 
    char* file_path; 

file_path = get_resource(filename); 
surface = IMG_Load(file_path); 
if (!surface) { 
    SDL_Log("failed to create surface\n"); 
    SDL_Quit(); 
    return -1; 
} else { 
    if ((surface->w & (surface->w - 1)) != 0) { 
     SDL_Log("image { %s } width is not power of 2\n", filename); 
    } 
    if ((surface->h & (surface->h - 1)) != 0) { 
     SDL_Log("image { %s } height is not power of 2\n", filename); 
    } 

    num_colors = surface->format->BytesPerPixel; 
    if (num_colors == 4) { 
     if (surface->format->Rmask == 0x000000ff) 
      tex_format = GL_RGBA; 
     else 
      tex_format = GL_BGRA; 
    } 
    if (num_colors == 3) { 
     if (surface->format->Rmask == 0x000000ff) 
      tex_format = GL_RGB; 
     else 
      tex_format = GL_BGR; 

    } else { 
     SDL_Log("pixel image format shouldn't get here! Quitting\n"); 
     SDL_Quit(); 
    }; 

    glGenTextures(1, &tex_id); 
    glBindTexture(GL_TEXTURE_2D, tex_id); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

    glTexImage2D(GL_TEXTURE_2D, 0, tex_format, surface->w, surface->h, 0, 
       tex_format, GL_UNSIGNED_BYTE, surface->pixels); 
} 
if (surface) SDL_FreeSurface(surface); 
free(file_path); 

return tex_id; 
} 

上面的這段代碼對於加載圖像數據是正確的。

頂點着色器

#version 330 core 

layout (location = 0) in vec3 a_pos; 
layout (location = 1) in vec4 a_col; 
layout (location = 2) in vec2 a_tex; 

uniform mat4 u_mvp_mat; 
uniform mat4 u_mod_mat; 
uniform mat4 u_view_mat; 
uniform mat4 u_proj_mat; 

out vec4 f_color; 
out vec2 f_tex; 

void main() 
{ 
    gl_Position = u_mvp_mat * vec4(a_pos, 1.0); 
    f_tex = a_tex; 
    f_color = a_col; 
} 

片段着色器。

#version 330 core 

in vec4 f_color; 
out vec4 o_color; 

in vec2 f_tex; 
uniform sampler2D u_sprite_tex; 

void main (void) 
{ 
    o_color = f_color; 
    o_color = texture(u_sprite_tex, f_tex); 
} 

這是我的VBO

quad = ren2d_new(); //just a wrapper around a quad or two tri. 
ren2d_set_tint(quad, 0, 1, 0, 1); //setting the color to green 

pos_loc = get_attrib_location(ce_get_default_shader(), "a_pos"); 
col_loc = get_attrib_location(ce_get_default_shader(), "a_col"); 
mvp_matrix_loc = get_uniform_location(ce_get_default_shader(), "u_mvp_mat"); 
model_mat_loc = get_uniform_location(ce_get_default_shader(), "u_mod_mat"); 
view_mat_loc = get_uniform_location(ce_get_default_shader(), "u_view_mat"); 
proj_matrix_loc = 
    get_uniform_location(ce_get_default_shader(), "u_proj_mat"); 

tex_loc = get_uniform_location(ce_get_default_shader(), "u_sprite_tex"); 

camera = cam_2d_new(ce_get_width(), ce_get_height()); 

model_mat = mat4_identity(); 
mat4_scale(model_mat, 128, 128, 1); 

tex_id = create_texture("test.png"); 

glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 

glGenBuffers(1, &vert_buff); 
glBindBuffer(GL_ARRAY_BUFFER, vert_buff); 
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->vertices), quad->vertices, 
      GL_STATIC_DRAW); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glGenBuffers(1, &col_buff); 
glBindBuffer(GL_ARRAY_BUFFER, col_buff); 
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors, 
      GL_STATIC_DRAW); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(1); 

glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords), 
         quad->tex_coords); 
glEnableVertexAttribArray(2); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glGenBuffers(1, &ind_buff); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad->indices), quad->indices, 
      GL_STATIC_DRAW); 

glBindVertexArray(0); 

我怎麼設置,這是我的渲染功能:

glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 
glClear(GL_COLOR_BUFFER_BIT); 

//could my texturing problems be here? 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, tex_id); 
glUniform1i(tex_loc, 0); 

glUseProgram(ce_get_default_shader()->shader_program); 
glBindVertexArray(vao); 

//excuse the silly names 
ce_get_view_matrices(&vview_mat, &pproj_mat, &mmvp_mat); 

mat4_multi(&mmvp_mat, &vview_mat, model_mat); 
mat4_multi(&mmvp_mat, &pproj_mat, &mmvp_mat); 
glUniformMatrix4fv(mvp_matrix_loc, 1, GL_FALSE, mat4_get_data(&mmvp_mat)); 

glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, mat4_get_data(model_mat)); 
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, mat4_get_data(&vview_mat)); 
glUniformMatrix4fv(proj_matrix_loc, 1, GL_FALSE, mat4_get_data(&pproj_mat)); 

glDrawElements(GL_TRIANGLES, quad->vertex_count, GL_UNSIGNED_SHORT, 0); 
glBindVertexArray(0); 

我剛開黑四。我無法追查,現在我一直在盯着這幾個小時。

像這樣在片段着色器中做一些非常基本的測試。

#version 330 core 

in vec4 f_color; 
out vec4 o_color; 

in vec2 f_tex; 
uniform sampler2D u_sprite_tex; 

void main (void) 
{ 
    //o_color = f_color; 
    vec4 c; 
    if(f_tex.y == 1.0) { c = vec4(1.0, 0.0, 0.0, 1.0); } 
    if(f_tex.y == 0.0) { c = vec4(0.0, 0.0, 1.0, 1.0); } 
    o_color = c; 
    o_color = texture(u_sprite_tex, f_tex); 
} 

我的四邊形在x軸和y軸上都是藍色的。這似乎是0.0中傳遞的唯一值,這是沒有意義的。

回答

0

至少有兩件事情,可能是錯的:

glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords), 
        quad->tex_coords); 

你肯定quad->tex_coords包含4維向量?片段着色器預計vec2。如果每個頂點只提供兩個浮點數,則必須將第二個參數更改爲兩個。當OpenGL嘗試從太小的ARRAY_BUFFER讀取時,這也會導致分段錯誤。請注意,如果這些屬性對最終顏色沒有貢獻,則將其設置爲非活動狀態,因此只有在使用紋理時纔可以讀取紋理座標。

第二:在將數據上傳到紋理之前,您正在調用glGenerateMipmap

1

好吧,這絕對是我自己創作的問題。我得到分段錯誤的原因是因爲這個代碼。

glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 

glGenBuffers(1, &vert_buff); 
glBindBuffer(GL_ARRAY_BUFFER, vert_buff); 
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->vertices), quad->vertices, 
      GL_STATIC_DRAW); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glGenBuffers(1, &col_buff); 
glBindBuffer(GL_ARRAY_BUFFER, col_buff); 
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors, 
      GL_STATIC_DRAW); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(1); 
glBindBuffer(GL_ARRAY_BUFFER, 0); //right here 

glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords), 
         quad->tex_coords); 
glEnableVertexAttribArray(2); 


glGenBuffers(1, &ind_buff); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad->indices), quad->indices, 
      GL_STATIC_DRAW); 

glBindVertexArray(0); 

您的VBO緩衝區綁定到零試圖訪問它會導致段故障後...

後,只是確保我發送正確的數據到GPU和所有其他代碼工作如預期。

   GL_STATIC_DRAW); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

glGenBuffers(1, &col_buff); 
glBindBuffer(GL_ARRAY_BUFFER, col_buff); 
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors, 
      GL_STATIC_DRAW); 
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(1); 
//glBindBuffer(GL_ARRAY_BUFFER, 0); //right here remove this 

//properly setup the local data to gpu data 
glBufferData(GL_ARRAY_BUFFER, rend2d_get_sizeof_tex_coord(quad), 
      rend2d_get_tex_coord_data(quad), GL_STATIC_DRAW); 
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(2); 

glBindBuffer(GL_ARRAY_BUFFER, 0); //put it here after finished with vbo 

這兩個變化後,一切都按預期工作。希望這可以節省一些時間。