Proste generowanie sceny z wykorzystaniem sledzenia promieni
This commit is contained in:
parent
93ab7d8546
commit
dc450860f3
3 changed files with 120 additions and 0 deletions
|
@ -1,11 +1,15 @@
|
|||
[deps]
|
||||
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
||||
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
|
||||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
||||
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
|
||||
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
|
||||
ImageView = "86fae568-95e7-573e-a6b2-d8a6b900c9ef"
|
||||
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
|
||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
|
||||
StackViews = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
|
||||
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
|
||||
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
||||
|
|
88
SimpleRayTracer.jl
Normal file
88
SimpleRayTracer.jl
Normal file
|
@ -0,0 +1,88 @@
|
|||
module SimpleRayTracer
|
||||
|
||||
using LinearAlgebra
|
||||
using Images
|
||||
using GeometryBasics
|
||||
using Rotations
|
||||
|
||||
export OrthogonalCamera
|
||||
export World, Ray
|
||||
export Sphere
|
||||
|
||||
abstract type AbstractCamera end
|
||||
abstract type AbstractObject end
|
||||
|
||||
struct OrthogonalCamera{T<:AbstractFloat} <: AbstractCamera
|
||||
origin::Vec3{T}
|
||||
rotation::RotXYZ{T}
|
||||
size::Tuple{T, T}
|
||||
# function OrthogonalCamera(o, θ, s)
|
||||
# new(o, RotXYZ(0.0, 0.0, 0.0), s)
|
||||
# end
|
||||
end
|
||||
|
||||
function get_rays(camera::OrthogonalCamera, resolution::Tuple{I, I}) where {I<:Integer}
|
||||
X, Y = camera.size
|
||||
rx, ry = resolution
|
||||
origins = [Vec3(x, y, 0.0) + camera.origin for x = LinRange(-X, X, rx), y = LinRange(-Y, Y, ry)]
|
||||
[Ray(o, Vec3(0.0, 0.0, 1.0)) for o in origins]
|
||||
end
|
||||
|
||||
struct Ray{T<:AbstractFloat}
|
||||
origin::Vec3{T}
|
||||
direction::Vec3{T}
|
||||
# function Ray{T}(o, d) where {T<:AbstractFloat}
|
||||
# new(o, d |> normalize)
|
||||
# end
|
||||
end
|
||||
|
||||
struct HitInfo
|
||||
hit::Bool
|
||||
color::RGB{N0f8}
|
||||
end
|
||||
|
||||
struct World
|
||||
objects::Vector
|
||||
background::RGB{N0f8}
|
||||
function World(color)
|
||||
new([], color)
|
||||
end
|
||||
end
|
||||
|
||||
Base.push!(w::World, x::AbstractObject) = push!(w.objects, x)
|
||||
|
||||
struct Sphere{T<:AbstractFloat} <: AbstractObject
|
||||
origin::Vec3{T}
|
||||
radius::T
|
||||
color::RGB{N0f8}
|
||||
end
|
||||
|
||||
function check_hit(ray::Ray{T}, sphere::Sphere{T})::Tuple{Bool, T} where {T <: AbstractFloat}
|
||||
p = ray.origin - sphere.origin
|
||||
a = dot(ray.direction, ray.direction)
|
||||
b = 2 * dot(p, ray.direction)
|
||||
c = dot(p, p) - sphere.radius^2
|
||||
Δ = b^2 - 4a*c
|
||||
Δ < 0.0 && return false, -1.0
|
||||
x, z = -b/(2a), √Δ/(2a)
|
||||
t = x - z
|
||||
t = t < eps() ? x + z : t
|
||||
return t < eps() ? (false, -1.0) : (true, t)
|
||||
end
|
||||
|
||||
function trace_ray(world::World, ray::Ray)::HitInfo
|
||||
mindist = Float64 |> typemax |> prevfloat
|
||||
hit = false
|
||||
color = world.background
|
||||
for obj in world.objects
|
||||
hit, dist = check_hit(ray, obj)
|
||||
if hit && dist < mindist
|
||||
mindist = dist
|
||||
hit = true
|
||||
color = obj.color
|
||||
end
|
||||
end
|
||||
return HitInfo(hit, color)
|
||||
end
|
||||
|
||||
end
|
28
rt.jl
Normal file
28
rt.jl
Normal file
|
@ -0,0 +1,28 @@
|
|||
using BenchmarkTools
|
||||
using LinearAlgebra
|
||||
using Rotations
|
||||
|
||||
# using Images
|
||||
using Colors
|
||||
using GLMakie
|
||||
|
||||
##
|
||||
include("SimpleRayTracer.jl")
|
||||
|
||||
world = SimpleRayTracer.World(RGB(.1,.5,.5))
|
||||
push!(world, SimpleRayTracer.Sphere(Vec3(-2.5, 0.0, 0.0), 2.0, RGB(1, 0, 0)))
|
||||
push!(world, SimpleRayTracer.Sphere(Vec3( 2.5, 0.0, 0.0), 2.0, RGB(0, 1, 0)))
|
||||
push!(world, SimpleRayTracer.Sphere(Vec3( 0.0, 0.0, 2.5), 2.0, RGB(0, 0, 1)))
|
||||
|
||||
camera = SimpleRayTracer.OrthogonalCamera(
|
||||
Vec3(0.0, 0.0, -5.0),
|
||||
RotXYZ(0.0, 0.0, 0.0),
|
||||
(5.0, 5.0)
|
||||
)
|
||||
|
||||
resolution = (256, 256)
|
||||
img = [SimpleRayTracer.trace_ray(world, ray).color for ray in SimpleRayTracer.get_rays(camera, resolution)];
|
||||
|
||||
fig = Figure(size=resolution)
|
||||
ax = Axis(fig[1,1], aspect=1)
|
||||
image!(ax, img)
|
Loading…
Reference in a new issue