Текстурирование сферы в OpenGL 3+ - PullRequest
1 голос
/ 05 января 2012

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

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

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

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

www.opengl-tutorial.org / beginners-tutorials/ tutorial-5-a-текстурированный-куб /

Это говорит: «Ну, мы должны сделать то же самое здесь, но вместо того, чтобы давать триплеты буфера (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, но все еще не могу понять это

Ответы [ 2 ]

1 голос
/ 06 января 2012

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

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

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

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

1 голос
/ 05 января 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...