当前位置: 首页 > 知识库问答 >
问题:

当纹理数量增加时,多个立方体贴图纹理表现异常[duplicate]

公孙鸿才
2023-03-14

所以我已经成功地在我的引擎中实现了批处理,但是在我的片段着色器中的samplerCubes数组中遇到了一些奇怪的行为。批处理渲染器可以很好地使用2个纹理单元-如果我只绑定2个纹理,我可以成功地绘制具有正确纹理的立方体,但是一旦我向mTexture向量添加第3个,并使用glUniform1i作为samplerCube数组中的索引,即使纹理ID(TexID)是正确的,也会显示错误的纹理(我在片段着色器中检查了这一点)。

问题似乎与我对OpenGL的理解有关,因为出于某种原因,textureCubes[2](片段着色器统一)应该显示的纹理由textureCubes[1]显示,而textureCubes[2]显示的纹理与textureCubes[0]相同。textureCubes[1]应该显示的内容与第三个纹理绑定不存在。

这是我的代码:

Main.cpp

#include "Window.h"
#include "Block.h"
#include "BatchRenderer.h"
#include "Shader.h"
#include "Camera.h"

void Submit(gfx::BatchRenderer* renderer, float height) //temporary to test batching
{  
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            gfx::Block* block = new gfx::Block(j % 2 == 0 ? (i % 2 == 0 ? gfx::BlockType::DIRT : gfx::BlockType::GRASS) : gfx::BlockType::COBBLE, math::Vec3f(i * 5.0, height, j * 5.0));
            renderer->Submit(block);
        }
    }
}

int main()
{
    gfx::Window* window = new gfx::Window("MineClone", 800, 800);

    gfx::Shader* shader = new gfx::Shader();
    shader->FromFile(GL_VERTEX_SHADER, "Resources/ModelTest.vert");
    shader->FromFile(GL_FRAGMENT_SHADER, "Resources/ModelTest.frag");
    shader->RefreshProgram();

    math::Mat4f projection = math::Mat4f::Perspective(70.0, window->GetWidth() / window->GetHeight(), 0.1, 1000.0);
    gfx::Camera* camera = new gfx::Camera(projection, 0.05, 0.0015);

    gfx::BatchRenderer* renderer = new gfx::BatchRenderer();

    gfx::TextureCube* grass = new gfx::TextureCube("Resources/top.png", "Resources/dirt.png", "Resources/sides.png");
    renderer->Submit(grass);

    gfx::TextureCube* dirt = new gfx::TextureCube("Resources/dirt.png");
    renderer->Submit(dirt);

    gfx::TextureCube* cobble = new gfx::TextureCube("Resources/cobble.png");
    renderer->Submit(cobble);

    Submit(renderer, 0.0);
    Submit(renderer, 5.0);
    Submit(renderer, 10.0);
    Submit(renderer, 15.0);
    Submit(renderer, 20.0);
    Submit(renderer, 25.0);
    Submit(renderer, 30.0);
    Submit(renderer, 35.0);

    while (!window->IsClosed())
    {
        window->Update();
        if (window->GetInputHandler()->IsKeyDown(VK_ESCAPE))
            window->SwitchMouseState();

        if (window->IsSynced())
            camera->Update(window->GetInputHandler());
    
        shader->Bind();
        math::Mat4f projection = camera->GetProjection();
        shader->SetUniform("projection", projection);

        math::Mat4f view = camera->GetView();
        shader->SetUniform("view", view);

        shader->SetUniform("cubeTextures[0]", 0);
        shader->SetUniform("cubeTextures[1]", 1);
        shader->SetUniform("cubeTextures[2]", 2);

        renderer->Render();
        shader->Unbind();
    }

    return 0;
}

分批渲染器。cpp

#include "BatchRenderer.h"

namespace gfx
{
    BatchRenderer::BatchRenderer()
        : mMesh(NULL)
    {
    }

    BatchRenderer::~BatchRenderer()
    {
        mBlocks.clear();
        mTextures.clear();
        delete mMesh;
    }

    void BatchRenderer::Submit(Block* block)
    {
        MeshData data = block->GetMesh();
        mMeshData.vertices.insert(mMeshData.vertices.end(), 
            data.vertices.begin(), 
            data.vertices.end());

        for (int i = 0; i < 36; i++)
        {
            data.indices[i] += mBlocks.size() * 8;
        }
        mMeshData.indices.insert(mMeshData.indices.end(),
            data.indices.begin(),
            data.indices.end());

        mMesh = Mesh::Make(mMeshData);
        mBlocks.push_back(block);
    }

    void BatchRenderer::Submit(TextureCube* texture)
    {
        mTextures.push_back(texture);
    }

    void BatchRenderer::Render()
    {
        for (int i = 0; i < mTextures.size(); i++)
        {
            mTextures[i]->Bind(i);
        }

        mMesh->Render();

        for (int i = 0; i < mTextures.size(); i++)
        {
            mTextures[i]->Unbind(i);
        }
    }
}

我会的。cpp

#include "TextureCube.h"

