I am on my way to create a material system and what does a generic material info actually contain? Should it also include shaders?
What does a material contain,
Members - Reputation: 4684
Posted 22 August 2014 - 03:00 PM
what does a generic material info actually contain?
A generic material may contain many different colors or may contain no colors. It also may have any number of textures. It all depends on the shader. I like to think of a material as all of the parameters needed for the shader. So you need to be able to define what values are present in the material.
Material material = new Material(shaderProgram); // Add parameter by name // These parameters should // match the shader program material.AddColor("emissiveColor"); material.AddTexture("diffuse"); // Set values material.SetColor("emissiveColor", Color.White); material.SetTexture("diffuse", diffuseTeture);The AddColor and AddTexture stage could be inside a material loader class that loads material definitions from a file, and could also set default values for the material.
In my example the material actually contains a reference to a shader program. This works pretty well.
Should it also include shaders?
Edited by HappyCoder, 22 August 2014 - 03:00 PM.
GDNet+ - Reputation: 6281
Posted 24 August 2014 - 09:14 AM
Members - Reputation: 969
Posted 02 September 2014 - 11:30 AM
I've been looking at materials and shaders as two sides of the same coin lately. The shader is the algorithm in which your graphics are processed, while the material would be the configuration that sets up your shader's uniforms. Now of course, you will see additional input coming into the shader in the form of what I call scene uniforms such as your model-view-projection (or pvm, possibly) matrices, lighting data, camera data, etc, and that should be kept separate from your material system. It wouldn't be a bad idea to provide status flags in your shader class that'll inject source code into your shader providing the names of those uniforms when lighting is enabled, depth and/or alpha is enabled, and so on, but that's outside the scope of your question lol.
In this concept, I'm assuming a 1-to-1 relationship between shaders and materials, and that your materials should always match up to your shader. The way I'd ensure a correct match-up is to allow the materials to hold a pointer to your loaded shader and a dictionary (in C++ we call them STL maps) that'll hold the uniform's handle as the key, and whatever generic data you like as the value. Whenever that shader reference is set, the dictionary is cleared, and re-populated with whatever uniforms were put into your material block in your shader. You shader could have a copy of all your uniform locations ahead of time so that you don't have to run a series of glGetUniformLocation() every time you assign a material to a loaded shader. ;) On top of that, since remembering arbitrary shader handles is impractical for us, your Material class could provide methods to get handles by name referenced in the shader:
GLuint Material::GetProperty(string name);
That would return the handle to you based on string name where you could cache the uniform to get around string look-ups. Setting material data would be similar to how HappyCoder's doing it, except I'd provide a more generic route which would allow you to provide not just basic datatypes, but whole, complex structures built from those basic datatypes as you can do in GLSL like so:
Material::SetProperty(int handle, IMaterialProperty *property); // set property by handle (fast, inconvenient)
Material::SetProperty(string name, IMaterialProperty *property); // set property by string look-up (slow, convenient)
Assume that IMaterialProperty is a probably empty abstract class (C++) or interface (C#). It could even just be a void pointer (C++) or object (C#). Anyway, my current setup is just like HappyCoder's where I have an upload method for each type of vector, matrix and color format as I'm still coming from OpenGL ES 2.0/OpenGL 2.1. Once I wrap my head around OpenGL 4.x better, I'll have an efficient system in place. Hopefully, I'll be able to upload whole blocks of uniforms for things like skeletal data to the shader with a single gl* API call instead of 3 UploadVector4() calls per bone, then I have to convert them to mat4s in the vertex shader.
Now, that doesn't mean your mesh doesn't have to be limited to just 1 materials. You could provide multiple materials for multiple render passes. For example, you'd have a "regular" material for all your blur passes, but then you'd maybe have a glow material with a low-res alpha map and color for your "glow" material for the glow pass.