浏览代码

Halfway through adding multiple light sources.

angel 7 年之前
父节点
当前提交
d8f85eef95
共有 9 个文件被更改,包括 145 次插入54 次删除
  1. 1 1
      include/geometry.h
  2. 8 8
      include/light.h
  3. 10 2
      include/scene.h
  4. 37 28
      include/shader.h
  5. 7 0
      include/softwareRenderer.h
  6. 16 3
      scenes/teapot/teapot_config.txt
  7. 6 1
      src/renderManager.cpp
  8. 35 5
      src/scene.cpp
  9. 25 6
      src/softwareRenderer.cpp

+ 1 - 1
include/geometry.h

@@ -33,7 +33,7 @@ class Frustrum{
         };
     public:
         float  fov, AR, near, far , nearH, nearW, farH, farW;
-        Frustrum(float ratio): fov(90), near(0.1), far(100), AR(ratio){};
+        Frustrum(float ratio): fov(75), near(0.1), far(100), AR(ratio){};
         Plane pl[6];
 
         void setCamInternals();

+ 8 - 8
include/light.h

@@ -1,11 +1,11 @@
-// #ifndef LIGHT_H
-// #define LIGHT_H
+#ifndef LIGHT_H
+#define LIGHT_H
 
-// #include "vector3D.h"
+#include "vector3D.h"
 
-// struct BaseLight{
-//     Vector3f position;
-//     Vector3f color;
-// };
+struct BaseLight{
+    Vector3f position;
+    Vector3f color;
+};
 
-// #endif
+#endif

+ 10 - 2
include/scene.h

@@ -1,12 +1,11 @@
 #ifndef SCENE_H
 #define SCENE_H
 
-
 #include <vector>
 #include <queue>
 #include "model.h"
 #include "camera.h"
-
+#include "light.h"
 
 //Keeps track of all the lights, models and cameras contained in a current
 //scene. Also performs frustrumc ulling to determine what objects to send to
