New parsing (#4)

* works for cornell now, will be extended to import others

* works for all scenes

* can load environments and blur them

* minor cleanup

* Example commands added to README.md
This commit is contained in:
Jakub Poćwiardowski 2025-01-18 18:31:27 +01:00 committed by GitHub
parent 9b3d3615e3
commit b74883b796
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 366 additions and 174 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

10
.idea/TRAK.iml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.8 (TRAK)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.8 (TRAK)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (TRAK)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/TRAK.iml" filepath="$PROJECT_DIR$/.idea/TRAK.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -30,4 +30,16 @@ W programie powinny znaleźć się m.in.:
| ~~Prezentacja projektów związanych z artykułami~~ | 3.12.2024 |
| (!) Oddanie pierwszego etapu projektu (!) | 13.12.2024 |
| **Oddanie ostatecznej wersji programu** | **24.01.2025** |
| **Prezentacja projektów nie związanych z artykułami** | **28.01.2025** |
| **Prezentacja projektów nie związanych z artykułami** | **28.01.2025** |
## Wywoływanie z terminala
```bash
# Wywołanie algorytmu ray tracing z domyślnymi parametrami i sceną
python main.py --algorithm ray_tracing
```
```bash
# Wywołanie algorytmu ray tracing ze specyfikacją sceny z folderu scenes, liczbą sampli na pixek, rozdzielczością, środowiskiem i rozmyciem środowiska
python main.py --scene three_spheres --samples_per_pixel 100 --resolution 100x100 --environment lake.png --env_blur 10
```

View File

@ -1,35 +0,0 @@
import argparse
from configparser import ConfigParser
from rendering import ray_trace
from utils import load_config, parse_resolution
def main():
# default config
config = load_config('config.ini')
# Parse
parser = argparse.ArgumentParser(description="Rendering Program")
parser.add_argument('--algorithm', type=str, help='Algorithm to use', default=config.get('DEFAULT', 'algorithm'))
parser.add_argument('--scene', type=str, help='Path to scene file', default=config.get('DEFAULT', 'scene'))
parser.add_argument('--environment_map', type=str, help='Environment map file', default=config.get('DEFAULT', 'environment_map'))
parser.add_argument('--resolution', type=str, help='Image resolution (WIDTHxHEIGHT)',
default=config.get('DEFAULT', 'resolution'))
parser.add_argument('--num_spheres', type=int, default=3, help='Number of spheres in the scene')
args = parser.parse_args()
width, height = parse_resolution(args.resolution)
# Run the selected algorithm
if args.algorithm == "ray_tracing":
print("Starting ray tracing...")
# ray_trace(args.scene, args.environment_map, image_width=width, image_height=height, output_file="output_ray_traced.png")
ray_trace(args.num_spheres, args.environment_map, image_width=width, image_height=height, # na razie generujemy w kodzie, ale potem trzeba będzie obj wczytywać
output_file="output_ray_traced.png")
else:
print(f"Unknown algorithm: {args.algorithm}")
return
if __name__ == '__main__':
main()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

View File

@ -1,3 +0,0 @@
# Scene directory
This is scene directory. Put .obj files here.

View File

@ -1,130 +0,0 @@
from sightpy import *
# Set Scene
Sc = Scene(ambient_color=rgb(0.00, 0.00, 0.00))
angle = -0
Sc.add_Camera(
screen_width=100,
screen_height=100,
look_from=vec3(278, 278, 800),
look_at=vec3(278, 278, 0),
focal_distance=1.0,
field_of_view=40,
)
# define materials to use
green_diffuse = Diffuse(diff_color=rgb(0.12, 0.45, 0.15))
red_diffuse = Diffuse(diff_color=rgb(0.65, 0.05, 0.05))
white_diffuse = Diffuse(diff_color=rgb(0.73, 0.73, 0.73))
emissive_white = Emissive(color=rgb(15.0, 15.0, 15.0))
emissive_blue = Emissive(color=rgb(2.0, 2.0, 3.5))
blue_glass = Refractive(n=vec3(1.5 + 0.05e-8j, 1.5 + 0.02e-8j, 1.5 + 0.0j))
# this is the light
Sc.add(
Plane(
material=emissive_white,
center=vec3(213 + 130 / 2, 554, -227.0 - 105 / 2),
width=130.0,
height=105.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, 1.0),
),
importance_sampled=True,
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 555 / 2, -555.0),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(1.0, 0, 0.0),
)
)
Sc.add(
Plane(
material=green_diffuse,
center=vec3(-0.0, 555 / 2, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=red_diffuse,
center=vec3(555.0, 555 / 2, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 555, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 0.0, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
cb = Cuboid(
material=white_diffuse,
center=vec3(182.5, 165, -285 - 160 / 2),
width=165,
height=165 * 2,
length=165,
shadow=False,
)
cb.rotate(θ=15, u=vec3(0, 1, 0))
Sc.add(cb)
Sc.add(
Sphere(
material=blue_glass,
center=vec3(370.5, 165 / 2, -65 - 185 / 2),
radius=165 / 2,
shadow=False,
max_ray_depth=3,
),
importance_sampled=True,
)
# Render
img = Sc.render(samples_per_pixel=100, progress_bar=True)
# you are going to need more than 10 samples to remove the noise. At least 1000 for a nice image.
img.save("cornell_box.png")
img.show()

View File

@ -1,11 +1,14 @@
[DEFAULT]
algorithm = ray_tracing
scene = scenes/scene.obj
environment_map = environments/map.hdr
scene = cornell_box
environment = lake.png
env_blur = 0
resolution = 400x300
output = output.png
[ray_tracing]
max_depth = 5 ; Params for ray tracing
samples_per_pixel = 6
[photon_mapping]
photon_count = 100000 ; Params for photon mapping

View File

Before

Width:  |  Height:  |  Size: 2.8 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 614 KiB

After

Width:  |  Height:  |  Size: 614 KiB

61
main.py Normal file
View File

@ -0,0 +1,61 @@
import argparse
from configparser import ConfigParser
from rendering import ray_trace
from utils import load_config, parse_resolution
import importlib
import os
# from scenes.cornell_box import *
def main():
# default config
config = load_config('config.ini')
# Parse
parser = argparse.ArgumentParser(description="Rendering Program")
parser.add_argument('--algorithm', type=str, help='Algorithm to use', default=config.get('DEFAULT', 'algorithm'))
parser.add_argument('--scene', type=str, help='Name of the scene to render (without .py).', default=config.get('DEFAULT', 'scene'))
parser.add_argument('--environment', type=str, help='Environment file', default=config.get('DEFAULT', 'environment'))
parser.add_argument('--env_blur', type=str, help='Environment blur', default=config.get('DEFAULT', 'env_blur'))
parser.add_argument('--resolution', type=str, help='Image resolution (WIDTHxHEIGHT)',
default=config.get('DEFAULT', 'resolution'))
parser.add_argument("--samples_per_pixel", type=int, default=config.get('ray_tracing', 'samples_per_pixel'), help="Samples per pixel for rendering.")
parser.add_argument("--output", type=str, default=config.get('DEFAULT', 'output'), help="Output file name.")
parser.add_argument('--num_spheres', type=int, default=3, help='Number of spheres in the scene for Ray Tracing 0')
args = parser.parse_args()
width, height = parse_resolution(args.resolution)
# Run the selected algorithm
if args.algorithm == "ray_tracing0":
print("Starting ray tracing zero...")
# ray_trace(args.scene, args.environment_map, image_width=width, image_height=height, output_file="output_ray_traced.png")
ray_trace(args.num_spheres, args.environment_map, image_width=width, image_height=height, # na razie generujemy w kodzie, ale potem trzeba będzie obj wczytywać
output_file="output_ray_traced.png")
elif args.algorithm == "ray_tracing":
print("Starting ray tracing...")
try:
print(args.scene)
scene_module = importlib.import_module(f"scenes.{args.scene}")
except ModuleNotFoundError:
print(f"Error: Scene '{args.scene}' not found in the 'scenes' directory.")
return
try:
scene = scene_module.setup_scene(width=width, height=height, environment=f"{args.environment}")
except AttributeError:
print(f"Error: Scene '{args.scene}' does not define a `setup_scene` function.")
return
# Renderowanie
print(f"Rendering scene '{args.scene}' with {args.samples_per_pixel} samples per pixel...")
img = scene.render(samples_per_pixel=args.samples_per_pixel)
output_path = os.path.join("outputs", args.output)
img.save(output_path)
print(f"Image saved to {output_path}")
img.show()
else:
print(f"Unknown algorithm: {args.algorithm}")
return
if __name__ == '__main__':
main()

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

BIN
outputs/output.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

3
scenes/README.md Normal file
View File

@ -0,0 +1,3 @@
# Scene directory
This is scene directory. Put scene files here.

118
scenes/cornell_box.py Normal file
View File

@ -0,0 +1,118 @@
from sightpy import *
# define materials to use
def setup_scene(width=400, height=300, environment=None):
Sc = Scene(ambient_color=rgb(0.00, 0.00, 0.00))
angle = -0
Sc.add_Camera(
screen_width=width,
screen_height=height,
look_from=vec3(278, 278, 800),
look_at=vec3(278, 278, 0),
focal_distance=1.0,
field_of_view=40,
)
# define materials to use
green_diffuse = Diffuse(diff_color=rgb(0.12, 0.45, 0.15))
red_diffuse = Diffuse(diff_color=rgb(0.65, 0.05, 0.05))
white_diffuse = Diffuse(diff_color=rgb(0.73, 0.73, 0.73))
emissive_white = Emissive(color=rgb(15.0, 15.0, 15.0))
emissive_blue = Emissive(color=rgb(2.0, 2.0, 3.5))
blue_glass = Refractive(n=vec3(1.5 + 0.05e-8j, 1.5 + 0.02e-8j, 1.5 + 0.0j))
# this is the light
Sc.add(
Plane(
material=emissive_white,
center=vec3(213 + 130 / 2, 554, -227.0 - 105 / 2),
width=130.0,
height=105.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, 1.0),
),
importance_sampled=True,
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 555 / 2, -555.0),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(1.0, 0, 0.0),
)
)
Sc.add(
Plane(
material=green_diffuse,
center=vec3(-0.0, 555 / 2, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=red_diffuse,
center=vec3(555.0, 555 / 2, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(0.0, 1.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 555, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
Sc.add(
Plane(
material=white_diffuse,
center=vec3(555 / 2, 0.0, -555 / 2),
width=555.0,
height=555.0,
u_axis=vec3(1.0, 0.0, 0),
v_axis=vec3(0.0, 0, -1.0),
)
)
cb = Cuboid(
material=white_diffuse,
center=vec3(182.5, 165, -285 - 160 / 2),
width=165,
height=165 * 2,
length=165,
shadow=False,
)
cb.rotate(θ=15, u=vec3(0, 1, 0))
Sc.add(cb)
Sc.add(
Sphere(
material=blue_glass,
center=vec3(370.5, 165 / 2, -65 - 185 / 2),
radius=165 / 2,
shadow=False,
max_ray_depth=3,
),
importance_sampled=True,
)
return Sc

19
scenes/soap_bubble.py Normal file
View File

@ -0,0 +1,19 @@
from sightpy import *
# define materials to use
def setup_scene(width=400, height=300, environment="lake.png"):
# Set Scene
Sc = Scene(ambient_color=rgb(0.01, 0.01, 0.01))
angle = -np.pi * 0.5
Sc.add_Camera(screen_height=height, screen_width=width,
look_from=vec3(4.0 * np.sin(angle), 0.00, 4.0 * np.cos(angle)),
look_at=vec3(0., 0.05, 0.0))
soap_bubble = ThinFilmInterference(thickness=330, noise=60.)
Sc.add(Sphere(material=soap_bubble, center=vec3(1., 0.0, 1.5), radius=1.7, shadow=False, max_ray_depth=5))
Sc.add_Background(environment, blur=10.)
return Sc

35
scenes/three_spheres.py Normal file
View File

@ -0,0 +1,35 @@
from sightpy import *
# define materials to use
def setup_scene(width=400, height=300, environment="miramar.jpeg"):
blue_glass = Refractive(n=vec3(1.5 + 4e-8j, 1.5 + 4e-8j, 1.5 + 0.j)) # n = index of refraction
green_glass = Refractive(n=vec3(1.5 + 4e-8j, 1.5 + 0.j, 1.5 + 4e-8j))
red_glass = Refractive(n=vec3(1.5 + 0.j, 1.5 + 5e-8j, 1.5 + 5e-8j))
floor = Glossy(diff_color=image("checkered_floor.png", repeat=80.), n=vec3(1.2 + 0.3j, 1.2 + 0.3j, 1.1 + 0.3j),
roughness=0.2, spec_coeff=0.3, diff_coeff=0.9)
# Set Scene
Sc = Scene(ambient_color=rgb(0.05, 0.05, 0.05))
angle = np.pi / 2 * 0.3
Sc.add_Camera(look_from=vec3(2.5 * np.sin(angle), 0.25, 2.5 * np.cos(angle) - 1.5),
look_at=vec3(0., 0.25, -1.5),
screen_width=width,
screen_height=height)
Sc.add_DirectionalLight(Ldir=vec3(0.52, 0.45, -0.5), color=rgb(0.15, 0.15, 0.15))
Sc.add(Sphere(material=blue_glass, center=vec3(-1.2, 0.0, -1.5), radius=.5, shadow=False, max_ray_depth=3))
Sc.add(Sphere(material=green_glass, center=vec3(0., 0.0, -1.5), radius=.5, shadow=False, max_ray_depth=3))
Sc.add(Sphere(material=red_glass, center=vec3(1.2, 0.0, -1.5), radius=.5, shadow=False, max_ray_depth=3))
Sc.add(Plane(material=floor, center=vec3(0, -0.5, -3.0), width=120.0, height=120.0, u_axis=vec3(1.0, 0, 0),
v_axis=vec3(0, 0, -1.0), max_ray_depth=3))
# see sightpy/backgrounds
Sc.add_Background(environment)
return Sc

View File

@ -0,0 +1,27 @@
from sightpy import *
# define materials to use
def setup_scene(width=400, height=300, environment="stormydays.png"):
floor = Glossy(diff_color=image("checkered_floor.png", repeat=2.), roughness=0.2, spec_coeff=0.3, diff_coeff=0.7,
n=vec3(2.2, 2.2, 2.2)) # n = index of refraction
green_glass = Refractive(n=vec3(1.5 + 4e-8j, 1.5 + 0.j, 1.5 + 4e-8j))
Sc = Scene()
Sc.add_Camera(look_from=vec3(0., 0.25, 1.), look_at=vec3(0., 0.25, -3.),
screen_width=width,
screen_height=height)
Sc.add_DirectionalLight(Ldir=vec3(0.0, 0.5, 0.5), color=rgb(0.5, 0.5, 0.5))
Sc.add(Plane(material=floor, center=vec3(0, -0.5, -3.0), width=6.0, height=6.0, u_axis=vec3(1.0, 0, 0),
v_axis=vec3(0, 0, -1.0), max_ray_depth=5))
cb = Cuboid(material=green_glass, center=vec3(0.00, 0.0001, -0.8), width=0.9, height=1.0, length=0.4, shadow=False,
max_ray_depth=5)
cb.rotate(θ=30, u=vec3(0, 1, 0))
Sc.add(cb)
# see sightpy/backgrounds
Sc.add_Background(environment)
return Sc

38
scenes/two_spheres.py Normal file
View File

@ -0,0 +1,38 @@
from sightpy import *
# define materials to use
def setup_scene(width=400, height=300, environment="stormydays.png"):
gold_metal = Glossy(diff_color = rgb(1., .572, .184), n = vec3(0.15+3.58j, 0.4+2.37j, 1.54+1.91j), roughness = 0.0, spec_coeff = 0.2, diff_coeff= 0.8) # n = index of refraction
bluish_metal = Glossy(diff_color = rgb(0.0, 0, 0.1), n = vec3(1.3+1.91j, 1.3+1.91j, 1.4+2.91j), roughness = 0.2,spec_coeff = 0.5, diff_coeff= 0.3)
floor = Glossy(diff_color = image("checkered_floor.png", repeat = 80.),
n = vec3(1.2+ 0.3j, 1.2+ 0.3j, 1.1+ 0.3j), roughness = 0.2, spec_coeff = 0.3, diff_coeff= 0.9 )
# Set Scene
Sc = Scene(ambient_color = rgb(0.05, 0.05, 0.05))
angle = -np.pi/2 * 0.3
Sc.add_Camera(look_from = vec3(2.5*np.sin(angle), 0.25, 2.5*np.cos(angle) -1.5 ),
look_at = vec3(0., 0.25, -3.),
screen_width = width ,
screen_height = height)
Sc.add_DirectionalLight(Ldir = vec3(0.52,0.45, -0.5), color = rgb(0.15, 0.15, 0.15))
Sc.add(Sphere(material = gold_metal, center = vec3(-.75, .1, -3.),radius = .6, max_ray_depth = 3))
Sc.add(Sphere(material = bluish_metal, center = vec3(1.25, .1, -3.), radius = .6, max_ray_depth = 3))
Sc.add(Plane(material = floor, center = vec3(0, -0.5, -3.0), width = 120.0,height = 120.0, u_axis = vec3(1.0, 0, 0), v_axis = vec3(0, 0, -1.0), max_ray_depth = 3))
#see sightpy/backgrounds
Sc.add_Background(environment)
return Sc

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

Before

Width:  |  Height:  |  Size: 666 KiB

After

Width:  |  Height:  |  Size: 666 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -3,9 +3,8 @@ import numpy as np
import time
from .utils import colour_functions as cf
from .camera import Camera
from .utils.constants import *
from .utils.vector3 import vec3, rgb
from .ray import Ray, get_raycolor, get_distances
from .ray import get_raycolor, get_distances
from . import lights
from .backgrounds.skybox import SkyBox
from .backgrounds.panorama import Panorama
@ -31,7 +30,7 @@ class Scene():
self.Light_list += [lights.PointLight(pos, color)]
def add_DirectionalLight(self, Ldir, color):
self.Light_list += [lights.DirectionalLight(Ldir.normalize() , color)]
self.Light_list += [lights.DirectionalLight(Ldir.normalize(), color)]
def add(self,primitive, importance_sampled = False):
self.scene_primitives += [primitive]

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB