Poprawki do renderowania + nowy model kamery

This commit is contained in:
zymon 2024-01-20 22:53:43 +01:00
parent 952b90e79e
commit a42a7ac1a7
4 changed files with 64 additions and 13 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
.CondaPkg
Manifest.toml Manifest.toml

4
CondaPkg.toml Normal file
View file

@ -0,0 +1,4 @@
channels = ["conda-forge"]
[pip.deps]
opencv-python = ""

View file

@ -1,6 +1,8 @@
module SimpleRayTracer module SimpleRayTracer
using LinearAlgebra using LinearAlgebra
using StaticArrays
using Images using Images
using GeometryBasics using GeometryBasics
using Rotations using Rotations
@ -14,20 +16,47 @@ abstract type AbstractObject end
struct OrthogonalCamera{T<:AbstractFloat} <: AbstractCamera struct OrthogonalCamera{T<:AbstractFloat} <: AbstractCamera
origin::Vec3{T} origin::Vec3{T}
rotation::RotXYZ{T}
size::Tuple{T, T} size::Tuple{T, T}
rotation::RotXYZ{T}
# function OrthogonalCamera(o, θ, s) # function OrthogonalCamera(o, θ, s)
# new(o, RotXYZ(0.0, 0.0, 0.0), s) # new(o, RotXYZ(0.0, 0.0, 0.0), s)
# end # end
end end
function get_rays(camera::OrthogonalCamera, resolution::Tuple{I, I}) where {I<:Integer} function get_rays(camera::OrthogonalCamera, resolution::Tuple{I, I}) where {I<:Integer}
R = camera.rotation
X, Y = camera.size X, Y = camera.size
rx, ry = resolution Nx, Ny = resolution
origins = [Vec3(x, y, 0.0) + camera.origin for x = LinRange(-X, X, rx), y = LinRange(-Y, Y, ry)] screen_pixel_position = [Vec3(x, y, 0.0) + camera.origin for y = LinRange(Y/2, -Y/2, Ny), x = LinRange(-X/2, X/2, Nx)]
[Ray(o, Vec3(0.0, 0.0, 1.0)) for o in origins] [Ray(p, Vec3(0.0, 0.0, 1.0)) for p in screen_pixel_position]
end end
struct PinHoleCamera{T<:AbstractFloat} <: AbstractCamera
origin::Vec3{T}
distance::T
base::SMatrix{3, 3, T}
size::Tuple{T, T}
end
function PinHoleCamera(origin, lookAt, up, distance, size)
w = origin - lookAt |> normalize
u = cross(up, w) |> normalize
v = cross(w, u)
B = [u v w]
PinHoleCamera(origin, distance, B, size)
end
function get_rays(camera::PinHoleCamera, resolution::Tuple{I, I}) where {I<:Integer}
origin = camera.origin
d = camera.distance
X, Y = camera.size
B = camera.base
Nx, Ny = resolution
[Ray(origin, normalize(B*Vec3(x, y, -d))) for y = LinRange(Y/2, -Y/2, Ny), x = LinRange(-X/2, X/2, Nx)]
end
struct Ray{T<:AbstractFloat} struct Ray{T<:AbstractFloat}
origin::Vec3{T} origin::Vec3{T}
direction::Vec3{T} direction::Vec3{T}
@ -85,4 +114,9 @@ function trace_ray(world::World, ray::Ray)::HitInfo
return HitInfo(hit, color) return HitInfo(hit, color)
end end
function render(world, camera, resolution)
rays = get_rays(camera, resolution)
[trace_ray(world, ray).color for ray in rays];
end
end end

30
rt.jl
View file

@ -2,7 +2,8 @@ using BenchmarkTools
using LinearAlgebra using LinearAlgebra
using Rotations using Rotations
# using Images using Images
using GeometryBasics
using Colors using Colors
using GLMakie using GLMakie
@ -10,19 +11,30 @@ using GLMakie
include("SimpleRayTracer.jl") include("SimpleRayTracer.jl")
world = SimpleRayTracer.World(RGB(.1,.5,.5)) 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(-4.0, 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( 4.0, 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))) push!(world, SimpleRayTracer.Sphere(Vec3( 0.0, 0.0, 3.0), 2.0, RGB(0, 0, 1)))
camera = SimpleRayTracer.OrthogonalCamera( camera = SimpleRayTracer.OrthogonalCamera(
Vec3(0.0, 0.0, -5.0), Vec3(0.0, 0.0, -5.0),
(20.0, 10.0),
RotXYZ(0.0, 0.0, 0.0), RotXYZ(0.0, 0.0, 0.0),
(5.0, 5.0)
) )
resolution = (256, 256) camera = SimpleRayTracer.PinHoleCamera(
img = [SimpleRayTracer.trace_ray(world, ray).color for ray in SimpleRayTracer.get_rays(camera, resolution)]; Vec3(0.0, 1.0, -8.0),
Vec3(0.0, 0.0, 0.0),
Vec3(0.0, 1.0, 0.0),
1.0,
(4.0, 2.0),
)
resolution = (512, 256);
img = SimpleRayTracer.render(world, camera, resolution);
# img |> size
fig = Figure(size=resolution) fig = Figure(size=resolution)
ax = Axis(fig[1,1], aspect=1) ax = GLMakie.Axis(fig[1,1], aspect=2)
image!(ax, img) image!(ax, img |> rotr90)
Images.save("test.png", img)