angel %!s(int64=7) %!d(string=hai) anos
pai
achega
86605daeae
Modificáronse 4 ficheiros con 86 adicións e 90 borrados
  1. 2 1
      CMakeLists.txt
  2. 68 39
      include/shader.h
  3. 10 13
      include/vector3D.h
  4. 6 37
      src/texture.cpp

+ 2 - 1
CMakeLists.txt

@@ -10,7 +10,8 @@ include_directories(${SDL2_INCLUDE_DIR} include libs)
 
 file(GLOB source_files "*.h" "*.cpp" "src/*.cpp" "include/*.h" "libs/*.h")
 add_executable(softwareRenderer ${source_files})
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -g -fno-exceptions  -ffast-math")
+#-fopt-info-vec-all -xCORE-AVX2 -no-prec-sqrt -ffast-math
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -g -xCORE-AVX2 -fno-exceptions -no-prec-sqrt ")
 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})

+ 68 - 39
include/shader.h

@@ -4,7 +4,7 @@
 #include "vector3D.h"
 #include "matrix.h"
 #include "texture.h"
-#include <array>
+#include <math.h>
 
 //Shader Interface for a class that emulates modern GPU fragment and vertex shaders
 struct IShader {
@@ -243,12 +243,11 @@ struct PBRShader : public IShader {
     Matrix4 TBN;
     
     //Interpolated variables
-    Vector3f interpCoords, interpLightDir,
-             interpNormal, interpViewDir,
+    Vector3f interpCoords, interpNormal, interpViewDir,
              interpCol;
 
     //Per fragment
-    Vector3f F, NDF, G ; //Fresnel, normal distribution function and geometry occlusion 
+   // Vector3f F, NDF, G ; //Fresnel, normal distribution function and geometry occlusion 
     Vector3f halfwayDir, radianceOut, ambient;
     Vector3f specular, kD, kS;
     float interpRough, interpAO, interpMetal;
@@ -266,20 +265,20 @@ struct PBRShader : public IShader {
         float NdotH  = std::max(normal.dotProduct(halfway), 0.0f);
         float NdotH2 = NdotH*NdotH;
         
-        float denom = (NdotH2 * (a2 - 1.0) + 1.0);
-        denom = M_1_PI / (denom * denom);
+        float denom = (NdotH2 * (a2 - 1.0f) + 1.0f);
+        denom =  M_1_PIf32/ (denom * denom);
         
         return a2 * denom;
     }
-    float GeometrySchlickGGX(float NdotV, float roughness){
-        float r = (roughness + 1.0); 
-        float k = (r*r) / 8.0; //Only useful for direct lighting must be changed in ibr
-        float denom = 1 / (NdotV * (1.0 - k) + k);
+    float GeometrySchlickGGX(float Ndot, float roughness){
+        float r = (roughness + 1.0f); 
+        float k = (r*r) / 8.0f; //Only useful for direct lighting must be changed in ibr
+        float denom = 1.0f / (Ndot * (1.0f- k) + k);
         
-        return NdotV * denom;
+        return Ndot * denom;
     }
-    float GeometrySmith(float roughness){
-        return GeometrySchlickGGX(nDotL, roughness) * GeometrySchlickGGX(nDotV, roughness);
+    float GeometrySmith(float roughness, float nDL, float nDV){
+        return GeometrySchlickGGX(nDL, roughness) * GeometrySchlickGGX(nDV, roughness);
     }
 
     //Vertex shader
@@ -325,41 +324,49 @@ struct PBRShader : public IShader {
         //Varying f0 based on metallicness of surface
         float invMetal = (1.0f-interpMetal);
         F0corrected = (F0 * invMetal) + (interpCol * interpMetal);
-        
         nDotV = std::max(interpNormal.dotProduct(interpViewDir), 0.0f);
 
         //Setting up Direct Lighting variables
         radianceOut.zero();
         const int maxLights = numLights;
-        Vector3f radiaceLights[maxLights];
-        //#pragma omp simd 
+        int val;
+        Vector3f radianceLights[maxLights];
+        Vector3f interpLightDir[maxLights];
+        Vector3f halfwayDir[maxLights];
+        Vector3f F[maxLights];
+        Vector3f numerator[maxLights];
+        Vector3f specular[maxLights];
+        Vector3f kD[maxLights];
+        float  NDF[maxLights];
+        float  nDotL[maxLights];
+        float  invDenominator[maxLights];
+        float  G[maxLights];
+        for(int i = 0; i < maxLights; ++i ){
+            val = i*3;
+            interpLightDir[i] = (lightDirVal[val] +  (lightDirVal[val + 1] - lightDirVal[val])* u +  (lightDirVal[val + 2] - lightDirVal[val]) * v).normalized();
+        }
+
+        #pragma omp simd
         for(int light = 0; light < maxLights; ++light ){
-            int val = light*3;
-            interpLightDir = lightDirVal[val] +  (lightDirVal[val + 1] - lightDirVal[val])* u +  (lightDirVal[val + 2] - lightDirVal[val]) * v;
-            halfwayDir = (interpLightDir.normalized() + interpViewDir).normalized();
-            nDotL = std::max(interpNormal.dotProduct(interpLightDir), 0.0f);
+            halfwayDir[light] = (interpLightDir[light] + interpViewDir);
+            halfwayDir[light] = halfwayDir[light].normalized();
+            nDotL[light] = std::fmax(interpNormal.dotProduct(interpLightDir[light]), 0.0f);
+            //#pragma distribute_point
+            F[light]     = fresnelSchlick(std::fmax(halfwayDir[light].dotProduct(interpViewDir), 0.0f), F0corrected);
+            NDF[light]   = distributionGGX(interpNormal, halfwayDir[light], interpRough); 
+            G[light]     = GeometrySmith(interpRough, nDotL[light] , nDotV);
+           // #pragma distribute_point
+            numerator[light] = F[light] * G[light]*NDF[light];
+            invDenominator[light]  = 1.0f / std::fmax(4.0f * (nDotL[light] * nDotV), 0.001f);
+            specular[light]  = numerator[light] * invDenominator[light];
+            //#pragma distribute_point
+            kD[light] = (Vector3f(1.0f) - F[light])*invMetal;
+            radianceLights[light] = (kD[light] * (interpCol * (M_1_PIf32)) + specular[light] ) * nDotL[light] * lightCol[light];
 
-            //We assume the only lights in the scene are far away so there is no attenuation
-            
-            //Setting up BRDF
-            F   = fresnelSchlick(std::max(halfwayDir.dotProduct(interpViewDir), 0.0f), F0corrected);
-            NDF = distributionGGX(interpNormal, halfwayDir, interpRough); 
-            G   = GeometrySmith(interpRough);
-
-            //Calculating specular component of BRDF
-            Vector3f numerator = F * (G*NDF);
-            float invDenominator  = 1 / std::max(4.0 * nDotL * nDotV, 0.001);
-            specular  = numerator * invDenominator;
-
-            //Calculating the full rendering equation for a single light
-            //kS = F;
-            kD = (Vector3f(1.0) - F);
-            kD = kD *invMetal; 
-            radiaceLights[light] = ( (kD * (interpCol * (1/M_PI)) + specular ) * nDotL * lightCol[light]);
         }
-        
+
         for(int i = 0; i < maxLights; ++i) {
-            radianceOut += radiaceLights[i];
+            radianceOut += radianceLights[i];
         }
 
         //Simplistic ambient term
@@ -370,7 +377,29 @@ struct PBRShader : public IShader {
 
 };
 
+        //#pragma omp simd simdlen(512)
+        // for(int light = 0; light < maxLights; ++light ){
+        //     halfwayDir = (interpLightDir[light] + interpViewDir).normalized();
+        //     nDotL = std::max(interpNormal.dotProduct(interpLightDir[light]), 0.0f);
 
+        //     //We assume the only lights in the scene are far away so there is no attenuation
+            
+        //     //Setting up BRDF
+        //     F   = fresnelSchlick(std::max(halfwayDir.dotProduct(interpViewDir), 0.0f), F0corrected);
+        //     NDF = distributionGGX(interpNormal, halfwayDir, interpRough); 
+        //     G   = GeometrySmith(interpRough);
+
+        //     //Calculating specular component of BRDF
+        //     Vector3f numerator = F * (G*NDF);
+        //     invDenominator  = 1.0f / std::max(4.0f * nDotL * nDotV, 0.001f);
+        //     specular  = numerator * invDenominator;
+
+        //     //Calculating the full rendering equation for a single light
+        //     //kS = F;
+        //     kD = (Vector3f(1.0f) - F)*invMetal;
+        //     //kD = kD *invMetal; 
+        //     radianceLights[light] = ( (kD * (interpCol * (1/M_PI)) + specular ) * nDotL * lightCol[light]);
+        // }
 
 
 

+ 10 - 13
include/vector3D.h

@@ -51,8 +51,11 @@ struct Vector3{
     Vector3 operator+(const Vector3 &rhs) const
     {return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);}
 
-    void operator+=(const Vector3 &rhs) 
-    {(*this) = (*this) + rhs ;}
+    void operator+=(const Vector3 &rhs) {   
+        x += rhs.x;
+        y += rhs.y;
+        z += rhs.z;
+    }
 
     void operator-=(const Vector3 &rhs) 
     {(*this) = (*this) - rhs ;}
@@ -72,18 +75,12 @@ struct Vector3{
     T length() const
     {return std::sqrt(x*x + y*y + z*z);}
 
-    Vector3 &normalized()
-    {
+    Vector3 &normalized(){
         T len = length();
-        if( len > 0){
-            T factor = 1 / len;
-            x *= factor;
-            y *= factor;
-            z *= factor;
-        }
-        else {
-            printf("WARNING: Attempting to normalize a vector of length 0.\n");
-        }
+        T factor = 1.0f / len;
+        x *= factor;
+        y *= factor;
+        z *= factor;
 
         return *this;
     }

+ 6 - 37
src/texture.cpp

@@ -39,45 +39,9 @@ Texture::Texture(std::string path, std::string type){
     stbi_image_free(data);
 }
 
-// void Texture::tileData(){
-//     float *tiledPixelData = new float[width*height*channels];
-
-//     int tileNumW    = width / tileW;
-//     int tileNumH    = height / tileH;
-//     int linearIndex = 0;
-//     int tiledIndex  = 0;
-//     for(int tileRow = 0; tileRow < tileNumW; ++tileRow){
-
-//         for(int tileCol = 0; tileCol < tileNumH; ++tileCol){
-
-//             for(int tilePixelHeight = 0; tilePixelHeight < tileH; ++tilePixelHeight){
-                
-//                 //Increment the linear index by one width to move down
-//                 linearIndex = (width*tilePixelHeight + tileW*tileCol + tileRow*tileH)*channels;
-
-//                 for(int tilepixelWidth = 0; tilePixelWidth < tileW; P+tilepixelWidth){
-
-//    P                //To move width wise you just increment again by the channel numbers
-
-//                     for(int pC = 0; pC < channels; ++pC){
-//                         printf("%d, %d\n", tiledIndex, linearIndex);
-//                         tiledPixelData[tiledIndex] = pixelData[linearIndex];
-//                         ++linearIndex;
-//                         ++tiledIndex;
-                        
-//                     }
-//                 }
-//             }
-//         }
-//     }
-//     delete [] pixelData;
-//     pixelData = tiledPixelData;
-// }
-
 void Texture::tileData(){
     float *tiledPixelData = new float[width*height*channels];
 
-    
     int tileNumW    = width / tileW;
     int tileNumH    = height / tileH;
     int linearIndex = 0;
@@ -88,10 +52,16 @@ void Texture::tileData(){
         for(int tileCol = 0; tileCol < tileNumH; ++tileCol){
 
             for(int tilePixelHeight = 0; tilePixelHeight < tileH; ++tilePixelHeight){
+
+                //1.First multiplication accounts for a change in pixel height within a tile
+                //2.Second accounts for a change of tile along arrow(tile movement column wise)
+                //3.Third accounts for the movement of one whole tile row downwards
                 
                 linearIndex = (tilePixelHeight*width + tileCol*tileW + tileRow*width*tileH)*channels;
 
                 for(int tilePixelWidth = 0; tilePixelWidth < tileW; ++tilePixelWidth){
+                    
+                    //Pixel wise movement is equal to channelwise movement in the array
 
                     for(int pC = 0; pC < channels; ++pC){
 
@@ -100,7 +70,6 @@ void Texture::tileData(){
                         ++tiledIndex;
                         
                     }
-
                 }
             }
         }