Я хочу, чтобы программа OpenGL могла представлять изображение и деформировать представленные изображения.
Хотя я добился рендеринга изображений с помощью OpenGL, я не мог знать, как деформировать 4 вершины изображения.
Пример, который мне нужен, это (ссылка)
Несмотря на то, что я изменил значение позиции, чтобы деформировать изображение, такой результат неверен.
Я не знаю, почему этот эффект кривой появляется. введите описание изображения здесь

Вот мой исходный код. Пожалуйста, дайте мне знать, как я могу подойти для искажения изображения.

void imageRender(Shader initShader, Shader imgShader, char *path){

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

float positions = { 0.5f, 0.5f, 0.0f, 
                    1.0f, -1.0f, 0.0f, 
                    -1.0f, -1.0f, 0.0f, 
                    -1.0f, 1.0f, 0.0f };

float vertices[] = {
    // positions                                 // colors           // texture coords
    position[0], position[1], position[2],   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
    position[3], position[4], position[5],   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
    position[6], position[7], position[8],   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
    position[9], position[10],position[11],  1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left 
};
unsigned int indices[] = {
    0, 1, 3,
    1, 2, 3
};

unsigned int VAO, VBO, EBO;

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute 
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); 
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);

// color attribute 
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);

//texture attribute 
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(3);


FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path, 0);
if (format == -1){
    cerr << BOLDRED << "[ERROR] IMAGE_NOT_FOUND" << RESET << endl;
    exit(1);
}

if (format == FIF_UNKNOWN){
    cerr << BOLDRED << "[ERROR] UNKNOWN_IMAGE_FORMAT" << RESET << endl;
    format = FreeImage_GetFIFFromFilename(path);
    if (!FreeImage_FIFSupportsReading(format)){
        cerr << BOLDRED << "[ERROR] IMAGE_FORMAT_NOT_READABLE" << RESET << endl;
        exit(1);
    }
}

FIBITMAP *bitmap = FreeImage_Load(format, path);
FIBITMAP *bitmap32;

int bitsPerPixel = FreeImage_GetBPP(bitmap);
bitmap32 = FreeImage_ConvertTo32Bits(bitmap);
int imageWidth = FreeImage_GetWidth(bitmap32);
int imageHeight = FreeImage_GetHeight(bitmap32);

GLubyte *textureData = FreeImage_GetBits(bitmap32);

GLuint texture1;
glGenTextures(1, &texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

initShader.use();
glBindVertexArray(VAO);

int initalTime = time(NULL);

while(1){

    glBindVertexArray(VAO);

    int timecal = time(NULL);
    //glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glfwSwapBuffers(window);
    glfwPollEvents();
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    if ((timecal - initalTime) > imageTime) // imageTime value is 10 
        break;
}

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glDeleteTextures(1, &texture1);// image
glDisable(GL_TEXTURE_2D);//image

FreeImage_Unload(bitmap32);
FreeImage_Unload(bitmap);

glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}

}

Код шейдера такой

//shader.vs
#version 330 core 
layout(location = 1) in vec3 position;
layout(location = 2) in vec3 color;
layout(location = 3) in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

void main()
{
    gl_Position = vec4(position, 1.0);
    Texcoord = texcoord; 
}

//shader.fs
#version 330 core 
in vec3 Color;
in vec2 Texcoord;

out vec4 outColor;
uniform sampler2D texture5;

void main()
{
    outColor = texture2D(texture5, Texcoord); 
}
0
YangSsong 27 Фев 2020 в 13:29

2 ответа

Лучший ответ

Я думаю, что вам нужно проективное преобразование. Вот пример с формулами, взятыми из принятого ответа в этот вопрос math.stackexchange:

Matrix4x4 MatFromPoints(Vector2 BL, Vector2 BR, Vector2 TL, Vector2 TR)
{
    Matrix4x4 m = new Matrix4x4(
        new Vector4(BL.x, BL.y, 1, 0), //col 1
        new Vector4(BR.x, BR.y, 1, 0), //col 2
        new Vector4(TL.x, TL.y, 1, 0), //col 3
        new Vector4(0, 0, 0, 1)        //col 4
        );

    var mI = m.inverse;
    var c = mI * new Vector4(TR.x, TR.y, 1, 0);

    return new Matrix4x4(
        new Vector4(BL.x * c.x, BL.y * c.x, c.x, 0),
        new Vector4(BR.x * c.y, BR.y * c.y, c.y, 0),
        new Vector4(TL.x * c.z, TL.y * c.z, c.z, 0),
        new Vector4(0, 0, 0, 1)
        );        
}

И с этим рассчитать матрицу преобразования:

//                         (-1,-1) (1,-1) (-1,1) (.5,.5)
Matrix4x4 A = MatFromPoints(fromBL, fromBR, fromTL, fromTR);
//                         (0,0) (1,0) (0,1) (1,1)
Matrix4x4 B = MatFromPoints(toBL, toBR, toTL, toTR);

Matrix4x4 UvTransform = B * A.inverse;

Установите UvTransform как униформу. И во фрагментном шейдере:

// pos is local vertex position
float4 uv = float4(pos.xy, 1, 0);
uv = mul(UvTransform, uv);
uv.xy = uv.xy / uv.z;

fixed4 outColor = tex2D(Texture, uv.xy);

И вы получите:
введите описание изображения здесь

1
Pluto 27 Фев 2020 в 20:07

Обтекание текстуры не является неправильным. Вы оборачиваете текстуру в 2 треугольника, определенных точками (0.5, 1), (1, -1), (-1, 1) и (1, -1), (-1, -1), (-1, 1 ) :

Обратите внимание, что текстура привязана к каждому треугольнику отдельно. Если вы хотите получить эффект 3d, вам нужно указать трехмерные координаты и использовать Перспектива проекция.

1
Rabbid76 27 Фев 2020 в 14:29