Simple openGL shader renderer in C++ displacement mapping and hair growing generation. Developed in the context of the second homework of the fundamentals of computer graphics course held by Prof. Fabio Pellacini.
In your second assignment, you will implement a fragment shader and smooth curves and surfaces and add textures to a simple OpenGL renderer on the GPU. This will show you how a remarkable amount of complexity can be quickly achieved in interactive rendering applications.
You are to implement the code left blank in model_fragment.glsl
for fragment shading and tesselation.cpp
for curves and surfaces. You will implement these features.
-
Compute fragment colors (
shade_fragment.glsl
). Compute fragment colors by implementing ambient light and Blinn-Phong shading with points lights. All variables are already bound for you and the vertex shader is providing the proper transformed data. This code will look remarkably similar to your raytracer code. Note that for this to work, you have to symlink (or manually copy) the shaders in the test directory. -
Bezier curves (
tesselation.cpp#subdivide_bezier
). Implement Bezier subdivision using the De Casteljau algorithm applied recursively to eachbezier
segment. In doing so, ensure that the the vertex shared by the two splines for each subdivision has the same index. Implement subdivision for position only, then call thesmooth_tangent
function. Ignore texture coordinates. -
Catmull-Clark subdivision (
tesselation.cpp#subdivide_catmullclark
). Implement recursive Catmull-Clark subdivision with the simplified algorithm given in the class. Implement subdivision only for positionspos
. You will compute normals with eitherfacet_normals
orsmooth_normals
based on thesmooth
parameter. To simplify development, we have given you a class to compute unique edgesEdgeMap
. To use it, add all triangles and quads, and then look up the edge index withEdgeMap::edge_index
. To test your mesh, usefacet_normals
right before returning the mesh. For triangles, split them in three quads still using the edge vertices and face center. -
Normal smoothing (
tesselation.cpp#smooth_normals
). Implement normal smoothing with the pseudocode given in class. Add normal smoothing to the subdivision code. -
Textures.
- Textures are loded into OpenGL for you and texture coordinates are already specified. You only have to implement the code in the fagment shader for it.
- Diffuse and Specular texturing (
model_fragment.glsl
). Compute diffuse colorkd
by multiply the material diffuse responsematerial_kd
by the value looked up in the texturematerial_kd_txt
if the texture is enabledmaterial_kd_txt_on
(if not, just use the material color). Do the same for the specular color. Use these values to compute lighting. - Normal mapping (
model_fragment.glsl
). If enabled, copy normal values directly from the normal map. Normals are encoded scaled ans shifted, so get them from the texture by multiplying by 2, subtracting 1 and normalizing them.
-
Implement displacement mapping. Take a heavily subdivided quad and a bump map (greyscale image with heights). Move the vertex position along the vertex normal by a quantity proportional to the bump map. Smooth normals at the end.
-
Implement hair growing. Take a triangle mesh and grow random hair uniformly on it. For each hair, you need to follow three steps:
- Pick a triangle. For a not so good look, just randomly pick a triangle. For a better distribution, picka triangle proportinal to its area (using
std::discrete_distribution
where the weight are the triangle areas). - Pick a point on a triangle by selecting baricentric coordinates as u = 1 - sqrt(r1) and v = r2 * sqrt(r1) where r1 and r2 are random numbers on [0,1).
- Grow hair. For example create a line from the position p to p + n * l, where n is the normal and l the hair length (maybe random).
- Pick a triangle. For a not so good look, just randomly pick a triangle. For a better distribution, picka triangle proportinal to its area (using