I'll post screenshots and shaders for analysis...
Good far away screenshot!
Good Inside Atmosphere Screenshot
Bad Middle Ground Screenshot:
Here is my shader, remember, all incoming positions, normals, etc, are in object space, and I output to my deferred renderer in world space. In the fragment you'll notice I'm using MRTs. I only write to the last one in the case of a translucent forward shaded object like this. Any thoughts on this would surely be appreciated!
Vertex Shader
#version 130
uniform mat4 projection_matrix;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 normal_matrix;
in vec4 vertex_position;
in vec4 vertex_normal;
in vec4 vertex_texcoord;
in vec4 vertex_binormal;
in vec4 vertex_bitangent;
in vec4 vertex_weights;
in ivec4 vertex_weight_indices;
smooth out vec3 object_position;
smooth out vec3 world_position;
smooth out vec3 normal;
void main() {
object_position = vertex_position.xyz;
world_position = (model_matrix * vertex_position).xyz;
normal = normalize(object_position);
gl_Position = projection_matrix * view_matrix * model_matrix * vertex_position;
}
Fragment Shader
#version 130
smooth in vec3 object_position;
smooth in vec3 world_position;
smooth in vec3 normal;
uniform vec3 camera_position;
uniform float material_specularity;
uniform vec4 material_color;
uniform int normal_mapping_enabled;
uniform int receives_lighting;
uniform sampler2D decal_map;
uniform vec4 light_position;
uniform float inner_radius;
uniform float outer_radius;
out vec4 fragment0;
out vec4 fragment1;
out vec4 fragment2;
out vec4 fragment3;
void main() {
// constants
float stretch_amount = 0.001;
float exposure = 0.5;
float g = -0.990;
float g2 = g * g;
float tweak_amount = 0.025;
float outer_radius2 = outer_radius * outer_radius;
float camera_height = length(camera_position);
vec3 camera_to_position = world_position - camera_position;
float far_distance = length(camera_to_position);
vec3 light_direction = normalize(light_position.xyz - camera_position);
vec3 ray_direction = camera_to_position / far_distance;
float camera_height2 = camera_height * camera_height;
float B = 2.0 * dot(camera_position.xyz, ray_direction);
float C = camera_height2 - outer_radius2;
float det = max(00, B*B - 4.0 * C);
float near_distance = 0.5 * (-B - sqrt(det));
vec3 near_position = camera_position.xyz + (ray_direction * near_distance);
vec3 near_normal = normalize(near_position);
float lc = dot(light_direction, camera_position / camera_height);
float ln = dot(light_direction, normal);
float lnn = dot(light_direction, near_normal);
float altitude = camera_height - inner_radius;
float horizon_distance = sqrt((altitude * altitude) + (2.0 * inner_radius * altitude));
float max_dot = horizon_distance / camera_height;
altitude = max(0.0, camera_height - outer_radius);
horizon_distance = sqrt((altitude * altitude) + (2.0 * outer_radius * altitude));
float min_dot = max(tweak_amount, horizon_distance / camera_height);
float min_dot2 = ((camera_height - inner_radius) * (1.0 / outer_radius - inner_radius)) - (1.0 - tweak_amount);
min_dot = min(min_dot, min_dot2);
float pos_dot = dot(camera_to_position / far_distance, -camera_position.xyz / camera_height) - min_dot;
float height = pos_dot * (1.0 / (max_dot - min_dot));
ln = max(0.0, ln + stretch_amount);
lnn = max(0.0, lnn + stretch_amount);
float brightness = clamp(ln + (lnn * lc), 0.0, 1.0);
vec2 uv = vec2(brightness * clamp(lc + 1.0 + stretch_amount, 0.0, 1.0), height);
height -= min(0.0, min_dot2 + (ln * min_dot2));
float alpha = height * brightness;
vec3 negative_ray_dir = -ray_direction;
vec3 new_light_direction = normalize(light_position.xyz - world_position.xyz);
vec4 diffuse = texture(decal_map, uv);
vec4 diffuse2 = texture(decal_map, vec2(min(0.5, uv.x), 1.0));
float cosine = dot(normalize(new_light_direction.xyz), normalize(negative_ray_dir));
float cosine2 = cosine * cosine;
vec4 diffuse_color = diffuse * alpha;
float mie_phase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + cosine2) /(1.0 + g2 - 2.0 * g * cosine);
vec4 mie_color = diffuse2 * mie_phase * alpha;
vec4 color_out = vec4(1.0) - exp((diffuse_color * (1.0 + uv.y) + mie_color) * -exposure);
if (color_out.a < 0.0001) {
discard;
}
fragment0 = vec4(0.0, 0.0, 0.0, color_out.a);
fragment1 = vec4(0.0, 0.0, 0.0, color_out.a);
fragment2 = vec4(0.0, 0.0, 0.0, color_out.a);
fragment3 = vec4(color_out);
}