File Material.cs

File List > Render > src > Material.cs

Go to the documentation of this file.

using System;
using System.Drawing;
using System.Linq;
using Qkmaxware.Geometry;

namespace Qkmaxware.Rendering {

public class Material {
    public bool TwoSided = false;
    public virtual Color Vert(ShaderVariables variables) { return Color.Transparent; }
    public virtual Color Edge(ShaderVariables variables) { return Fragment(variables); }
    public virtual Color Fragment(ShaderVariables variables) { return Color.Transparent; }
}

public class Wireframe : Material {
    public Color Colour = Color.White;

    public Wireframe(Color colour) {
        this.Colour = colour;
        this.TwoSided = true;
    }
    public override Color Edge(ShaderVariables variables) {
        return this.Colour;
    }
}

public class UnlitColour : Material {
    public Color Colour = Color.White;
    public UnlitColour(Color colour) {
        this.Colour = colour;
    }
    public override Color Edge(ShaderVariables variables) {
        return Colour;
    }
    public override Color Fragment(ShaderVariables variables) { 
        return Colour;
    }
}

public class TexturedMaterial : Material {
    public Texture2D Texture;

    public TexturedMaterial(Texture2D texture) {
        this.Texture = texture;
    }

    protected Color ColourSample(Vec2 uv) {
        var uvx = (int)(uv.X * Texture.Width);
        var uvy = (int)(uv.Y * Texture.Height);

        return Texture[uvx, uvy];
    }
}

public class UnlitTexture : TexturedMaterial {
    public UnlitTexture(Texture2D texture) : base(texture) {}

    public override Color Edge(ShaderVariables variables) {
        return Fragment(variables);
    }
    public override Color Fragment(ShaderVariables variables) {
        return ColourSample(variables.UVCoordinates);
    }
}

public class DiffuseColour : Material {
    public Color Colour = Color.White;
    public double Albedo = 1;

    public DiffuseColour(Color colour) {
        this.Colour = colour;
    }

    private Color Darken(Color colour, double shade) {
        double r = shade * colour.R;
        double g = shade * colour.G;
        double b = shade * colour.B;

        return Color.FromArgb(colour.A, (int)r % 255, (int)g % 255, (int)b % 255);
    }

    private Color Mix(Color a, Color b) {
        return Color.FromArgb(
            a.A,
            (a.R * b.R)/255,
            (a.G * b.G)/255,
            (a.B * b.B)/255
        );
    }
    public override Color Fragment(ShaderVariables variables) {
        var surfColour = Colour;
        Vec3 N = variables.WorldNormal;
        var tint = variables.LightSources.Select((light) => {
            var lightColour = light.Tint;
            Vec3 L = light.Direction(variables.WorldPosition, variables.WorldNormal);
            double Lintensity = light.Intensity(variables.WorldPosition, variables.WorldNormal);
            double diffuse_surface_shade = (Albedo / Math.PI) * Lintensity * Math.Max(Vec3.Dot(L, N), 0);

            return Darken(lightColour, diffuse_surface_shade);
        }).Aggregate((a,b) => Mix(a, b));
        return Mix(surfColour, tint);
    }
}

public class DiffuseTexture : TexturedMaterial {
    public Color Colour = Color.White;
    public double Albedo = 1;

    public DiffuseTexture(Texture2D texture) : base(texture) {}

    private Color Darken(Color colour, double shade) {
        double r = shade * colour.R;
        double g = shade * colour.G;
        double b = shade * colour.B;

        return Color.FromArgb(colour.A, (int)r % 255, (int)g % 255, (int)b % 255);
    }

    private Color Mix(Color a, Color b) {
        return Color.FromArgb(
            a.A,
            (a.R * b.R)/255,
            (a.G * b.G)/255,
            (a.B * b.B)/255
        );
    }
    public override Color Fragment(ShaderVariables variables) {
        var surfColour = ColourSample(variables.UVCoordinates);
        Vec3 N = variables.WorldNormal;
        var tint = variables.LightSources.Select((light) => {
            var lightColour = light.Tint;
            Vec3 L = light.Direction(variables.WorldPosition, variables.WorldNormal);
            double Lintensity = light.Intensity(variables.WorldPosition, variables.WorldNormal);
            double diffuse_surface_shade = (Albedo / Math.PI) * Lintensity * Math.Max(Vec3.Dot(L, N), 0);

            return Darken(lightColour, diffuse_surface_shade);
        }).Aggregate((a,b) => Mix(a, b));
        return Mix(surfColour, tint);
    }
}

}