diff --git a/assets/CS-184-Mesh-Edit-Writeup.pdf b/assets/CS-184-Mesh-Edit-Writeup.pdf index 83793a4..b8d9877 100644 Binary files a/assets/CS-184-Mesh-Edit-Writeup.pdf and b/assets/CS-184-Mesh-Edit-Writeup.pdf differ diff --git a/hw2/index.html b/hw2/index.html index 21ddd6b..85be95e 100644 --- a/hw2/index.html +++ b/hw2/index.html @@ -78,6 +78,13 @@ margin-top: 5px; /* Add some margin above captions */ } + + .highlighter-rouge { + color: #b00505; + background-color: rgb(247, 222, 222); + border-radius: 4px; + padding: 3px; + } CS 184 Mesh Edit @@ -104,856 +111,901 @@

Ian Dong

-
+

Overview

+ + In this homework, I explored the world of mesh editing through building Bezier curves and surfaces using the + de Casteljau algorithm and implementing various mesh operations such as area-weighted vertex normals, edge + flip, edge split, and loop subdivision. + +
+
+ +

Section I: Bezier Curves and Surfaces

+ +

Part 1: Bezier Curves with 1D de Casteljau Subdivision

+ +
+ + Briefly explain de Casteljau's algorithm and how you implemented it in order to evaluate Bezier curves. +

- In this project, I explored the world of mesh editing through building Bezier curves and surfaces using the - de Casteljau algorithm and implementing various mesh operations such as area-weighted vertex normals, edge - flip, edge split, and loop subdivision. +

    +
  • + de Casteljau's Algorithm takes in a set of control points and a parameter t, a + proportion + of length along the line and evaluates a + Bezier curve by recursively interpolating between each pair of control points. It can repeat this + process until the criterion has been met or that the final interpolated point has been calculated. + By + adjusting this parameter t, it can find all the points along the + curve. I implemented + this + algorithm by looping through each point and its adjacent point, \(p_i\) and \(p_{i+1}\), and + computing the interpolated point \(p_i^{'} = \text{lerp}(p_i, p_{i + 1}, t) = (1 - t) p_i + t p_{i + + 1}\). After each iteration, there will be one fewer control point than the previous iteration. This + process can be repeated until there is only one point left, which would be the final evaluated point. +
  • +

-
+
-

Section I: Bezier Curves and Surfaces

- -

Part 1: Bezier Curves with 1D de Casteljau Subdivision

- -
- - Briefly explain de Casteljau's algorithm and how you implemented it in order to evaluate Bezier curves. - -

-

    -
  • - de Casteljau's Algorithm takes in a set of control points and a parameter t, a - proportion - of length along the line and evaluates a - Bezier curve by recursively interpolating between each pair of control points. It can repeat this - process until the criterion has been met or that the final interpolated point has been calculated. - By - adjusting this parameter t, it can find all the points along the curve. I implemented - this - algorithm by looping through each point and its adjacent point, \(p_i\) and \(p_{i+1}\), and - computing the interpolated point \(p_i^{'} = \text{lerp}(p_i, p_{i + 1}, t) = (1 - t) p_i + t p_{i + - 1}\). After each iteration, there will be one fewer control point than the previous iteration. This - process can be repeated until there is only one point left, which would be the final evaluated point. -
  • -
-

-
+
-
+
+ + Take a look at the provided .bzc files and create your own Bezier + curve with 6 control + points of your choosing. Use this Bezier curve for your screenshots below. + +

+

    -
    - - Take a look at the provided .bzc files and create your own Bezier curve with 6 control - points of your choosing. Use this Bezier curve for your screenshots below. - -

    -

      - -
    • - Here is a Bezier curve with 6 control points of my choosing: -
      - - - - -
      -
      - -
      Bezier Curve
      -
      -
      -
    • -
    -

    -
    -
    -
    - Show screenshots of each step / level of the evaluation from the original control points down to the final - evaluated point. Press E to step through. Toggle C to show the completed Bezier curve - as well. -

    -

      -
    • - Here are the screenshots of each step of the evaluation from the original control points down to the - final evaluated point as well as the completed Bezier curve: -
      - - - - - - - - - - - - - -
      -
      - -
      Step 0
      -
      - -
      Step 1
      -
      - -
      Step 2
      -
      - -
      Step 3
      -
      - -
      Step 4
      -
      - -
      Step 5
      -
      - - - - -
      - -
      Completed Bezier Curve
      -
      -
      -
    • -

      -
    -
    -
    - Show a screenshot of a slightly different Bezier curve by moving the original control points around and - modifying the parameter \(t\) via mouse scrolling. -

    - -

  • - I had shifted \(t\) to a higher value which meant that the curve was more towards the right. I also - moved the control points around to create a different curve. Here is a screenshot of a slightly - different Bezier curve by moving the original control points around - and modifying the parameter \(t\) via mouse scrolling: -
    - - - - - -
    -
    - -
    Original Completed Bezier Curve
    -
    - -
    Modified Completed Bezier Curve
    -
    -
    -
  • -
