본문 바로가기

컴퓨터 그래픽스

[파이썬을 이용한 Ray Tracing 구현] 5. shade와 그림자 생성

마지막으로 shade와 그림자를 생성하는 방법에 대해 작성하겠습니다. 

 

먼저 그림자는 intersect point와 light source 사이에 다른 도형이 있다면 그 픽셀은 빛을 받지 못하므로 그 light source로 얻게되는 밝기를 더해주지 않았습니다. 미리 구현해놓았던 ray trace 함수를 사용하였습니다. 다만 전과 다른 점은 view point 대신 light의 중점을 넣어주었고 ray vector의 방향이 light의 중점에서 intersection point로 나아가는 vector가 되었다는 점입니다. 

 

shader는 phong과 lambertian이 각각 다른 방법을 사용하였습니다. 공통적으로 필요한 정보는 intersection point에서의 normal vector입니다. 구에서의 normal vector는 구의 특징을 활용하여 구의 중점에서 intersection point로 나아가는 vector가 normal vector임을 이용하였습니다. box에서의 normal vector는 axes-aligned box라는 점을 잊고 코드를 작성하여 다소 비효율적으로 구현하게 되었습니다. 모든 평면의 방정식을 구한 후 intersection point를 대입하였을 때 오차가 가장 적은 평면이 intersection point가 존재하는 평면이라고 판단하여 그 평면의 normal vector를 이용하는 방식으로 작성하였습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 for i in light:
            # sum of the reflected light
            l_i = v + i.position - view.viewPoint
            l_i = l_i / np.sqrt(np.sum(l_i * l_i))
            check = raytrace(list, -l_i, i.position)
 
            if check[1== idx:
                if list[idx].s.__class__.__name__ == 'ShaderPhong':
                    v_unit = v / np.sqrt(np.sum(v**2))
                    h = v_unit + l_i
                    h = h / np.sqrt(np.sum(h*h))
                    x = x + list[idx].s.d[0]*max(0,np.dot(n,l_i))*i.intensity[0+ list[idx].s.s[0* i.intensity[0* pow(max(0np.dot(n, h)),list[idx].s.e[0])
                    y = y + list[idx].s.d[1]*max(0,np.dot(n,l_i))*i.intensity[1+ list[idx].s.s[1* i.intensity[1* pow(max(0np.dot(n, h)),list[idx].s.e[0])
                    z = z + list[idx].s.d[2]*max(0,np.dot(n,l_i))*i.intensity[2+ list[idx].s.s[2* i.intensity[2* pow(max(0np.dot(n, h)),list[idx].s.e[0])
 
                elif list[idx].s.__class__.__name__ == "ShaderLambertian":
                    x = x + list[idx].s.d[0* i.intensity[0* max(0np.dot(l_i, n))
                    y = y + list[idx].s.d[1* i.intensity[1* max(0np.dot(l_i, n))
                    z = z + list[idx].s.d[2* i.intensity[2* max(0np.dot(l_i, n))
 

 

위와 같이 각각의 light source에 대해 그 light source가 다른 도형에 가리지 않는지 확인하여 check 변수에 넣어주었고, 가리지 않는다면 각 shader에 맞는 빛의 양을 더해주었습니다. 

 

1
2
rawimg = Image.fromarray(img, 'RGB')
rawimg.save(sys.argv[1+ '.png')

각각의 구해진 색을 img 배열에 저장하여 png로 저장해주었습니다.

 

최종 결과물

여러개의 light source가 주어졌을 때 여러개의 도형을 ray tracing 하여 저장한 최종 결과물입니다. 사용한 코드는 github에 올려두었습니다. 느리고 비효율적인 코드이지만 도움이 필요하신 분은 사용하시기 바랍니다.

 

https://github.com/niley7464/Ray-Tracing

 

niley7464/Ray-Tracing

2019_CSE4020_PA1. Contribute to niley7464/Ray-Tracing development by creating an account on GitHub.

github.com