Actually working oh wow
This commit is contained in:
parent
123ebc83df
commit
4a399c7bb7
@ -42,22 +42,40 @@ func (m *Mat44f) SetIdentity() {
|
|||||||
// instead of creating a new one all the time (garbage collection)
|
// instead of creating a new one all the time (garbage collection)
|
||||||
|
|
||||||
// Compute the projection matrix, filling the given matrix. FOV is in degrees
|
// Compute the projection matrix, filling the given matrix. FOV is in degrees
|
||||||
func (m *Mat44f) SetProjection(fov float32, near float32, far float32) {
|
func (m *Mat44f) SetProjection(fov float32, aspect float32, near float32, far float32) {
|
||||||
// Projection matrix is (ROW MAJOR!)
|
// Projection matrix is (ROW MAJOR!)
|
||||||
// S 0 0 0
|
// S 0 0 0
|
||||||
// 0 S 0 0
|
// 0 S 0 0
|
||||||
// 0 0 -f/(f-n) -1
|
// 0 0 -f/(f-n) -1
|
||||||
// 0 0 -fn/(f-n) 0
|
// 0 0 -fn/(f-n) 0
|
||||||
// where S (scale) is 1 / tan(fov / 2) (assuming fov is radians)
|
// where S (scale) is 1 / tan(fov / 2) (assuming fov is radians)
|
||||||
// NOTE: -1 there is actually -1/c, where c is distance from viewer to
|
// // NOTE: -1 there is actually -1/c, where c is distance from viewer to
|
||||||
// projection plane. We fix it at 1 for now but...
|
// // projection plane. We fix it at 1 for now but...
|
||||||
|
// m.ZeroFill()
|
||||||
|
// scale := float32(1 / math.Tan(float64(fov)*0.5*math.Pi/180))
|
||||||
|
// m.Set(0, 0, scale)
|
||||||
|
// m.Set(1, 1, scale)
|
||||||
|
// m.Set(2, 2, -far/(far-near))
|
||||||
|
// m.Set(3, 2, -1)
|
||||||
|
// m.Set(2, 3, -far*near/(far-near))
|
||||||
|
// OK apparently I suck, let's use somebody else's projection matrix:
|
||||||
m.ZeroFill()
|
m.ZeroFill()
|
||||||
scale := float32(1 / math.Tan(float64(fov)*0.5*math.Pi/180))
|
|
||||||
m.Set(0, 0, scale)
|
DEG2RAD := math.Acos(-1.0) / 180.0
|
||||||
m.Set(1, 1, scale)
|
tangent := math.Tan(float64(fov/2.0) * DEG2RAD) // tangent of half fovY
|
||||||
m.Set(2, 2, -far/(far-near))
|
top := near * float32(tangent) // half height of near plane
|
||||||
|
right := top * aspect // half width of near plane
|
||||||
|
// Column major maybe???
|
||||||
|
// n/r 0 0 0
|
||||||
|
// 0 n/t 0 0
|
||||||
|
// 0 0 -(f+n)/(f-n) -1
|
||||||
|
// 0 0 -(2fn)/(f-n) 0
|
||||||
|
|
||||||
|
m.Set(0, 0, near/right)
|
||||||
|
m.Set(1, 1, near/top)
|
||||||
|
m.Set(2, 2, -(far+near)/(far-near))
|
||||||
m.Set(3, 2, -1)
|
m.Set(3, 2, -1)
|
||||||
m.Set(2, 3, -far*near/(far-near))
|
m.Set(2, 3, -(2*far*near)/(far-near))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mat44f) SetTranslation(x, y, z float32) {
|
func (m *Mat44f) SetTranslation(x, y, z float32) {
|
||||||
|
@ -42,6 +42,9 @@ 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) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if boundsTL.Y < 0 {
|
if boundsTL.Y < 0 {
|
||||||
boundsTL.Y = 0
|
boundsTL.Y = 0
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"renderer1/hrend"
|
"renderer1/hrend"
|
||||||
"runtime/pprof" // For performance profiling (unnecessary)
|
"runtime/pprof" // For performance profiling (unnecessary)
|
||||||
|
"time"
|
||||||
|
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
|
|
||||||
@ -20,7 +23,9 @@ const (
|
|||||||
FarClip = 100
|
FarClip = 100
|
||||||
FOV = 90.0
|
FOV = 90.0
|
||||||
ZOffset = -1.5
|
ZOffset = -1.5
|
||||||
ObjectFile = "head.obj"
|
Movement = 1.0
|
||||||
|
Fps = 60
|
||||||
|
ObjectFile = "../head.obj"
|
||||||
TextureFile = "../head.jpg"
|
TextureFile = "../head.jpg"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,38 +78,98 @@ func main() {
|
|||||||
defer pprof.StopCPUProfile()
|
defer pprof.StopCPUProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
fb := NewRaylibBuffer(Width, Height)
|
|
||||||
rb := hrend.NewRenderbuffer(fb, Width, Height)
|
|
||||||
o, texture := loadDefault()
|
|
||||||
|
|
||||||
light := hrend.Vec3f{0, 0, -1}
|
|
||||||
|
|
||||||
var projection, worldToCamera, viewport hrend.Mat44f
|
|
||||||
|
|
||||||
rl.InitWindow(Width, Height, "Simple renderer with raylib")
|
rl.InitWindow(Width, Height, "Simple renderer with raylib")
|
||||||
defer rl.CloseWindow()
|
defer rl.CloseWindow()
|
||||||
|
|
||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(Fps)
|
||||||
|
|
||||||
|
fb := NewRaylibBuffer(Width, Height)
|
||||||
|
defer rl.UnloadTexture(fb.Texture)
|
||||||
|
defer rl.UnloadImageColors(fb.Data)
|
||||||
|
defer rl.UnloadImage(fb.Image)
|
||||||
|
|
||||||
|
rb := hrend.NewRenderbuffer(fb, Width, Height)
|
||||||
|
o, texture := loadDefault()
|
||||||
|
|
||||||
|
light := hrend.Vec3f{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Z: -1,
|
||||||
|
}
|
||||||
|
|
||||||
var thing hrend.Vec2i
|
var thing hrend.Vec2i
|
||||||
log.Print(thing)
|
log.Print(thing)
|
||||||
|
|
||||||
|
var projection, worldToCamera, viewport hrend.Mat44f
|
||||||
|
|
||||||
|
// These don't really change
|
||||||
|
projection.SetProjection(float32(FOV), float32(Width)/float32(Height), NearClip, FarClip)
|
||||||
|
viewport.SetViewportSimple(int(fb.Width), int(fb.Height), 1) //65535)
|
||||||
|
|
||||||
|
log.Printf("Starting raylib loop")
|
||||||
|
|
||||||
|
frameSum := 0.0
|
||||||
|
frameCount := 0
|
||||||
|
frameAverage := 0.0
|
||||||
|
|
||||||
|
xofs := float32(0.0)
|
||||||
|
yofs := float32(0.0)
|
||||||
|
zofs := float32(ZOffset)
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
rl.BeginDrawing()
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
if rl.IsKeyDown(rl.KeyD) {
|
||||||
|
xofs += Movement / Fps
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeyA) {
|
||||||
|
xofs -= Movement / Fps
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeyW) {
|
||||||
|
zofs += Movement / Fps
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeyS) {
|
||||||
|
zofs -= Movement / Fps
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeySpace) {
|
||||||
|
yofs -= Movement / Fps
|
||||||
|
}
|
||||||
|
if rl.IsKeyDown(rl.KeyLeftShift) {
|
||||||
|
yofs += Movement / Fps
|
||||||
|
}
|
||||||
|
|
||||||
|
// This might (thought not currently)
|
||||||
|
worldToCamera.SetTranslation(xofs, yofs, zofs)
|
||||||
|
|
||||||
screenmat := worldToCamera.Multiply(&projection)
|
screenmat := worldToCamera.Multiply(&projection)
|
||||||
screenmat = screenmat.Multiply(&viewport)
|
screenmat = screenmat.Multiply(&viewport)
|
||||||
|
|
||||||
|
for i := 0; i < Width*Height; i++ {
|
||||||
|
fb.Data[i].R = 0
|
||||||
|
fb.Data[i].G = 0
|
||||||
|
fb.Data[i].B = 0
|
||||||
|
}
|
||||||
|
//rl.ImageDrawRectangle(fb.Image, 0, 0, Width, Height, rl.Black)
|
||||||
|
//rl.ImageClearBackground(fb.Image, rl.Black)
|
||||||
|
|
||||||
var sc [3]hrend.Vertex
|
var sc [3]hrend.Vertex
|
||||||
rb.ResetZBuffer()
|
rb.ResetZBuffer()
|
||||||
for _, f := range o.Faces {
|
for _, f := range o.Faces {
|
||||||
// Precompute perspective for vertices to save time. Notice Z
|
// Precompute perspective for vertices to save time. Notice Z
|
||||||
// is not considered: is this orthographic projection? Yeah probably...
|
// is not considered: is this orthographic projection? Yeah probably...
|
||||||
var fpt [3]hrend.Vec3f
|
var fpt [3]hrend.Vec3f
|
||||||
|
maxz := float32(-math.MaxFloat32)
|
||||||
for i := range 3 { // Triangles, bro
|
for i := range 3 { // Triangles, bro
|
||||||
sc[i] = f[i]
|
sc[i] = f[i]
|
||||||
sc[i].Pos = screenmat.MultiplyPoint3(f[i].Pos)
|
sc[i].Pos = screenmat.MultiplyPoint3(f[i].Pos)
|
||||||
fpt[i] = worldToCamera.MultiplyPoint3(f[i].Pos)
|
fpt[i] = worldToCamera.MultiplyPoint3(f[i].Pos)
|
||||||
|
maxz = max(maxz, sc[i].Pos.Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxz < 0 || maxz > 1 {
|
||||||
|
//log.Printf("Clipping %f %f %f", sc[0].Pos.Z, sc[1].Pos.Z, sc[2].Pos.Z)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
l1 := fpt[2].Sub(fpt[0])
|
l1 := fpt[2].Sub(fpt[0])
|
||||||
@ -113,12 +178,24 @@ func main() {
|
|||||||
intensity := n.MultSimp(&light)
|
intensity := n.MultSimp(&light)
|
||||||
if intensity > 0 {
|
if intensity > 0 {
|
||||||
hrend.TriangleTextured(&rb, texture, intensity, sc[0], sc[1], sc[2])
|
hrend.TriangleTextured(&rb, 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl.UpdateTexture(fb.Texture, fb.Data)
|
||||||
|
|
||||||
|
frameSum += time.Since(start).Seconds()
|
||||||
|
frameCount += 1
|
||||||
|
if frameCount&0x7 == 0 {
|
||||||
|
frameAverage = frameSum / float64(frameCount)
|
||||||
|
frameSum = 0
|
||||||
|
frameCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.BeginDrawing()
|
||||||
rl.ClearBackground(rl.RayWhite)
|
rl.ClearBackground(rl.RayWhite)
|
||||||
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LightGray)
|
rl.DrawTexture(fb.Texture, 0, 0, rl.White)
|
||||||
|
rl.DrawText(fmt.Sprintf("Frame: %fms", frameAverage*1000), 5, 5, 20, rl.Red)
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,31 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
rl "github.com/gen2brain/raylib-go/raylib"
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RaylibBuffer struct {
|
type RaylibBuffer struct {
|
||||||
Data []rl.Color
|
Data []rl.Color
|
||||||
|
Image *rl.Image
|
||||||
|
Texture rl.Texture2D
|
||||||
Width uint
|
Width uint
|
||||||
Height uint
|
Height uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRaylibBuffer(width uint, height uint) *RaylibBuffer {
|
func NewRaylibBuffer(width uint, height uint) *RaylibBuffer {
|
||||||
|
log.Printf("Creating new raylib framebuffer using texture + image")
|
||||||
|
//rl.NewTexture2D(1, Width, Height, 0, )
|
||||||
|
rlimage := rl.GenImageColor(Width, Height, rl.Black)
|
||||||
|
rl.ImageFormat(rlimage, rl.UncompressedR8g8b8a8)
|
||||||
|
log.Printf("Generated baseline image: %v", rlimage)
|
||||||
|
rltexture := rl.LoadTextureFromImage(rlimage)
|
||||||
|
log.Printf("Generated texture from image")
|
||||||
|
data := rl.LoadImageColors(rlimage)
|
||||||
|
log.Printf("Generated pixel data from image")
|
||||||
return &RaylibBuffer{
|
return &RaylibBuffer{
|
||||||
Data: make([]rl.Color, width*height),
|
Data: data,
|
||||||
|
Image: rlimage,
|
||||||
|
Texture: rltexture,
|
||||||
Width: width,
|
Width: width,
|
||||||
Height: height,
|
Height: height,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user