Yeah as far as number of materials, the only limitations are:
- ALU (**) and bandwidth performance. I have GTX 1070, so my card does loops and texture fetches in the amounts, the shader requires, easily. But it can put some strain on less performant GPUs. Only testing can reveal the real limitations here as I don't see them locally.
- GPU memory footprint. The way spring draws maps (SMF) currently that main texture "diffuse" is broken down into 1024x1024 chunks during compilation stage and then rendered in sequential calls. Together with @gajop and @Anarchid we decided that the PBR terrain shader would NOT follow the "tiled" principle for now, instead all textures are defined on the "global" level. I'll leave out rationale for such decision, but mention that in such approach textures themselves might need to be better details/larger file size. Also as @MaDDoX pointed out, the rendering pipeline can leverage up to 32 textures (spring and general mid-age OpenGL version limitation). These together impose increased demand on GPU memory size. Again only testing can reveal details.
- Number of addressable texture units - 32. Implementation (algorithm) itself has no limitation on the amount of materials artist defines. Can be one per map, could be 100. However usually materials are represented with a set of textures and distribution of materials is represented with texture as well. So here, the number of textures that can be bound at a given time kicks in. The practical limitation is that the number of simultaneously used textures cannot exceed 32. That said, the number of textures available to the artists is even less, because auxiliary textures like $shadow, $reflection, $info, $normals, BRDF LUT, POM-prepass (in the future) eat up resources from the same pool. Realistically only around 24 textures will be available for the artists (***).
(**) ALU - An arithmetic logic unit.
Also there exist two fundamentally different material blending principles.
- One is output blending, the one is used now. Basically what it does it takes non-zero weighted materials, evaluate material shades (PBR diffuse, specular, IBL) and then the outputs of the each material shading are mixed together according to the weights.
- Another one is inputs blending (currently not implemented). This is the mode where PBR inputs, like color, metalness roughness, etc are mixed according to weights in the first place and then the resulting/pre-mixed PBR inputs are used to to perform PBR shading evaluation (PBR diffuse, specular, IBL) only once per pixel. The use of such blending principle will reduce the ALU and bandwidth load drastically.
Why is it not default? Some smart folks told me the end result would look incorrect. Sure it will not be correct, however I'm not hesitant to get a proof myself how big quality hit it will be. So inputs blending is on my (long) TODO list.
(***) There might be a place for some tricks, to alleviate this limitation a little bit (like a prepass to see what materials are used by a specific tile), however this is not reliable nor trivial to do. The real solution is to adopt OpenGL bindless textures or go vulkan. Although I'm not even sure the amount of the bound textures will be a bottleneck.