1
0
Fork 0
fgdata/Shaders/HDR/3dcloud.vert

117 lines
4.5 KiB
GLSL
Raw Normal View History

#version 330 core
layout(location = 0) in vec4 pos;
layout(location = 2) in vec4 vertexColor;
layout(location = 3) in vec4 multiTexCoord0;
layout(location = 10) in vec4 usrAttr1;
layout(location = 11) in vec4 usrAttr2;
out vec2 texCoord;
out vec4 cloudColor;
uniform float range;
uniform float detail_range;
uniform mat4 osg_ModelViewMatrix;
uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 osg_ViewMatrixInverse;
uniform vec3 fg_SunDirectionWorld;
// aerial-perspective-include.frag
vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth);
vec3 get_sun_radiance(vec3 p);
void main()
{
float alpha_factor = usrAttr1.r;
float shade_factor = usrAttr1.g;
float cloud_height = usrAttr1.b;
float bottom_factor = usrAttr2.r;
float middle_factor = usrAttr2.g;
float top_factor = usrAttr2.b;
texCoord = multiTexCoord0.st;
// XXX: Should be sent as an uniform
mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix);
vec4 ep = inverseModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
vec4 l = inverseModelViewMatrix * vec4(0.0, 0.0, 1.0, 1.0);
vec3 u = normalize(ep.xyz - l.xyz);
// Find a rotation matrix that rotates 1,0,0 into u. u, r and w are
// the columns of that matrix.
vec3 absu = abs(u);
vec3 r = normalize(vec3(-u.y, u.x, 0.0));
vec3 w = cross(u, r);
// Do the matrix multiplication by [ u r w pos]. Assume no
// scaling in the homogeneous component of pos.
vec4 final_pos = vec4(0.0, 0.0, 0.0, 1.0);
final_pos.xyz = pos.x * u;
final_pos.xyz += pos.y * r;
final_pos.xyz += pos.z * w;
// Apply Z scaling to allow sprites to be squashed in the z-axis
final_pos.z = final_pos.z * vertexColor.w;
// Now shift the sprite to the correct position in the cloud.
final_pos.xyz += vertexColor.xyz;
// Determine the position - used for fog and shading calculations
float fogCoord = length(vec3(osg_ModelViewMatrix * vec4(vertexColor.xyz, 1.0)));
float center_dist = length(vec3(osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)));
if ((fogCoord > detail_range) && (fogCoord > center_dist) && (shade_factor < 0.7)) {
// More than detail_range away, so discard all sprites on opposite side of
// cloud center by shifting them beyond the view fustrum
gl_Position = vec4(0.0, 0.0, 10.0, 1.0);
cloudColor = vec4(0.0);
} else {
gl_Position = osg_ModelViewProjectionMatrix * final_pos;
vec4 final_view_pos = osg_ModelViewMatrix * final_pos;
vec4 final_world_pos = osg_ViewMatrixInverse * final_view_pos;
// Determine a lighting normal based on the vertex position from the
// center of the cloud, so that sprite on the opposite side of the cloud
// to the sun are darker.
vec3 n = normalize(vec3(osg_ViewMatrixInverse *
osg_ModelViewMatrix * vec4(-final_pos.xyz, 0.0)));
float NdotL = dot(-fg_SunDirectionWorld, n);
// Determine the shading of the vertex. We shade it based on it's position
// in the cloud relative to the sun, and it's vertical position in the cloud.
float shade = mix(shade_factor, top_factor, smoothstep(-0.3, 0.3, NdotL));
if (final_pos.z < 0.5 * cloud_height) {
shade = min(shade, mix(bottom_factor, middle_factor,
final_pos.z * 2.0 / cloud_height));
} else {
shade = min(shade, mix(middle_factor, top_factor,
final_pos.z * 2.0 / cloud_height - 1.0));
}
cloudColor.rgb = shade * get_sun_radiance(final_world_pos.xyz);
// Perspective division and scale to [0, 1] to get the screen position
// of the vertex.
vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5;
cloudColor.rgb = add_aerial_perspective(
cloudColor.rgb, coord, length(final_view_pos));
if ((fogCoord > (0.9 * detail_range))
&& (fogCoord > center_dist)
&& (shade_factor < 0.7)) {
// cloudlet is almost at the detail range, so fade it out.
cloudColor.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord);
} else {
// As we get within 100m of the sprite, it is faded out.
// Equally at large distances it also fades out.
cloudColor.a = min(smoothstep(10.0, 100.0, fogCoord),
1.0 - smoothstep(0.9 * range, range, fogCoord));
}
cloudColor.a *= alpha_factor;
}
}