| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #include "softwareRenderer.h"
- #include "shader.h"
- #include "mesh.h"
- SoftwareRenderer::SoftwareRenderer(){}
- SoftwareRenderer::~SoftwareRenderer(){}
- bool SoftwareRenderer::startUp(int w, int h){
- if( !createBuffers(w, h) ){
- return false;
- }
- startUpComplete = true;
- return true;
- }
- void SoftwareRenderer::shutDown(){
- mCamera = nullptr;
- if (startUpComplete){
- delete zBuffer;
- delete pixelBuffer;
- }
- }
- void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
- //Getting the vertices, faces
- Mesh *triMesh = currentModel->getMesh();
- std::vector<Vector3i> * vIndices = &triMesh->vertexIndices;
- std::vector<Vector3i> * nIndices = &triMesh->normalsIndices;
- std::vector<Vector3f> * vertices = &triMesh->vertices;
- std::vector<Vector3f> * normals = &triMesh->normals;
- int numFaces = triMesh->numFaces;
- //Array grouping vertices together into triangle
- Vector3f trianglePrimitive[3];
- Vector3f normalPrim[3];
- //Initializing shader
- BlinnPhongShader shader;
- //Basic light direction
- float t = static_cast<float>(SDL_GetTicks());
- float radius = 1;
- float lX = std::sin(t/2000) * radius;
- float lY = std::cos(t/2000) * radius;
- Vector3f lightDir{lX, lY, 0};
- Vector3f viewDir;
- //Building ModelViewProjection matrix
- shader.MV = (mCamera->viewMatrix)*(currentModel->getModelMatrix());
- shader.MVP = (mCamera->projectionMatrix)*shader.MV;
- shader.V = (mCamera->viewMatrix);
- shader.N = (shader.MV.inverse()).transpose();
- //Iterate through every triangle
- for (int j = 0; j < numFaces; ++j){
- //Current vertex and normal indices
- Vector3i f = (*vIndices)[j];
- Vector3i n = (*nIndices)[j];
- //Pack vertex and normal data together into an array
- buildTri(f,trianglePrimitive, *vertices);
- buildTri(n,normalPrim, *normals);
- //Skip faces that are pointing away from us
- //Apply vertex shader
- for(int i = 0; i < 3; ++i){
- trianglePrimitive[i] = shader.vertex(trianglePrimitive[i], normalPrim[i], lightDir.normalized(), i);
- }
- //Skip triangles that are outside viewing frustrum
- //Does not rebuild triangles that are partially out TO DO
- if (clipTriangles(trianglePrimitive)) continue;
- perspectiveDivide(trianglePrimitive);
- //Send to rasterizer which will also call the fragment shader and write to the
- //zbuffer and pixel buffer.
- Rasterizer::drawTriangles(trianglePrimitive, shader, pixelBuffer, zBuffer);
- }
- }
- void SoftwareRenderer::clearBuffers(){
- zBuffer->clear();
- pixelBuffer->clear();
- }
- Buffer<Uint32>* SoftwareRenderer::getRenderTarget(){
- return pixelBuffer;
- }
- void SoftwareRenderer::setCameraToRenderFrom(Camera * camera){
- mCamera = camera;
- }
- bool SoftwareRenderer::createBuffers(int w, int h){
- int pixelCount = w*h;
- bool success = true;
- zBuffer = new Buffer<float>(w, h, new float[pixelCount]);
- if( zBuffer == nullptr){
- printf("Could not build z-Buffer.\n");
- success = false;
- }
- else{
- pixelBuffer = new Buffer<Uint32>(w, h, new Uint32[pixelCount]);
- if( pixelBuffer == nullptr){
- printf("Could not build pixel Buffer.\n");
- success = false;
- }
- }
- return success;
- }
- void SoftwareRenderer::buildTri(Vector3i &index, Vector3f *primitive, std::vector<Vector3f> &vals){
- for(int i = 0; i < 3; ++i){
- primitive[i] = vals[index.data[i]];
- }
- }
- bool SoftwareRenderer::backFaceCulling(Vector3f *trianglePrim, Vector3f &viewDir){
- //Triangle surface normal
- //Should probably be calculated on load next time
- Vector3f N1 = trianglePrim[1] - trianglePrim[0];
- Vector3f N2 = trianglePrim[2] - trianglePrim[0];
- Vector3f N = (N1.crossProduct(N2)).normalized();
- viewDir = mCamera->position - trianglePrim[0];
- viewDir.normalized();
- //Returns false if the triangle cannot see the camera
- float intensity = N.dotProduct(viewDir);
- return intensity <= 0.0;
- }
- bool SoftwareRenderer::clipTriangles(Vector3f *clipSpaceVertices){
- int count = 0;
- for(int i = 0; i < 3; ++i){
- Vector3f vertex = clipSpaceVertices[i];
- bool inside = (-vertex.w <= vertex.x <= vertex.w )
- && (-vertex.w <= vertex.y <= vertex.w)
- && (0 <= vertex.z <= vertex.w);
- if (!inside) ++count;
- }
- //If count equals three it means every vertex was out so we skip it
- return count == 3 ;
- }
- void SoftwareRenderer::perspectiveDivide(Vector3f *clippedVertices){
- for(int i = 0; i < 3; ++i){
- clippedVertices[i].perspectiveDivide();
- }
- }
|