#region usings
using System;
using System.Collections.Generic;
using SM.Base.Utility;
using SM.Base.Window;
using SM.OGL.Shaders;
#endregion
namespace SM.Base.Shaders
{
///
/// Allows for simple creation of shaders.
///
public class SimpleShader : MaterialShader
{
///
/// Vertex files that are stored in this dictionary can be used as vertex presets.
///
public static Dictionary>> VertexFiles =
new Dictionary>>();
private readonly string _vertexPreset;
///
/// Stores the function that sets the uniforms.
///
public Action SetUniform;
static SimpleShader()
{
VertexFiles.Add("basic", new Tuple>(
new ShaderFile(
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
{
StringOverrides = {["extension"] = "0"}
},
BasicSetUniforms
));
VertexFiles.Add("E_basic", new Tuple>(
new ShaderFile(
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
{
StringOverrides = {["extension"] = "1"}
},
BasicSetUniforms
));
VertexFiles.Add("instanced", new Tuple>(
new ShaderFile(
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl"))
{
StringOverrides = {["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0"}
},
InstancedSetUniforms
));
VertexFiles.Add("E_instanced", new Tuple>(
new ShaderFile(
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl"))
{
StringOverrides = {["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0"}
},
InstancedSetUniforms
));
}
///
/// Creates a simple shader.
///
/// The vertex preset.
/// The fragment shader
/// The uniform function.
public SimpleShader(string vertexPreset, string fragment, Action setUniform) :
base(new ShaderFileCollection(VertexFiles[vertexPreset].Item1, new ShaderFile(fragment)))
{
_vertexPreset = vertexPreset;
SetUniform = setUniform;
}
///
/// Creates a simple shader with a extension.
///
/// The vertex preset.
/// The vertex extension shader
/// The fragment shader
/// The uniform function.
public SimpleShader(string vertexPreset, string vertexExtension, string fragment,
Action setUniform) : base(new ShaderFileCollection(
new[] {VertexFiles["E_" + vertexPreset].Item1, new ShaderFile(vertexExtension)},
new[] {new ShaderFile(fragment)}))
{
_vertexPreset = vertexPreset;
SetUniform = setUniform;
}
private static void BasicSetUniforms(UniformCollection uniforms, DrawContext context)
{
// Vertex Uniforms
uniforms["MVP"]
.SetMatrix4(context.Instances[0].ModelMatrix * context.ModelMatrix * context.View * context.World);
uniforms["MasterTextureMatrix"].SetMatrix3(context.Instances[0].TextureMatrix * context.TextureMatrix);
uniforms["HasVColor"]
.SetUniform1(context.Mesh.Attributes.Has("color"));
DrawObject(context.ForcedType.GetValueOrDefault(context.Mesh.PrimitiveType), context.Mesh);
}
private static void InstancedSetUniforms(UniformCollection uniforms, DrawContext context)
{
uniforms["MVP"].SetMatrix4(context.ModelMatrix * context.View * context.World);
uniforms["MasterTextureMatrix"].SetMatrix3(context.TextureMatrix);
uniforms["HasVColor"]
.SetUniform1(context.Mesh.Attributes.Has("color"));
UniformArray instances = uniforms.GetArray("Instances");
int shaderInstanceI = 0;
for (int i = 0; i < context.Instances.Count; i++)
{
if (shaderInstanceI > instances.Length - 1)
{
DrawObject(context.Mesh, instances.Length);
shaderInstanceI = 0;
}
var shaderInstance = instances[shaderInstanceI];
var instance = context.Instances[i];
if (instance == null) continue;
shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix);
shaderInstance["TextureMatrix"].SetMatrix3(instance.TextureMatrix);
shaderInstanceI++;
}
DrawObject(context.ForcedType.GetValueOrDefault(context.Mesh.PrimitiveType), context.Mesh, shaderInstanceI);
}
///
protected override void DrawProcess(DrawContext context)
{
SetUniform?.Invoke(Uniforms, context);
VertexFiles[_vertexPreset].Item2(Uniforms, context);
}
}
}