/
geosphere_sky.frag
92 lines (74 loc) · 3.03 KB
/
geosphere_sky.frag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright © 2008-2016 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#include "attributes.glsl"
#include "logz.glsl"
#include "lib.glsl"
#include "eclipse.glsl"
uniform vec4 atmosColor;
// to keep distances sane we do a nearer, smaller scam. this is how many times
// smaller the geosphere has been made
uniform float geosphereRadius;
uniform float geosphereAtmosTopRad;
uniform vec3 geosphereCenter;
uniform float geosphereAtmosFogDensity;
uniform float geosphereAtmosInvScaleHeight;
in vec4 varyingEyepos;
out vec4 frag_color;
void sphereEntryExitDist(out float near, out float far, const in vec3 sphereCenter, const in vec3 eyeTo, const in float radius)
{
vec3 v = -sphereCenter;
vec3 dir = normalize(eyeTo);
float b = -dot(v, dir);
float det = (b * b) - dot(v, v) + (radius * radius);
float i1, i2;
near = 0.0;
far = 0.0;
if (det > 0.0) {
det = sqrt(det);
i1 = b - det;
i2 = b + det;
if (i2 > 0.0) {
near = max(i1, 0.0);
far = i2;
}
}
}
void main(void)
{
float skyNear, skyFar;
vec3 eyenorm = normalize(varyingEyepos.xyz);
float specularHighlight=0.0;
sphereEntryExitDist(skyNear, skyFar, geosphereCenter, varyingEyepos.xyz, geosphereRadius * geosphereAtmosTopRad);
float atmosDist = (skyFar - skyNear);
float ldprod=0.0;
// a&b scaled so length of 1.0 means planet surface.
vec3 a = (skyNear * eyenorm - geosphereCenter) / geosphereRadius;
vec3 b = (skyFar * eyenorm - geosphereCenter) / geosphereRadius;
ldprod = AtmosLengthDensityProduct(a, b, atmosColor.a * geosphereAtmosFogDensity, atmosDist, geosphereAtmosInvScaleHeight);
float fogFactor = 1.0 / exp(ldprod);
vec4 atmosDiffuse = vec4(0.0);
#if (NUM_LIGHTS > 0)
vec3 surfaceNorm = normalize(skyNear * eyenorm - geosphereCenter);
for (int i=0; i<NUM_LIGHTS; ++i) {
vec3 lightDir = normalize(vec3(uLight[i].position));
float uneclipsed = clamp(calcUneclipsedSky(i, a, b, lightDir), 0.0, 1.0);
float nDotVP = max(0.0, dot(surfaceNorm, lightDir));
float nnDotVP = max(0.0, dot(surfaceNorm, -lightDir)); //need backlight to increase horizon
atmosDiffuse += uLight[i].diffuse * uneclipsed * 0.5*(nDotVP+0.5*clamp(1.0-nnDotVP*4.0,0.0,1.0) * INV_NUM_LIGHTS);
//Calculate Specular Highlight
vec3 L = normalize(uLight[i].position.xyz - varyingEyepos.xyz);
vec3 E = normalize(-varyingEyepos.xyz);
vec3 R = normalize(-reflect(L,vec3(0.0)));
specularHighlight += pow(max(dot(R,E),0.0),64.0) * uneclipsed * INV_NUM_LIGHTS;
}
#endif
//calculate sunset tone red when passing through more atmosphere, clamp everything.
float atmpower = (atmosDiffuse.r+atmosDiffuse.g+atmosDiffuse.b)/3.0;
vec4 sunset = vec4(0.8,clamp(pow(atmpower,0.8),0.0,1.0),clamp(pow(atmpower,1.2),0.0,1.0),1.0);
atmosDiffuse.a = 1.0;
frag_color = (1.0-fogFactor) * (atmosDiffuse*
vec4(atmosColor.rgb, 1.0)) +
(0.02-clamp(fogFactor,0.0,0.01))*atmosDiffuse*ldprod*sunset + //increase light on lower atmosphere.
atmosColor*specularHighlight*(1.0-fogFactor)*sunset; //add light from specularHighlight.
SetFragDepth();
}