2015-04-05 2 views
1

Я пытаюсь изучить отображение текстуры с использованием программы Shader с помощью OpenGL 3.30. Я могу загрузить изображение, но я не могу правильно отобразить его на каждом кубе.Изображение текстуры не отображается правильно - OpenGL

Приведенный ниже код определяет свойства вершин, которые являются его вершинами и координатами текстуры, связанными с каждой вершиной куба. Затем создаются 2 VBOs, один содержит вершины куба, а другой содержит информацию текстур.

Я думаю, что я очень закрыт до конечного результата: я получил куб, загруженное изображение успешно, способное получить информацию об изображении. Так что же я сделал здесь неправильно?

Я использую stblib для загрузки изображения.

Это мой код:

#include <windows.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <stddef.h> /* must include for the offsetof macro */ 
#include <GL/glew.h> 
#include <GLFW/glfw3.h> 
#include <glm/glm.hpp> 
#include <glm/gtc/matrix_transform.hpp> 
#include <glm/gtc/type_ptr.hpp> 
#include <stdlib.h> 
#include "utils.h" 

#include "stb_image.h" 

struct Vertex { 
    GLdouble position[3]; 
    GLdouble texture[2]; 
    }; 
/* These pointers will receive the contents of our shader source code files */ 
GLchar *vertexsource, *fragmentsource; 
/* These are handles used to reference the shaders */ 
GLuint vertexshader, fragmentshader; 
/* This is a handle to the shader program */ 
GLuint shaderprogram; 
GLuint vbo[1]; /* Create handles for our Vertex Array Object and One Vertex Buffer Object */ 

//GLuint text_2d_1; 

const struct Vertex plane[24] = { 
       // Front Face 
     {{1.0f, 1.0f, 1.0f}, {0.0, 0.0}}, 
     {{-1.0f, 1.0f, 1.0f}, {1.0, 0.0}}, 
     {{-1.0f, -1.0f, 1.0f}, {1.0, 1.0}}, 
     {{ 1.0f, -1.0f, 1.0f}, {0.0, 1.0}}, 
     // Back Face 
     {{-1.0f, -1.0f, -1.0f}, {1.0, 0.0}}, 
     {{-1.0f, 1.0f, -1.0f}, {1.0, 1.0}}, 
     {{ 1.0f, 1.0f, -1.0f}, {0.0, 1.0}}, 
     {{ 1.0f, -1.0f, -1.0f}, {0.0, 0.0}}, 
     // Top Face 
     {{-1.0f, 1.0f, -1.0f}, {0.0, 1.0}}, 
     {{-1.0f, 1.0f, 1.0f}, {0.0, 0.0}}, 
     {{ 1.0f, 1.0f, 1.0f}, {1.0, 0.0}}, 
     {{ 1.0f, 1.0f, -1.0f}, {1.0, 1.0}}, 
     // Bottom Face 
     {{-1.0f, -1.0f, -1.0f}, {1.0, 1.0}}, 
     {{ 1.0f, -1.0f, -1.0f}, {0.0, 1.0}}, 
     {{ 1.0f, -1.0f, 1.0f}, {0.0, 0.0}}, 
     {{-1.0f, -1.0f, 1.0f}, {1.0, 0.0}}, 
     // Right face 
     {{1.0f, -1.0f, -1.0f}, {1.0, 0.0}}, 
     {{1.0f, 1.0f, -1.0f}, {1.0, 1.0}}, 
     {{1.0f, 1.0f, 1.0f}, {0.0, 1.0}}, 
     {{1.0f, -1.0f, 1.0f}, {0.0, 0.0}}, 
     // Left Face 
     {{-1.0f, -1.0f, -1.0f}, {0.0, 0.0}}, 
     {{-1.0f, -1.0f, 1.0f}, {1.0, 0.0}}, 
     {{-1.0f, 1.0f, 1.0f}, {1.0, 1.0}}, 
     {{-1.0f, 1.0f, -1.0f}, {0.0, 1.0}} 

}; 

void SetupGeometry() { 
    /* Allocate and assign One Vertex Buffer Object to our handle */ 
    glGenBuffers(1, vbo); 
    /* Bind our VBO as being the active buffer and storing vertex attributes (coordinates + colors) */ 
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); 
    /* Copy the vertex data from plane to our buffer */ 
    /* 12 * sizeof(GLfloat) is the size of the tetrahedrom array, since it contains 12 Vertex values */ 
    glBufferData (GL_ARRAY_BUFFER, 24 * sizeof (struct Vertex), plane, GL_STATIC_DRAW); 
    /* Specify that our coordinate data is going into attribute index 0, and contains three doubles per vertex */ 
    /* Note stride = sizeof (struct Vertex) and pointer = (const GLvoid*) 0 */ 
    glVertexAttribPointer ((GLuint) 0, 3, GL_DOUBLE, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof (struct Vertex,position)); 
    /* Enable attribute index 0 as being used */ 
    glEnableVertexAttribArray(0); 
    /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */ 
    /* Note stride = sizeof (struct Vertex) and pointer = (const GLvoid*) (3 * sizeof (GLdouble)) i.e. the size (in bytes) 
    occupied by the first attribute (position) */ 
    glVertexAttribPointer ((GLuint) 1, 3, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof(struct Vertex,texture)); // bug); 
    /* Enable attribute index 1 as being used */ 
    glEnableVertexAttribArray (1);/* Bind our fourth VBO as being the active buffer and storing vertex attributes (texture) */ 
    printf("vertex %d\n", offsetof(struct Vertex,position)); 
    printf("texture %d\n", offsetof(struct Vertex,texture)); 
} 

void SetupShaders(void) { 
    /* Read our shaders into the appropriate buffers */ 
    vertexsource = filetobuf("plane/plane.vert"); 
    fragmentsource = filetobuf("plane/plane.frag"); 
    /* Assign our handles a "name" to new shader objects */ 
    vertexshader = glCreateShader(GL_VERTEX_SHADER); 
    fragmentshader = glCreateShader(GL_FRAGMENT_SHADER); 
    /* Associate the source code buffers with each handle */ 
    glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0); 
    glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0); 
    /* Compile our shader objects */ 
    glCompileShader(vertexshader); 
    glCompileShader(fragmentshader); 
    /* Assign our program handle a "name" */ 
    shaderprogram = glCreateProgram(); 
    glAttachShader(shaderprogram, vertexshader);/* Attach our shaders to our program */ 
    glAttachShader(shaderprogram, fragmentshader); 
    glBindAttribLocation(shaderprogram, 0, "in_Position"); /* Bind attribute 0 (coordinates) to in_Position and attribute 1 (colors) to in_Texture */ 
    glBindAttribLocation(shaderprogram, 1, "in_Texture"); 
    glLinkProgram(shaderprogram);/* Link our program, and set it as being actively used */ 
    glUseProgram(shaderprogram); 
    } 

void Render(int i) { 
    GLfloat angle; 
    glm::mat4 Projection = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f); 
    angle = (GLfloat) (i % 360); 
    glm::mat4 View = glm::mat4(1.); 
    View = glm::translate(View, glm::vec3(0.f, 0.f, -5.0f)); 
    View = glm::rotate(View, angle * -1.0f, glm::vec3(1.f, 0.f, 0.f)); 
    View = glm::rotate(View, angle * 0.5f, glm::vec3(0.f, 1.f, 0.f)); 
    View = glm::rotate(View, angle * 0.5f, glm::vec3(0.f, 0.f, 1.f)); 
    glm::mat4 Model = glm::mat4(1.0); 
    glm::mat4 MVP = Projection * View * Model; 
    glUniformMatrix4fv(glGetUniformLocation(shaderprogram, "mvpmatrix"), 1, GL_FALSE, glm::value_ptr(MVP)); 
    /* Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram */ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glDrawArrays(GL_QUADS, 0, 24); 
    /* Invoke glDrawArrays telling that our data consists of individual triangles */ 
} 

int reverse = 1; 

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { 
    if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS) 
     glfwSetWindowShouldClose(window, GL_TRUE); 
    if ((key == GLFW_KEY_R) && action == GLFW_PRESS) 
     reverse = 1 - reverse; // togrls reverse from 0 to 1 to o to ... 
    } 


int main(void) { 
    int k = 0; 
    GLFWwindow* window; 
    if(!glfwInit()) { 
      printf("Failed to start GLFW\n"); 
      exit(EXIT_FAILURE); 
      } 
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); 
    if (!window) { 
      glfwTerminate(); 
      printf("GLFW Failed to start\n"); 
      return -1; 
      } 
    /* Make the window's context current */ 
    glfwMakeContextCurrent(window); // IMPORTANT: Must be done so glew recognises OpenGL 
    glewExperimental = GL_TRUE; 
    int err = glewInit(); 
    if (GLEW_OK != err) { 
      /* Problem: glewInit failed, something is seriously wrong. */ 
      fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); 
      } 
    fprintf(stderr, "Glew done\n"); 
    glfwSetKeyCallback(window, key_callback); 
    fprintf(stderr, "GL INFO %s\n", glGetString(GL_VERSION)); 
    SetupGeometry(); 
    SetupShaders(); 
    int w, h, n, O; 
    char *filename = "plane/rock.bmp"; 
    unsigned char * data = stbi_load(filename, &w, &h, &n, 0); //image data 
    if(data == NULL) { 
     print("Image not loaded"); 
     const char *error = stbi_failure_reason(); 
     printf("Failure reason %s\n", error); 
     exit(0); 
    }else{ 
     print("Image loaded successfully"); 
    } 
    printf("Image Stats %d %d %d\n", w, h, n); 
