Add Skydome effect.
Signed-off-by: Vivian Meazza <vivian.meazza@lineone.net>
This commit is contained in:
parent
3825563122
commit
c67632905a
4 changed files with 855 additions and 442 deletions
64
Effects/skydome.eff
Normal file
64
Effects/skydome.eff
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PropertyList>
|
||||||
|
<name>Effects/skydome</name>
|
||||||
|
<parameters>
|
||||||
|
<mie><use>/sim/rendering/mie</use></mie>
|
||||||
|
<rayleigh><use>/sim/rendering/rayleigh</use></rayleigh>
|
||||||
|
<density><use>/sim/rendering/dome-density</use></density>
|
||||||
|
</parameters>
|
||||||
|
<technique n="8">
|
||||||
|
<predicate>
|
||||||
|
<and>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
<property>/sim/rendering/scattering-shader</property>
|
||||||
|
<or>
|
||||||
|
<less-equal>
|
||||||
|
<value type="float">2.0</value>
|
||||||
|
<glversion/>
|
||||||
|
</less-equal>
|
||||||
|
<and>
|
||||||
|
<extension-supported>GL_ARB_shader_objects</extension-supported>
|
||||||
|
<extension-supported>GL_ARB_shading_language_100</extension-supported>
|
||||||
|
<extension-supported>GL_ARB_vertex_shader</extension-supported>
|
||||||
|
<extension-supported>GL_ARB_fragment_shader</extension-supported>
|
||||||
|
</and>
|
||||||
|
</or>
|
||||||
|
</and>
|
||||||
|
</predicate>
|
||||||
|
|
||||||
|
<pass>
|
||||||
|
<lighting>true</lighting>
|
||||||
|
<shade-model>smooth</shade-model>
|
||||||
|
<cull-face>back</cull-face>
|
||||||
|
<program>
|
||||||
|
<vertex-shader>Shaders/skydome.vert</vertex-shader>
|
||||||
|
<fragment-shader>Shaders/skydome.frag</fragment-shader>
|
||||||
|
</program>
|
||||||
|
<uniform>
|
||||||
|
<name>mK</name>
|
||||||
|
<type>float</type>
|
||||||
|
<value><use>mie</use></value>
|
||||||
|
</uniform>
|
||||||
|
<uniform>
|
||||||
|
<name>rK</name>
|
||||||
|
<type>float</type>
|
||||||
|
<value><use>rayleigh</use></value>
|
||||||
|
</uniform>
|
||||||
|
<uniform>
|
||||||
|
<name>density</name>
|
||||||
|
<type>float</type>
|
||||||
|
<value><use>density</use></value>
|
||||||
|
</uniform>
|
||||||
|
</pass>
|
||||||
|
</technique>
|
||||||
|
|
||||||
|
<!-- fall back without shaders -->
|
||||||
|
<technique n="11">
|
||||||
|
<pass>
|
||||||
|
<lighting>false</lighting>
|
||||||
|
<shade-model>smooth</shade-model>
|
||||||
|
<cull-face>back</cull-face>
|
||||||
|
</pass>
|
||||||
|
</technique>
|
||||||
|
|
||||||
|
</PropertyList>
|
40
Shaders/skydome.frag
Normal file
40
Shaders/skydome.frag
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
// Atmospheric scattering shader for flightgear
|
||||||
|
// Written by Lauri Peltonen (Zan)
|
||||||
|
// Implementation of O'Neil's algorithm
|
||||||
|
|
||||||
|
varying vec3 rayleigh;
|
||||||
|
varying vec3 mie;
|
||||||
|
varying vec3 eye;
|
||||||
|
|
||||||
|
float miePhase(in float cosTheta, in float g)
|
||||||
|
{
|
||||||
|
float g2 = g*g;
|
||||||
|
float a = 1.5 * (1.0 - g2);
|
||||||
|
float b = (2.0 + g2);
|
||||||
|
float c = 1.0 + cosTheta*cosTheta;
|
||||||
|
float d = pow(1.0 + g2 - 2.0 * g * cosTheta, 0.6667);
|
||||||
|
|
||||||
|
return (a*c) / (b*d);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rayleighPhase(in float cosTheta)
|
||||||
|
{
|
||||||
|
//return 1.5 * (1.0 + cosTheta*cosTheta);
|
||||||
|
return 1.5 * (2.0 + 0.5*cosTheta*cosTheta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float cosTheta = dot(normalize(eye), gl_LightSource[0].position.xyz);
|
||||||
|
|
||||||
|
vec3 color = rayleigh * rayleighPhase(cosTheta);
|
||||||
|
color += mie * miePhase(cosTheta, -0.8);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(color, 1.0);
|
||||||
|
gl_FragDepth = 0.1;
|
||||||
|
}
|
||||||
|
|
172
Shaders/skydome.vert
Normal file
172
Shaders/skydome.vert
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
// Atmospheric scattering shader for flightgear
|
||||||
|
// Written by Lauri Peltonen (Zan)
|
||||||
|
// Implementation of O'Neil's algorithm
|
||||||
|
|
||||||
|
|
||||||
|
uniform mat4 osg_ViewMatrix;
|
||||||
|
uniform mat4 osg_ViewMatrixInverse;
|
||||||
|
|
||||||
|
varying vec3 rayleigh;
|
||||||
|
varying vec3 mie;
|
||||||
|
varying vec3 eye;
|
||||||
|
|
||||||
|
// Dome parameters from FG and screen
|
||||||
|
const float domeSize = 80000.0;
|
||||||
|
const float realDomeSize = 100000.0;
|
||||||
|
const float groundRadius = 0.984503332 * domeSize;
|
||||||
|
const float altitudeScale = domeSize - groundRadius;
|
||||||
|
|
||||||
|
// Dome parameters when calculating scattering
|
||||||
|
// Assuming dome size is 5.0
|
||||||
|
const float groundLevel = 0.984503332 * 5.0;
|
||||||
|
const float heightScale = (5.0 - groundLevel);
|
||||||
|
|
||||||
|
// Integration parameters
|
||||||
|
const int nSamples = 7;
|
||||||
|
const float fSamples = float(nSamples);
|
||||||
|
|
||||||
|
// Scattering parameters
|
||||||
|
uniform float rK = 0.0003; //0.00015;
|
||||||
|
uniform float mK = 0.003; //0.0025;
|
||||||
|
uniform float density = 0.5; //1.0
|
||||||
|
vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
|
||||||
|
vec3 mieK = vec3(mK);
|
||||||
|
vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.0);
|
||||||
|
|
||||||
|
// Find intersections of ray to skydome
|
||||||
|
// ray must be normalized
|
||||||
|
// cheight is camera height
|
||||||
|
float intersection (in float cheight, in vec3 ray, in float rad2)
|
||||||
|
{
|
||||||
|
float B = 2.0 * cheight*ray.y;
|
||||||
|
float C = cheight*cheight - rad2; // 25.0 is skydome radius * radius
|
||||||
|
float fDet = max(0.0, B*B - 4.0 * C);
|
||||||
|
return 0.5 * (-B - sqrt(fDet));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the scale function at height = 0 for different thetas
|
||||||
|
float outscatterscale(in float costheta)
|
||||||
|
{
|
||||||
|
float x = 1.0 - costheta;
|
||||||
|
|
||||||
|
float a = 1.16941;
|
||||||
|
float b = 0.618989;
|
||||||
|
float c = 6.34484;
|
||||||
|
float d = -31.4138;
|
||||||
|
float e = 75.3249;
|
||||||
|
float f = -80.1643;
|
||||||
|
float g = 32.2878;
|
||||||
|
|
||||||
|
return exp(a+x*(b+x*(c+x*(d+x*(e+x*(f+x*g))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the amount of outscatter for different heights and thetas
|
||||||
|
// assuming view ray hits the skydome
|
||||||
|
// height is 0 at ground level and 1 at space
|
||||||
|
// Assuming average density of atmosphere is at 1/4 height
|
||||||
|
// and atmosphere height is 100 km
|
||||||
|
float outscatter(in float costheta, in float height)
|
||||||
|
{
|
||||||
|
return density * outscatterscale(costheta) * exp(-4.0 * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Make sure the dome is of a correct size
|
||||||
|
vec4 realVertex = gl_Vertex; //vec4(normalize(gl_Vertex.xyz) * domeSize, 1.0);
|
||||||
|
|
||||||
|
// Ground point (skydome center) in eye coordinates
|
||||||
|
vec4 groundPoint = gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Calculate altitude as the distance from skydome center to camera
|
||||||
|
// Make it so that 0.0 is ground level and 1.0 is 100km (space) level
|
||||||
|
float altitude = distance(groundPoint, vec4(0.0, 0.0, 0.0, 1.0));
|
||||||
|
float scaledAltitude = altitude / realDomeSize;
|
||||||
|
|
||||||
|
// Camera's position, z is up!
|
||||||
|
float cameraRealAltitude = groundLevel + heightScale*scaledAltitude;
|
||||||
|
vec3 camera = vec3(0.0, 0.0, cameraRealAltitude);
|
||||||
|
vec3 sample = 5.0 * realVertex.xyz / domeSize; // Sample is the dome vertex
|
||||||
|
vec3 relativePosition = camera - sample; // Relative position
|
||||||
|
|
||||||
|
// Find intersection of skydome and view ray
|
||||||
|
float space = intersection(cameraRealAltitude, -normalize(relativePosition), 25.0);
|
||||||
|
if(space > 0.0) {
|
||||||
|
// We are in space, calculate correct positiondelta!
|
||||||
|
relativePosition -= space * normalize(relativePosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 positionDelta = relativePosition / fSamples;
|
||||||
|
float deltaLength = length(positionDelta); // Should multiply by something?
|
||||||
|
|
||||||
|
vec3 lightDirection = gl_LightSource[0].position.xyz;
|
||||||
|
|
||||||
|
// Cos theta of camera's position and sample point
|
||||||
|
// Since camera is 0,0,z, dot porduct is just the z coordinate
|
||||||
|
float cameraCosTheta;
|
||||||
|
|
||||||
|
// If sample is above camera, reverse ray direction
|
||||||
|
if(positionDelta.z < 0.0) cameraCosTheta = -positionDelta.z / deltaLength;
|
||||||
|
else cameraCosTheta = positionDelta.z / deltaLength;
|
||||||
|
|
||||||
|
// Total attenuation from camera to skydome
|
||||||
|
float totalCameraScatter = outscatter(cameraCosTheta, scaledAltitude);
|
||||||
|
|
||||||
|
|
||||||
|
// Do numerical integration of scsattering function from skydome to camera
|
||||||
|
vec3 color = vec3(0.0);
|
||||||
|
for(int i = 0; i < nSamples; i++)
|
||||||
|
{
|
||||||
|
// Altitude of the sample point 0...1
|
||||||
|
float sampleAltitude = (length(sample) - groundLevel) / heightScale;
|
||||||
|
|
||||||
|
// Cosine between the angle of sample's up vector and sun
|
||||||
|
// Since lightDirection is in eye space, we must transform sample too
|
||||||
|
vec3 sampleUp = gl_NormalMatrix * normalize(sample);
|
||||||
|
float cosTheta = dot(sampleUp, lightDirection);
|
||||||
|
|
||||||
|
// Scattering from sky to sample point
|
||||||
|
float skyScatter = outscatter(cosTheta, sampleAltitude);
|
||||||
|
|
||||||
|
// Calculate the attenuation from this point to camera
|
||||||
|
// Again, reverse the direction if vertex is over the camera
|
||||||
|
float cameraScatter;
|
||||||
|
if(relativePosition.z < 0.0) { // Vertex is over the camera
|
||||||
|
cameraCosTheta = -dot(normalize(positionDelta), normalize(sample));
|
||||||
|
cameraScatter = totalCameraScatter - outscatter(cameraCosTheta, sampleAltitude);
|
||||||
|
} else { // Vertex is below camera
|
||||||
|
cameraCosTheta = dot(normalize(positionDelta), normalize(sample));
|
||||||
|
cameraScatter = outscatter(cameraCosTheta, sampleAltitude) - totalCameraScatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total attenuation
|
||||||
|
vec3 totalAttenuate = 4.0 * 3.14159 * (rayleighK + mieK) * (-skyScatter - cameraScatter);
|
||||||
|
|
||||||
|
vec3 inScatter = exp(totalAttenuate - sampleAltitude*4.0);
|
||||||
|
|
||||||
|
color += inScatter * deltaLength;
|
||||||
|
sample += positionDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
color *= sunIntensity;
|
||||||
|
|
||||||
|
rayleigh = rayleighK * color;
|
||||||
|
mie = mieK * color;
|
||||||
|
eye = gl_NormalMatrix * positionDelta;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// We need to move the camera so that the dome appears to be centered around earth
|
||||||
|
// to make the dome render correctly!
|
||||||
|
float moveDown = -altitude; // Center dome on camera
|
||||||
|
moveDown += groundRadius;
|
||||||
|
moveDown += scaledAltitude * altitudeScale; // And move correctly according to altitude
|
||||||
|
|
||||||
|
// Vertex transformed correctly so that at 100km we are at space border
|
||||||
|
vec4 finalVertex = realVertex - vec4(0.0, 0.0, 1.0, 0.0) * moveDown;
|
||||||
|
// Transform
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * finalVertex;
|
||||||
|
}
|
|
@ -8,13 +8,17 @@
|
||||||
|
|
||||||
<group>
|
<group>
|
||||||
<layout>hbox</layout>
|
<layout>hbox</layout>
|
||||||
<empty><stretch>1</stretch></empty>
|
<empty>
|
||||||
|
<stretch>1</stretch>
|
||||||
|
</empty>
|
||||||
|
|
||||||
<text>
|
<text>
|
||||||
<label>Rendering options</label>
|
<label>Rendering options</label>
|
||||||
</text>
|
</text>
|
||||||
|
|
||||||
<empty><stretch>1</stretch></empty>
|
<empty>
|
||||||
|
<stretch>1</stretch>
|
||||||
|
</empty>
|
||||||
|
|
||||||
<button>
|
<button>
|
||||||
<pref-width>16</pref-width>
|
<pref-width>16</pref-width>
|
||||||
|
@ -544,6 +548,139 @@
|
||||||
</text>
|
</text>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<text>
|
||||||
|
<label>Experimental effects</label>
|
||||||
|
<halign>left</halign>
|
||||||
|
</text>
|
||||||
|
<hrule>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</hrule>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>vbox</layout>
|
||||||
|
<padding>10</padding>
|
||||||
|
<checkbox>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>Skydome scattering</label>
|
||||||
|
<name>skydome-scattering</name>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<property>/sim/rendering/scattering-shader</property>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
<object-name>skydome-scattering</object-name>
|
||||||
|
</binding>
|
||||||
|
</checkbox>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<halign>right</halign>
|
||||||
|
<text>
|
||||||
|
<label>Mie factor</label>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<name>mie-factor</name>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<min>0.0</min>
|
||||||
|
<max>0.01</max>
|
||||||
|
<step>0.001</step>
|
||||||
|
<property>/sim/rendering/mie</property>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
<object-name>mie-factor</object-name>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<label>12345678</label>
|
||||||
|
<format>%.3f</format>
|
||||||
|
<live>true</live>
|
||||||
|
<property>/sim/rendering/mie</property>
|
||||||
|
</text>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<halign>right</halign>
|
||||||
|
<text>
|
||||||
|
<label>Rayleigh factor</label>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<name>rayleigh-factor</name>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<min>0.0</min>
|
||||||
|
<max>0.001</max>
|
||||||
|
<step>0.0001</step>
|
||||||
|
<property>/sim/rendering/rayleigh</property>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
<object-name>rayleigh-factor</object-name>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<label>12345678</label>
|
||||||
|
<format>%.4f</format>
|
||||||
|
<live>true</live>
|
||||||
|
<property>/sim/rendering/rayleigh</property>
|
||||||
|
</text>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<halign>right</halign>
|
||||||
|
<text>
|
||||||
|
<label>Density factor</label>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<name>density-factor</name>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<min>0.0</min>
|
||||||
|
<max>1.0</max>
|
||||||
|
<step>0.1</step>
|
||||||
|
<property>/sim/rendering/dome-density</property>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
<object-name>density-factor</object-name>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<enable>
|
||||||
|
<property>/sim/rendering/shader-effects</property>
|
||||||
|
</enable>
|
||||||
|
<label>12345678</label>
|
||||||
|
<format>%.1f</format>
|
||||||
|
<live>true</live>
|
||||||
|
<property>/sim/rendering/dome-density</property>
|
||||||
|
</text>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue