294 lines
7.0 KiB
Core
294 lines
7.0 KiB
Core
/* EXTRA CREDITS (bottom of README.md on github)
|
|
|
|
* https://bitwise.handmade.network/ - series by Per Vognsen where he actually creates a C like language, very helpful, very hands on!
|
|
* https://hero.handmade.network/episode/code/day206/ - this episode of handmade hero started me on the entire compiler journey a long, long time ago.
|
|
* https://www.youtube.com/watch?v=TH9VCN6UkyQ&list=PLmV5I2fxaiCKfxMBrNsU1kgKJXD3PkyxO - I have rewatched this playlist many this, searching for keywords and ideas. Jonathan Blow's compiler was a big inspiration of mine when learning programming languages.
|
|
* A Retargetable C Compiler: Design and Implementation by Christopher W. Fraser and David R. Hanson - sometimes looked at this as a reference to figure stuff out. Very helpful resource on compiler construction, the way it's written reads more like documentation but you use what you have.
|
|
* https://github.com/JoshuaManton/sif - looked at this as a reference from time to time, author seems like a Jonathan Blow fan so it was a good resource informed by similar resources as I used.
|
|
* https://github.com/c3lang/c3c - I sometimes looked at C3 compiler as a reference, the author also let me use his big int library he wrote sometime in the past! Thanks a lot!
|
|
* https://go.dev/blog/constants - article on golang type system, untyped types, constants that kind of stuff.
|
|
* https://github.com/gingerbill/odin - I sometimes peeked at the compiler to figure stuff out when I was confused about stuff. Also we get a free code indexing and syntax highlighting using odin sublime text plugin ! :D
|
|
|
|
*/
|
|
|
|
|
|
//
|
|
// #1
|
|
//
|
|
// * Inspired by: Per Vognsen(Ion), Jonathan Blow(Jai)
|
|
// * Standard programming constructs
|
|
// * No forward declarations needed
|
|
// * Named function arguments
|
|
// * Enum values are nicely namespaced
|
|
#import "Multimedia.core"
|
|
|
|
main :: (): int
|
|
StartMultimedia(title = "Hello people!")
|
|
DrawYellowFill()
|
|
DrawCoolGradient()
|
|
DrawCircleWithGradient()
|
|
AnimateTransmorphingCircle()
|
|
RaymarchSphere()
|
|
|
|
DrawYellowFill :: ()
|
|
for y := 0, y < Mu.window.y, y+=1
|
|
for x := 0, x < Mu.window.x, x+=1
|
|
Mu.screen[x + y*Mu.window.x] = 0xFFFFFF00
|
|
|
|
for UpdateMultimedia()
|
|
if Mu.key[Key.Escape].down
|
|
Mu.key[Key.Escape].down = false
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// #2
|
|
//
|
|
// * Modules
|
|
// * User names the imports
|
|
// * Aliasing
|
|
// * Operator overloads
|
|
F :: #import "MathF32.core"
|
|
V3 :: #import "MathVec3.core"
|
|
V2 :: #import "MathVec2.core"
|
|
Vec3 :: V3.Vec3
|
|
|
|
DrawCoolGradient :: ()
|
|
for y := 0, y < Mu.window.y, y+=1
|
|
for x := 0, x < Mu.window.x, x+=1
|
|
|
|
// Normalize to range {0, 1}
|
|
uv := V2.Vec2{x->F32, y->F32} / Mu.window.sizef
|
|
|
|
// Move to range {-1, 1}
|
|
uv = uv*2->F32 - 1->F32
|
|
Assert(uv.x >= -1 && uv.x <= 1)
|
|
Assert(uv.y >= -1 && uv.y <= 1)
|
|
|
|
color := Vec3{uv.x, uv.y, 1}
|
|
Mu.screen[x + y*Mu.window.x] = V3.ConvertToARGB(color)
|
|
|
|
for UpdateMultimedia()
|
|
if Mu.key[Key.Escape].down
|
|
Mu.key[Key.Escape].down = false
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// #3
|
|
//
|
|
// * The ';;' operator
|
|
// * The ';' operator
|
|
// * Compound expressions, named parameters!
|
|
DrawCircleWithGradient :: ()
|
|
default_color := V3.ConvertToARGB({x = 1, y = 1, z = 1})
|
|
ratio := Mu.window.sizef.x / Mu.window.sizef.y
|
|
for y := 0, y < Mu.window.y, y+=1
|
|
for x := 0, x < Mu.window.x, x+=1
|
|
|
|
// Normalize to range {0, 1}
|
|
uv := V2.Vec2{x->F32, y->F32} / Mu.window.sizef
|
|
|
|
// Move to range {-1, 1}
|
|
uv = uv*2->F32 - 1->F32
|
|
uv.x *= ratio
|
|
|
|
if uv.x*uv.x + uv.y*uv.y < 0.5
|
|
color := Vec3{uv.x, uv.y, 1}
|
|
Mu.screen[x + y*Mu.window.x] = V3.ConvertToARGB(color)
|
|
else;; Mu.screen[x + y*Mu.window.x] = default_color
|
|
|
|
for UpdateMultimedia()
|
|
if Mu.key[Key.Escape].down
|
|
Mu.key[Key.Escape].down = false
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// #4
|
|
//
|
|
AnimateTransmorphingCircle :: ()
|
|
for UpdateMultimedia()
|
|
if Mu.key[Key.Escape].down
|
|
Mu.key[Key.Escape].down = false
|
|
break
|
|
|
|
default_color := V3.ConvertToARGB({x = 1, y = 1, z = 1})
|
|
ratio := Mu.window.sizef.x / Mu.window.sizef.y
|
|
for y := 0, y < Mu.window.y, y+=1
|
|
for x := 0, x < Mu.window.x, x+=1
|
|
|
|
// Normalize to range {0, 1}
|
|
uv := V2.Vec2{x->F32, y->F32} / Mu.window.sizef
|
|
|
|
// Move to range {-1, 1}
|
|
uv = uv*2->F32 - 1->F32
|
|
uv.x *= ratio
|
|
|
|
if F.Cos(Mu.time.total->F32)*uv.x*uv.x + F.Sin(Mu.time.total->F32)*uv.y*uv.y < 0.5
|
|
color := Vec3{uv.x, uv.y, 1}
|
|
Mu.screen[x + y*Mu.window.x] = V3.ConvertToARGB(color)
|
|
else ;; Mu.screen[x + y*Mu.window.x] = default_color
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// #5
|
|
//
|
|
Epsilon :: 0.00001
|
|
|
|
SphereSDF :: (pos: Vec3): F32
|
|
result := V3.Length(pos) - 1.0
|
|
return result
|
|
|
|
RaymarchSphere :: ()
|
|
for UpdateMultimedia()
|
|
if Mu.key[Key.Escape].down
|
|
Mu.key[Key.Escape].down = false
|
|
break
|
|
|
|
up := Vec3{0, 1, 0}
|
|
forward := Vec3{0, 0, -1}
|
|
side := V3.Normalize(V3.Cross(forward, up))
|
|
|
|
LightPos := Vec3{2,4,2}
|
|
LightPos.x = F.Cos(Mu.time.total->F32)*4
|
|
LightPos.y = F.Sin(Mu.time.total->F32)*4
|
|
|
|
ambient_color := Vec3{0.2,0.2,0.2}
|
|
diffuse_color := Vec3{0.7,0.2,0.2}
|
|
eye := Vec3{0, 0, 2}
|
|
light_intensity :: 1.2->F32
|
|
|
|
Xf := 1 / Mu.window.sizef.x
|
|
Yf := 1 / Mu.window.sizef.y
|
|
ratio := Mu.window.sizef.x / Mu.window.sizef.y
|
|
for y := 0, y < Mu.window.y, y+=1
|
|
for x := 0, x < Mu.window.x, x+=1
|
|
uv := Vec3{x->F32 * Xf * 2 - 1, y->F32 * Yf * 2 - 1, 1.0}
|
|
uv.x *= ratio
|
|
dir := V3.Normalize(Vec3{V3.Dot(side, uv), V3.Dot(up, uv), V3.Dot(forward, uv)})
|
|
|
|
t: F32
|
|
end: F32 = 100.0
|
|
hit := true
|
|
p: Vec3
|
|
for i := 0, i < 255, i+=1
|
|
p = eye + dir*t
|
|
|
|
distance := SphereSDF(p)
|
|
if distance < Epsilon
|
|
break
|
|
|
|
t += distance
|
|
if distance >= end
|
|
hit = false
|
|
break
|
|
|
|
if hit
|
|
normal := V3.Normalize(Vec3{
|
|
SphereSDF({p.x + Epsilon, p.y, p.z}) - SphereSDF({p.x - Epsilon, p.y, p.z}),
|
|
SphereSDF({p.x, p.y + Epsilon, p.z}) - SphereSDF({p.x, p.y - Epsilon, p.z}),
|
|
SphereSDF({p.x, p.y, p.z + Epsilon}) - SphereSDF({p.x, p.y, p.z - Epsilon}),
|
|
})
|
|
|
|
light_to_point := V3.Normalize(LightPos - p)
|
|
|
|
ambient :: 0.2->F32
|
|
diffuse := V3.Dot(normal, light_to_point)
|
|
|
|
color := ambient_color*ambient->F32
|
|
if diffuse > Epsilon
|
|
color = color + diffuse_color*diffuse
|
|
color = color * light_intensity
|
|
|
|
// Gamma correction
|
|
color.x = F.SquareRoot(color.x)
|
|
color.y = F.SquareRoot(color.y)
|
|
color.z = F.SquareRoot(color.z)
|
|
Mu.screen[x + y*Mu.window.x] = V3.ConvertToARGB(color)
|
|
|
|
else;; Mu.screen[x + y*Mu.window.x] = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|