From de0691d28e10b1cf18b006c4127b354f7f54934c Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 26 Jul 2024 17:48:47 -0400 Subject: [PATCH] Setting up render2 --- tinyrender2/main.go | 65 +++++++------- tinyrender2/obj.go | 4 + tinyrender2/render.go | 200 ++---------------------------------------- 3 files changed, 45 insertions(+), 224 deletions(-) diff --git a/tinyrender2/main.go b/tinyrender2/main.go index 6b5a012..b9d147d 100644 --- a/tinyrender2/main.go +++ b/tinyrender2/main.go @@ -12,7 +12,7 @@ const ( Width = 512 Height = 512 ObjectFile = "head.obj" - Repeat = 1_000 + Repeat = 100_000 ) func must(err error) { @@ -41,44 +41,45 @@ func main() { fb := NewFramebuffer(Width, Height) - log.Printf("Loading obj %s", ObjectFile) + /* + log.Printf("Loading obj %s", ObjectFile) - of, err := os.Open(ObjectFile) - must(err) - defer of.Close() - o, err := ParseObj(of) - must(err) + of, err := os.Open(ObjectFile) + must(err) + defer of.Close() + o, err := ParseObj(of) + must(err) + */ log.Printf("Running render") - halfwidth := float32(fb.Width / 2) - halfheight := float32(fb.Height / 2) - - var x [3]int - var y [3]int - var hi = int(fb.Height - 1) + //halfwidth := float32(fb.Width / 2) + //halfheight := float32(fb.Height / 2) for range Repeat { - for _, f := range o.Faces { - // Precompute perspective for vertices to save time. Notice Z - // is not considered: is this orthographic projection? Yeah probably... - for i := range 3 { // Triangles, bro - x[i] = int((f[i].X + 1) * halfwidth) - y[i] = hi - int((f[i].Y+1)*halfheight) - } - Bresenham2(&fb, 0xFFFFFF, x[0], y[0], x[1], y[1]) - Bresenham2(&fb, 0xFFFFFF, x[1], y[1], x[2], y[2]) - Bresenham2(&fb, 0xFFFFFF, x[2], y[2], x[0], y[0]) - } - - // Just draw a simple line (a million times or something) - // // LineDumb5(&fb, 0xFFFFFF, 100, 100, 350, 200) - // // LineDumb5(&fb, 0xFF0000, 120, 100, 200, 350) - // // LineDumb5(&fb, 0xFF0000, 350, 200, 100, 100) // backward first line - // Bresenham2(&fb, 0xFFFFFF, 100, 100, 350, 200) - // Bresenham2(&fb, 0xFF0000, 120, 100, 200, 350) - // Bresenham2(&fb, 0xFF0000, 350, 200, 100, 100) // backward first line + Triangle1(&fb, 0xFF0000, Vec2i{10, 70}, Vec2i{50, 160}, Vec2i{70, 80}) + Triangle1(&fb, 0xFFFFFF, Vec2i{180, 50}, Vec2i{150, 1}, Vec2i{70, 180}) + Triangle1(&fb, 0x00FF00, Vec2i{180, 150}, Vec2i{120, 160}, Vec2i{130, 180}) } + /* + var x [3]int + var y [3]int + var hi = int(fb.Height - 1) + for range Repeat { + for _, f := range o.Faces { + // Precompute perspective for vertices to save time. Notice Z + // is not considered: is this orthographic projection? Yeah probably... + for i := range 3 { // Triangles, bro + x[i] = int((f[i].X + 1) * halfwidth) + y[i] = hi - int((f[i].Y+1)*halfheight) + } + Bresenham2(&fb, 0xFFFFFF, x[0], y[0], x[1], y[1]) + Bresenham2(&fb, 0xFFFFFF, x[1], y[1], x[2], y[2]) + Bresenham2(&fb, 0xFFFFFF, x[2], y[2], x[0], y[0]) + } + } + */ + log.Printf("Exporting ppm to stdout") fmt.Print(fb.ExportPPM()) diff --git a/tinyrender2/obj.go b/tinyrender2/obj.go index c951083..a9e3a8c 100644 --- a/tinyrender2/obj.go +++ b/tinyrender2/obj.go @@ -13,6 +13,10 @@ type Vec3f struct { X, Y, Z float32 } +type Vec2i struct { + X, Y int +} + type Facef [3]Vec3f type ObjModel struct { diff --git a/tinyrender2/render.go b/tinyrender2/render.go index bf5a23c..56990c6 100644 --- a/tinyrender2/render.go +++ b/tinyrender2/render.go @@ -4,161 +4,6 @@ import ( "math" ) -// Draw a line using dumb -func LineDumb(fb *Framebuffer, color uint, x0 uint, y0 uint, x1 uint, y1 uint) { - var t float32 - for t = 0; t < 1; t += 0.01 { - // Very simple interpolation between x and y - x := x0 + uint(float32(x1-x0)*t) - y := y0 + uint(float32(y1-y0)*t) - fb.Set(x, y, color) - } -} - -func LineDumb2(fb *Framebuffer, color uint, x0 uint, y0 uint, x1 uint, y1 uint) { - for x := x0; x < x1; x++ { - // For each pixel across, compute how far across we are and interpolate y - t := float32(x-x0) / float32(x1-x0) - y := uint(float32(y0)*(1-t) + float32(y1)*t) - fb.Set(x, y, color) - } -} - -func LineDumb3(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - steep := false - // This one makes sure that going pixel by pixel will not make holes in the - // other direction by always moving in the less steep direction. - if math.Abs(float64(x0-x1)) < math.Abs(float64(y0-y1)) { - x0, y0 = y0, x0 - x1, y1 = y1, x1 - steep = true - } - // Don't let lines be invisible, always go left to right - if x0 > x1 { // need to be left to right - x0, x1 = x1, x0 - y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... - } - // Same as dumb2, going across pixel by pixel. But "x" here might actually be y - // because of the inverted direction - for x := x0; x <= x1; x++ { - t := float32(x-x0) / float32(x1-x0) - y := uint(float32(y0)*(1-t) + float32(y1)*t) - if steep { - fb.Set(y, uint(x), color) - } else { - fb.Set(uint(x), y, color) - } - } -} - -func LineDumb4(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - steep := false - // This one makes sure that going pixel by pixel will not make holes in the - // other direction by always moving in the less steep direction. - if math.Abs(float64(x1-x0)) < math.Abs(float64(y1-y0)) { - x0, y0 = y0, x0 - x1, y1 = y1, x1 - steep = true - } - // Don't let lines be invisible, always go left to right - if x0 > x1 { // need to be left to right - x0, x1 = x1, x0 - y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... - } - dx := x1 - x0 // These MUST be POST calcs - dy := y1 - y0 - // Delta error or something? Basically, as we move in one direction, we get farther - // and farther off course if we never move in the OTHER direction. This is the amount - // of that per x direction. - derror := math.Abs(float64(dy) / float64(dx)) - y := uint(y0) - var err float64 - // Same as dumb2, going across pixel by pixel. But "x" here might actually be y - // because of the inverted direction - for x := x0; x <= x1; x++ { - if steep { - fb.Set(y, uint(x), color) - } else { - fb.Set(uint(x), y, color) - } - err += derror - if err > 0.5 { - if y1 > y0 { - y += 1 - } else { - y = y - 1 - } - err -= 1 - } - } -} - -// For not-steep lines -func BresenhamLow(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - dx := x1 - x0 - dy := y1 - y0 - yi := 1 // This is the increment - if dy < 0 { // Line moves in opposite vertical direction - yi = -1 - dy = -dy - } - d := 2*dy - dx - // Why minus dx? if slope is 0 then d is -dx. If slope is 1 then d = dy. - // I don't know... - y := y0 - x1u := uint(x1) - for x := uint(x0); x <= x1u; x++ { - fb.Set(x, uint(y), color) - if d > 0 { - y = y + yi - d = d + 2*(dy-dx) - } else { - d = d + 2*dy - } - } -} - -// For steep lines -func BresenhamHigh(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - dx := x1 - x0 - dy := y1 - y0 - xi := 1 // This is the increment - if dx < 0 { // Line moves in opposite vertical direction - xi = -1 - dx = -dx - } - d := 2*dx - dy - // Why minus dx? if slope is 0 then d is -dx. If slope is 1 then d = dy. - // I don't know... - x := x0 - y1u := uint(y1) - for y := uint(y0); y <= y1u; y++ { - fb.Set(uint(x), y, color) - if d > 0 { - x = x + xi - d = d + 2*(dx-dy) - } else { - d = d + 2*dx - } - } -} - -func Bresenham(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - if math.Abs(float64(y1-y0)) < math.Abs(float64(x1-x0)) { // This is a flatter line - if x0 > x1 { // This line is backwards - BresenhamLow(fb, color, x1, y1, x0, y0) - } else { - BresenhamLow(fb, color, x0, y0, x1, y1) - } - } else { // This is a steep line - if y0 > y1 { // This line is backwards - BresenhamHigh(fb, color, x1, y1, x0, y0) - } else { - BresenhamHigh(fb, color, x0, y0, x1, y1) - } - } -} - func Bresenham2(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { dx := int(math.Abs(float64(x1 - x0))) sx := -1 @@ -195,41 +40,12 @@ func Bresenham2(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { } } -func LineDumb5(fb *Framebuffer, color uint, x0 int, y0 int, x1 int, y1 int) { - steep := false - // This one makes sure that going pixel by pixel will not make holes in the - // other direction by always moving in the less steep direction. - if math.Abs(float64(x1-x0)) < math.Abs(float64(y1-y0)) { - x0, y0 = y0, x0 - x1, y1 = y1, x1 - steep = true - } - // Don't let lines be invisible, always go left to right - if x0 > x1 { // need to be left to right - x0, x1 = x1, x0 - y0, y1 = y1, y0 // Why are we swapping these? I guess because we're swapping the points... - } - dx := x1 - x0 // These MUST be POST calcs - dy := y1 - y0 - derror2 := int(math.Abs(float64(dy))) * 2 - error2 := 0 - y := y0 - sy := 1 - if y1 <= y0 { - sy = -1 - } - // Same as dumb2, going across pixel by pixel. But "x" here might actually be y - // because of the inverted direction - for x := x0; x <= x1; x++ { - if steep { - fb.Set(uint(y), uint(x), color) - } else { - fb.Set(uint(x), uint(y), color) - } - error2 += derror2 - if error2 > dx { - y = y + sy - error2 -= dx * 2 - } - } +func line(fb *Framebuffer, color uint, v0 Vec2i, v1 Vec2i) { + Bresenham2(fb, color, v0.X, v0.Y, v1.X, v1.Y) +} + +func Triangle1(fb *Framebuffer, color uint, v0 Vec2i, v1 Vec2i, v2 Vec2i) { + line(fb, color, v0, v1) + line(fb, color, v1, v2) + line(fb, color, v2, v0) }