// for(int d = 0; d < w * h * 3; d++) 
//  printf("img content: %i\n",data[d]); 
    printf (" first 4 bytes are: %i %i %i %i\n", data[ 0], data[ 1], data[ 2], data[ 3]); 

    GLuint tex; 
    glGenTextures(1, &tex); 
    Print("Texture"); 
    Print(GL_TEXTURE0); 
    print((int) tex); 
    //glActiveTexture(GL_TEXTURE0); 
    /* 
    * To get the texture to activate, take the base texture GL_TEXTURE0 and add the value of the generated texture. 
    * This needs checking with more than one texture. 
    * beware of NIDIA specific. 
    */ 
    //glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, tex); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data); 
    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    stbi_image_free(data); // free up image data 
    //glDisable(gl_te) 

    glEnable(GL_DEPTH_TEST); 
    glClearColor(0.0, 0.0, 0.0, 1.0);/* Make our background black */ 
    while(!glfwWindowShouldClose(window)) {// Main loop 
     Render(k);// OpenGL rendering goes here... 
      if(reverse) 
       k--; 
      else 
       k++; 

     Sleep(20); 
     glfwSwapBuffers(window);// Swap front and back rendering buffers 
     glfwPollEvents(); 
     } 
    glfwTerminate();// Close window and terminate GLFW 
    exit(EXIT_SUCCESS);// Exit program 
    } 

вершинный шейдер:

#version 330 
precision highp float; 
in vec3 in_Position; 
in vec2 in_Texture; 

// mvpmatrix is the result of multiplying the model, view, and projection matrices */ 
uniform mat4 mvpmatrix; 

out vec2 UV; 
void main(void) { 
// Multiply the mvp matrix by the vertex to obtain our final vertex position 
    gl_Position = mvpmatrix * vec4(in_Position, 1.0); 
    UV = in_Texture; 
} 

Фрагмент шейдеры:

#version 330 
precision highp float; 

in vec2 UV; 

out vec3 color; 

uniform sampler2D myTexture; 

void main(void) { 
    color = texture(myTexture, UV).rgb; 
} 

Это входное изображение: rock.bmp

Это результат работы программы: output

ответ

2

Существует некоторая несогласованность в типах данных, которые вы используете. Декларация вашей структуры использует двойников для обеих позиций и текстурных координат:

struct Vertex { 
    GLdouble position[3]; 
    GLdouble texture[2]; 
}; 

Во время установки атрибута, вы используете различные типы:

glVertexAttribPointer ((GLuint) 0, 3, GL_DOUBLE, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof (struct Vertex,position)); 
glVertexAttribPointer ((GLuint) 1, 3, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof(struct Vertex,texture)); // bug); 

координаты текстуры используются как GL_FLOAT здесь. Кроме того, вы указываете здесь 3 компонента, где структура имеет только 2.

Существует очень редко причина использовать двойные координаты. В любом случае OpenGL будет использовать 32-битную точность. Поэтому, если вы укажете атрибуты как двойные, вы добавите только конверсии и будете использовать больше памяти.

Чтобы использовать поплавок для всего, то структура должна быть объявлена ​​так:

struct Vertex { 
    GLfloat position[3]; 
    GLfloat texture[2]; 
}; 

Спецификация атрибута будет выглядеть следующим образом:

glVertexAttribPointer ((GLuint) 0, 3, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof (struct Vertex,position)); 
glVertexAttribPointer ((GLuint) 1, 2, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof(struct Vertex,texture)); // bug); 
+0

спасибо!Типы данных, которые я объявил в конструкторе, действительно застрелили меня: D –

+0

У меня вопрос: есть ли разница между текстурированием сферы и куба? –

+0

Nice catch: я полностью пропустил эту проблему с типом данных. – datenwolf

2

Проблема заключается здесь:

/* Specify that our color data is going into attribute index 1, 
    and contains three floats per vertex */ 
/* Note stride = sizeof (struct Vertex) and 
    pointer = (const GLvoid*) (3 * sizeof (GLdouble)) 
    i.e. the size (in bytes) occupied by the first attribute 
    (position) */ 
glVertexAttribPointer ((GLuint) 1, 3, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) offsetof(struct Vertex,texture)); 

Фактура вершина координат атрибут имеет два элемента, но вы говорите OpenGL, что есть 3 элемента в последовательности. Это, очевидно, не соответствует вашим данным вершин или типу атрибута вершин шейдера. Отрегулируйте размер элемента до 2, и он должен работать. О, и вам не нужно явно указывать числовой литерал на GLuint.

+0

Он по-прежнему не работает. Был произведен такой же выход. –

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