My university holds a 3D game development that was normally taught using OpenGL. However, this past year, the professor had changed the curriculum to use the Vulkan API to teach the class instead. He offered a C based seed project for students to start working in, but I had issues getting the project to build and run on my machine. In the end, I had decided to build the project from scratch using C++. I considered my Vulkan project as an experimental playground, so I decided to use it to experiment with writing shaders in the Vulkan.
My primary experience with shaders had been only in Unity prior to this class. Unity combines the fragment and vertex stages into a single file, so I had never had the opportunity to work with them in separate scripts. I had also had very little exposure to using GLSL prior to working in Vulkan, so the experience overall was very exciting to me.
The main model I was experimenting with.
I used basic vertex and fragment shaders to start in order to make sure that the graphics pipeline was functional. I didn’t do anything particularly fancy with it except for making sure it was capable of applying an RGB gradient across the available faces.
Once I was sure that the shaders were functioning without any issues, I moved on to writing a geometry shader. I chose to write a geometry shader since I had never actually written one, and really wanted to step outside my comfort zone.
I had to create shader modules for each shader file I planned to use, and then create a VkPipelineShaderStageCreateInfo object to prep the shader file to be used in the graphics pipeline. I also found that if the shader stages were not put in the right order in the shaderStages array, the executable would crash. I also figured out that the amount of shader stages had to be specified, otherwise a shader would be skipped. I had made the mistake of specifying only 2 shader stages, so my solution had errors in running the shader modules, as the information never made it to the fragment shader.
A snippet of the createGraphicsPipeline() function pertaining to the shader stages.
I had some difficulties writing the geometry shader, as some GLSL operations either didn’t work well in Vulkan or I simply wasn’t writing it properly to my inexperience. I decided to write a basic geometry shader that would draw lines from each of the model’s vertices to the origin of the model, seeing as I didn’t have enough experience to write anything more complex.
I applied a geometry shader to only the dog model. A house model was present to verify that the entity system was functional.
I included user input options to allow the user to move the model around and distort it. The user had the ability to alter the rotation angle, zoom in/out, and stretch the model along the x, y, and z axes. I had also included a sound manager to play background music (mostly for my own entertainment).
I had difficulties pushing to my initial GitHub repository due to some mistakes I made with my .gitignore file, so I had to push the final solution to a new repository. Although this was a minor issue, the repository containing the final changes to the project does not reflect the progress and changes between commits. The final result was not impressive whatsoever, but this class project inspired me to spend my free time learning GLSL. I really hope to revisit Vulkan once I have a better understanding of GLSL.
The repository for this project can be found on my GitHub account.