+
  • + Here is a Bezier curve with 6 control points of my choosing: +
    + + + + +
    +
    + +
    Bezier Curve
    +
    +
    +
  • + +

    +
    +
    +
    + Show screenshots of each step / level of the evaluation from the original control points down to the final + evaluated point. Press E to step through. Toggle C to show the completed Bezier curve + as well. +

    +

      +
    • + Here are the screenshots of each step of the evaluation from the original control points down to the + final evaluated point as well as the completed Bezier curve: +
      + + + + + + + + + + + + + +
      +
      + +
      Step 0
      +
      + +
      Step 1
      +
      + +
      Step 2
      +
      + +
      Step 3
      +
      + +
      Step 4
      +
      + +
      Step 5
      +
      + + + + +
      + +
      Completed Bezier Curve
      +
      +
      +
    • -
    -
    +
    +
    +
    + Show a screenshot of a slightly different Bezier curve by moving the original control points around and + modifying the parameter \(t\) via mouse scrolling. +

    +

    +

    +
    +
    -

    Part 2: Bezier Surfaces with Separable 1D de Casteljau

    -
    - Briefly explain how de Casteljau algorithm extends to Bezier surfaces and how you implemented it in order to - evaluate Bezier surfaces. -

    -

    -

    -
    -
    -
    - Show a screenshot of bez/teapot.bez (not code) evaluated by your implementation. -

    -

    -

    -
    +

    Part 2: Bezier Surfaces with Separable 1D de Casteljau

    +
    + Briefly explain how de Casteljau algorithm extends to Bezier surfaces and how you implemented it in order to + evaluate Bezier surfaces. +

    +

    +

    +
    +
    +
    + Show a screenshot of bez/teapot.bez (not dae) evaluated by your implementation. +

    +

    +

    +
    -
    -

    - - -

    Section II: Triangle Meshes and Half-Edge Data Structure

    - -

    Part 3: Area-Weighted Vertex Normals

    -
    - Briefly explain how you implemented the area-weighted vertex normals. -

    -

    -

    -
    -
    -
    - Show screenshots of dae/teapot.dae (not .bez) comparing teapot shading with and - without vertex normals. Use Q to toggle default flat shading and Phong shading. - -

    -
    +
    +

    -
    -

    Part 4: Edge Flip

    - -
    - Briefly explain how you implemented the edge flip operation and describe any interesting implementation / - debugging tricks you have used. -

    -

    -

    -
    -
    +

    Section II: Triangle Meshes and Half-Edge Data Structure

    +

    Part 3: Area-Weighted Vertex Normals

    +
    + Briefly explain how you implemented the area-weighted vertex normals.

    -

    - Show screenshots of the teapot before and after some edge flips. -
      -
    • - Here are some screenshots of dae/teapot.dae before and after some edge flips. -
      - - - - - -
      -
      - -
      Before Edge Flips
      -
      - -
      After Edge Flips
      -
      -
      -
    • -
    -

    -
    + +

    +
    +
    +
    + Show screenshots of dae/teapot.dae (not .bez) comparing + teapot shading with and + without vertex normals. Use Q to toggle default flat shading and Phong shading. + +

    +
    -
    +
    + +

    Part 4: Edge Flip

    -
    - Write about your eventful debugging journey, if you have experienced one. -

    -

    + +
  • + Here are the formal steps I took to implement the edge flip operation: +
      +
    1. + First, I checked if e0->isBoundary() was true to make sure to + never + flip a boundary edge and simply returned if it was. +
    2. +
    3. + Then, I defined the inner and outer half-edges of the two triangles using the + twin() and next() + methods. Each of these half-edges corresponded + to + the 10 half-edges, h0 ... h9, as shown in the diagram + above. +
    4. +
    5. + Next, I defined the vertices of the two triangles using the vertex() method on + the + appropriate half-edge. Each of these vertices corresponded to the 4 vertices, + v0 ... v3, as shown in the diagram above. +
    6. +
    7. + Afterwards, I defined the edges and faces of the two triangles using the edge() + and + face() methods on the appropriate half-edge. Each of + these edges and faces + corresponded to the 5 edges, e0 ... e4, and 2 faces, + f0, f1, as + shown + in + the diagram above. +
    8. +
    9. + Then, I updated each of the 10 half-edge pointers using the setNeighbors() + method + according to the diagram above. +
    10. +
    11. + Finally, I reassigned the half-edge pointers for each of the 4 vertices, 5 edges, and 2 + faces + according to the diagram above and returned the newly updated e0. +
    12. +
    + Some tricks I used was to follow my diagram very closely and checking which pointers I was passing + into + my functions as well as using the additional debugging utilities provided in the spec. +
  • + +

    + +
    + +

    +

    + Show screenshots of the teapot before and after some edge flips. + +

    +
    -
    +
    -
    - Show screenshots of a mesh before and after some edge splits. -

    -

    -

    -
    +
    + Write about your eventful debugging journey, if you have experienced one. +

    +

    +


    +
    +
    +

    Part 5: Edge Split

    +
    + Briefly explain how you implemented the edge split operation and describe any interesting implementation + / + debugging tricks you have used. +

    +

    +

    +
    -
    - Show screenshots of a mesh before and after a combination of both edge splits and edge flips. -

    -

    -

    -
    -
    +
    -
    - Write about your eventful debugging journey, if you have experienced one. -

    -

    -

    -

    +
    + Show screenshots of a mesh before and after some edge splits. +

    +

    +

    +
    +
    -
    +
    + Show screenshots of a mesh before and after a combination of both edge splits and edge flips. +

    +

    +

    +
    +
    -
    - Extra Credit: If you have implemented support for boundary edges, show screenshots of your implementation properly - handling split operations on boundary edges. -

    -

    -

    -
    -
    +
    + Write about your eventful debugging journey, if you have experienced one. +

    +

    +

    +

    -

    Part 6: Loop Subdivision for Mesh Upsampling

    -
    - Briefly explain how you implemented the loop subdivision and describe any interesting implementation / - debugging tricks you have used. - -

    - I decided to follow the order of operations as described in the spec. Here are the formal steps I took - to implement the loop subdivision: -

      -
    1. - First, I iterated through all of the vertices in mesh using a for loop over the - mesh.verticesBegin() and mesh.verticesEnd() iterators. For each vertex, I - found all of the neighbors that were connected to it and then computed the new position by weighting - it as the sum following the formula from lecture. I then set the vertex->newPosition to - this weighted position and the vertex->isNew to false because this was not - a newly created vertex. -
    2. -
    3. - Next, I iterated through all of the edges in the mesh using a for loop over the - mesh.EdgesBegin() and mesh.EdgesEnd() iterators. For each edge, I found - the vertex and face that it was connected to and then computed the new position by weighting it as - the sum following the formula from lecture. I then set the e->newPosition to this - weighted position and the e->isNew to false because this was not a newly - created edge. -
    4. -
    5. - Then, I iterated through all of these edges in the original mesh again in order to split each of - them and updated their position to be that of the previously computed new position stored in the - edge. -
    6. -
    7. - Afterwards, I iterated through all the edges in the mesh and flipped any of the newly created edges - that connected an old and new vertex. -
    8. -
    9. - Finally, I iterated through all of the vertices to set their position to the previously computed new - position stored in the vertex. -
    10. -
    -

    -
    +
    -
    +
    + Extra Credit: If you have implemented support for boundary edges, show screenshots of your implementation + properly + handling split operations on boundary edges. +

    +

    +

    +
    +
    -
    - Take some notes, as well as some screenshots, of your observations on how meshes behave after loop - subdivision. What happens to sharp corners and edges? Can you reduce this effect by pre-splitting some - edges? -

    -

    -

    -
    +

    Part 6: Loop Subdivision for Mesh Upsampling

    +
    + Briefly explain how you implemented the loop subdivision and describe any interesting implementation / + debugging tricks you have used. -
    +

    + I decided to follow the order of operations as described in the spec. Here are the formal steps I took + to implement the loop subdivision: +

      +
    1. + First, I iterated through all of the vertices in mesh using a for + loop over the + mesh.verticesBegin() and mesh.verticesEnd() + iterators. For each vertex, I + found all of the neighbors that were connected to it and then computed the new position by weighting + it as the sum following the formula from lecture. I then set the vertex->newPosition to + this weighted position and the vertex->isNew to false because this was not + a newly created vertex. +
    2. +
    3. + Next, I iterated through all of the edges in the mesh using a for + loop over the + mesh.EdgesBegin() and mesh.EdgesEnd() iterators. For each edge, I found + the vertex and face that it was connected to and then computed the new position by weighting it as + the sum following the formula from lecture. I then set the e->newPosition to this + weighted position and the e->isNew to false because this was not a newly + created edge. +
    4. +
    5. + Then, I iterated through all of these edges in the original mesh again in order to split each of + them and updated their position to be that of the previously computed new position stored in the + edge. +
    6. +
    7. + Afterwards, I iterated through all the edges in the mesh and flipped any of the newly created edges + that connected an old and new vertex. +
    8. +
    9. + Finally, I iterated through all of the vertices to set their position to the previously computed new + position stored in the vertex. +
    10. +
    +

    +
    +
    -
    - Load dae/cube.dae. Perform several iterations of loop subdivision on the cube. Notice that the cube - becomes - slightly asymmetric after repeated subdivisions. Can you pre-process the cube with edge flips and splits - so - that the cube subdivides symmetrically? Document these effects and explain why they occur. Also explain - how - your pre-processing helps alleviate the effects. - -

    -

    -

    -
    -
    +
    + Take some notes, as well as some screenshots, of your observations on how meshes behave after loop + subdivision. What happens to sharp corners and edges? Can you reduce this effect by pre-splitting some + edges? +

    +

    +

    +
    -
    - If you have implemented any extra credit extensions, explain what you did and document how they work - with - screenshots. -

    - I did not implement any extra credit extensions. -

    -
    -
    +
    + + +
    + Load dae/cube.dae. Perform several iterations of loop subdivision on the cube. Notice that the cube + becomes + slightly asymmetric after repeated subdivisions. Can you pre-process the cube with edge flips and splits + so + that the cube subdivides symmetrically? Document these effects and explain why they occur. Also explain + how + your pre-processing helps alleviate the effects. + +

    +

    +

    +
    +
    -

    Part 7 (Optional, Possible Extra Credit)

    - + -
    +
    diff --git a/hw3/Images/bunny.png b/hw3/Images/bunny.png new file mode 100644 index 0000000..186c627 Binary files /dev/null and b/hw3/Images/bunny.png differ diff --git a/hw3/index.html b/hw3/index.html index c30176b..9660533 100644 --- a/hw3/index.html +++ b/hw3/index.html @@ -1,7 +1,542 @@ - - - - - Homework 3 index.html here - + + + + + + + + CS 184 Mesh Edit + + + + + + + + + + + +

    CS 184: Computer Graphics and Imaging, Spring 2024

    +

    Homework + 3: PathTracer

    +

    Ian Dong

    + +

    + + + +
    + +

    Overview

    + In this homework, I implemented a path tracing renderer. First, I worked on generating camera rays from image space + to sensor in camera space and their intersection with triangles and spheres. Then, I built a bounding volume + hierarchy to accelerate ray intersection tests and speed up the path tracers rendering. Afterwards, I explored + direct illumination to simulate light sources and render images with realistic shadowing. Then, I implemented global + illumination to simulate indirect lighting and reflections using diffuse BSDF. Finally, I implemented adaptive sampling to reduce noise + in the rendered images. +
    + + + +
    + +
    My bunny is the bounciest bunny
    +
    +
    +
    + +

    Section 1: Ray Generation and Scene Intersection (20 Points)

    + + +

    + Walk through the ray generation and primitive intersection parts of the rendering pipeline. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + +

    + Explain the triangle intersection algorithm you implemented in your own words. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + +

    + Show images with normal shading for a few small .dae files. +

    + +
    + + + + + + + + + +
    + +
    example1.dae
    +
    + +
    example2.dae
    +
    + +
    example3.dae
    +
    + +
    example4.dae
    +
    +
    +
    + + +

    Section 2: Bounding Volume Hierarchy (20 Points)

    + + +

    + Walk through your BVH construction algorithm. Explain the heuristic you chose for picking the splitting point. +

    +

    + YOUR RESPONSE GOES HERE +

    + +

    + Show images with normal shading for a few large .dae files that you can only render with BVH acceleration. +

    + +
    + + + + + + + + + +
    + +
    example1.dae
    +
    + +
    example2.dae
    +
    + +
    example3.dae
    +
    + +
    example4.dae
    +
    +
    +
    + +

    + Compare rendering times on a few scenes with moderately complex geometries with and without BVH acceleration. + Present your results in a one-paragraph analysis. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + +

    Section 3: Direct Illumination (20 Points)

    + + +

    + Walk through both implementations of the direct lighting function. +

    +

    + YOUR RESPONSE GOES HERE +

    + +

    + Show some images rendered with both implementations of the direct lighting function. +

    + +
    + + + + + + +
    + + + + +
    + + + + +
    +
    + Uniform Hemisphere Sampling + + Light Sampling +
    + +
    example1.dae
    +
    + +
    example1.dae
    +
    + +
    example2.dae
    +
    + +
    example2.dae
    +
    +
    +
    + +

    + Focus on one particular scene with at least one area light and compare the noise levels in soft shadows + when rendering with 1, 4, 16, and 64 light rays (the -l flag) and with 1 sample per pixel (the -s flag) using + light sampling, not uniform hemisphere sampling. +

    + +
    + + + + + + + + + +
    + +
    1 Light Ray (example1.dae)
    +
    + +
    4 Light Rays (example1.dae)
    +
    + +
    16 Light Rays (example1.dae)
    +
    + +
    64 Light Rays (example1.dae)
    +
    +
    +

    + YOUR EXPLANATION GOES HERE +

    +
    + +

    + Compare the results between uniform hemisphere sampling and lighting sampling in a one-paragraph analysis. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + + +

    Section 4: Global Illumination (20 Points)

    + + +

    + Walk through your implementation of the indirect lighting function. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + +

    + Show some images rendered with global (direct and indirect) illumination. Use 1024 samples per pixel. +

    + +
    + + + + + +
    + +
    example1.dae
    +
    + +
    example2.dae
    +
    +
    +
    + +

    + Pick one scene and compare rendered views first with only direct illumination, then only indirect illumination. + Use 1024 samples per pixel. (You will have to edit PathTracer::at_least_one_bounce_radiance(...) in your code to + generate these views.) +

    + +
    + + + + + +
    + +
    Only direct illumination (example1.dae)
    +
    + +
    Only indirect illumination (example1.dae)
    +
    +
    +
    +

    + YOUR EXPLANATION GOES HERE +

    +
    + +

    + For CBbunny.dae, compare rendered views with max_ray_depth set to 0, 1, 2, 3, and 100 (the -m flag). Use 1024 + samples per pixel. +

    + +
    + + + + + + + + + + + + +
    + +
    max_ray_depth = 0 (CBbunny.dae)
    +
    + +
    max_ray_depth = 1 (CBbunny.dae)
    +
    + +
    max_ray_depth = 2 (CBbunny.dae)
    +
    + +
    max_ray_depth = 3 (CBbunny.dae)
    +
    + +
    max_ray_depth = 100 (CBbunny.dae)
    +
    +
    +
    +

    + YOUR EXPLANATION GOES HERE +

    +
    + +

    + Pick one scene and compare rendered views with various sample-per-pixel rates, including at least 1, 2, 4, 8, + 16, 64, and 1024. Use 4 light rays. +

    + +
    + + + + + + + + + + + + + + + + +
    + +
    1 sample per pixel (example1.dae)
    +
    + +
    2 samples per pixel (example1.dae)
    +
    + +
    4 samples per pixel (example1.dae)
    +
    + +
    8 samples per pixel (example1.dae)
    +
    + +
    16 samples per pixel (example1.dae)
    +
    + +
    64 samples per pixel (example1.dae)
    +
    + +
    1024 samples per pixel (example1.dae)
    +
    +
    +
    +

    + YOUR EXPLANATION GOES HERE +

    +
    + + +

    Section 5: Adaptive Sampling (20 Points)

    + + +

    + Explain adaptive sampling. Walk through your implementation of the adaptive sampling. +

    +

    + YOUR RESPONSE GOES HERE +

    +
    + +

    + Pick two scenes and render them with at least 2048 samples per pixel. Show a good sampling rate image with + clearly visible differences in sampling rate over various regions and pixels. Include both your sample rate + image, which shows your how your adaptive sampling changes depending on which Section of the image you are + rendering, and your noise-free rendered result. Use 1 sample per light and at least 5 for max ray depth. +

    + +
    + + + + + + + + + +
    + +
    Rendered image (example1.dae)
    +
    + +
    Sample rate image (example1.dae)
    +
    + +
    Rendered image (example2.dae)
    +
    + +
    Sample rate image (example2.dae)
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/index.html b/index.html index 3ca4f0d..fae500e 100644 --- a/index.html +++ b/index.html @@ -4,13 +4,13 @@

    CS184/284A Homework Webpages



    - Homework 1 + Homework 1

    - Homework 2 + Homework 2

    - Homework 3 + Homework 3

    - Homework 4 + Homework 4