-
Notifications
You must be signed in to change notification settings - Fork 13
Open
Description
Hello dear,
FIXED NOW!
I have tried to port to C#
Is it correct or wrongly?
My code is completely with Clear
and ClearColor
in class Rasterizer
namespace SurfaceRasterizer;
using static DeafMan1983.ConvFunctions;
using DeafMan1983.Interop.SDL2;
using static DeafMan1983.Interop.SDL2.SDL;
using System.Runtime.InteropServices;
unsafe class Program
{
const int WIDTH = 1024;
const int HEIGHT = 728;
const int POS = (int)SDL_WINDOWPOS_CENTERED;
static sbyte* TITLE = SBytePointerFromString("Draw Filled Triangle!");
const uint FLAGS = (uint)SDL_WindowFlags.SDL_WINDOW_SHOWN;
// Structure Color
struct Color
{
public float R, G, B;
public Color(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
public uint ToPixel()
{
byte red = (byte)(R * 255.0f);
byte green = (byte)(G * 255.0f);
byte blue = (byte)(B * 255.0f);
return (uint)((red << 16) | (green << 8) | blue);
}
public static Color operator +(Color left, Color right)
{
return new Color(left.R + right.R, left.G + right.G, left.B + right.B);
}
public static Color operator -(Color left, Color right)
{
return new Color(left.R - right.R, left.G - right.G, left.B - right.B);
}
public static Color operator *(Color color, float f)
{
return new Color(color.R * f, color.G * f, color.B * f);
}
}
// Structure Vertex
public struct Vertex
{
public float x, y;
public float r, g, b;
public Vertex(float x, float y, float r, float g, float b)
{
this.x = x;
this.y = y;
this.r = r;
this.g = g;
this.b = b;
}
public static Vertex operator -(Vertex left, Vertex right)
{
return new Vertex(left.x - right.x, left.y - right.y, left.r - right.r, left.g - right.g, left.b - right.b);
}
public static Vertex operator +(Vertex left, Vertex right)
{
return new Vertex(left.x + right.x, left.y + right.y, left.r + right.r, left.g + right.g, left.b + right.b);
}
}
// Structure EdgeEquation
struct EdgeEquation
{
public float a, b, c;
public bool tie;
public EdgeEquation(Vertex v0, Vertex v1)
{
a = v0.y - v1.y;
b = v1.x - v0.x;
c = - (a * (v0.x + v1.x) + b * (v0.y + v1.y)) / 2;
tie = a != 0 ? a > 0 : b > 0;
}
public float evaluate(float x, float y)
{
return a * x + b * y + c;
}
public bool test(float x, float y)
{
return test(evaluate(x, y));
}
public bool test(float v)
{
return (v > 0 || v == 0 && tie);
}
}
// Structure ParameterEquation
struct ParameterEquation
{
public float a, b, c;
public ParameterEquation(float p0, float p1, float p2, EdgeEquation e0, EdgeEquation e1, EdgeEquation e2, float area)
{
float factor = 1.0f / (2.0f * area);
a = factor * (p0 * e0.a + p1 * e1.a + p2 * e2.a);
b = factor * (p0 * e0.b + p1 * e1.b + p2 * e2.b);
c = factor * (p0 * e0.c + p1 * e1.c + p2 * e2.c);
}
public float evaluate(float x, float y)
{
return a * x + b * y + c;
}
}
// Raszerizer
class Raszerizer
{
[DllImport("c")]
public static extern void* memset(void* str, int c, nuint n);
private SDL_Surface* m_surf;
private uint* m_pixels;
private int m_width;
private int m_height;
private int m_minX, m_minY, m_maxX, m_maxY;
public Raszerizer()
{
Viewport(0, 0, 0, 0);
}
public void SetFrameBuffer(SDL_Surface* surf, int width, int height)
{
m_surf = surf;
m_pixels = (uint*)surf->pixels;
m_width = width;
m_height = height;
}
private void SetPixel(int x, int y, Color color)
{
if (x >= m_width || y >= m_height)
return;
m_pixels[y * m_width + x] = color.ToPixel();
}
private void SetPixel(int x, int y, uint color_pixel)
{
if (x >= m_width || y >= m_height)
return;
m_pixels[y * m_width + x] = color_pixel;
}
public void Clear()
{
memset(m_pixels, 0, (nuint)(sizeof(uint) * m_width * m_height));
}
public void ClearColor(Color color)
{
for (int x = 0; x < m_width; x++)
{
for (int y = 0; y < m_height; y++)
{
SetPixel(x, y, color);
}
}
}
public void Viewport(int x, int y, int width, int height)
{
m_minX = x;
m_minY = y;
m_maxX = x + width;
m_maxY = y + m_height;
}
public void DrawTriangle(Vertex v0, Vertex v1, Vertex v2)
{
// Compute triangle bounding box.
int minX = (int)Math.Min(Math.Min(v0.x, v1.x), v2.x);
int maxX = (int)Math.Max(Math.Max(v0.x, v1.x), v2.x);
int minY = (int)Math.Min(Math.Min(v0.y, v1.y), v2.y);
int maxY = (int)Math.Max(Math.Max(v0.y, v1.y), v2.y);
// Clip to scissor rect.
minX = Math.Max(minX, m_minX);
maxX = Math.Min(maxX, m_maxX);
minY = Math.Max(minY, m_minY);
maxY = Math.Min(maxY, m_maxY);
// Compute edge equations.
EdgeEquation e0 = new(v1, v2);
EdgeEquation e1 = new(v2, v0);
EdgeEquation e2 = new(v0, v1);
float area = (float)(0.5 * (e0.c + e1.c + e2.c));
// Check if triangle is backfacing.
if (area < 0)
return;
ParameterEquation r = new(v0.r, v1.r, v2.r, e0, e1, e2, area);
ParameterEquation g = new(v0.g, v1.g, v2.g, e0, e1, e2, area);
ParameterEquation b = new(v0.b, v1.b, v2.b, e0, e1, e2, area);
// Add 0.5 to sample at pixel centers.
for (float x = minX + 0.5f, xm = maxX + 0.5f; x <= xm; x += 1.0f)
for (float y = minY + 0.5f, ym = maxY + 0.5f; y <= ym; y += 1.0f)
{
if (e0.test(x, y) && e1.test(x, y) && e2.test(x, y))
{
byte rint = (byte)(r.evaluate(x, y) * 255);
byte gint = (byte)(g.evaluate(x, y) * 255);
byte bint = (byte)(b.evaluate(x, y) * 255);
uint color = SDL_MapRGB(m_surf->format, rint, gint, bint);
SetPixel((int)x, (int)y, color);
}
}
}
}
// Static Main function
static int Main(string[] args)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow(TITLE, POS, POS, WIDTH, HEIGHT, FLAGS);
SDL_Surface* surface = SDL_GetWindowSurface(window);
Raszerizer rast = new();
while (true)
{
SDL_Event evt;
SDL_PollEvent(&evt);
if (evt.type == (uint)SDL_EventType.SDL_QUIT)
{
break;
}
if (evt.type == (uint)SDL_EventType.SDL_KEYDOWN)
{
if (evt.key.keysym.sym == SDL_KeyCode.SDLK_ESCAPE)
{
break;
}
}
if (evt.type == (uint)SDL_EventType.SDL_WINDOWEVENT)
{
if (evt.window.eventID == (byte)SDL_WindowEventID.SDL_WINDOWEVENT_EXPOSED)
{
SDL_SetWindowSize(SDL_GetWindowFromID(evt.window.windowID), evt.window.data1, evt.window.data2);
}
if (evt.window.eventID == (byte)SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED)
{
SDL_SetWindowSize(SDL_GetWindowFromID(evt.window.windowID), evt.window.data1, evt.window.data2);
SDL_SetWindowMaximumSize(SDL_GetWindowFromID(evt.window.windowID), evt.window.data1, evt.window.data2);
}
if (evt.window.eventID == (byte)SDL_WindowEventID.SDL_WINDOWEVENT_MAXIMIZED)
{
SDL_SetWindowSize(SDL_GetWindowFromID(evt.window.windowID), evt.window.data1, evt.window.data2);
}
}
// Lock Surface
if (SDL_LockSurface(surface) != 0)
return -1;
// Set Rasterizing FrameBuffer
rast.SetFrameBuffer(surface, WIDTH, HEIGHT);
rast.Clear();
rast.Viewport(0, 0, WIDTH, HEIGHT);
// Clear color
Color backcolor = new Color { R = 1.0f, G = 1.0f / 4, B = 0f };
rast.ClearColor(backcolor);
// Draw Filled Traingle
Vertex v1 = new Vertex { x = 256, y = 540, r = 1f, g = 0f, b = 0f };
Vertex v2 = new Vertex { x = WIDTH / 2, y = 180, r = 0f, g = 1f, b = 0f };
Vertex v3 = new Vertex { x = 768, y = 540, r = 0f, g = 0f, b = 1f };
rast.DrawTriangle(v1, v2, v3);
// Unlock and Update Surface
SDL_UnlockSurface(surface);
SDL_UpdateWindowSurface(window);
}
SDL_FreeSurface(surface);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
}
Update: I don't expect that float means 1.0f = WIDTH like in OpenGL or Vulkan.
float 1 : int 1 ....
Now it works fine :D
Thanks
Metadata
Metadata
Assignees
Labels
No labels