Sunday, December 2, 2012

Tessellation Shader

Added a Tessellation shader to the project. The Tessellation shader is made up of 3 parts (2 programmable and 1 fixed)
OpenGL Basic Rendering Pipeline

The flowchart above shows the basic OpenGL Rendering pipeline. In this project I have modified all the programmable stages shown in green above. The Tessellation shader consists of the Tessellation Control Shader which is called for every vertex coming out from the Vertex shader and they know what are the other vertices that make up the primitive. It is here that we assign the inner and outer tessellation levels for a triangle. The inner level determines how many concentric primitives will be created during tessellation of a single primitive; while the outer level determines how the concentric primitives will be attached to each other. The OpenGL Insights book - Chapter 6 explains this well. The OpenGL specifications for Tessellation shaders is also a good read. So once this is set, it is sent off to the Tessellator which does the actual tessellation by creating new vertices and primitives. The Tessellation Evaluation Shader (TES) is then called which I used to generate the actual coordinates of the vertices generated in world space. What comes out of the TES, in case of triangle primitives, are barycentric coordinates and in case of quads they are uv values. These can then be interpolated with the original primitive coordinates to get the final values.

This output from here is passed on to the Geometry Shader, where I calculate the normals for the primitives (details in previous blog post). Few images based on different tessellation levels are shown below. Right now I am doing a straight tessellation for all geometry present in the scene, which will be later changed to tessellation based on distance.
No Tessellation - 30 fps

Tessellation applied - Inner: 2, Outer: 2 - 9 fps

Tessellation applied - Inner: 3, Outer: 2 - 6 fps

I haven't yet displaced the tessellated vertices and so they appear on the same plane as the original primitive. Due to this, shading is not affected by tessellation currently.

Next Steps:
  • Displacement of tessellated vertices
  • Tessellation based on distance

Helpful Links:

Saturday, December 1, 2012

Geometry Shader

Added a geometry shader to the code for calculating face normals. The Geometry Shader is called after the Vertex assembly for each primitive. So it has all the information about a primitive, thus making it easy to calculate normals for a face. But the problem here is that shading will be flat for a single triangle which might not be an issue after I apply tessellation. Will have to wait and see when I implement tessellation. Below are images with diffuse lighting (A single directional light in the -ve y-direction)

Mesh structure

Diffuse Shading with normals

The terrain looks faceted with this change, with allowed to get some diffuse lighting.

Next Steps:
  • Tessellation

Basic Terrain

I was looking into different literature for generating terrains and finally decided to start off with the basic one - using height fields. The following is an algorithm to generate a simple terrain to start off with.

  • Get a heightfield (you can get it using an image or generate it using noise). I decided to use Perlin noise to create a heightfield.
  • Create a flat triangular mesh (flat = y-coordinate is same for all the vertices).
  • Perturb the vertices in the vertex shader using the heightfield values. The noise is generated in the vertex shader itself. More details on the noise generated below.
  • Shade the mesh in the fragment shader. Can shade with different colors based on elevation too.
The noise function that I used was adapted from http://www.sci.utah.edu/~leenak/IndStudy_reportfall/PNoiseCode.txt. Perlin noise generates random values based on a Hermite curve. This gives a continuous value for the randomly generated values. It randomly generates values based on a frequency that you pass in and generate a curve based oin these values. THe intermediate values are then determined using this curve. I clamped the output a bit so that I have more flat areas in my terrain.
Shown below are outputs generated from my first stab at the algorithm. The images display the mesh instead of the shaded polygons as I haven't yet calculated normals for the primitives.

 Basic Mesh Output

Terrain Depth

Color coded based on height

Next Steps:
  • Calculate normals for the primitives.
  • Shade terrain using the normal values (diffuse shading).
  • Tessellate the geometry using the Tessellation Shader.

Wednesday, November 21, 2012

Introduction

As my final project for the GPU Programming course, I have decided to implement procedural terrain generator using the Tesselation Shader available in latest versions of OpenGL.


Goal: Terrain Generation on the GPU with increasing level of detail using tessellation depending on the camera position.

This is inspired by my love for the outdoors, landscape photography and the work seen at TerraGen and Procedural Worlds.


Features I am planning to implement:
  • Basic Terrain Generation on the GPU using OpenGL
  • Use Tessellation shader available in newer versions of OpenGL.
  • Detect slope of terrains and change textures based on the slope.
Code:
The code for my implementation is present here (https://github.com/tijutv/GPU-Terrain-Generation).

References: