opengl - OpenGL 2D 批量渲染:当有多个活动纹理时,纹理一起出现故障
问题描述
这就是我在一个简单的 for 循环中绘制从黑色纹理切换到浅绿色纹理时发生的情况。它似乎有来自先前绘制的纹理的位。
这是我的渲染器工作原理的简化版本
- Init():创建我的 VAO 和属性指针并生成元素缓冲区和索引
- Begin():绑定我的顶点缓冲区并映射缓冲区指针
- Draw():提交一个可渲染的绘图,它在顶点缓冲区中获得 4 个顶点,每个顶点都有一个位置、颜色、texCoords 和一个纹理槽
- End():我删除缓冲区指针,将我的 VAO、IBO 和纹理绑定到它们的活动纹理槽并绘制元素。
我每帧都这样做(初始化除外)。我不明白的是,如果我绘制 PER TEXTURE,只有一个处于活动状态,那么这不会发生。当我有多个活动纹理并且它们被绑定时。
这是我的渲染器
void Renderer2D::Init()
{
m_Textures.reserve(32);
m_VertexBuffer.Create(nullptr, VERTEX_BUFFER_SIZE);
m_Layout.PushFloat(2); //Position
m_Layout.PushUChar(4); //Color
m_Layout.PushFloat(2); //TexCoords
m_Layout.PushFloat(1); //Texture ID
//VA is bound and VB is unbound
m_VertexArray.AddBuffer(m_VertexBuffer, m_Layout);
unsigned int* indices = new unsigned int[INDEX_COUNT];
int offset = 0;
for (int i = 0; i < INDEX_COUNT; i += 6)
{
indices[i + 0] = offset + 0;
indices[i + 1] = offset + 1;
indices[i + 2] = offset + 2;
indices[i + 3] = offset + 2;
indices[i + 4] = offset + 3;
indices[i + 5] = offset + 0;
offset += 4;
}
m_IndexBuffer.Create(indices, INDEX_COUNT);
m_VertexArray.Unbind();
}
void Renderer2D::Begin()
{
m_VertexBuffer.Bind();
m_Buffer = (VertexData*)m_VertexBuffer.GetBufferPointer();
}
void Renderer2D::Draw(Renderable2D& renderable)
{
const glm::vec2& position = renderable.GetPosition();
const glm::vec2& size = renderable.GetSize();
const Color& color = renderable.GetColor();
const glm::vec4& texCoords = renderable.GetTextureRect();
const float tid = AddTexture(renderable.GetTexture());
DT_CORE_ASSERT(tid != 0, "TID IS EQUAL TO ZERO");
m_Buffer->position = glm::vec2(position.x, position.y);
m_Buffer->color = color;
m_Buffer->texCoord = glm::vec2(texCoords.x, texCoords.y);
m_Buffer->tid = tid;
m_Buffer++;
m_Buffer->position = glm::vec2(position.x + size.x, position.y);
m_Buffer->color = color;
m_Buffer->texCoord = glm::vec2(texCoords.z, texCoords.y);
m_Buffer->tid = tid;
m_Buffer++;
m_Buffer->position = glm::vec2(position.x + size.x, position.y + size.y);
m_Buffer->color = color;
m_Buffer->texCoord = glm::vec2(texCoords.z, texCoords.w);
m_Buffer->tid = tid;
m_Buffer++;
m_Buffer->position = glm::vec2(position.x, position.y + size.y);
m_Buffer->color = color;
m_Buffer->texCoord = glm::vec2(texCoords.x, texCoords.w);
m_Buffer->tid = tid;
m_Buffer++;
m_IndexCount += 6;
}
void Renderer2D::End()
{
Flush();
}
const float Renderer2D::AddTexture(const Texture2D* texture)
{
for (int i = 0; i < m_Textures.size(); i++) {
if (texture == m_Textures[i]) // Compares memory addresses
return i + 1; // Returns the texture id plus one since 0 is null texture id
}
// If the texture count is already at or greater than max textures
if (m_Textures.size() >= MAX_TEXTURES)
{
End();
Begin();
}
m_Textures.push_back((Texture2D*)texture);
return m_Textures.size();
}
void Renderer2D::Flush()
{
m_VertexBuffer.DeleteBufferPointer();
m_VertexArray.Bind();
m_IndexBuffer.Bind();
for (int i = 0; i < m_Textures.size(); i++) {
glActiveTexture(GL_TEXTURE0 + i);
m_Textures[i]->Bind();
}
glDrawElements(GL_TRIANGLES, m_IndexCount, GL_UNSIGNED_INT, NULL);
m_IndexBuffer.Unbind();
m_VertexArray.Unbind();
m_IndexCount = 0;
m_Textures.clear();
}
这是我的片段着色器
#version 330 core
out vec4 FragColor;
in vec4 ourColor;
in vec2 ourTexCoord;
in float ourTid;
uniform sampler2D textures[32];
void main()
{
vec4 texColor = ourColor;
if(ourTid > 0.0)
{
int tid = int(ourTid - 0.5);
texColor = ourColor * texture(textures[tid], ourTexCoord);
}
FragColor = texColor;
}
感谢您的帮助,如果您需要查看更多代码,请告诉我
解决方案
我不知道你是否需要这个,但记录在案
您的片段代码中有逻辑问题
让我们考虑一下,如果您的“ourTid”大于 0 让我们以 1.0f 为例,您减去 0.5f ,我们将其转换为 int(0.5) 现在肯定是 0 假设我们需要纹理编号 2 并执行相同的过程 2- 0.5 = 1.5 "cast it to int" = 1 肯定你每次都会有以前的纹理现在解决方案很容易你应该添加 0.5 而不是减去它以确保避免数字插值并且你得到正确的纹理。
推荐阅读
- angular - createSelector - 我做错了
- android - 如何使用新的 Jetpack 首选项库实现首选项标头?
- ringcentral - RingCentral 与个人用户的事件订阅集成
- css - 边距 0 自动应用于父容器时视频不居中
- java - SectionsStatePagerAdapter 已弃用错误
- javascript - 将 GeoJSON 数据添加到本地托管的 Google Maps API
- r - 填补R中咒语(日期范围)之前、之间和之后的空白
- python - 使用命名空间和共享内存字典时关闭管理器错误“AttributeError:'ForkAwareLocal'对象没有属性'连接'”
- nginx - Nginx 如果烧瓶应用程序未运行重定向到不同的 url
- javascript - 在 Google App Script 声明中删除了超链接