#ifndef CG1_TRACER_CLOUDSHADER_H #define CG1_TRACER_CLOUDSHADER_H #include "scene/scene.h" #include "shader.h" #include "light/light.h" #include "primitive/primitive.h" #include "common/noise/worleynoise.h" int const NOISE_SIZE = 64; float const TRANSMITTANCE_BREAK = 0.0001f; // If transmittance goes below this limit, the cloud is considered opaque struct CloudSettings { unsigned int seed = 0; // 0 for random seed float densitySteps = .2f; // .2f float scale = 30; // 30 float densityOffset = -.55f; // -.55f float densityIntensity = 5.0f; // 5.0f float darknessThreshold = .1f; // .1f float shadowIntensity = .6f; // .6f float shadowLightAbsorption = 1; // 1 float lightAbsorptionTowardsLight = 0.1f; // .3f // How Bright should the clouds be? Lower is brighter float lightAbsorptionThroughCloud = .8f; // .8f // How dark should the background be where the cloud is? Higher values mean darker background float phaseA = .8f; // .5f float phaseB = .4f; // .3f float phaseOffset = .8f; // .8f float phaseIntensity = .1f; // 1.0f float edgeFadeOffDistance = .5f; // .5f }; class CloudShader : public Shader { public: CloudShader(CloudSettings const &settings = CloudSettings()); // Shader functions Color shade(Scene const &scene, Ray const &ray) const; Color transparency(const Scene &scene, const Ray &ray, float maxLength) const override; private: CloudSettings settings; bool isTransparent() const; Noise cloudNoise; float getCloudDensity(Vector3d point, const Primitive *primitive = nullptr) const; Color lightMarch(const Scene &scene, Vector3d currentInCloudPosition, Vector3d lengthDistance, const Primitive *cloudObject) const; float rayDensity(const Ray &ray, float maxLength) const; float phase(Vector3d visualRay, Vector3d illuminationRay) const; static float calcDualHenyeyGreenstein(float cosTheta, float g) ; static float calcBeer(float d) ; float getEdgeDensity(const Vector3d &point, const Primitive *primitive) const; }; #endif //CG1_TRACER_CLOUDSHADER_H