--- title: "Graduation" description: "It's official!" pubDate: "Aug 16 2023" heroImage: "/post_images/graduation.jpg" --- Hi all, sorry for the huge delay in updates, hopefully you can cut me a just little slack... __as I finally graduated!__ I took an admittedly long break after classes ended in June and I am so happy to be able to say that I have officially completed my bachelor's degree in Computer Science. I was just going over some of my projects this afternoon as I continue to refine my CV and it's really incredible how far I've come. Like many of life's great moments I couldn't have done any of this without support, and I want to thank my partner Valerie. From the bottom of my heart, I appreciate all that you've done to help me on this journey. My final projects for Computer Graphics Shaders as well as Intro to Databases went exceptionally well. For my shaders class I chose to create a realistic motion blur based on documentation in Nvidia's [GPU Gems 3](https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-27-motion-blur-post-processing-effect). I was rather excited about this project and I'd like to go through a few details for anyone who might be interested, otherwise feel free to skip ahead. I used a two pass process with OpenGL and GLSL in which I first simply rendered an object to a texture. Then to create a per-fragment blur effect I sample the depth buffer in the fragment shader to find each pixel's current position and world position. // Sample depth buffer float dbAtPixel = texture(uDepthBuf, vec3(st, 1.)); // Find view position vec4 viewAtPixel = vec4(s * 2 - 1, (1 - t) * 2 - 1, dbAtPixel, 1); // Convert to world coords, -1 to 1 vec4 worldPos = viewAtPixel / viewAtPixel.w; Next, I multiply the world position by a "blur position" (a stand-in for the direction of movement) to find a previous position. This allows me to calculate a velocity. // No previous view in a static image, so we make one up with uBlurPos vec4 prevPos = worldPos * uBlurPos; // Put in range -1 to 1 prevPos = prevPos / prevPos.w; // Find pixel velocity and scale it if desired vec2 velocity = uVelScale * vec2((currPos - prevPos)/2.); In the third and final stage I sample the color buffer in a loop, using the velocity to cacluate each fragments color. The number of times the color buffer is sampled directly impacts the quality of the effect, with higher sample rates resulting in a smoother and more realistic blur. // Sample color buffer vec4 color = texture(uColorBuf, st); // Add velocity to st coords st += velocity; // Continue sampling color buffer until preferred number of samples is reached for (int i = 1; i < uNumSamples; ++i, st += velocity) { vec4 rgba = texture(uColorBuf, st); color += rgba; } // Average samples to get blur color color = color / uNumSamples; Of course, all of that was very boring if you don't know what it means. Let's see what it actually looks like! ![2D bunny with orange and red stripes](/post_images/graduation/bunny_no_blur.jpg) ![2D bunny with orange and red stripes and a low quality blur](/post_images/graduation/bunny_low_sample.jpg) ![2D bunny with orange and red stripes and a high quality blur](/post_images/graduation/bunny_high_sample.jpg) With those two classes completed I began the spring term and my final Capstone Project, a three month long grind to produce a complete piece of professional quality software. I was grouped with two other students and selected for the "3D Escape Room Game" - a video game intended to mimic the experience of a real life escape room. This was the first full video game we had ever created so naturally I was incredibly excited, but quite nervous too! I'll have a lot more to say about this project in the near future, I was required to write a few blog-style assignments so I intend on posting those as a series too. Unfortunately I don't think I'm allowed to make our code public, but on the bright side you will be able to download and actually play the game!