为每个对象绑定不同的纹理

Posted

技术标签:

【中文标题】为每个对象绑定不同的纹理【英文标题】:Bind different textures for each object 【发布时间】:2017-10-29 01:00:01 【问题描述】:

我对“加载”或为场景中的单独对象绑定不同的纹理有点困惑。

这是我设置纹理的方式(从硬盘加载纹理并绑定):

setTexture ( const std::string& t_filename )

int width, height, nrChannels;

glBindTexture( GL_TEXTURE_2D, m_TEX );
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

unsigned char* image = stbi_load( t_filename.c_str(), &width, &height, &nrChannels, 0 );

if ( image )

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image );
    glGenerateMipmap( GL_TEXTURE_2D );

else

    throw std::string( "Texture could not get loaded. Abort" );

stbi_image_free( image );

glBindTexture( GL_TEXTURE_2D, 0 );

该函数属于一个名为Rectangle的类。

我有 VAO、VBO 和纹理对象的成员变量:

GLuint m_VAO 0 ;
GLuint m_VBO 0 ;
GLuint m_VEBO 0 ;
GLuint m_TEX 0 ;

所以Rectangle 的每个实例都有一个纹理对象m_Tex

每次我在绘制框架的主函数中绘制对象时,我都会使用这种方式:

glBindVertexArray( m_VAO );
glBindTexture( GL_TEXTURE_2D, m_TEX );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr );
glBindVertexArray( 0 );

问题:我的所有对象(假设我有 3 个Rectangle 实例)都使用相同的纹理,尽管它们都在绘制之前绑定了自己的纹理对象。这是为什么呢?

编辑:好吧,我的错!我忘了在我的setTexture 函数中生成纹理对象:

glGenTextures(1, &m_TEX);

现在我可以加载我的纹理并按预期在它们之间“切换”!

【问题讨论】:

这是什么问题,你的记忆不是无限的,所以当然会有限制。 @wandering-warrior 这就是我写“理论上无限”的原因。我当然知道不能加载无限的纹理。 @Rabbid76 也许我写的问题难以理解。我只想为 10 个不同的对象(立方体、矩形等)设置一个单独的纹理。但是它们都使用相同的纹理.. 【参考方案1】:

如何在开始时为理论上无限的对象加载每个纹理,然后在它们之间“切换”?

只需创建几个纹理对象,并在您想使用它们时绑定它们。纹理单位与此无关。

// at init time
GLuint texA, texB;

// create texture A
glGenTextures(1, &texA);
glBindTexture(GL_TEXTURE_2D, texA);
glTexParameter(...); glTexImage(...);

// create texture B
glGenTextures(1, &texB);
glBindTexture(GL_TEXTURE_2D, texB);
glTexParameter(...); glTexImage(...);


// at draw time
glBindTexture(GL_TEXTURE_2D, texA);
glDraw*(...); // draw with texture A
glDraw*(...); // still draw with texture A

glBindTexture(GL_TEXTURE_2D, texB);
glDraw*(...); // now draw with texture B

不清楚代码中的m_TEX 是什么,但它看起来像是类的某个成员变量。但是,您没有显示您的代码片段属于哪些类,因此很难猜测您到底在做什么。在我看来,您似乎只有一个 m_TEX 变量,这意味着您只能记住一个纹理对象名称,因此可以一遍又一遍地重复使用相同的纹理。即,您的加载程序代码不会生成新的纹理对象,而只是重复使用m_TEX

Texture units 用于multitexturing,能够同时绑定多个纹理(意思是在一次draw call期间):

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texA);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texB);
glDraw*(...)  // draw with both texA and texB

这当然需要使用两种纹理的着色器,如何组合它们(或将它们用于不同类型的数据)完全取决于您。

【讨论】:

以上是关于为每个对象绑定不同的纹理的主要内容,如果未能解决你的问题,请参考以下文章

lwjgl 纹理多重绑定到一个 VBO

OpenGL纹理映射总结

在Vulkan中使用纹理绘制多个对象

将一个纹理绑定到两个不同的统一采样器

纹理可以绑定到多个 fbo 吗?

将 2 个纹理绑定到一个或两个 FBO 是不是更快?