Skip to content

Commit

Permalink
TextureMaterial. Textured triangle example
Browse files Browse the repository at this point in the history
  • Loading branch information
kystyn committed Feb 3, 2021
1 parent 69e4ebc commit 2f11d4b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 12 deletions.
Binary file added examples/16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions examples/16_textured_scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Example 16: Textured raytracing
#
# This time we render a triangle
# TODO render sphere in this scene
from pyrt.light import PointLight
from pyrt.material.texturematerial import TextureMaterial
from pyrt.math import *
from pyrt.scene import *
from pyrt.geometry import Sphere
from pyrt.material import PhongMaterial
from pyrt.camera import PerspectiveCamera
from pyrt.renderer import SimpleRT

from pyrt.renderer import RGBImage
from pyrt.math import Vec2, Vec3
from pyrt.camera import PerspectiveCamera
from pyrt.geometry import Triangle, Vertex
from PIL import Image


w = 320
h = 240

# Create a camera with width, height and field of view:
camera = PerspectiveCamera(w, h, 60)

# Set View matrix of camera: define where to look at
camera.setView(Vec3(0, -10, 0), Vec3(0, 0, 0), Vec3(0, 0, 1))

# Create view-projection matrix (right to left)
vp = camera.projection * camera.view

# Create a scene
scene = Scene()

# Add a light to the scene
scene.addLight(PointLight(Vec3(-1, -8, 1)))

# Create a triangle
t = Triangle(Vertex(position=(-5, 1, 0), texcoord=(0, 0)),
Vertex(position=(0, 1, 5), texcoord=(1, 0)),
Vertex(position=(5, 1, 0), texcoord=(1, 1)),
material=
TextureMaterial(texturepath='tex16.png'))

# Add a sphere to the scene:
scene.add(t)

# Now tell the scene which camera we use
scene.setCamera(camera)

# Create a raytracer using "SimpleRT"
engine = SimpleRT()

# Render the scene:
image = engine.render(scene)


image.save("16.png")
Binary file added examples/tex16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions pyrt/geometry/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
(renderable object)
"""

from abc import abstractmethod
from ..math import Ray, HitRecord, Vec3
from abc import abstractmethod, abstractclassmethod
from ..math import Ray, HitRecord, Vec2, Vec3
import uuid


Expand Down Expand Up @@ -67,7 +67,6 @@ def getSurfaceArea(self) -> float:
return 0



####################
# TODO: MATERIAL
# handle shape material (color, textures, ...)
Expand Down
11 changes: 8 additions & 3 deletions pyrt/material/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from PIL import Image
from numpy import asarray
from ..math import Vec3
from ..math import Vec2, Vec3


class Texture:
Expand All @@ -17,5 +17,10 @@ def __init__(self, path: str):
self._w, self._h = image.size

def color(self, u: float, v: float):
rgb = self._pixels[int(v * self._h)][int(u * self._w)]
return Vec3(rgb[0], rgb[1], rgb[2])
rgb = self._pixels[int(v * self._h) * self._w + int(u * self._w)]
return Vec3(float(rgb[0]) / 255.0, float(rgb[1]) / 255.0, float(rgb[2]) / 255.0)


def color(self, uv: Vec2):
rgb = self._pixels[int(uv.y * self._h) * self._w + int(uv.x * self._w)]
return Vec3(float(rgb[0]) / 255.0, float(rgb[1]) / 255.0, float(rgb[2]) / 255.0)
14 changes: 8 additions & 6 deletions pyrt/material/texturematerial.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ class TextureMaterial(Material):

"""Texture Material Class"""

def __init__(self, color: Vec3 = Vec3(1.,1.,1.), shininess: float = 10.0, reflectivity: float = 0.0, refraction: float = 1.0):
def __init__(self, color: Vec3 = Vec3(1.,1.,1.), shininess: float = 10.0, reflectivity: float = 0.0, refraction: float = 1.0,
texturepath: str = ''):
Material.__init__(self, color, shininess, reflectivity, refraction)
self.texture = None
self.texture = None if len(texturepath) == 0 else Texture(texturepath)

def setTexture(self, texture: Texture):
self.texture = texture
Expand All @@ -28,7 +29,9 @@ def shade(self, camera: Camera, ray: Ray, hitrecord: HitRecord, lights: list) -
"""
colorsum = Vec3(0.,0.,0.)

if len(lights)>0:
texcolor = self.texture.color(hitrecord.texcoord)

if 0: #len(lights) > 0:
for light in lights:
N = hitrecord.normal_g
L = normalize3(hitrecord.point - light.position)
Expand All @@ -37,14 +40,13 @@ def shade(self, camera: Camera, ray: Ray, hitrecord: HitRecord, lights: list) -
diffuse = max(1. - dot3(N, L), 0.0)
specular = pow(max(dot3(R, E), 0.0), 0.3 * self.shininess)

# TODO: just take color from self.texture.color(hitrecord.texcoord.x, hitrecord.texcoord.y)?
color = self.color * 0.5 * (diffuse + specular) * hitrecord.color
color = texcolor * 0.5 * (diffuse + specular) * hitrecord.color
colorsum += color
colorsum /= len(lights)
colorsum = clamp3(colorsum, Vec3(0.,0.,0.), Vec3(1.,1.,1.))
else:
# no light in scene, use material color
colorsum = self.color * hitrecord.color
colorsum = texcolor * hitrecord.color

return colorsum

0 comments on commit 2f11d4b

Please sign in to comment.