Browse Source

Work on area lights

Josh Engebretson 8 years ago
parent
commit
6ad2dbe371

+ 1 - 1
Script/AtomicEditor/ui/frames/inspector/SelectionSectionCoreUI.ts

@@ -152,7 +152,7 @@ class GlowComponentSectionUI extends SelectionSectionUI {
 
             glow.subscribeToEvent(Editor.AtomicGlowBakeResultEvent((evData:Editor.AtomicGlowBakeResultEvent) => {
 
-                if (glowOutput && evData.success) {
+                if (glowOutput) {
                     glowOutput.hide();
                     glowOutput.close();                    
                 }

+ 3 - 4
Source/AtomicGlow/Common/GlowSettings.h

@@ -174,13 +174,12 @@ namespace AtomicGlow
                 case GLOW_PRESET_FAST_LOW_QUALITY:
                     lexelDensity_ = 0.16f;
                     nsamples_ = 16;
-                    photonPassCount_          = 8;
-                    photonBounceCount_        = 1;
+                    photonPassCount_          = 64;
+                    photonBounceCount_        = 4;
                     photonEnergyThreshold_    = 0.05f;
-                    // fix me should be 10, bigger for massive cornell
                     photonMaxDistance_        = 10;
 
-                    finalGatherSamples_       = 32;
+                    finalGatherSamples_       = 1024;
                     finalGatherDistance_      = 50;
                     finalGatherRadius_        = 7;
                     break;

+ 153 - 18
Source/AtomicGlow/Kernel/BakeLight.cpp

@@ -67,19 +67,15 @@ void BakeLight::SetInfluenceModel( LightInfluence* value )
     influenceModel_ = value;
 }
 
-/*
-LightVertexGenerator* BakeLight::vertexGenerator( void ) const
+LightVertexGenerator* BakeLight::GetVertexGenerator( void ) const
 {
     return vertexGenerator_;
 }
 
-// ** BakeLight::setVertexGenerator
-void BakeLight::setVertexGenerator( LightVertexGenerator* value )
+void BakeLight::SetVertexGenerator( LightVertexGenerator* value )
 {
-    delete m_vertexGenerator;
-    m_vertexGenerator = value;
+    vertexGenerator_ = value;
 }
-*/
 
 LightAttenuation* BakeLight::GetAttenuationModel( void ) const
 {
@@ -203,19 +199,17 @@ BakeLight* BakeLight::CreateDirectionalLight( SceneBaker* baker, const Vector3&
     return light;
 }
 
-/*
-BakeLight* BakeLight::CreateAreaLight( SceneBaker* baker, const Mesh* mesh, const Vector3& position, const Rgb& color, float intensity, bool castsShadow )
+BakeLight* BakeLight::CreateAreaLight( SceneBaker* baker, BakeMesh* bakeMesh, const Vector3& position, const Color& color, float intensity, bool castsShadow )
 {
-    Light* light = new Light;
+    BakeLight* light = new BakeLight(baker->GetContext(), baker);
 
-    light->SetInfluence( new LightInfluence( light ) );
-    light->SetAttenuation( new LinearLightAttenuation( light, mesh->bounds().volume() ) );
+    light->SetInfluenceModel( new LightInfluence( light ) );
+    const BoundingBox bbox = bakeMesh->GetBoundingBox();
+    float volume = 7.25f; /*(bbox.max_.x_ - bbox.min_.x_) * (bbox.max_.y_ - bbox.min_.y_) * (bbox.max_.z_ - bbox.min_.z_)*/;
+    light->SetAttenuationModel( new LinearLightAttenuation( light, volume ) );
     light->SetPhotonEmitter( new PhotonEmitter( light ) );
-    light->SetCutoff( new LightCutoff( light ) );
-    //light->SetVertexGenerator( new FaceLightVertexGenerator( mesh, true, 3 ) );
-    //light->SetVertexGenerator( new FaceLightVertexGenerator( mesh, false, 0 ) );
-    light->SetVertexGenerator( new FaceLightVertexGenerator( mesh, true, 0 ) );
-    //  light->SetVertexGenerator( new LightVertexGenerator( mesh ) );
+    light->SetCutoffModel( new LightCutoff( light ) );
+    light->SetVertexGenerator( new FaceLightVertexGenerator( bakeMesh, true, 0 ) );
     light->SetCastsShadow( castsShadow );
     light->SetPosition( position );
     light->SetColor( color );
@@ -225,7 +219,6 @@ BakeLight* BakeLight::CreateAreaLight( SceneBaker* baker, const Mesh* mesh, cons
 
     return light;
 }
-*/
 
 // ------------------------------------------------------- LightInfluence --------------------------------------------------------- //
 
@@ -523,5 +516,147 @@ void DirectionalPhotonEmitter::Emit( SceneBaker* sceneBaker, Vector3& position,
     direction = direction_;
 }
 
+// ---------------------------------------------------- LightVertexGenerator ------------------------------------------------------ //
+
+
+LightVertexGenerator::LightVertexGenerator( BakeMesh* bakeMesh ) : mesh_( bakeMesh )
+{
+
+}
+
+unsigned LightVertexGenerator::GetVertexCount( void ) const
+{
+    return vertices_.Size();
+}
+
+
+const LightVertexVector& LightVertexGenerator::GetVertices( void ) const
+{
+    return vertices_;
+}
+
+
+void LightVertexGenerator::Clear( void )
+{
+    vertices_.Clear();
+}
+
+
+void LightVertexGenerator::Generate( void )
+{
+    Clear();
+
+    unsigned numVertices;
+    const SharedArrayPtr<BakeMesh::MMVertex>& vertices = mesh_->GetVertices(numVertices);
+
+    LightVertex lightVertex;
+
+    for( unsigned i = 0; i < numVertices; i++ )
+    {
+        lightVertex.position_ = vertices[i].position_;
+        lightVertex.normal_   = vertices[i].normal_;
+
+        Push( lightVertex ) ;
+    }
+}
+
+
+void LightVertexGenerator::Push(const LightVertex &vertex )
+{
+    vertices_.Push( vertex );
+}
+
+// ------------------------------------------------- FaceLightVertexGenerator --------------------------------------------------- //
+
+FaceLightVertexGenerator::FaceLightVertexGenerator( BakeMesh* bakeMesh, bool excludeVertices, int maxSubdivisions )
+    : LightVertexGenerator( bakeMesh ),
+      excludeVertices_( excludeVertices ),
+      maxSubdivisions_( maxSubdivisions )
+{
+
+}
+
+void FaceLightVertexGenerator::Generate( void )
+{
+    Clear();
+
+    if( !excludeVertices_ ) {
+        LightVertexGenerator::Generate();
+    }
+
+    unsigned numVertices;
+    const SharedArrayPtr<BakeMesh::MMVertex>& vertices = mesh_->GetVertices(numVertices);
+
+    unsigned numTriangles;
+    const SharedArrayPtr<BakeMesh::MMTriangle>& triangles = mesh_->GetTriangles(numTriangles);
+
+    for( unsigned i = 0; i < numTriangles; i++ )
+    {
+        const BakeMesh::MMTriangle& mtri = triangles[i];
+
+        LightVertex verts[3];
+
+        for (int j = 0; j < 3; j++)
+        {
+            verts[j].position_ = vertices[mtri.indices_[j]].position_;
+            verts[j].normal_ = vertices[mtri.indices_[j]].normal_;
+        }
+
+        LightTriangle triangle(verts[0], verts[1], verts[2]);
+
+        GenerateFromTriangle( triangle, 0 );
+    }
+}
+
+void FaceLightVertexGenerator::GenerateFromTriangle( const LightTriangle& triangle, int subdivision )
+{
+    // Generate light vertex from triangle centroid
+    Push( triangle.GetCentroid() );
+
+    // The maximum subdivisions exceeded
+    if( subdivision >= maxSubdivisions_ ) {
+        return;
+    }
+
+    //  Tesselate a triangle
+    LightTriangle center, corners[3];
+    triangle.Tesselate( center, corners );
+
+    // Process corner triangles
+    for( int i = 0; i < 3; i++ )
+    {
+        GenerateFromTriangle( corners[i], subdivision + 1 );
+    }
+}
+
+// ---------------------------------------------- Triangle ---------------------------------------------- //
+
+LightTriangle::LightTriangle( const LightVertex& a, const LightVertex& b, const LightVertex& c ) :
+    a_( a ),
+    b_( b ),
+    c_( c )
+{
+    centroid_.position_ = (a_.position_ + b_.position_ + c_.position_)  / 3.0f;
+    centroid_.normal_   = (a_.normal_   + b_.normal_   + c_.normal_)    / 3.0f;
+    centroid_.normal_.Normalize();
+}
+
+const LightVertex& LightTriangle::GetCentroid( void ) const
+{
+    return centroid_;
+}
+
+void LightTriangle::Tesselate( LightTriangle& center, LightTriangle triangles[3] ) const
+{
+    LightVertex xA = LightVertex::Interpolate( a_, b_, 0.5f );
+    LightVertex xB = LightVertex::Interpolate( b_, c_, 0.5f );
+    LightVertex xC = LightVertex::Interpolate( c_, a_, 0.5f );
+
+    triangles[0] = LightTriangle( a_, xA,  xC  );
+    triangles[1] = LightTriangle( xA,  b_, xB  );
+    triangles[2] = LightTriangle( xC,  xB,  c_ );
+    center       = LightTriangle( xA,  xB,  xC  );
+}
+
 
 }

+ 94 - 43
Source/AtomicGlow/Kernel/BakeLight.h

@@ -41,6 +41,8 @@ namespace AtomicGlow
 class LightRay;
 class BakeMesh;
 class BakeLight;
+class LightVertexGenerator;
+
 
 /// Light cuttoff is used for configuring the light source influence direction (omni, directional, spotlight).
 /// LightCutoff class is a base for all cutoff models and represents an omni-directional light.
@@ -150,10 +152,10 @@ class LightInfluence : public RefCounted
 
     ATOMIC_REFCOUNTED(LightInfluence)
 
-public:
+    public:
 
-    /// Constructs a LightInfluence instance.
-    LightInfluence( const BakeLight* light );
+        /// Constructs a LightInfluence instance.
+        LightInfluence( const BakeLight* light );
 
     virtual ~LightInfluence( void ) {}
 
@@ -174,10 +176,10 @@ class DirectionalLightInfluence : public LightInfluence
 {
     ATOMIC_REFCOUNTED(DirectionalLightInfluence)
 
-public:
+    public:
 
-    /// Constructs a DirectionalLightInfluence instance.
-    DirectionalLightInfluence( const BakeLight* light, const Vector3& direction );
+        /// Constructs a DirectionalLightInfluence instance.
+        DirectionalLightInfluence( const BakeLight* light, const Vector3& direction );
 
     /// Calculates a directional light influence.
     virtual float Calculate( LightRay* lightRay, const Vector3& light, float& distance ) const;
@@ -193,7 +195,7 @@ class AmbientOcclusionInfluence : public LightInfluence
 {
     ATOMIC_REFCOUNTED(AmbientOcclusionInfluence)
 
-public:
+    public:
 
     /// Constructs a AmbientOcclusionInfluence instance.
     AmbientOcclusionInfluence( const BakeLight* light);
@@ -236,7 +238,7 @@ class DirectionalPhotonEmitter : public PhotonEmitter
 
     ATOMIC_REFCOUNTED(DirectionalPhotonEmitter)
 
-public:
+    public:
 
     // Constructs a new DirectionalPhotonEmitter instance.
     // param light Parent light source.
@@ -283,10 +285,10 @@ class BakeLight : public BakeNode
     void SetAttenuationModel( LightAttenuation* value );
 
     // Returns a light vertex generator.
-    // LightVertexGenerator* vertexGenerator( void ) const;
+    LightVertexGenerator* GetVertexGenerator( void ) const;
 
     // Sets an light vertex generator.
-    // void SetVertexGenerator( LightVertexGenerator* value );
+    void SetVertexGenerator( LightVertexGenerator* value );
 
     // Returns an cutoff model.
     LightCutoff* GetCutoffModel( void ) const;
@@ -343,7 +345,7 @@ class BakeLight : public BakeNode
     static BakeLight* CreateDirectionalLight( SceneBaker* baker, const Vector3& direction, const Color& color = Color::WHITE, float intensity = 1.0f, bool castsShadow = true );
 
     // Creates an area light instance.
-    // static BakeLight* CreateAreaLight( SceneBaker* baker, const Mesh* mesh, const Vector3& position, const Color& color = Color::WHITE, float intensity = 1.0f, bool castsShadow = true );
+    static BakeLight* CreateAreaLight( SceneBaker* baker, BakeMesh* mesh, const Vector3& position, const Color& color = Color::WHITE, float intensity = 1.0f, bool castsShadow = true );
 
 private:
 
@@ -372,80 +374,129 @@ private:
     SharedPtr<PhotonEmitter> photonEmitter_;
 
     // Light vertex sampler.
-    // SharedPtr<LightVertexGenerator> vertexGenerator_;
+    SharedPtr<LightVertexGenerator> vertexGenerator_;
 
 };
 
-/*
-
-// Zone ambient, etc
-class ZoneBakeLight : public BakeLight
+// A light vertex is a single light point used with mesh light sources.
+struct LightVertex
 {
-    ATOMIC_OBJECT(ZoneBakeLight, BakeLight)
+    // Point position.
+    Vector3 position_;
+    // Point normal.
+    Vector3  normal_;
 
-    public:
+    static LightVertex Interpolate( const LightVertex& a, const LightVertex& b, float scalar )
+    {
+        LightVertex result;
 
-    ZoneBakeLight(Context* context, SceneBaker* sceneBaker);
-    virtual ~ZoneBakeLight();
+        result.position_ = a.position_ * scalar + b.position_ * (1.0f - scalar);
 
-    void Light(LightRay* lightRay);
-    void SetLight(Atomic::BakeLight* light) {}
+        result.normal_ = a.normal_ * scalar + b.normal_ * (1.0f - scalar);
+        result.normal_.Normalize();
 
-    void SetZone(Zone* zone);
+        return result;
+    }
+};
 
-protected:
+// A helper class to tesselate faces.
+class LightTriangle
+{
+public:
+
+    /// Constructs a Triangle instance
+    LightTriangle( void ) {}
+
+    /// Constructs a Triangle instance from three vertices.
+    LightTriangle( const LightVertex& a, const LightVertex& b, const LightVertex& c );
+
+    /// Returns a triangle centroid.
+    const LightVertex&   GetCentroid( void ) const;
+
+    /// Tesselates a triangle. Splits this triangle into 4 smaller ones.
+    /// param center Output center triangle.
+    /// param triangles Three triangles on corners.
+    void Tesselate( LightTriangle& center, LightTriangle triangles[3] ) const;
 
 private:
 
-    Zone* zone_;
+    // Triangle vertices
+    LightVertex a_, b_, c_;
 
+    // Triangle centroid.
+    LightVertex centroid_;
 };
 
 
-class DirectionalBakeLight : public BakeLight
+typedef PODVector<LightVertex> LightVertexVector;
+
+/// A LightVertexGenerator used to generate a set of light points for mesh light sources.
+class LightVertexGenerator : public RefCounted
 {
-    ATOMIC_OBJECT(DirectionalBakeLight, BakeLight)
+    ATOMIC_REFCOUNTED(LightVertexGenerator)
 
     public:
 
-        DirectionalBakeLight(Context* context, SceneBaker* sceneBaker);
-    virtual ~DirectionalBakeLight();
+    /// Constructs a LightVertexGenerator instance.
+    LightVertexGenerator( BakeMesh* bakeMesh );
+    virtual ~LightVertexGenerator( void ) {}
 
-    void Set(const Vector3& direction, const Vector3& radiance, float cosAngle);
+    /// Returns vector of light vertices.
+    const LightVertexVector& GetVertices( void ) const;
 
-    void Light(LightRay* lightRay);
+    /// Generates a set of light vertices based on mesh vertices.
+    virtual void Generate( void );
 
-    void SetLight(Atomic::BakeLight* light);
+    /// Clears a previously generated data.
+    void Clear( void );
 
+    /// Returns a total number of light vertices.
+    unsigned GetVertexCount( void ) const;
 
 protected:
 
+    /// Adds a new light vertex.
+    void Push( const LightVertex& vertex );
 
-private:
+protected:
+
+    // Source mesh.
+    WeakPtr<BakeMesh> mesh_;
 
+    // Set of generated light vertices.
+    LightVertexVector vertices_;
 };
 
-class PointBakeLight : public BakeLight
+/// A FaceLightVertexGenerator generates a set of vertices based on mesh vertices & face centroids.
+/// Face based generator can also perform a mesh tesselation.
+class FaceLightVertexGenerator : public LightVertexGenerator
 {
-    ATOMIC_OBJECT(PointBakeLight, BakeLight)
+    ATOMIC_REFCOUNTED(FaceLightVertexGenerator)
 
     public:
 
-        PointBakeLight(Context* context, SceneBaker* sceneBaker);
-    virtual ~PointBakeLight();
+    /// Constructs a FaceLightVertexGenerator instance.
+    /// param mesh Source light mesh.
+    /// param excludeVertices The flag indicating that we should skip mesh vertices.
+    /// param maxSubdivisions Maximum subdivision steps per mesh face (0 means no tesselation).
+    FaceLightVertexGenerator( BakeMesh* bakeMesh, bool excludeVertices = true, int maxSubdivisions = 0 );
 
-    void Light(LightRay* lightRay);
+    /// Generates a set of light vertices.
+    virtual void Generate( void );
 
-    void SetLight(Atomic::BakeLight* light);
-
-protected:
+private:
 
+    /// Generates a set of light vertices from triangle.
+    virtual void GenerateFromTriangle( const LightTriangle& triangle, int subdivision );
 
 private:
 
-};
+    /// The flag indicating that we should skip mesh vertices.
+    bool excludeVertices_;
 
-*/
+    /// Max subdivision depth.
+    int  maxSubdivisions_;
+};
 
 
 }

+ 1 - 1
Source/AtomicGlow/Kernel/BakeMesh.h

@@ -95,7 +95,7 @@ class BakeMesh : public BakeNode
     /// Get world space bounding box
     const BoundingBox& GetBoundingBox() const { return boundingBox_; }    
     const SharedArrayPtr<MMVertex>& GetVertices(unsigned& numVertices) const { numVertices = numVertices_; return vertices_; }
-    const SharedArrayPtr<MMTriangle>& GetTriangles(unsigned numTriangles) const { numTriangles = numTriangles_; return triangles_; }
+    const SharedArrayPtr<MMTriangle>& GetTriangles(unsigned& numTriangles) const { numTriangles = numTriangles_; return triangles_; }
 
     void Preprocess();
 

+ 49 - 26
Source/AtomicGlow/Kernel/SceneBaker.cpp

@@ -423,7 +423,7 @@ bool SceneBaker::LoadScene(const String& filename)
 
         staticModel->SetZone(newZone, false);
 
-        if (staticModel->GetModel() && (staticModel->GetLightmap() ||staticModel->GetCastShadows()))
+        if (staticModel->GetModel() && (staticModel->GetLightmap() || staticModel->GetCastShadows()))
         {
             Model* model = staticModel->GetModel();
 
@@ -473,6 +473,17 @@ bool SceneBaker::LoadScene(const String& filename)
             SharedPtr<BakeMesh> meshMap (new BakeMesh(context_, this));
             meshMap->SetStaticModel(staticModel);
             bakeMeshes_.Push(meshMap);
+
+            if (staticModel->GetNode()->GetName() == "Plane")
+            {
+                // NOTE: photo emitter should probably be using the vertex generator not staticModel world position
+                BakeLight* bakeLight = BakeLight::CreateAreaLight(this, meshMap, staticModel->GetNode()->GetWorldPosition(), Color::WHITE);
+                if (bakeLight)
+                {
+                    bakeLights_.Push(SharedPtr<BakeLight>(bakeLight));
+                }
+
+            }
         }
 
     }
@@ -490,11 +501,11 @@ void SceneBaker::DirectLight( LightRay* lightRay, const PODVector<BakeLight*>& b
 
         Color influence;
 
-        // if (light->GetVertexGenerator())
-        //{
-        // influence = DirectLightFromPointSet( lightRay, bakeLight );
-        //}
-        //else
+        if (bakeLight->GetVertexGenerator())
+        {
+            influence = DirectLightFromPointSet( lightRay, bakeLight );
+        }
+        else
         {
             influence = DirectLightFromPoint( lightRay, bakeLight );
         }
@@ -521,31 +532,39 @@ Color SceneBaker::DirectLightFromPoint( LightRay* lightRay, const BakeLight* lig
 
 Color SceneBaker::DirectLightFromPointSet( LightRay* lightRay, const BakeLight* light ) const
 {
-    /*
-    LightVertexGenerator* vertexGenerator = light->vertexGenerator();
+    LightVertexGenerator* vertexGenerator = light->GetVertexGenerator();
 
-    // ** No light vertices generated - just exit
-    if( vertexGenerator->vertexCount() == 0 ) {
-        return Rgb( 0, 0, 0 );
+    if (!vertexGenerator)
+    {
+        // this should not happen
+        ATOMIC_LOGERROR("SceneBaker::DirectLightFromPointSet - called without vertex generator");
+        return Color::BLACK;
     }
 
-    const LightVertexBuffer& vertices = vertexGenerator->vertices();
-    Rgb                      color    = Rgb( 0, 0, 0 );
+    // No light vertices generated - just exit
+    if( !vertexGenerator->GetVertexCount())
+    {
+        return Color::BLACK;
+    }
+
+    const LightVertexVector& vertices = vertexGenerator->GetVertices();
+    Color color = Color::BLACK;
 
-    for( int i = 0, n = vertexGenerator->vertexCount(); i < n; i++ ) {
-        const LightVertex&  vertex    = vertices[i];
-        float               influence = influenceFromPoint( lumel, vertex.m_position + light->position(), light );
+    for( unsigned i = 0, n = vertexGenerator->GetVertexCount(); i < n; i++ )
+    {
+        const LightVertex&  vertex = vertices[i];
+        float influence = DirectLightInfluenceFromPoint( lightRay, vertex.position_ /*+ light->GetPosition()*/, light );
 
         // ** We have a non-zero light influence - add a light color to final result
-        if( influence > 0.0f ) {
-            color += light->color() * light->intensity() * influence;
+        if( influence > 0.0f )
+        {
+            color += light->GetColor() * light->GetIntensity() * influence;
         }
     }
 
-    return color / static_cast<float>( vertexGenerator->vertexCount() );
-    */
+    color = color * ( 1.0f / static_cast<float>( vertexGenerator->GetVertexCount()));
 
-    return Color::BLACK;
+    return color;
 }
 
 // ** DirectLight::influenceFromPoint
@@ -608,14 +627,18 @@ void SceneBaker::IndirectLight( LightRay* lightRay)
 
         rtcIntersect(GetEmbreeScene()->GetRTCScene(), ray);
 
+        bool skyEnabled = true;
+
         if (ray.geomID == RTC_INVALID_GEOMETRY_ID)
         {
-            Color skyColor(130.0f/255.0f, 209.0f/255.0f, 207.0f/255.0f);
-
-            skyColor = skyColor * 0.30f;
+            if (skyEnabled)
+            {
+                Color skyColor(130.0f/255.0f, 209.0f/255.0f, 207.0f/255.0f);
+                skyColor = Color::WHITE * 0.15f;
+                gathered += (skyColor * influence).ToVector3();// + ambientColor;
+                hits++;
+            }
 
-            gathered += (skyColor * influence).ToVector3();// + ambientColor;
-            hits++;
             continue;
         }