// -------------------------------------------------------------------------------------------------------------------- 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; }
// -------------------------------------------------------------------------------------------------------------------- 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; }