c++ - 如何将多个纹理加载到片段着色器中

标签 c++ opengl textures texture2d

因此,我尝试在 OpenGL 中为一个对象制作纹理,并且我有两个纹理想在片段着色器(rock.tga 和 grass.tga)中混合在一起。我的片段着色器:

out vec3 color;

in vec2 uv;

uniform sampler2D grasstexture;
uniform sampler2D rocktexture;

要加载 sampler2D 纹理,这是我在 C++ 头文件中所做的:

OpenGP::EigenImage<vec3> image;
OpenGP::imread("grass.tga", image);

glGenTextures(0, &_tex);
glBindTexture(GL_TEXTURE_2D, _tex);

check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F,
             image.cols(), image.rows(), 0,
             GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "grasstexture");
glUniform1i(tex_id, 0);

它将草纹理加载到我的片段着色器中。现在我想知道的是如何加载多个纹理。我不能将上面的代码复制两次,因为一个纹理总是被另一个纹理覆盖。那么如何将多个纹理加载到片段着色器中呢?

编辑:这是声明我的 _tex 的地方:

    class Mesh{
    protected:
        GLuint _tex;

        GLuint _vpoint;    ///< memory buffer
        GLuint _vnormal;   ///< memory buffer

    public:
        GLuint getProgramID(){ return _pid; }

        void init(){
//code for the textures goes in here

这是我更新后的代码:

OpenGP::EigenImage<vec3> image;
glActiveTexture(GL_TEXTURE0);
OpenGP::imread("grass.tga", image);

//glGenTextures(1, &_tex);
glBindTexture(GL_TEXTURE_2D, _tex);

check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F,
             image.cols(), image.rows(), 0,
             GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "grasstexture");
glUniform1i(tex_id, 0);

glActiveTexture(GL_TEXTURE1);
OpenGP::imread("rock.tga", image);

//glGenTextures(0, &_tex);

glBindTexture(GL_TEXTURE_2D, _tex);

check_error_gl();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
check_error_gl();
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB32F,
             image.cols(), image.rows(), 0,
             GL_RGB, GL_FLOAT, image.data());
check_error_gl();
tex_id = glGetUniformLocation(_pid, "rocktexture");
glUniform1i(tex_id, 1);

最佳答案

Opengl 隐藏了很多它的上下文,所以你需要记住它。你有纹理的三个部分:

  • 纹理名称 - 只是一个整数,传递它。
  • 事件纹理单元 - 上下文事物,使用 GL_TEXTURE0 设置...
  • Texture target - 对于初学者来说,GL_TEXTURE_2D 就是您所需要的。

为了使 2d 纹理正常工作,您需要执行以下操作:

  1. glGenTextures 创建opengl 纹理名称
  2. 使用以下一组操作设置纹理:

    2.1 使用 glActiveTexture 设置事件纹理单元

    2.2 指定命名纹理绑定(bind)到的事件纹理单元目标 glBindTexture .为此,所有三个纹理部分都应该“受到控制”。

    2.3 用glTexImage2D事件纹理单元 指定一个二维纹理图像。

    2.4 使用 glTexParameteri事件纹理单元设置参数

  3. 为了同时使用多个纹理,请确保它们具有唯一的名称纹理单元:

    3.1 设置事件纹理unit为0

    3.2 将一个命名纹理绑定(bind)到事件纹理单元

    3.3 将纹理单元 (0) 传递给着色器

    3.4 设置事件纹理单元为1

    3.5 将另一个命名纹理绑定(bind)到事件纹理单元

    3.6 将纹理单元 (1) 传递给着色器

    ...

  4. 完成后不要忘记使用glDeleteTextures 删除所有命名的纹理。

命令的顺序不是唯一可能的,命令集也不是最小的 - 它只是典型的。


原始答案:

您需要像这样设置下一个事件纹理:

 glActiveTexture(GL_TEXTURE1);

在绑定(bind)之前绑定(bind)下一个纹理。 它还将像这样工作:

std::vector<std::string> textures = {"grass.tga", "rock.tga"};
for(int i = 0; i < textures.size(); i++) {
    glActiveTexture(GL_TEXTURE0 + i);
    // create the texture
}

关于c++ - 如何将多个纹理加载到片段着色器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44940952/

相关文章:

opengl - 简单来说,textureGrad()是什么?

opengl - LibGDX 中的清屏

c# - GLSL "zoom"像模糊

android - OpenGL Android 应用程序适用于大多数手机,但纹理在 Xoom 上显示为白色

opengl - 如何在视觉上定义将纹理数组附加到 FBO 的颜色附加点?

c++ - 确定模板中模板参数的类型

c++ - 如何解决此 "cast to pointer from type of different size"警告?

c++ - QGraphicsScene清晰显示

c++ - CppCMS URL 映射问题

opengl - 附加到纹理的帧缓冲区是否必须绑定(bind)到纹理单元?