@@ -26,12 +25,21 @@ class Scene{
 
         Camera * getCurrentCamera();
 
+        BaseLight * getCurrentLights();
+        int getLightCount();
+        
+
         //Used in the scene loading check to determine if models were loaded 
         //correctly. It sends this info upstream to the scene manager to abort
         //the load procedure.
         bool checkIfEmpty();
+        
     private:
         Camera mainCamera;
+        
+        BaseLight *lights;
+        int lightCount;
+
         bool emptyScene;
         std::vector<Model*> modelsInScene;
         //Contains the models that remain after frustrum culling

+ 37 - 28
include/shader.h

@@ -230,9 +230,10 @@ struct PBRShader : public IShader {
     Vector3f cameraPos;
 
     //Light Variables
-    Vector3f lightColor{1,1,1}, F0{0.04, 0.04, 0.04}, F0corrected; //Default value dielectric
+    Vector3f F0{0.04, 0.04, 0.04}, F0corrected; //Default value dielectric
     float nDotL, nDotV, ambientInt = 0.01;
-    Vector3f lightDir[3];
+    int numLights;
+    Vector3f *lightDirForInterp, *lightColor, *lightPos;
 
     //Variables set per vertex
     Vector3f viewDir[3], texCoords[3];
@@ -278,7 +279,7 @@ struct PBRShader : public IShader {
     }
 
     //Vertex shader
-    Vector3f vertex(const Vector3f &vertex, const Vector3f &normal,const Vector3f &textureVals, const Vector3f &tangent, const Vector3f &light, int index) override{
+    Vector3f vertex(const Vector3f &vertex, const Vector3f &normal,const Vector3f &textureVals, const Vector3f &tangent, const Vector3f &n, int index) override{
         //Creating TBN matrix
         normal_WS     = N.matMultDir(normal).normalized();
         tangent_WS    = N.matMultDir(tangent).normalized();
@@ -289,7 +290,11 @@ struct PBRShader : public IShader {
         texCoords[index] = textureVals;
 
         //Passing all lighting related data to tangent space
-        lightDir[index]  = TBN.matMultVec(light);
+        for(int lIndex = 0; lIndex < numLights; ++lIndex){
+            int indc2 = (lIndex*3) + index;
+            lightDirForInterp[indc2]  = TBN.matMultVec(lightPos[lIndex]);
+            //printf("%d\n",indc2);
+        }
         viewDir[index]   = TBN.matMultVec(cameraPos - M.matMultVec(vertex));
         
         return MVP.matMultVec(vertex);
@@ -299,7 +304,6 @@ struct PBRShader : public IShader {
     Vector3f fragment(float u, float v) override{
         //Interpolated stuff
         interpCoords   = texCoords[0] + (texCoords[1] - texCoords[0])* u + (texCoords[2] - texCoords[0]) * v;
-        interpLightDir = lightDir[0] + (lightDir[1] - lightDir[0])* u + (lightDir[2] - lightDir[0]) * v;
         interpViewDir  = viewDir[0] + (viewDir[1] - viewDir[0])* u + (viewDir[2] - viewDir[0]) * v;
 
         //Correcting UV's for tiling
@@ -316,31 +320,36 @@ struct PBRShader : public IShader {
         interpViewDir = interpViewDir.normalized();
 
         //Setting up Direct Lighting variables
-        halfwayDir = (interpLightDir + interpViewDir).normalized();
-        nDotV = std::max(interpNormal.dotProduct(interpViewDir), 0.0f);
-        nDotL = std::max(interpNormal.dotProduct(interpLightDir), 0.0f);
-        F0corrected = (F0 * (1.0f-interpMetal)) + (interpCol * interpMetal);//Varying f0 based on metallicness of surface
         radianceOut.zero();
-
-        //TODO:: Iterate through every light and set radiance 
-        //We assume the only light in the scene is the sun so there is no attenuation
+        for(int light = 0; light < numLights; ++light ){
+            int val = light*3;
+            interpLightDir = lightColor[0];
+            //interpLightDir = lightDirForInterp[0] + (lightDirForInterp[1] - lightDirForInterp[0])* u + (lightDirForInterp[2] - lightDirForInterp[0]) * v;
+            halfwayDir = (interpLightDir + interpViewDir).normalized();
+            nDotV = std::max(interpNormal.dotProduct(interpViewDir), 0.0f);
+            nDotL = std::max(interpNormal.dotProduct(interpLightDir), 0.0f);
+            F0corrected = (F0 * (1.0f-interpMetal)) + (interpCol * interpMetal);//Varying f0 based on metallicness of surface
+
+
+            //We assume the only light in the scene is the sun 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) - kS);
+            kD = kD * (1.0f - interpMetal); 
+            radianceOut = radianceOut +  ( (kD * (interpCol * (1/M_PI)) + specular ) * nDotL * lightColor[light]);
+        }
         
-        //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) - kS);
-        kD = kD * (1.0f - interpMetal); 
-        radianceOut = ( (kD * (interpCol * (1/M_PI)) + specular ) * nDotL * lightColor);
-
         //Simplistic ambient term
         ambient =  interpCol * (ambientInt * interpAO);
 

+ 7 - 0
include/softwareRenderer.h

@@ -5,6 +5,7 @@
 #include "buffer.h"
 #include "model.h"
 #include "camera.h"
+#include "light.h"
 
 class SoftwareRenderer {
 
@@ -42,6 +43,8 @@ class SoftwareRenderer {
         Buffer<Uint32>* getRenderTarget();
 
         void setCameraToRenderFrom(Camera * camera);
+
+        void setSceneLights(BaseLight * lights, int numLights);
     private:
         //Buffer methods
         bool createBuffers(int w, int h);
@@ -58,6 +61,10 @@ class SoftwareRenderer {
         Camera * mCamera;
         bool startUpComplete = false;
 
+        //Pointer to structs containing all the light info
+        int mNumLights;
+        BaseLight *mLights;
+
         Buffer<float> * zBuffer;
         Buffer<Uint32> * pixelBuffer;
 };

+ 16 - 3
scenes/teapot/teapot_config.txt

@@ -3,17 +3,30 @@ s teapot
 /
 //SECTION: models
 m 1
-01 teapot
+m01 teapot
 pos 0.0 0.0 0.0 
 rot 90.0 0.0 0.0
 sca 0.4 0.4 0.4 
 /
+m02 teapot
+pos 1.0 1.0 0.0 
+rot 90.0 0 0.0
+sca 0.4 0.4 0.4 
+/
 //SECTION: lights
 l 1
 l01 sun
-pos 1.0 1.0 1.0
+pos 1.0 0.0 0.0
+col 1.0 1.0 1.0
+/
+l02 sun
+pos 0.0 1.0 0.0
 col 1.0 1.0 1.0
-//
+/
+l03 sun
+pos 0.0 0.0 1.0
+col 1.0 1.0 1.0
+/
 //SECTION: cameras
 c 
 /

+ 6 - 1
src/renderManager.cpp

@@ -48,11 +48,16 @@ void RenderManager::render(){
 //Gets the list of visible models from the current scene
 //Done every frame in case scene changes
 void RenderManager::buildRenderQueue(){
+
+    //set scene info
+    Scene* currentScene = sceneLocator->getCurrentScene();
     
     //Set renderer camera
-    Scene* currentScene = sceneLocator->getCurrentScene();
     renderInstance.setCameraToRenderFrom(currentScene->getCurrentCamera());
 
+    //Update the pointer to the list of lights in the scene
+    renderInstance.setSceneLights(currentScene->getCurrentLights(), currentScene->getLightCount() );
+
     //Get pointers to the visible model queu
     renderObjectQueue = currentScene->getVisiblemodels();
 }

+ 35 - 5
src/scene.cpp

@@ -28,6 +28,7 @@ Scene::~Scene(){
         for(Model *models : modelsInScene){
             delete models;
         }
+        delete [] lights;
     }
 }
 
@@ -63,10 +64,16 @@ void Scene::frustrumCulling(){
     }
 }
 
- std::queue<Model*>* Scene::getVisiblemodels(){
+std::queue<Model*>* Scene::getVisiblemodels(){
     return &visibleModels;
 }
 
+BaseLight * Scene::getCurrentLights(){
+    return lights;
+}
+
+
+
 Camera* Scene::getCurrentCamera(){
     return &mainCamera;
 }
@@ -131,7 +138,7 @@ bool Scene::loadContent(const std::string &baseFilePath, const std::string &scen
                         for(int i = 0; i < max; ++i){
 
                             //Burn one line with model type for now
-                            std::getline(file,line); 
+                            std::getline(file,line);
 
                             //Position
                             std::getline(file,line);
@@ -162,9 +169,28 @@ bool Scene::loadContent(const std::string &baseFilePath, const std::string &scen
                     else if(key == "l"){ //light related setup
                         printf("Loading lights...\n");
                         iss >> key;
-                        int max = stoi(key);
-                        for(int i = 0; i < max; ++i){
-                            printf("Light 1\n");
+                        lightCount = stoi(key);
+                        lights = new BaseLight[lightCount];
+                        for(int i = 0; i < lightCount; ++i){
+
+                            //Burn one line with light type for now
+                            std::getline(file,line);
+
+                            //Position
+                            std::getline(file,line);
+                            std::istringstream pos(line);
+                            pos >> key >> x >> y >> z;
+                            lights[i].position = Vector3f(stof(x), stof(y), stof(z));
+
+                            //Color
+                            std::getline(file,line);
+                            std::istringstream col(line);
+                            col >> key >> x >> y >> z;
+                            lights[i].color = Vector3f(stof(x), stof(y), stof(z));
+
+                            //Burning empty line that makes the config easier to read
+                            std::getline(file,line);
+                            
                         }
                     }
                     else if(key == "c"){ //camera related setup
@@ -179,3 +205,7 @@ bool Scene::loadContent(const std::string &baseFilePath, const std::string &scen
         }
     }
 }
+
+int Scene::getLightCount(){
+    return lightCount;
+}

+ 25 - 6
src/softwareRenderer.cpp

@@ -15,6 +15,7 @@ bool SoftwareRenderer::startUp(int w, int h){
 }
 
 void SoftwareRenderer::shutDown(){
+    mLights = nullptr;
     mCamera = nullptr;
     if (startUpComplete){
         delete zBuffer;
@@ -24,7 +25,6 @@ void SoftwareRenderer::shutDown(){
 
 void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
     //Getting the vertices, faces, texture data 
-
     Mesh *triMesh = currentModel->getMesh();
     std::vector<Vector3i> * vIndices = &triMesh->vertexIndices;
     std::vector<Vector3i> * tIndices = &triMesh->textureIndices;
@@ -49,7 +49,16 @@ void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
     shader.roughT    = currentModel->getRoughness();
     shader.metalT    = currentModel->getMetallic();
 
-    //Initializing shader matrices
+    //Setting up lighting
+    Vector3f lightDir[mNumLights * 3 ];
+    Vector3f lightPositions[mNumLights];
+    Vector3f lightCol[mNumLights];
+    for(int x = 0; x < mNumLights; ++x){
+        lightCol[x] = mLights[x].color;
+        lightPositions[x] = mLights[x].position;
+    }
+
+    //Initializing shader matrices & variables
     shader.MV  = (mCamera->viewMatrix)*(*(currentModel->getModelMatrix()));
     shader.MVP = (mCamera->projectionMatrix)*shader.MV;
     shader.V   = (mCamera->viewMatrix);
@@ -57,15 +66,18 @@ void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
     shader.N   = (shader.M.inverse()).transpose(); 
     shader.cameraPos = mCamera->position;
 
-    //Basic light direction
-    Vector3f lightDir{1, 0, 0};
-    lightDir = lightDir.normalized();
+    shader.numLights  = mNumLights;
+    shader.lightColor = lightCol;
+    shader.lightDirForInterp = lightDir;
+    shader.lightPos = lightPositions;
+
 
     //Building worldToObject matrix
     Matrix4 worldToObject = (*(currentModel->getModelMatrix())).inverse();
 
     // Iterate through every triangle
     int count = 0;
+    Vector3f dummyDir; //TO DO FIX THIS
 
     #pragma omp parallel for private(trianglePrimitive, normalPrim, uvPrim, tangentPrim) firstprivate(shader)
     for (int j= 0; j < numFaces; ++j){
@@ -88,7 +100,7 @@ void SoftwareRenderer::drawTriangularMesh(Model * currentModel){
             trianglePrimitive[i] = shader.vertex(
                 trianglePrimitive[i], normalPrim[i],
                 uvPrim[i], tangentPrim[i], 
-                lightDir, i);
+                dummyDir, i);
         }
 
         //Skip triangles that are outside viewing frustrum
@@ -118,6 +130,13 @@ void SoftwareRenderer::setCameraToRenderFrom(Camera * camera){
     mCamera = camera;
 }
 
+
+void SoftwareRenderer::setSceneLights(BaseLight * lights, int numLights){
+    mNumLights = numLights;
+    mLights = lights;
+}
+
+
 bool SoftwareRenderer::createBuffers(int w, int h){
     int pixelCount = w*h;
     bool success = true;