8f3114e377
Signed-off-by: Michael Fabian Dirks <michael.dirks@project-kube.de>
259 lines
8.2 KiB
Plaintext
259 lines
8.2 KiB
Plaintext
#version 420
|
|
|
|
/* Animated Water using Flow Maps
|
|
* Shader By: Xaymar
|
|
*
|
|
* Usage:
|
|
* s2FlowMap - FlowMap for the Water, see below on the color components
|
|
* s2DiffuseMap - DiffuseMap (Used for <Foam>)
|
|
* s2NormalMap - NormalMap (Used for refracting the <Reflection> and <Objects in Water>)
|
|
* s2Reflect - Reflection Texture (RGB = Color)
|
|
* s2Refract - Refraction Texture (RGB = Color, A = Depth)
|
|
* v2Density - Thickness Settings: Density, MinimumDepth
|
|
* v3Color - Tinting of Refraction and color of Fog
|
|
* v3Animation - Animation Settings: Length, SpeedMul, OffsetMul
|
|
* v2ReflectDimensions - Size of 's2Reflect'
|
|
* v2RefractDimensions - Size of 's2Refract'
|
|
*
|
|
* Components of the Flow map:
|
|
* Red - X-Direction (Normalized with Y-Direction to create movement Vector)
|
|
* Green - Y-Direction (Normalized with X-Direction to create movement Vector)
|
|
* Blue - Speed (0.125 = Half, 0.25 = Normal, 0.5 = Double, 1.0 = Quadruple)
|
|
*
|
|
* NormalMap Color Components:
|
|
* RGB - Normal
|
|
* Alpha - Height
|
|
*/
|
|
|
|
/* Which Fading technique to use for each Texture.
|
|
* Defaults to RGB fading if none is defined.
|
|
*/
|
|
// YUV based fading
|
|
//#define FADE_DIFFUSEMAP_YUV
|
|
//#define FADE_NORMALMAP_YUV
|
|
|
|
// YIQ based fading
|
|
//#define FADE_DIFFUSEMAP_YIQ
|
|
//#define FADE_NORMALMAP_YIQ
|
|
|
|
// HSL based fading
|
|
//#define FADE_DIFFUSEMAP_HSL
|
|
//#define FADE_NORMALMAP_HSL
|
|
|
|
// HSV based fading
|
|
//#define FADE_DIFFUSEMAP_HSV
|
|
//#define FADE_NORMALMAP_HSV
|
|
|
|
/* Enable Debug Modes */
|
|
//#define DEBUG_FLOW
|
|
//#define DEBUG_TESTDIFFUSE
|
|
//#define DEBUG_DIFFUSE
|
|
//#define DEBUG_NORMAL
|
|
//#define DEBUG_REFRACT
|
|
//#define DEBUG_REFLECT
|
|
|
|
/* Constants */
|
|
const float LOG2 = 1.442695;
|
|
|
|
/* Water Variables */
|
|
uniform sampler2D s2DiffuseMap;
|
|
uniform sampler2D s2NormalMap;
|
|
uniform sampler2D s2FlowMap;
|
|
uniform vec2 v2Density;
|
|
uniform vec3 v3Color;
|
|
uniform vec3 v3Animation;
|
|
|
|
/* Reflection and Refraction */
|
|
uniform sampler2D s2Reflect;
|
|
uniform vec2 v2ReflectSize;
|
|
uniform sampler2D s2Refract;
|
|
uniform vec2 v2RefractSize;
|
|
|
|
/* Other Things */
|
|
uniform float fTime;
|
|
uniform float fNormalStrength;
|
|
|
|
/* Variables from Vertex Program */
|
|
in vec2 v2TextureCoord0;
|
|
in vec4 v4VertexPosition;
|
|
|
|
/* Function pre-definitions */
|
|
vec3 RGB2YUV(in vec3 RGB);
|
|
vec3 YUV2RGB(in vec3 YUV);
|
|
vec3 RGB2YIQ(in vec3 RGB);
|
|
vec3 YIQ2RGB(in vec3 YIQ);
|
|
vec3 RGB2HSL(in vec3 RGB);
|
|
vec3 HSL2RGB(in vec3 HSL);
|
|
vec3 RGB2HSV(in vec3 RGB);
|
|
vec3 HSV2RGB(in vec3 HSV);
|
|
|
|
// Main Loop
|
|
void main(void) {
|
|
// Read and convert the flowmap color into useable values.
|
|
vec4 v4FlowData = texture(s2FlowMap, v2TextureCoord0);
|
|
vec2 v2Offset = normalize(vec2(-1.0 + v4FlowData.r * 2.0, -1.0 + v4FlowData.g * 2.0));
|
|
float fSpeed = max(v3Animation.y * (v4FlowData.b * 4.0), 0.00001);
|
|
float fTimeOffset = dot(v2Offset, v2TextureCoord0) * v3Animation.z;
|
|
|
|
// Since the water can flow at different speeds, the same repeat time is not always appropriate.
|
|
float fAnimTime = max(v3Animation.x / fSpeed, 0.00001);
|
|
float fRealTime = mod(fTime + fTimeOffset, fAnimTime);
|
|
float fProgress = fRealTime / fAnimTime;
|
|
// Calculate the fade value from how far the time has progressed.
|
|
float fFade = sin(radians(fProgress * 90));
|
|
|
|
// Calculate the new Texture Coords using direction, speed and time.
|
|
vec2 v2Coord1 = v2TextureCoord0 + v2Offset * fSpeed * fRealTime;
|
|
vec2 v2Coord2 = v2Coord1 - v2Offset * fSpeed * fAnimTime;
|
|
|
|
// Normal: Gather Texels and combine them.
|
|
vec4 v4Normal;
|
|
vec4 v4Normal1 = texture(s2NormalMap, v2Coord1);
|
|
vec4 v4Normal2 = texture(s2NormalMap, v2Coord2);
|
|
|
|
// Normal: Fade between Normal1 and Normal2.
|
|
#ifdef FADE_NORMALMAP_YUV
|
|
v4Normal.rgb = YUV2RGB(mix(RGB2YUV(v4Normal1.rgb), RGB2YUV(v4Normal2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_NORMALMAP_YIQ
|
|
v4Normal.rgb = YIQ2RGB(mix(RGB2YIQ(v4Normal1.rgb), RGB2YIQ(v4Normal2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_NORMALMAP_HSL
|
|
v4Normal.rgb = HSL2RGB(mix(RGB2HSL(v4Normal1.rgb), RGB2HSL(v4Normal2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_NORMALMAP_HSV
|
|
v4Normal.rgb = HSV2RGB(mix(RGB2HSV(v4Normal1.rgb), RGB2HSV(v4Normal2.rgb), fFade));
|
|
#else //Default to RGB mixing
|
|
v4Normal.rgb = mix(v4Normal1.rgb, v4Normal2.rgb, fFade);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
v4Normal.a = mix(v4Normal1.a, v4Normal2.a, fFade);
|
|
|
|
// Normal: Adjust XYZ Vector.
|
|
v4Normal.xyz = (vec3(-1.0, -1.0, -1.0) + (2.0 * v4Normal.xyz)) * fNormalStrength;
|
|
v4Normal.xy *= gl_FragCoord.w;
|
|
|
|
// Refraction & Reflection: Use Screen Coordinates and Normal map to distort.
|
|
vec3 v3RefractColor = texture(s2Refract, (gl_FragCoord.xy / v2RefractSize) + v4Normal.xy).rgb;
|
|
vec3 v3ReflectColor = texture(s2Reflect, (gl_FragCoord.xy / v2ReflectSize) + v4Normal.xy).rgb;
|
|
|
|
// Refraction & Reflection: Visibility is based on Distance to camera and ground.
|
|
//@TODO: Visibility using distance to object behind it.
|
|
float fDepth = max(length(v4VertexPosition.xyz - gl_ModelViewMatrixInverse[3].xyz) - v2Density.y, 0.0);
|
|
float fTransparency = clamp(exp2(-v2Density.x * v2Density.x * fDepth * fDepth * LOG2), 0.0, 1.0);
|
|
vec3 v3Output = mix(v3ReflectColor, v3RefractColor * v3Color.rgb, fTransparency);
|
|
|
|
// Diffuse/Foam: Add foam to the top of the waves.
|
|
vec4 v4Diffuse;
|
|
vec4 v4Diffuse1 = texture(s2DiffuseMap, v2Coord1);
|
|
vec4 v4Diffuse2 = texture(s2DiffuseMap, v2Coord2);
|
|
|
|
// Diffuse/Foam: Fade between Diffuse1 and Diffuse2.
|
|
#ifdef FADE_DIFFUSEMAP_YUV
|
|
v4Diffuse.rgb = YUV2RGB(mix(RGB2YUV(v4Diffuse1.rgb), RGB2YUV(v4Diffuse2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_DIFFUSEMAP_YIQ
|
|
v4Diffuse.rgb = YIQ2RGB(mix(RGB2YIQ(v4Diffuse1.rgb), RGB2YIQ(v4Diffuse2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_DIFFUSEMAP_HSL
|
|
v4Diffuse.rgb = HSL2RGB(mix(RGB2HSL(v4Diffuse1.rgb), RGB2HSL(v4Diffuse2.rgb), fFade));
|
|
#else
|
|
#ifdef FADE_DIFFUSEMAP_HSV
|
|
v4Diffuse.rgb = HSV2RGB(mix(RGB2HSV(v4Diffuse1.rgb), RGB2HSV(v4Diffuse2.rgb), fFade));
|
|
#else //Default to RGB mixing
|
|
v4Diffuse.rgb = mix(v4Diffuse1.rgb, v4Diffuse2.rgb, fFade);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
v4Diffuse.a = mix(v4Diffuse1.a, v4Diffuse2.a, fFade);
|
|
|
|
// Output the result.
|
|
#ifdef DEBUG_FLOW
|
|
gl_FragColor.rgb = v4FlowData.rgb;
|
|
#else
|
|
#ifdef DEBUG_DIFFUSE
|
|
gl_FragColor.rgb = v4Diffuse.rgb;
|
|
#else
|
|
#ifdef DEBUG_NORMAL
|
|
gl_FragColor.rgb = v3Normal;
|
|
#else
|
|
#ifdef DEBUG_REFRACT
|
|
gl_FragColor.rgb = v3Refract;
|
|
#else
|
|
#ifdef DEBUG_REFLECT
|
|
gl_FragColor.rgb = v3Reflect;
|
|
#else
|
|
gl_FragColor.rgb = v3Output;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
/* --- --- RGB Conversion Functions --- ---*/
|
|
// RGB <-> YUV
|
|
const vec3 yuv_Y = vec3(0.299000, 0.587000, 0.114000);
|
|
const vec3 yuv_U = vec3(0.595716, -0.274453, -0.321263);
|
|
const vec3 yuv_V = vec3(0.211456, -0.522591, 0.311135);
|
|
const vec3 yuv_R = vec3(1.0, 0.9562, 0.6210);
|
|
const vec3 yuv_G = vec3(1.0, -0.2721, -0.6474);
|
|
const vec3 yuv_B = vec3(1.0, -1.1070, 1.7046);
|
|
|
|
vec3 RGB2YUV(in vec3 RGB) {
|
|
return RGB;
|
|
}
|
|
|
|
vec3 YUV2RGB(in vec3 YUV) {
|
|
return YUV;
|
|
}
|
|
|
|
// RGB <-> YIQ
|
|
const vec3 yiq_Y = vec3(0.299000, 0.587000, 0.114000);
|
|
const vec3 yiq_I = vec3(0.595716, -0.274453, -0.321263);
|
|
const vec3 yiq_Q = vec3(0.211456, -0.522591, 0.311135);
|
|
const vec3 yiq_R = vec3(1.0, 0.9562, 0.6210);
|
|
const vec3 yiq_G = vec3(1.0, -0.2721, -0.6474);
|
|
const vec3 yiq_B = vec3(1.0, -1.1070, 1.7046);
|
|
|
|
#define dRGB2YIQ(RGB) vec3(dot(RGB, yiq_Y), dot(RGB, yiq_I), dot(RGB, yiq_Q))
|
|
#define dYIQ2RGB(YIQ) vec3(dot(YIQ, yiq_R), dot(YIQ, yiq_G), dot(YIQ, yiq_B))
|
|
vec3 RGB2YIQ(in vec3 RGB) {
|
|
return vec3(dot(RGB, yiq_Y), dot(RGB, yiq_I), dot(RGB, yiq_Q));
|
|
}
|
|
|
|
vec3 YIQ2RGB(in vec3 YIQ) {
|
|
return vec3(dot(YIQ, yiq_R), dot(YIQ, yiq_G), dot(YIQ, yiq_B));
|
|
}
|
|
|
|
// RGB <-> HSL
|
|
vec3 RGB2HSL(in vec3 RGB) {
|
|
return RGB;
|
|
}
|
|
|
|
vec3 HSL2RGB(in vec3 HSL) {
|
|
return HSL;
|
|
}
|
|
|
|
// RGB <-> HSV
|
|
const vec4 hsv_From = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
const vec4 hsv_To = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
|
|
vec3 RGB2HSV(in vec3 RGB) {
|
|
vec4 p = mix(vec4(RGB.bg, hsv_From.wz), vec4(RGB.gb, hsv_From.xy), step(RGB.b, RGB.g));
|
|
vec4 q = mix(vec4(p.xyw, RGB.r), vec4(RGB.r, p.yzx), step(p.x, RGB.r));
|
|
|
|
float d = q.x - min(q.w, q.y);
|
|
float e = 1.0e-10;
|
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
|
}
|
|
|
|
vec3 HSV2RGB(in vec3 HSV) {
|
|
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
vec3 p = abs(fract(HSV.xxx + hsv_To.xyz) * 6.0 - hsv_To.www);
|
|
return HSV.z * mix(hsv_To.xxx, clamp(p - K.xxx, 0.0, 1.0), HSV.y);
|
|
}
|
|
/* --- --- End Of: RGB Conversion Functions --- --- */ |