112 lines
3.5 KiB
C#
112 lines
3.5 KiB
C#
using System.Diagnostics;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
using Raylib_cs;
|
|
|
|
|
|
public class RenderDevice
|
|
{
|
|
public int width { get; private set; }
|
|
public int height { get; private set; }
|
|
|
|
private int screenWidth, screenHeight;
|
|
|
|
private Texture2D renderTarget;
|
|
private IntPtr pixelPtr;
|
|
private byte[] pixelData;
|
|
|
|
private int frame = 1;
|
|
public RenderDevice(int width, int height, int screenWidth, int screenHeight)
|
|
{
|
|
this.width = width;
|
|
this.height = height;
|
|
this.screenWidth = screenWidth;
|
|
this.screenHeight = screenHeight;
|
|
|
|
Image image = Raylib.GenImageColor(width, height, Color.Black);
|
|
renderTarget = Raylib.LoadTextureFromImage(image);
|
|
Raylib.UnloadImage(image);
|
|
|
|
pixelData = new byte[width * height * 4];
|
|
pixelPtr = Marshal.AllocHGlobal(pixelData.Length);
|
|
|
|
}
|
|
|
|
public void render()
|
|
{
|
|
Marshal.Copy(pixelData, 0, pixelPtr, pixelData.Length);
|
|
unsafe
|
|
{
|
|
Raylib.UpdateTexture(renderTarget, (void*)pixelPtr);
|
|
}
|
|
|
|
Raylib.DrawTexturePro(renderTarget, new Rectangle(0,0, width, height), new Rectangle(0, 0, screenWidth, screenHeight), Vector2.Zero, 0f, Color.White);
|
|
|
|
frame++;
|
|
}
|
|
|
|
public void SetPixel(int x, int y, float3 color)
|
|
{
|
|
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
|
int idx = (y * width + x) * 4;
|
|
pixelData[idx] = (byte)(Math.Clamp(color.r * 255, 0, 255));
|
|
pixelData[idx + 1] = (byte)(Math.Clamp(color.g * 255, 0, 255));
|
|
pixelData[idx + 2] = (byte)(Math.Clamp(color.b * 255, 0, 255));
|
|
pixelData[idx + 3] = 0xFF;
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
for (int i = 0; i < pixelData.Length; i++) pixelData[i] = 0;
|
|
}
|
|
|
|
public void DrawTriangle(float2 v0, float2 v1, float2 v2, IPixelShader pixelShader)
|
|
{
|
|
v0 = MathHelpers.NDCToScreen(v0, width, height);
|
|
v1 = MathHelpers.NDCToScreen(v1, width, height);
|
|
v2 = MathHelpers.NDCToScreen(v2, width, height);
|
|
|
|
Debug.WriteLine(v0.x);
|
|
|
|
int minX = (int)MathF.Floor(MathF.Min(v0.x, MathF.Min(v1.x, v2.x)));
|
|
int maxX = (int)MathF.Ceiling(MathF.Max(v0.x, MathF.Max(v1.x, v2.x)));
|
|
int minY = (int)MathF.Floor(MathF.Min(v0.y, MathF.Min(v1.y, v2.y)));
|
|
int maxY = (int)MathF.Ceiling(MathF.Max(v0.y, MathF.Max(v1.y, v2.y)));
|
|
|
|
float area = MathHelpers.Edge(v0, v1, v2);
|
|
if (area == 0f) return; // Degenerate
|
|
|
|
for (int y = minY; y <= maxY; y++)
|
|
{
|
|
for (int x = minX; x <= maxX; x++)
|
|
{
|
|
float2 p = new float2(x + 0.5f, y + 0.5f);
|
|
|
|
float w0 = MathHelpers.Edge(v1, v2, p);
|
|
float w1 = MathHelpers.Edge(v2, v0, p);
|
|
float w2 = MathHelpers.Edge(v0, v1, p);
|
|
|
|
|
|
|
|
if (w0 <= 0 && w1 <= 0 && w2 <= 0)
|
|
{
|
|
|
|
w0 /= area;
|
|
w1 /= area;
|
|
w2 /= area;
|
|
float3 bary = new float3(w0, w1, w2);
|
|
|
|
// Inside triangle
|
|
SetPixel(x, y, pixelShader.GetColor(bary, x, y, frame));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void cleanup()
|
|
{
|
|
Raylib.UnloadTexture(renderTarget);
|
|
Marshal.FreeHGlobal(pixelPtr); // always free after upload
|
|
}
|
|
} |