diff --git a/README.md b/README.md index c2504ab..f6d4674 100644 --- a/README.md +++ b/README.md @@ -3,56 +3,101 @@ CUDA Path Tracer **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 3** -* (TODO) YOUR NAME HERE -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +* Ziwei Zong +* Tested on: Windows 10, i7-5500 @ 2.40GHz 8GB, GTX 950M (Personal) -### (TODO: Your README) +Description +======================== +-------------------------- +## Overview -*DO NOT* leave the README to the last minute! It is a crucial part of the -project, and we will not be able to grade you without a good README. +This GPU based path tracer with global illumination and anti-alising can render diffuse, perfect/non-perfect specular, transparent and subsurface scattering materials with textures. Shown as the picture below. -Instructions (delete me) -======================== +![](img/01Overview.jpg) +-------------------------- +## Features + +### Materials + +Below are material types that this path tracer supports: + * **Diffuse** + * **Specular** + * Perfect Specular (Mirrors) + * Non-perfect Reflection + * **Transparent (with fresnel reflection)** + * **Subsurface Scattering** + * Diffuse Subsurface + * Subsurface with reflection + + ![alt tag](img/04DiffSpecTrans.png "scene file: \scenes\DiffSpecTrans.txt") + +#### Subsurface Scattering +![](img/05SSS.png) + +Subsurface scattering is implemented based on Yining Karl Li's [Slides](https://github.com/CIS565-Fall-2015/cis565-fall-2015.github.io/raw/master/lectures/4.1-Path-Tracing-1.pdf). +And [BSSRDF Explorer: A rendering framework for the BSSRDF](http://noobody.org/bachelor-thesis.pdf) + + Subsurface Scattering | Compare with diffuse +:----------------------:|:-------------------------: +![](img/05SSS02.png) |![](img/05SSS01.png) + +### Texture Mapping +![](img/06TexMap.png) + +Cube Texture Mapping Test |Sphere Texture Mapping test +:------------------------:|:---------------------------: +![](img/06TexMap_cube.png)|![](img/06TexMap_sphere.png) + +### Global Illumination + +For rays that reached the camera depth, check the intersection point if it is directly shined by any lights. +Global Illumination helps rendering more realistic pictures. -This is **NOW** due ~~Thursday, September 24~~ **Tuesday, September 29** evening at midnight. +With Direct Lighting | Without Direct Lighting +:----------------------:|:-------------------------: +![](img/02Gobal_on.png)|![](img/02Gobal_off.png) -**Summary:** -In this project, you'll implement a CUDA-based path tracer capable of rendering -globally-illuminated images very quickly. -Since in this class we are concerned with working in GPU programming, -performance, and the generation of actual beautiful images (and not with -mundane programming tasks like I/O), this project includes base code for -loading a scene description file, described below, and various other things -that generally make up a framework for previewing and saving images. +#### Anti-aliasing -The core renderer is left for you to implement. Finally, note that, while this -base code is meant to serve as a strong starting point for a CUDA path tracer, -you are not required to use it if you don't want to. You may also change any -part of the base code as you please. **This is YOUR project.** +Choose a random direction inside each pixel to smooth edges while iterating. -**Recommendation:** Every image you save should automatically get a different -filename. Don't delete all of them! For the benefit of your README, keep a -bunch of them around so you can pick a few to document your progress at the -end. +With Anti-Aliasing |Without Anti-Aliasing +:----------------------:|:------------------: +![](img/03AntiA_on.PNG) |![](img/03AntiA_off.png) -### Contents +### Work-efficient Stream Compaction with Shared Memory -* `src/` C++/CUDA source files. -* `scenes/` Example scene description files. -* `img/` Renders of example scene description files. - (These probably won't match precisely with yours.) -* `external/` Includes and static libraries for 3rd party libraries. +For below's screenshot, it is an open scene with camera's depth 8, resolution 800*800. +The number of rays reduces from 640000 to 97004 after 8 depth's bouncing. +![](img/Analysis/SharedMem.PNG) -### Running the code +-------------------------- +## Analysis +**Open vs Closed scenes** -The main function requires a scene description file. Call the program with -one as an argument: `cis565_path_tracer scenes/sphere.txt`. -(In Visual Studio, `../scenes/sphere.txt`.) +In an open scene, many rays interact with nothing after several bounces. +Thus using stream compaction can optimize the render process when depth is larger than a certain value. + +![](img/Analysis/OpenScene.png) -If you are using Visual Studio, you can set this in the Debugging > Command -Arguments section in the Project properties. Make sure you get the path right - -read the console for errors. +However, when the scene is closed, only very small amount of rays get terminated even if there are a great amount of bounces. +For this condition, the advantages of reducing ray numbers by sream compaction cannot trade off the calculation and memory accessing time. +Therefore, as expected, stream compaction performs poor for closed scenes. + +![](img/Analysis/CloseScene.png) + +-------------------------- +## Appendix +#### Command line + + <%s> | <"s"> + scene file path |(with/without) turn on/off stream compaction + +* example: + + ../cornell.txt s //with stream compaction + ../cornell_closed.txt //without stream compaction #### Controls @@ -60,254 +105,36 @@ read the console for errors. * Space to save an image. Watch the console for the output filename. * W/A/S/D and R/F move the camera. Arrow keys rotate. -## Requirements - -**Ask on the mailing list for clarifications.** - -In this project, you are given code for: - -* Loading and reading the scene description format -* Sphere and box intersection functions -* Support for saving images -* Working CUDA-GL interop for previewing your render while it's running -* A function which generates random screen noise (instead of an actual render). - -You will need to implement the following features: - -* Raycasting from the camera into the scene through an imaginary grid of pixels - (the screen). - * Implement simple antialiasing (by jittering rays within each pixel). -* Diffuse surfaces (using provided cosine-weighted scatter function) [PBRT 8.3]. -* Perfectly specular-reflective (mirrored) surfaces. - * See notes on diffuse/specular in `scatterRay` and on imperfect specular below. -* Stream compaction optimization, using: -* **NEWLY ADDED:** Work-efficient stream compaction using shared memory across - multiple blocks. (See - [*GPU Gems 3*, Chapter 39](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html).) - -You are also required to implement at least 2 of the following features. -If you find other good references for these features, share them! -**Extra credit**: implement more features on top of the 2 required ones, -with point value up to +20/100 at the grader's discretion -(based on difficulty and coolness). - -* **NOW REQUIRED - NOT AN EXTRA:** ~~Work-efficient stream compaction (see above).~~ -* These 2 smaller features: - * Refraction (e.g. glass/water) [PBRT 8.2] with Frensel effects using - [Schlick's approximation](https://en.wikipedia.org/wiki/Schlick's_approximation) - or more accurate methods [PBRT 8.5]. - * Physically-based depth-of-field (by jittering rays within an aperture) - [PBRT 6.2.3]. - * Recommended but not required: non-perfect specular surfaces. (See below.) -* Texture mapping [PBRT 10.4]. -* Bump mapping [PBRT 9.3]. -* Direct lighting (by taking a final ray directly to a random point on an - emissive object acting as a light source). Or more advanced [PBRT 15.1.1]. -* Some method of defining object motion, and motion blur by averaging samples - at different times in the animation. -* Subsurface scattering [PBRT 5.6.2, 11.6]. -* Arbitrary mesh loading and rendering (e.g. `obj` files). You can find these - online or export them from your favorite 3D modeling application. - With approval, you may use a third-party OBJ loading code to bring the data - into C++. - * You can use the triangle intersection function `glm::intersectRayTriangle`. - -This 'extra features' list is not comprehensive. If you have a particular idea -you would like to implement (e.g. acceleration structures, etc.), please -contact us first. - -For each extra feature, you must provide the following analysis: - -* Overview write-up of the feature -* Performance impact of the feature -* If you did something to accelerate the feature, what did you do and why? -* Compare your GPU version of the feature to a HYPOTHETICAL CPU version - (you don't have to implement it!) Does it benefit or suffer from being - implemented on the GPU? -* How might this feature be optimized beyond your current implementation? - -## Base Code Tour - -You'll be working in the following files. Look for important parts of the code: -search for `CHECKITOUT`. You'll have to implement parts labeled with `TODO`. -(But don't let these constrain you - you have free rein!) - -* `src/pathtrace.cu`: path tracing kernels, device functions, and calling code - * `pathtraceInit` initializes the path tracer state - it should copy - scene data (e.g. geometry, materials) from `Scene`. - * `pathtraceFree` frees memory allocated by `pathtraceInit` - * `pathtrace` performs one iteration of the rendering - it handles kernel - launches, memory copies, transferring some data, etc. - * See comments for a low-level path tracing recap. -* `src/intersections.h`: ray intersection functions - * `boxIntersectionTest` and `sphereIntersectionTest`, which take in a ray and - a geometry object and return various properties of the intersection. -* `src/interactions.h`: ray scattering functions - * `calculateRandomDirectionInHemisphere`: a cosine-weighted random direction - in a hemisphere. Needed for implementing diffuse surfaces. - * `scatterRay`: this function should perform all ray scattering, and will - call `calculateRandomDirectionInHemisphere`. See comments for details. -* `src/main.cpp`: you don't need to do anything here, but you can change the - program to save `.hdr` image files, if you want (for postprocessing). - -### Generating random numbers - -``` -thrust::default_random_engine rng(hash(index)); -thrust::uniform_real_distribution u01(0, 1); -float result = u01(rng); -``` - -There is a convenience function for generating a random engine using a -combination of index, iteration, and depth as the seed: - -``` -thrust::default_random_engine rng = random_engine(iter, index, depth); -``` - -### Imperfect specular lighting - -In path tracing, like diffuse materials, specular materials are -simulated using a probability distribution instead computing the -strength of a ray bounce based on angles. - -Equations 7, 8, and 9 of -[*GPU Gems 3*, Chapter 20](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html) -give the formulas for generating a random specular ray. (Note that -there is a typographical error: χ in the text = ξ in the formulas.) - -Also see the notes in `scatterRay` for probability splits between -diffuse/specular/other material types. - -See also: PBRT 8.2.2. - -### Handling Long-Running CUDA Threads - -By default, your GPU driver will probably kill a CUDA kernel if it runs for more than 5 seconds. There's a way to disable this timeout. Just beware of infinite loops - they may lock up your computer. - -> The easiest way to disable TDR for Cuda programming, assuming you have the NVIDIA Nsight tools installed, is to open the Nsight Monitor, click on "Nsight Monitor options", and under "General" set "WDDM TDR enabled" to false. This will change the registry setting for you. Close and reboot. Any change to the TDR registry setting won't take effect until you reboot. [Stack Overflow](http://stackoverflow.com/questions/497685/cuda-apps-time-out-fail-after-several-seconds-how-to-work-around-this) - -### Notes on GLM - -This project uses GLM for linear algebra. - -On NVIDIA cards pre-Fermi (pre-DX12), you may have issues with mat4-vec4 -multiplication. If you have one of these cards, be careful! If you have issues, -you might need to grab `cudamat4` and `multiplyMV` from the -[Fall 2014 project](https://github.com/CIS565-Fall-2014/Project3-Pathtracer). -Let us know if you need to do this. - -### Scene File Format +#### Scene File This project uses a custom scene description format. Scene files are flat text -files that describe all geometry, materials, lights, cameras, and render -settings inside of the scene. Items in the format are delimited by new lines, -and comments can be added using C-style `// comments`. +files that describe all geometry, materials, lights, cameras, textures and render +settings inside of the scene. 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 +* 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 -* EMITTANCE (float emittance) //the emittance strength of the material. Material is a light source iff emittance > 0. - -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 -* DEPTH (int depth) //maximum depth (number of times the path will bounce) -* FILE (string filename) //file to output render to upon completion -* 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 -* TRANS (float transx) (float transy) (float transz) //translation -* ROTAT (float rotationx) (float rotationy) (float rotationz) //rotation -* SCALE (float scalex) (float scaley) (float scalez) //scale - -Two examples are provided in the `scenes/` directory: a single emissive sphere, -and a simple cornell box made using cubes for walls and lights and a sphere in -the middle. - -## Third-Party Code Policy - -* Use of any third-party code must be approved by asking on our Google Group. -* 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 path 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, at minimum, - result in you receiving an F for the semester. - -## README - -Please see: [**TIPS FOR WRITING AN AWESOME README**](https://github.com/pjcozzi/Articles/blob/master/CIS565/GitHubRepo/README.md) - -* Sell your project. -* Assume the reader has a little knowledge of path tracing - don't go into - detail explaining what it is. Focus on your project. -* Don't talk about it like it's an assignment - don't say what is and isn't - "extra" or "extra credit." Talk about what you accomplished. -* Use this to document what you've done. -* *DO NOT* leave the README to the last minute! It is a crucial part of the - project, and we will not be able to grade you without a good README. - -In addition: - -* This is a renderer, so include images that you've made! -* Be sure to back your claims for optimization with numbers and comparisons. -* If you reference any other material, please provide a link to it. -* You wil not be graded on how fast your path tracer runs, but getting close to - real-time is always nice! -* If you have a fast GPU renderer, it is very good to show case this with a - video to show interactivity. If you do so, please include a link! - -### Analysis - -* Stream compaction helps most after a few bounces. Print and plot the - effects of stream compaction within a single iteration (i.e. the number of - unterminated rays after each bounce) and evaluate the benefits you get from - stream compaction. -* Compare scenes which are open (like the given cornell box) and closed - (i.e. no light can escape the scene). Again, compare the performance effects - of stream compaction! Remember, stream compaction only affects rays which - terminate, so what might you expect? - - -## Submit - -If you have modified any of the `CMakeLists.txt` files at all (aside from the -list of `SOURCE_FILES`), you must test that your project can build in Moore -100B/C. Beware of any build issues discussed on the Google Group. - -1. Open a GitHub pull request so that we can see that you have finished. - The title should be "Submission: YOUR NAME". -2. Send an email to the TA (gmail: kainino1+cis565@) with: - * **Subject**: in the form of `[CIS565] Project N: PENNKEY`. - * Direct link to your pull request on GitHub. - * Estimate the amount of time you spent on the project. - * If there were any outstanding problems, or if you did any extra - work, *briefly* explain. - * Feedback on the project itself, if any. - -## References - -* [PBRT] Physically Based Rendering, Second Edition: From Theory To Implementation. Pharr, Matt and Humphreys, Greg. 2010. +* 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 +* EMITTANCE (float emittance) //the emittance strength of the material. Material is a light source iff emittance > 0. +* BSSRDF (float bssrdf) //value of Sigma_t for subsurface materials +* TEX (string) //file path for the texture, put "NULL" if no texture for this material + +#### Future Work + +* Load arbitrary meshes +* Bump & Displacement Mapping +* Depth of field + +#### Base Code + +[CIS565-Fall-2015/Project3-CUDA-Path-Tracer](https://github.com/CIS565-Fall-2015/Project3-CUDA-Path-Tracer) + +#### References + +* Yining Karl Li's [Slides](https://github.com/CIS565-Fall-2015/cis565-fall-2015.github.io/raw/master/lectures/4.1-Path-Tracing-1.pdf) +* [BSSRDF Explorer: A rendering framework for the BSSRDF](http://noobody.org/bachelor-thesis.pdf) \ No newline at end of file diff --git a/img/01Overview.jpg b/img/01Overview.jpg new file mode 100644 index 0000000..4895ed4 Binary files /dev/null and b/img/01Overview.jpg differ diff --git a/img/01Overview.png b/img/01Overview.png new file mode 100644 index 0000000..1fec710 Binary files /dev/null and b/img/01Overview.png differ diff --git a/img/02Gobal_off.png b/img/02Gobal_off.png new file mode 100644 index 0000000..d617492 Binary files /dev/null and b/img/02Gobal_off.png differ diff --git a/img/02Gobal_on.png b/img/02Gobal_on.png new file mode 100644 index 0000000..8308146 Binary files /dev/null and b/img/02Gobal_on.png differ diff --git a/img/03AntiA_off.png b/img/03AntiA_off.png new file mode 100644 index 0000000..e83ce7c Binary files /dev/null and b/img/03AntiA_off.png differ diff --git a/img/03AntiA_on.PNG b/img/03AntiA_on.PNG new file mode 100644 index 0000000..0301fe7 Binary files /dev/null and b/img/03AntiA_on.PNG differ diff --git a/img/03AntiAl_off.png b/img/03AntiAl_off.png new file mode 100644 index 0000000..8b17eef Binary files /dev/null and b/img/03AntiAl_off.png differ diff --git a/img/03AntiAl_on.png b/img/03AntiAl_on.png new file mode 100644 index 0000000..d08aeff Binary files /dev/null and b/img/03AntiAl_on.png differ diff --git a/img/04DiffSpecTrans.png b/img/04DiffSpecTrans.png new file mode 100644 index 0000000..e11e003 Binary files /dev/null and b/img/04DiffSpecTrans.png differ diff --git a/img/05SSS.png b/img/05SSS.png new file mode 100644 index 0000000..3ced275 Binary files /dev/null and b/img/05SSS.png differ diff --git a/img/05SSS01.png b/img/05SSS01.png new file mode 100644 index 0000000..8124d4d Binary files /dev/null and b/img/05SSS01.png differ diff --git a/img/05SSS02.png b/img/05SSS02.png new file mode 100644 index 0000000..938ea8a Binary files /dev/null and b/img/05SSS02.png differ diff --git a/img/05SSS03.png b/img/05SSS03.png new file mode 100644 index 0000000..f1d04c2 Binary files /dev/null and b/img/05SSS03.png differ diff --git a/img/06TexMap.png b/img/06TexMap.png new file mode 100644 index 0000000..70ae6fc Binary files /dev/null and b/img/06TexMap.png differ diff --git a/img/06TexMap_cube.png b/img/06TexMap_cube.png new file mode 100644 index 0000000..eb9bccd Binary files /dev/null and b/img/06TexMap_cube.png differ diff --git a/img/06TexMap_sphere.png b/img/06TexMap_sphere.png new file mode 100644 index 0000000..c68bb03 Binary files /dev/null and b/img/06TexMap_sphere.png differ diff --git a/img/Analysis/CloseScene.png b/img/Analysis/CloseScene.png new file mode 100644 index 0000000..75c8d12 Binary files /dev/null and b/img/Analysis/CloseScene.png differ diff --git a/img/Analysis/OpenScene.png b/img/Analysis/OpenScene.png new file mode 100644 index 0000000..078c12a Binary files /dev/null and b/img/Analysis/OpenScene.png differ diff --git a/img/Analysis/SharedMem.PNG b/img/Analysis/SharedMem.PNG new file mode 100644 index 0000000..dd6354c Binary files /dev/null and b/img/Analysis/SharedMem.PNG differ diff --git a/img/DirectIllumination_SSS_thrustRemoveIf.PNG b/img/DirectIllumination_SSS_thrustRemoveIf.PNG new file mode 100644 index 0000000..1c7c091 Binary files /dev/null and b/img/DirectIllumination_SSS_thrustRemoveIf.PNG differ diff --git a/img/DirectIllumination_SSS_thrustRemoveIfOn.PNG b/img/DirectIllumination_SSS_thrustRemoveIfOn.PNG new file mode 100644 index 0000000..99dd02e Binary files /dev/null and b/img/DirectIllumination_SSS_thrustRemoveIfOn.PNG differ diff --git a/img/cornell.2015-09-19_02-00-56z.5000samp.png b/img/cornell.2015-09-19_02-00-56z.5000samp.png new file mode 100644 index 0000000..9e85aef Binary files /dev/null and b/img/cornell.2015-09-19_02-00-56z.5000samp.png differ diff --git a/img/cornell.2015-09-19_02-23-59z.5000samp_direct.png b/img/cornell.2015-09-19_02-23-59z.5000samp_direct.png new file mode 100644 index 0000000..edf33ca Binary files /dev/null and b/img/cornell.2015-09-19_02-23-59z.5000samp_direct.png differ diff --git a/img/cornell.2015-09-21_16-03-04z.3494samp.png b/img/cornell.2015-09-21_16-03-04z.3494samp.png new file mode 100644 index 0000000..8220e88 Binary files /dev/null and b/img/cornell.2015-09-21_16-03-04z.3494samp.png differ diff --git a/img/cornell.2015-09-23_14-49-24z.2728samp.png b/img/cornell.2015-09-23_14-49-24z.2728samp.png new file mode 100644 index 0000000..ff9dec8 Binary files /dev/null and b/img/cornell.2015-09-23_14-49-24z.2728samp.png differ diff --git a/img/cornell.2015-09-23_14-55-22z.5000samp.png b/img/cornell.2015-09-23_14-55-22z.5000samp.png new file mode 100644 index 0000000..a2a762a Binary files /dev/null and b/img/cornell.2015-09-23_14-55-22z.5000samp.png differ diff --git a/img/cornell.2015-09-25_00-05-55z.1318samp.png b/img/cornell.2015-09-25_00-05-55z.1318samp.png new file mode 100644 index 0000000..5dbd9ba Binary files /dev/null and b/img/cornell.2015-09-25_00-05-55z.1318samp.png differ diff --git a/img/cornell.2015-09-25_16-02-37z.5000samp.png b/img/cornell.2015-09-25_16-02-37z.5000samp.png new file mode 100644 index 0000000..be5c6f2 Binary files /dev/null and b/img/cornell.2015-09-25_16-02-37z.5000samp.png differ diff --git a/img/cornell.2015-09-27_16-30-51z.431samp.png b/img/cornell.2015-09-27_16-30-51z.431samp.png new file mode 100644 index 0000000..7afda61 Binary files /dev/null and b/img/cornell.2015-09-27_16-30-51z.431samp.png differ diff --git a/img/cornell.2015-09-27_16-32-50z.5000samp.png b/img/cornell.2015-09-27_16-32-50z.5000samp.png new file mode 100644 index 0000000..7959668 Binary files /dev/null and b/img/cornell.2015-09-27_16-32-50z.5000samp.png differ diff --git a/img/cornell.2015-09-28_21-35-15z.5000samp.png b/img/cornell.2015-09-28_21-35-15z.5000samp.png new file mode 100644 index 0000000..b1a2adf Binary files /dev/null and b/img/cornell.2015-09-28_21-35-15z.5000samp.png differ diff --git a/img/cornell.2015-09-28_23-53-06z.5000samp.png b/img/cornell.2015-09-28_23-53-06z.5000samp.png new file mode 100644 index 0000000..6d0bfac Binary files /dev/null and b/img/cornell.2015-09-28_23-53-06z.5000samp.png differ diff --git a/img/cornell.2015-09-29_00-21-48z.5000samp.png b/img/cornell.2015-09-29_00-21-48z.5000samp.png new file mode 100644 index 0000000..8944333 Binary files /dev/null and b/img/cornell.2015-09-29_00-21-48z.5000samp.png differ diff --git a/img/no_anti.png b/img/no_anti.png new file mode 100644 index 0000000..52a2ffb Binary files /dev/null and b/img/no_anti.png differ diff --git a/scenes/DiffSpecTrans.txt b/scenes/DiffSpecTrans.txt new file mode 100644 index 0000000..71c698a --- /dev/null +++ b/scenes/DiffSpecTrans.txt @@ -0,0 +1,268 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 +TEX NULL + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse pink +MATERIAL 2 +RGB .95 .72 .85 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Mirror blue +MATERIAL 3 +RGB 1 1 1 +SPECEX 0 +SPECRGB .8 .9 .85 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse Gray +MATERIAL 4 +RGB .7 .7 .7 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// transparent white +MATERIAL 5 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 1 +REFRIOR 1.6 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// transparent coffe +MATERIAL 6 +RGB .7 .6 .5 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 1 +REFRIOR 1.2 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// transparent mint +MATERIAL 7 +RGB .85 .98 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 1 +REFRIOR 1.6 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// mirror lemon +MATERIAL 8 +RGB 1 1 1 +SPECEX 0 +SPECRGB .97 .95 .7 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// diffuse mint +MATERIAL 9 +RGB .7 .98 .95 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// spec orange +MATERIAL 10 +RGB .98 .8 .7 +SPECEX 10 +SPECRGB .98 .8 .7 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX pp.jpg + +// spec violet +MATERIAL 11 +RGB .8 .8 .97 +SPECEX 30 +SPECRGB .9 .7 .97 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX pp.jpg + +// Camera +CAMERA +RES 800 800 +FOVY 30 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +//EYE -0.7 2 3.5 +EYE 0 4 12 +VIEW 0 -0.1 -1 +UP 0 1 0 + + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 12 0 +ROTAT 0 0 0 +SCALE 4 .3 4 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 28 .01 28 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 12 0 +ROTAT 0 0 90 +SCALE .01 40 40 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -13 +ROTAT 0 90 0 +SCALE .01 30 30 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -10 5 0 +ROTAT 0 0 0 +SCALE .01 30 30 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 16 5 0 +ROTAT 00 60 0 +SCALE .01 30 30 + +// Front wall +OBJECT 6 +cube +material 4 +TRANS 7 5 13 +ROTAT 0 90 0 +SCALE .01 30 30 + +// Transparent Sphere (white) +OBJECT 7 +sphere +material 5 +TRANS -2 1.6 1 +ROTAT 0 30 0 +SCALE 3 3 3 + +// Transparent Cube (coffee) +OBJECT 8 +cube +material 6 +TRANS -4 1.5 -5 +ROTAT 0 50 0 +SCALE 3 3 3 + +// Transparent Sphere (mint) +OBJECT 9 +sphere +material 7 +TRANS -4 4.3 -5 +ROTAT 0 0 0 +SCALE 2.6 2.6 2.6 + +// Transparent Sphere (lemon) +OBJECT 10 +sphere +material 8 +TRANS 4 4.3 -3 +ROTAT 0 0 0 +SCALE 2.6 2.6 2.6 + +// Diffuse cube(mint) +OBJECT 11 +cube +material 9 +TRANS 4 1.5 -3 +ROTAT 0 10 0 +SCALE 2 3 2 + +// Spec sphere(orange) +OBJECT 12 +sphere +material 10 +TRANS 2 1 -2.8 +ROTAT 0 10 0 +SCALE 2 2 2 + +// Spec sphere(violet) +OBJECT 13 +sphere +material 11 +TRANS 2.7 .5 -1.5 +ROTAT 0 10 0 +SCALE 1 1 1 \ No newline at end of file diff --git a/scenes/SSS.txt b/scenes/SSS.txt new file mode 100644 index 0000000..f556179 --- /dev/null +++ b/scenes/SSS.txt @@ -0,0 +1,258 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse pink +MATERIAL 2 +RGB .95 .72 .85 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Mirror blue +MATERIAL 3 +RGB 1 1 1 +SPECEX 0 +SPECRGB .8 .9 .85 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse Gray +MATERIAL 4 +RGB .7 .7 .7 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +//------------------------------------- Object-Materials -------// + +// SSS-Refl white +MATERIAL 5 +RGB .8 .8 .8 +SPECEX 0 +SPECRGB .99 .99 .99 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.5 + +// SSS coffe +MATERIAL 6 +RGB .7 .6 .5 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1 + +// SSS-Refl mint +MATERIAL 7 +RGB .85 .88 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.2 + +// SSS-refl lemon +MATERIAL 8 +RGB .97 .95 .75 +SPECEX 0 +SPECRGB .97 .95 .75 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.1 + +// SSS mint +MATERIAL 9 +RGB .7 .9 .8 +SPECEX 0 +SPECRGB .7 .9 .8 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1.5 + +// spec orange +MATERIAL 10 +RGB .98 .8 .7 +SPECEX 0 +SPECRGB .98 .8 .7 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.8 + +// spec violet +MATERIAL 11 +RGB .8 .8 .97 +SPECEX 0 +SPECRGB .9 .7 .97 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.8 + +// Camera +CAMERA +RES 800 800 +FOVY 30 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 8 12.5 +VIEW 0 -0.25 -1 +UP 0 1 0 + +//------------------------------------- Objects -------// + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 5 .3 5 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 28 .01 28 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 40 40 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -13 +ROTAT 0 90 0 +SCALE .01 30 30 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -10 5 0 +ROTAT 0 0 0 +SCALE .01 30 30 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 16 5 0 +ROTAT 00 60 0 +SCALE .01 30 30 + +// Front wall +OBJECT 6 +cube +material 4 +TRANS 7 5 13 +ROTAT 0 90 0 +SCALE .01 30 30 + +// Transparent Sphere (white) +OBJECT 7 +sphere +material 5 +TRANS -2 1.6 1 +ROTAT 0 30 0 +SCALE 3 3 3 + +// Transparent Cube (coffee) +OBJECT 8 +cube +material 6 +TRANS -4 1.5 -5 +ROTAT 0 50 0 +SCALE 3 3 3 + +// Transparent Sphere (mint) +OBJECT 9 +sphere +material 7 +TRANS -4 4.3 -5 +ROTAT 0 0 0 +SCALE 2.6 2.6 2.6 + +// Transparent Sphere (lemon) +OBJECT 10 +sphere +material 8 +TRANS 3.5 7.3 3 +ROTAT 0 0 0 +SCALE 2.6 2.6 2.6 + +// Diffuse cube(mint) +OBJECT 11 +cube +material 9 +TRANS 3.5 3 3 +ROTAT 0 10 0 +SCALE 2 6 2 + +// Spec sphere(orange) +OBJECT 12 +sphere +material 10 +TRANS 2 1 -2.8 +ROTAT 0 10 0 +SCALE 2 2 2 + +// Spec sphere(violet) +OBJECT 13 +sphere +material 11 +TRANS 2.7 .5 -1.5 +ROTAT 0 10 0 +SCALE 1 1 1 \ No newline at end of file diff --git a/scenes/Subsurface_diffuse.txt b/scenes/Subsurface_diffuse.txt new file mode 100644 index 0000000..a4e2a6b --- /dev/null +++ b/scenes/Subsurface_diffuse.txt @@ -0,0 +1,141 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 6 +BSSRDF 0 + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse red +MATERIAL 2 +RGB .85 .55 .55 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse green +MATERIAL 3 +RGB .65 .85 .65 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Subsurface +MATERIAL 4 +RGB .98 .66 .45 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1 + +// diffuse +MATERIAL 5 +RGB .98 .66 .45 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Camera +CAMERA +RES 800 800 +FOVY 45 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 5 10.5 +VIEW 0 0 -1 +UP 0 1 0 + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS -1 7 -2 +ROTAT 45 45 90 +SCALE 2 .3 2 + + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// cube +OBJECT 6 +cube +material 4 +TRANS 3 1 1 +ROTAT 0 20 0 +SCALE 2 2 2 + +// cube +OBJECT 7 +cube +material 4 +TRANS 3 2.7 1 +ROTAT 0 0 0 +SCALE 1.6 1.4 1.6 \ No newline at end of file diff --git a/scenes/cornell.txt b/scenes/cornell.txt index 5f7b59b..c35a780 100644 --- a/scenes/cornell.txt +++ b/scenes/cornell.txt @@ -7,6 +7,8 @@ REFL 0 REFR 0 REFRIOR 0 EMITTANCE 5 +BSSRDF 0 +TEX NULL // Diffuse white MATERIAL 1 @@ -17,6 +19,8 @@ REFL 0 REFR 0 REFRIOR 0 EMITTANCE 0 +BSSRDF 0 +TEX NULL // Diffuse red MATERIAL 2 @@ -27,6 +31,8 @@ REFL 0 REFR 0 REFRIOR 0 EMITTANCE 0 +BSSRDF 0 +TEX NULL // Diffuse green MATERIAL 3 @@ -37,16 +43,20 @@ REFL 0 REFR 0 REFRIOR 0 EMITTANCE 0 +BSSRDF 0 +TEX NULL // Specular white MATERIAL 4 RGB .98 .98 .98 SPECEX 0 SPECRGB .98 .98 .98 -REFL 1 +REFL 0 REFR 0 REFRIOR 0 EMITTANCE 0 +BSSRDF 0 +TEX NULL // Camera CAMERA @@ -59,7 +69,6 @@ EYE 0.0 5 10.5 VIEW 0 0 -1 UP 0 1 0 - // Ceiling light OBJECT 0 cube diff --git a/scenes/cornell_all.txt b/scenes/cornell_all.txt new file mode 100644 index 0000000..3a9cb3e --- /dev/null +++ b/scenes/cornell_all.txt @@ -0,0 +1,237 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse red +MATERIAL 2 +RGB .85 .35 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse green +MATERIAL 3 +RGB .35 .85 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Specular blue +MATERIAL 4 +RGB .4 .4 .85 +SPECEX 5 +SPECRGB .6 .6 .6 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Mirror yellow +MATERIAL 5 +RGB .85 .85 .4 +SPECEX 10 +SPECRGB .85 .85 .4 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// diffuse blue +MATERIAL 6 +RGB .4 .4 .85 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// subsurface purple +MATERIAL 7 +RGB .95 .5 .8 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1.5 + +// mirror yellow +MATERIAL 8 +RGB .85 .8 .4 +SPECEX 0 +SPECRGB .85 .8 .4 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// transparent white +MATERIAL 9 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 1 +REFRIOR 1.4 +EMITTANCE 0 +BSSRDF 0 + +// Reflective Subsurface white +MATERIAL 10 +RGB .5 .85 .85 +SPECEX 0 +SPECRGB .5 .85 .85 +REFL 1 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0.3 + +// Camera +CAMERA +RES 800 800 +FOVY 45 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 5 10.5 +VIEW 0 0 -1 +UP 0 1 0 + + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 3 .3 3 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + + +// Diffuse Sphere (blue) +OBJECT 6 +sphere +material 6 +TRANS -1 4 -1 +ROTAT 0 0 0 +SCALE 1.5 1.5 1.5 + +// Specuar Sphere (white-blue) +OBJECT 7 +sphere +material 4 +TRANS -2 6 -2 +ROTAT 0 0 0 +SCALE 2 2 2 + +// Mirror Sphere (yellow) +OBJECT 8 +sphere +material 8 +TRANS 2 4.5 -6 +ROTAT 0 0 0 +SCALE 4 4 4 + +// Subsurface-Diffuse Cube(purple) +OBJECT 9 +cube +material 7 +TRANS 1.7 2 2 +ROTAT 0 30 0 +SCALE 2 2.4 1.5 + +// Transparent Sphere (white) +OBJECT 10 +sphere +material 9 +TRANS -2 1.6 1 +ROTAT 0 0 0 +SCALE 3 3 3 + +// Reflective+Subsurface Sphere (blue-green) +OBJECT 11 +sphere +material 10 +TRANS 1.4 6.5 0.8 +ROTAT 0 0 0 +SCALE 2.35 2.35 2.35 + +// Light Sphere (blue-green) +OBJECT 12 +sphere +material 0 +TRANS 0.6 3 0.5 +ROTAT 0 0 0 +SCALE 1.2 1.2 1.2 \ No newline at end of file diff --git a/scenes/cornell_closed.txt b/scenes/cornell_closed.txt new file mode 100644 index 0000000..04c016e --- /dev/null +++ b/scenes/cornell_closed.txt @@ -0,0 +1,134 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 +TEX NULL + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse red +MATERIAL 2 +RGB .85 .35 .35 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse green +MATERIAL 3 +RGB .35 .85 .35 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Specular white +MATERIAL 4 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Camera +CAMERA +RES 800 800 +FOVY 45 +ITERATIONS 5000 +DEPTH 32 +FILE cornell +EYE 0.0 5 4 +VIEW 0 0 -1 +UP 0 1 0 + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 3 .3 3 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Sphere +OBJECT 6 +sphere +material 4 +TRANS -1 4 -1 +ROTAT 0 0 0 +SCALE 3 3 3 + +// front wall +OBJECT 7 +cube +material 2 +TRANS 0 5 4.9 +ROTAT 0 0 0 +SCALE 10 10 .1 \ No newline at end of file diff --git a/scenes/cornell_subsurface.txt b/scenes/cornell_subsurface.txt new file mode 100644 index 0000000..e66a21c --- /dev/null +++ b/scenes/cornell_subsurface.txt @@ -0,0 +1,148 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse red +MATERIAL 2 +RGB .85 .35 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse green +MATERIAL 3 +RGB .35 .85 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Subsurface +MATERIAL 4 +RGB .98 .66 .45 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1 + +// diffuse +MATERIAL 5 +RGB .98 .66 .45 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Camera +CAMERA +RES 800 800 +FOVY 45 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 5 10.5 +VIEW 0 0 -1 +UP 0 1 0 + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 3 .3 3 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// sphere +OBJECT 6 +sphere +material 5 +TRANS 2 7 1 +ROTAT 0 0 0 +SCALE 2.5 2.5 2.5 + +// sphere +OBJECT 7 +sphere +material 4 +TRANS -2 7 1 +ROTAT 0 0 0 +SCALE 2.5 2.5 2.5 + +// sphere +OBJECT 8 +cube +material 4 +TRANS 0 4 0 +ROTAT 0 0 0 +SCALE 2.5 2.5 2.5 \ No newline at end of file diff --git a/scenes/cornell_tex.txt b/scenes/cornell_tex.txt new file mode 100644 index 0000000..94a44de --- /dev/null +++ b/scenes/cornell_tex.txt @@ -0,0 +1,127 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 5 +BSSRDF 0 +TEX NULL + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse red +MATERIAL 2 +RGB .55 .35 .35 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse green +MATERIAL 3 +RGB .35 .55 .35 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX NULL + +// Diffuse white cube +MATERIAL 4 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB .98 .98 .98 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 +TEX 2031.jpg +//https://www.filterforge.com/filters/2031.jpg + +// Camera +CAMERA +RES 800 800 +FOVY 30 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 5 10.5 +VIEW 0 0 -1 +UP 0 1 0 + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 3 .3 3 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Sphere +OBJECT 6 +sphere +material 4 +TRANS 0 4 -1 +ROTAT 30 0 20 +SCALE 4 4 4 diff --git a/scenes/subsurface.txt b/scenes/subsurface.txt new file mode 100644 index 0000000..6b44ef1 --- /dev/null +++ b/scenes/subsurface.txt @@ -0,0 +1,132 @@ +// Emissive material (light) +MATERIAL 0 +RGB 1 1 1 +SPECEX 0 +SPECRGB 0 0 0 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 8 +BSSRDF 0 + +// Diffuse white +MATERIAL 1 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse red +MATERIAL 2 +RGB .9 .35 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Diffuse green +MATERIAL 3 +RGB .35 .9 .35 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Subsurface +MATERIAL 4 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 1 + +// diffuse +MATERIAL 5 +RGB .98 .98 .98 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 0 +EMITTANCE 0 +BSSRDF 0 + +// Camera +CAMERA +RES 800 800 +FOVY 45 +ITERATIONS 5000 +DEPTH 8 +FILE cornell +EYE 0.0 5 10.5 +VIEW 0 0 -1 +UP 0 1 0 + +// Ceiling light +OBJECT 0 +cube +material 0 +TRANS 0 10 0 +ROTAT 0 0 0 +SCALE 2 .3 2 + +// Floor +OBJECT 1 +cube +material 1 +TRANS 0 0 0 +ROTAT 0 0 0 +SCALE 10 .01 10 + +// Ceiling +OBJECT 2 +cube +material 1 +TRANS 0 10 0 +ROTAT 0 0 90 +SCALE .01 10 10 + +// Back wall +OBJECT 3 +cube +material 1 +TRANS 0 5 -5 +ROTAT 0 90 0 +SCALE .01 10 10 + +// Left wall +OBJECT 4 +cube +material 2 +TRANS -5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// Right wall +OBJECT 5 +cube +material 3 +TRANS 5 5 0 +ROTAT 0 0 0 +SCALE .01 10 10 + +// cube +OBJECT 6 +cube +material 4 +TRANS -2 3.5 0.2 +ROTAT 0 30 0 +SCALE 3 7 3 \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1cb3fb..ee12acb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,4 +20,4 @@ set(SOURCE_FILES cuda_add_library(src ${SOURCE_FILES} OPTIONS -arch=sm_20 - ) + ) \ No newline at end of file diff --git a/src/image.cpp b/src/image.cpp index 9405155..4efd429 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -1,17 +1,23 @@ #include #include #include +#include #include "image.h" image::image(int x, int y) : xSize(x), ySize(y), - pixels(new glm::vec3[x * y]) { + pixels(new glm::vec3[x * y]), + isTex(false){ } image::~image() { - delete pixels; + if (!isTex) + { + delete pixels; + } + } void image::setPixel(int x, int y, const glm::vec3 &pixel) { @@ -19,6 +25,17 @@ void image::setPixel(int x, int y, const glm::vec3 &pixel) { pixels[(y * xSize) + x] = pixel; } +glm::vec3 image::getPixel(int x, int y) { + assert(x >= 0 && y >= 0 && x < xSize && y < ySize); + return pixels[(y * xSize) + x]; +} + +void image::saveHDR(const std::string &baseFilename) { + std::string filename = baseFilename + ".hdr"; + stbi_write_hdr(filename.c_str(), xSize, ySize, 3, (const float *) pixels); + std::cout << "Saved " + filename + "." << std::endl; +} + void image::savePNG(const std::string &baseFilename) { unsigned char *bytes = new unsigned char[3 * xSize * ySize]; for (int y = 0; y < ySize; y++) { @@ -37,9 +54,54 @@ void image::savePNG(const std::string &baseFilename) { delete[] bytes; } +image::image(const std::string &baseFilename) +{ + //unsigned char *bytes = new unsigned char[3 * xSize * ySize]; + int n = 3,x,y; + unsigned char *bytes = stbi_load(baseFilename.c_str(), &x, &y, &n, 0); + xSize = x; + ySize = y; + pixels = new glm::vec3[xSize * ySize]; -void image::saveHDR(const std::string &baseFilename) { - std::string filename = baseFilename + ".hdr"; - stbi_write_hdr(filename.c_str(), xSize, ySize, 3, (const float *) pixels); - std::cout << "Saved " + filename + "." << std::endl; + for (int y = 0; y < ySize; y++) { + for (int x = 0; x < xSize; x++) { + int i = y * xSize + x; + pixels[i].x = (float)bytes[3 * i + 0] / 255.f; + pixels[i].y = (float)bytes[3 * i + 1] / 255.f; + pixels[i].z = (float)bytes[3 * i + 2] / 255.f; + } + } + isTex = true; + //setPixel(,); + std::cout << "loaded " << baseFilename << "." << std::endl; + delete[] bytes; +} +void image::loadPNG(const std::string &baseFilename) { + //unsigned char *bytes = new unsigned char[3 * xSize * ySize]; + int n = 3; + unsigned char *bytes = stbi_load(baseFilename.c_str(), &xSize, &ySize, &n, 0); + pixels = new glm::vec3[xSize * ySize]; + + for (int y = 0; y < ySize; y++) { + for (int x = 0; x < xSize; x++) { + int i = y * xSize + x; + //glm::vec3 pix = glm::clamp(pixels[i], glm::vec3(), glm::vec3(1)) * 255.f; + //bytes[3 * i + 0] = (unsigned char)pix.x; + //bytes[3 * i + 1] = (unsigned char)pix.y; + //bytes[3 * i + 2] = (unsigned char)pix.z; + pixels[i].x = (float)bytes[3 * i + 0]/255.f; + pixels[i].y = (float)bytes[3 * i + 1] / 255.f; + pixels[i].z = (float)bytes[3 * i + 2] / 255.f; + } + } + + //std::string filename = baseFilename + ".png"; + //stbi_write_png(filename.c_str(), xSize, ySize, 3, bytes, xSize * 3); + std::cout << "loaded " << baseFilename << "." << std::endl; + + delete[] bytes; +} +int image::getSize() +{ + return xSize*ySize; } diff --git a/src/image.h b/src/image.h index ae1b768..51d841f 100644 --- a/src/image.h +++ b/src/image.h @@ -6,14 +6,22 @@ using namespace std; class image { private: - int xSize; - int ySize; - glm::vec3 *pixels; + + public: + int xSize; + int ySize; + glm::vec3 *pixels; image(int x, int y); + image(const std::string &baseFilename); ~image(); void setPixel(int x, int y, const glm::vec3 &pixel); + glm::vec3 getPixel(int x, int y); void savePNG(const std::string &baseFilename); void saveHDR(const std::string &baseFilename); + void loadPNG(const std::string &baseFilename); + int getSize(); + bool isTex; }; + diff --git a/src/interactions.h b/src/interactions.h index d8107fb..2375df3 100644 --- a/src/interactions.h +++ b/src/interactions.h @@ -2,6 +2,8 @@ #include "intersections.h" + + // CHECKITOUT /** * Computes a cosine-weighted random direction in a hemisphere. @@ -40,6 +42,48 @@ glm::vec3 calculateRandomDirectionInHemisphere( + cos(around) * over * perpendicularDirection1 + sin(around) * over * perpendicularDirection2; } +//http://www.igorsklyar.com/system/documents/papers/4/fiscourse.comp.pdf +__host__ __device__ +glm::vec3 calculateRandomSpecularDirection( +glm::vec3 specDir,float specExp, thrust::default_random_engine &rng) { + thrust::uniform_real_distribution u01(0, 1); + float X1 = u01(rng); + float X2 = u01(rng); + float n = specExp; + + float thi = acos(pow(X1, 1 / (n+1))); + float phi = TWO_PI*X2; + + float z = cos(thi); + float x = cos(phi)*sin(thi); + float y = sin(phi)*sin(thi); + + // Find a direction that is not the normal based off of whether or not the + // normal's components are all equal to sqrt(1/3) or whether or not at + // least one component is less than sqrt(1/3). Learned this trick from + // Peter Kutz. + + glm::vec3 directionNotNormal; + if (abs(specDir.x) < SQRT_OF_ONE_THIRD) { + directionNotNormal = glm::vec3(1, 0, 0); + } + else if (abs(specDir.y) < SQRT_OF_ONE_THIRD) { + directionNotNormal = glm::vec3(0, 1, 0); + } + else { + directionNotNormal = glm::vec3(0, 0, 1); + } + + // Use not-normal direction to generate two perpendicular directions + glm::vec3 perpendicularDirection1 = + glm::normalize(glm::cross(specDir, directionNotNormal)); + glm::vec3 perpendicularDirection2 = + glm::normalize(glm::cross(specDir, perpendicularDirection1)); + + return z * specDir + + x * perpendicularDirection1 + + y * perpendicularDirection2; +} /** * Scatter a ray with some probabilities according to the material properties. @@ -66,15 +110,215 @@ glm::vec3 calculateRandomDirectionInHemisphere( * * You may need to change the parameter list for your purposes! */ + +__host__ __device__ glm::vec3 ColorInTex(int texId,glm::vec3**texs,glm::vec2*info,glm::vec2 uv) +{ + int xSize = info[texId].x; + int ySize = info[texId].y; + if (uv.x < 0 || uv.y < 0 || uv.x >1 || uv.y >1) return glm::vec3(0, 0, 0); + int x = (float)(uv.x*(float)xSize); + int y = (float)(uv.y*(float)ySize); + return texs[texId][(y * xSize) + x]; +} + __host__ __device__ -void scatterRay( - Ray &ray, - glm::vec3 &color, - glm::vec3 intersect, - glm::vec3 normal, - const Material &m, - thrust::default_random_engine &rng) { - // TODO: implement this. - // A basic implementation of pure-diffuse shading will just call the - // calculateRandomDirectionInHemisphere defined above. +glm::vec3 scatterRay( +Ray &ray, +bool outside, +float intrT, +glm::vec3 intersect, +glm::vec3 normal, +const Material &m, +glm::vec3**t, +glm::vec2*info, +glm::vec2 uv, +thrust::default_random_engine &rrr) { + // TODO: implement this. + // A basic implementation of pure-diffuse shading will just call the + // calculateRandomDirectionInHemisphere defined above. + enum RayType + { + DiffRay, // Diffuse ray : calculateRandomDirectionInHemisphere + ReflRay, // (Mirror) Reflected ray: glm::reflect(ray.direction, normal); + RefrRay, // (Transparent) refracted ray : n1/n2 + SpecRay, // (Non-perfect Mirror) calculateRandomSpecularDirection + SSSRay_o, // + SSSRay_i + }; + int ray_type; + float specProb = 0; + thrust::uniform_real_distribution u01(0, 1); + + if (ray.terminated) + return ray.carry; + + glm::vec3 matColor = m.color; + glm::vec3 matSpecClr = m.specular.color; + if (m.TexIdx!=-1) + { + matColor = ColorInTex(m.TexIdx,t,info, uv); + //matSpecClr = matColor; + //printf("UV:%3f,%3f\n color:%3f,%3f,%3f\n",uv.x,uv.y, matColor.x, matColor.y, matColor); + //matColor = glm::vec3(0, 1, 0); + } + + if (m.emittance > 0) + { + ray.carry *= m.emittance*matColor;// m.color; + ray.terminated = true; + return ray.carry; + } + // Shading + else if (m.hasRefractive) + {//later + float cos_thi = glm::dot(glm::normalize(-ray.direction), glm::normalize(normal)); + float R0 = (m.indexOfRefraction-1) / (1+m.indexOfRefraction); + R0 *= R0; + float R_thi = R0 + (1 - R0)*pow(1 - cos_thi, 5); + if (outside) + { + if (u01(rrr)0) + { + + if (outside) //from outside + { + float cos_thi = glm::dot(glm::normalize(-ray.direction), glm::normalize(normal)); + float R_thi = pow(1 - cos_thi, 5); + if (u01(rrr) < R_thi)//later: what value to choose? + ray_type = ReflRay; + else + ray_type = SSSRay_o; + } + else//inside + ray_type = SSSRay_i; + } + else + ray_type = ReflRay; + } + else if (m.bssrdf > 0) //subsurface scattering : try brute-force bssrdf + { + //http://noobody.org/bachelor-thesis.pdf + //(1) incident or exitant or currently inside obj ? + // if incident: + if (outside) //from outside + { + if (u01(rrr) > -0.1)//later: what value to choose? + ray_type = SSSRay_o; + else + ray_type = DiffRay; + } + else//inside + ray_type = SSSRay_i; + + } + else // diffuse / specular + { + //!!! later : specular + //http://www.tomdalling.com/blog/modern-opengl/07-more-lighting-ambient-specular-attenuation-gamma/ + + if (m.specular.exponent > 0) + { + specProb = glm::length(matSpecClr); + //specProb = specProb / (specProb + glm::length(m.color)); + specProb = specProb / (specProb + glm::length(matColor)); + if (u01(rrr) < specProb) //spec ray + ray_type = SpecRay; + else//diffuse ray + ray_type = DiffRay; + } + else + ray_type = DiffRay; + } + + + switch (ray_type) + { + case DiffRay: + { + ray.origin = getPointOnRay(ray, intrT); + ray.carry *= matColor;//m.color;// *(1.f / (1 - specProb)); + ray.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rrr)); + } + break; + case ReflRay: + { + ray.origin = getPointOnRay(ray, intrT); + ray.direction = glm::normalize(glm::reflect(ray.direction, normal)); + ray.carry *= matSpecClr; + } + break; + case RefrRay: + { + + float n = m.indexOfRefraction; + if (outside) + n = 1 / n; + float angle = 1.0f - glm::pow(n, 2) * (1.0f - glm::pow(glm::dot(normal, ray.direction), 2)); + if (angle < 0) + { + ray.origin = getPointOnRay(ray, intrT); + ray.direction = glm::normalize(glm::reflect(ray.direction, normal)); + ray.carry *= matSpecClr; + } + else + { + ray.origin = getPointOnRay(ray, intrT + 0.001f); + ray.direction = glm::normalize(glm::refract(ray.direction, normal, n)); + ray.carry *= matColor;// m.color; + } + } + break; + case SpecRay: + { + ray.origin = getPointOnRay(ray, intrT); + glm::vec3 specDir = glm::reflect(ray.direction, normal); + ray.direction = glm::normalize(calculateRandomSpecularDirection(specDir, m.specular.exponent, rrr)); + ray.carry *= matSpecClr;// *(1.f / specProb); + } + break; + case SSSRay_o: + { + ray.origin = getPointOnRay(ray, intrT + .0002f); + glm::vec3 refraDir = glm::normalize(calculateRandomDirectionInHemisphere(-normal, rrr)); + ray.carry *= matColor;// m.color; + ray.direction = refraDir; + } + break; + case SSSRay_i: + { + //Sigma_a: Absorption coefficient + //Sigma_s: Scattering coefficient + // Extinction coefficient Sigma_t = Sigma_s+Sigma_a + float Sigma_t = m.bssrdf; + float so = -log(u01(rrr)) / Sigma_t; + float si = glm::length(getPointOnRay(ray, intrT) - ray.origin); + if (si <= so) //turns into exitant, go out of the objects + //if (true) + { + //ray.carry *= m.color; + ray.origin = getPointOnRay(ray, intrT + .0002f); + ray.direction = glm::normalize(calculateRandomDirectionInHemisphere(-normal, rrr)); + } + else //stays in the obj, pick new direction and scatter distance + { + //ray.carry *= m.color; + ray.origin = getPointOnRay(ray, so); + ray.direction = -glm::normalize(calculateRandomDirectionInHemisphere(ray.direction, rrr)); + } + } + break; + default: + break; + } + return ray.carry; + } diff --git a/src/intersections.h b/src/intersections.h index f34b89d..cc9e1f6 100644 --- a/src/intersections.h +++ b/src/intersections.h @@ -44,12 +44,17 @@ __host__ __device__ glm::vec3 multiplyMV(glm::mat4 m, glm::vec4 v) { * @param outside Output param for whether the ray came from outside. * @return Ray parameter `t` value. -1 if no intersection. */ -__host__ __device__ float boxIntersectionTest(Geom box, Ray r, - glm::vec3 &intersectionPoint, glm::vec3 &normal, bool &outside) { +__host__ __device__ float boxIntersectionTest( + Geom box, Ray r, + glm::vec3 &intersectionPoint, + glm::vec3 &normal, + bool &outside, + glm::vec2 &UV) +{ Ray q; q.origin = multiplyMV(box.inverseTransform, glm::vec4(r.origin , 1.0f)); q.direction = glm::normalize(multiplyMV(box.inverseTransform, glm::vec4(r.direction, 0.0f))); - + //q: local ray float tmin = -1e38f; float tmax = 1e38f; glm::vec3 tmin_n; @@ -82,6 +87,35 @@ __host__ __device__ float boxIntersectionTest(Geom box, Ray r, outside = false; } intersectionPoint = multiplyMV(box.transform, glm::vec4(getPointOnRay(q, tmin), 1.0f)); + + glm::vec3 localP = getPointOnRay(q, tmin); + + UV = glm::vec2(-1, -1); + + if (abs(abs( localP.z) - 0.5) <0.01) //top or bottom + { + UV.x = (localP.y + 1.5f)/4.f; + UV.y = (localP.x + 0.5f) / 4.f; + if (localP.z < 0) + UV.y += 2.f / 4.f; + + } + else if (abs(abs(localP.x) - 0.5) <0.01)////front or back + { + UV.x = (localP.y + 1.5f) / 4.f; + UV.y = (1.5f - localP.z) / 4.f; + if (localP.x <0) + UV.y += 2.f / 4.f; + + } + else if (abs(abs(localP.y) - 0.5) <0.01) //left or right + { + UV.y = (1.5f - localP.z) / 4.f; + UV.x = (localP.x + 0.5f) / 4.f; + if (localP.y < 0) + UV.x += 2.f / 4.f; + } + normal = glm::normalize(multiplyMV(box.transform, glm::vec4(tmin_n, 0.0f))); return glm::length(r.origin - intersectionPoint); } @@ -98,8 +132,14 @@ __host__ __device__ float boxIntersectionTest(Geom box, Ray r, * @param outside Output param for whether the ray came from outside. * @return Ray parameter `t` value. -1 if no intersection. */ -__host__ __device__ float sphereIntersectionTest(Geom sphere, Ray r, - glm::vec3 &intersectionPoint, glm::vec3 &normal, bool &outside) { +__host__ __device__ float sphereIntersectionTest( + Geom sphere, + Ray r, + glm::vec3 &intersectionPoint, + glm::vec3 &normal, + bool &outside, + glm::vec2 &UV) +{ float radius = .5; glm::vec3 ro = multiplyMV(sphere.inverseTransform, glm::vec4(r.origin, 1.0f)); @@ -139,5 +179,13 @@ __host__ __device__ float sphereIntersectionTest(Geom sphere, Ray r, normal = -normal; } + UV = glm::vec2(-1, -1); + float dx = objspaceIntersection.x; + float dy = objspaceIntersection.y; + float dz = objspaceIntersection.z; + UV.x = 0.5 + atan2(dz, dx) / (2 * PI); + UV.y = 0.5 - asin(dy) / (PI); + + return glm::length(r.origin - intersectionPoint); } diff --git a/src/main.cpp b/src/main.cpp index 77671f4..3868ccf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,9 @@ #include "main.h" #include "preview.h" #include +#include + + static std::string startTimeString; static bool camchanged = false; @@ -14,6 +17,8 @@ int iteration; int width; int height; +bool ifStreamCompact = false; + //------------------------------- //-------------MAIN-------------- //------------------------------- @@ -27,10 +32,18 @@ int main(int argc, char** argv) { } const char *sceneFile = argv[1]; + if (argv[2]!=NULL) + { + string strCompactArg = argv[2]; + if (strCompactArg == "s" || strCompactArg == "S") + { + printf("Using stream compaction.\n", strCompactArg); + ifStreamCompact = true; + } + } // Load scene file scene = new Scene(sceneFile); - // Set up camera stuff from loaded path tracer settings iteration = 0; renderState = &scene->state; @@ -58,7 +71,6 @@ void saveImage() { img.setPixel(width - 1 - x, y, glm::vec3(pix) / samples); } } - std::string filename = renderState->imageName; std::ostringstream ss; ss << filename << "." << startTimeString << "." << samples << "samp"; @@ -66,7 +78,7 @@ void saveImage() { // CHECKITOUT img.savePNG(filename); - //img.saveHDR(filename); // Save a Radiance HDR file + img.saveHDR(filename); // Save a Radiance HDR file } void runCuda() { @@ -90,7 +102,7 @@ void runCuda() { if (iteration == 0) { pathtraceFree(); - pathtraceInit(scene); + pathtraceInit(scene, ifStreamCompact); } if (iteration < renderState->iterations) { @@ -100,8 +112,17 @@ void runCuda() { // execute the kernel int frame = 0; - pathtrace(pbo_dptr, frame, iteration); + //cin.get(); + + clock_t t1, t2; + t1 = clock(); + pathtrace(pbo_dptr, frame, iteration); + t2 = clock(); + float diff((float)t2 - (float)t1); + diff = diff / CLOCKS_PER_SEC; + printf("time/iter: %f\t iters/sec %f\n", diff,1/diff); + //cin.get(); // unmap buffer object cudaGLUnmapBufferObject(pbo); } else { @@ -135,3 +156,6 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods } } } + + + diff --git a/src/pathtrace.cu b/src/pathtrace.cu index e7ef1c6..788287b 100644 --- a/src/pathtrace.cu +++ b/src/pathtrace.cu @@ -4,7 +4,7 @@ #include #include #include - +#include #include "sceneStructs.h" #include "scene.h" #include "glm/glm.hpp" @@ -13,6 +13,7 @@ #include "pathtrace.h" #include "intersections.h" #include "interactions.h" +#include "image.h" #define ERRORCHECK 1 @@ -67,59 +68,529 @@ __global__ void sendImageToPBO(uchar4* pbo, glm::ivec2 resolution, } } + static Scene *hst_scene = NULL; static glm::vec3 *dev_image = NULL; -// TODO: static variables for device memory, scene/camera info, etc -// ... +static Geom *dev_geoms; +static Material *dev_mats; + +glm::vec3 **dev_textures; +glm::vec2 * dev_texInfo; + +bool doStreamCompact = false; +Ray * dev_rays; +Ray * dev_rays_temp; + +int ttlLights = 0; +int * dev_lightIdxs; +int *dev_temps; +int *dev_incre; +int *dev_bSum; + -void pathtraceInit(Scene *scene) { +void pathtraceInit(Scene *scene,bool strCmpt) { hst_scene = scene; + doStreamCompact = strCmpt; const Camera &cam = hst_scene->state.camera; const int pixelcount = cam.resolution.x * cam.resolution.y; + //(1) Initialize array of path rays + int raySize = pixelcount*sizeof(Ray); + cudaMalloc((void**)&dev_rays, raySize); + cudaMalloc((void**)&dev_rays_temp, raySize); + + //for stream compact + cudaMalloc((void**)&dev_temps, sizeof(int)*pixelcount); + cudaMalloc((void**)&dev_incre, sizeof(int)*pixelcount); + cudaMalloc((void**)&dev_bSum, sizeof(int)*pixelcount); + //Copy geoms to dev_geoms + int geoSize = hst_scene->geoms.size()*sizeof(Geom); + Geom * hst_geoms = (Geom *)malloc(geoSize); + + std::copy(hst_scene->geoms.begin(),hst_scene->geoms.end(),hst_geoms); + /* //??? or: + hst_geoms = & hst_scene->geoms[0]; + */ + + cudaMalloc((void**)&dev_geoms, geoSize); + cudaMemcpy(dev_geoms, hst_geoms, geoSize, cudaMemcpyHostToDevice); + + //Copy materials to dev_mats + int matSize = hst_scene->materials.size()*sizeof(Material); + cudaMalloc((void**)&dev_mats, matSize); + cudaMemcpy(dev_mats, hst_scene->materials.data(), matSize, cudaMemcpyHostToDevice); + + //Copy materials to dev_textures + int texSize = hst_scene->textures.size()*sizeof(glm::vec3 *); + int texInfoSize = hst_scene->textures.size()*sizeof(glm::vec2); + cudaMalloc((void**)&dev_textures, texSize); + cudaMalloc((void**)&dev_texInfo, texInfoSize); + std::vector tempImg; + std::vector tempInfo; + for (int i = 0; i < hst_scene->textures.size(); i++) + { + glm::vec3 * dev_img; + int imgSize = hst_scene->textures[i].getSize()*sizeof(glm::vec3); + cudaMalloc((void**)&dev_img, imgSize); + cudaMemcpy(dev_img, hst_scene->textures[i].pixels, imgSize, cudaMemcpyHostToDevice); + tempImg.push_back(dev_img); + tempInfo.push_back(glm::vec2(hst_scene->textures[i].xSize, hst_scene->textures[i].ySize)); + } + cudaMemcpy(dev_textures, tempImg.data(), texSize, cudaMemcpyHostToDevice); + cudaMemcpy(dev_texInfo, tempInfo.data(), texInfoSize, cudaMemcpyHostToDevice); + + + //Copy lightIdxs to dev_lightIdxs + ttlLights = hst_scene->lightIdxs.size(); + int lightSize = ttlLights *sizeof(int); + cudaMalloc((void**)&dev_lightIdxs, lightSize); + cudaMemcpy(dev_lightIdxs, hst_scene->lightIdxs.data(), lightSize, cudaMemcpyHostToDevice); + + // dev_image initialize cudaMalloc(&dev_image, pixelcount * sizeof(glm::vec3)); cudaMemset(dev_image, 0, pixelcount * sizeof(glm::vec3)); - // TODO: initialize the above static variables added above checkCUDAError("pathtraceInit"); } void pathtraceFree() { - cudaFree(dev_image); // no-op if dev_image is null - // TODO: clean up the above static variables + cudaFree(dev_bSum); + + cudaFree(dev_incre); + cudaFree(dev_temps); + cudaFree(dev_rays); + cudaFree(dev_rays_temp); + cudaFree(dev_geoms); + cudaFree(dev_mats); + + cudaFree(dev_image);// no-op if dev_image is null + + //for (int i = 0; i < hst_scene->textures.size(); i++) + //{ + // cudaFree(dev_textures[i]); + //} + cudaFree(dev_texInfo); + cudaFree(dev_textures); checkCUDAError("pathtraceFree"); } -/** - * Example function to generate static and test the CUDA-GL interop. - * Delete this once you're done looking at it! - */ -__global__ void generateNoiseDeleteMe(Camera cam, int iter, glm::vec3 *image) { - int x = (blockIdx.x * blockDim.x) + threadIdx.x; - int y = (blockIdx.y * blockDim.y) + threadIdx.y; +__device__ Ray GenerateRayFromCam(Camera cam, int x, int y) +{ + Ray ray_xy; + ray_xy.origin = cam.position; - if (x < cam.resolution.x && y < cam.resolution.y) { - int index = x + (y * cam.resolution.x); + glm::vec3 C_ = cam.view; + glm::vec3 U_ = cam.up; + glm::vec3 A_ = glm::cross(C_, U_); + glm::vec3 B_ = glm::cross(A_, C_); + glm::vec3 M_ = cam.position + C_; - thrust::default_random_engine rng = makeSeededRandomEngine(iter, index, 0); - thrust::uniform_real_distribution u01(0, 1); + float tanPhi = tan(cam.fov.x*PI / 360); + float tanTheta = tanPhi*(float)cam.resolution.x / (float)cam.resolution.y; + glm::vec3 V_ = glm::normalize(B_)*glm::length(C_)*tanPhi; + glm::vec3 H_ = glm::normalize(A_)*glm::length(C_)*tanTheta; - // CHECKITOUT: Note that on every iteration, noise gets added onto - // the image (not replaced). As a result, the image smooths out over - // time, since the output image is the contents of this array divided - // by the number of iterations. - // - // Your renderer will do the same thing, and, over time, it will become - // smoother. - image[index] += glm::vec3(u01(rng)); - } + float Sx = ((float)x + 0.5) / (cam.resolution.x - 1); + float Sy = ((float)y + 0.5) / (cam.resolution.y - 1); + glm::vec3 Pw = M_ + (2 * Sx - 1)*H_ - (2 * Sy - 1)*V_; + glm::vec3 Dir_ = Pw - cam.position; + + ray_xy.direction = glm::normalize(Dir_); + + return ray_xy; +} + +__global__ void kernInitPathRays(Camera cam,Ray * rays,int iter) +{ + int x = (blockIdx.x * blockDim.x) + threadIdx.x; + int y = (blockIdx.y * blockDim.y) + threadIdx.y; + if (x < cam.resolution.x && y < cam.resolution.y) + { + int index = x + (y * cam.resolution.x); + rays[index].pixelIndex = glm::vec2(x,y); + rays[index].imageIndex = index; + rays[index].terminated = false; + rays[index].origin = cam.position; + rays[index].carry = glm::vec3(1,1,1); + + glm::vec3 C_ = cam.view; + glm::vec3 U_ = cam.up; + glm::vec3 A_ = glm::cross(C_, U_); + glm::vec3 B_ = glm::cross(A_, C_); + glm::vec3 M_ = cam.position + C_; + + float tanPhi = tan(cam.fov.x*PI / 180); + float tanTheta = tanPhi*(float)cam.resolution.x / (float)cam.resolution.y; + glm::vec3 V_ = glm::normalize(B_)*glm::length(C_)*tanPhi; + glm::vec3 H_ = glm::normalize(A_)*glm::length(C_)*tanTheta; + + thrust::uniform_real_distribution u01(0, 1); + thrust::default_random_engine rng = makeSeededRandomEngine(iter, index, 1); + + float rdmX = 1.05*(u01(rng) - 0.5); + float rdmY = 1.05*(u01(rng) - 0.5); + //anti-aliasing + float Sx = ((float)x + rdmX) / (cam.resolution.x - 1); + float Sy = ((float)y + rdmY) / (cam.resolution.y - 1); + glm::vec3 Pw = M_ - (2 * Sx - 1)*H_ - (2 * Sy - 1)*V_; + glm::vec3 Dir_ = Pw - cam.position; + + rays[index].direction = glm::normalize(Dir_); + rays[index].lastObjIdx = -1; + rays[index].origMatIdx = -1; + } +} + +__device__ float rayIntersection( + Geom geometry, + Ray r, + glm::vec3& intersectionPoint, + glm::vec3& normal, + int &materIdx, + bool &outside, + glm::vec2& uv + ) +{ + float temp_T = -1; + switch (geometry.type) + { + case SPHERE: + temp_T = sphereIntersectionTest(geometry, r, intersectionPoint, normal,outside,uv); + materIdx = geometry.materialid; + break; + case CUBE: + temp_T = boxIntersectionTest(geometry, r, intersectionPoint, normal, outside,uv); + materIdx = geometry.materialid;// glm::vec3(0, 1, 0); + break; + default: + break; + } + return temp_T; +} + +__global__ void kernComputeRay( + int raysNum, + Camera cam, + Ray * rays, + Material * dev_mat, + glm::vec3**dev_textures, + glm::vec2 * dev_texInfo, + Geom * dev_geo, + int geoNum, + int iter, + int depth) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + //int y = (blockIdx.y * blockDim.y) + threadIdx.y; + //int index = x + (y * cam.resolution.x); + //if (x < cam.resolution.x && y < cam.resolution.y) + if (index < raysNum) + { + if (rays[index].terminated) + { + return; + } + // intersection with objects + glm::vec3 intrPoint; + glm::vec3 intrNormal; + float intrT = -1; + int intrMatIdx; + bool intrOutside; + glm::vec2 intrUV; + + for (int i = 0; i < geoNum; i++) + { + glm::vec3 temp_intrPoint; + glm::vec3 temp_intrNormal; + float temp_T; + int temp_MatIdx; + bool temp_outside; + glm::vec2 temp_uv; + temp_T = rayIntersection(dev_geo[i], rays[index], temp_intrPoint, temp_intrNormal, temp_MatIdx, temp_outside, temp_uv); + if (temp_T < 0) continue; + + if (intrT < 0 || temp_T < intrT && temp_T >0) + { + intrT = temp_T; + intrPoint = temp_intrPoint; + intrNormal = temp_intrNormal; + intrMatIdx = temp_MatIdx; + intrOutside = temp_outside; + intrUV = temp_uv; + } + } + if (intrT > 0)//intersect with obj, update ray + { + thrust::default_random_engine rr = makeSeededRandomEngine(iter, index, depth); + scatterRay(rays[index], intrOutside, intrT, intrPoint, intrNormal, dev_mat[intrMatIdx], dev_textures, dev_texInfo,intrUV, rr); + rays[index].origMatIdx = intrMatIdx; + rays[index].lastObjIdx = intrOutside; + } + else + { + rays[index].terminated = true; + rays[index].carry = glm::vec3(0, 0, 0);// later background color + rays[index].lastObjIdx = -1; + } + + } +} + +__global__ void kernUpdateImage( + int raysNum, + Camera cam, + Ray * rays, + glm::vec3 *image) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + //int y = (blockIdx.y * blockDim.y) + threadIdx.y; + //int index = x + (y * cam.resolution.x); + if (index < raysNum) + { + if (rays[index].terminated) + { + image[rays[index].imageIndex] += rays[index].carry; + rays[index].carry = glm::vec3(0, 0, 0); + } + } + +} + +__global__ void kernFinalImage( + int iter, + int raysNum, + glm::vec3** dev_textures, + Camera cam, Ray * rays, + glm::vec3 *image, + glm::vec2*dev_texInfo, + Geom * dev_geo, + Material * dev_mat, + int * dev_lightIdxs, + int geoNum, + int totalLights) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + //int y = (blockIdx.y * blockDim.y) + threadIdx.y; + //int index = x + (y * cam.resolution.x); + if (index < raysNum) + { + //Direct lighting + //(1) random point on light + // curently, only one box light source + // !!!later : a.multiply lights; b.sphere light + glm::vec3 color(0, 0, 0); + for (int i = 0; i < totalLights; i++) + { + int lightIndex = dev_lightIdxs[i]; + glm::vec4 pointOnLight(0, 0, 0, 1); + thrust::default_random_engine rng = makeSeededRandomEngine(iter, index, 1); + thrust::uniform_real_distribution u01(0, 1); + pointOnLight.x = u01(rng) - 0.5; + pointOnLight.y = u01(rng) - 0.5; + pointOnLight.z = u01(rng) - 0.5; + pointOnLight = dev_geo[lightIndex].transform *pointOnLight; + //(2) surface point (ray.origin) to light_point, anything in between? + glm::vec3 intrPoint; + glm::vec3 intrNormal; + float intrT = -1; + int intrMatIdx; + bool intrOutside; + glm::vec2 intrUV; + + Ray surToLight; + surToLight.origin = rays[index].origin; + surToLight.direction = glm::normalize((glm::vec3)pointOnLight - rays[index].origin); + //!!! later : Function this forloop into rayIntersection. + for (int i = 0; i < geoNum; i++) + { + glm::vec3 temp_intrPoint; + glm::vec3 temp_intrNormal; + float temp_T; + int temp_MatIdx; + bool temp_outside; + glm::vec2 temp_uv; + temp_T = rayIntersection(dev_geo[i], surToLight, temp_intrPoint, temp_intrNormal, temp_MatIdx, temp_outside, temp_uv); + + if (temp_T < 0) continue; + if (intrT < 0 || temp_T < intrT && temp_T >0) + { + intrT = temp_T; + intrPoint = temp_intrPoint; + intrNormal = temp_intrNormal; + intrMatIdx = temp_MatIdx; + intrOutside = temp_outside; + intrUV = temp_uv; + } + } + //(3) if nothing in between, cos ray, calc direct illumination + if (intrMatIdx == lightIndex) + { + //Direct Illumination + //!!! later : reduce bounce + color = dev_mat[lightIndex].emittance*dev_mat[lightIndex].color; + color *= rays[index].carry; + scatterRay(rays[index], intrOutside, intrT, intrPoint, intrNormal, dev_mat[rays[index].origMatIdx], dev_textures, dev_texInfo, intrUV,rng); + color *= max(0.0f, glm::dot(glm::normalize(-rays[index].direction), glm::normalize(surToLight.direction))); + } + } + image[rays[index].imageIndex] += color; + rays[index].terminated = true; + } } +/** + * Example function to generate static and test the CUDA-GL interop. + * Delete this once you're done looking at it! + */ +struct testdelete +{ + __host__ __device__ + bool operator()(const int a) + { + return a==1?false:true; + } +}; +struct is_terminated +{ + __host__ __device__ + bool operator()(const Ray ray_xy) + { + return ray_xy.terminated; + } +}; + /** * Wrapper for the __global__ call that sets up the kernel calls and does a ton * of memory management */ + +__global__ void scan_sharedMem(int *dev_temp, int *Scan_odata) +{ + int n = blockDim.x * 2; + + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + int thid = threadIdx.x; + + //Work-efficient scan with shared memory. + //http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html + extern __shared__ int scan[]; //allocated on invocation + int offset = 1; + scan[2 * thid] = dev_temp[2 * index]; //loat ray.terminated to shared memory : scan + scan[2 * thid + 1] = dev_temp[2 * index + 1]; + + + for (int d = n >> 1; d > 0; d >>= 1) //build sum in place up the tree + { + __syncthreads(); + if (thid>= 1; + __syncthreads(); + if (thid < d) + { + int ai = offset*(2 * thid + 1) - 1; + int bi = offset*(2 * thid + 2) - 1; + + int t = scan[ai]; + scan[ai] = scan[bi]; + scan[bi] += t; + } + } + //__syncthreads(); + + Scan_odata[2 * index] = scan[2 * thid]; //write scan results to device memory + Scan_odata[2 * index + 1] = scan[2 * thid + 1]; +} + +__global__ void blockWise_sum(int *dev_temp,int *dev_scan,int * dev_bSum,int bSize) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + + int origIdx = (index + 1)*(bSize * 2) - 1; + + dev_bSum[index] = dev_temp[origIdx] + dev_scan[origIdx]; +} + +void delete_PrintIntArray(int * array, int length,std::string name) +{ + printf("%s = \n[",name); + for (int i = 0; i < length; i++) + { + printf("%3d ", array[i]); + } + printf("]\n"); +} +__global__ void sum_scan_incre(int * dev_scan,int*dev_incre,int t,int bSize) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + int incrIdx = index / (bSize * 2); + dev_scan[index] += dev_incre[incrIdx]; +} +void ExclusiveScanTraverse(int * dev_inc, int&ttRayNum, int bSize, int *dev_temps) +{ + int halfTtlRays = (int)((ttRayNum + 1) / 2); + int GridSize = (halfTtlRays + bSize - 1) / bSize; + + if (GridSize == 1) //then start step 5 + { + //dev_temps is dev_bIncre + scan_sharedMem << > >(dev_temps, dev_inc); + //scan_sharedMem << > >(dev_temps, dev_scan); + } + else + { + int *dev_scan; + cudaMalloc((void**)&dev_scan, sizeof(int)*ttRayNum); + scan_sharedMem << > >(dev_temps, dev_scan); + + //int *dev_bSum; + //cudaMalloc((void**)&dev_bSum, sizeof(int)*GridSize); + blockWise_sum << <(int)((GridSize + bSize - 1) / bSize), bSize >> >(dev_temps, dev_scan, dev_bSum, bSize); + + //int *dev_incre; + //cudaMalloc((void**)&dev_incre, sizeof(int)*GridSize); + ExclusiveScanTraverse(dev_inc, GridSize, bSize, dev_bSum); + + GridSize = (ttRayNum + bSize - 1) / bSize; + sum_scan_incre << > >(dev_scan, dev_inc, ttRayNum, bSize); + + cudaMemcpy(dev_inc, dev_scan, sizeof(int)*ttRayNum, cudaMemcpyDeviceToDevice); + cudaFree(dev_scan); + //cudaFree(dev_incre); + } +} + +__global__ void getUnterminatedTemp(Ray*ray,int*temp,int ttlRay) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + //if (index < ttlRay) + temp[index] = ray[index].terminated ? 0 : 1; +} + +__global__ void streamCmp_scatter(Ray*irays, Ray*orays, int*tempBool, int * scanResult,int totalNum) +{ + int index = (blockIdx.x * blockDim.x) + threadIdx.x; + if (index >= totalNum) return; + if (!irays[index].terminated) + { + orays[scanResult[index]] = irays[index]; + } +} + void pathtrace(uchar4 *pbo, int frame, int iter) { const int traceDepth = hst_scene->state.traceDepth; const Camera &cam = hst_scene->state.camera; @@ -130,38 +601,127 @@ void pathtrace(uchar4 *pbo, int frame, int iter) { (cam.resolution.x + blockSize2d.x - 1) / blockSize2d.x, (cam.resolution.y + blockSize2d.y - 1) / blockSize2d.y); - /////////////////////////////////////////////////////////////////////////// - - // Recap: - // * Initialize array of path rays (using rays that come out of the camera) - // * You can pass the Camera object to that kernel. - // * Each path ray is a (ray, color) pair, where color starts as the - // multiplicative identity, white = (1, 1, 1). - // * For debugging, you can output your ray directions as colors. - // * For each depth: - // * Compute one new (ray, color) pair along each path (using scatterRay). - // Note that many rays will terminate by hitting a light or hitting - // nothing at all. You'll have to decide how to represent your path rays - // and how you'll mark terminated rays. - // * Color is attenuated (multiplied) by reflections off of any object - // surface. - // * You can debug your ray-scene intersections by displaying various - // values as colors, e.g., the first surface normal, the first bounced - // ray direction, the first unlit material color, etc. - // * Add all of the terminated rays' results into the appropriate pixels. - // * Stream compact away all of the terminated paths. - // You may use either your implementation or `thrust::remove_if` or its - // cousins. - // * Note that you can't really use a 2D kernel launch any more - switch - // to 1D. - // * Finally, handle all of the paths that still haven't terminated. - // (Easy way is to make them black or background-colored.) - - // TODO: perform one iteration of path tracing - - generateNoiseDeleteMe<<>>(cam, iter, dev_image); - - /////////////////////////////////////////////////////////////////////////// + //(1) Initialize array of path rays + kernInitPathRays <<>>(cam, dev_rays, iter); + + //(2) For each depth: + int geoNum = hst_scene->geoms.size(); + int totalRays = cam.resolution.x*cam.resolution.y; + int why = totalRays;// totalRays; + thrust::default_random_engine rng = makeSeededRandomEngine(iter, 1, traceDepth); + bool raySel = true; + for (int i = 0; i < traceDepth; i++) + { + int bSize = 128;// blockSize.x*blockSize.y*blockSize.z; + dim3 fullBlocksPerGrid((totalRays + bSize - 1) / bSize); + // a. Compute one ray along each path + if (raySel) + { + kernComputeRay << > >(totalRays, cam, dev_rays, dev_mats, dev_textures,dev_texInfo,dev_geoms, geoNum, iter, i); + // b. Add all terminated rays results into pixels + kernUpdateImage << > >(totalRays, cam, dev_rays, dev_image); + // c. Stream compact away/thrust::remove_if all terminated paths. + } + else + { + kernComputeRay << > >(totalRays, cam, dev_rays_temp, dev_mats,dev_textures,dev_texInfo, dev_geoms, geoNum, iter, i); + // b. Add all terminated rays results into pixels + kernUpdateImage << > >(totalRays, cam, dev_rays_temp, dev_image); + // c. Stream compact away/thrust::remove_if all terminated paths. + } + + if (doStreamCompact) + { + int ttRayNum = why; + if (ttRayNum == 0) continue; + + bSize = 64; + + int GridSize = (ttRayNum + bSize - 1) / bSize; + + //int *hst_temp = new int[ttRayNum]; + /*for (int i = 0; i < ttRayNum; i++) + { + thrust::uniform_real_distribution u01(0, 1); + + if (u01(rng)>0.5) + { + hst_temp[i] = 1; + } + else hst_temp[i] = 0; + + } + */ + //printf("\n\n/******* Test *******/\n"); + if (raySel) + getUnterminatedTemp << > >(dev_rays, dev_temps, ttRayNum); + else + getUnterminatedTemp << > >(dev_rays_temp, dev_temps, ttRayNum); + + //cudaMemcpy(dev_temps, hst_temp, sizeof(int)*ttRayNum, cudaMemcpyHostToDevice); + //cudaMemcpy( hst_temp,dev_temps, sizeof(int)*ttRayNum, cudaMemcpyDeviceToHost); + //delete_PrintIntArray(hst_temp, ttRayNum, "1. original"); //dev_temp + int lastInOrig; + cudaMemcpy(&lastInOrig, dev_temps + ttRayNum - 1, sizeof(int), cudaMemcpyDeviceToHost); + //printf("lastInOrig:%d\n", lastInOrig); + //int *dev_temps_thrust; + //cudaMalloc((void**)&dev_temps_thrust, sizeof(int)*ttRayNum); + //getUnterminatedTemp << > >(dev_rays, dev_temps_thrust, ttRayNum); + //cudaMemcpy(dev_temps_thrust, hst_temp, sizeof(int)*ttRayNum, cudaMemcpyHostToDevice); + + //printf("before scatter totalNum: %d\n", ttRayNum); + ExclusiveScanTraverse(dev_incre,ttRayNum, bSize, dev_temps); + checkCUDAError("ExclusiveScanTraverse"); + /* + thrust::device_ptr RayStart(dev_temps_thrust); + thrust::device_ptr newRayEnd = RayStart + ttRayNum; + newRayEnd = thrust::remove_if(RayStart, newRayEnd, testdelete()); + int thrustTT = (int)(newRayEnd - RayStart); + */ + checkCUDAError("bbb"); + int lastInScan; + cudaMemcpy(&lastInScan, dev_incre + ttRayNum - 1, sizeof(int), cudaMemcpyDeviceToHost); + /* + //thrust::remove_if stream compact: + thrust::device_ptr RayStart(dev_rays); + thrust::device_ptr newRayEnd = RayStart + ttRayNum; + newRayEnd = thrust::remove_if(RayStart, newRayEnd, is_terminated()); + int thrustTT = (int)(newRayEnd - RayStart); + */ + ttRayNum = lastInScan + lastInOrig; + int thrustTT = 0; + //printf("after scatter totalNum: %d,\t thrust: %d\n\n", ttRayNum,thrustTT); + //why = ttRayNum; + //totalRays = ttRayNum; + //Ray * dev_rays_tempt; + //cudaMalloc((void**)&dev_rays_tempt, sizeof(Ray)*why); + if (raySel) + streamCmp_scatter << > >(dev_rays, dev_rays_temp, dev_temps, dev_incre, why); + else + streamCmp_scatter << > >(dev_rays_temp, dev_rays, dev_temps, dev_incre, why); + + raySel = !raySel; + //printf(""); + //cudaMemcpy( hst_temp, dev_incre,sizeof(int)*ttRayNum, cudaMemcpyDeviceToHost); + //delete_PrintIntArray(hst_temp, ttRayNum, "final. scan"); //dev_temp + //printf("Before Stream Compaction: %d rays\t,",why); + why = ttRayNum; + //printf("After Stream Compaction: %d rays\t\n", why); + totalRays = why; + } + } + //(3) Handle all not terminated + int bSize = 128;// blockSize.x*blockSize.y*blockSize.z; + dim3 fullBlocksPerGrid((totalRays + bSize - 1) / bSize); + if (raySel) + { + kernFinalImage << > >(iter, totalRays,dev_textures, cam, dev_rays, dev_image, dev_texInfo,dev_geoms, dev_mats,dev_lightIdxs, geoNum, ttlLights); + } + else + { + kernFinalImage << > >(iter, totalRays,dev_textures, cam, dev_rays_temp, dev_image, dev_texInfo,dev_geoms, dev_mats, dev_lightIdxs, geoNum, ttlLights); + } + // Send results to OpenGL buffer for rendering sendImageToPBO<<>>(pbo, cam.resolution, iter, dev_image); @@ -171,4 +731,4 @@ void pathtrace(uchar4 *pbo, int frame, int iter) { pixelcount * sizeof(glm::vec3), cudaMemcpyDeviceToHost); checkCUDAError("pathtrace"); -} +} \ No newline at end of file diff --git a/src/pathtrace.h b/src/pathtrace.h index 1241227..ced2717 100644 --- a/src/pathtrace.h +++ b/src/pathtrace.h @@ -3,6 +3,6 @@ #include #include "scene.h" -void pathtraceInit(Scene *scene); +void pathtraceInit(Scene *scene, bool strCmpt = false); void pathtraceFree(); void pathtrace(uchar4 *pbo, int frame, int iteration); diff --git a/src/scene.cpp b/src/scene.cpp index 5804ce3..db7b56f 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -153,8 +153,9 @@ int Scene::loadMaterial(string materialid) { cout << "Loading Material " << id << "..." << endl; Material newMaterial; + string textureFile = "NULL"; //load static properties - for (int i = 0; i < 7; i++) { + for (int i = 0; i < 9; i++) { string line; utilityCore::safeGetline(fp_in, line); vector tokens = utilityCore::tokenizeString(line); @@ -174,8 +175,26 @@ int Scene::loadMaterial(string materialid) { newMaterial.indexOfRefraction = atof(tokens[1].c_str()); } else if (strcmp(tokens[0].c_str(), "EMITTANCE") == 0) { newMaterial.emittance = atof(tokens[1].c_str()); - } + }else if (strcmp(tokens[0].c_str(), "BSSRDF") == 0) { + newMaterial.bssrdf = atof(tokens[1].c_str()); + } + else if (strcmp(tokens[0].c_str(), "TEX") == 0) { + //newMaterial.bssrdf = atof(tokens[1].c_str()); + textureFile = tokens[1].c_str(); + if (textureFile != "NULL") + { + newMaterial.TexIdx = textures.size(); + image newTexture(textureFile); + textures.push_back(newTexture); + } + else newMaterial.TexIdx = -1; + } } + if (newMaterial.emittance>0) + { + lightIdx = materials.size(); + lightIdxs.push_back(lightIdx); + } materials.push_back(newMaterial); return 1; } diff --git a/src/scene.h b/src/scene.h index f29a917..7b453ae 100644 --- a/src/scene.h +++ b/src/scene.h @@ -7,6 +7,7 @@ #include "glm/glm.hpp" #include "utilities.h" #include "sceneStructs.h" +#include "image.h" using namespace std; @@ -20,7 +21,10 @@ class Scene { Scene(string filename); ~Scene(); + int lightIdx = 0;//??? multilight + std::vector lightIdxs; std::vector geoms; std::vector materials; + std::vector textures; RenderState state; }; diff --git a/src/sceneStructs.h b/src/sceneStructs.h index baa2e30..de92678 100644 --- a/src/sceneStructs.h +++ b/src/sceneStructs.h @@ -13,6 +13,12 @@ enum GeomType { struct Ray { glm::vec3 origin; glm::vec3 direction; + glm::vec2 pixelIndex; + int imageIndex; + bool terminated = false; + glm::vec3 carry = glm::vec3(1, 1, 1); + int origMatIdx = -1; + int lastObjIdx = -1; }; struct Geom { @@ -36,6 +42,8 @@ struct Material { float hasRefractive; float indexOfRefraction; float emittance; + float bssrdf; + int TexIdx; }; struct Camera {