Initial commit
This commit is contained in:
commit
f26c478727
18 changed files with 621 additions and 0 deletions
47
render/engine.go
Normal file
47
render/engine.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package render
|
||||
|
||||
import (
|
||||
"github.com/pnx/go-raytracer/graphics"
|
||||
"github.com/pnx/go-raytracer/math"
|
||||
"github.com/pnx/go-raytracer/world"
|
||||
)
|
||||
|
||||
func DrawColumn(ctx *graphics.Context, x int32, wall_h int32, color math.Color) {
|
||||
if wall_h < ctx.Height() {
|
||||
y1 := (ctx.Height() - wall_h) / 2
|
||||
y2 := (ctx.Height() + wall_h) / 2
|
||||
|
||||
// Top
|
||||
// renderer.SetDrawColor(90, 90, 0, 255)
|
||||
ctx.DrawLine(x, 0, int32(x), y1, math.Color{R: 90, G: 90, B: 0, A: 255})
|
||||
|
||||
// // Middle
|
||||
// renderer.SetDrawColor(color.R, color.G, color.B, color.A)
|
||||
ctx.DrawLine(x, y1, int32(x), y2, color)
|
||||
|
||||
// Bottom
|
||||
if y2 < ctx.Height() {
|
||||
// renderer.SetDrawColor(50, 50, 50, 255)
|
||||
ctx.DrawLine(x, y2, int32(x), ctx.Height(), math.Color{R: 50, G: 50, B: 50, A: 255})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ctx.SetDrawColor(color.R, color.G, color.B, color.A)
|
||||
ctx.DrawLine(x, 0, int32(x), ctx.Height(), color)
|
||||
}
|
||||
|
||||
func DrawScene(ctx *graphics.Context, camera math.Transform, level *world.Level, colorMap []math.Color) {
|
||||
for x := range ctx.Width() {
|
||||
result := CastRay(camera, level, int(x), int(ctx.Width()))
|
||||
lineHeight := int(float64(ctx.Height()) / result.Distance)
|
||||
|
||||
color := colorMap[level.Cell(int(result.Cell.X), int(result.Cell.Y))-1]
|
||||
|
||||
if result.Side > 0 {
|
||||
color = color.Shade(2)
|
||||
}
|
||||
|
||||
DrawColumn(ctx, int32(x), int32(lineHeight), color)
|
||||
}
|
||||
}
|
||||
36
render/minimap.go
Normal file
36
render/minimap.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package render
|
||||
|
||||
import (
|
||||
"github.com/pnx/go-raytracer/graphics"
|
||||
"github.com/pnx/go-raytracer/math"
|
||||
"github.com/pnx/go-raytracer/world"
|
||||
)
|
||||
|
||||
func DrawMiniMap(ctx *graphics.Context, camera math.Transform, level *world.Level) {
|
||||
const tileSize = 32
|
||||
const scale = float64(tileSize) / float64(world.TileSize)
|
||||
// offset := math.Vec2i32{X: 25, Y: 25}
|
||||
// size := math.Vec2i32{X: 200, Y: 100}
|
||||
|
||||
ctx.DrawRect(0, 0, int32(level.W*tileSize)+3, int32(level.H*tileSize)+3, math.Color{})
|
||||
|
||||
for y := range level.H {
|
||||
for x := range level.W {
|
||||
if level.Wall(x, y) {
|
||||
ctx.DrawRect(int32(x*tileSize), int32(y*tileSize), tileSize, tileSize, math.Color{R: 255, G: 255, B: 255, A: 255})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Camera Position
|
||||
cPos := camera.Position.Get().Scale(scale)
|
||||
ctx.DrawRect(int32(cPos.X-2), int32(cPos.Y-2), 4, 4, math.Color{R: 255, G: 0, B: 255, A: 255})
|
||||
|
||||
// Rays
|
||||
for x := range ctx.Width() {
|
||||
hit := CastRay(camera, level, int(x), int(ctx.Width()))
|
||||
end := camera.Position.Get().AddVec(hit.Pos.Scale(world.TileSize)).Scale(scale)
|
||||
|
||||
ctx.DrawLine(int32(cPos.X), int32(cPos.Y), int32(end.X), int32(end.Y), math.Color{R: 150, G: 150, B: 0, A: 255})
|
||||
}
|
||||
}
|
||||
85
render/raycaster.go
Normal file
85
render/raycaster.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package render
|
||||
|
||||
import (
|
||||
stdmath "math"
|
||||
|
||||
"github.com/pnx/go-raytracer/math"
|
||||
"github.com/pnx/go-raytracer/world"
|
||||
)
|
||||
|
||||
type RayHit struct {
|
||||
Cell math.Vec2u8
|
||||
Side int
|
||||
Distance float64
|
||||
Pos math.Vec2f
|
||||
}
|
||||
|
||||
func CastRay(camera math.Transform, level *world.Level, x int, max_rays int) RayHit {
|
||||
angle := camera.Direction.Get()
|
||||
cameraX := 2*float64(x)/float64(max_rays) - 1
|
||||
rayDirX := stdmath.Cos(angle) + cameraX*stdmath.Cos(angle+stdmath.Pi/2)
|
||||
rayDirY := stdmath.Sin(angle) + cameraX*stdmath.Sin(angle+stdmath.Pi/2)
|
||||
|
||||
mapX := int(camera.X) / world.TileSize
|
||||
mapY := int(camera.Y) / world.TileSize
|
||||
|
||||
deltaDistX := stdmath.Abs(1 / rayDirX)
|
||||
deltaDistY := stdmath.Abs(1 / rayDirY)
|
||||
|
||||
var stepX, stepY int
|
||||
var sideDistX, sideDistY float64
|
||||
|
||||
if rayDirX < 0 {
|
||||
stepX = -1
|
||||
sideDistX = (float64(camera.X)/world.TileSize - float64(mapX)) * deltaDistX
|
||||
} else {
|
||||
stepX = 1
|
||||
sideDistX = (float64(mapX+1) - float64(camera.X)/world.TileSize) * deltaDistX
|
||||
}
|
||||
if rayDirY < 0 {
|
||||
stepY = -1
|
||||
sideDistY = (float64(camera.Y)/world.TileSize - float64(mapY)) * deltaDistY
|
||||
} else {
|
||||
stepY = 1
|
||||
sideDistY = (float64(mapY+1) - float64(camera.Y)/world.TileSize) * deltaDistY
|
||||
}
|
||||
|
||||
// DDA loop
|
||||
var side int // 0 = x, 1 = y
|
||||
for {
|
||||
if sideDistX < sideDistY {
|
||||
sideDistX += deltaDistX
|
||||
mapX += stepX
|
||||
side = 0
|
||||
} else {
|
||||
sideDistY += deltaDistY
|
||||
mapY += stepY
|
||||
side = 1
|
||||
}
|
||||
|
||||
if mapX < 0 || mapX >= level.W || mapY < 0 || mapY >= level.H {
|
||||
break // out of bounds
|
||||
}
|
||||
if level.Wall(mapX, mapY) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate distance to wall
|
||||
var perpWallDist float64
|
||||
if side == 0 {
|
||||
perpWallDist = (float64(mapX) - float64(camera.X)/world.TileSize + float64(1-stepX)/2) / rayDirX
|
||||
} else {
|
||||
perpWallDist = (float64(mapY) - float64(camera.Y)/world.TileSize + float64(1-stepY)/2) / rayDirY
|
||||
}
|
||||
|
||||
return RayHit{
|
||||
Cell: math.Vec2u8{X: uint8(mapX), Y: uint8(mapY)},
|
||||
Side: side,
|
||||
Distance: perpWallDist,
|
||||
Pos: math.Vec2f{
|
||||
X: rayDirX * perpWallDist,
|
||||
Y: rayDirY * perpWallDist,
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue