top of page

Material System!

  • Writer: Pablo Narvaja
    Pablo Narvaja
  • Dec 5, 2019
  • 2 min read

In this post I'll talk about the simple yet powerful material system I've implemented for Llamathrust.


Lets begin with the clases involved:

Shader: Is the shader program with API abstraction. Material: Can be thought as an instance of a shader. Is a shader with associated textures, colors and other info. ShaderLibrary: A singleton class for loading and caching a shader in memory.


First system iteration

You needed to load shaders from disc passing the shader type with its filepath and a name for calling the shader program later.

auto shader_filePaths = { {VERTEX_SHADER, "resources/basic"}, {PIXEL_SHADER, "resources/basic} }; ShaderLibrary::Get().LoadFromFiles("shader_name", shaders_filePaths);

Note that the file extention assiociated with each shader type was added automatically from the shader library. The material constructor recieves the material type and a shader. The material type is used by the renderer to do sorting and render order (mostly for alpha materials to be rendered last).

auto material(MATERIAL_TYPE::LIT | MATERIAL_TYPE::TEXTURED, shader_lit_tex);

Second and final system iteration

You can see a bit of limitation in the above iteration due to manually create each shader combination which at the long run it becomes very messy.

So for this iteration I added what is a sort of uber shader (a big shader with preprocessor branches) so what you have to do is read the file from the disc and add to the string object a header with all the defines. Instead of doing one single file I divide it into pieces and one main function that is in a single file. Example:

  • shadow_calculation.frag

  • lighting_uniforms.frag

  • main.frag

And then I use the Material as:

auto material(LIT | TEXTURED | SHADOWED);

Meaning that the material will be using diffuse textures, be affected by the shadow map and by light. Internally the constructor creates a string callled predefines with:

"#version 440\n" "#define LIT\n" "#define TEXTURED\n"

And then load the files above and concatenate them as:

string frag_src = predefines + lighting_uniforms + shadow_calculation + main;

Then create the shader and cache it in the library:

ShaderLibrary::Get().Load(material_type, vert_src, frag_src);

Before creating a new shader first checks if already exists:

bool exist = ShaderLibrary::Get().Exist(material_type);

Note that the system only support materials with vertex and fragment shaders and both are required.


Realcode example:

The player is blue, is affected by light and cast shadows.

The crates have a textures, is affected by light and cast shadows.

The terrain is dark green, is affected by light, is affected by shadows but does not cast shadows.


Here's a demo of the code above:



So as you see, the shadows are only on the terrain since is the only material affected by shadows, the shadow of the player(blue) or other crates dont affect the crates or the player.


That's all for this post, folks. Bye!


Comments


  • facebook
  • linkedin
  • youtube
  • generic-social-link
  • Grey LinkedIn Icon
  • Facebook
  • YouTube

2019 Pablo Narvaja. Llamathrust GameEngine

bottom of page