OpenGL - 在同一对象上混合两个纹理
OpenGL - blend two textures on the same object
我想在同一个对象(实际上只是一个 2D 矩形)上应用两个纹理以混合它们。我想我可以通过简单地用第一个纹理调用 glDrawElements
,然后绑定另一个纹理并再次调用 glDrawElements
来实现这一点。像这样:
//create vertex buffer, frame buffer, depth buffer, texture sampler, build and bind model
//...
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
// Clear the screen
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind our texture in Texture Unit 0
GLuint textureID;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
//second draw call
GLuint textureID2;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID2);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
不幸的是,第二个纹理根本没有绘制,我只看到了第一个纹理。如果我在两次绘制调用之间调用 glClear
,它会正确绘制第二个纹理。
有什么指点吗?我如何强制 OpenGL 在第二次调用时绘制?
感谢@tkausl 的提示。
我在初始化阶段启用了深度测试。
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
在我的例子中需要禁用该选项,混合操作才能工作。
//make sure to disable depth test
glDisable(GL_DEPTH_TEST);
作为您目前采用的方法的替代方法,我建议您在 GLSL 着色器中使用两个纹理采样器并在那里执行混合。这样,您只需一次绘制调用即可完成,从而减少 CPU/GPU 交互。为此,只需在着色器中定义纹理采样器,如
layout(binding = 0) uniform sampler2D texture_0;
layout(binding = 1) uniform sampler2D texture_1;
或者,您可以使用采样器数组:
layout(binding = 0) uniform sampler2DArray textures;
在您的应用程序中,使用
设置纹理和采样器
enum Sampler_Unit{BASE_COLOR_S = GL_TEXTURE0 + 0, NORMAL_S = GL_TEXTURE0 + 2};
glActiveTexture(Sampler_Unit::BASE_COLOR_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer1);
glTexStorage2D( ....)
glActiveTexture(Sampler_Unit::NORMAL_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer2);
glTexStorage2D( ....)
我想在同一个对象(实际上只是一个 2D 矩形)上应用两个纹理以混合它们。我想我可以通过简单地用第一个纹理调用 glDrawElements
,然后绑定另一个纹理并再次调用 glDrawElements
来实现这一点。像这样:
//create vertex buffer, frame buffer, depth buffer, texture sampler, build and bind model
//...
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
// Clear the screen
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind our texture in Texture Unit 0
GLuint textureID;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
//second draw call
GLuint textureID2;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID2);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
不幸的是,第二个纹理根本没有绘制,我只看到了第一个纹理。如果我在两次绘制调用之间调用 glClear
,它会正确绘制第二个纹理。
有什么指点吗?我如何强制 OpenGL 在第二次调用时绘制?
感谢@tkausl 的提示。
我在初始化阶段启用了深度测试。
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
在我的例子中需要禁用该选项,混合操作才能工作。
//make sure to disable depth test
glDisable(GL_DEPTH_TEST);
作为您目前采用的方法的替代方法,我建议您在 GLSL 着色器中使用两个纹理采样器并在那里执行混合。这样,您只需一次绘制调用即可完成,从而减少 CPU/GPU 交互。为此,只需在着色器中定义纹理采样器,如
layout(binding = 0) uniform sampler2D texture_0;
layout(binding = 1) uniform sampler2D texture_1;
或者,您可以使用采样器数组:
layout(binding = 0) uniform sampler2DArray textures;
在您的应用程序中,使用
设置纹理和采样器enum Sampler_Unit{BASE_COLOR_S = GL_TEXTURE0 + 0, NORMAL_S = GL_TEXTURE0 + 2};
glActiveTexture(Sampler_Unit::BASE_COLOR_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer1);
glTexStorage2D( ....)
glActiveTexture(Sampler_Unit::NORMAL_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer2);
glTexStorage2D( ....)