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 } }