Browse Source

Added simplest possible parallization with openMP.

angel 7 years ago
parent
commit
c28035e52f
6 changed files with 75 additions and 19 deletions
  1. 4 3
      CMakeLists.txt
  2. 48 2
      include/shader.h
  3. 2 2
      src/camera.cpp
  4. 7 2
      src/engine.cpp
  5. 10 9
      src/rasterizer.cpp
  6. 4 1
      src/softwareRenderer.cpp

+ 4 - 3
CMakeLists.txt

@@ -5,14 +5,15 @@ project(softwareRenderer)
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/modules")
 #set(SDL2_PATH "C:\\vs_dev_lib\\SDL2-2.0.8")
 find_package(SDL2 REQUIRED)
+find_package(OpenMP REQUIRED)
 include_directories(${SDL2_INCLUDE_DIR} include libs)
 
 file(GLOB source_files "*.h" "*.cpp" "src/*.cpp" "include/*.h" "libs/*.h")
 message(STATUS $ENV{source_files})
 add_executable(softwareRenderer ${source_files})
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 ")
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}  -g  ")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g ")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -g ")
 target_link_libraries(softwareRenderer ${SDL2_LIBRARY})
 
 if(WIN32)

+ 48 - 2
include/shader.h

@@ -46,7 +46,7 @@ struct GouraudShader : public IShader {
         reflectDir = Vector3f::reflect(-light2, normal);
         viewDir = MV.matMultVec(vertex).normalized();
         varying_specular.data[index] = std::pow( std::max( -viewDir.dotProduct(reflectDir), 0.0f), 32.0f);
-        varying_diffuse.data[index] = std::max(0.0f, (normal).dotProduct(light2));
+        varying_diffuse.data[index] = std::max(0.0f, (normal).dotProduct(-light2));
         return MVP.matMultVec(vertex);
     }
 
