diff --git a/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.filters b/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.filters index d49ad9c..74c676d 100755 --- a/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.filters +++ b/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.filters @@ -3,7 +3,6 @@ - @@ -12,6 +11,7 @@ stb_image + diff --git a/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.user b/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.user index d7ca222..c80576a 100755 --- a/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.user +++ b/PROJ1_WIN/565Raytracer/565Raytracer.vcxproj.user @@ -1,7 +1,11 @@  - scene="../../scenes/sampleScene.txt" + scene="../../scenes/sampleScene2.txt" frame=29 + WindowsLocalDebugger + + + scene=../../scenes/sampleScene.txt frame=0 WindowsLocalDebugger \ No newline at end of file diff --git a/PROJ1_WIN/565Raytracer/renders/sampleScene.0.bmp b/PROJ1_WIN/565Raytracer/renders/sampleScene.0.bmp new file mode 100755 index 0000000..8d8863e Binary files /dev/null and b/PROJ1_WIN/565Raytracer/renders/sampleScene.0.bmp differ diff --git a/PROJ1_WIN/565Raytracer/renders/sampleScene.0_with_AA.bmp b/PROJ1_WIN/565Raytracer/renders/sampleScene.0_with_AA.bmp new file mode 100755 index 0000000..1e23eb6 Binary files /dev/null and b/PROJ1_WIN/565Raytracer/renders/sampleScene.0_with_AA.bmp differ diff --git a/PROJ1_WIN/565Raytracer/renders/sampleScene.0_without_AA.bmp b/PROJ1_WIN/565Raytracer/renders/sampleScene.0_without_AA.bmp new file mode 100755 index 0000000..e34a0cd Binary files /dev/null and b/PROJ1_WIN/565Raytracer/renders/sampleScene.0_without_AA.bmp differ diff --git a/PROJ1_WIN/565Raytracer/renders/sampleScene.29.bmp b/PROJ1_WIN/565Raytracer/renders/sampleScene.29.bmp new file mode 100755 index 0000000..a47b059 Binary files /dev/null and b/PROJ1_WIN/565Raytracer/renders/sampleScene.29.bmp differ diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 4a65ba6..4e43011 --- a/README.md +++ b/README.md @@ -6,46 +6,18 @@ Fall 2012 Due Sunday, 09/30/2012 ------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -NOTE: -------------------------------------------------------------------------------- -This project requires an NVIDIA graphics card with CUDA capability! Any card after the Geforce 8xxx series will work. If you do not have an NVIDIA graphics card in the machine you are working on, feel free to use any machine in the SIG Lab or in Moore100 labs. All machines in the SIG Lab and Moore100 are equipped with CUDA capable NVIDIA graphics cards. If this too proves to be a problem, please contact Patrick or Karl as soon as possible. - -------------------------------------------------------------------------------- -INTRODUCTION: -------------------------------------------------------------------------------- -In this project, you will implement a CUDA based raytracer capable of generating raytraced rendered images extremely quickly. For those of you who have taken CIS460/560, building a raytracer should not be anything new to you from a conceptual point of you. For those of you that have not taken CIS460/560, raytracing is a technique for generating images by tracing rays of light through pixels in an image plane out into a scene and following the way the rays of light bounce and interact with objects in the scene. More information can be found here: http://en.wikipedia.org/wiki/Ray_tracing_(graphics). - -The ultimate purpose of this project is to serve as the foundation for your next project: a full CUDA based global illumination pathtracer. Raytracing can be thought of as a way to generate an isolated version of the direct light contribution in a global illumination scenario. +BLOG Link: http://seunghoon-cis565.blogspot.com/2012/09/project-1-cuda-raytracer.html -Since in this class we are concerned with working in generating actual images and less so with mundane tasks like file I/O, this project includes basecode for loading a scene description file format, described below, and various other things that generally make up the render "harness" that takes care of everything up to the rendering itself. The core renderer is left for you to implement. -Finally, note that while this basecode is meant to serve as a strong starting point for a CUDA raytracer, you are not required to use this basecode if you wish, and you may also change any part of the basecode specification as you please, so long as the final rendered result is correct. ------------------------------------------------------------------------------- -CONTENTS: +A brief description ------------------------------------------------------------------------------- -The Project1 root directory contains the following subdirectories: - -* src/ contains the source code for the project. Both the Windows Visual Studio solution and the OSX makefile reference this folder for all source; the base source code compiles on OSX and Windows without modification. -* scenes/ contains an example scene description file. -* renders/ contains an example render of the given example scene file. -* PROJ1_WIN/ contains a Windows Visual Studio 2010 project and all dependencies needed for building and running on Windows 7. -* PROJ1_OSX/ contains a OSX makefile, run script, and all dependencies needed for building and running on Mac OSX 10.8. - -The Windows and OSX versions of the project build and run exactly the same way as in Project0. +The goal of this project is to implement a simple RayTracing algorithm by using CUDA. ------------------------------------------------------------------------------- -REQUIREMENTS: +Features ------------------------------------------------------------------------------- -In this project, you are given code for: - -* Loading, reading, and storing the TAKUAscene scene description format -* Example functions that can run on both the CPU and GPU for generating random numbers, spherical intersection testing, and surface point sampling on cubes -* A class for handling image operations and saving images -* Working code for CUDA-GL interop - -You will need to implement the following features: - +- Basic * Raycasting from a camera into a scene through a pixel grid * Phong lighting for one point light source * Diffuse lambertian surfaces @@ -53,122 +25,13 @@ You will need to implement the following features: * Cube intersection testing * Sphere surface point sampling -You are also required to implement at least 2 of the following features: - +- Addtional * Specular reflection -* Soft shadows and area lights -* Texture mapping -* Bump mapping -* Depth of field * Supersampled antialiasing -* Refraction, i.e. glass -* OBJ Mesh loading and renderin -* Interactive camera ------------------------------------------------------------------------------- -BASE CODE TOUR: -------------------------------------------------------------------------------- -You will be working in three files: raytraceKernel.cu, intersections.h, and interactions.h. Within these files, areas that you need to complete are marked with a TODO comment. Areas that are useful to and serve as hints for optional features are marked with TODO (Optional). Functions that are useful for reference are marked with the comment LOOK. - -* raytraceKernel.cu contains the core raytracing CUDA kernel. You will need to complete: - * cudaRaytraceCore() handles kernel launches and memory management; this function already contains example code for launching kernels, transferring geometry and cameras from the host to the device, and transferring image buffers from the host to the device and back. You will have to complete this function to support passing materials and lights to CUDA. - * raycastFromCameraKernel() is a function that you need to implement. This function once correctly implemented should handle camera raycasting. - * raytraceRay() is the core raytracing CUDA kernel; all of your raytracing logic should be implemented in this CUDA kernel. raytraceRay() should take in a camera, image buffer, geometry, materials, and lights, and should trace a ray through the scene and write the resultant color to a pixel in the image buffer. - -* intersections.h contains functions for geometry intersection testing and point generation. You will need to complete: - * boxIntersectionTest(), which takes in a box and a ray and performs an intersection test. This function should work in the same way as sphereIntersectionTest(). - * getRandomPointOnSphere(), which takes in a sphere and returns a random point on the surface of the sphere with an even probability distribution. This function should work in the same way as getRandomPointOnCube(). You can (although do not necessarily have to) use this to generate points on a sphere to use a point lights, or can use this for area lighting. - -* interactions.h contains functions for ray-object interactions that define how rays behave upon hitting materials and objects. You will need to complete: - * getRandomDirectionInSphere(), which generates a random direction in a sphere with a uniform probability. This function works in a fashion similar to that of calculateRandomDirectionInHemisphere(), which generates a random cosine-weighted direction in a hemisphere. - * calculateBSDF(), which takes in an incoming ray, normal, material, and other information, and returns an outgoing ray. You can either implement this function for ray-surface interactions, or you can replace it with your own function(s). - -You will also want to familiarize yourself with: - -* sceneStructs.h, which contains definitions for how geometry, materials, lights, cameras, and animation frames are stored in the renderer. -* utilities.h, which serves as a kitchen-sink of useful functions - -------------------------------------------------------------------------------- -NOTES ON GLM: -------------------------------------------------------------------------------- -This project uses GLM, the GL Math library, for linear algebra. You need to know two important points on how GLM is used in this project: - -* In this project, indices in GLM vectors (such as vec3, vec4), are accessed via swizzling. So, instead of v[0], v.x is used, and instead of v[1], v.y is used, and so on and so forth. -* GLM Matrix operations work fine on NVIDIA Fermi cards and later, but pre-Fermi cards do not play nice with GLM matrices. As such, in this project, GLM matrices are replaced with a custom matrix struct, called a cudaMat4, found in cudaMat4.h. A custom function for multiplying glm::vec4s and cudaMat4s is provided as multiplyMV() in intersections.h. - +How to build ------------------------------------------------------------------------------- -TAKUAscene FORMAT: -------------------------------------------------------------------------------- -This project uses a custom scene description format, called TAKUAscene. TAKUAscene files are flat text files that describe all geometry, materials, lights, cameras, render settings, and animation frames inside of the scene. Items in the format are delimited by new lines, and comments can be added at the end of each line preceded with a double-slash. - -Materials are defined in the following fashion: - -* MATERIAL (material ID) //material header -* RGB (float r) (float g) (float b) //diffuse color -* SPECX (float specx) //specular exponent -* SPECRGB (float r) (float g) (float b) //specular color -* REFL (bool refl) //reflectivity flag, 0 for no, 1 for yes -* REFR (bool refr) //refractivity flag, 0 for no, 1 for yes -* REFRIOR (float ior) //index of refraction for Fresnel effects -* SCATTER (float scatter) //scatter flag, 0 for no, 1 for yes -* ABSCOEFF (float r) (float b) (float g) //absorption coefficient for scattering -* RSCTCOEFF (float rsctcoeff) //reduced scattering coefficient -* EMITTANCE (float emittance) //the emittance of the material. Anything >0 makes the material a light source. - -Cameras are defined in the following fashion: - -* CAMERA //camera header -* RES (float x) (float y) //resolution -* FOVY (float fovy) //vertical field of view half-angle. the horizonal angle is calculated from this and the reslution -* ITERATIONS (float interations) //how many iterations to refine the image, only relevant for supersampled antialiasing, depth of field, area lights, and other distributed raytracing applications -* FILE (string filename) //file to output render to upon completion -* frame (frame number) //start of a frame -* EYE (float x) (float y) (float z) //camera's position in worldspace -* VIEW (float x) (float y) (float z) //camera's view direction -* UP (float x) (float y) (float z) //camera's up vector - -Objects are defined in the following fashion: -* OBJECT (object ID) //object header -* (cube OR sphere OR mesh) //type of object, can be either "cube", "sphere", or "mesh". Note that cubes and spheres are unit sized and centered at the origin. -* material (material ID) //material to assign this object -* frame (frame number) //start of a frame -* TRANS (float transx) (float transy) (float transz) //translation -* ROTAT (float rotationx) (float rotationy) (float rotationz) //rotation -* SCALE (float scalex) (float scaley) (float scalez) //scale - -An example TAKUAscene file setting up two frames inside of a Cornell Box can be found in the scenes/ directory. - -------------------------------------------------------------------------------- -BLOG -------------------------------------------------------------------------------- -As mentioned in class, all students should have student blogs detailing progress on projects. If you already have a blog, you can use it; otherwise, please create a blog using www.blogger.com or any other tool, such as www.wordpress.org. Blog posts on your project are due on the SAME DAY as the project, and should include: - -* A brief description of the project and the specific features you implemented. -* A link to your github repo if the code is open source. -* At least one screenshot of your project running. -* A 30 second or longer video of your project running. To create the video use http://www.microsoft.com/expression/products/Encoder4_Overview.aspx - -------------------------------------------------------------------------------- -THIRD PARTY CODE POLICY -------------------------------------------------------------------------------- -* Use of any third-party code must be approved by asking on Piazza. If it is approved, all students are welcome to use it. Generally, we approve use of third-party code that is not a core part of the project. For example, for the ray tracer, we would approve using a third-party library for loading models, but would not approve copying and pasting a CUDA function for doing refraction. -* Third-party code must be credited in README.md. -* Using third-party code without its approval, including using another student's code, is an academic integrity violation, and will result in you receiving an F for the semester. - -------------------------------------------------------------------------------- -SELF-GRADING -------------------------------------------------------------------------------- -* On the submission date, email your grade, on a scale of 0 to 100, to Karl, yiningli@seas.upenn.edu, with a one paragraph explanation. Be concise and realistic. Recall that we reserve 30 points as a sanity check to adjust your grade. Your actual grade will be (0.7 * your grade) + (0.3 * our grade). We hope to only use this in extreme cases when your grade does not realistically reflect your work - it is either too high or too low. In most cases, we plan to give you the exact grade you suggest. -* Projects are not weighted evenly, e.g., Project 0 doesn't count as much as the path tracer. We will determine the weighting at the end of the semester based on the size of each project. - -------------------------------------------------------------------------------- -SUBMISSION -------------------------------------------------------------------------------- -As with the previous project, you should fork this project and work inside of your fork. Upon completion, commit your finished project back to your fork, and make a pull request to the master repository. -You should include a README.md file in the root directory detailing the following - -* A brief description of the project and specific features you implemented -* At least one screenshot of your project running, and at least one screenshot of the final rendered output of your raytracer -* Instructions for building and running your project if they differ from the base code -* A link to your blog post detailing the project -* A list of all third-party code used \ No newline at end of file +I developed this project on Visual Studio 2010. +Its solution file is located in "PROJ1_WIN/565Raytracer.sln". +You should be able to build it without modification. \ No newline at end of file diff --git a/reference/06raytracing1.pdf b/reference/06raytracing1.pdf new file mode 100755 index 0000000..5972781 Binary files /dev/null and b/reference/06raytracing1.pdf differ diff --git a/reference/09shadingBasics.pdf b/reference/09shadingBasics.pdf new file mode 100755 index 0000000..281ff6b Binary files /dev/null and b/reference/09shadingBasics.pdf differ diff --git a/reference/294-lecture1.ppt b/reference/294-lecture1.ppt new file mode 100755 index 0000000..0a47807 Binary files /dev/null and b/reference/294-lecture1.ppt differ diff --git a/reference/RayTracing.ppt b/reference/RayTracing.ppt new file mode 100755 index 0000000..ec79ec6 Binary files /dev/null and b/reference/RayTracing.ppt differ diff --git a/reference/comp175-13-illumination-gpus-6up.pdf b/reference/comp175-13-illumination-gpus-6up.pdf new file mode 100755 index 0000000..0e11ceb Binary files /dev/null and b/reference/comp175-13-illumination-gpus-6up.pdf differ diff --git a/reference/lecture16_raytracing.ppt b/reference/lecture16_raytracing.ppt new file mode 100755 index 0000000..6ced8c1 Binary files /dev/null and b/reference/lecture16_raytracing.ppt differ diff --git a/renders/debugging.png b/renders/debugging.png new file mode 100755 index 0000000..7bc4192 Binary files /dev/null and b/renders/debugging.png differ diff --git a/scenes/makeFrames.m b/scenes/makeFrames.m new file mode 100644 index 0000000..f736444 --- /dev/null +++ b/scenes/makeFrames.m @@ -0,0 +1,63 @@ +numOfFrames = 30; +numOfControls = 5; +control_frames = round(linspace(1, 30, numOfControls)); + +%% +[control_X, control_Y] = ginput(numOfControls); +[control_Z, dummy] = ginput(numOfControls); + +%% +control_X = rand(numOfControls, 1); +control_Y = rand(numOfControls, 1); +control_Z = rand(numOfControls, 1); + +%% scale +control_X = control_X*4 - 2; +control_Y = control_Y*4; +control_Z = control_Z*3; + +X = interp1(control_frames, control_X, 1:30, 'spline'); +Y = interp1(control_frames, control_Y, 1:30, 'spline'); +Z = interp1(control_frames, control_Z, 1:30, 'spline'); + +plot3(X, Y, Z, '*'); + +%% +for i = 1:numOfFrames + fprintf('frame %d\n', i-1); + fprintf('TRANS %f %f %f\n', X(i), Y(i), Z(i)); + fprintf('ROTAT 0 180 0\n'); + fprintf('SCALE 3 3 3\n'); +end + +%% a fixed camera +for i = 1:numOfFrames + fprintf('frame %d\n', i-1); + fprintf('EYE 0 4.5 12\n'); + fprintf('VIEW 0 0 -1\n'); + fprintf('UP 0 1 0\n'); +end + +%% a fixed object +for i = 1:numOfFrames + fprintf('frame %d\n', i-1); + fprintf('TRANS 0 10 0\n'); + fprintf('ROTAT 0 0 90\n'); + fprintf('SCALE .3 3 3\n'); +end + +%% +addpath('S:\fall2012\CIS565(GPU)\Project1-Raytracer\PROJ1_WIN\Release\renders'); + +writerObj = VideoWriter('video.avi'); +writerObj.FrameRate = 1; + +open(writerObj); + +for n = 1:30 + fname = sprintf('sampleScene.%d.bmp', n-1); + frame = imread(fname); + writeVideo(writerObj, frame); +end + +close(writerObj); \ No newline at end of file diff --git a/scenes/sampleScene.txt b/scenes/sampleScene.txt index 936135b..9186015 100755 --- a/scenes/sampleScene.txt +++ b/scenes/sampleScene.txt @@ -13,7 +13,7 @@ EMITTANCE 0 MATERIAL 1 //red diffuse RGB .63 .06 .04 SPECEX 0 -SPECRGB 1 1 1 +SPECRGB 0 0 0 REFL 0 REFR 0 REFRIOR 0 @@ -25,7 +25,7 @@ EMITTANCE 0 MATERIAL 2 //green diffuse RGB .15 .48 .09 SPECEX 0 -SPECRGB 1 1 1 +SPECRGB 0 0 0 REFL 0 REFR 0 REFRIOR 0 @@ -36,7 +36,7 @@ EMITTANCE 0 MATERIAL 3 //red glossy RGB .63 .06 .04 -SPECEX 0 +SPECEX 50 SPECRGB 1 1 1 REFL 0 REFR 0 @@ -48,7 +48,7 @@ EMITTANCE 0 MATERIAL 4 //white glossy RGB 1 1 1 -SPECEX 0 +SPECEX 50 SPECRGB 1 1 1 REFL 0 REFR 0 @@ -72,7 +72,7 @@ EMITTANCE 0 MATERIAL 6 //green glossy RGB .15 .48 .09 -SPECEX 0 +SPECEX 50 SPECRGB 1 1 1 REFL 0 REFR 0 @@ -109,7 +109,7 @@ EMITTANCE 15 CAMERA RES 800 800 FOVY 25 -ITERATIONS 5000 +ITERATIONS 1 FILE renders/sampleScene.bmp frame 0 EYE 0 4.5 12 @@ -226,4 +226,4 @@ SCALE .3 3 3 frame 1 TRANS 0 10 0 ROTAT 0 0 90 -SCALE .3 3 3 \ No newline at end of file +SCALE .3 3 3 diff --git a/scenes/sampleScene2.txt b/scenes/sampleScene2.txt new file mode 100755 index 0000000..a08fb79 --- /dev/null +++ b/scenes/sampleScene2.txt @@ -0,0 +1,1101 @@ +MATERIAL 0 //white diffuse +RGB 1 1 1 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 1 //red diffuse +RGB .63 .06 .04 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 2 //green diffuse +RGB .15 .48 .09 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 3 //red glossy +RGB .63 .06 .04 +SPECEX 50 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 2 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 4 //white glossy +RGB 1 1 1 +SPECEX 50 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 2 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 5 //glass +RGB 0 0 0 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 1 +REFRIOR 2.2 +SCATTER 0 +ABSCOEFF .02 5.1 5.7 +RSCTCOEFF 13 +EMITTANCE 0 + +MATERIAL 6 //green glossy +RGB .15 .48 .09 +SPECEX 50 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 2.6 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 7 //light +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 1 + +MATERIAL 8 //light +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 15 + +CAMERA +RES 800 800 +FOVY 25 +ITERATIONS 1 +FILE renders/sampleScene.bmp +frame 0 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 1 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 2 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 3 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 4 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 5 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 6 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 7 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 8 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 9 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 10 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 11 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 12 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 13 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 14 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 15 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 16 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 17 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 18 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 19 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 20 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 21 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 22 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 23 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 24 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 25 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 26 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 27 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 28 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 +frame 29 +EYE 0 4.5 12 +VIEW 0 0 -1 +UP 0 1 0 + +OBJECT 0 +cube +material 0 +frame 0 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 1 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 2 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 3 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 4 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 5 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 6 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 7 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 8 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 9 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 10 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 11 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 12 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 13 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 14 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 15 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 16 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 17 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 18 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 19 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 20 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 21 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 22 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 23 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 24 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 25 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 26 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 27 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 28 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 29 +TRANS 0 0 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +OBJECT 1 +cube +material 0 +frame 0 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 2 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 3 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 4 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 5 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 6 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 7 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 8 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 9 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 10 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 11 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 12 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 13 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 14 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 15 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 16 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 17 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 18 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 19 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 20 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 21 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 22 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 23 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 24 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 25 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 26 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 27 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 28 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 +frame 29 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +OBJECT 2 +cube +material 0 +frame 0 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 2 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 3 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 4 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 5 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 6 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 7 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 8 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 9 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 10 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 11 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 12 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 13 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 14 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 15 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 16 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 17 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 18 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 19 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 20 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 21 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 22 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 23 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 24 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 25 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 26 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 27 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 28 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 +frame 29 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +OBJECT 3 +cube +material 1 +frame 0 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 1 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 3 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 4 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 5 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 6 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 7 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 8 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 9 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 10 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 11 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 12 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 13 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 14 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 15 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 16 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 17 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 18 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 19 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 20 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 21 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 22 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 23 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 24 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 25 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 26 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 27 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 28 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 29 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +OBJECT 4 +cube +material 2 +frame 0 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 1 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 2 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 4 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 5 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 6 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 7 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 8 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 9 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 10 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 11 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 12 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 13 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 14 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 15 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 16 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 17 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 18 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 19 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 20 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 21 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 22 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 23 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 24 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 25 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 26 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 27 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 28 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 +frame 29 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +OBJECT 5 +sphere +material 6 +frame 0 +TRANS -0.651509 0.662595 2.244455 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 1 +TRANS -1.291115 1.367890 2.183578 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 2 +TRANS -1.706408 1.886862 2.093015 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 3 +TRANS -1.924048 2.240111 1.977245 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 4 +TRANS -1.970695 2.448241 1.840743 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 5 +TRANS -1.873008 2.531852 1.687988 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 6 +TRANS -1.657647 2.511547 1.523456 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 7 +TRANS -1.351271 2.407928 1.351625 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 8 +TRANS -0.980539 2.241596 1.176971 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 9 +TRANS -0.572112 2.033154 1.003973 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 10 +TRANS -0.152648 1.803203 0.837107 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 11 +TRANS 0.251193 1.572345 0.680851 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 12 +TRANS 0.612752 1.361182 0.539681 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 13 +TRANS 0.905369 1.190317 0.418075 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 14 +TRANS 1.102384 1.080351 0.320510 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 15 +TRANS 1.177138 1.051885 0.251464 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 16 +TRANS 1.112322 1.118966 0.214668 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 17 +TRANS 0.928029 1.269412 0.210869 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 18 +TRANS 0.653699 1.484487 0.240071 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 19 +TRANS 0.318775 1.745452 0.302276 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 20 +TRANS -0.047301 2.033570 0.397486 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 21 +TRANS -0.415087 2.330104 0.525703 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 22 +TRANS -0.755140 2.616316 0.686931 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 23 +TRANS -1.038019 2.873470 0.881171 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 24 +TRANS -1.234281 3.082827 1.108426 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 25 +TRANS -1.314484 3.225650 1.368699 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 26 +TRANS -1.249186 3.283203 1.661992 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 27 +TRANS -1.008946 3.236746 1.988306 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 28 +TRANS -0.564320 3.067544 2.347646 +ROTAT 0 180 0 +SCALE 3 3 3 +frame 29 +TRANS 0.114133 2.756858 2.740012 +ROTAT 0 180 0 +SCALE 3 3 3 + +OBJECT 6 +cube +material 8 +frame 0 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 2 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 3 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 4 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 5 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 6 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 7 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 8 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 9 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 10 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 11 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 12 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 13 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 14 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 15 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 16 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 17 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 18 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 19 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 20 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 21 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 22 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 23 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 24 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 25 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 26 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 27 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 28 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 +frame 29 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .3 3 3 diff --git a/scenes/video1.avi b/scenes/video1.avi new file mode 100755 index 0000000..f8d8712 Binary files /dev/null and b/scenes/video1.avi differ diff --git a/scenes/video1/Thumbs.db b/scenes/video1/Thumbs.db new file mode 100755 index 0000000..8a13f94 Binary files /dev/null and b/scenes/video1/Thumbs.db differ diff --git a/scenes/video1/sampleScene.0.bmp b/scenes/video1/sampleScene.0.bmp new file mode 100755 index 0000000..395de07 Binary files /dev/null and b/scenes/video1/sampleScene.0.bmp differ diff --git a/scenes/video1/sampleScene.1.bmp b/scenes/video1/sampleScene.1.bmp new file mode 100755 index 0000000..1b5d2ee Binary files /dev/null and b/scenes/video1/sampleScene.1.bmp differ diff --git a/scenes/video1/sampleScene.10.bmp b/scenes/video1/sampleScene.10.bmp new file mode 100755 index 0000000..735aaee Binary files /dev/null and b/scenes/video1/sampleScene.10.bmp differ diff --git a/scenes/video1/sampleScene.11.bmp b/scenes/video1/sampleScene.11.bmp new file mode 100755 index 0000000..7358a2b Binary files /dev/null and b/scenes/video1/sampleScene.11.bmp differ diff --git a/scenes/video1/sampleScene.12.bmp b/scenes/video1/sampleScene.12.bmp new file mode 100755 index 0000000..1178707 Binary files /dev/null and b/scenes/video1/sampleScene.12.bmp differ diff --git a/scenes/video1/sampleScene.13.bmp b/scenes/video1/sampleScene.13.bmp new file mode 100755 index 0000000..0081234 Binary files /dev/null and b/scenes/video1/sampleScene.13.bmp differ diff --git a/scenes/video1/sampleScene.14.bmp b/scenes/video1/sampleScene.14.bmp new file mode 100755 index 0000000..48705b5 Binary files /dev/null and b/scenes/video1/sampleScene.14.bmp differ diff --git a/scenes/video1/sampleScene.15.bmp b/scenes/video1/sampleScene.15.bmp new file mode 100755 index 0000000..6cef652 Binary files /dev/null and b/scenes/video1/sampleScene.15.bmp differ diff --git a/scenes/video1/sampleScene.16.bmp b/scenes/video1/sampleScene.16.bmp new file mode 100755 index 0000000..0ccc461 Binary files /dev/null and b/scenes/video1/sampleScene.16.bmp differ diff --git a/scenes/video1/sampleScene.17.bmp b/scenes/video1/sampleScene.17.bmp new file mode 100755 index 0000000..61fa632 Binary files /dev/null and b/scenes/video1/sampleScene.17.bmp differ diff --git a/scenes/video1/sampleScene.18.bmp b/scenes/video1/sampleScene.18.bmp new file mode 100755 index 0000000..0a94567 Binary files /dev/null and b/scenes/video1/sampleScene.18.bmp differ diff --git a/scenes/video1/sampleScene.19.bmp b/scenes/video1/sampleScene.19.bmp new file mode 100755 index 0000000..c25c6e0 Binary files /dev/null and b/scenes/video1/sampleScene.19.bmp differ diff --git a/scenes/video1/sampleScene.2.bmp b/scenes/video1/sampleScene.2.bmp new file mode 100755 index 0000000..1237c34 Binary files /dev/null and b/scenes/video1/sampleScene.2.bmp differ diff --git a/scenes/video1/sampleScene.20.bmp b/scenes/video1/sampleScene.20.bmp new file mode 100755 index 0000000..59a1dc4 Binary files /dev/null and b/scenes/video1/sampleScene.20.bmp differ diff --git a/scenes/video1/sampleScene.21.bmp b/scenes/video1/sampleScene.21.bmp new file mode 100755 index 0000000..f3d9adb Binary files /dev/null and b/scenes/video1/sampleScene.21.bmp differ diff --git a/scenes/video1/sampleScene.22.bmp b/scenes/video1/sampleScene.22.bmp new file mode 100755 index 0000000..a773d8d Binary files /dev/null and b/scenes/video1/sampleScene.22.bmp differ diff --git a/scenes/video1/sampleScene.23.bmp b/scenes/video1/sampleScene.23.bmp new file mode 100755 index 0000000..a60c79c Binary files /dev/null and b/scenes/video1/sampleScene.23.bmp differ diff --git a/scenes/video1/sampleScene.24.bmp b/scenes/video1/sampleScene.24.bmp new file mode 100755 index 0000000..76fbfff Binary files /dev/null and b/scenes/video1/sampleScene.24.bmp differ diff --git a/scenes/video1/sampleScene.25.bmp b/scenes/video1/sampleScene.25.bmp new file mode 100755 index 0000000..268da1d Binary files /dev/null and b/scenes/video1/sampleScene.25.bmp differ diff --git a/scenes/video1/sampleScene.26.bmp b/scenes/video1/sampleScene.26.bmp new file mode 100755 index 0000000..134e4f8 Binary files /dev/null and b/scenes/video1/sampleScene.26.bmp differ diff --git a/scenes/video1/sampleScene.27.bmp b/scenes/video1/sampleScene.27.bmp new file mode 100755 index 0000000..f8159e7 Binary files /dev/null and b/scenes/video1/sampleScene.27.bmp differ diff --git a/scenes/video1/sampleScene.28.bmp b/scenes/video1/sampleScene.28.bmp new file mode 100755 index 0000000..1d94324 Binary files /dev/null and b/scenes/video1/sampleScene.28.bmp differ diff --git a/scenes/video1/sampleScene.29.bmp b/scenes/video1/sampleScene.29.bmp new file mode 100755 index 0000000..7c5fdc6 Binary files /dev/null and b/scenes/video1/sampleScene.29.bmp differ diff --git a/scenes/video1/sampleScene.3.bmp b/scenes/video1/sampleScene.3.bmp new file mode 100755 index 0000000..28d14ba Binary files /dev/null and b/scenes/video1/sampleScene.3.bmp differ diff --git a/scenes/video1/sampleScene.4.bmp b/scenes/video1/sampleScene.4.bmp new file mode 100755 index 0000000..6d97a77 Binary files /dev/null and b/scenes/video1/sampleScene.4.bmp differ diff --git a/scenes/video1/sampleScene.5.bmp b/scenes/video1/sampleScene.5.bmp new file mode 100755 index 0000000..9c32ee0 Binary files /dev/null and b/scenes/video1/sampleScene.5.bmp differ diff --git a/scenes/video1/sampleScene.6.bmp b/scenes/video1/sampleScene.6.bmp new file mode 100755 index 0000000..63086e5 Binary files /dev/null and b/scenes/video1/sampleScene.6.bmp differ diff --git a/scenes/video1/sampleScene.7.bmp b/scenes/video1/sampleScene.7.bmp new file mode 100755 index 0000000..bcd6db3 Binary files /dev/null and b/scenes/video1/sampleScene.7.bmp differ diff --git a/scenes/video1/sampleScene.8.bmp b/scenes/video1/sampleScene.8.bmp new file mode 100755 index 0000000..e0f1c1d Binary files /dev/null and b/scenes/video1/sampleScene.8.bmp differ diff --git a/scenes/video1/sampleScene.9.bmp b/scenes/video1/sampleScene.9.bmp new file mode 100755 index 0000000..6c42cdd Binary files /dev/null and b/scenes/video1/sampleScene.9.bmp differ diff --git a/scenes/video2.avi b/scenes/video2.avi new file mode 100755 index 0000000..c8ea65e Binary files /dev/null and b/scenes/video2.avi differ diff --git a/src/interactions.h b/src/interactions.h index e18cfff..25bc8d1 100755 --- a/src/interactions.h +++ b/src/interactions.h @@ -49,7 +49,7 @@ __host__ __device__ glm::vec3 calculateReflectionDirection(glm::vec3 normal, glm return glm::vec3(0,0,0); } -//TODO (OPTIONAL): IMPLEMENT THIS FUNCTION +//TODO (OPTIONAL): IMPLEMENT THIS FUNCTION67 __host__ __device__ Fresnel calculateFresnel(glm::vec3 normal, glm::vec3 incident, float incidentIOR, float transmittedIOR, glm::vec3 reflectionDirection, glm::vec3 transmissionDirection) { Fresnel fresnel; @@ -90,7 +90,11 @@ __host__ __device__ glm::vec3 calculateRandomDirectionInHemisphere(glm::vec3 nor //Now that you know how cosine weighted direction generation works, try implementing non-cosine (uniform) weighted random direction generation. //This should be much easier than if you had to implement calculateRandomDirectionInHemisphere. __host__ __device__ glm::vec3 getRandomDirectionInSphere(float xi1, float xi2) { - return glm::vec3(0,0,0); + // reference: Slide 7 in http://www.cs.sjsu.edu/~teoh/teaching/previous/cs116b_sp08/lectures/lecture16_raytracing.ppt + float q = TWO_PI * xi1; + float f = acos(2.f*xi2 - 1); + + return glm::normalize(glm::vec3(cos(q)*sin(f), sin(q)*sin(f), cos(f))); } //TODO (PARTIALLY OPTIONAL): IMPLEMENT THIS FUNCTION diff --git a/src/intersections.h b/src/intersections.h index 2d9dcc8..2b37110 100755 --- a/src/intersections.h +++ b/src/intersections.h @@ -12,14 +12,31 @@ #include "utilities.h" #include +#define OBJECT_RADIUS_UNIT 0.5f + +__host__ __device__ void mySwap(float &a, float &b) // mySwap gives me a compilation error +{ + float temp = a; + a = b; + b = temp; +} + + //Some forward declarations __host__ __device__ glm::vec3 getPointOnRay(ray r, float t); __host__ __device__ glm::vec3 multiplyMV(cudaMat4 m, glm::vec4 v); __host__ __device__ glm::vec3 getSignOfRay(ray r); __host__ __device__ glm::vec3 getInverseDirectionOfRay(ray r); __host__ __device__ float boxIntersectionTest(staticGeom sphere, ray r, glm::vec3& intersectionPoint, glm::vec3& normal); +__host__ __device__ bool boxIntersectionTest(staticGeom box, ray r); __host__ __device__ float sphereIntersectionTest(staticGeom sphere, ray r, glm::vec3& intersectionPoint, glm::vec3& normal); +__host__ __device__ bool sphereIntersectionTest(staticGeom sphere, ray r); __host__ __device__ glm::vec3 getRandomPointOnCube(staticGeom cube, float randomSeed); +__host__ __device__ int findClosestIntersection(const staticGeom* geoms, int numOfGeoms, const ray& r, + glm::vec3* closestIntersection, glm::vec3* closestIntersectionNormal, + float* closestDistance); +__host__ __device__ int findClosestIntersection(const staticGeom* geoms, int numOfGeoms, const ray& r); +__host__ __device__ bool isOriginOutsideBox(const glm::vec3& originInObjectSpace); //Handy dandy little hashing function that provides seeds for random number generation __host__ __device__ unsigned int hash(unsigned int a){ @@ -71,23 +88,115 @@ __host__ __device__ glm::vec3 getSignOfRay(ray r){ //TODO: IMPLEMENT THIS FUNCTION //Cube intersection test, return -1 if no intersection, otherwise, distance to intersection __host__ __device__ float boxIntersectionTest(staticGeom box, ray r, glm::vec3& intersectionPoint, glm::vec3& normal){ + float minBound = -OBJECT_RADIUS_UNIT; + float maxBound = OBJECT_RADIUS_UNIT; - return -1; + // transform the ray r to the object-space from the world-space + glm::vec3 ro = multiplyMV(box.inverseTransform, glm::vec4(r.origin, 1.0f)); + glm::vec3 rd = glm::normalize(multiplyMV(box.inverseTransform, glm::vec4(r.direction, 0.0f))); + ray rt; rt.origin = ro; rt.direction = rd; + + //TODO: find different constants for CUDA not for CPU + float t_near = -FLT_MAX; + float t_far = FLT_MAX; + + // YZ plane(X is normal) + if (fabs(rt.direction.x) < EPSILON // rt is parallel to YZ plane + && (rt.origin.x < minBound || rt.origin.x > maxBound)) { + return -1; + } + float dDiv = 1 / rt.direction.x; + float t1 = (minBound - rt.origin.x)*dDiv; + float t2 = (maxBound - rt.origin.x)*dDiv; + if (t1 > t2) mySwap(t1, t2); + if (t1 > t_near) t_near = t1; + if (t2 < t_far) t_far = t2; + if (t_far < EPSILON) return -1; // cube is behind + + // ZX plane(Y is normal) + if (fabs(rt.direction.y) < EPSILON // rt is parallel to ZX plane + && (rt.origin.y < minBound || rt.origin.y > maxBound)) { + return -1; + } + dDiv = 1 / rt.direction.y; + t1 = (minBound - rt.origin.y)*dDiv; + t2 = (maxBound - rt.origin.y)*dDiv; + if (t1 > t2) mySwap(t1, t2); + if (t1 > t_near) t_near = t1; + if (t2 < t_far) t_far = t2; + if (t_near > t_far) return -1; // cube is missed + if (t_far < EPSILON) return -1; // cube is behind + + // XY plane(Z is normal) + if (fabs(rt.direction.z) < EPSILON // rt is parallel to XY plane + && (rt.origin.z < minBound || rt.origin.z > maxBound)) { + return -1; + } + dDiv = 1 / rt.direction.z; + t1 = (minBound - rt.origin.z)*dDiv; + t2 = (maxBound - rt.origin.z)*dDiv; + if (t1 > t2) mySwap(t1, t2); + if (t1 > t_near) t_near = t1; + if (t2 < t_far) t_far = t2; + if (t_near > t_far) return -1; // cube is missed + if (t_far < EPSILON) return -1; // cube is behind + + // compute the final t + float t = t_near; + if (t_near < 0.f) t = t_far; + + // compute the real intersection point + glm::vec3 intersectionPointInObjectSpace = getPointOnRay(rt, t); + intersectionPoint = multiplyMV(box.transform, glm::vec4(intersectionPointInObjectSpace, 1.0f)); + + glm::vec3 normalInObjectSpace; + float xLength = fabs(intersectionPointInObjectSpace.x); + float yLength = fabs(intersectionPointInObjectSpace.y); + float zLength = fabs(intersectionPointInObjectSpace.z); + if (xLength > yLength && xLength > zLength) { + normalInObjectSpace = glm::vec3(-intersectionPointInObjectSpace.x, 0.f, 0.f); + } else if (yLength > xLength && yLength > zLength) { + normalInObjectSpace = glm::vec3(0.f, -intersectionPointInObjectSpace.y, 0.f); + } else if (zLength > xLength && zLength > yLength) { + normalInObjectSpace = glm::vec3(0.f, 0.f, -intersectionPointInObjectSpace.z); + } else if (xLength < yLength && xLength < zLength) { // edges where both y and z are at the miximum bound + normalInObjectSpace = glm::vec3(0.f, -intersectionPointInObjectSpace.y, -intersectionPointInObjectSpace.z); + } else if (yLength < xLength && yLength < zLength) { // edges where both x and z are at the miximum bound + normalInObjectSpace = glm::vec3(-intersectionPointInObjectSpace.x, 0.f, -intersectionPointInObjectSpace.z); + } else if (zLength < xLength && zLength < yLength) { // edges where both x and y are at the miximum bound + normalInObjectSpace = glm::vec3(-intersectionPointInObjectSpace.x, -intersectionPointInObjectSpace.y, 0.f); + } else { + normalInObjectSpace = -intersectionPointInObjectSpace; + } + + if (isOriginOutsideBox(rt.origin)) { + normalInObjectSpace = -normalInObjectSpace; + } + + // don't forget to transform normal in object space to real-world space + normal = glm::normalize(multiplyMV(box.transform, glm::vec4(normalInObjectSpace, 0.f))); + return glm::length(r.origin - intersectionPoint); +} + +__host__ __device__ bool boxIntersectionTest(staticGeom box, ray r) { + glm::vec3 vec3Dummy1, vec3Dummy2; + float intersectionDistance = + boxIntersectionTest(box, r, vec3Dummy1, vec3Dummy2); + + return (intersectionDistance > EPSILON); } //LOOK: Here's an intersection test example from a sphere. Now you just need to figure out cube and, optionally, triangle. //Sphere intersection test, return -1 if no intersection, otherwise, distance to intersection __host__ __device__ float sphereIntersectionTest(staticGeom sphere, ray r, glm::vec3& intersectionPoint, glm::vec3& normal){ - float radius = .5; - glm::vec3 ro = multiplyMV(sphere.inverseTransform, glm::vec4(r.origin,1.0f)); glm::vec3 rd = glm::normalize(multiplyMV(sphere.inverseTransform, glm::vec4(r.direction,0.0f))); ray rt; rt.origin = ro; rt.direction = rd; float vDotDirection = glm::dot(rt.origin, rt.direction); - float radicand = vDotDirection * vDotDirection - (glm::dot(rt.origin, rt.origin) - pow(radius, 2)); + float radicand = vDotDirection * vDotDirection - (glm::dot(rt.origin, rt.origin) - pow(OBJECT_RADIUS_UNIT, 2)); if (radicand < 0){ return -1; } @@ -115,6 +224,14 @@ __host__ __device__ float sphereIntersectionTest(staticGeom sphere, ray r, glm: return glm::length(r.origin - realIntersectionPoint); } +__host__ __device__ bool sphereIntersectionTest(staticGeom sphere, ray r) { + glm::vec3 vec3Dummy1, vec3Dummy2; + float intersectionDistance = + sphereIntersectionTest(sphere, r, vec3Dummy1, vec3Dummy2); + + return (intersectionDistance > EPSILON); +} + //returns x,y,z half-dimensions of tightest bounding box __host__ __device__ glm::vec3 getRadiuses(staticGeom geom){ glm::vec3 origin = multiplyMV(geom.transform, glm::vec4(0,0,0,1)); @@ -180,4 +297,57 @@ __host__ __device__ glm::vec3 getRandomPointOnSphere(staticGeom sphere, float ra return glm::vec3(0,0,0); } +__host__ __device__ int findClosestIntersection(const staticGeom* geoms, int numOfGeoms, const ray& r, + glm::vec3* closestIntersection, glm::vec3* closestIntersectionNormal, + float* closestDistance) { +// if the front closest geom is found, the index of it is returned +// otherwise, returns -1 + glm::vec3 intersectionPoint, normal; + float intersectionDistance; + *closestDistance = FLT_MAX; + int closestGeomInd = -1; + + for (int i = 0; i < numOfGeoms; i++) { // for each object + if (geoms[i].type == SPHERE) { + intersectionDistance = sphereIntersectionTest(geoms[i], r, intersectionPoint, normal); + } else if (geoms[i].type == CUBE) { + intersectionDistance = boxIntersectionTest(geoms[i], r, intersectionPoint, normal); + } else { // not-supported object type + continue; + } + + if (intersectionDistance < EPSILON) { // object is missed + continue; + } else if (intersectionDistance < *closestDistance) { // closer is found + *closestDistance = intersectionDistance; + *closestIntersection = intersectionPoint; + *closestIntersectionNormal = normal; + closestGeomInd = i; + } + } + + return closestGeomInd; +} + +__host__ __device__ int findClosestIntersection(const staticGeom* geoms, int numOfGeoms, const ray& r) { +// if the front closest geom is found, the index of it is returned +// otherwise, returns -1 + glm::vec3 vec3Dummy1, vec3Dummy2; + float floatDummy; + return findClosestIntersection(geoms, numOfGeoms, r, &vec3Dummy1, &vec3Dummy2, &floatDummy); +} + +__host__ __device__ bool isOriginOutsideBox(const glm::vec3& originInObjectSpace) { + // if the origin is inside of the box, return true. + // otherwise, return false. + + float x = originInObjectSpace.x; + float y = originInObjectSpace.y; + float z = originInObjectSpace.z; + + return !(x < OBJECT_RADIUS_UNIT && x > -OBJECT_RADIUS_UNIT + && y < OBJECT_RADIUS_UNIT && y > -OBJECT_RADIUS_UNIT + && z < OBJECT_RADIUS_UNIT && z > -OBJECT_RADIUS_UNIT); +} + #endif \ No newline at end of file diff --git a/src/raytraceKernel.cu b/src/raytraceKernel.cu index dae7b03..51551f5 100755 --- a/src/raytraceKernel.cu +++ b/src/raytraceKernel.cu @@ -15,7 +15,11 @@ #include "raytraceKernel.h" #include "intersections.h" #include "interactions.h" -#include +#include "glm/gtx/vector_access.hpp" + +// 2x2 rays will be generated for each pixel, this is assumed to be even number +// Special case: 1 means Anti-Aliasing is disabled. +#define SUPER_SAMPLE_GRID_SIZE 2 void checkCUDAError(const char *msg) { cudaError_t err = cudaGetLastError(); @@ -40,11 +44,45 @@ __host__ __device__ glm::vec3 generateRandomNumberFromThread(glm::vec2 resolutio //Function that does the initial raycast from the camera __host__ __device__ ray raycastFromCameraKernel(glm::vec2 resolution, float time, int x, int y, glm::vec3 eye, glm::vec3 view, glm::vec3 up, glm::vec2 fov){ ray r; - r.origin = glm::vec3(0,0,0); - r.direction = glm::vec3(0,0,-1); + r.origin = eye; + + glm::vec3 right = glm::normalize(glm::cross(view, up)); + //TODO: use glm::tan and glm::radians + float d = 0.5f * resolution.y / tan(fov.y*(PI/180.f)); // distance from the eye to the image plane + r.direction = glm::normalize(view*d + right*(x - 0.5f*resolution.x) + up*(0.5f*resolution.y - y)); return r; } +//Function that does the initial raycast from the camera +__host__ __device__ void superSampleRays(ray rays[], const glm::vec2& resolution, float time, int x, int y, + const glm::vec3& eye, const glm::vec3& view, const glm::vec3& up, const glm::vec2& fov){ + + glm::vec3 right = glm::normalize(glm::cross(view, up)); + float d = 0.5f * resolution.y / tan(fov.y*(PI/180.f)); // distance from the eye to the image plane + glm::vec3 viewTimesD = view*d; + glm::vec3 rightTimesHalfWidth = right*0.5f*resolution.x; + glm::vec3 upTimesHalfHeight = up*0.5f*resolution.y; + + float sampleStep = 1.f / SUPER_SAMPLE_GRID_SIZE; + + float subX = x - ((SUPER_SAMPLE_GRID_SIZE+1)/2.f)*sampleStep; + float subY = 0.f; + int ind = 0; + for (int i = 0; i < SUPER_SAMPLE_GRID_SIZE; i++) { + subX += sampleStep; + subY = y - ((SUPER_SAMPLE_GRID_SIZE+1)/2.f)*sampleStep; + for (int j = 0; j < SUPER_SAMPLE_GRID_SIZE; j++) { + subY += sampleStep; + + ind = i*SUPER_SAMPLE_GRID_SIZE + j; + rays[ind].origin = eye; + rays[ind].direction = glm::normalize(viewTimesD + right*subX - rightTimesHalfWidth + upTimesHalfHeight - up*subY); + } + } + + return; +} + //Kernel that blacks out a given image buffer __global__ void clearImage(glm::vec2 resolution, glm::vec3* image){ int x = (blockIdx.x * blockDim.x) + threadIdx.x; @@ -66,8 +104,8 @@ __global__ void sendImageToPBO(uchar4* PBOpos, glm::vec2 resolution, glm::vec3* glm::vec3 color; color.x = image[index].x*255.0; - color.y = image[index].x*255.0; - color.z = image[index].x*255.0; + color.y = image[index].y*255.0; + color.z = image[index].z*255.0; if(color.x>255){ color.x = 255; @@ -92,16 +130,91 @@ __global__ void sendImageToPBO(uchar4* PBOpos, glm::vec2 resolution, glm::vec3* //TODO: IMPLEMENT THIS FUNCTION //Core raytracer kernel __global__ void raytraceRay(glm::vec2 resolution, float time, cameraData cam, int rayDepth, glm::vec3* colors, - staticGeom* geoms, int numberOfGeoms){ + staticGeom* geoms, int numberOfGeoms, + const material* materials, int numOfMaterials, + const int* lightIndices, int numOfLights){ + int x = (blockIdx.x * blockDim.x) + threadIdx.x; + int y = (blockIdx.y * blockDim.y) + threadIdx.y; + int index = x + (y * resolution.x); - int x = (blockIdx.x * blockDim.x) + threadIdx.x; - int y = (blockIdx.y * blockDim.y) + threadIdx.y; - int index = x + (y * resolution.x); + if((x<=resolution.x && y<=resolution.y)){ + // colors[index] = generateRandomNumberFromThread(resolution, time, x, y); + glm::set(colors[index], 0.f, 0.f, 0.f); + + // super-sample rays for pixel (x, y) + const int numOfSuperSamples = SUPER_SAMPLE_GRID_SIZE*SUPER_SAMPLE_GRID_SIZE; + ray superSampledRays[numOfSuperSamples]; + if (numOfSuperSamples > 1) { + superSampleRays(superSampledRays, resolution, time, x, y, cam.position, cam.view, cam.up, cam.fov); + } else {// Anti-Aliasing is disabled. + superSampledRays[0] = raycastFromCameraKernel(resolution, time, x, y, cam.position, cam.view, cam.up, cam.fov); + } + + glm::vec3 sampledColor(0.f, 0.f, 0.f); + glm::vec3 sumOfSampledColors(0.f, 0.f, 0.f); - if((x<=resolution.x && y<=resolution.y)){ + for (int n = 0; n < numOfSuperSamples; n++) { + const ray& r = superSampledRays[n]; + glm::set(sampledColor, 0.f, 0.f, 0.f); + + glm::vec3 intersectionPoint, normal; + float intersectionDistance; + int intersectionGeomInd = findClosestIntersection(geoms, numberOfGeoms, r, + &intersectionPoint, &normal, &intersectionDistance); - colors[index] = generateRandomNumberFromThread(resolution, time, x, y); - } + if (intersectionGeomInd != -1) { // found the closest front object + const material& objectMaterial = materials[geoms[intersectionGeomInd].materialid]; + glm::vec3 diffuseColor = objectMaterial.color; + glm::vec3 specularColor = objectMaterial.specularColor; + + if (objectMaterial.emittance > EPSILON) { + // object to be rendered is a light source + sumOfSampledColors += diffuseColor; + continue; + } + + /* Phong Illumination Model */ + /* ka*diffuse_color + kd*diffuse_color*(N*L) + ks*specular_color*(N*H)^exp_n + * N(normal) : unit vector, the direction of the surface normal at the intersection + * L(ligtDirection) : unit vector, the direction of the vector to the light source from the intersection + * H : unit vector, the direction that is halfway between the direction to the light and the direction to the viewer */ + glm::vec3 diffuse_sum(0.f, 0.f, 0.f); + glm::vec3 specular_sum(0.f, 0.f, 0.f); + for (int i = 0; i < numOfLights; i++) { // for each light source + int lightInd = lightIndices[i]; + const staticGeom& light = geoms[lightInd]; + glm::vec3 lightCenter = multiplyMV(light.transform, glm::vec4(0.f, 0.f, 0.f, 1.0f)); + glm::vec3 lightDirection = glm::normalize(lightCenter - intersectionPoint); + + // check occulusion for shadow + // NOTE: move the intersection point toward each light a little bit to avoid numerical error + ray lightRay; lightRay.origin = intersectionPoint + lightDirection*float(RAY_BIAS_AMOUNT); lightRay.direction = lightDirection; + int obstacleGeomInd = findClosestIntersection(geoms, numberOfGeoms, lightRay); + if (obstacleGeomInd != lightInd) { + continue; + } + + glm::vec3 V = glm::normalize(-r.direction); + glm::vec3 H = glm::normalize(lightDirection + V); + + const material& lightMaterial = materials[light.materialid]; + glm::vec3 lightColor = lightMaterial.color; + diffuse_sum += lightColor * max(0.f, glm::dot(normal, lightDirection)); + + if (glm::dot(normal, H) > EPSILON) { + specular_sum += lightColor * (glm::pow(glm::dot(normal, H), objectMaterial.specularExponent)); + } + } + + sampledColor = glm::clamp(0.2f*diffuseColor + diffuseColor*diffuse_sum + specularColor*specular_sum, 0.f, 1.f); + } + + sumOfSampledColors += sampledColor; + } // for each sub-pixel + + // compute the naive average(filter would be applied though.) + colors[index] = sumOfSampledColors * (1.f/numOfSuperSamples); + } } @@ -121,8 +234,10 @@ void cudaRaytraceCore(uchar4* PBOpos, camera* renderCam, int frame, int iteratio cudaMalloc((void**)&cudaimage, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(glm::vec3)); cudaMemcpy( cudaimage, renderCam->image, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(glm::vec3), cudaMemcpyHostToDevice); - //package geometry and materials and sent to GPU + //package geometry and indices for lights and send them to GPU staticGeom* geomList = new staticGeom[numberOfGeoms]; + int* lightIndices = new int[numberOfGeoms]; + int numOfLights = 0; for(int i=0; i EPSILON) { + lightIndices[numOfLights++] = i; + } } staticGeom* cudageoms = NULL; cudaMalloc((void**)&cudageoms, numberOfGeoms*sizeof(staticGeom)); cudaMemcpy( cudageoms, geomList, numberOfGeoms*sizeof(staticGeom), cudaMemcpyHostToDevice); + int* cudaLightIndices = NULL; + cudaMalloc((void**)&cudaLightIndices, numOfLights*sizeof(int)); + cudaMemcpy( cudaLightIndices, lightIndices, numOfLights*sizeof(int), cudaMemcpyHostToDevice); + + // package materials and send to GPU + material* cudaMaterials = NULL; + cudaMalloc((void**)&cudaMaterials, numberOfMaterials*sizeof(material)); + cudaMemcpy(cudaMaterials, materials, numberOfMaterials*sizeof(material), cudaMemcpyHostToDevice); + //package camera cameraData cam; cam.resolution = renderCam->resolution; @@ -148,7 +276,8 @@ void cudaRaytraceCore(uchar4* PBOpos, camera* renderCam, int frame, int iteratio cam.fov = renderCam->fov; //kernel launches - raytraceRay<<>>(renderCam->resolution, (float)iterations, cam, traceDepth, cudaimage, cudageoms, numberOfGeoms); + raytraceRay<<>>(renderCam->resolution, (float)iterations, cam, traceDepth, cudaimage, + cudageoms, numberOfGeoms, cudaMaterials, numberOfMaterials, cudaLightIndices, numOfLights); sendImageToPBO<<>>(PBOpos, renderCam->resolution, cudaimage); @@ -158,7 +287,10 @@ void cudaRaytraceCore(uchar4* PBOpos, camera* renderCam, int frame, int iteratio //free up stuff, or else we'll leak memory like a madman cudaFree( cudaimage ); cudaFree( cudageoms ); + cudaFree( cudaMaterials ); + cudaFree( cudaLightIndices ); delete geomList; + delete lightIndices; // make certain the kernel has completed cudaThreadSynchronize(); diff --git a/src/utilities.h b/src/utilities.h index cb0e89d..45ad9e8 100755 --- a/src/utilities.h +++ b/src/utilities.h @@ -23,7 +23,7 @@ #define E 2.7182818284590452353602874713526624977572 #define EPSILON .000000001 #define ZERO_ABSORPTION_EPSILON 0.00001 -#define RAY_BIAS_AMOUNT 0.0002 +#define RAY_BIAS_AMOUNT 0.00001 namespace utilityCore { extern float clamp(float f, float min, float max);