169 lines
5.4 KiB
Go
169 lines
5.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
"image/color"
|
||
|
"renderer3/hrend"
|
||
|
)
|
||
|
|
||
|
func Checkerboard(cols []color.Color, size int) image.Image {
|
||
|
result := image.NewRGBA(image.Rect(0, 0, size, size))
|
||
|
for y := range size {
|
||
|
for x := range size {
|
||
|
result.Set(x, y, cols[(x+y)%len(cols)])
|
||
|
}
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// Returns a sizexsize*3 texture where the top is the top color,
|
||
|
// bottom is bottom color, middle is gradient
|
||
|
func Gradient(bottom color.Color, top color.Color, size int) image.Image {
|
||
|
result := image.NewRGBA(image.Rect(0, 0, size, size*3))
|
||
|
br, bg, bb, ba := bottom.RGBA()
|
||
|
tr, tg, tb, ta := top.RGBA()
|
||
|
for y := range size {
|
||
|
for x := range size {
|
||
|
lerp := float32(y) / float32(size-1)
|
||
|
result.Set(x, y, top)
|
||
|
result.Set(x, y+size, color.RGBA{
|
||
|
R: byte(float32(tr>>8)*(1-lerp) + float32(br>>8)*lerp),
|
||
|
G: byte(float32(tg>>8)*(1-lerp) + float32(bg>>8)*lerp),
|
||
|
B: byte(float32(tb>>8)*(1-lerp) + float32(bb>>8)*lerp),
|
||
|
A: byte(float32(ta>>8)*(1-lerp) + float32(ba>>8)*lerp),
|
||
|
})
|
||
|
result.Set(x, y+size*2, bottom)
|
||
|
}
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// Returns a 1px wide gradient where top is top color, bottom is bottom color
|
||
|
func Gradient1px(bottom color.Color, top color.Color, size int) image.Image {
|
||
|
result := image.NewRGBA(image.Rect(0, 0, 1, size))
|
||
|
br, bg, bb, ba := bottom.RGBA()
|
||
|
tr, tg, tb, ta := top.RGBA()
|
||
|
for y := range size {
|
||
|
lerp := float32(y) / float32(size-1)
|
||
|
result.Set(0, y, color.RGBA{
|
||
|
R: byte(float32(tr>>8)*(1-lerp) + float32(br>>8)*lerp),
|
||
|
G: byte(float32(tg>>8)*(1-lerp) + float32(bg>>8)*lerp),
|
||
|
B: byte(float32(tb>>8)*(1-lerp) + float32(bb>>8)*lerp),
|
||
|
A: byte(float32(ta>>8)*(1-lerp) + float32(ba>>8)*lerp),
|
||
|
})
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// Skybox for now assumes a 1px gradient
|
||
|
func Skybox() *hrend.ObjModel {
|
||
|
v := make([]hrend.Vec3f, 8)
|
||
|
vt := make([]hrend.Vec3f, 2)
|
||
|
f := make([]hrend.Facef, 12)
|
||
|
// Assuming 1px gradient, these are the only two texture points you need
|
||
|
vt[0] = hrend.Vec3f{X: 0, Y: 0, Z: 0}
|
||
|
vt[1] = hrend.Vec3f{X: 0, Y: 1, Z: 0}
|
||
|
vvt := []hrend.Vec3f{
|
||
|
vt[0], vt[0], vt[0], vt[0], vt[1], vt[1], vt[1], vt[1],
|
||
|
}
|
||
|
// Cube faces are weird, I guess just manually do them? ugh
|
||
|
// First 4 are the bottom vertices. We can make two faces out of these
|
||
|
v[0] = hrend.Vec3f{X: float32(-1), Y: float32(-1), Z: float32(-1)}
|
||
|
v[1] = hrend.Vec3f{X: float32(1), Y: float32(-1), Z: float32(-1)}
|
||
|
v[2] = hrend.Vec3f{X: float32(1), Y: float32(-1), Z: float32(1)}
|
||
|
v[3] = hrend.Vec3f{X: float32(-1), Y: float32(-1), Z: float32(1)}
|
||
|
// Now the top 4 vertices, same order as bottom
|
||
|
v[4] = hrend.Vec3f{X: float32(-1), Y: float32(1), Z: float32(-1)}
|
||
|
v[5] = hrend.Vec3f{X: float32(1), Y: float32(1), Z: float32(-1)}
|
||
|
v[6] = hrend.Vec3f{X: float32(1), Y: float32(1), Z: float32(1)}
|
||
|
v[7] = hrend.Vec3f{X: float32(-1), Y: float32(1), Z: float32(1)}
|
||
|
// These are our 12 faces
|
||
|
fv := [][3]int{
|
||
|
{0, 2, 1}, // bottom
|
||
|
{1, 2, 3},
|
||
|
{4, 5, 6}, // top
|
||
|
{6, 7, 4},
|
||
|
{0, 1, 5}, // south
|
||
|
{5, 4, 0},
|
||
|
{1, 2, 6}, // east
|
||
|
{6, 5, 1},
|
||
|
{2, 3, 7}, // North
|
||
|
{7, 6, 2},
|
||
|
{3, 0, 4}, // west
|
||
|
{4, 7, 3},
|
||
|
}
|
||
|
for i, face := range fv {
|
||
|
for j := range 3 {
|
||
|
f[i][j] = hrend.Vertex{Pos: v[face[j]], Tex: vvt[face[j]]}
|
||
|
}
|
||
|
}
|
||
|
// Now the bottom 2 faces
|
||
|
// f[0] = hrend.Facef{
|
||
|
// hrend.Vertex{Pos: v[0], Tex: vt[0]},
|
||
|
// hrend.Vertex{Pos: v[1], Tex: vt[0]},
|
||
|
// hrend.Vertex{Pos: v[2], Tex: vt[0]},
|
||
|
// }
|
||
|
// f[1] = hrend.Facef{
|
||
|
// hrend.Vertex{Pos: v[2], Tex: vt[0]},
|
||
|
// hrend.Vertex{Pos: v[3], Tex: vt[0]},
|
||
|
// hrend.Vertex{Pos: v[0], Tex: vt[0]},
|
||
|
// }
|
||
|
// // Top 2 faces
|
||
|
// f[3] = hrend.Facef{
|
||
|
// hrend.Vertex{Pos: v[4], Tex: vt[1]},
|
||
|
// hrend.Vertex{Pos: v[5], Tex: vt[1]},
|
||
|
// hrend.Vertex{Pos: v[6], Tex: vt[1]},
|
||
|
// }
|
||
|
// f[4] = hrend.Facef{
|
||
|
// hrend.Vertex{Pos: v[6], Tex: vt[1]},
|
||
|
// hrend.Vertex{Pos: v[7], Tex: vt[1]},
|
||
|
// hrend.Vertex{Pos: v[4], Tex: vt[1]},
|
||
|
// }
|
||
|
// Ugh and now the sides... so complicated
|
||
|
return &hrend.ObjModel{
|
||
|
Vertices: v,
|
||
|
VTexture: vt,
|
||
|
Faces: f,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func FlatTerrain(size int) *hrend.ObjModel {
|
||
|
result := hrend.ObjModel{
|
||
|
Vertices: make([]hrend.Vec3f, 0),
|
||
|
VTexture: make([]hrend.Vec3f, 4),
|
||
|
Faces: make([]hrend.Facef, 0),
|
||
|
}
|
||
|
// For the simple square terrain, there aren't a lot of texture coords...
|
||
|
result.VTexture[0] = hrend.Vec3f{X: 0, Y: 0, Z: 0}
|
||
|
result.VTexture[1] = hrend.Vec3f{X: 1, Y: 0, Z: 0}
|
||
|
result.VTexture[2] = hrend.Vec3f{X: 0, Y: 1, Z: 0}
|
||
|
result.VTexture[3] = hrend.Vec3f{X: 1, Y: 1, Z: 0}
|
||
|
// Generate all the simple vertices along the plane at y=0
|
||
|
for z := -size; z <= size; z++ {
|
||
|
for x := -size; x <= size; x++ {
|
||
|
result.Vertices = append(result.Vertices, hrend.Vec3f{X: float32(x), Y: 0, Z: float32(z)})
|
||
|
}
|
||
|
}
|
||
|
width := size + size + 1
|
||
|
// Faces are slightly different; we generate two for every "cell" inside the vertices
|
||
|
for z := 0; z < width-1; z++ {
|
||
|
for x := 0; x < width-1; x++ {
|
||
|
topleft := x + z*width
|
||
|
topright := x + 1 + z*width
|
||
|
bottomleft := x + (z+1)*width
|
||
|
bottomright := x + 1 + (z+1)*width
|
||
|
// remember to wind counter-clockwise
|
||
|
result.Faces = append(result.Faces, hrend.Facef{
|
||
|
hrend.Vertex{Pos: result.Vertices[topleft], Tex: result.VTexture[0]},
|
||
|
hrend.Vertex{Pos: result.Vertices[bottomleft], Tex: result.VTexture[2]},
|
||
|
hrend.Vertex{Pos: result.Vertices[topright], Tex: result.VTexture[1]},
|
||
|
}, hrend.Facef{
|
||
|
hrend.Vertex{Pos: result.Vertices[topright], Tex: result.VTexture[1]},
|
||
|
hrend.Vertex{Pos: result.Vertices[bottomleft], Tex: result.VTexture[2]},
|
||
|
hrend.Vertex{Pos: result.Vertices[bottomright], Tex: result.VTexture[3]},
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
return &result
|
||
|
}
|