首页 > 解决方案 > 如何在渲染器中使用多个着色器?

问题描述

我试图让我的渲染器能够使用默认或自定义着色器。

class Renderer
{
public:
    void Create()
    {
        //Setup vao, vbo, ebo, quad indices, add data to ebo, 
        //create default Shader
        //set camera projection
    }

    void Map()
    {
        vertexData = (VertexData*)glMapBufferRange(...);
    }

    void Draw(Rectangle destRect, Rectangle texCoordRect, Texture* texture)
    {
        //4 times for 4 different corners
        float textureSlot = FindTexture(texture);
        AddDataToMappedBuffer(position, texCoords, textureSlot, color);

        indexCount += 6;
    }

    void Unmap()
    {
        glUnmapBuffer(...);
    }

    void Render()
    {
        Unmap();

        shader.UniformMatrix4fv("projection", camera.getProjection());

        for(uint i = 0; i < texture.size(); ++i)
        {
            texture[i]->Bind(i);
        }

        BindVAO();
        DrawElements(TRIANGELS, indexCount, UNSIGNED_INT, nullptr);
        UnbindVAO();

        For(uint i = 0; i < texture.size(); ++i)
        {
            texture[i]->Unbind(i);
        }

        indexCount = 0;
        texture.clear();
    }

    float Renderer2D::FindTexture(Texture* t)
    {
        float result = 0.0f;
        bool found = false;
        for (uint i = 0; i < texture.size(); ++i) {
            if (texture[i] == t) {
                result = static_cast<float>(i + 1);
                found = true;
                break;
            }
        }

        if (!found) {
            if (texture.size() >= MAX_TEXTURES) {
                Render();
                Map();
            }
            texture.push_back(t);
            result = static_cast<float>(texture.size());
        }

        return result;
    }
private:
    std::vector<Texture*> texture;
    uint vao, vbo, ebo;
    VertexData* vertexData;
    float FindTexture(Texture*);
    Shader shader;
    Camera2D camera;
};


int main()
{
    Renderer renderer;
    renderer.Create();

    while(!quit)
    {
        //Clear color etc.

        renderer.Map();
        renderer.Draw(Rectangle(0.0f, 0.0f, 500.0f, 500.0f), Rectangle(0.0f, 0.0f, 1.0f, 1.0f), texture("sometexture.png"));
        renderer.Render();
    }
}

这就是它现在的工作方式。

我希望我的渲染器是这样的:

我试图做找到着色器的方法 - 类似于纹理 - 并通过所有着色器并使用它们。它不完全符合我的要求。

std::vector<Shader*> shader;

void Renderer2D::FindShader(Shader* sh)
{
    bool found = false;
    for (uint i = 0; i < shader.size(); ++i) {
        if (shader[i] == sh) {
            found = true;
            return;
        }
    }

    if (!found) {
        shader.push_back(sh);
        Render();
        Map();
    }
}

void Render()
{
    Unmap();

    for(const auto& shader : shader) 
    {
        shader->UseProgram();
        shader.UniformMatrix4fv("projection", camera.getProjection());   
    }

    for(uint i = 0; i < texture.size(); ++i)
    {
        texture[i]->Bind(i);
    }

    BindVAO();
    DrawElements(TRIANGELS, indexCount, UNSIGNED_INT, nullptr);
    UnbindVAO();

    For(uint i = 0; i < texture.size(); ++i)
    {
        texture[i]->Unbind(i);
    }

    indexCount = 0;
    texture.clear();
}

void Draw(Rectangle destRect, Rectangle texCoordRect, Texture* texture, Shader* shader)
{
    FindShader(shader);
    float textureSlot = FindTexture(texture);
    AddDataToMappedBuffer(position, texCoords, textureSlot, color);

    indexCount += 6;
}

当未找到着色器时,我还尝试在不进行另一个绘图调用的情况下找到着色器 - 仅将其添加到数组中 - 并在渲染方法中循环遍历所有着色器并进行绘图调用。它也没有很好地工作。

我该怎么做?

标签: c++openglshaderrenderer

解决方案


推荐阅读