@@ -141,7 +141,53 @@ struct BlinnPhongShader : public IShader {
         diffuse = lightColor * diff * diffStrength;
         
         //Specular
-        halfwayDir = (lightDir -interpViewDir).normalized();
+        halfwayDir = (lightDir - interpViewDir).normalized();
+        spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
+        specular = lightColor * spec * specularStrength;
+
+        return (ambient + diffuse) * interpCol + specular * white;
+    }
+
+};
+
+
+struct TestShader{
+    Texture *albedo;
+    Matrix4 MVP, MV, V, N;
+    float ambientStrength = 0.05, diffStrength=1 , specularStrength= 0.5;
+    float diff, spec, shininess = 128;
+    Vector3f normals[3], viewDir[3], UV[3];
+    Vector3f ambient, diffuse, specular, interpNormal, interpViewDir, interpUV;
+    Vector3f lightColor{1,1,1};
+    Vector3f halfwayDir, lightDir;
+    Vector3f interpCol, white{255,255,255};
+
+    Vector3f vertex(Vector3f &vertex, Vector3f &normal, Vector3f &textureVals, Vector3f &light, int index) {
+        normals[index] = N.matMultDir(normal).normalized();
+        UV[index] = textureVals;
+        viewDir[index] = MV.matMultVec(vertex).normalized();
+        lightDir = V.matMultDir(light).normalized();
+        return MVP.matMultVec(vertex);
+    }
+
+    Vector3f fragment(float u, float v) {
+        //Interpolated stuff
+        interpNormal = (normals[0] + (normals[1] - normals[0])* u + (normals[2] - normals[0]) * v).normalized();
+        interpViewDir = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
+        interpUV = UV[0] + (UV[1] - UV[0])* u + (UV[2] - UV[0]) * v;
+        //Albedo
+        interpCol = albedo->getPixelVal(interpUV.x, interpUV.y);
+        //rgb.print();
+
+        //Ambient 
+        ambient = lightColor * ambientStrength;
+
+        //Diffuse
+        diff = std::max(0.0f, interpNormal.dotProduct(lightDir));
+        diffuse = lightColor * diff * diffStrength;
+        
+        //Specular
+        halfwayDir = (lightDir - interpViewDir).normalized();
         spec = std::pow(std::max(0.0f, interpNormal.dotProduct(halfwayDir)), shininess);
         specular = lightColor * spec * specularStrength;
 

+ 2 - 2
src/camera.cpp

@@ -12,8 +12,8 @@ Camera::Camera(){
 void Camera::update(){
     float t = static_cast<float>(SDL_GetTicks());
     float radius = 1.4;
-    float camX   = std::sin(t/5000) * radius;
-    float camZ   = std::cos(t/5000) * radius;
+    float camX   = std::sin(t/3000) * radius;
+    float camZ   = std::cos(t/3000) * radius;
     position.x   = camX;
     position.y   = 0;
     position.z   = camZ;

+ 7 - 2
src/engine.cpp

@@ -62,7 +62,8 @@ void Engine::run(){
     //Iteration and time keeping counters
     int count = 0;
     unsigned int end = 0;
-    unsigned int start = 0;
+    unsigned int start = 0;;
+    unsigned int total = 0;
 
     printf("Entered Main Loop!\n");
     while(!done){
@@ -93,7 +94,11 @@ void Engine::run(){
         //Stats about frame
         end = SDL_GetTicks();
         printf("%2.1d: Loop elapsed time (ms):%d\n",count,end - start);
-        //break;
+        total += end - start;
+        if (count == 500) break;
     }
+
     printf("Closing down engine:\n");
+    printf("Average frame time over %2.1d frames: %f\n", count,total/(float)count);
+    
 }

+ 10 - 9
src/rasterizer.cpp

@@ -1,6 +1,7 @@
 #include "rasterizer.h"
 #include "vector"
 #include "array"
+
 #include <algorithm>
 
 //Initializing all the basic colors 
@@ -86,7 +87,7 @@ void Rasterizer::drawTriangles(Vector3f *vertices, IShader &shader, Buffer<Uint3
 
     //Per fragment variables
     float depth, uPers, vPers, areaPers; //u, v, are perspective corrected
-    Vector3f e, e_row, f;
+    Vector3f e, e_row, e_init, f;
     Vector3f rgbVals{255,255,255};
     
 
@@ -116,21 +117,21 @@ void Rasterizer::drawTriangles(Vector3f *vertices, IShader &shader, Buffer<Uint3
 
 
     //Iterating through each pixel in triangle bounding box
-    for(point.y = yMin; point.y <= yMax; ++point.y){
+    for(int y = yMin; y <= yMax; ++y){
         //Bary coordinates at start of row
         e.x = e_row.x;
         e.y = e_row.y;
         e.z = e_row.z;
 
-        for(point.x = xMin; point.x <= xMax; ++point.x){
+        for(int x = xMin; x <= xMax; ++x){
 
             //Only draw if inside pixel and following top left rule
             if(inside(e.x, A01, B01) && inside(e.y, A12, B12) && inside(e.z, A20, B20) ){
 
                 //Zbuffer check
                 depth = (e*area).dotProduct(zVals);
-                if((*zBuffer)(point.x,point.y) < depth &&  depth <= 1.0){
-                    (*zBuffer)(point.x,point.y) = depth;
+                if((*zBuffer)(x,y) < depth &&  depth <= 1.0){
+                    (*zBuffer)(x,y) = depth;
 
                     //Get perspective correct barycentric coords
                     f = e * hW;
@@ -142,7 +143,7 @@ void Rasterizer::drawTriangles(Vector3f *vertices, IShader &shader, Buffer<Uint3
                     rgbVals = shader.fragment(uPers , vPers);
 
                     //Update pixel buffer with clamped values 
-                    (*pixelBuffer)(point.x,point.y) = SDL_MapRGB(mappingFormat,
+                    (*pixelBuffer)(x,y) = SDL_MapRGB(mappingFormat,
                     std::min(rgbVals.data[0],255.0f),
                     std::min(rgbVals.data[1],255.0f),
                     std::min(rgbVals.data[2],255.0f));
@@ -194,9 +195,9 @@ float Rasterizer::edge(Vector3f &a, Vector3f &b, Vector3f &c){
     return (b.x - a.x)*(c.y-a.y) - (b.y - a.y)*(c.x - a.x);
 }
 
-bool Rasterizer::inside(float edge, float a, float b){
-    if (edge > 0) return true;
-    if (edge < 0) return false;
+bool Rasterizer::inside(float e, float a, float b){
+    if ( e > 0) return true;
+    if ( e < 0) return false;
     if ( a > 0 )  return true;
     if ( a < 0 )  return false;
     if ( b > 0 )  return true;

+ 4 - 1
src/softwareRenderer.cpp

@@ -1,6 +1,7 @@
 #include "softwareRenderer.h"
 #include "shader.h"
 #include "mesh.h"
+#include "omp.h"
 
 SoftwareRenderer::SoftwareRenderer(){}
 SoftwareRenderer::~SoftwareRenderer(){}
@@ -61,7 +62,9 @@ void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
 
     //Iterate through every triangle
     int count = 0;
-    for (int j = 0; j < numFaces; ++j){
+
+    #pragma omp parallel for private(trianglePrimitive, normalPrim, uvPrim) firstprivate(shader)
+    for (int j= 0; j < numFaces; ++j){
         //Current vertex and normal indices
         Vector3i f = (*vIndices)[j];
         Vector3i n = (*nIndices)[j];