Currently Materials are immutable, it sucks.
I don't think it's that hard to make them mutable. API is like
Material:get/setNumber(kind, number)
Material:get/setVector(kind, vector)
Material:get/setColor(kind, color) (like :setVector, but does sRGB->linear conversion and accepts a hexcode)
Material:get/setTexture(kind, texture)
Internally, materials will issue a staged copy to the block's UBO the first time they are modified during a frame, and then all writes during that frame will hit the staging buffer.
Modifying a texture allocates a new material from the block the first time one is modified during the frame (guaranteeing the new descriptor set is not in use), and subsequent texture modifications do vkUpdateDescriptorSets / gpu_bundle_write with the new binding.
So changing a Material during a frame is roughly equivalent to the cost of a Buffer:setData, and changing a Texture is more expensive and is basically the same cost as recreating the Material.
Also, while we're here, we should add Model:setMaterial(name|index, material).
Tangential:
- For a long time I thought materials should be removed, but I can't think of anything better. Material object is really useful when drawing models and is a good way to package up all the PBR info from glTF.
- Custom material properties could be really interesting, but I'm holding off on it for now.
Currently Materials are immutable, it sucks.
I don't think it's that hard to make them mutable. API is like
Material:get/setNumber(kind, number)Material:get/setVector(kind, vector)Material:get/setColor(kind, color)(like :setVector, but does sRGB->linear conversion and accepts a hexcode)Material:get/setTexture(kind, texture)Internally, materials will issue a staged copy to the block's UBO the first time they are modified during a frame, and then all writes during that frame will hit the staging buffer.
Modifying a texture allocates a new material from the block the first time one is modified during the frame (guaranteeing the new descriptor set is not in use), and subsequent texture modifications do
vkUpdateDescriptorSets/gpu_bundle_writewith the new binding.So changing a Material during a frame is roughly equivalent to the cost of a
Buffer:setData, and changing a Texture is more expensive and is basically the same cost as recreating the Material.Also, while we're here, we should add
Model:setMaterial(name|index, material).Tangential: