diff --git a/fancy1.cpp b/fancy1.cpp index 04271ee..86b4830 100644 --- a/fancy1.cpp +++ b/fancy1.cpp @@ -29,9 +29,10 @@ int main() { FastScene scene; scene.setBackgroundColor(Color(0.529f, 0.808f, 0.922f) * 1.0f); +// scene.setBackgroundColor(Color(1, 0.79f, 0.62f) * 0.8f); // Add lights - auto mainLight = std::make_shared(Vector3d(-1.0f, -0.5f, -1.0f), 5.0f, Color(1, 0.79f, 0.62f)); + auto mainLight = std::make_shared(Vector3d(-1.0f, -0.5f, -1.0f), 2.0f, Color(1,1,1));//Color(1, 0.79f, 0.62f)); scene.add(mainLight); // scene.add(std::make_shared(0.3f)); // auto light = std::make_shared(Vector3d(25.0f, 10.0f, 25.0f), 100.0f); @@ -43,10 +44,10 @@ int main() // busShader); // Refraction boxes - auto boxShader = std::make_shared(1.05f, 1, Color(1,1,0), 0.7f); - scene.add(std::make_shared(Vector3d(5.0f, 3.0f, 10.0f), Vector3d(3.0f, 3.0f, 3.0f), boxShader)); - auto boxShader1 = std::make_shared(1.05f, 1, Color(0,1,1), 0.7f); - scene.add(std::make_shared(Vector3d(9.0f, 3.0f, 12.0f), Vector3d(3.0f, 3.0f, 3.0f), boxShader1)); +// auto boxShader = std::make_shared(1.05f, 1, Color(1,1,0), 0.7f); +// scene.add(std::make_shared(Vector3d(5.0f, 3.0f, 10.0f), Vector3d(3.0f, 3.0f, 3.0f), boxShader)); +// auto boxShader1 = std::make_shared(1.05f, 1, Color(0,1,1), 0.7f); +// scene.add(std::make_shared(Vector3d(9.0f, 3.0f, 12.0f), Vector3d(3.0f, 3.0f, 3.0f), boxShader1)); // Add floor auto floorShader = std::make_shared(Color(0.9f, 0.9f, 0.9f)); diff --git a/shader/cloudshader.cpp b/shader/cloudshader.cpp index 6df0fd1..830fde3 100644 --- a/shader/cloudshader.cpp +++ b/shader/cloudshader.cpp @@ -33,10 +33,10 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const // Calculate step length int noiseSamples = settings.densitySamples; - float stepLength = cloudLength / noiseSamples; + float stepLength = cloudLength / (float) noiseSamples; // Step through cloud - float transmittance = 1; + float accumulatedDensity = 0.0f; Color cloudColor = Color(0, 0, 0); for (int i = 0; i < noiseSamples; ++i) { @@ -49,14 +49,14 @@ Color CloudShader::shade(const Scene &scene, const Ray &ray) const if (sampleDensity > 0) { - cloudColor += lightMarch(scene, samplePoint, lengthDirection) * stepLength * sampleDensity; + cloudColor += lightMarch(scene, samplePoint, lengthDirection, ray.primitive) * sampleDensity; } - transmittance *= exp(-sampleDensity * stepLength * settings.lightAbsorptionThroughCloud); - - if (transmittance < TRANSMITTANCE_BREAK) break; // Cloud is effectively opaque + accumulatedDensity += sampleDensity; } + float transmittance = exp(-accumulatedDensity * settings.lightAbsorptionThroughCloud); + return background * transmittance + cloudColor; } @@ -84,15 +84,17 @@ float CloudShader::getCloudDensity(Vector3d point) const return density; } -Color CloudShader::lightMarch(const Scene &scene, Vector3d currentInCloudPosition, Vector3d lengthDistance) const +Color CloudShader::lightMarch(const Scene &scene, Vector3d currentInCloudPosition, Vector3d lengthDistance, + const Primitive *cloudObject) const { - Color cloudColor; + Color cloudColor = Color(0, 0, 0); // For alle lights for (const auto &light: scene.lights()) { Ray ray = Ray(currentInCloudPosition - lengthDistance, normalized(lengthDistance)); ray.length = length(lengthDistance); + ray.primitive = cloudObject; auto illumination = light->illuminate(scene, ray); // Handle ambient lights @@ -106,22 +108,30 @@ Color CloudShader::lightMarch(const Scene &scene, Vector3d currentInCloudPositio Ray lightRay; lightRay.origin = currentInCloudPosition; lightRay.direction = illumination.direction; + lightRay.primitive = cloudObject; lightRay.length = 0; // Starting in cloud itself float density = this->rayDensity(lightRay, illumination.distance); density *= settings.lightAbsorptionTowardsLight; // Proper light calculation - float transmittance = exp(-density) * (1 - exp(-density * 2)); + float transmittance = getDensityTransmittance(density); float scatter = scatterFactor(normalized(lengthDistance), illumination.direction); - float factor = settings.darknessThreshold + (scatter * transmittance) * (1 - settings.darknessThreshold); // (transmittance * scatter) + // TODO: Back to default + float factor = settings.darknessThreshold + + (1.0f - settings.darknessThreshold) * (1); // (transmittance * scatter) cloudColor += factor * illumination.color; } return cloudColor; } +float CloudShader::getDensityTransmittance(float density) const +{ + return exp(-density) * (1 - exp(-density * 2)) / 0.4f; +} + Color CloudShader::transparency(const Scene &scene, const Ray &ray, float maxLength) const { float density = rayDensity(ray, maxLength); @@ -163,9 +173,7 @@ float CloudShader::rayDensity(const Ray &ray, float maxLength) const Vector3d samplePoint = startPoint + i * stepLength * ray.direction; // Get data at point - float sampleDensity = getCloudDensity(samplePoint) * stepLength; - - density += sampleDensity * stepLength; + density += getCloudDensity(samplePoint) * stepLength; } // If there is length left, check if it is in the cloud recursively @@ -189,14 +197,14 @@ float CloudShader::rayDensity(const Ray &ray, float maxLength) const float CloudShader::scatterFactor(Vector3d visualRay, Vector3d illuminationRay) const { // The asymmetry parameter - float g = 0.7f; + float g = settings.scatterWeight; // The angle between the visual and illumination rays float cosTheta = dotProduct(visualRay, illuminationRay); // The Dual-Lob Henyey-Greenstein function float blend = .5; - float scatter = HenyeyGreenstein(cosTheta,g) * (1-blend) + HenyeyGreenstein(cosTheta,-g) * blend; + float scatter = HenyeyGreenstein(cosTheta, g) * (1 - blend) + HenyeyGreenstein(cosTheta, -g) * blend; // Clamp the result to the range [0, 1] scatter = std::max(std::min(scatter, 1.0f), 0.0f); diff --git a/shader/cloudshader.h b/shader/cloudshader.h index c0773ea..cb4fc7a 100644 --- a/shader/cloudshader.h +++ b/shader/cloudshader.h @@ -16,12 +16,13 @@ struct CloudSettings int lightSamples = 100; float scale = 10; float densityOffset = -0.57f; - float densityIntensity = 7.0f; - float darknessThreshold = 0.07f; - float shadowIntensity = 0.8f; + float densityIntensity = 7.0f; // 7.0f + float darknessThreshold = 0.2f; // 0.07f + float shadowIntensity = 0.6f; float shadowLightAbsorption = 1; - float lightAbsorptionTowardsLight = 0.94f; - float lightAbsorptionThroughCloud = 0.85f; + float lightAbsorptionTowardsLight = 1.0f; + float lightAbsorptionThroughCloud = 0.5f; + float scatterWeight = 0.5f; }; class CloudShader : public Shader @@ -43,13 +44,15 @@ private: float getCloudDensity(Vector3d point) const; - Color lightMarch(const Scene &scene, Vector3d currentInCloudPosition, Vector3d lengthDistance) const; + Color lightMarch(const Scene &scene, Vector3d currentInCloudPosition, Vector3d lengthDistance, const Primitive *cloudObject) const; float rayDensity(const Ray &ray, float maxLength) const; float scatterFactor(Vector3d visualRay, Vector3d illuminationRay) const; float HenyeyGreenstein(float cosTheta, float g) const; + + float getDensityTransmittance(float density) const; };