softwareRenderer.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // ===============================
  2. // AUTHOR : Angel Ortiz (angelo12 AT vt DOT edu)
  3. // CREATE DATE : 2018-07-10
  4. // ===============================
  5. //Headers
  6. #include "softwareRenderer.h"
  7. #include "shader.h"
  8. #include "mesh.h"
  9. #include "omp.h"
  10. //Dummy Constructor / Destructor
  11. SoftwareRenderer::SoftwareRenderer(){}
  12. SoftwareRenderer::~SoftwareRenderer(){}
  13. bool SoftwareRenderer::startUp(int w, int h){
  14. if( !createBuffers(w, h) ){
  15. return false;
  16. }
  17. //Want to make sure that we don't call for a delete of zbuffer and pixelbuffer
  18. //Unless the startup has been complete
  19. startUpComplete = true;
  20. return startUpComplete;
  21. }
  22. void SoftwareRenderer::shutDown(){
  23. mLights = nullptr;
  24. mCamera = nullptr;
  25. //Only delete buffers if startup completed successfully
  26. if (startUpComplete){
  27. delete zBuffer;
  28. delete pixelBuffer;
  29. }
  30. }
  31. void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
  32. //Getting the vertices, faces, normals and texture data for the whole model
  33. Mesh *triMesh = currentModel->getMesh();
  34. std::vector<Vector3i> * vIndices = &triMesh->vertexIndices;
  35. std::vector<Vector3i> * tIndices = &triMesh->textureIndices;
  36. std::vector<Vector3i> * nIndices = &triMesh->normalsIndices;
  37. std::vector<Vector3f> * fNormals = &triMesh->fNormals;
  38. std::vector<Vector3f> * vertices = &triMesh->vertices;
  39. std::vector<Vector3f> * texels = &triMesh->texels;
  40. std::vector<Vector3f> * normals = &triMesh->normals;
  41. std::vector<Vector3f> * tangents = &triMesh->tangents;
  42. int numFaces = triMesh->numFaces;
  43. //Initializing shader textures
  44. PBRShader shader;
  45. shader.albedoT = currentModel->getAlbedo();
  46. shader.normalT = currentModel->getNormal();
  47. shader.ambientOT = currentModel->getAO();
  48. shader.roughT = currentModel->getRoughness();
  49. shader.metalT = currentModel->getMetallic();
  50. //Setting up lighting
  51. Vector3f lightPositions[mNumLights];
  52. Vector3f lColor[mNumLights];
  53. for(int x = 0; x < mNumLights; ++x){
  54. lColor[x] = mLights[x].color;
  55. lightPositions[x] = mLights[x].position;
  56. }
  57. //Initializing shader matrices & variables
  58. shader.MV = (mCamera->viewMatrix)*(*(currentModel->getModelMatrix()));
  59. shader.MVP = (mCamera->projectionMatrix)*shader.MV;
  60. shader.V = (mCamera->viewMatrix);
  61. shader.M = *(currentModel->getModelMatrix());
  62. shader.N = (shader.M.inverse()).transpose();
  63. shader.cameraPos = mCamera->position;
  64. shader.numLights = mNumLights;
  65. shader.lightCol = lColor;
  66. shader.lightPos = lightPositions;
  67. //Building worldToObject matrix
  68. Matrix4 worldToObject = (*(currentModel->getModelMatrix())).inverse();
  69. //Iterate through every triangle on mesh with early quiting by backface culling
  70. //It also uses dynamic scheduling since on average 50% of the threads would finish early
  71. //because of backface culling. This allows for redistributing of parallel tasks between
  72. //threads to increase parallelization effectiveness.
  73. #pragma omp parallel for firstprivate(shader) schedule(dynamic)
  74. for (int j= 0; j < numFaces; ++j){
  75. //Arrays used to group vertices together into triangles
  76. Vector3f trianglePrimitive[3], normalPrim[3], uvPrim[3],
  77. tangentPrim[3];
  78. //Current vertex, normals and texture data indices
  79. Vector3i f = (*vIndices)[j];
  80. Vector3i n = (*nIndices)[j];
  81. Vector3i u = (*tIndices)[j];
  82. //Last setup of shader light variables
  83. Vector3f lightDir[mNumLights * 3 ];
  84. shader.lightDirVal = lightDir;
  85. //Pack vertex, normal and UV data into triangles
  86. packDataIntoTris(f, trianglePrimitive, *vertices);
  87. packDataIntoTris(n, normalPrim, *normals);
  88. packDataIntoTris(u, uvPrim, *texels);
  89. packDataIntoTris(f, tangentPrim, *tangents);
  90. //Early quit if face is pointing away from camera
  91. if (backFaceCulling((*fNormals)[j], trianglePrimitive[0], worldToObject)) continue;
  92. //Apply vertex shader
  93. for(int i = 0; i < 3; ++i){
  94. trianglePrimitive[i] = shader.vertex(trianglePrimitive[i], normalPrim[i],
  95. uvPrim[i], tangentPrim[i], i);
  96. }
  97. //Skip triangles that are outside viewing frustrum
  98. //Does not rebuild triangles that are only partially out
  99. if (clipTriangles(trianglePrimitive)) continue;
  100. perspectiveDivide(trianglePrimitive);
  101. //Send to rasterizer which will also call the fragment shader and write to the
  102. //zbuffer and pixel buffer.
  103. Rasterizer::drawTriangles(trianglePrimitive, shader, pixelBuffer, zBuffer);
  104. }
  105. }
  106. //Candidate to be refactored out into render manager
  107. void SoftwareRenderer::clearBuffers(){
  108. zBuffer->clear();
  109. pixelBuffer->clear();
  110. }
  111. Buffer<Uint32>* SoftwareRenderer::getRenderTarget(){
  112. return pixelBuffer;
  113. }
  114. void SoftwareRenderer::setCameraToRenderFrom(Camera * camera){
  115. mCamera = camera;
  116. }
  117. void SoftwareRenderer::setSceneLights(BaseLight * lights, int numLights){
  118. mNumLights = numLights;
  119. mLights = lights;
  120. }
  121. bool SoftwareRenderer::createBuffers(int w, int h){
  122. int pixelCount = w*h;
  123. bool success = true;
  124. zBuffer = new Buffer<float>(w, h, new float[pixelCount]);
  125. if( zBuffer == nullptr){
  126. printf("Could not build z-Buffer.\n");
  127. success = false;
  128. }
  129. else{
  130. pixelBuffer = new Buffer<Uint32>(w, h, new Uint32[pixelCount]);
  131. if( pixelBuffer == nullptr){
  132. printf("Could not build pixel Buffer.\n");
  133. success = false;
  134. }
  135. }
  136. return success;
  137. }
  138. void SoftwareRenderer::packDataIntoTris(Vector3i &index, Vector3f *primitive, std::vector<Vector3f> &vals){
  139. for(int i = 0; i < 3; ++i){
  140. primitive[i] = vals[index.data[i]];
  141. }
  142. }
  143. //Gets view direction in object space and uses it to check if the facet normal
  144. //Is aligned with the viewdirection
  145. bool SoftwareRenderer::backFaceCulling(Vector3f &facetNormal, Vector3f &vert, Matrix4 &worldToObject){
  146. Vector3f viewDir = worldToObject.matMultVec(mCamera->position) - vert;
  147. viewDir.normalized();
  148. //Returns false if the triangle cannot see the camera
  149. float intensity = facetNormal.dotProduct(viewDir);
  150. return intensity <= 0.0;
  151. }
  152. //Inside bounds described in perspective matrix calculation
  153. bool SoftwareRenderer::clipTriangles(Vector3f *clipSpaceVertices){
  154. int count = 0;
  155. for(int i = 0; i < 3; ++i){
  156. Vector3f vertex = clipSpaceVertices[i];
  157. bool inside = (-vertex.w <= vertex.x <= vertex.w )
  158. && (-vertex.w <= vertex.y <= vertex.w)
  159. && (0 <= vertex.z <= vertex.w);
  160. if (!inside) ++count;
  161. }
  162. //If count equals three it means every vertex was out so we skip it
  163. return count == 3 ;
  164. }
  165. void SoftwareRenderer::perspectiveDivide(Vector3f *clippedVertices){
  166. for(int i = 0; i < 3; ++i){
  167. clippedVertices[i].perspectiveDivide();
  168. }
  169. }