[Stanley.Hayes]
  • About Stan
  • Projects
  • Resume
  • SubRay Website
  • ShaderToy Submissions
  • Triangle Rasterizer(C++)
  • 2d MetaBall Shader(HLSL)
  • Edge Light Shader(HLSL)
  • 2d "Wibble" shader (HLSL)
  • Valintines day shader
  • Blog

CODE SAMPLE - SIMPLE TRIANGLE Rasterizer

This is a simple software triangle rasterizer using just set-pixel.
It takes 3 vertices in screen space and renders a triangle between them. To the right is an example of how this rasterizer can be used to render a 3D scene. All the models in the scene to the right were stored in world space then before being rendered were translated to screen space and rendered with this function. 
Picture
//
// Rasterize a Simple Triangle
//
void DrawTri(Vertex v1, Vertex v2, Vertex v3, unsigned char * texture, unsigned char drawtype)
{
	//T for Top, M for Middle, B for Bottom
	//Note: Short var names for readability
	Vertex T, M, B; 
	bool Left; 
	//find which vertex is the T, M and B
	getTMB(v1, v2, v3, T, M, B, Left); 

	float xL, xR; 
	//Set to top
	xL = T.pos.x; 
	xR = T.pos.x; 
	
	int x, y; 
	float mR, mL;

	//Top Half
	//Calc inverse slopes
	if(Left){
		mL = (M.pos.x - T.pos.x) / (float)(M.pos.y - T.pos.y);
		mR = (B.pos.x - T.pos.x) / (float)(B.pos.y - T.pos.y); 
	}
	else{
		mL = (B.pos.x - T.pos.x) / (float)(B.pos.y - T.pos.y); 
		mR = (M.pos.x - T.pos.x) / (float)(M.pos.y - T.pos.y); 
	}

	//Preping for cross product to find abc for to get the increments
	Vector3 VecU, VecV; 
	VecU.x = (float)M.pos.x - T.pos.x; 
	VecU.y = (float)M.pos.y - T.pos.y; 
	VecU.z = M.color.r - T.color.r; 

	VecV.x = (float)B.pos.x - T.pos.x; 
	VecV.y = (float)B.pos.y - T.pos.y; 
	VecV.z = B.color.r - T.color.r; 

	Vector3 vR = Vector3::cross(VecU, VecV); 
	
	//since the z is the only thing that changes we only need to update .z
	VecU.z = M.color.g - T.color.g; 
	VecV.z = B.color.g - T.color.g;

	Vector3 vG = Vector3::cross(VecU, VecV); 
	
	VecU.z = M.color.b - T.color.b; 
	VecV.z = B.color.b - T.color.b; 

	Vector3 vB = Vector3::cross(VecU, VecV);

	VecU.z = M.uv.x - T.uv.x; 
	VecV.z = B.uv.x - T.uv.x;

	Vector3 vtcU = Vector3::cross(VecU, VecV);

	VecU.z = M.uv.y - T.uv.y; 
	VecV.z = B.uv.y - T.uv.y; 

	Vector3 vtcV = Vector3::cross(VecU, VecV); 
	
	float innerR, innerG, innerB, innerV, innerU; //inner increment for r,g,b, V and U
	float outerR, outerG, outerB, outerV, outerU; //outer increment


	//calculating the OUTER RGB increments
	outerR = (-vR.x * (float)mL - vR.y) / vR.z; 
	outerG = (-vG.x * (float)mL - vG.y) / vG.z; 
	outerB = (-vB.x * (float)mL - vB.y) / vB.z; 
	outerU = (-vtcU.x * (float)mL - vtcU.y) / vtcU.z; 
	outerV = (-vtcV.x * (float)mL - vtcV.y) / vtcV.z; 

	//calculating the INNER RGB increments
	innerR = -vR.x / (float)vR.z; 
	innerG = -vG.x / (float)vG.z; 
	innerB = -vB.x / (float)vB.z; 
	innerU = -vtcU.x / (float)vtcU.z;
	innerV = -vtcV.x / (float)vtcV.z;
	
	//initial r,g,b these values will be incremented
	//temp values for use in incrementing across the x axis
	float currR, currG, currB, currU, currV;
	float tempR, tempG, tempB, tempU, tempV; 

	currR = T.color.r;
	currG = T.color.g; 
	currB = T.color.b;
	currU = T.uv.x; 
	currV = T.uv.y; 

	tempR = currR; 
	tempB = currB; 
	tempG = currG; 
	tempV = currV;
	tempU = currU; 

	for(y = ceil(T.pos.y); y < ceil(M.pos.y); y++){
		//calc right xl and xr
		for(x = xL; x < ceil(xR); x++){
			SetPixelBlending(texture, tempU, tempV, x, y, drawtype, tempR, tempG, tempB); 

			tempR += innerR; 
			tempG += innerG;
			tempB += innerB; 
			tempU += innerU; 
			tempV += innerV; 
		}

		xL += mL; 
		xR += mR; 

		currR += outerR; 
		currB += outerB;
		currG += outerG;
		currU += outerU; 
		currV += outerV; 

		tempR = currR; 
		tempB = currB; 
		tempG = currG; 
		tempV = currV; 
		tempU = currU; 
	}

	//Bottom Half
	if(Left){
		mL = (B.pos.x - M.pos.x) / (float)(B.pos.y - M.pos.y);
		
		outerR = (-vR.x * (float)mL - vR.y) / vR.z; 
		outerG = (-vG.x * (float)mL - vG.y) / vG.z; 
		outerB = (-vB.x * (float)mL - vB.y) / vB.z; 
		outerU = (-vtcU.x * (float)mL - vtcU.y) / vtcU.z; 
		outerV = (-vtcV.x * (float)mL - vtcV.y) / vtcV.z; 
		xL = M.pos.x;
	}
	else{
		mR = (B.pos.x - M.pos.x) / (float)(B.pos.y - M.pos.y); 
		xR = M.pos.x; 
	}

	//second fill loop
	for(y = ceil(M.pos.y); y < ceil(B.pos.y); y++){
		//calc right xl and xr
		for(x = ceil(xL); x < ceil(xR); x++){
			SetPixelBlending(texture, tempU, tempV, x, y, drawtype, tempR, tempG, tempB); 
			
			tempR += innerR; 
			tempG += innerG;
			tempB += innerB;
			tempU += innerU; 
			tempV += innerV; 
		}
		xL += mL; 
		xR += mR; 

		currR += outerR; 
		currB += outerB;
		currG += outerG;
		currV += outerV; 
		currU += outerU; 

		tempR = currR; 
		tempB = currB; 
		tempG = currG; 
		tempV = currV; 
		tempU = currU; 
	}

}
Powered by Create your own unique website with customizable templates.