New renderer going great!

This commit is contained in:
Carlos Sanchez 2024-08-02 17:55:21 -04:00
parent 699b35ce89
commit bbc73c4a68
3 changed files with 90 additions and 28 deletions

View File

@ -134,6 +134,12 @@ func (m *Mat44f) SetTranslation(x, y, z float32) {
m.Set(2, 3, z) // Get farther away from the face (user) m.Set(2, 3, z) // Get farther away from the face (user)
} }
func (m *Mat44f) ScaleSelf(scale float32) {
m.Set(0, 0, m.Get(0, 0)*scale)
m.Set(1, 1, m.Get(1, 1)*scale)
m.Set(2, 2, m.Get(2, 2)*scale)
}
func (m *Mat44f) SetRotationX(radang float32) { func (m *Mat44f) SetRotationX(radang float32) {
m.SetIdentity() m.SetIdentity()
m[5] = float32(math.Cos(float64(radang))) m[5] = float32(math.Cos(float64(radang)))
@ -168,9 +174,6 @@ func (m *Mat44f) SetCamera(loc *Vec3f, yaw float32, pitch float32, up *Vec3f) Ve
Y: float32(math.Cos(float64(pitch))), Y: float32(math.Cos(float64(pitch))),
} }
m.SetLookAt(loc, loc.Add(&lookvec), up) m.SetLookAt(loc, loc.Add(&lookvec), up)
//m.Set(0, 0, m.Get(0, 0)*scale)
//m.Set(1, 1, m.Get(1, 1)*scale)
//m.Set(2, 2, m.Get(2, 2)*scale)
return lookvec return lookvec
} }

View File