namespace gfx
{
    TextureCube::TextureCube(std::string paths[6])
        : Texture(TextureEnum::TEXTURE_CUBE)
    {
        glGenTextures(1, &mHandle);
        glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);

        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        for (int i = 0; i < 6; i++)
        {
            std::vector<byte> pixels;
            lodepng::decode(pixels, mWidth, mHeight, paths[i].c_str());
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
        }

        glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    }

    TextureCube::TextureCube(std::string path)
        : Texture(TextureEnum::TEXTURE_CUBE)
    {
        glGenTextures(1, &mHandle);
        glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);

        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        std::vector<byte> pixels;
        lodepng::decode(pixels, mWidth, mHeight, path.c_str());
        for (int i = 0; i < 6; i++)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
        }

        glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    }

    TextureCube::TextureCube(std::string top, std::string bottom, std::string sides)
        : Texture(TextureEnum::TEXTURE_CUBE)
    {
        glGenTextures(1, &mHandle);
        glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);

        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        std::vector<byte> topPixels;
        lodepng::decode(topPixels, mWidth, mHeight, top.c_str());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, topPixels.data());

        std::vector<byte> bottomPixels;
        lodepng::decode(bottomPixels, mWidth, mHeight, bottom.c_str());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bottomPixels.data());

        std::vector<byte> sidesPixels;
        lodepng::decode(sidesPixels, mWidth, mHeight, sides.c_str());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());

        glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    }

    TextureCube::~TextureCube()
    {
        glDeleteTextures(1, &mHandle);
        mHandle = NULL;
    }

    void TextureCube::Bind(uint32_t slot)
    {
        glBindTextureUnit(slot, mHandle);
    }

    void TextureCube::Unbind(uint32_t slot)
    {
        glBindTextureUnit(slot, 0);
    }
}

型号est.vert

#version 450 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 offset;
layout (location = 3) in float textureID;

uniform mat4 projection;
uniform mat4 view;

out vec3 TexPos;
out flat float TexID;

void main()
{
    gl_Position = projection * view * vec4(position, 1.0);
    TexPos = position - offset;
    TexID = textureID;
}

型号est.frag

#version 450 core

out vec4 FragColour;

in vec3 TexPos;
in flat float TexID;
uniform samplerCube cubeTextures[3];

void main()
{
    vec3 norm = normalize(TexPos);
    int id = int(TexID);
    FragColour = texture(cubeTextures[id], norm);
}

共有1个答案

劳星晖
2023-03-14

对于任何寻找解决方案的人来说,我花了一段时间,但我找到了它(我对OpenGL相对较新)。问题是我使用glUniform1i单独设置纹理采样器插槽。为了解决这个问题,由于cubeTexture是一个samplerCubes数组,我为包含int数组和长度的采样器数据创建了一个结构,并使用glUniform1iv设置纹理采样器插槽。

 类似资料:
  • 纹理贴图是Threejs一个很重要的内容,游戏、产品720展示、物联网3D可视化等项目程序员加载模型的同时需要处理纹理贴图。 刚开始学习的学习的时候,也没必要去掌握Threejs所有种类纹理贴图的细节,关键是建立一个整体概念,用到的时候,知道需要查找那一节课,但是学习的时候,还是需要都打开相应的案例源码体验一边,跟着文字介绍,调试一下参数,体验感受一下。在以后的开发中遇到没有学过的纹理贴图,知道如

  • 加载纹理贴图集 可以使用Pixi的loader来加载纹理贴图集。如果是用Texture Packer生成的JSON,loader会自动读取数据,并对每一个帧创建纹理。下面就是怎么用loader来加载treasureHunter.json。当它成功加载,setup方法将会执行。 loader .add("images/treasureHunter.json") .load(setup); 现

  • 在实际的工程中创建三维场景往往会使用纹理贴图,简单地说就是把png、jpg等格式图片显示在WebGL三维场景中,比如一个产品的三维模型上贴一个商标。一张图片从数据结构的角度看, 文件中包含的信息就是和颜色缓冲区中的RGB或RGBA数据一样,.jpg格式图片数据包含RGB红绿蓝三个颜色分量,.png格式图片的数据除了RGB三个分量还包含透明度A分量, 在WebGL中可以通过调节透明度A分量的值可以实

  • 立方体纹理是放置在立方体各个表面上的六个单独的方形纹理的集合。大多数情况下,它们用于在物体上显示无限远的反射,类似于天空盒在背景中显示远处的风景。一个展开的立方体纹理可能是这样的: 在 Cocos2d-x 中,这样创建立方体纹理: // create a textureCube object with six texture assets auto textureCube = TextureCub

  • A Cubemap Texture is a collection of six separate square Textures that are put onto the faces of an imaginary cube. Most often they are used to display infinitely faraway reflections on objects, simil

  • 创建一个由6张图片所组成的纹理对象。 代码示例 const loader = new THREE.CubeTextureLoader(); loader.setPath( 'textures/cube/pisa/' ); const textureCube = loader.load( [ 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png'