CSC 471 Final Project - Spring 2017
For my Introduction to Graphics final project, I built a tool to allow users to sculpt terrain from a plane. This is a type of tool found in game engine editors and some 3D modeling applications to allow artists to craft custom terrain for games or movies.
The plane is a created at runtime by generating an array of verticies and generating the face indicies to connect them all. My tool has two starting points for sculpting: a flat plane and a plane of sine wave hills. When the user exits free camera mode and enter the editing mode, a cursor appears on the plane. The user is able to move the cusor with the mouse. The cursor takes the user's current view rotation into account to move relative to the user's view.
The user can deform the terrain by clicking the mouse to raise terrain or shift + clicking the mouse to lower terrain. The terrain is deformed with Gaussian hills which are calculated using the Gaussian function. The user can adjust the sharpness of the Gaussian hill to create sharper or smoother terrain. The amount the terrain is raised or lowered by is based on the current deformation speed which the user can adjust. The user can also adjust the size of the brush and the smoothness of the deformation.
Since deforming the plane required modifying the VBO, I had to take performance into consideration. Moving the VBO with hundreds of thousands of elements to the GPU is very computationally expensive. To address this issue, I used the OpenGL function glBufferSubData which allows you to update a piece of the VBO instead of having to pass the entire thing to the GPU. This drastically increased the runtime performance of my application.
Additionally, I added a few shading options for the terrain. The user can cycle through a flat gray color, a brown color which looks better with grass, and a height based coloring which makes higher terrain more green and lower terrain more purple. The user can also cycle between wireframe mode to either show or hide a wireframe of the terrain.
To create grass over the terrain, I wanted to try working with geometry shaders. The geometry shader sits between the vertex shader and the fragment shader in the graohics pipeline. It takes in primitives defined in the vertex and allows you to generate new primitives from those. To create grass in my terrain sculptor, I had the geometry shader take in triangles from the vertex shader and add blades of grass (modeled with three triangles) within the bounds of the triangle. I then used the sine of the current time to add a little sway to the grass and added height based shading in the fragment shader.
For fun, I also added a "techno mode" shading for the grass. By activating this mode this, the grass will pulse with vibrant colors based on its height in the world.
To add a skybox to the world, I used a simple cubemap textured with a skybox texture I found online (link can be found in references below). The translation of the cubemap is restricted so that it stays at the origin and the user can never leave it. The depth test is diabled when drawing the cubemap.