OpenGL 纹理混合

问题描述 投票:0回答:1

所以我在 opengl 中有一个纹理类,它基本上是一个缓冲区并在屏幕上渲染 2D 纹理。就其本身而言,它工作得非常好,并允许我在屏幕上渲染尽可能多的纹理。但我想添加一个

transition
函数,该函数获取第二个纹理以及原始纹理,并将它们混合在一个矩形中。

在一个没有纹理类的独立项目中,我设法在片段着色器的帮助下使其工作。但是,当我将过渡函数添加到纹理类并用它创建第二个不是过渡的纹理时,一切都变得很奇怪,第二个矩形消失了,并且出于某种原因,应该过渡的第一个矩形使用了第二个矩形纹理。

所以应该发生这样的情况:使用

render
函数的带有 data1 的矩形应该出现在屏幕上。屏幕上应该出现另一个具有
transition
功能的矩形,但同时使用 data2 和 data3。到目前为止,这是我的代码:

主.cpp

class Texture{
private:
    typedef struct transtex_s { 
        uint8_t* buff;
        int w, h;
    } transtex; 


    Shader ourShader;
    unsigned int texture;
    unsigned int texture2;
    unsigned int VBO, VAO, EBO;
public:
    transtex tex2;

    Texture(float pos, bool is_trans, std::string shader): ourShader("camera.vs", shader.c_str())
    {
    float vertices[] = {
        // positions          // colors           // texture coords
         pos,  pos, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
         pos, -pos, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -pos, -pos, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -pos,  pos, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left 
    };
    unsigned int indices[] = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
    };

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

    glBindVertexArray(VAO);

    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(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // color attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // texture coord attribute
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);


    ourShader.use(); 
    glUniform1i(glGetUniformLocation(ourShader.ID, "texture"), 1);

    if(is_trans)
    {
        ourShader.setInt("texture2", 1);
    }
    }

    void transition(int width1,int height1, uint8_t* data1, float progress)
    {
        ourShader.use();
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width1, height1, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
        glGenerateMipmap(GL_TEXTURE_2D);

        glGenTextures(1, &texture2);
        glBindTexture(GL_TEXTURE_2D, texture2);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex2.w, tex2.h, 0, GL_RGB, GL_UNSIGNED_BYTE, tex2.buff);
        glGenerateMipmap(GL_TEXTURE_2D);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);
        glUniform1f(glGetUniformLocation(ourShader.ID, "progress"), progress);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }

    void render(int w, int h, uint8_t* buffer)
    {
        ourShader.use();
        glEnable(GL_BLEND);

        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        glGenerateMipmap(GL_TEXTURE_2D);

        glActiveTexture(GL_TEXTURE2);
        
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }

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

int main()
{
    ... // init glfw, opengl and glad.
   
    // Read images as buffers using stbi image.
    int width1, height1, nrChannels1;
    stbi_set_flip_vertically_on_load(true);
    unsigned char *data1 = stbi_load("/home/tb/Desktop/Work/CameraTest/bin/ex2.jpeg", &width1, &height1, &nrChannels1, 0);

    int width2, height2, nrChannels2;
    unsigned char *data2 = stbi_load("/home/tb/Desktop/Work/CameraTest/bin/ex1.jpeg", &width2, &height2, &nrChannels2, 0);

    int width3, height3, nrChannels3;
    unsigned char *data3 = stbi_load("/home/tb/Desktop/Work/CameraTest/bin/WATERMARK.png", &width3, &height3, &nrChannels3, 0);

    Texture rect1 = Texture(0.5f, true, "camera.fs");
    Texture rect2 = Texture(1.0f, false, "normal.fs");

    float progress = 0.0f;

    while (!glfwWindowShouldClose(window))
    {
        rect1.tex2.buff = data2;
        rect1.tex2.w = width2;
        rect1.tex2.h = height2;

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        rect2.render(width3, height3, data3);
        rect1.transition(width1, height1, data1, progress);

        progress += 0.01f;

        if(progress >= 1.0f) progress = 0.0f;

        glfwSwapBuffers(window);
    }

    stbi_image_free(data1);
    stbi_image_free(data2);
    return 0;
}

矢量:

camera.fs

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D texture1;
uniform sampler2D texture2;
uniform float progress;

void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), progress);
}

normal.fs

#version 330 core

in vec2 TexCoord;
out vec4 FragColor; 

uniform sampler2D texture1; 

void main()
{
    vec4 texColor = texture(texture1, TexCoord);

    FragColor = texColor;
}

上线:

rect2.render(width3, height3, data3);
rect1.transition(width1, height1, data1, progress);

...当我尝试评论一个并尝试渲染另一个时,每一个都可以单独工作。但是当我同时启用它们时,本应在屏幕上显示的 data1 却不存在。而 rect,应该从 data2 转换到 data3,只是保持为 data2。

为什么会发生这种情况?我该如何解决这个问题?

编辑:经过进一步检查,我意识到渲染中的

ourShader.use();
(基本上就是 gluseprogram(ID))导致了问题。但我仍然不确定如何预防。

编辑2:有关转换功能的问题现已解决。然而现在,在前几帧之后

render
函数开始使用data1而不是data3。

c++ opengl glsl glfw stb-image
1个回答
0
投票

所以我的代码中有两个错误:

  1. 在每个函数(渲染和过渡)中不首先使用着色器

  2. GL_TEXTURE2
    中使用
    render
    而不是
    GL_TEXTURE0

修复这些错误给了我想要的输出。

© www.soinside.com 2019 - 2024. All rights reserved.