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));
|
||||
|
||||
// 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(std::make_shared<AmbientLight>(0.3f));
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const
|
|||
|
||||
// Step through cloud
|
||||
float transmittance = 1.0f;
|
||||
Color cloudColor = Color(1, 1, 1);
|
||||
for (int i = 0; i < noiseSamples; ++i)
|
||||
{
|
||||
// Get sample point
|
||||
|
@ -45,8 +46,10 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const
|
|||
|
||||
// Get data at point
|
||||
float sampleDensity = getCloudDensity(samplePoint) * stepLength;
|
||||
// cloudColor += lightMarch(scene, samplePoint, ray);
|
||||
|
||||
transmittance *= exp(-sampleDensity * stepLength * settings.densityAbsorption);
|
||||
if (transmittance <= TRANSMITTANCE_BREAK) break; // No need to continue
|
||||
}
|
||||
|
||||
// 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;
|
||||
// }
|
||||
|
||||
return background * transmittance + (1.0f - transmittance) * settings.cloudColor;
|
||||
return background * transmittance + (1.0f - transmittance) * cloudColor;
|
||||
}
|
||||
|
||||
bool CloudShader::isTransparent() const
|
||||
|
@ -84,3 +87,55 @@ float CloudShader::getCloudDensity(Vector3d point) const
|
|||
|
||||
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 "shader.h"
|
||||
#include "light/light.h"
|
||||
#include "primitive/primitive.h"
|
||||
#include "common/noise/worleynoise.h"
|
||||
|
||||
int const NOISE_SIZE = 128;
|
||||
int const TRANSMITTANCE_BREAK = 0.01f; // If transmittance goes below this limit, the cloud is considered opaque
|
||||
|
||||
struct CloudSettings
|
||||
{
|
||||
int densitySamples = 100;
|
||||
int lightSamples = 25;
|
||||
float scale = 10;
|
||||
float densityTreshold = 0.55f;
|
||||
float densityIntensity = 2.5f;
|
||||
float densityAbsorption = 2;
|
||||
Color cloudColor = Color(1, 1, 1);
|
||||
float darknessThreshold = 0.1f;
|
||||
};
|
||||
|
||||
class CloudShader : public Shader
|
||||
|
@ -35,6 +39,8 @@ private:
|
|||
Noise cloudNoise;
|
||||
|
||||
float getCloudDensity(Vector3d point) const;
|
||||
|
||||
Color lightMarch(const Scene &scene, Vector3d position, const Ray &ray) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue