softwareRenderer.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "softwareRenderer.h"
  2. #include "shader.h"
  3. #include "mesh.h"
  4. SoftwareRenderer::SoftwareRenderer(){}
  5. SoftwareRenderer::~SoftwareRenderer(){}
  6. bool SoftwareRenderer::startUp(int w, int h){
  7. if( !createBuffers(w, h) ){
  8. return false;
  9. }
  10. startUpComplete = true;
  11. return true;
  12. }
  13. void SoftwareRenderer::shutDown(){
  14. mCamera = nullptr;
  15. if (startUpComplete){
  16. delete zBuffer;
  17. delete pixelBuffer;
  18. }
  19. }
  20. void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
  21. //Getting the vertices, faces
  22. Mesh *triMesh = currentModel->getMesh();
  23. std::vector<Vector3i> * vIndices = &triMesh->vertexIndices;
  24. std::vector<Vector3i> * nIndices = &triMesh->normalsIndices;
  25. std::vector<Vector3f> * vertices = &triMesh->vertices;
  26. std::vector<Vector3f> * normals = &triMesh->normals;
  27. int numFaces = triMesh->numFaces;
  28. //Array grouping vertices together into triangle
  29. Vector3f trianglePrimitive[3];
  30. Vector3f normalPrim[3];
  31. //Initializing shader
  32. BlinnPhongShader shader;
  33. //Basic light direction
  34. float t = static_cast<float>(SDL_GetTicks());
  35. float radius = 1;
  36. float lX = std::sin(t/2000) * radius;
  37. float lY = std::cos(t/2000) * radius;
  38. Vector3f lightDir{lX, lY, 0};
  39. Vector3f viewDir;
  40. //Building ModelViewProjection matrix
  41. shader.MV = (mCamera->viewMatrix)*(currentModel->getModelMatrix());
  42. shader.MVP = (mCamera->projectionMatrix)*shader.MV;
  43. shader.V = (mCamera->viewMatrix);
  44. shader.N = (shader.MV.inverse()).transpose();
  45. //Iterate through every triangle
  46. for (int j = 0; j < numFaces; ++j){
  47. //Current vertex and normal indices
  48. Vector3i f = (*vIndices)[j];
  49. Vector3i n = (*nIndices)[j];
  50. //Pack vertex and normal data together into an array
  51. buildTri(f,trianglePrimitive, *vertices);
  52. buildTri(n,normalPrim, *normals);
  53. //Skip faces that are pointing away from us
  54. //Apply vertex shader
  55. for(int i = 0; i < 3; ++i){
  56. trianglePrimitive[i] = shader.vertex(trianglePrimitive[i], normalPrim[i], lightDir.normalized(), i);
  57. }
  58. //Skip triangles that are outside viewing frustrum
  59. //Does not rebuild triangles that are partially out TO DO
  60. if (clipTriangles(trianglePrimitive)) continue;
  61. perspectiveDivide(trianglePrimitive);
  62. //Send to rasterizer which will also call the fragment shader and write to the
  63. //zbuffer and pixel buffer.
  64. Rasterizer::drawTriangles(trianglePrimitive, shader, pixelBuffer, zBuffer);
  65. }
  66. }
  67. void SoftwareRenderer::clearBuffers(){
  68. zBuffer->clear();
  69. pixelBuffer->clear();
  70. }
  71. Buffer<Uint32>* SoftwareRenderer::getRenderTarget(){
  72. return pixelBuffer;
  73. }
  74. void SoftwareRenderer::setCameraToRenderFrom(Camera * camera){
  75. mCamera = camera;
  76. }
  77. bool SoftwareRenderer::createBuffers(int w, int h){
  78. int pixelCount = w*h;
  79. bool success = true;
  80. zBuffer = new Buffer<float>(w, h, new float[pixelCount]);
  81. if( zBuffer == nullptr){
  82. printf("Could not build z-Buffer.\n");
  83. success = false;
  84. }
  85. else{
  86. pixelBuffer = new Buffer<Uint32>(w, h, new Uint32[pixelCount]);
  87. if( pixelBuffer == nullptr){
  88. printf("Could not build pixel Buffer.\n");
  89. success = false;
  90. }
  91. }
  92. return success;
  93. }
  94. void SoftwareRenderer::buildTri(Vector3i &index, Vector3f *primitive, std::vector<Vector3f> &vals){
  95. for(int i = 0; i < 3; ++i){
  96. primitive[i] = vals[index.data[i]];
  97. }
  98. }
  99. bool SoftwareRenderer::backFaceCulling(Vector3f *trianglePrim, Vector3f &viewDir){
  100. //Triangle surface normal
  101. //Should probably be calculated on load next time
  102. Vector3f N1 = trianglePrim[1] - trianglePrim[0];
  103. Vector3f N2 = trianglePrim[2] - trianglePrim[0];
  104. Vector3f N = (N1.crossProduct(N2)).normalized();
  105. viewDir = mCamera->position - trianglePrim[0];
  106. viewDir.normalized();
  107. //Returns false if the triangle cannot see the camera
  108. float intensity = N.dotProduct(viewDir);
  109. return intensity <= 0.0;
  110. }
  111. bool SoftwareRenderer::clipTriangles(Vector3f *clipSpaceVertices){
  112. int count = 0;
  113. for(int i = 0; i < 3; ++i){
  114. Vector3f vertex = clipSpaceVertices[i];
  115. bool inside = (-vertex.w <= vertex.x <= vertex.w )
  116. && (-vertex.w <= vertex.y <= vertex.w)
  117. && (0 <= vertex.z <= vertex.w);
  118. if (!inside) ++count;
  119. }
  120. //If count equals three it means every vertex was out so we skip it
  121. return count == 3 ;
  122. }
  123. void SoftwareRenderer::perspectiveDivide(Vector3f *clippedVertices){
  124. for(int i = 0; i < 3; ++i){
  125. clippedVertices[i].perspectiveDivide();
  126. }
  127. }