diff --git a/.gitignore b/.gitignore index bec7ce5..3c4dd4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +# VS +Debug/ +Release/ +ipch/ +*.sdf + # General builds/ diff --git a/MedianNoise.png b/MedianNoise.png new file mode 100644 index 0000000..5ec8bc4 Binary files /dev/null and b/MedianNoise.png differ diff --git a/MedianRef.png b/MedianRef.png new file mode 100644 index 0000000..121f37d Binary files /dev/null and b/MedianRef.png differ diff --git a/MedianSubjectBetter.png b/MedianSubjectBetter.png new file mode 100644 index 0000000..5c8896a Binary files /dev/null and b/MedianSubjectBetter.png differ diff --git a/PerformStreamCompact.xls b/PerformStreamCompact.xls new file mode 100644 index 0000000..5950435 Binary files /dev/null and b/PerformStreamCompact.xls differ diff --git a/README.md b/README.md index ae6088d..b40cee1 100644 --- a/README.md +++ b/README.md @@ -94,180 +94,30 @@ For each 'extra feature' you must provide the following analysis : should give a roadmap of how to further optimize and why you believe this is the next step) -## 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 pathtracing - 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. +## Implementation +All required features are implemented; -* 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. +2 extra features, Refraction and Subsurface scattering are also provided. -* 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). +![Alt text](https://github.com/chiwsy/Project3-Pathtracer/blob/master/test.png) -You will also want to familiarize yourself with: +![Alt text](https://github.com/chiwsy/Project3-Pathtracer/blob/master/test_mark.png) -* 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 +![Alt text](https://github.com/chiwsy/Project3-Pathtracer/blob/master/compare.png) -## 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: +These 3 images show the features implemented and the performance of the render with and without stream compaction. -* 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. +The second figure marks the features. -## SCENE FORMAT -This project uses a custom scene description format. -Scene 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. +For the performance parts, I tested various parameters of trace depth and plot an curve to show the relationship of the stream compaction have on the overall performance. We can see that with larger trace depth, larger than 10, using stream compact can largely reduce the rendering time. This is because that most of the rays are killed before they reached the trace depth. -Materials are defined in the following fashion: +As the images are very noise, especially when the iteration is very low, I think we can use some simple filter to improve the quality of the image. Even in the final version, after 5000 iteration, there exists irregular points on the output image. -* 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. +![Alt text](https://github.com/chiwsy/Project3-Pathtracer/blob/master/MedianNoise.png) -Cameras are defined in the following fashion: +This image shows the initial condition when there are only 20 iterations. The original image on the left is very noisy and we can see a number of yellow dots on the reflective surface. In order to remove such salt-and-pepper-like noise, a common method is using median filter. The filtered image has a better PSNR value, the objective criteria for image quality. However, the visual effect is no much better than the original one. If we use this image instead of the original one, I think we can have a faster convergence towards the referrence image which iterated for 5000 times. -* 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 +![Alt text](https://github.com/chiwsy/Project3-Pathtracer/blob/master/MedianSubjectBetter.png) -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 scene file setting up two frames inside of a Cornell Box can be -found in the scenes/ directory. - -For meshes, note that the base code will only read in .obj files. For more -information on the .obj specification see http://en.wikipedia.org/wiki/Wavefront_.obj_file. - -An example of a mesh object is as follows: - -OBJECT 0 -mesh tetra.obj -material 0 -frame 0 -TRANS 0 5 -5 -ROTAT 0 90 0 -SCALE .01 10 10 - -Check the Google group for some sample .obj files of varying complexity. - -## 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 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 Harmony, - harmoli+cis565@seas.upenn.com, 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 -Please change the README to reflect the answers to the questions we have posed -above. Remember: -* 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 e 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 good to show case this with a video to - show interactivity. If you do so, please include a link. - -Be sure to open a pull request and to send Harmony your grade and why you -believe this is the grade you should get. +This image shows using median filter on the final result. After 5000 iteration, the quality of the image is relatively high but still, there are irregular points. The right side has relatively low PSNR value but as far as I am concered, I think the right image has better quality since the image is more clean than the left one. diff --git a/compare.png b/compare.png new file mode 100644 index 0000000..3f096d7 Binary files /dev/null and b/compare.png differ diff --git a/data/scenes/error.txt b/data/scenes/error.txt new file mode 100644 index 0000000..e69de29 diff --git a/data/scenes/sampleScene.txt b/data/scenes/sampleScene.txt index 6a9f5cc..5b35eb5 100644 --- a/data/scenes/sampleScene.txt +++ b/data/scenes/sampleScene.txt @@ -2,7 +2,7 @@ MATERIAL 0 //white diffuse RGB 1 1 1 SPECEX 0 SPECRGB 1 1 1 -REFL 0 +REFL .5 REFR 0 REFRIOR 0 SCATTER 0 @@ -47,10 +47,10 @@ RSCTCOEFF 0 EMITTANCE 0 MATERIAL 4 //white glossy -RGB 1 1 1 +RGB .7 .7 .5 SPECEX 0 SPECRGB 1 1 1 -REFL 0 +REFL 0.95 REFR 0 REFRIOR 2 SCATTER 0 @@ -63,7 +63,7 @@ RGB 0 0 0 SPECEX 0 SPECRGB 1 1 1 REFL 0 -REFR 1 +REFR .5 REFRIOR 2.2 SCATTER 0 ABSCOEFF .02 5.1 5.7 @@ -72,7 +72,7 @@ EMITTANCE 0 MATERIAL 6 //green glossy RGB .15 .48 .09 -SPECEX 0 +SPECEX 2 SPECRGB 1 1 1 REFL 0 REFR 0 @@ -104,7 +104,43 @@ REFRIOR 0 SCATTER 0 ABSCOEFF 0 0 0 RSCTCOEFF 0 -EMITTANCE 15 +EMITTANCE 25 + +MATERIAL 9 //Scattering +RGB .15 .48 .09 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0 +REFR 0 +REFRIOR 2 +SCATTER 0.7 +ABSCOEFF 0.9 0.1 0.3 +RSCTCOEFF 2.3 +EMITTANCE 0 + +MATERIAL 10 //Yellow reflective +RGB .7 .7 .3 +SPECEX 0 +SPECRGB 1 1 1 +REFL 0.95 +REFR 0 +REFRIOR 0 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 + +MATERIAL 11 //gray specular +RGB .7 .7 .7 +SPECEX 4 +SPECRGB 1 1 1 +REFL 0.1 +REFR 0 +REFRIOR 2 +SCATTER 0 +ABSCOEFF 0 0 0 +RSCTCOEFF 0 +EMITTANCE 0 CAMERA RES 800 800 @@ -118,7 +154,7 @@ UP 0 1 0 OBJECT 0 cube -material 0 +material 2 frame 0 TRANS 0 0 0 ROTAT 0 0 90 @@ -126,7 +162,7 @@ SCALE .01 10 10 OBJECT 1 cube -material 0 +material 10 frame 0 TRANS 0 5 -5 ROTAT 0 90 0 @@ -134,7 +170,7 @@ SCALE .01 10 10 OBJECT 2 cube -material 0 +material 4 frame 0 TRANS 0 10 0 ROTAT 0 0 90 @@ -150,7 +186,7 @@ SCALE .01 10 10 OBJECT 4 cube -material 2 +material 1 frame 0 TRANS 5 5 0 ROTAT 0 0 0 @@ -158,25 +194,25 @@ SCALE .01 10 10 OBJECT 5 sphere -material 4 +material 5 frame 0 -TRANS 0 2 0 +TRANS 0 6 5 ROTAT 0 180 0 -SCALE 3 3 3 +SCALE 1 1 1 OBJECT 6 sphere -material 3 +material 6 frame 0 -TRANS 2 5 2 +TRANS 2 2 6 ROTAT 0 180 0 SCALE 2.5 2.5 2.5 OBJECT 7 sphere -material 6 +material 5 frame 0 -TRANS -2 5 -2 +TRANS -2 2 -2 ROTAT 0 180 0 SCALE 3 3 3 @@ -187,4 +223,44 @@ material 8 frame 0 TRANS 0 10 0 ROTAT 0 0 90 -SCALE .3 3 3 \ No newline at end of file +SCALE .3 3 3 + +OBJECT 9 +sphere +material 9 +frame 0 +TRANS -3 6 -2 +ROTAT 0 180 0 +SCALE 2 3 1 + +OBJECT 10 +sphere +material 4 +frame 0 +TRANS 4 4 1 +ROTAT 0 0 0 +SCALE 2 2 2 + +OBJECT 11 +sphere +material 10 +frame 0 +TRANS 0 2 1 +ROTAT 0 0 0 +SCALE 1 1 1 + +OBJECT 12 +sphere +material 5 +frame 0 +TRANS 0 2 3 +ROTAT 0 0 0 +SCALE 2 2 2 + +OBJECT 13 +sphere +material 11 +frame 0 +TRANS 3 2 -2 +ROTAT 0 0 0 +SCALE 2 2 2 \ No newline at end of file diff --git a/img/0010iter.png b/img/0010iter.png new file mode 100644 index 0000000..9ee1df8 Binary files /dev/null and b/img/0010iter.png differ diff --git a/img/0020iter.png b/img/0020iter.png new file mode 100644 index 0000000..d1ce2e7 Binary files /dev/null and b/img/0020iter.png differ diff --git a/img/0050iter.png b/img/0050iter.png new file mode 100644 index 0000000..35c3bb7 Binary files /dev/null and b/img/0050iter.png differ diff --git a/img/0099iter.png b/img/0099iter.png new file mode 100644 index 0000000..d19b728 Binary files /dev/null and b/img/0099iter.png differ diff --git a/img/0255iter.png b/img/0255iter.png new file mode 100644 index 0000000..f347f14 Binary files /dev/null and b/img/0255iter.png differ diff --git a/img/0515iter.png b/img/0515iter.png new file mode 100644 index 0000000..4416287 Binary files /dev/null and b/img/0515iter.png differ diff --git a/img/1035iter.png b/img/1035iter.png new file mode 100644 index 0000000..9d2f365 Binary files /dev/null and b/img/1035iter.png differ diff --git a/img/2140iter.png b/img/2140iter.png new file mode 100644 index 0000000..af6b761 Binary files /dev/null and b/img/2140iter.png differ diff --git a/img/4134iter.png b/img/4134iter.png new file mode 100644 index 0000000..7e1574f Binary files /dev/null and b/img/4134iter.png differ diff --git a/img/5000iter.png b/img/5000iter.png new file mode 100644 index 0000000..1129b60 Binary files /dev/null and b/img/5000iter.png differ diff --git a/medianFilter/MedianNoise.png b/medianFilter/MedianNoise.png new file mode 100644 index 0000000..5ec8bc4 Binary files /dev/null and b/medianFilter/MedianNoise.png differ diff --git a/medianFilter/MedianRef.png b/medianFilter/MedianRef.png new file mode 100644 index 0000000..121f37d Binary files /dev/null and b/medianFilter/MedianRef.png differ diff --git a/medianFilter/MedianSubjectBetter.png b/medianFilter/MedianSubjectBetter.png new file mode 100644 index 0000000..5c8896a Binary files /dev/null and b/medianFilter/MedianSubjectBetter.png differ diff --git a/medianFilter/PSNR.m b/medianFilter/PSNR.m new file mode 100644 index 0000000..07b5214 --- /dev/null +++ b/medianFilter/PSNR.m @@ -0,0 +1,94 @@ +function decibels=PSNR(A,B) + +% PURPOSE: To find the PSNR (peak signal-to-noise ratio) between two +% intensity images A and B, each having values in the interval +% [0,1]. The answer is in decibels (dB). +% +% There is also a provision, in EXAMPLE 3 below, for images +% stored in the interval [0,255], i.e. 256 gray levels. +% +% SYNOPSIS: PSNR(A,B) +% +% DESCRIPTION: The following is quoted from "Fractal Image Compression", +% by Yuval Fisher et al.,(Springer Verlag, 1995), +% section 2.4, "Pixelized Data". +% +% "...PSNR is used to measure the difference between two +% images. It is defined as +% +% PSNR = 20 * log10(b/rms) +% +% where b is the largest possible value of the signal +% (typically 255 or 1), and rms is the root mean square +% difference between two images. The PSNR is given in +% decibel units (dB), which measure the ratio of the peak +% signal and the difference between two images. An increase +% of 20 dB corresponds to a ten-fold decrease in the rms +% difference between two images. +% +% There are many versions of signal-to-noise ratios, but +% the PSNR is very common in image processing, probably +% because it gives better-sounding numbers than other +% measures." +% +% EXAMPLE 1: load clown +% A = ind2gray(X,map); % Convert to an intensity image in [0,1]. +% B = 0.95 * A; % Make B close to, but different from, A. +% PSNR(A,B) % ---> "PSNR = +33.49 dB" +% +% EXAMPLE 2: A = rand(256); % A is a random 256 X 256 matrix in [0,1]. +% B = 0.9 * A; % Make B close to, but different from, A. +% PSNR(A,B) % ---> "PSNR = +24.76 dB (approx)" +% +% EXAMPLE 3: For images with 256 gray levels: this function PSNR was +% originally written for matrix-values between 0 and 1, +% because of MATLAB's preference for that interval. +% +% However, suppose the matrix has values in [0,255]. Taking +% Example 1 above, we could change the image to 256 gray levels. +% +% load clown +% A = ind2gray(X,map); % Convert to intensity image in [0,1] +% AA = uint8(255*A); % Change to integers in [0,255] +% BB = 0.95*AA; % Make BB close to AA. +% +% Now we must alter the code for this new case. Comment out the +% existing program (using %) and uncomment the alternative +% underneath it. +% +% PSNR(AA,BB) % ---> "PSNR = +33.56 dB" +% +% Note the slightly different result from Example 1, because +% decimal values were rounded into integers. + +if A == B + %error('Images are identical: PSNR has infinite value') + decibels=Inf; + return; +end + +max2_A = max(max(A)); +max3_B = max(max(max(B))); +min2_A = min(min(A)); +min2_B = min(min(B)); + +error_diff = A - B; +decibels = 20*log10(double(max3_B)/(sqrt(mean(mean(mean(error_diff.^2)))))); +disp(sprintf('PSNR = +%5.2f dB',decibels)) + +% if A == B +% error('Images are identical: PSNR has infinite value') +% end + +% max2_A = max(max(A)); +% max2_B = max(max(B)); +% min2_A = min(min(A)); +% min2_B = min(min(B)); +% +% if max2_A > 255 || max2_B > 255 || min2_A < 0 || min2_B < 0 +% error('input matrices must have values in the interval [0,255]') +% end + +% error_diff = A - B; +% decibels = 20*log10(255/(sqrt(mean(mean(error_diff.^2))))); +% disp(sprintf('PSNR = +%5.2f dB',decibels)) \ No newline at end of file diff --git a/medianFilter/img/0010iter.png b/medianFilter/img/0010iter.png new file mode 100644 index 0000000..9ee1df8 Binary files /dev/null and b/medianFilter/img/0010iter.png differ diff --git a/medianFilter/img/0020iter.png b/medianFilter/img/0020iter.png new file mode 100644 index 0000000..d1ce2e7 Binary files /dev/null and b/medianFilter/img/0020iter.png differ diff --git a/medianFilter/img/0050iter.png b/medianFilter/img/0050iter.png new file mode 100644 index 0000000..35c3bb7 Binary files /dev/null and b/medianFilter/img/0050iter.png differ diff --git a/medianFilter/img/0099iter.png b/medianFilter/img/0099iter.png new file mode 100644 index 0000000..d19b728 Binary files /dev/null and b/medianFilter/img/0099iter.png differ diff --git a/medianFilter/img/0255iter.png b/medianFilter/img/0255iter.png new file mode 100644 index 0000000..f347f14 Binary files /dev/null and b/medianFilter/img/0255iter.png differ diff --git a/medianFilter/img/0515iter.png b/medianFilter/img/0515iter.png new file mode 100644 index 0000000..4416287 Binary files /dev/null and b/medianFilter/img/0515iter.png differ diff --git a/medianFilter/img/1035iter.png b/medianFilter/img/1035iter.png new file mode 100644 index 0000000..9d2f365 Binary files /dev/null and b/medianFilter/img/1035iter.png differ diff --git a/medianFilter/img/2140iter.png b/medianFilter/img/2140iter.png new file mode 100644 index 0000000..af6b761 Binary files /dev/null and b/medianFilter/img/2140iter.png differ diff --git a/medianFilter/img/4134iter.png b/medianFilter/img/4134iter.png new file mode 100644 index 0000000..7e1574f Binary files /dev/null and b/medianFilter/img/4134iter.png differ diff --git a/medianFilter/img/5000iter.png b/medianFilter/img/5000iter.png new file mode 100644 index 0000000..1129b60 Binary files /dev/null and b/medianFilter/img/5000iter.png differ diff --git a/medianFilter/medianf.m b/medianFilter/medianf.m new file mode 100644 index 0000000..31d5b3c --- /dev/null +++ b/medianFilter/medianf.m @@ -0,0 +1,26 @@ +name=dir('./img'); +[m,n]=size(name); +hold on +ref=imread(['./img/' name(m).name]); +h=fspecial('average', 3); +for i=3:m + figure; + img=imread(['./img/' name(i).name]); + subplot(1,2,1) + imshow(img,[]); + p=PSNR(img,ref); + + title(['Original PSNR=' num2str(p)]); +% img(:,:,1)=imfilter(img(:,:,1),h,'symmetric'); +% img(:,:,2)=imfilter(img(:,:,2),h,'symmetric'); +% img(:,:,3)=imfilter(img(:,:,3),h,'symmetric'); + img(:,:,1)=medfilt2(img(:,:,1),[5,5],'symmetric'); + img(:,:,2)=medfilt2(img(:,:,2),[5,5],'symmetric'); + img(:,:,3)=medfilt2(img(:,:,3),[5,5],'symmetric'); + subplot(1,2,2) + imshow(img,[]); + p=PSNR(img,ref); + + title(['Midian Filter PSNR=' num2str(p)]); + imwrite(img,['./out/filtered' name(i).name]); +end \ No newline at end of file diff --git a/medianFilter/out/filtered0010iter.png b/medianFilter/out/filtered0010iter.png new file mode 100644 index 0000000..6c461f4 Binary files /dev/null and b/medianFilter/out/filtered0010iter.png differ diff --git a/medianFilter/out/filtered0020iter.png b/medianFilter/out/filtered0020iter.png new file mode 100644 index 0000000..c14986f Binary files /dev/null and b/medianFilter/out/filtered0020iter.png differ diff --git a/medianFilter/out/filtered0050iter.png b/medianFilter/out/filtered0050iter.png new file mode 100644 index 0000000..d2874fa Binary files /dev/null and b/medianFilter/out/filtered0050iter.png differ diff --git a/medianFilter/out/filtered0099iter.png b/medianFilter/out/filtered0099iter.png new file mode 100644 index 0000000..20b7cec Binary files /dev/null and b/medianFilter/out/filtered0099iter.png differ diff --git a/medianFilter/out/filtered0255iter.png b/medianFilter/out/filtered0255iter.png new file mode 100644 index 0000000..2368e06 Binary files /dev/null and b/medianFilter/out/filtered0255iter.png differ diff --git a/medianFilter/out/filtered0515iter.png b/medianFilter/out/filtered0515iter.png new file mode 100644 index 0000000..4231e65 Binary files /dev/null and b/medianFilter/out/filtered0515iter.png differ diff --git a/medianFilter/out/filtered1035iter.png b/medianFilter/out/filtered1035iter.png new file mode 100644 index 0000000..e2d737e Binary files /dev/null and b/medianFilter/out/filtered1035iter.png differ diff --git a/medianFilter/out/filtered2140iter.png b/medianFilter/out/filtered2140iter.png new file mode 100644 index 0000000..78b65c0 Binary files /dev/null and b/medianFilter/out/filtered2140iter.png differ diff --git a/medianFilter/out/filtered4134iter.png b/medianFilter/out/filtered4134iter.png new file mode 100644 index 0000000..299fe18 Binary files /dev/null and b/medianFilter/out/filtered4134iter.png differ diff --git a/medianFilter/out/filtered5000iter.png b/medianFilter/out/filtered5000iter.png new file mode 100644 index 0000000..ba89198 Binary files /dev/null and b/medianFilter/out/filtered5000iter.png differ diff --git a/out/filtered_PSNR_34.75820020iter.png b/out/filtered_PSNR_34.75820020iter.png new file mode 100644 index 0000000..629bb85 Binary files /dev/null and b/out/filtered_PSNR_34.75820020iter.png differ diff --git a/out/filtered_PSNR_35.07450099iter.png b/out/filtered_PSNR_35.07450099iter.png new file mode 100644 index 0000000..2cc4ca9 Binary files /dev/null and b/out/filtered_PSNR_35.07450099iter.png differ diff --git a/out/filtered_PSNR_35.16310050iter.png b/out/filtered_PSNR_35.16310050iter.png new file mode 100644 index 0000000..b3a918d Binary files /dev/null and b/out/filtered_PSNR_35.16310050iter.png differ diff --git a/out/filtered_PSNR_35.23182140iter.png b/out/filtered_PSNR_35.23182140iter.png new file mode 100644 index 0000000..61385bb Binary files /dev/null and b/out/filtered_PSNR_35.23182140iter.png differ diff --git a/out/filtered_PSNR_35.24220255iter.png b/out/filtered_PSNR_35.24220255iter.png new file mode 100644 index 0000000..d6e9dff Binary files /dev/null and b/out/filtered_PSNR_35.24220255iter.png differ diff --git a/out/filtered_PSNR_35.43660515iter.png b/out/filtered_PSNR_35.43660515iter.png new file mode 100644 index 0000000..ddac420 Binary files /dev/null and b/out/filtered_PSNR_35.43660515iter.png differ diff --git a/out/filtered_PSNR_35.55811035iter.png b/out/filtered_PSNR_35.55811035iter.png new file mode 100644 index 0000000..a514775 Binary files /dev/null and b/out/filtered_PSNR_35.55811035iter.png differ diff --git a/out/filtered_PSNR_36.45524134iter.png b/out/filtered_PSNR_36.45524134iter.png new file mode 100644 index 0000000..f5e5ebc Binary files /dev/null and b/out/filtered_PSNR_36.45524134iter.png differ diff --git a/out/filtered_PSNR_36.54240010iter.png b/out/filtered_PSNR_36.54240010iter.png new file mode 100644 index 0000000..9eac9e9 Binary files /dev/null and b/out/filtered_PSNR_36.54240010iter.png differ diff --git a/out/filtered_PSNR_39.45685000iter.png b/out/filtered_PSNR_39.45685000iter.png new file mode 100644 index 0000000..4a8edd2 Binary files /dev/null and b/out/filtered_PSNR_39.45685000iter.png differ diff --git a/src/interactions.h b/src/interactions.h index 7bf6fab..0c459d4 100644 --- a/src/interactions.h +++ b/src/interactions.h @@ -40,13 +40,23 @@ __host__ __device__ bool calculateScatterAndAbsorption(ray& r, float& depth, Abs // TODO (OPTIONAL): IMPLEMENT THIS FUNCTION __host__ __device__ glm::vec3 calculateTransmissionDirection(glm::vec3 normal, glm::vec3 incident, float incidentIOR, float transmittedIOR) { - return glm::vec3(0,0,0); + float n12 = incidentIOR / transmittedIOR; + + float tmp = 1.0f - n12 * n12 * (1.0f - pow(glm::dot(normal, incident), 2)); + + if(tmp >= 0.0f){ + return glm::normalize((-n12 * glm::dot(normal, incident) - sqrt(tmp)) * normal + n12 * incident); + } + else + { + return calculateReflectionDirection(normal, incident); + } } // TODO (OPTIONAL): IMPLEMENT THIS FUNCTION __host__ __device__ glm::vec3 calculateReflectionDirection(glm::vec3 normal, glm::vec3 incident) { //nothing fancy here - return glm::vec3(0,0,0); + return glm::normalize(incident - 2.0f * normal * (glm::dot(incident, normal)));; } // TODO (OPTIONAL): IMPLEMENT THIS FUNCTION @@ -55,6 +65,25 @@ __host__ __device__ Fresnel calculateFresnel(glm::vec3 normal, glm::vec3 inciden fresnel.reflectionCoefficient = 1; fresnel.transmissionCoefficient = 0; + if(transmittedIOR == 0.0f) + return fresnel; + + float n1_n2 = incidentIOR / transmittedIOR; + + float cosI = - glm::dot(incident, normal); + float sin = (n1_n2 * n1_n2) * (1 - pow(cosI,2)); + + if(1 - sin < 0.f) + return fresnel; + + float cos = sqrt(1.0f - sin); + + float r1 = pow(((incidentIOR * cosI - transmittedIOR * cos) / (incidentIOR * cosI + transmittedIOR * cos)), 2); + + float r2 = pow(((incidentIOR * cos - transmittedIOR * cosI) / (incidentIOR * cos + transmittedIOR * cos)), 2); + fresnel.reflectionCoefficient = (r1 + r2) / 2.0f; + fresnel.transmissionCoefficient = 1.0f - fresnel.reflectionCoefficient; + return fresnel; } diff --git a/src/intersections.h b/src/intersections.h index c9eafb6..89133bc 100644 --- a/src/intersections.h +++ b/src/intersections.h @@ -57,7 +57,15 @@ __host__ __device__ glm::vec3 multiplyMV(cudaMat4 m, glm::vec4 v){ r.z = (m.z.x*v.x)+(m.z.y*v.y)+(m.z.z*v.z)+(m.z.w*v.w); return r; } +__host__ __device__ cudaMat4 transpose(cudaMat4 mat){ + glm::mat4 mm=glm::transpose(glm::mat4(mat.x,mat.y,mat.z,mat.w)); + mat.x=mm[0]; + mat.y=mm[1]; + mat.z=mm[2]; + mat.w=mm[3]; + return mat; +} // Gets 1/direction for a ray __host__ __device__ glm::vec3 getInverseDirectionOfRay(ray r){ return glm::vec3(1.0/r.direction.x, 1.0/r.direction.y, 1.0/r.direction.z); @@ -69,11 +77,187 @@ __host__ __device__ glm::vec3 getSignOfRay(ray r){ return glm::vec3((int)(inv_direction.x < 0), (int)(inv_direction.y < 0), (int)(inv_direction.z < 0)); } +__host__ __device__ bool rayBoxIntersect(ray r, float t[2]) +{ + float t_min,t_max; + + t[0] = FLT_MIN;//t_near + + t[1] = FLT_MAX;//t_far + + glm::vec3 min_box = glm::vec3(-.5,-.5,-.5); + glm::vec3 max_box = glm::vec3(.5,.5,.5); + + bool intersectFlag = true; + + for(int i = 0;i<3;i++){ + if(r.direction[i] == 0){ + if(r.origin[i] < min_box[i] || r.origin[i] >max_box[i]){ + intersectFlag = false; + } + } + else{ + t_min = (min_box[i] - r.origin[i]) / r.direction[i]; + t_max = (max_box[i] - r.origin[i]) / r.direction[i]; + + if(t_min > t_max){ + float temp = t_min; + t_min = t_max; + t_max = temp; + } + if(t_min > t[0]) + t[0] = t_min; + if(t_max < t[1]){ + t[1] = t_max; + } + if(t[0]>t[1]){ + intersectFlag = false; + } + if(t[1]<0){ + intersectFlag = false; + } + } + } + return intersectFlag; +} + +__host__ __device__ glm::vec3 getUnitBoxNommal(glm::vec3& p) +{ + glm::vec3 normal; + float eps = 0.001f; + if(abs(p.x - 0.5) < eps) + normal = glm::vec3(1,0,0); + else if(abs(p.x + 0.5) < eps){ + normal = glm::vec3(-1,0,0); + } + else if(abs(p.y - 0.5) < eps){ + normal = glm::vec3(0,1,0); + } + else if(abs(p.y + 0.5) < eps){ + normal = glm::vec3(0,-1,0); + } + else if(abs(p.z - 0.5) < eps){ + normal = glm::vec3(0,0,1); + } + else if(abs(p.z + 0.5) < eps){ + normal = glm::vec3(0,0,-1); + } + return normal; +} + // 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){ + 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))); - return -1; + ray rt; rt.origin = ro; rt.direction = rd; + + float t[2] = {FLT_MIN, FLT_MAX}; + //float t[2] = {0}; + bool isIntersect = rayBoxIntersect(rt, t); + + float ti; + if(isIntersect) + { + if(t[0]<=0){ + ti = t[1]; + } + else + ti = t[0]; + + + glm::vec3 realIntersectionPoint = multiplyMV(box.transform, glm::vec4(getPointOnRay(rt, ti), 1.0)); + glm::vec3 realOrigin = multiplyMV(box.transform, glm::vec4(0,0,0,1)); + + glm::vec3 unitNormal = getUnitBoxNommal(getPointOnRay(rt, ti)); + + intersectionPoint = realIntersectionPoint; + + glm::vec3 realNormal = multiplyMV(box.transform, glm::vec4(unitNormal, 1)); + + normal = glm::normalize(realNormal - realOrigin); + + //normal = glm::normalize(realOrigin - realNormal); + + return glm::length(r.origin - realIntersectionPoint); + } + else + return -1; + + //glm::vec3 newP0 = multiplyMV(box.inverseTransform, glm::vec4(r.origin,1.0f)); + //glm::vec3 newV0 = glm::normalize(multiplyMV(box.inverseTransform, glm::vec4(r.direction,0.0f))); + //if (newV0[0] == 0 && newV0[1] == 0 && newV0[2] == 0) { + // return -1.0f; + //} + //ray rt; rt.origin = newP0; rt.direction = newV0; + //for (int i = 0; i < 3; i++) { + // if (newP0[i] > .5f && newV0[i] > 0) + // return -1; + // if (newP0[i] < -.5f && newV0[i] < 0) + // return -1; + // } + + // glm::vec3 face(0.0f); + // for (int i = 0; i < 3; i++) { + // if (newV0[i] > 0) { + // if (newP0[i] >= -.5f) + // face[i] = .5f; + // else + // face[i] = -.5f; + // } else { + // if (newP0[i] <= .5f) + // face[i] = -.5f; + // else + // face[i] = .5f; + // } + // } + // glm::vec3 t(-1.0f,-1.0f,-1.0f); + // glm::vec3 IntNom(0.0f); + // float minT = -1.0f; + // float tmp1 = 0.0f, tmp2 = 0.0f; + // for (int i = 0; i < 3; i++) { + // if (newV0[i] == 0.0f) + // continue; + // t[i] = (face[i] - newP0[i]) / newV0[i]; + // if (t[i] > 0) { + // tmp1 = newP0[(i + 1) % 3] + t[i] * newV0[(i + 1) % 3]; + // tmp2 = newP0[(i + 2) % 3] + t[i] * newV0[(i + 2) % 3]; + // } + // if (!(tmp1 >= -.5f && tmp1 <= .5f && tmp2 >= -.5f && tmp2 <= .5f)) + // t[i] = -1.0f; + // } + // minT = -1.0f; + // for (int i = 0; i < 3; i++) { + // if (minT <= 0.0f) { + // if (t[i] > 0.0f) { + // minT = t[i]; + // IntNom[i] = 2.0f*face[i]; + // IntNom[(i + 1) % 3] = 0.0f; + // IntNom[(i + 2) % 3] = 0.0f; + // } + // } + // else if (t[i] <= 0.0f) + // continue; + // else { + // if (t[i] < minT) { + // minT = t[i]; + // IntNom[i] = 2.0f*face[i]; + // IntNom[(i + 1) % 3] = 0.0f; + // IntNom[(i + 2) % 3] = 0.0f; + // } + // } + + // } + //if(minT<0) return minT; + + //glm::vec3 realIntersectionPoint = multiplyMV(box.transform, glm::vec4(getPointOnRay(rt, minT), 1.0f)); + //glm::vec3 realOrigin = multiplyMV(box.transform, glm::vec4(0,0,0,1.0f)); + + //intersectionPoint = realIntersectionPoint; + ////normal = glm::normalize(realIntersectionPoint - realOrigin); + //normal=multiplyMV(transpose(box.inverseTransform),glm::vec4(IntNom,1.0f)); + //return minT; } // LOOK: Here's an intersection test example from a sphere. Now you just need to figure out cube and, optionally, triangle. @@ -177,10 +361,34 @@ __host__ __device__ glm::vec3 getRandomPointOnCube(staticGeom cube, float random // TODO: IMPLEMENT THIS FUNCTION // Generates a random point on a given sphere __host__ __device__ glm::vec3 getRandomPointOnSphere(staticGeom sphere, float randomSeed){ + //Marsaglia (1972) uniform distribution of points on sphere + thrust::default_random_engine rng(hash(randomSeed)); + thrust::uniform_real_distribution u1(-1.0f,1.0f); + //thrust::uniform_real_distribution u02(0,2.0f); + float x1=1.0f; + float x2=1.0f; + while(x1*x1+x2*x2>=1.0f){ + x1=u1(rng); + x2=u1(rng); + } - return glm::vec3(0,0,0); + return multiplyMV(sphere.transform,glm::vec4(x1*sqrt(1-x1*x1-x2*x2),x2*sqrt(1-x1*x1-x2*x2),.5f-(x1*x1+x2*x2),1.0)); } +__host__ __device__ glm::vec3 getRandomPointOnSphere(float randomSeed){ + //Marsaglia (1972) uniform distribution of points on sphere + thrust::default_random_engine rng(hash(randomSeed)); + thrust::uniform_real_distribution u1(-1.0f,1.0f); + //thrust::uniform_real_distribution u02(0,2.0f); + float x1=1.0f; + float x2=1.0f; + while(x1*x1+x2*x2>=1.0f){ + x1=u1(rng); + x2=u1(rng); + } + + return glm::vec3(x1*sqrt(1-x1*x1-x2*x2),x2*sqrt(1-x1*x1-x2*x2),.5f-(x1*x1+x2*x2)); +} #endif diff --git a/src/macros.h b/src/macros.h new file mode 100644 index 0000000..70a4459 --- /dev/null +++ b/src/macros.h @@ -0,0 +1,14 @@ +#ifndef MACROS_H_ +#define MACROS_H_ +#define PI 3.1415926535897932384626422832795028841971 +#define TWO_PI 6.2831853071795864769252867665590057683943 +#define SQRT_OF_ONE_THIRD 0.5773502691896257645091487805019574556476 +#define NATURAL_E 2.7182818284590452353602874713526624977572 +#define EPSILON .000000001 +#define ZERO_ABSORPTION_EPSILON 0.00001 +#define RAY_BIAS_AMOUNT 0.0002 +#define traceDepth 20 + +#define _STREAM_COMPACT + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b002500..cae1d33 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,9 @@ int main(int argc, char** argv){ if(!loadedScene){ cout << "Error: scene file needed!" << endl; + ofstream fout("findme.me"); + fout<<"I am here!"<iterations){ uchar4 *dptr=NULL; iterations++; @@ -111,7 +128,6 @@ void runCuda(){ // unmap buffer object cudaGLUnmapBufferObject(pbo); } else { - if (!finishedRender) { // output image file image outputImage(renderCam->resolution.x, renderCam->resolution.y); @@ -155,6 +171,7 @@ void runCuda(){ finishedRender = false; } } + } //------------------------------- diff --git a/src/main.h b/src/main.h index 8bd2aed..fe23e9f 100644 --- a/src/main.h +++ b/src/main.h @@ -27,6 +27,10 @@ #include "utilities.h" #include "scene.h" +#include +#include +#include + using namespace std; //------------------------------- diff --git a/src/raytraceKernel.cu b/src/raytraceKernel.cu index 9c7bc7d..02efc14 100644 --- a/src/raytraceKernel.cu +++ b/src/raytraceKernel.cu @@ -9,6 +9,11 @@ #include #include +#include +#include +#include +#include + #include "sceneStructs.h" #include "glm/glm.hpp" #include "utilities.h" @@ -17,149 +22,649 @@ #include "interactions.h" void checkCUDAError(const char *msg) { - cudaError_t err = cudaGetLastError(); - if( cudaSuccess != err) { - fprintf(stderr, "Cuda error: %s: %s.\n", msg, cudaGetErrorString( err) ); - exit(EXIT_FAILURE); - } + cudaError_t err = cudaGetLastError(); + if( cudaSuccess != err) { + fprintf(stderr, "Cuda error: %s: %s.\n", msg, cudaGetErrorString( err) ); + exit(EXIT_FAILURE); + } } + // LOOK: This function demonstrates how to use thrust for random number generation on the GPU! // Function that generates static. __host__ __device__ glm::vec3 generateRandomNumberFromThread(glm::vec2 resolution, float time, int x, int y){ - int index = x + (y * resolution.x); - - thrust::default_random_engine rng(hash(index*time)); - thrust::uniform_real_distribution u01(0,1); + int index = x + (y * resolution.x); + + thrust::default_random_engine rng(hash(index*time)); + thrust::uniform_real_distribution u01(0,1); - return glm::vec3((float) u01(rng), (float) u01(rng), (float) u01(rng)); + return glm::vec3((float) u01(rng), (float) u01(rng), (float) u01(rng)); } // TODO: IMPLEMENT THIS FUNCTION // 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); - return r; + ray r; + r.origin = glm::vec3(0,0,0); + r.direction = glm::vec3(0,0,-1); + return r; +} + +__global__ void raycastFromCamera(cameraData cam,glm::vec3 ScreenH, glm::vec3 ScreenV, pathray* viewray){ + int x = (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)){ + //ray curray; + //curray.origin=cam.position; + //curray.direction=glm::normalize(cam.view+(2.0f*x/(float)cam.resolution.x-1)*ScreenH+(2.0f*y/(float)cam.resolution.y-1)*ScreenV); + viewray[index]=pathray(x,y,cam.position, + glm::normalize(cam.view+(2.0f*x/(float)cam.resolution.x-1)*ScreenH+(2.0f*y/(float)cam.resolution.y-1)*ScreenV)); + //colors[index] = t<0?glm::vec3(0.0f):glm::vec3(.80f);//generateRandomNumberFromThread(resolution, time, x, y); + } } //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; - int y = (blockIdx.y * blockDim.y) + threadIdx.y; - int index = x + (y * resolution.x); - if(x<=resolution.x && y<=resolution.y){ - image[index] = glm::vec3(0,0,0); - } +__global__ void clearImage(glm::vec2 resolution, glm::vec3* image,float val=0.0f){ + 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){ + image[index] = glm::vec3(val); + } } //Kernel that writes the image to the OpenGL PBO directly. -__global__ void sendImageToPBO(uchar4* PBOpos, glm::vec2 resolution, glm::vec3* image){ - - 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){ - - glm::vec3 color; - color.x = 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; - } - - if(color.y>255){ - color.y = 255; - } - - if(color.z>255){ - color.z = 255; - } - - // Each thread writes one pixel location in the texture (textel) - PBOpos[index].w = 0; - PBOpos[index].x = color.x; - PBOpos[index].y = color.y; - PBOpos[index].z = color.z; - } +__global__ void sendImageToPBO(uchar4* PBOpos, glm::vec2 resolution, glm::vec3* image,int iter){ + + 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){ + + glm::vec3 color; + color.x = image[index].x*255.0/(float)iter; + color.y = image[index].y*255.0/(float)iter; + color.z = image[index].z*255.0/(float)iter; + + if(color.x>255){ + color.x = 255; + } + + if(color.y>255){ + color.y = 255; + } + + if(color.z>255){ + color.z = 255; + } + + // Each thread writes one pixel location in the texture (textel) + PBOpos[index].w = 0; + PBOpos[index].x = color.x; + PBOpos[index].y = color.y; + PBOpos[index].z = color.z; + } } + +__device__ glm::vec3 TracePath(pathray r, staticGeom* geoms,int numberOfGeoms,material* mats,float time, cameraData cam, int x, int y,glm::vec3& IntClr){ + IntClr=glm::vec3(1.0f); + if(r.depth>=traceDepth) { + r.isDead=true; + IntClr=glm::vec3(0.0f); + return glm::vec3(0.0f); + } + //glm::vec3 IntClr(1.0f); + for(int i=0;i=0&&t>p))?p:t; + //geoId=(t<0||(p>=0&&t>p))?i:geoId; + //if(t<0) colors[index]=glm::vec3(0.0f); + if(epsilonCheck(p,t)) geoId=i; + break; + case GEOMTYPE::CUBE: + p=boxIntersectionTest(geoms[i],r.curray,IntSecPt,normal); + t=(t<0||(p>=0&&t>p))?p:t; + //geoId=(t<0||(p>=0&&t>p))?i:geoId; + //if(t<0) colors[index]=glm::vec3(0.0f); + if(epsilonCheck(p,t)) geoId=i; + break; + case GEOMTYPE::MESH: + break; + default: + break; + } + } + + if(geoId<0) { + //r.state=-1; + r.isDead=true; + IntClr=glm::vec3(0.0f); + return glm::vec3(0.0f); + } + else{ + glm::vec3 rand = generateRandomNumberFromThread(cam.resolution, time + (i+1), x, y); + material curmat=mats[geoms[geoId].materialid]; + //r.pushback(geoms[geoId].materialid,ray(IntSecPt,getRandomPointOnSphere(hash(time)),normal),normal); + if(curmat.emittance>0){ + IntClr*=curmat.emittance*curmat.color; + r.isDead=true; + return glm::vec3(0.0f); + } + else{ + r.curray.direction=glm::normalize(calculateRandomDirectionInHemisphere(normal,rand.x,rand.y)); + r.curray.origin=IntSecPt+0.001f*r.curray.direction; + } + //return mats[geoms[geoId].materialid].color; + //return (normal+glm::vec3(1.0f))/2.0f; + //r.depth++; + //r.state=geoId; + //return geoms[geoId].materialid; + IntClr*=curmat.color; + } + } + IntClr=glm::vec3(0.0f); + return IntClr; + //__syncthreads(); +} +__host__ __device__ bool intersection(staticGeom* geoms, int numberOfGeoms, ray r, glm::vec3& intersectionPoint, glm::vec3& normal, int& geomIndex){ + float t = FLT_MAX; + //int geomIndex = 0; + for(int i = numberOfGeoms - 1; i >= 0; --i) + { + float temp; + if(geoms[i].type == SPHERE) + temp = sphereIntersectionTest(geoms[i], r, intersectionPoint, normal); + else if(geoms[i].type == CUBE) + temp = boxIntersectionTest(geoms[i], r, intersectionPoint, normal); + else if(geoms[i].type == MESH){ + //printf("hahah tri \n"); + //printf("after haah tri \n"); + } + + if(temp != -1.0f && temp < t) + { + t = temp; + geomIndex = i; + } + } + + if(t != FLT_MAX){ + //get the intersection point and normal + if(geoms[geomIndex].type == SPHERE) + sphereIntersectionTest(geoms[geomIndex], r, intersectionPoint, normal); + else if(geoms[geomIndex].type == CUBE) + boxIntersectionTest(geoms[geomIndex], r, intersectionPoint, normal); + else if(geoms[geomIndex].type == MESH){ + //printf("have tri "); + } + return true; + } + else + { + return false; + } +} +__host__ __device__ bool diffuseScatter(staticGeom* geoms, int numberOfGeoms, glm::vec3& intersectionPoint, glm::vec3 inNormal, material material, + glm::vec3 rand, int geomIndex, Fresnel fresnel, float &diffuseScatterCoeff) +{ + glm::vec3 dir = glm::normalize(calculateRandomDirectionInHemisphere(inNormal, rand.x, rand.y)); + glm::vec3 pSample = intersectionPoint + 1/material.reducedScatterCoefficient * dir; + ray r; + r.origin = pSample; + r.direction = -inNormal; + glm::vec3 newIntersectionPoint; + glm::vec3 newNormal; + int newGeomIndex; + if(intersection(geoms, numberOfGeoms, r, newIntersectionPoint, newNormal, newGeomIndex)) + { + if(newGeomIndex == geomIndex) + { + float r = glm::distance(intersectionPoint, newIntersectionPoint); + float zr = 1.0f/material.reducedScatterCoefficient; + float zv = zr + 4 * (1.0f/(3.f * material.reducedScatterCoefficient) * (1.f + fresnel.reflectionCoefficient / 1.f - fresnel.reflectionCoefficient)); + float dr = glm::sqrt(r*r + zr*zr); + float dv = glm::sqrt(r*r + zv*zv); + float tr = glm::sqrt(3 * material.absorptionCoefficient.x * material.reducedScatterCoefficient); + float tr_dr = tr * dr; + float tr_dv = tr * dv; + + float rd = (tr_dr + 1.0) * glm::exp(-tr_dr)/* * zr *// (glm::pow(dr, 3.f)) + + (tr_dv + 1.0) * glm::exp(-tr_dv) * zv / (glm::pow(dv,3.0f)); + + diffuseScatterCoeff = ((glm::dot(dir ,inNormal) * rd) / (material.reducedScatterCoefficient * material.reducedScatterCoefficient * glm::exp(-material.reducedScatterCoefficient * r))) / 3 * PI; + intersectionPoint = newIntersectionPoint; + return true; + } + } + return false; +} + + + +__host__ __device__ void pathTrace(pathray &pr, staticGeom* geoms, material* mats, int geomsNum,cameraData cam, float time,int x, int y, glm::vec3& clr,int lPos){ + //glm::vec3 acol = glm::vec3(1,1,1); + clr = glm::vec3(1,1,1); + ray r=pr.curray; + for(int i = 0; i < traceDepth; i++) + { + glm::vec3 intSecPt, normal; + int geoId; + if(!intersection(geoms, geomsNum, r, intSecPt, normal, geoId)) + { + clr = glm::vec3(0,0,0); + return; + } + + material curmat = mats[geoms[geoId].materialid]; + glm::vec3 rand = generateRandomNumberFromThread(cam.resolution, time + (i+1), x, y); + + if(curmat.emittance>0){ + clr *= curmat.emittance * curmat.color; + return; + } + + //printf("ahhaha\n"); + if(curmat.hasReflective>0.0f&&curmat.hasReflective>rand.z){ + //reflection parts + glm::vec3 rfDir=calculateReflectionDirection(normal, r.direction); + r.origin= intSecPt+0.001f*rfDir; + r.direction=rfDir; + + Fresnel fsl; + bool IsOut=glm::dot(rfDir,normal)>0; + glm::vec3 rfClr,rfractClr; + if(!IsOut){ + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfClr, rfractClr); + } + else{ + fsl=calculateFresnel(-normal, r.direction, curmat.indexOfRefraction,1.0f, rfClr, rfractClr); + } + clr*=curmat.color*fsl.reflectionCoefficient; + } + else if(curmat.specularExponent>0){ + glm::vec3 newr(glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y))); + clr*=curmat.color*curmat.specularColor*glm::pow(glm::dot(normal,glm::normalize(newr-r.direction)),curmat.specularExponent); + r.direction=newr; + r.origin=intSecPt+0.001f*r.direction; + } + else if(curmat.hasScatter>0.0f&&curmat.hasScatter>rand.z){ + //subsurface scattering parts + Fresnel fsl; + bool IsOut = glm::dot(r.direction, normal)>0; + glm::vec3 rfclr, rfractClr; + if(!IsOut) + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfclr, rfractClr); + else + fsl = calculateFresnel(-normal, r.direction, curmat.indexOfRefraction, 1.0f, rfclr, rfractClr); + + glm::vec3 diffDir; + float singleScatterCoeff; + float diffuseScatterCoeff; + if(diffuseScatter(geoms, geomsNum, intSecPt, normal, curmat, rand, geoId, fsl, diffuseScatterCoeff)) + { + glm::vec3 light = getRandomPointOnCube(geoms[lPos], rand.x); + diffDir = glm::normalize(light - intSecPt); + r.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y));//diffuseDirection; + r.origin = intSecPt + 0.001f * r.direction; + clr *= diffuseScatterCoeff; + } + } + else if(curmat.hasRefractive>0.0f){ + //refraction parts + glm::vec3 rfDir;//=calculateTransmissionDirection(normal, r.direction); + //r.origin= intSecPt+0.001f*rfDir; + //r.direction=rfDir; + bool IsOut=glm::dot(r.direction,normal)>0; + Fresnel fsl; + glm::vec3 rfClr,rfractClr; + if(!IsOut){ + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfClr, rfractClr); + } + else{ + fsl=calculateFresnel(-normal, r.direction, curmat.indexOfRefraction,1.0f, rfClr, rfractClr); + } + + float rfcoef=curmat.indexOfRefraction; + //glm::vec3 rfClr,rfractClr; + + if(rand.z>.5f){ + if(!IsOut) + rfDir = calculateTransmissionDirection(normal, r.direction, 1.0f, rfcoef); + else + rfDir = calculateTransmissionDirection(-normal, r.direction, rfcoef,1.0f); + + r.origin= intSecPt+0.001f*rfDir; + r.direction=rfDir; + clr *= fsl.transmissionCoefficient; + } + else{ + glm::vec3 rflectDir=calculateReflectionDirection(normal, r.direction); + r.origin= intSecPt+0.001f*rflectDir; + r.direction=rflectDir; + clr*=fsl.reflectionCoefficient; + } + } + else{ + r.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y)); + r.origin = intSecPt + 0.001f * r.direction; + + clr *= curmat.color; + } + + + } + clr = glm::vec3(0,0,0); + return; +} + +__host__ __device__ void pathTraceSC(pathray& pr, staticGeom* geoms, material* mats, int geomsNum,cameraData cam, float time,int x, int y, glm::vec3& clr,int lPos){ + //glm::vec3 acol = glm::vec3(1,1,1); + //clr = glm::vec3(1,1,1); + ray r=pr.curray; + + //for(int i = 0; i < traceDepth; i++) + { + glm::vec3 intSecPt, normal; + int geoId; + if(!intersection(geoms, geomsNum, r, intSecPt, normal, geoId)) + { + clr = glm::vec3(0,0,0); + pr.isDead=true; + return; + } + + material curmat = mats[geoms[geoId].materialid]; + glm::vec3 rand = generateRandomNumberFromThread(cam.resolution, time + (pr.depth+1), x, y); + + if(curmat.emittance>0){ + clr *= curmat.emittance * curmat.color; + pr.isDead=true; + return; + } + + //printf("ahhaha\n"); + if(curmat.hasReflective>0.0f&&curmat.hasReflective>rand.z){ + //reflection parts + glm::vec3 rfDir=calculateReflectionDirection(normal, r.direction); + r.origin= intSecPt+0.001f*rfDir; + r.direction=rfDir; + + Fresnel fsl; + bool IsOut=glm::dot(rfDir,normal)>0; + glm::vec3 rfClr,rfractClr; + if(!IsOut){ + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfClr, rfractClr); + } + else{ + fsl=calculateFresnel(-normal, r.direction, curmat.indexOfRefraction,1.0f, rfClr, rfractClr); + } + clr*=curmat.color*fsl.reflectionCoefficient; + } + else if(curmat.specularExponent>0){ + glm::vec3 newr(glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y))); + clr*=curmat.color*curmat.specularColor*glm::pow(glm::dot(normal,glm::normalize(newr-r.direction)),curmat.specularExponent); + r.direction=newr; + r.origin=intSecPt+0.001f*r.direction; + } + else if(curmat.hasScatter>0.0f&&curmat.hasScatter>rand.z){ + //subsurface scattering parts + Fresnel fsl; + bool IsOut = glm::dot(r.direction, normal)>0; + glm::vec3 rfclr, rfractClr; + if(!IsOut) + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfclr, rfractClr); + else + fsl = calculateFresnel(-normal, r.direction, curmat.indexOfRefraction, 1.0f, rfclr, rfractClr); + + glm::vec3 diffDir; + float singleScatterCoeff; + float diffuseScatterCoeff; + if(diffuseScatter(geoms, geomsNum, intSecPt, normal, curmat, rand, geoId, fsl, diffuseScatterCoeff)) + { + glm::vec3 light = getRandomPointOnCube(geoms[lPos], rand.x); + diffDir = glm::normalize(light - intSecPt); + r.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y));//diffuseDirection; + r.origin = intSecPt + 0.001f * r.direction; + clr *= diffuseScatterCoeff; + } + } + else if(curmat.hasRefractive>0.0f){ + //refraction parts + glm::vec3 rfDir;//=calculateTransmissionDirection(normal, r.direction); + //r.origin= intSecPt+0.001f*rfDir; + //r.direction=rfDir; + bool IsOut=glm::dot(r.direction,normal)>0; + Fresnel fsl; + glm::vec3 rfClr,rfractClr; + if(!IsOut){ + fsl = calculateFresnel(normal, r.direction, 1.0f, curmat.indexOfRefraction, rfClr, rfractClr); + } + else{ + fsl=calculateFresnel(-normal, r.direction, curmat.indexOfRefraction,1.0f, rfClr, rfractClr); + } + + float rfcoef=curmat.indexOfRefraction; + //glm::vec3 rfClr,rfractClr; + + if(rand.z>.5f){ + if(!IsOut) + rfDir = calculateTransmissionDirection(normal, r.direction, 1.0f, rfcoef); + else + rfDir = calculateTransmissionDirection(-normal, r.direction, rfcoef,1.0f); + + r.origin= intSecPt+0.001f*rfDir; + r.direction=rfDir; + clr *= fsl.transmissionCoefficient; + } + else{ + glm::vec3 rflectDir=calculateReflectionDirection(normal, r.direction); + r.origin= intSecPt+0.001f*rflectDir; + r.direction=rflectDir; + clr*=fsl.reflectionCoefficient; + } + } + else{ + r.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rand.x, rand.y)); + r.origin = intSecPt + 0.001f * r.direction; + + clr *= curmat.color; + } + + pr.curray=r; + } + //clr = glm::vec3(0,0,0); + pr.depth++; + if(pr.depth>=traceDepth) clr=glm::vec3(0.0f); + return; +} + + // 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){ +__global__ void raytraceRay(float time, cameraData cam,staticGeom* geoms, material* mats,int numberOfGeoms, pathray* rays,glm::vec3* img,int lPos){ + int x = (blockIdx.x * blockDim.x) + threadIdx.x; + int y = (blockIdx.y * blockDim.y) + threadIdx.y; + int index = x + (y * cam.resolution.x); + + if(xresolution.x)/float(tileSize)), (int)ceil(float(renderCam->resolution.y)/float(tileSize))); - - // send image to GPU - glm::vec3* cudaimage = NULL; - 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 - staticGeom* geomList = new staticGeom[numberOfGeoms]; - for(int i=0; iresolution; - cam.position = renderCam->positions[frame]; - cam.view = renderCam->views[frame]; - cam.up = renderCam->ups[frame]; - cam.fov = renderCam->fov; + //determines how many bounces the raytracer traces + cudaEvent_t start, stop; + cudaEventCreate(&start); + cudaEventCreate(&stop); + cudaEventRecord( start, 0); + // set up crucial magic + int tileSize = 8; + dim3 threadsPerBlock(tileSize, tileSize); + dim3 fullBlocksPerGrid((int)ceil(float(renderCam->resolution.x)/float(tileSize)), (int)ceil(float(renderCam->resolution.y)/float(tileSize))); - // kernel launches - raytraceRay<<>>(renderCam->resolution, (float)iterations, cam, traceDepth, cudaimage, cudageoms, numberOfGeoms); + // send image to GPU + glm::vec3* cudaimage = NULL; + 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); - sendImageToPBO<<>>(PBOpos, renderCam->resolution, cudaimage); + if(iterations==1){ + clearImage<<>>(renderCam->resolution,cudaimage); + } + // package geometry and materials and sent to GPU + staticGeom* geomList = new staticGeom[numberOfGeoms]; + int lPos; + for(int i=0; i0) + lPos=i; + } - // retrieve image from GPU - cudaMemcpy( renderCam->image, cudaimage, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(glm::vec3), cudaMemcpyDeviceToHost); + staticGeom* cudageoms = NULL; + cudaMalloc((void**)&cudageoms, numberOfGeoms*sizeof(staticGeom)); + cudaMemcpy( cudageoms, geomList, numberOfGeoms*sizeof(staticGeom), cudaMemcpyHostToDevice); - // free up stuff, or else we'll leak memory like a madman - cudaFree( cudaimage ); - cudaFree( cudageoms ); - delete geomList; + material* cudaMaterials=NULL; + cudaMalloc((void**)&cudaMaterials, numberOfMaterials*sizeof(material)); + cudaMemcpy(cudaMaterials,materials,numberOfMaterials*sizeof(material),cudaMemcpyHostToDevice); + // package camera + cameraData cam; + cam.resolution = renderCam->resolution; + cam.position = renderCam->positions[frame]; + cam.view = renderCam->views[frame]; + cam.up = renderCam->ups[frame]; + cam.fov = renderCam->fov; - // make certain the kernel has completed - cudaThreadSynchronize(); + glm::vec3 A=glm::normalize(glm::cross(cam.up,cam.view)); + glm::vec3 ScreenH=A*(float)tan(cam.fov.x*PI/180.0f)*glm::length(cam.view); + glm::vec3 ScreenV=glm::normalize(glm::cross(A,cam.view))*(float)tan(cam.fov.y*PI/180.0f)*glm::length(cam.view); - checkCUDAError("Kernel failed!"); + pathray* rays=NULL; + cudaMalloc((void**)&rays, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(pathray)); + //initial rays from camera; + raycastFromCamera<<>>(cam,ScreenH,ScreenV,rays); + // kernel launches + //while(!rays[0].isDead) + //for(int i=0;i>>((float)iterations, cam, cudageoms, cudaMaterials, numberOfGeoms,rays,cudaimage,lPos); +#else + //pathray* pool=rays; + //cudaMalloc((void**)&rays, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(pathray)); + + glm::vec3* cacheimage = NULL; + cudaMalloc((void**)&cacheimage, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(glm::vec3)); + //if(iterations==1){ + clearImage<<>>(renderCam->resolution,cacheimage,1.0f); + //} + int poolSize=(int)renderCam->resolution.x*(int)renderCam->resolution.y; + + int curDepth=0; + while(poolSize>0&&curDepth>>(poolSize,(float)iterations, cam, cudageoms, cudaMaterials, numberOfGeoms,rays,cacheimage,lPos); + cudaThreadSynchronize(); + thrust::device_ptr iteratorStart(rays); + thrust::device_ptr iteratorEnd=iteratorStart+poolSize; + iteratorEnd=thrust::remove_if(iteratorStart, iteratorEnd,IsDead()); + poolSize=(int)(iteratorEnd-iteratorStart); + + } + //printf("curDepth=%d\n",curDepth); + fullBlocksPerGrid=dim3((int)ceil(float(renderCam->resolution.x)/float(tileSize)), (int)ceil(float(renderCam->resolution.y)/float(tileSize))); + //thrust::copy_if(rays,rays+poolSize,pool,NotDead()); + + imageAdd<<>>(cudaimage,cacheimage,cam); + cudaFree(cacheimage); + //if(poolSize>0) cudaFree(pool); +#endif + + + + //cudaThreadSynchronize(); + //} + + //compose<<>>(cudaimage,rays,cudaMaterials,cam); + + sendImageToPBO<<>>(PBOpos, renderCam->resolution, cudaimage,iterations); + + //cudaThreadSynchronize(); + // retrieve image from GPU + cudaMemcpy( renderCam->image, cudaimage, (int)renderCam->resolution.x*(int)renderCam->resolution.y*sizeof(glm::vec3), cudaMemcpyDeviceToHost); + //checkCUDAError("11 Kernel failed!"); + // free up stuff, or else we'll leak memory like a madman + cudaFree( cudaimage ); + cudaFree( cudageoms ); + cudaFree( rays ); + delete geomList; + + // make certain the kernel has completed + cudaThreadSynchronize(); + cudaEventRecord( stop, 0); + cudaEventSynchronize( stop ); + + float seconds = 0.0f; + cudaEventElapsedTime( &seconds, start, stop); + + printf("One Loop time: %f ms\n", seconds); + checkCUDAError("Kernel failed!"); } diff --git a/src/raytraceKernel.h b/src/raytraceKernel.h index 984e89f..0a03833 100755 --- a/src/raytraceKernel.h +++ b/src/raytraceKernel.h @@ -10,10 +10,17 @@ #include #include + +#include + #include #include #include "sceneStructs.h" +#include "macros.h" + + + void cudaRaytraceCore(uchar4* pos, camera* renderCam, int frame, int iterations, material* materials, int numberOfMaterials, geom* geoms, int numberOfGeoms); #endif diff --git a/src/sceneStructs.h b/src/sceneStructs.h index 5e0c853..b071c5f 100644 --- a/src/sceneStructs.h +++ b/src/sceneStructs.h @@ -11,13 +11,97 @@ #include #include +#include "macros.h" + enum GEOMTYPE{ SPHERE, CUBE, MESH }; +//class RenderCre{ +// static RenderCre* Inst; +//public: +// static RenderCre* GetInstance(){ +// if(!Inst) //return Inst; +// Inst=new RenderCre; +// return Inst; +// } +// RenderCre(){ +// } +//}; +// +//RenderCre* RenderCre::Inst=NULL; + struct ray { glm::vec3 origin; glm::vec3 direction; + __host__ __device__ ray(){} + __host__ __device__ ray(glm::vec3& o, glm::vec3& d){ + origin=o+d*0.001f; + direction=glm::normalize(d); + } + __host__ __device__ ray(glm::vec3& o, glm::vec3& d, glm::vec3& n){ + //origin=o; + direction=glm::dot(d,n)<0?d:-d; + direction=glm::normalize(direction); + origin=o+direction*0.001f; + } +}; +struct pathray{ + bool isDead; + int depth; + ray curray; + glm::vec2 onscreen; + //int geoId[traceDepth]; + //float blnPng[traceDepth]; + __host__ __device__ pathray(){ + depth=0; + isDead=false; + //memset(geoId,-1,traceDepth*sizeof(int)); + } + __host__ __device__ pathray(int x, int y, glm::vec3& o,glm::vec3& d):onscreen(x,y),curray(o,d){ + depth=0; + isDead=false; + //memset(geoId,-1,traceDepth*sizeof(int)); + } + __host__ __device__ pathray(int x, int y, glm::vec3& o,glm::vec3& d, glm::vec3& n):onscreen(x,y),curray(o,d,n){ + depth=0; + isDead=false; + //memset(geoId,-1,traceDepth*sizeof(int)); + } + + __host__ __device__ ray& operator=(ray& r){ + curray=r; + return r; + }; + __host__ __device__ void pushback(int id,ray& r,glm::vec3& n){ + //geoId[depth]=id; + //blnPng[depth]=0;//glm::clamp(glm::abs(glm::dot(n,glm::normalize(glm::normalize(r.direction)-glm::normalize(curray.direction))))/*/glm::dot(curray.origin-r.origin,curray.origin-r.origin)*/,0.0f,1.0f); + //blnPng[depth]=blnPng[depth]>0?blnPng[depth]:0; + /*depth++; + curray=r; + isDead=(depth>=traceDepth);*/ + } + __host__ __device__ int getback(){ + //return depth>0?geoId[--depth]:-1; + } + __host__ __device__ void getback(int& id, float& phg){ + if(depth>0){ + //id=geoId[--depth]; + //phg=blnPng[depth]; + } + else{ + id=-1; + phg=0; + } + + } }; +struct IsDead{ + __host__ __device__ bool operator()(const pathray r){ + return r.isDead; + } +}; + + struct geom { enum GEOMTYPE type; int materialid; diff --git a/src/utilities.cpp b/src/utilities.cpp index a8e5d90..fe1da3c 100755 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -72,9 +72,9 @@ void utilityCore::printCudaMat4(cudaMat4 m){ glm::mat4 utilityCore::buildTransformationMatrix(glm::vec3 translation, glm::vec3 rotation, glm::vec3 scale){ glm::mat4 translationMat = glm::translate(glm::mat4(), translation); - glm::mat4 rotationMat = glm::rotate(glm::mat4(), rotation.x, glm::vec3(1,0,0)); - rotationMat = rotationMat*glm::rotate(glm::mat4(), rotation.y, glm::vec3(0,1,0)); - rotationMat = rotationMat*glm::rotate(glm::mat4(), rotation.z, glm::vec3(0,0,1)); + glm::mat4 rotationMat = glm::rotate(glm::mat4(), rotation.x/180.0f*(float)PI, glm::vec3(1,0,0)); + rotationMat = rotationMat*glm::rotate(glm::mat4(), rotation.y*(float)PI/180.0f, glm::vec3(0,1,0)); + rotationMat = rotationMat*glm::rotate(glm::mat4(), rotation.z*(float)PI/180.0f, glm::vec3(0,0,1)); glm::mat4 scaleMat = glm::scale(glm::mat4(), scale); return translationMat*rotationMat*scaleMat; } diff --git a/src/utilities.h b/src/utilities.h index f51598f..cd4d60f 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -17,13 +17,7 @@ #include #include "cudaMat4.h" -#define PI 3.1415926535897932384626422832795028841971 -#define TWO_PI 6.2831853071795864769252867665590057683943 -#define SQRT_OF_ONE_THIRD 0.5773502691896257645091487805019574556476 -#define NATURAL_E 2.7182818284590452353602874713526624977572 -#define EPSILON .000000001 -#define ZERO_ABSORPTION_EPSILON 0.00001 -#define RAY_BIAS_AMOUNT 0.0002 +#include "macros.h" namespace utilityCore { extern float clamp(float f, float min, float max); diff --git a/test.png b/test.png new file mode 100644 index 0000000..bd552a8 Binary files /dev/null and b/test.png differ diff --git a/test_mark.png b/test_mark.png new file mode 100644 index 0000000..88cd8e7 Binary files /dev/null and b/test_mark.png differ diff --git a/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj b/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj index c45dd79..1b3e75c 100644 --- a/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj +++ b/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj @@ -28,7 +28,7 @@ - + @@ -50,6 +50,9 @@ cudart.lib;glew32s.lib;glfw3.lib;opengl32.lib;%(AdditionalDependencies) Console + + compute_20,sm_20 + @@ -73,6 +76,7 @@ + @@ -95,6 +99,6 @@ - + \ No newline at end of file diff --git a/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj.filters b/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj.filters index 584fd19..7148c91 100644 --- a/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj.filters +++ b/windows/Project3-Pathtracer/Project3-Pathtracer/Project3-Pathtracer.vcxproj.filters @@ -48,6 +48,9 @@ Header Files + + Header Files + diff --git a/windows/Project3-Pathtracer/Project3-Pathtracer/findme.me b/windows/Project3-Pathtracer/Project3-Pathtracer/findme.me new file mode 100644 index 0000000..4c727c5 --- /dev/null +++ b/windows/Project3-Pathtracer/Project3-Pathtracer/findme.me @@ -0,0 +1 @@ +I am here! diff --git a/windows/Project3-Pathtracer/Project3-Pathtracer/test.0.bmp b/windows/Project3-Pathtracer/Project3-Pathtracer/test.0.bmp new file mode 100644 index 0000000..156e55d Binary files /dev/null and b/windows/Project3-Pathtracer/Project3-Pathtracer/test.0.bmp differ