// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLTextureArrayUniform::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                              const std::vector<TexturedQuadsProblem::Index>& _indices,
                                              const std::vector<TextureDetails*>& _textures,
                                              size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    auto numTextures = _textures.size();
    if (!mTexManager.Init(false, numTextures)) {
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "DrawID", "TexContainer", nullptr };

    mProgram = CreateProgramT("textures_gl_texture_array_uniform_vs.glsl",
                              "textures_gl_texture_array_uniform_fs.glsl",
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    GLint lastTexId = -1;
    GLint lastTexUnit = -1;
    std::vector<DenseTexAddress> texAddress(numTextures);
    for (size_t i = 0; i < numTextures; ++i) {
        auto texture = mTextures[i];
        auto texId = texture->GetTexId();
        if (lastTexId != texId) {
            lastTexId = texId;
            lastTexUnit = (GLint) mTexUnits.size();

            glActiveTexture(GL_TEXTURE0 + lastTexUnit);
            glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
            mTexUnits.push_back(lastTexUnit);
        }

        texAddress[i].m_container_index = lastTexUnit;
        texAddress[i].m_layer = ((float) texture->getSliceNum() + 0.5f) / numTextures;
    }

    std::vector<DenseTexAddress> texAddressContents(_objectCount);
    for (uint32_t i = 0; i < _objectCount; ++i) {
        texAddressContents[i] = texAddress[i % numTextures];
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    // Buffers
    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    return glGetError() == GL_NO_ERROR;
}
Example #2
0
// --------------------------------------------------------------------------------------------------------------------
bool TexturedQuadsGLTextureArrayMultiDraw::Init(const std::vector<TexturedQuadsProblem::Vertex>& _vertices,
                                       const std::vector<TexturedQuadsProblem::Index>& _indices,
                                       const std::vector<TextureDetails*>& _textures,
                                       size_t _objectCount)
{
    if (!TexturedQuadsSolution::Init(_vertices, _indices, _textures, _objectCount)) {
        return false;
    }

    // Prerequisites
    auto numTextures = _textures.size();
    if (!mTexManager.Init(false, numTextures)) {
        return false;
    }

    if (mUseShaderDrawParameters && !HasExtension("GL_ARB_shader_draw_parameters")) {
        console::warn("Unable to initialize solution, ARB_shader_draw_parameters is required but not available.");
        return false;
    }

    // Program
    const char* kUniformNames[] = { "ViewProjection", "TexContainer", nullptr };

    mProgram = CreateProgramT("textures_gl_texture_array_multidraw_vs.glsl",
                              "textures_gl_texture_array_multidraw_fs.glsl",
                              mUseShaderDrawParameters ? std::string("#define USE_SHADER_DRAW_PARAMETERS 1\n") : std::string(""),
                              kUniformNames, &mUniformLocation);

    if (mProgram == 0) {
        console::warn("Unable to initialize solution '%s', shader compilation/linking failed.", GetName().c_str());
        return false;
    }

    // Textures
    for (auto it = _textures.begin(); it != _textures.end(); ++it) {
        mTextures.push_back(mTexManager.newTexture2DFromDetails(*it));
    }

    GLint lastTexId = -1;
    GLint lastTexUnit = -1;
    std::vector<DenseTexAddress> texAddress(numTextures);
    for (size_t i = 0; i < numTextures; ++i) {
        auto texture = mTextures[i];
        auto texId = texture->GetTexId();
        if (lastTexId != texId) {
            lastTexId = texId;
            lastTexUnit = (GLint) mTexUnits.size();

            glActiveTexture(GL_TEXTURE0 + lastTexUnit);
            glBindTexture(GL_TEXTURE_2D_ARRAY, texId);
            mTexUnits.push_back(lastTexUnit);
        }

        texAddress[i].m_container_index = lastTexUnit;
        texAddress[i].m_layer = ((float) texture->getSliceNum() + 0.5f) / numTextures;
    }

    std::vector<DenseTexAddress> texAddressContents(_objectCount);
    for (uint32_t i = 0; i < _objectCount; ++i) {
        texAddressContents[i] = texAddress[i % numTextures];
    }

    mTexAddressBuffer = NewBufferFromVector(GL_SHADER_STORAGE_BUFFER, texAddressContents, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mTexAddressBuffer);

    // Buffers
    glGenVertexArrays(1, &mVertexArray);
    glBindVertexArray(mVertexArray);

    mVertexBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, _vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, pos));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedQuadsProblem::Vertex), (void*)offsetof(TexturedQuadsProblem::Vertex, tex));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // If we aren't using shader draw parameters, use the workaround instead.
    if (!mUseShaderDrawParameters) {
        std::vector<uint32_t> drawids(_objectCount);
        for (uint32_t i = 0; i < _objectCount; ++i) {
            drawids[i] = i;
        }

        mDrawIDBuffer = NewBufferFromVector(GL_ARRAY_BUFFER, drawids, GL_STATIC_DRAW);
        glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(uint32_t), 0);
        glVertexAttribDivisor(2, 1);
        glEnableVertexAttribArray(2);
    }

    mIndexBuffer = NewBufferFromVector(GL_ELEMENT_ARRAY_BUFFER, _indices, GL_STATIC_DRAW);

    glGenBuffers(1, &mTransformBuffer);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mTransformBuffer);

    // Set the command buffer size.
    m_commands.resize(_objectCount);

    return glGetError() == GL_NO_ERROR;
}