rtx_2.py

Created by chick-chicky

Created on April 04, 2023

4.75 KB

basic 3d raytracing


from math import *
from kandinsky import *
from time import monotonic,sleep
class Vec:
  def __init__(self,a,b=None,c=None):
    if type(a)==Vec:self.x=a.x;self.y=a.y;self.z=a.z
    else:self.x=a;self.y=b;self.z=c
  def __add__(self,other):
    if type(other)in(int,float):other=Vec(other,other,other)
    return Vec(self.x+other.x,self.y+other.y,self.z+other.z)
  def __sub__(self,other):
    if type(other)in(int,float):other=Vec(other,other,other)
    return Vec(self.x-other.x,self.y-other.y,self.z-other.z)
  def __mul__(self,other):
    if type(other)in(int,float):other=Vec(other,other,other)
    return Vec(self.x*other.x,self.y*other.y,self.z*other.z)
  def __truediv__(self,other):
    if type(other)in(int,float):other=Vec(other,other,other)
    return Vec(self.x/other.x,self.y/other.y,self.z/other.z)
  def distanceTo(self,other):return (self-Vec(other)).magnitude()
  def magnitude(self):return sqrt(self.x**2+self.y**2+self.z**2)
  def normalize(self):return self.__truediv__(self.magnitude())
  def unit(self):return self.normalize()
  def __index__(self,other):
    if type(other)!=int:raise TypeError('Vector indices must be integers, not '.format(other))
    if other not in range(0,2):raise IndexError('Vector index out of range, expected a value in range(0,2)')
    return[self.x,self.y,self.z][other]
  def __iter__(self):
    for i in (self.x,self.y,self.z):yield i
class Color:
  def __init__(self,a,b=None,c=None,d=1):
    if type(a)==Color:self.r=a.r;self.g=a.g;self.b=a.b;self.a=a.a
    if type(a)==type(b)==type(c)==int and(type(d)==float or type(d)==int):self.r=a;self.g=b;self.b=c;self.a=d
    if type(a)==int and type(b)==type(c)==None:self.r=(a&4278190080)>>24;self.b=(a&16711680)>>16;self.g=(a&65280)>>8;self.a=(a&255)>>0
  def __add__(self,other):
    if type(other)in(float,int):other=Color(other,other,other,1)
    return Color(max(0,min(255,floor(self.r+other.r*other.a))),max(0,min(255,floor(self.g+other.g*other.a))),max(0,min(255,floor(self.b+other.b*other.a))),max(0,min(self.a+other.a,1)))
  def __sub__(self,other):
    if type(other)in(float,int):other=Color(other,other,other,1)
    return Color(max(0,min(255,floor(self.r-other.r*other.a))),max(0,min(255,floor(self.g-other.g*other.a))),max(0,min(255,floor(self.b-other.b*other.a))),max(0,min(self.a+other.a,1)))
  def __mul__(self,other):
    if type(other)in(float,int):other=Color(other,other,other,1)
    return Color(max(0,min(255,floor(self.r*(other.r*other.a)))),max(0,min(255,floor(self.g*(other.g*other.a)))),max(0,min(255,floor(self.b*(other.b*other.a)))),max(0,min(self.a+other.a,1)))
  def __truediv__(self,other):
    if type(other)in(float,int):other=Color(other,other,other,1)
    return Color(max(0,min(255,floor(self.r/(other.r*other.a)))),max(0,min(255,floor(self.g/(other.g*other.a)))),max(0,min(255,floor(self.b/(other.b*other.a)))),max(0,min(self.a+other.a,1)))
  def __int__(self):return self.r<<16&self.g<<8&self.b
  def __index__(self,other):
    if type(other)!=int:raise TypeError('Color indices must be integers, not '.format(other))
    if other not in range(0,2):raise IndexError('Color index out of range, expected a value in range(0,2)')
    return[self.r,self.g,self.b][other]
  def __iter__(self):
    for i in (self.r,self.g,self.b):yield i
class Shape:
  def __init__(self,*a,**kwa):...
  def intersects(self,p):...
  def color(self):...
class Sphere(Shape):
  def __init__(self,pos,radius,color):self.colorValue=Color(color);self.pos=Vec(pos);self.radius=radius
  def intersects(self,p):return (self.pos-p).magnitude()<self.radius
  def color(self):return self.colorValue
camerapos=Vec(0,0,0)
camerasize=5
cameralength=2
resolution=100,100
precision=1
maxrange=10
shapes=[Sphere(Vec(0,0,2),1,Color(255,0,0))]
enable_shadows=False
enable_reflections=True
max_reflections=1
lightpos=Vec(0,5,3)
voidColor=Color(0,0,60)
def calculateColor(source,direction,bouncesLeft):
  ray=Vec(source);i=0
  while i<precision*maxrange:
    ray=ray.__add__(direction.__truediv__(precision))
    for obj in shapes:
      if obj.intersects(ray):
        hit=False;color=Color(obj.color())
        if enable_shadows:
          ld=lightpos.__sub__(ray).unit();rr=Vec(ray);rr+=ld/precision
          while 1:
            rr+=ld/precision
            if lightpos.distanceTo(rr)<1/precision*1.5:break
            dd=False
            for objj in shapes:
              if objj.intersects(rr):hit=True;dd=True
            if dd:break
        if hit:color=Color(color)/4
        return Color(color)
    i=i+1
  return voidColor
s=floor(240/resolution[1])
for px in range(0,resolution[0]):
  for py in range(0,resolution[1]):direction=Vec(camerasize/2-px/resolution[0]*camerasize,camerasize/2-py/resolution[1]*camerasize,cameralength).unit();ray=Vec(camerapos);c=calculateColor(ray,direction,max_reflections);fill_rect(px*s,py*s,s,s,tuple(c))
input()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.