所以我在 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。
所以我的代码中有两个错误:
在每个函数(渲染和过渡)中不首先使用着色器
在
GL_TEXTURE2
中使用 render
而不是 GL_TEXTURE0
。
修复这些错误给了我想要的输出。