/****************************************************************************** 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; };