Skip to content

XinCastle/Project4-CUDA-Rasterizer

 
 

Repository files navigation

CUDA Rasterizer

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)

.

Description&Features


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 in Progress


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

__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.

.

Point and lines Primitives Optimization


  • 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.

About

CIS565: CUDA Rasterizer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C 43.8%
  • C++ 23.7%
  • CMake 23.6%
  • Cuda 6.9%
  • GLSL 1.9%
  • Makefile 0.1%