CSC3223_Graphics_For_Games_Software_Rasteriser / SoftwareRasteriser / SoftwareRasteriser.h
SoftwareRasteriser.h
Raw
/******************************************************************************
Class:SoftwareRasteriser
Implements:Window
Author:Rich Davison	<richard.davison4@newcastle.ac.uk>
Description: Class to encapsulate the various rasterisation techniques looked
at in the course material.
This is the class you'll be modifying the most!
-_-_-_-_-_-_-_,------,
_-_-_-_-_-_-_-|   /\_/\   NYANYANYAN
-_-_-_-_-_-_-~|__( ^ .^) /
_-_-_-_-_-_-_-""  ""
*/ /////////////////////////////////////////////////////////////////////////////

#pragma once

#include "Matrix4.h"
#include "Mesh.h"
#include "Texture.h"
#include "RenderObject.h"
#include "Common.h"
#include "Window.h"

#include <vector>

using std::vector;

struct BoundingBox
{
	Vector2 topLeft;
	Vector2 bottomRight;
};

enum TextureSampleMode
{
  SAMPLE_NEAREST,
  SAMPLE_BILINEAR,
  SAMPLE_MIPMAP_NEAREST,
  SAMPLE_MIPMAP_BILINEAR
};

enum BlendSampleMode 
{
	SAMPLE_BLEND_ADDITION,
	SAMPLE_BLEND_REPLACE,
	SAMPLE_BLEND_ALPHA
	
};

class RenderObject;
class Texture;

class SoftwareRasteriser : public Window
{
public:
	SoftwareRasteriser(uint width, uint height);
	~SoftwareRasteriser(void);

	void DrawObject(RenderObject *o);

	void ClearBuffers();
	void SwapBuffers();

	inline void SetViewMatrix(const Matrix4 &m)
	{
		viewMatrix = m;
		viewProjMatrix = projectionMatrix * viewMatrix;
	}

	/*void SetViewMatrix(const Matrix4 &m)
	{
		viewMatrix = m;
		viewProjMatrix = projectionMatrix * viewMatrix;
	}*/

	inline void SetProjectionMatrix(const Matrix4 &m)
	{
		projectionMatrix = m;
		viewProjMatrix = projectionMatrix * viewMatrix;
	}

	BoundingBox CalculateBoxForTri(const Vector4 &a, const Vector4 &b, const Vector4 &c);

	static float ScreenAreaOfTri(const Vector4 &v0, const Vector4 &v1, const Vector4 &v2);

	inline bool DepthFunc(int x, int y, float depthValue);

	Texture *currentTexture;

	void SwitchTextureFiltering() {
		if (texSampleState == SAMPLE_NEAREST) {
			texSampleState = SAMPLE_NEAREST;
		}
		else if (texSampleState == SAMPLE_BILINEAR) {
			texSampleState = SAMPLE_MIPMAP_NEAREST;
		}
		else {
			texSampleState = SAMPLE_NEAREST;
		}
	}

  void SetTextureSamplingMode(TextureSampleMode mode)
  {
    texSampleState = mode;
  }

  TextureSampleMode GetTextureSamplingMode()
  {
    return texSampleState;
  }

  void SetBlendSamplingMode(BlendSampleMode mode)
  {
    blendSampleState = mode;
  }

  BlendSampleMode GetBlendSamplingMode()
  {
    return blendSampleState;
  }

  

 




  //Draw Line
  void RasteriseLine(const Vector4 &v0, const Vector4 &v1,
	  const Colour &colA = Colour(255, 255, 255, 255),
	  const Colour &colB = Colour(255, 255, 255, 255),
	  const Vector3 &texA = Vector3(0, 0, 0),
	  const Vector3 &texB = Vector3(1, 1, 1));

  void RasteriseTri(const Vector4 &triA, const Vector4 &triB, const Vector4 &triC,
	  const Colour &colA = Colour(), const Colour &colB = Colour(),
	  const Colour &colC = Colour(), const Vector3 &texA = Vector3(),
	  const Vector3 &texB = Vector3(), const Vector3 &texC = Vector3());

  bool RasteriseCohenLine(Vector4 &v0, Vector4 &v1, Colour &colA, Colour &colB, Vector3 &texA, Vector3 &texB);

  void RasteriseHodgmanTri(Vector4 &triA, Vector4 &triB, Vector4 &triC, const Colour &colA, const Colour &colB, const Colour &colC, const Vector2 &texA, const Vector2 &texB, const Vector2 &texC);

  float RefineEdges(const Vector4 &v0, const Vector4 &v1, int edge);

  int OutPixel(const Vector4 &input);

  void RasteriseTriSpans(const Vector4 &triA, const Vector4 &triB, const Vector4 &triC,
	  const Colour &colA, const Colour &colB, const Colour &colC,
	  const Vector3 &texA, const Vector3 &texB, const Vector3 &t2texC);

  void SoftwareRasteriser::RasteriseTriEdgeSpans(const Vector4 &triA, const Vector4 &triB,
	  const Vector4 &triC, const Vector4 &triD);

  void CalculateWeights(const Vector4 &v0, const Vector4 &v1, const Vector4 &v2, const Vector4 &p,
	  float &alpha, float &beta, float &gamma);

protected: 
  Colour *GetCurrentBuffer();

  TextureSampleMode texSampleState;
  BlendSampleMode blendSampleState;

  virtual void Resize();

  inline void ShadePixel(uint x, uint y, const Colour &c) {
	  if (y >= screenHeight) {
		  return;
	  }
	  if (x >= screenWidth) {
		  return;
	  }
    int index = (y * screenWidth) + x;
    buffers[currentDrawBuffer][index] = c;
  }

  inline void BlendPixel(uint x, uint y, const Colour& source) {
	  if (y >= screenHeight || y < 0) {
		  return;
	  }
	  if (x >= screenWidth || x < 0) {
		  return;
	  }

    int index = (y * screenWidth) + x;

    Colour& dest = buffers[currentDrawBuffer][index];

	if (blendSampleState == SAMPLE_BLEND_ALPHA) {
		const unsigned char sFactor = source.a;
		const unsigned char dFactor = (255 - source.a);
		dest.r = ((source.r * sFactor) + (dest.r * dFactor)) / 255;
		dest.g = ((source.g * sFactor) + (dest.g * dFactor)) / 255;
		dest.b = ((source.b * sFactor) + (dest.b * dFactor)) / 255;
		dest.a = ((source.a * sFactor) + (dest.a * dFactor)) / 255;		
	}
	else if (blendSampleState == SAMPLE_BLEND_ADDITION) {
		dest = dest + source;
	}
	else {
		dest = source;
	}
  }

  int currentDrawBuffer;

  Colour *buffers[2];

  unsigned short *depthBuffer;

  void RasterisePointsMesh(RenderObject *o);
  void RasteriseLinesMesh(RenderObject *o);
  void RasteriseTriMesh(RenderObject *o);
  void RasteriseTriMeshStripPrimitives(RenderObject *o);
  void RasteriseTriMeshFanPrimitives(RenderObject *o);

  Matrix4 viewMatrix;
  Matrix4 projectionMatrix;
  Matrix4 textureMatrix;

  Matrix4 viewProjMatrix;
  Matrix4 portMatrix;
};