University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 4
- Xincheng Zhang
- Tested on: *Windows 10, i7-4702HQ @ 2.20GHz 8GB, GTX 870M 3072MB (Personal Laptop)
.
In this project, I use CUDA to implement a simplified rasterized graphics pipeline, similar to the OpenGL pipeline. Specific content and features are listed below.
Basic part: Rasterizer pipeline
- Vertex shading
- Primitive assembly with support for triangles read from buffers of index and vertex data
- Rasterization
- Fragment shading
- A depth buffer for storing and depth testing fragments
- Fragment-to-depth-buffer writing (with atomics for race avoidance)
- (Fragment shader) simple lighting scheme, Lambert and Blinn-Phong.
Extra part:
- Texture with perspective correctness and bilinear interpolation
- Point and line primitive implementation
- Optimization for point & line primitive by sampling vertices around bound and corner of bounding box
- (still working) SSAO & Tile base pipeline
.
Result Screenshot
- The duck and CesiumMilkTruck object with texture
- w/ perspective correctness & bilinear interpolation
- Blinn Phong and lambert are both implemented
.
Perspective Correct texture coordinate
- Original checkerboard texture:
- with perspective correctness:
- It's obvious that for the original one, the texture of checkerboard only appear to be correct on the angle of 45 degree and is twisted when we rotate the object. The perspective correctness solves this problem by using the method below. (reference: https://en.wikipedia.org/wiki/Texture_mapping)
#if PERSPECTIVE
glm::vec3 zbuffer(1.f / triEyePos[0].z, 1.f / triEyePos[1].z, 1.f / triEyePos[2].z);
glm::vec3 bottom(barycoord.x * zbuffer[0], barycoord.y * zbuffer[1], barycoord.z * zbuffer[2]);
float sumbot = bottom.x + bottom.y + bottom.z;
float denominator_inv = 1.f / sumbot;
glm::vec2 numerator = bottom.x * triTexcoord0[0] + bottom.y * triTexcoord0[1] + bottom.z * triTexcoord0[2];
dev_fragmentBuffer[pixelid].texcoord0 = numerator * denominator_inv;
#else
dev_fragmentBuffer[pixelid].texcoord0 = texB;
#endif
.
Bilinear Interpolation
- Original Checkerboard
- w/ Bilinear Interpolation
- The mosaic of original checkerboard is erased by applying bilinear interpolation method below. (reference: https://en.wikipedia.org/wiki/Bilinear_interpolation)
__device__
glm::vec3 bilinearInterpolation(float a, float b, glm::vec3 txy, glm::vec3 txplus1, glm::vec3 typuls1, glm::vec3 txyplus1)
{
glm::vec3 temp = (1.f - a) * txy + a * txplus1;
glm::vec3 temp1 = (1.f - a) * typuls1 + a * txyplus1;
return temp * (1.f - b) + temp1 * b;
}
.
Points and lines Primitives
- Points Primitives
- Lines Primitives
.
SSAO
- still working. Will update later.
.
- There is a problem of simply checking whether the point is inside the bounding box or not for points primitive implementation because there are a number of points whose fragment is in outside of bounding box but the point itself is in. In that case, the naive approach will lose many points which should be drawn.
- My approach: instead of checking whether the point is inside the box, I check whether the point is around the bounding box by setting a coefficient in barycentric function so that more points will show in the result. Same idea for lines (partial code for lines primitive condition below).
if (glm::abs(1 - glm::abs(barycentricCoord.x + barycentricCoord.y)) <= 0.07f && glm::abs(barycentricCoord.z) <= 0.07f) return true;
As the code above, do the same for the other two conditions to check lines primitives. Again, in this method, by modifying the value (0.07 for example), we can change the radius of the line we draw shown on the screen.







