# Having 3D material properties depend on shader

Disclaimer: I apologise if this is somehow a duplicate question or is unclear.

I am in the process of writing a 3D scene renderer/editor in C++ using the OpenGL specification. It is actually going surprisingly well considering my past experience (all but none) however I have hit hurdle in designing the way materials work. First, this is how they work now:

Materials have a diffuse/albedo map, a normal/bump map, and a specular map. They also have a diffuse/albedo colour, and a shininess value for when no specular map is provided. This works fine and all however I noticed Unity's material's properties depend entirely on a shader. This is pretty much what I want as this is wonderfully flexible.

I know you can get a list of a shader program's GLSL uniforms as described here but I am struggling with what my Material class should be looking like. Do I have each material hold a map of textures, colours, floats, with the keys being their GLSL uniform name? Or is there a nicer more elegant way? The reason I am against this is because I wouldn't know how to organise the properties in a GUI when all I am given is a uniform name. For example I might have multiple diffuse or specular maps, and I would like to arrange these in a specific manor.

Please let me know if this is an awful question, or if I could improve it in any way. My brain hurts right now.

The reason I am against this is because I wouldn't know how to organise the properties in a GUI when all I am given is a uniform name. For example I might have multiple diffuse or specular maps, and I would like to arrange these in a specific manor.

If you're interested in following Unity's example, then it's worth looking at how they do it.

Unity's ShaderLab files contain not just the shader code that's compiled for your GPU, but also mark-up describing how the engine should treat materials that use this shader. Details like:

• which shaders to use for various passes like shadow casting, deferred G-buffer population, forward lighting etc...

• how to group & sort geometry using these passes (eg. transparent stuff in its own sorted queue)

• what blend, stencil, and depth modes to use

• how to switch between shaders based on level of detail ranges

// properties for a water shader
Properties {
_WaveScale ("Wave scale", Range (0.02,0.15)) = 0.07 // sliders
_ReflDistort ("Reflection distort", Range (0,1.5)) = 0.5
_RefrDistort ("Refraction distort", Range (0,1.5)) = 0.4
_RefrColor ("Refraction color", Color) = (.34, .85, .92, 1) // color
_ReflectionTex ("Environment Reflection", 2D) = "" {} // textures
_RefractionTex ("Environment Refraction", 2D) = "" {}
_Fresnel ("Fresnel (A) ", 2D) = "" {}
_BumpMap ("Bumpmap (RGB) ", 2D) = "" {}
}


Here each line starts with an identifier corresponding to the name of the uniform in the shader code. Then in parentheses there's a friendly/descriptive name to display in the GUI, and an annotation of the variable's type and the GUI widget to use to populate it. Lastly there's a default value to use for initializing new instances of materials using this shader.

This way your code doesn't need to be "smart" and infer which variables should be exposed in your editors and how — the shader developer can tell it exactly what it should do. They're free to hide some uniforms that should be constant or set from other sources, or change the names/widgets/order to whatever they think will be most intuitive for users of the material.

• Exactly what I was looking for, thank you. My bad for assuming all unity used was a shader file to give to materials. Going to be a little more work than I had expected but that's okay :) – ImperialCoder Nov 14 '17 at 19:12