I want to render a scene with different materials and multiple objects. When I started to implement it myself, I found it difficult to bind material resources before iterating over the objects. I originally plan to use one descriptor set for each material that contains several parameters and textures and pass an array of them to our shader, but this is not possible because the glsl shader requires me to explicitly refer to the descriptor sets and bindings like
location(set = 0, binding = 0) uniform someUniformBuffer/someTextureSampler
Also, the number of descriptor sets and bindings need to be hard-coded into my shader code. Therefore, I do not think it would be possible to do it this way.
After some searching I found two existing ways to bind multiple material resources, basically from SaschaWillems Repo and Vulkan texture rendering on multiple meshes:
- Group the faces using the same material of an object, and bind material resources when drawing those faces (You have to do this because the materialId is specified per face). Then the framework would be like
// example for typical loops in rendering
for each view {
bind view resources // camera, environment...
for each shader {
bind shader pipeline
bind shader resources // shader control values
for each object {
bind object resources // object transforms
for each material group{
bind material resources // material parameters and textures
draw faces
}
}
}
}
This way works on all devices with Vulkan support, but is a little bit complicated because I will have to group the faces by their materialId when building my objects. This is similar to the framework proposed by The NVIDIA Post Vulkan Shader Resource Binding where they group the objects of the same material (In my case I have multiple materials inside the same object).
Use an array of textures and a separate sampler. In this case, I will have a bound for my texture array which could be as low as 128.
Use an array of combined samplers and use
location(set = 0, binding = 0) uniform sampler2DArray
in my shader to deal with an array of textures. This requires the physical device feature shaderSampledImageArrayDynamicIndexing
which is not supported by most mobile devices.
In this case, I think I prefer the first method. However, in solution 1, the same material could be bound multiple times for different objects using this material. I am wondering if this would impact the performance and how to improve it considering that each object I want to draw has several materials for different faces.