2015-12-02 1 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); 
} 

это, как я настроить мой ВБО

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

мои квадрациклы оказываются синими как вдоль оси х, так и оси 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); 

после связать ваш буфер VBÖ к нулю, пытающегося получить доступ это приведет к ошибке сегментации ...

После этого только убедившись, что я отправил соответствующие данные в ОГПУ и все другие код работал как и ожидалось.

   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 

после этих двух изменений все работало должным образом. Надеюсь, это может сэкономить некоторое время.

 Смежные вопросы

  • Нет связанных вопросов^_^