Commit 1e89aec1 authored by Georg Schaefer's avatar Georg Schaefer
Browse files

add athmospheric scattering for the planet

parent 8d402aec
#version 330
in vec2 texcoord_;
in vec3 color0_;
in vec3 color1_;
out vec4 frag_color;
uniform sampler2D albedo_texture;
void main() {
frag_color = texture(albedo_texture, texcoord_);
frag_color = vec4(color0_ + texture(albedo_texture, texcoord_).rgb * color1_, 1.f);
}
......@@ -6,12 +6,75 @@ in vec3 _normal;
in vec3 _tangent;
out vec2 texcoord_;
out vec3 color0_;
out vec3 color1_;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec3 camera_position;
uniform vec3 light_direction;
uniform vec3 inverse_wave_length;
uniform float camera_height;
uniform float camera_height_squared;
uniform float outer_radius;
uniform float outer_radius_squared;
uniform float inner_radius;
uniform float inner_radius_squared;
uniform float rayleigh_times_energy;
uniform float mie_times_energy;
uniform float rayleigh_times_four_pi;
uniform float mie_times_four_pi;
uniform float scale;
uniform float scale_depth;
uniform float scale_over_scale_depth;
const int samples_integral = 2;
const float samples_float = 2.f;
float scale_angle(float alpha) {
float x = 1.f - alpha;
return scale_depth * exp(-0.00287f + x * (0.459f + x * (3.83f + x * (-6.80f + x * 5.25f))));
}
void main() {
vec3 ray = _position - camera_position;
float far = length(ray);
ray /= far;
float b = 2.f * dot(camera_position, ray);
float c = camera_height_squared - outer_radius_squared;
float det = max(0.f, b * b - 4.f * c);
float near = 0.5f * (-b - sqrt(det));
vec3 start = camera_position + ray * near;
far -= near;
float depth = exp((inner_radius - outer_radius) / scale_depth);
float camera_angle = dot(-ray, _position) / length(_position);
float light_angle = dot(light_direction, _position) / length(_position);
float camera_scale = scale_angle(camera_angle);
float light_scale = scale_angle(light_angle);
float camera_offset = depth * camera_scale;
float temp = (light_scale + camera_scale);
float sample_length = far / samples_float;
float scaled_length = sample_length * scale;
vec3 sample_ray = ray * sample_length;
vec3 sample_point = start + sample_ray * 0.5f;
vec3 color0 = vec3(0.f);
vec3 color1 = vec3(0.f);
for (int i = 0; i < samples_integral; ++i) {
float height = length(sample_point);
float depth = exp(scale_over_scale_depth * (inner_radius - height));
float scatter = depth * temp - camera_offset;
color1 = exp(-scatter * (inverse_wave_length * rayleigh_times_four_pi + mie_times_four_pi));
color0 += color1 * (depth * scaled_length);
sample_point += sample_ray;
}
gl_Position = projection * view * model * vec4(_position, 1.f);
texcoord_ = _texcoord;
color0_ = color0 * (inverse_wave_length * rayleigh_times_energy + mie_times_energy);
color1_ = color1;
}
......@@ -882,6 +882,25 @@ namespace gdw {
}
void rendering_system::render_planet(camera_component& camera) {
if (directional_light_components_.empty()) {
return;
}
static const auto wavelength = glm::vec3(0.65f, 0.57f, 0.475f);
static const auto wavelength_high_four = glm::vec3(glm::pow(wavelength.r, 4.f), glm::pow(wavelength.g, 4.f), glm::pow(wavelength.b, 4.f));
static const auto inner_radius = 100.f;
static const auto outer_radius = 102.5f;
static const auto sun_energy = 20.f;
static const auto rayleigh_constant = 0.0025f;
static const auto rayleigh_times_energy = rayleigh_constant * sun_energy;
static const auto rayleigh_times_four_pi = rayleigh_constant * 4.f * glm::pi<float>();
static const auto mie_constant = 0.001f;
static const auto mie_times_energy = mie_constant * sun_energy;
static const auto mie_times_four_pi = mie_constant * 4.f * glm::pi<float>();
static const auto scale = 1.f / (outer_radius - inner_radius);
static const auto scale_depth = 0.25f;
auto camera_position = camera.owner().position();
composition_buffer_.bind();
glEnable(GL_DEPTH_TEST);
......@@ -892,6 +911,22 @@ namespace gdw {
planet_program_.uniform("projection", false, camera.projection());
planet_program_.uniform("view", false, camera.view());
planet_program_.uniform("model", false, planet_model_);
planet_program_.uniform("camera_position", 405.f * glm::normalize(camera_position));
planet_program_.uniform("light_direction", directional_light_components_.front()->owner().position());
planet_program_.uniform("inverse_wave_length", 1.f / wavelength_high_four);
planet_program_.uniform("camera_height", glm::length(camera_position));
planet_program_.uniform("camera_height_squared", glm::length2(camera_position));
planet_program_.uniform("outer_radius", outer_radius);
planet_program_.uniform("outer_radius_squared", outer_radius * outer_radius);
planet_program_.uniform("inner_radius", inner_radius);
planet_program_.uniform("inner_radius_sqaured", inner_radius * inner_radius);
planet_program_.uniform("rayleigh_times_energy", rayleigh_times_energy);
planet_program_.uniform("mie_times_energy", mie_times_energy);
planet_program_.uniform("rayleigh_times_four_pi", rayleigh_times_four_pi);
planet_program_.uniform("mie_times_four_pi", mie_times_four_pi);
planet_program_.uniform("scale", scale);
planet_program_.uniform("scale_depth", scale_depth);
planet_program_.uniform("scale_over_scale_depth", scale / scale_depth);
planet_program_.uniform("albedo_texture", 0);
planet_->draw(planet_program_);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment