I store an object's material in a array texture 2D comprised of the diffuse, bump, specular, etc. The handle to this texture array is then stored per vertex, along side the vertex, uv, normal arrays in a VAO, instead of using UBO's or SSBO's to achieve the same purpose.
My goal is to compress an entire model into a single vertex array object, since a model may have many meshes and each mesh may have its own texture. This way with the texture handle stored per vertex, I could just render the entire model in 1 draw call.
The problem is that all object's render black, suggesting to me that the sampler isn't working or somehow the handle isn't getting transferred all the way through. The shader program compiles successfully, and the geometry is rendering correctly (that is, I can substitute the final diffuse color with a fixed color and see the scene).
Texture Creation:
void TextureManager::FinishWorkOrders()
{
for ( ... ) {
Material_WorkOrder *material = Mat_Work_Orders[x];
glGenTextures(1, material->gl_array_ID);
glBindTexture(GL_TEXTURE_2D_ARRAY, *material->gl_array_ID);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, material->size.x, material->size.y, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, material->textureData);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
// Material handle is of type GLuint64
*material->handle = glGetTextureHandleARB(*material->gl_array_ID);
glMakeTextureHandleResidentARB(*material->handle);
}
}
VAO generation:
GLuint ModelManager::genVAO(const vector<vec3> &vs, const vector<vec2> &uv, const vector<vec3> &nm, const vector<vec3> &tg, const vector<vec3> &bt, const vector<GLuint64*> &ts)
{
AttribBuffers b;
GLuint vao = 0;
size_t arraySize = vs.size();
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(MAX_BUFFERS, b.buffers);
// Vertex array
glBindBuffer(GL_ARRAY_BUFFER, b.buffers[0]);
glBufferData(GL_ARRAY_BUFFER, arraySize * sizeof(vec3), &vs[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
...
// Texture Handle array
glBindBuffer(GL_ARRAY_BUFFER, b.buffers[5]);
glBufferData(GL_ARRAY_BUFFER, arraySize * sizeof(GLuint64), &ts[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(5);
glVertexAttribLPointer(5, 1, GL_UNSIGNED_INT64_ARB, 0, 0);
glBindVertexArray(0);
return vao;
}
Shader Usage:
Vertex:
#version 450
#extension GL_ARB_bindless_texture : require
#extension GL_ARB_gpu_shader5 : require
#extension GL_ARB_gpu_shader_int64 : require
layout (location = 0) in vec3 vertex;
...
layout (location = 5) in uint64_t texHandle;
flat out uint64_t TextureHandle;
void main(void)
{
TextureHandle = texHandle;
...
gl_Position = worldMVP * v;
}
Fragment:
#version 450
#extension GL_ARB_bindless_texture : require
#extension GL_ARB_gpu_shader5 : require
#extension GL_ARB_gpu_shader_int64 : require
flat in uint64_t TextureHandle;
layout (location = 0) out vec4 DiffuseOut;
void main()
{
sampler2DArray MaterialMap = sampler2DArray(TextureHandle);
...
DiffuseOut = texture(MaterialMap, vec3(TexCoord0, 0));
}