Support single color objects

This commit is contained in:
Carlos Sanchez 2024-08-04 18:55:54 -04:00
parent 0a6a5d6404
commit b72127d3b1
6 changed files with 59 additions and 31 deletions

View File

@ -81,9 +81,11 @@ func (fb *SimpleFramebuffer) Get(x uint, y uint) (byte, byte, byte) {
func (fb *SimpleFramebuffer) GetUv(u float32, v float32) (byte, byte, byte) { func (fb *SimpleFramebuffer) GetUv(u float32, v float32) (byte, byte, byte) {
x := uint(float32(fb.Width)*u) & (fb.Width - 1) x := uint(float32(fb.Width)*u) & (fb.Width - 1)
y := uint(float32(fb.Height)*(1-v)) & (fb.Height - 1) y := uint(float32(fb.Height)*(1-v)) & (fb.Height - 1)
return fb.Data[(x+y*fb.Width)*3], i := (x + y*fb.Width) * 3
fb.Data[(x+y*fb.Width)*3+1], return fb.Data[i], fb.Data[i+1], fb.Data[i+2]
fb.Data[(x+y*fb.Width)*3+2] // return fb.Data[(x+y*fb.Width)*3],
// fb.Data[(x+y*fb.Width)*3+1],
// fb.Data[(x+y*fb.Width)*3+2]
} }
func NewSimpleFramebuffer(width uint, height uint) *SimpleFramebuffer { func NewSimpleFramebuffer(width uint, height uint) *SimpleFramebuffer {

View File

@ -321,6 +321,14 @@ func (v0 *Vec3f) Sub(v1 *Vec3f) *Vec3f {
} }
} }
func (v0 *Vec3f) Scale(s float32) *Vec3f {
return &Vec3f{
X: v0.X * s,
Y: v0.Y * s,
Z: v0.Z * s,
}
}
func (v0 *Vec3f) CrossProduct(v1 *Vec3f) *Vec3f { func (v0 *Vec3f) CrossProduct(v1 *Vec3f) *Vec3f {
return &Vec3f{ return &Vec3f{
X: v0.Y*v1.Z - v0.Z*v1.Y, X: v0.Y*v1.Z - v0.Z*v1.Y,

View File

@ -18,17 +18,17 @@ type Vertex struct {
type Facef [3]Vertex type Facef [3]Vertex
// struct {
// Vertices [3]Vec3f
// TextureCoords [3]Vec2i
// }
type ObjModel struct { type ObjModel struct {
Vertices []Vec3f Vertices []Vec3f
VTexture []Vec3f VTexture []Vec3f
Faces []Facef Faces []Facef
} }
func (o *ObjModel) ClearCachedVertexInfo() {
o.Vertices = nil
o.VTexture = nil
}
// Parse an obj file at the given reader. Only handles v and f right now // Parse an obj file at the given reader. Only handles v and f right now
func ParseObj(reader io.Reader) (*ObjModel, error) { func ParseObj(reader io.Reader) (*ObjModel, error) {
result := ObjModel{ result := ObjModel{

View File

@ -10,6 +10,7 @@ type ObjectDef struct {
Texture Framebuffer // This needs to go somewhere else eventually! Texture Framebuffer // This needs to go somewhere else eventually!
Pos Vec3f Pos Vec3f
LookVec Vec3f LookVec Vec3f
Color Vec3f
Scale float32 Scale float32
Lighting bool Lighting bool
} }
@ -67,18 +68,19 @@ func ZClip(v0f Vec3f, v1f Vec3f, v2f Vec3f) bool {
return maxz < -1 || maxz > 1 return maxz < -1 || maxz > 1
} }
func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f) { func TriangleFlat(fb *RenderBuffer, color *Vec3f, v0f Vec3f, v1f Vec3f, v2f Vec3f) {
if ZClip(v0f, v1f, v2f) {
return
}
v0 := v0f.ToVec2i() v0 := v0f.ToVec2i()
v1 := v1f.ToVec2i() v1 := v1f.ToVec2i()
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.X < 0 || boundsBR.Y < 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
} }
parea := EdgeFunctioni(v0, v1, v2)
if parea <= 0 {
return
}
if boundsTL.Y < 0 { if boundsTL.Y < 0 {
boundsTL.Y = 0 boundsTL.Y = 0
} }
@ -93,7 +95,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)
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)
@ -101,6 +102,9 @@ func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f)
w0_xi, w0_yi := EdgeIncrementi(v1, v2) w0_xi, w0_yi := EdgeIncrementi(v1, v2)
w1_xi, w1_yi := EdgeIncrementi(v2, v0) w1_xi, w1_yi := EdgeIncrementi(v2, v0)
w2_xi, w2_yi := EdgeIncrementi(v0, v1) w2_xi, w2_yi := EdgeIncrementi(v0, v1)
r := byte(255 * color.X)
g := byte(255 * color.Y)
b := byte(255 * color.Z)
for y := uint(boundsTL.Y); y <= uint(boundsBR.Y); y++ { for y := uint(boundsTL.Y); y <= uint(boundsBR.Y); y++ {
w0 := w0_y w0 := w0_y
@ -139,12 +143,8 @@ func TriangleTextured(fb *RenderBuffer, texture Framebuffer, intensity float32,
v1 := v1v.Pos.ToVec2i() v1 := v1v.Pos.ToVec2i()
v2 := v2v.Pos.ToVec2i() v2 := v2v.Pos.ToVec2i()
parea := EdgeFunctioni(v0, v1, v2) parea := EdgeFunctioni(v0, v1, v2)
// Still draw back faces (assume someone else culls them) // Don't even bother with drawing backfaces or degenerate triangles;
// if parea < 0 { // don't even give the user the option
// log.Print("HEY", parea)
// v1, v2 = v2, v1
// parea = EdgeFunctioni(v0, v1, v2)
// }
if parea <= 0 { if parea <= 0 {
return return
} }
@ -245,4 +245,6 @@ func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef {
// TODO: Now that we're here doing it like this, might as well remove faces // TODO: Now that we're here doing it like this, might as well remove faces
// that are fully outside the other clipping zones. No need to do actual clipping... // that are fully outside the other clipping zones. No need to do actual clipping...
// just full rejections. This saves a BIT of processing... though not much // just full rejections. This saves a BIT of processing... though not much
// NOTE: Uh no... this is too much effort. Two points could be outside individual
// planes and thus still intersect the screen.
} }

View File

@ -43,6 +43,9 @@ func loadObject(name string) (*hrend.ObjModel, hrend.Framebuffer) {
o, err := hrend.ParseObj(of) o, err := hrend.ParseObj(of)
must(err) must(err)
// We also get rid of cached vertex info from the file
o.ClearCachedVertexInfo()
jf, err := os.Open(tfile) jf, err := os.Open(tfile)
must(err) must(err)
defer jf.Close() defer jf.Close()
@ -185,13 +188,19 @@ func main() {
// And the actual objects for the scene. We also put the world in there // And the actual objects for the scene. We also put the world in there
objects := make([]*hrend.ObjectDef, 0) objects := make([]*hrend.ObjectDef, 0)
objects = append(objects, hrend.NewObjectDef(world, wtex)) objects = append(objects, hrend.NewObjectDef(world, wtex))
worldobj := objects[len(objects)-1]
worldobj.Color = hrend.Vec3f{0.0, 1.0, 0.0}
objects = append(objects, hrend.NewObjectDef(sky, skytex)) // the actual skybox objects = append(objects, hrend.NewObjectDef(sky, skytex)) // the actual skybox
skyobj := objects[len(objects)-1] skyobj := objects[len(objects)-1]
skyobj.Scale = 50 skyobj.Scale = 50
skyobj.Lighting = false skyobj.Lighting = false
skyobj.Color = hrend.Vec3f{0.5, 0.5, 1.0}
objects = append(objects, hrend.NewObjectDef(models[1], textures[1])) objects = append(objects, hrend.NewObjectDef(models[1], textures[1]))
objects[len(objects)-1].Pos.Y += 1 diabloobj := objects[len(objects)-1]
objects[len(objects)-1].Pos.Z -= 2 diabloobj.Pos.Y += 1
diabloobj.Pos.Z -= 2
diabloobj.Color = hrend.Vec3f{1.0, 0.0, 0.0}
//diabloobj.Lighting = false
// These don't really change // These don't really change
var projection hrend.Mat44f var projection hrend.Mat44f
@ -254,6 +263,7 @@ func main() {
intensity = 1.0 intensity = 1.0
} }
hrend.TriangleTextured(&rb, o.Texture, intensity, sc[0], sc[1], sc[2]) hrend.TriangleTextured(&rb, o.Texture, intensity, sc[0], sc[1], sc[2])
//hrend.TriangleFlat(&rb, o.Color.Scale(intensity), sc[0].Pos, sc[1].Pos, sc[2].Pos)
} }
//break // only render one face //break // only render one face
//hrend.TriangleFlat(&rb, hrend.Col2Uint(byte(255*intensity), byte(255*intensity), byte(255*intensity)), sc[0].Pos, sc[1].Pos, sc[2].Pos) //hrend.TriangleFlat(&rb, hrend.Col2Uint(byte(255*intensity), byte(255*intensity), byte(255*intensity)), sc[0].Pos, sc[1].Pos, sc[2].Pos)

View File

@ -38,12 +38,16 @@ func (fb *RaylibBuffer) Dims() (uint, uint) {
// Sure hope this gets inlined... // Sure hope this gets inlined...
func (fb *RaylibBuffer) Set(x uint, y uint, r byte, g byte, b byte) { func (fb *RaylibBuffer) Set(x uint, y uint, r byte, g byte, b byte) {
if x >= fb.Width || y >= fb.Height { // if x >= fb.Width || y >= fb.Height {
return // return
} // }
fb.Data[x+y*fb.Width].R = r // fb.Data[x+y*fb.Width].R = r
fb.Data[x+y*fb.Width].G = g // fb.Data[x+y*fb.Width].G = g
fb.Data[x+y*fb.Width].B = b // fb.Data[x+y*fb.Width].B = b
c := &fb.Data[x+y*fb.Width]
c.R = r
c.G = g
c.B = b
} }
func (fb *RaylibBuffer) Get(x uint, y uint) (byte, byte, byte) { func (fb *RaylibBuffer) Get(x uint, y uint) (byte, byte, byte) {
@ -58,7 +62,9 @@ func (fb *RaylibBuffer) Get(x uint, y uint) (byte, byte, byte) {
func (fb *RaylibBuffer) GetUv(u float32, v float32) (byte, byte, byte) { func (fb *RaylibBuffer) GetUv(u float32, v float32) (byte, byte, byte) {
x := uint(float32(fb.Width)*u) & (fb.Width - 1) x := uint(float32(fb.Width)*u) & (fb.Width - 1)
y := uint(float32(fb.Height)*(1-v)) & (fb.Height - 1) y := uint(float32(fb.Height)*(1-v)) & (fb.Height - 1)
return fb.Data[x+y*fb.Width].R, c := &fb.Data[x+y*fb.Width]
fb.Data[x+y*fb.Width].G, return c.R, c.G, c.B
fb.Data[x+y*fb.Width].B // fb.Data[x+y*fb.Width].R,
// fb.Data[x+y*fb.Width].G,
// fb.Data[x+y*fb.Width].B
} }