Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- func Init(cfg : Kuin@CCfg)
- do cfg.Title :: "AOBench"
- do cfg.FullScr :: false
- do cfg.PadNum :: 1
- do cfg.WaitTime :: 60
- end func
- func Main()
- var ao : AOBench@AOBench
- do ao :: @new AOBench@AOBench
- do ao.Init(256, 256)
- do ao.Calc()
- while (true)
- do Kuin@Act()
- do ao.Render()
- end while
- do Kuin@Stop()
- end func
- class Vector3
- var X : float
- var Y : float
- var Z : float
- func Init(x : float, y : float, z : float)
- do this.X :: x
- do this.Y :: y
- do this.Z :: z
- end func
- func Clone() : AOBench@Vector3
- var v : AOBench@Vector3 :: @new AOBench@Vector3
- do v.Init(this.X, this.Y, this.Z)
- return v
- end func
- end class
- func VecAdd(a : AOBench@Vector3, b : AOBench@Vector3) : AOBench@Vector3
- var v : AOBench@Vector3 :: @new AOBench@Vector3
- do v.X :: a.X + b.X
- do v.Y :: a.Y + b.Y
- do v.Z :: a.Z + b.Z
- return v
- end func
- func VecSub(a : AOBench@Vector3, b : AOBench@Vector3) : AOBench@Vector3
- var v : AOBench@Vector3 :: @new AOBench@Vector3
- do v.X :: a.X - b.X
- do v.Y :: a.Y - b.Y
- do v.Z :: a.Z - b.Z
- return v
- end func
- func VecCross(a : AOBench@Vector3, b : AOBench@Vector3) : AOBench@Vector3
- var v : AOBench@Vector3 :: @new AOBench@Vector3
- do v.X :: a.Y * b.Z - a.Z * b.Y
- do v.Y :: a.Z * b.X - a.X * b.Z
- do v.Z :: a.X * b.Y - a.Y * b.X
- return v
- end func
- func VecDot(a : AOBench@Vector3, b : AOBench@Vector3) : float
- return a.X * b.X + a.Y * b.Y + a.Z * b.Z
- end func
- func VecLength(a : AOBench@Vector3) : float
- return Math@Sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z)
- end func
- func VecNormalize(a : AOBench@Vector3) : AOBench@Vector3
- var len : float :: AOBench@VecLength(a)
- var v : AOBench@Vector3 :: a.Clone()
- if (len > 0.00000000000000001)
- do v.X :/ len
- do v.Y :/ len
- do v.Z :/ len
- end if
- return v
- end func
- class AOBench
- class Isect
- var T : float
- var Hit : bool
- var Pos : AOBench@Vector3
- var Norm : AOBench@Vector3
- func Init()
- do this.T :: 1000000.0
- do this.Hit :: false
- do this.Pos :: @new AOBench@Vector3
- do this.Pos.Init(0.0, 0.0, 0.0)
- do this.Norm :: @new AOBench@Vector3
- do this.Norm.Init(0.0, 0.0, 0.0)
- end func
- end class
- class Ray
- var Org : AOBench@Vector3
- var Dir : AOBench@Vector3
- func Init(o : AOBench@Vector3, d : AOBench@Vector3)
- do this.Org :: o.Clone()
- do this.Dir :: d.Clone()
- end func
- end class
- class Sphere
- var Center : AOBench@Vector3
- var Radius : float
- func Init(c : AOBench@Vector3, r : float)
- do this.Center :: c.Clone()
- do this.Radius :: r
- end func
- func Intersect(ray : Ray, isect : Isect)
- var rs : AOBench@Vector3 :: AOBench@VecSub(ray.Org, this.Center)
- var B : float :: AOBench@VecDot(rs, ray.Dir)
- var C : float :: AOBench@VecDot(rs, rs) - (this.Radius * this.Radius)
- var D : float :: B * B - C
- if (D > 0.0)
- var t : float :: -B - Math@Sqrt(D)
- if ((t > 0.0) & (t < isect.T))
- do isect.T :: t
- do isect.Hit :: true
- do isect.Pos :: @new AOBench@Vector3
- do isect.Pos.X :: ray.Org.X + ray.Dir.X * t
- do isect.Pos.Y :: ray.Org.Y + ray.Dir.Y * t
- do isect.Pos.Z :: ray.Org.Z + ray.Dir.Z * t
- var n : AOBench@Vector3 :: AOBench@VecSub(isect.Pos, this.Center)
- do isect.Norm :: AOBench@VecNormalize(n)
- end if
- end if
- end func
- end class
- class Plane
- var Pos : AOBench@Vector3
- var Norm : AOBench@Vector3
- func Init(p : AOBench@Vector3, n : AOBench@Vector3)
- do this.Pos :: p.Clone()
- do this.Norm :: n.Clone()
- end func
- func Intersect(ray : Ray, isect : Isect)
- var d : float :: - AOBench@VecDot(this.Pos, this.Norm)
- var v : float :: AOBench@VecDot(ray.Dir, this.Norm)
- if ((-0.00000000000000001 < v) & (v < 0.00000000000000001))
- return
- end if
- var t : float :: - (AOBench@VecDot(ray.Org, this.Norm) + d) / v
- if ((t > 0.0) & (t < isect.T))
- do isect.Hit :: true
- do isect.T :: t
- do isect.Norm :: this.Norm.Clone()
- do isect.Pos.X :: ray.Org.X + ray.Dir.X * t
- do isect.Pos.Y :: ray.Org.Y + ray.Dir.Y * t
- do isect.Pos.Z :: ray.Org.Z + ray.Dir.Z * t
- end if
- end func
- end class
- var Width : int
- var Height : int
- var SubSamples : int
- var AoSamples : int
- var Eps : float
- var Phi : int
- var Theta : int
- var AllRay : int
- var Spheres : []Sphere
- var Floor : Plane
- var Output : [][]float
- func Init(x : int, y : int)
- do this.Width :: x
- do this.Height :: y
- do this.SubSamples :: 2
- do this.AoSamples :: 8
- do this.Eps :: 0.0001
- do this.Phi :: this.AoSamples
- do this.Theta :: this.AoSamples
- do this.AllRay :: this.AoSamples * this.AoSamples
- do this.Spheres :: @new [3]Sphere
- for i(0, 2)
- do this.Spheres[i] :: @new Sphere
- end for
- var rad : float :: 0.5
- var center : AOBench@Vector3 :: @new AOBench@Vector3
- do center.Init(-2.0, 0.0, -3.5)
- do this.Spheres[0].Init(center, rad)
- do center.Init(-0.5, 0.0, -3.0)
- do this.Spheres[1].Init(center, rad)
- do center.Init(1.0, 0.0, -2.2)
- do this.Spheres[2].Init(center, rad)
- var pos : AOBench@Vector3 :: @new AOBench@Vector3
- do pos.Init(0.0, -0.5, 0.0)
- var norm : AOBench@Vector3 :: @new AOBench@Vector3
- do norm.Init(0.0, 1.0, 0.0)
- do this.Floor :: @new Plane
- do this.Floor.Init(pos, norm)
- do this.Output :: @new [this.Width][]float
- for i(0, this.Width - 1)
- do this.Output[i] :: @new [this.Height]float
- for j(0, this.Height - 1)
- do this.Output[i][j] :: 0.0
- end for
- end for
- end func
- func OrthoBasis(basis : []Vector3, n : AOBench@Vector3)
- for i(0, 2)
- do basis[i] :: @new AOBench@Vector3
- do basis[i].Init(0.0, 0.0, 0.0)
- end for
- do basis[2] :: n.Clone()
- if ((n.X < 0.6) & (n.X > -0.6))
- do basis[1].X :: 1.0
- elif ((n.Y < 0.6) & (n.Y > -0.6))
- do basis[1].Y :: 1.0
- elif ((n.Z < 0.6) & (n.Z > -0.6))
- do basis[1].Z :: 1.0
- else
- do basis[1].X :: 1.0
- end if
- do basis[0] :: AOBench@VecNormalize(AOBench@VecCross(basis[1], basis[2]))
- do basis[1] :: AOBench@VecNormalize(AOBench@VecCross(basis[2], basis[0]))
- end func
- func Random() : float
- var r : float :: Kuin@Rand(0, 1000)$float
- do r :/ 1000.0
- return r
- end func
- var OcculusionResult : float
- func AmbientOcculusion(isect : Isect) : float
- var basis : []Vector3 :: @new [3]Vector3
- do this.OrthoBasis(basis, isect.Norm)
- var p : AOBench@Vector3 :: @new AOBench@Vector3
- do p.X :: isect.Pos.X + this.Eps * isect.Norm.X
- do p.Y :: isect.Pos.Y + this.Eps * isect.Norm.Y
- do p.Z :: isect.Pos.Z + this.Eps * isect.Norm.Z
- var occlusion : int :: 0
- for j(0, this.Phi)
- for i(0, this.Theta)
- var theta : float :: Math@Sqrt(this.Random())
- var phi : float :: 2.0 * Math@Pi * this.Random()
- var x : float :: Math@Cos(phi) * theta
- var y : float :: Math@Sin(phi) * theta
- var z : float :: Math@Sqrt(1.0 - theta * theta)
- { local -> global }
- var rx : float :: x * basis[0].X + y * basis[1].X + z * basis[2].X
- var ry : float :: x * basis[0].Y + y * basis[1].Y + z * basis[2].Y
- var rz : float :: x * basis[0].Z + y * basis[1].Z + z * basis[2].Z
- var rayDir : AOBench@Vector3 :: @new AOBench@Vector3
- do rayDir.Init(rx, ry, rz)
- var ray : Ray :: @new Ray
- do ray.Init(p, rayDir)
- var occIsect : Isect :: @new Isect
- do occIsect.Init()
- for i(0, 2)
- do this.Spheres[i].Intersect(ray, occIsect)
- end for
- do this.Floor.Intersect(ray, occIsect)
- if (occIsect.Hit)
- do occlusion :+ 1
- end if
- end for
- end for
- var occ : float :: (this.AllRay - occlusion)$float / this.AllRay$float
- do this.OcculusionResult :: occ
- return occ
- end func
- func Calc()
- var half_w : float :: this.Width$float * 0.5
- var half_h : float :: this.Height$float * 0.5
- for y(0, this.Height - 1)
- for x(0, this.Width - 1)
- var px : float :: (x$float - half_w)/half_w
- var py : float :: -(y$float - half_h)/half_h
- var eye : AOBench@Vector3 :: @new AOBench@Vector3
- do eye.Init(px, py, -1.0)
- do eye :: AOBench@VecNormalize(eye)
- var zero : AOBench@Vector3 :: @new AOBench@Vector3
- do zero.Init(0.0, 0.0, 0.0)
- var ray : Ray :: @new Ray
- do ray.Init(zero, eye)
- var isect : Isect :: @new Isect
- do isect.Init()
- for i(0, 2)
- do this.Spheres[i].Intersect(ray, isect)
- end for
- do this.Floor.Intersect(ray, isect)
- var col : float :: 0.0
- if (isect.Hit)
- do this.AmbientOcculusion(isect)
- {
- AmbientOcclusion() 関数の返り値が返ってこない。
- }
- do col :: this.OcculusionResult
- end if
- do this.Output[x][y] :: col
- end for
- do Kuin@Dbg(y.ToStr() ~ "/" ~ (this.Height - 1).ToStr())
- end for
- end func
- func Render()
- var half_w : float :: this.Width$float * 0.5
- var half_h : float :: this.Height$float * 0.5
- for y(0, this.Height - 1)
- for x(0, this.Width - 1)
- var x0 : float :: x$float
- var y0 : float :: y$float
- var x1 : float :: x$float + 1.0
- var y1 : float :: y$float + 1.0
- var col : float :: this.Output[x][y]
- do D3D@DrawRect(x0, y0, x1, y1, col, col, col, 1.0)
- end for
- end for
- end func
- end class
Add Comment
Please, Sign In to add comment