2012-01-05 3 views
1

Я хочу обернуть изображение размером 1024 * 512 вокруг сферы.Текстурирование сферы в OpenGL 3+

Вот мой код: (не все показаны)

в main.cpp:

struct Vertex { 

    GLdouble position[3]; 
    GLfloat color[3]; 
    GLfloat textureUV[2]; 
}; 

void SetupGemetry() { 

    //Allocate 4 VBOs 
    glGenBuffers(4, vbo); 

    } 

//Setting the current Buffer. 
void setBuffer(int buffer_no, int no_vertices, Vertex *vertices_array) 
{ 

    glBindBuffer(GL_ARRAY_BUFFER, vbo[buffer_no]); 

    glBufferData (GL_ARRAY_BUFFER, no_vertices * sizeof (struct Vertex), vertices_array, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(0); 

    glVertexAttribPointer ((GLuint) 0, 3, GL_DOUBLE, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) 
    offsetof(struct Vertex ,position));   

    glEnableVertexAttribArray (1); 

    glVertexAttribPointer ((GLuint) 1, 3, GL_FLOAT, GL_FALSE, sizeof (struct Vertex), (const GLvoid*) 
    offsetof(struct Vertex,color)); 

    //Textute Handling 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer((GLuint) 2,3,GL_FLOAT,GL_FALSE,sizeof(struct Vertex),(const GLvoid*)offsetof(struct Vertex ,texture)); 

}

сейчас в моей Sphere.cpp (здесь я загружаю * .bmp файл)

GLuint Sphere::loadBMP_custom(const char * imagepath) 
{ 
    // Data read from the header of the BMP file 
    unsigned char header[54]; // Each BMP file begins by a 54-bytes header 
    unsigned int dataPos;  // Position in the file where the actual data begins 
    unsigned int width, height; 
    unsigned int imageSize; // = width*height*3 
    // Actual RGB data 
    unsigned char * data; 
    // Open the file 
    FILE * file = fopen(imagepath,"rb"); 
    if (!file) 
    { 
     printf("Image could not be opened\n"); 
     return 0; 
    } 
    //Checking the header file 
    if (fread(header, 1, 54, file)!=54) 
    { // If not 54 bytes read : problem 
     printf("Not a correct BMP file\n"); 
     return false; 
    } 
    if (header[0]!='B' || header[1]!='M') 
    { 
     printf("Not a correct BMP file\n"); 
     return 0; 
    } 

    dataPos = *(int*)&(header[0x0A]); 
    imageSize = *(int*)&(header[0x22]); 
    width  = *(int*)&(header[0x12]); 
    height  = *(int*)&(header[0x16]); 
    // Some BMP files are misformatted, guess missing information 
    if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component 
    if (dataPos==0)  dataPos=54; // The BMP header is done that way 

    // Create a buffer 
    data = new unsigned char [imageSize]; 

    // Read the actual data from the file into the buffer 
    fread(data,1,imageSize,file); 

    //Everything is in memory now, the file can be closed 
    fclose(file); 

    //OpenGL Part 
    // Create one OpenGL texture 
    GLuint textureID; 
    glGenTextures(1, &textureID); 

    // "Bind" the newly created texture : all future texture functions will modify this texture 
    glBindTexture(GL_TEXTURE_2D, textureID); 

    // Give the image to OpenGL 
    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
} 

void Sphere::SetupShaders_sphere(void){ 

    // Read our shaders into the appropriate buffers 
    sphere_vertexsource = filetobuf_sphere("vertex_shader_2.vert"); 
    sphere_fragmentsource = filetobuf_sphere("fragment_shader_2.frag"); 

    //Assign our handles a "name" to new shader objects 
    sphere_vertexshader = glCreateShader(GL_VERTEX_SHADER); 
    sphere_fragmentshader = glCreateShader(GL_FRAGMENT_SHADER); 

    // Associate the source code buffers with each handle 
    glShaderSource(sphere_vertexshader, 1, (const GLchar**)&sphere_vertexsource, 0); 
    glShaderSource(sphere_fragmentshader, 1, (const GLchar**)&sphere_fragmentsource, 0); 

    //Setting them up by compiling, attaching and linking them! 
    glCompileShader(sphere_vertexshader); 
    glCompileShader(sphere_fragmentshader); 

    sphere_shaderprogram = glCreateProgram(); 
    glAttachShader(sphere_shaderprogram, sphere_vertexshader); 
    glAttachShader(sphere_shaderprogram, sphere_fragmentshader); 

    glBindAttribLocation(sphere_shaderprogram, 0, "in_Position"); 
    glBindAttribLocation(sphere_shaderprogram, 1, "in_Color"); 

    glLinkProgram(sphere_shaderprogram); 
    glUseProgram(sphere_shaderprogram); 

} 