@ -50,7 +50,7 @@ func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f)
v2 := v2f.ToVec2i() v2 := v2f.ToVec2i()
r, g, b := Uint2Col(color) r, g, b := Uint2Col(color)
boundsTL, boundsBR := ComputeBoundingBox(v0, v1, v2) boundsTL, boundsBR := ComputeBoundingBox(v0, v1, v2)
if boundsBR.Y < 0 || boundsBR.X < 0 || boundsTL.X >= int(fb.Width) || boundsTL.Y >= int(fb.Height) { if boundsBR.X < 0 || boundsBR.Y < 0 || boundsTL.X >= int(fb.Width) || boundsTL.Y >= int(fb.Height) {
return return
} }
if boundsTL.Y < 0 { if boundsTL.Y < 0 {
@ -68,11 +68,6 @@ func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f)
// Where to start our scanning // Where to start our scanning
pstart := Vec2i{boundsTL.X, boundsTL.Y} pstart := Vec2i{boundsTL.X, boundsTL.Y}
parea := EdgeFunctioni(v0, v1, v2) parea := EdgeFunctioni(v0, v1, v2)
// if parea < 0 {
// v1, v2 = v2, v1
// v1f, v2f = v2f, v1f
// parea = EdgeFunctioni(v0, v1, v2)
// }
invarea := 1 / float32(parea) invarea := 1 / float32(parea)
w0_y := EdgeFunctioni(v1, v2, pstart) w0_y := EdgeFunctioni(v1, v2, pstart)
w1_y := EdgeFunctioni(v2, v0, pstart) w1_y := EdgeFunctioni(v2, v0, pstart)
@ -87,18 +82,14 @@ func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f)
w2 := w2_y w2 := w2_y
for x := uint(boundsTL.X); x <= uint(boundsBR.X); x++ { for x := uint(boundsTL.X); x <= uint(boundsBR.X); x++ {
if (w0 | w1 | w2) >= 0 { if (w0 | w1 | w2) >= 0 {
//fb.Data[di] = color
//done = true
w0a := float32(w0) * invarea w0a := float32(w0) * invarea
w1a := float32(w1) * invarea w1a := float32(w1) * invarea
w2a := float32(w2) * invarea w2a := float32(w2) * invarea
pz := w0a*v0f.Z + w1a*v1f.Z + w2a*v2f.Z pz := w0a*v0f.Z + w1a*v1f.Z + w2a*v2f.Z
if pz < fb.ZBuffer[x+y*fb.Width] { if pz < fb.ZBuffer[x+y*fb.Width] {
//log.Print(pz)
fb.ZBuffer[x+y*fb.Width] = pz fb.ZBuffer[x+y*fb.Width] = pz
fb.Data.Set(x, y, r, g, b) fb.Data.Set(x, y, r, g, b)
} }
// fb.Set(x, y, Col2Uint(byte(255*w0a), byte(255*w1a), byte(255*w2a)))
} }
w0 += w0_xi w0 += w0_xi
w1 += w1_xi w1 += w1_xi

View File

@ -3,11 +3,12 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
//"image" "image"
"image/color" "image/color"
"log" "log"
"math" "math"
"os" "os"
"path/filepath"
"renderer2/hrend" "renderer2/hrend"
"runtime/pprof" // For performance profiling (unnecessary) "runtime/pprof" // For performance profiling (unnecessary)
"time" "time"
@ -33,6 +34,47 @@ func must(err error) {
} }
} }
type ObjectDef struct {
Model *hrend.ObjModel
Texture hrend.Framebuffer // This needs to go somewhere else eventually!
Pos hrend.Vec3f
LookVec hrend.Vec3f
Scale float32
//Transform hrend.Mat44f
}
func NewObjectDef(model *hrend.ObjModel, texture hrend.Framebuffer) *ObjectDef {
result := ObjectDef{
Model: model,
Texture: texture,
LookVec: hrend.Vec3f{X: 0, Y: 0, Z: -1},
Scale: 1,
}
//result.Transform.SetIdentity()
return &result
}
func loadObject(name string) (*hrend.ObjModel, hrend.Framebuffer) {
ofile := filepath.Join("../", name+".obj")
tfile := filepath.Join("../", name+".jpg")
log.Printf("Loading obj %s, texture %s", ofile, tfile)
of, err := os.Open(ofile)
must(err)
defer of.Close()
o, err := hrend.ParseObj(of)
must(err)
jf, err := os.Open(tfile)
must(err)
defer jf.Close()
timg, _, err := image.Decode(jf)
must(err)
texture := hrend.NewTexture(timg, 4)
return o, texture
}
// func loadDefault() (*hrend.ObjModel, hrend.Framebuffer) { // func loadDefault() (*hrend.ObjModel, hrend.Framebuffer) {
// log.Printf("Loading obj %s, texture %s", ObjectFile, TextureFile) // log.Printf("Loading obj %s, texture %s", ObjectFile, TextureFile)
// //
@ -63,6 +105,7 @@ var zofs = flag.Float64("zofs", 0, "starting z-offset")
var yofs = flag.Float64("yofs", 0.5, "starting y-offset") var yofs = flag.Float64("yofs", 0.5, "starting y-offset")
var fov = flag.Float64("fov", 90, "the horizontal fov") var fov = flag.Float64("fov", 90, "the horizontal fov")
var fps = flag.Int("fps", 60, "fps to run (realtime only)") var fps = flag.Int("fps", 60, "fps to run (realtime only)")
var minlight = flag.Float64("minlight", 0.5, "Minimum light level")
// var renderconfig = flag.String("renderconfig", "", "if set, rendering is written out") // var renderconfig = flag.String("renderconfig", "", "if set, rendering is written out")
@ -158,6 +201,21 @@ func main() {
wtex := hrend.NewTexture(wtexraw, 1) wtex := hrend.NewTexture(wtexraw, 1)
world := FlatTerrain(10) world := FlatTerrain(10)
// Some static models we could put in the scene
modnames := []string{"head", "diablo"}
models := make([]*hrend.ObjModel, len(modnames))
textures := make([]hrend.Framebuffer, len(modnames))
for i, name := range modnames {
models[i], textures[i] = loadObject(name)
}
// And the actual objects for the scene. We also put the world in there
objects := make([]*ObjectDef, 0)
objects = append(objects, NewObjectDef(world, wtex))
objects = append(objects, NewObjectDef(models[1], textures[1]))
objects[1].Pos.Y += 1
objects[1].Pos.Z -= 2
// These don't really change // These don't really change
var projection, viewport hrend.Mat44f var projection, viewport hrend.Mat44f
projection.SetProjection(float32(*fov), float32(Width)/float32(Height), NearClip, FarClip) projection.SetProjection(float32(*fov), float32(Width)/float32(Height), NearClip, FarClip)
@ -167,6 +225,8 @@ func main() {
var newcamtrans hrend.Vec3f var newcamtrans hrend.Vec3f
camtrans := hrend.Vec3f{X: float32(*xofs), Y: float32(*yofs), Z: float32(*zofs)} camtrans := hrend.Vec3f{X: float32(*xofs), Y: float32(*yofs), Z: float32(*zofs)}
camup := hrend.Vec3f{X: 0, Y: 1, Z: 0} camup := hrend.Vec3f{X: 0, Y: 1, Z: 0}
lightang := -math.Pi / 4 // Angle offset from "straight down"
light := hrend.Vec3f{X: 0, Y: float32(-math.Cos(lightang)), Z: float32(math.Sin(lightang))}
// In our system, 0 degree yaw is facing -Z, into the scene // In our system, 0 degree yaw is facing -Z, into the scene
yaw := float32(0) yaw := float32(0)
@ -191,21 +251,29 @@ func main() {
} }
var sc [3]hrend.Vertex var sc [3]hrend.Vertex
for _, f := range world.Faces { var modelmat hrend.Mat44f
for i := range 3 { for _, o := range objects {
sc[i] = f[i] // Create the final matrix
sc[i].Pos = screenmat.MultiplyPoint3(f[i].Pos) modelmat.SetLookAt(&o.Pos, o.Pos.Add(&o.LookVec), &camup)
matrix3d := modelmat.Multiply(screenmat)
//matrix3d.ScaleSelf(o.Scale)
for _, f := range o.Model.Faces {
for i := range 3 {
sc[i] = f[i]
sc[i].Pos = matrix3d.MultiplyPoint3(f[i].Pos)
}
l1 := f[2].Pos.Sub(&f[0].Pos)
n := l1.CrossProduct(f[1].Pos.Sub(&f[0].Pos))
n = n.Normalize()
// light = lookvec
intensity := n.MultSimp(&light)
if intensity < 0 {
intensity = 0
}
intensity = (intensity + float32(*minlight)) / (1 + float32(*minlight))
hrend.TriangleTextured(&rb, o.Texture, intensity, sc[0], sc[1], sc[2])
//hrend.TriangleFlat(&rb, hrend.Col2Uint(byte(255*intensity), byte(255*intensity), byte(255*intensity)), sc[0].Pos, sc[1].Pos, sc[2].Pos)
} }
// l1 := f[2].Pos.Sub(&f[0].Pos)
// n := l1.CrossProduct(f[1].Pos.Sub(&f[0].Pos))
// n = n.Normalize()
// intensity := n.MultSimp(&lookvec)
// if intensity < 0 {
// intensity = 0
// }
hrend.TriangleTextured(&rb, wtex, 1.0, sc[0], sc[1], sc[2])
//hrend.TriangleFlat(&rb, hrend.Col2Uint(byte(255*intensity), byte(255*intensity), byte(255*intensity)), sc[0].Pos, sc[1].Pos, sc[2].Pos)
} }
timer.Add(time.Since(start), 10) timer.Add(time.Since(start), 10)