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]
|
[deps]
|
||||||
|
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
||||||
|
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
|
||||||
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
|
||||||
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
|
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
|
||||||
|
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
|
||||||
ImageView = "86fae568-95e7-573e-a6b2-d8a6b900c9ef"
|
ImageView = "86fae568-95e7-573e-a6b2-d8a6b900c9ef"
|
||||||
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
|
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
|
||||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||||
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
|
||||||
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
|
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
|
||||||
StackViews = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
|
StackViews = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
|
||||||
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
|
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
|
||||||
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
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