теперь мой фрагмент и вершинные шейдеры:

Vertex:

#version 330 core 

// Input vertex data, different for all executions of this shader. 
layout(location = 0) in vec3 in_Position; 
layout(location = 1) in vec3 inColor; 
layout(location = 2) in vec2 vertexUV; 

// Output data ; will be interpolated for each fragment. 
out vec2 UV; 

// Values that stay constant for the whole mesh. 
uniform mat4 MVP_matrix; 

void main(){ 

    // Output position of the vertex, in clip space : MVP * position 
    gl_Position = MVP_matrix * vec4(in_Position,1); 

    // UV of the vertex. No special space for this one. 
    UV = vertexUV; 
} 

Фрагмент:

#version 330 core 

// Interpolated values from the vertex shaders 
in vec2 UV; 

// Ouput data 
out vec3 color; 

// Values that stay constant for the whole mesh. 
uniform sampler2D myTextureSampler; 

void main(){ 

    // Output color = color of the texture at the specified UV 
    color = texture2D(myTextureSampler, UV).rgb; 
} 

Как преобразовать координаты файла изображения (УФ) в 3D-те? Как передать им вершинный шейдер? (я знаю, как передавать данные в вершину, я в основном имею в виду, как преобразовать файл 2D-изображения в 3D?) Например, я нашел этот хороший учебник

www.opengl-tutorial.org/beginners-tutorials/tutorial -5-a-textured-cube/

Это говорит: «Ну, нам нужно будет сделать то же самое здесь, но вместо того, чтобы давать триплеты буфера (R, G, B), мы дадим буфер (U, V) пар. "

// Two UV coordinatesfor each vertex. They were created with Blender. You'll learn shortly how to do this yourself. 
static const GLfloat g_uv_buffer_data[] = { 
    0.000059f, 1.0f-0.000004f, 
    0.000103f, 1.0f-0.336048f, 
    0.335973f, 1.0f-0.335903f, 
    1.000023f, 1.0f-0.000013f, 
    0.667979f, 1.0f-0.335851f, 
    0.999958f, 1.0f-0.336064f, 
    0.667979f, 1.0f-0.335851f, 
    0.336024f, 1.0f-0.671877f, 
    0.667969f, 1.0f-0.671889f, 
    1.000023f, 1.0f-0.000013f, 
    0.668104f, 1.0f-0.000013f, 
    0.667979f, 1.0f-0.335851f, 
    0.000059f, 1.0f-0.000004f, 
    0.335973f, 1.0f-0.335903f, 
    0.336098f, 1.0f-0.000071f, 
    0.667979f, 1.0f-0.335851f, 
    0.335973f, 1.0f-0.335903f, 
    0.336024f, 1.0f-0.671877f, 
    1.000004f, 1.0f-0.671847f, 
    0.999958f, 1.0f-0.336064f, 
    0.667979f, 1.0f-0.335851f, 
    0.668104f, 1.0f-0.000013f, 
    0.335973f, 1.0f-0.335903f, 
    0.667979f, 1.0f-0.335851f, 
    0.335973f, 1.0f-0.335903f, 
    0.668104f, 1.0f-0.000013f, 
    0.336098f, 1.0f-0.000071f, 
    0.000103f, 1.0f-0.336048f, 
    0.000004f, 1.0f-0.671870f, 
    0.336024f, 1.0f-0.671877f, 
    0.000103f, 1.0f-0.336048f, 
    0.336024f, 1.0f-0.671877f, 
    0.335973f, 1.0f-0.335903f, 
    0.667969f, 1.0f-0.671889f, 
    1.000004f, 1.0f-0.671847f, 
    0.667979f, 1.0f-0.335851f 
}; 

Должен ли я использовать блендер? Я нашел это http://www.opengl.org/wiki/Texturing_a_Sphere#2D_Texture_Mapping_a_Sphere , но до сих пор я не могу понять, что

ответ

1

Как преобразовать координаты файла изображения (УФ) в 3D-те?

У вас нет. Текстура не делает вашу геометрию. Вам также необходимо предоставить координаты для сферы. Нет, вам не нужно использовать Blender, который использовался только для экспорта некоторых данных вершин (позиций, нормалей и текстурных координат) для последующего использования. Таким образом, помимо УФ-буфера, также должно быть положение и нормальный буфер.

+0

У меня есть буфер положения сферы, и тоже нормальный! Проблема заключается в УФ-буфере. Я не знаю, как это реализовать. Учебники, которые я нашел, для меня непросты. Когда вы говорите: «Вам нужно также предоставить координаты для сферы», я уже это сделал. Я передаю координаты позиции вершинному шейдеру. –

+0

Тогда я не вижу вашей проблемы. Вы уже проходите UV-координаты. Это самый последний вызов glVertexAttribPointer в вашем фрагменте main.cpp (ну, это не совсем правильно, у вас есть только 2 элемента для каждого texcoord, а не 3). Как насчет того, чтобы вы загрузили свой исходный код где-то? Таким образом, я могу попытаться воспроизвести вашу проблему, исправить свой код, чтобы вы могли учиться на нем. – datenwolf

+0

Я еще не пропущу УФ, потому что я еще не вычислил их. У меня есть последний glVertexAttribPointer, как вы сказали, но я ничего не пропускаю, потому что я не понимаю, как UV-координаты связаны с цветами изображения, которое я пытаюсь обернуть на сфере. –

1

Вопрос «как преобразовать координаты файла изображения (УФ) в 3D?» звуки обратные. Вы должны спросить: «Как преобразовать координаты сферы (3D) в координаты изображения (УФ)? В образце учебника использовался Блендер для создания статического массива УФ-данных. Если вы вычисляете вершины сферы, вам нужно вычислить УФ-координаты одновременно и сохраняют их в структуре Vertex. Если у вас есть предварительно рассчитанный набор координат статической сферы, вам нужно вычислить аналогичный набор UV-координат. Идея состоит в том, чтобы взять 3D-данные и передать их через функцию отображения, которая возвращает U, V координаты, для которых пиксель текстуры используется для этой трехмерной точки.

Самый простой расчет - это то, которое использует полярные координаты (азимут, высота) и отображает их в диапазон U, V. Если вычисляются 3D-вершины сферы, скорее всего, алгоритм уже использует полярные координаты и вызывает триггерные функции для получения X, Y, Z.

Opengl.org link упоминает, что «копия» является предпочтительным подходом для текстурирования сферы. «Для получения наилучшего результата используйте куб-файл. Проблема с применением 2D-текстуры заключается в том, что когда вы обертываете 2D-текстуру на сферу, верхнюю и нижнюю области сферы, текстура выглядит сжатой».

Предлагаемая двумерная карта всегда будет иметь искажения при обертывании вокруг сферы или других трехмерных кривых. Можно настроить алгоритм отображения U, V, чтобы минимизировать эффекты или скрыть швы за пределами первичной линии визирования, но сфера вращается, они где-нибудь появятся.

+0

Это то, чего я не понимаю. Я могу легко вычислить УФ-координацию и сохранить их, как вы сказали в моей структуре Вершины, и передать их вершинному шейдеру. Но я не понимаю, как изображение связано со всей этой УФ-координатой, я имею в виду цвета и т. Д. –

+0

@TestTest: Возможно, это видео дает понять. Левая панель - это текстура, нижний левый угол изображения (U, V) = (0,0) и верхний правый угол (U, V) = (1,1), правая панель - это некоторая геометрия, в этом случае один треугольник. http://www.youtube.com/watch?v=I0kP_YA5oE0 – datenwolf

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