Some experiments for Cloud lighting
This commit is contained in:
parent
d7d38944ea
commit
7ec5a8a5f4
3 changed files with 63 additions and 2 deletions
|
@ -29,7 +29,7 @@ int main()
|
||||||
scene.setBackgroundColor(Color(0.529f, 0.808f, 0.922f));
|
scene.setBackgroundColor(Color(0.529f, 0.808f, 0.922f));
|
||||||
|
|
||||||
// Add lights
|
// Add lights
|
||||||
auto mainLight = std::make_shared<SunLight>(Vector3d(1.0f, -1.0f, -1.0f), 10.0f);
|
auto mainLight = std::make_shared<SunLight>(Vector3d(-1.0f, -0.5f, -1.0f), 10.0f);
|
||||||
scene.add(mainLight);
|
scene.add(mainLight);
|
||||||
scene.add(std::make_shared<AmbientLight>(0.3f));
|
scene.add(std::make_shared<AmbientLight>(0.3f));
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const
|
||||||
|
|
||||||
// Step through cloud
|
// Step through cloud
|
||||||
float transmittance = 1.0f;
|
float transmittance = 1.0f;
|
||||||
|
Color cloudColor = Color(1, 1, 1);
|
||||||
for (int i = 0; i < noiseSamples; ++i)
|
for (int i = 0; i < noiseSamples; ++i)
|
||||||
{
|
{
|
||||||
// Get sample point
|
// Get sample point
|
||||||
|
@ -45,8 +46,10 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const
|
||||||
|
|
||||||
// Get data at point
|
// Get data at point
|
||||||
float sampleDensity = getCloudDensity(samplePoint) * stepLength;
|
float sampleDensity = getCloudDensity(samplePoint) * stepLength;
|
||||||
|
// cloudColor += lightMarch(scene, samplePoint, ray);
|
||||||
|
|
||||||
transmittance *= exp(-sampleDensity * stepLength * settings.densityAbsorption);
|
transmittance *= exp(-sampleDensity * stepLength * settings.densityAbsorption);
|
||||||
|
if (transmittance <= TRANSMITTANCE_BREAK) break; // No need to continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add some ambient and diffuse lighting
|
// Add some ambient and diffuse lighting
|
||||||
|
@ -59,7 +62,7 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const
|
||||||
// cloud += material.cloud() * illumination.cloud * diffuse;
|
// cloud += material.cloud() * illumination.cloud * diffuse;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return background * transmittance + (1.0f - transmittance) * settings.cloudColor;
|
return background * transmittance + (1.0f - transmittance) * cloudColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CloudShader::isTransparent() const
|
bool CloudShader::isTransparent() const
|
||||||
|
@ -84,3 +87,55 @@ float CloudShader::getCloudDensity(Vector3d point) const
|
||||||
|
|
||||||
return density;
|
return density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color CloudShader::lightMarch(const Scene &scene, Vector3d position, const Ray &ray) const
|
||||||
|
{
|
||||||
|
Color cloudColor;
|
||||||
|
|
||||||
|
// For alle lights
|
||||||
|
for (const auto &light: scene.lights())
|
||||||
|
{
|
||||||
|
auto illumination = light->illuminate(scene, position);
|
||||||
|
|
||||||
|
// Get light direction
|
||||||
|
Vector3d lightDirection = normalized(illumination.direction); // Points from surface to light
|
||||||
|
|
||||||
|
// Get length of remaining cloud in light direction
|
||||||
|
float cloudLength = 0.0f;
|
||||||
|
|
||||||
|
Ray cloudRay = ray;
|
||||||
|
cloudRay.origin = position;
|
||||||
|
cloudRay.direction = lightDirection;
|
||||||
|
cloudRay.length = INFINITY;
|
||||||
|
cloudRay.primitive = nullptr;
|
||||||
|
|
||||||
|
// Find other end of cloud
|
||||||
|
if (!ray.primitive->intersect(cloudRay) || cloudRay.length == INFINITY)
|
||||||
|
{
|
||||||
|
// No cloud or at edge
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cloudLength = cloudRay.length;
|
||||||
|
|
||||||
|
// Calculate step length
|
||||||
|
int lightSamples = settings.lightSamples;
|
||||||
|
float stepLength = cloudLength / lightSamples;
|
||||||
|
|
||||||
|
// Step through cloud
|
||||||
|
float transmittance = 0.0f;
|
||||||
|
for (int i = 0; i < lightSamples; ++i)
|
||||||
|
{
|
||||||
|
Vector3d samplePoint = position + i * stepLength * lightDirection;
|
||||||
|
float density = getCloudDensity(samplePoint) * stepLength;
|
||||||
|
transmittance *= exp(-density * settings.densityAbsorption);
|
||||||
|
|
||||||
|
if (transmittance <= TRANSMITTANCE_BREAK) break; // No need to continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// float lightAbsorption = dotProduct(lightDirection, ray.direction); // Approaches 1 when light is parallel to ray
|
||||||
|
|
||||||
|
cloudColor += transmittance * illumination.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloudColor;
|
||||||
|
}
|
||||||
|
|
|
@ -3,19 +3,23 @@
|
||||||
|
|
||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
#include "light/light.h"
|
||||||
#include "primitive/primitive.h"
|
#include "primitive/primitive.h"
|
||||||
#include "common/noise/worleynoise.h"
|
#include "common/noise/worleynoise.h"
|
||||||
|
|
||||||
int const NOISE_SIZE = 128;
|
int const NOISE_SIZE = 128;
|
||||||
|
int const TRANSMITTANCE_BREAK = 0.01f; // If transmittance goes below this limit, the cloud is considered opaque
|
||||||
|
|
||||||
struct CloudSettings
|
struct CloudSettings
|
||||||
{
|
{
|
||||||
int densitySamples = 100;
|
int densitySamples = 100;
|
||||||
|
int lightSamples = 25;
|
||||||
float scale = 10;
|
float scale = 10;
|
||||||
float densityTreshold = 0.55f;
|
float densityTreshold = 0.55f;
|
||||||
float densityIntensity = 2.5f;
|
float densityIntensity = 2.5f;
|
||||||
float densityAbsorption = 2;
|
float densityAbsorption = 2;
|
||||||
Color cloudColor = Color(1, 1, 1);
|
Color cloudColor = Color(1, 1, 1);
|
||||||
|
float darknessThreshold = 0.1f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CloudShader : public Shader
|
class CloudShader : public Shader
|
||||||
|
@ -35,6 +39,8 @@ private:
|
||||||
Noise cloudNoise;
|
Noise cloudNoise;
|
||||||
|
|
||||||
float getCloudDensity(Vector3d point) const;
|
float getCloudDensity(Vector3d point) const;
|
||||||
|
|
||||||
|
Color lightMarch(const Scene &scene, Vector3d position, const Ray &ray) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue