blob: 8a5677fa12c8823dcf6eca5bd9197f2293448def [file] [log] [blame]
#version 310 es
#define YFLIP 0
#define SPECULAR 0
#define GLOSSMAP 0
#define DEBUG_NONE 0
#define DEBUG_DIFFUSE 1
#define DEBUG_SPECULAR 2
#define DEBUG_LIGHTING 3
#define DEBUG_FOG 4
#define DEBUG DEBUG_NONE
#define FORWARD 0
#define DEFERRED 1
#define DEFERRED_VTEX 2
float saturate(float x) { return clamp(x, 0.0, 1.0); }
layout(std140, binding = 0) uniform GlobalVSData
{
vec4 g_ViewProj_Row0;
vec4 g_ViewProj_Row1;
vec4 g_ViewProj_Row2;
vec4 g_ViewProj_Row3;
vec4 g_CamPos;
vec4 g_CamRight;
vec4 g_CamUp;
vec4 g_CamFront;
vec4 g_SunDir;
vec4 g_SunColor;
vec4 g_TimeParams;
vec4 g_ResolutionParams;
vec4 g_CamAxisRight;
vec4 g_FogColor_Distance;
vec4 g_ShadowVP_Row0;
vec4 g_ShadowVP_Row1;
vec4 g_ShadowVP_Row2;
vec4 g_ShadowVP_Row3;
};
vec4 ComputeFogFactor(vec3 WorldPos)
{
vec4 FogData;
vec3 vEye = WorldPos - g_CamPos.xyz;
vec3 nEye = normalize(vEye);
FogData.w = exp(-dot(vEye, vEye) * g_FogColor_Distance.w * 0.75);
float fog_sun_factor = pow(saturate(dot(nEye, g_SunDir.xyz)), 8.0);
FogData.xyz = mix(vec3(1.0, 1.0, 1.0), vec3(0.6, 0.6, 0.9), nEye.y * 0.5 + 0.5);
FogData.xyz = mix(FogData.xyz, vec3(0.95, 0.87, 0.78), fog_sun_factor);
return FogData;
}
void ApplyFog(inout vec3 Color, vec4 FogData)
{
Color = mix(FogData.xyz, Color, FogData.w);
}
void ApplyLighting(inout mediump vec3 Color, mediump float DiffuseFactor)
{
mediump vec3 DiffuseLight = g_SunColor.xyz * DiffuseFactor;
mediump vec3 AmbientLight = vec3(0.2, 0.35, 0.55) * 0.5;
mediump vec3 Lighting = DiffuseLight + AmbientLight;
#if DEBUG == DEBUG_LIGHTING
Color = Lighting;
#else
Color *= Lighting;
#endif
}
void ApplySpecular(inout mediump vec3 Color, mediump vec3 EyeVec, mediump vec3 Normal, mediump vec3 SpecularColor, mediump float Shininess, mediump float FresnelAmount)
{
mediump vec3 HalfAngle = normalize(-EyeVec + g_SunDir.xyz);
mediump float v_dot_h = saturate(dot(HalfAngle, -EyeVec));
mediump float n_dot_l = saturate(dot(Normal, g_SunDir.xyz));
mediump float n_dot_h = saturate(dot(Normal, HalfAngle));
mediump float n_dot_v = saturate(dot(-EyeVec, Normal));
mediump float h_dot_l = saturate(dot(g_SunDir.xyz, HalfAngle));
const mediump float roughness_value = 0.25;
mediump float r_sq = roughness_value * roughness_value;
mediump float n_dot_h_sq = n_dot_h * n_dot_h;
mediump float roughness_a = 1.0 / (4.0 * r_sq * n_dot_h_sq * n_dot_h_sq);
mediump float roughness_b = n_dot_h_sq - 1.0;
mediump float roughness_c = r_sq * n_dot_h_sq;
mediump float roughness = saturate(roughness_a * exp(roughness_b / roughness_c));
FresnelAmount = 0.5;
mediump float fresnel_term = pow(1.0 - n_dot_v, 5.0) * (1.0 - FresnelAmount) + FresnelAmount;
mediump float geo_numerator = 2.0 * n_dot_h;
mediump float geo_denominator = 1.0 / v_dot_h;
mediump float geo_term = min(1.0, min(n_dot_v, n_dot_l) * geo_numerator * geo_denominator);
#if SPECULAR || GLOSSMAP
Color += SpecularColor * g_SunColor.xyz * fresnel_term * roughness * n_dot_l * geo_term / (n_dot_v * n_dot_l + 0.0001);
#endif
//Color = vec3(0.025 * 1.0 / (n_dot_v * n_dot_l));
}
precision highp int;
layout(binding = 0) uniform mediump sampler2D TexDisplacement;
layout(binding = 1) uniform mediump sampler2D TexLOD;
layout(location = 0) in vec4 Position;
layout(location = 1) in vec4 LODWeights;
layout(location = 0) out highp vec3 EyeVec;
layout(location = 1) out highp vec4 TexCoord;
layout(std140, binding = 4) uniform GlobalOcean
{
vec4 OceanScale;
vec4 OceanPosition;
vec4 InvOceanSize_PatchScale;
vec4 NormalTexCoordScale;
};
struct PatchData
{
vec4 Position;
vec4 LODs;
};
layout(std140, binding = 0) uniform Offsets
{
PatchData Patches[256];
};
vec2 lod_factor(vec2 uv)
{
float level = textureLod(TexLOD, uv, 0.0).x * (255.0 / 32.0);
float floor_level = floor(level);
float fract_level = level - floor_level;
return vec2(floor_level, fract_level);
}
#ifdef VULKAN
#define INSTANCE_ID gl_InstanceIndex
#else
#define INSTANCE_ID gl_InstanceID
#endif
vec2 warp_position()
{
float vlod = dot(LODWeights, Patches[INSTANCE_ID].LODs);
vlod = mix(vlod, Patches[INSTANCE_ID].Position.w, all(equal(LODWeights, vec4(0.0))));
float floor_lod = floor(vlod);
float fract_lod = vlod - floor_lod;
uint ufloor_lod = uint(floor_lod);
uvec4 uPosition = uvec4(Position);
uvec2 mask = (uvec2(1u) << uvec2(ufloor_lod, ufloor_lod + 1u)) - 1u;
uvec4 rounding;
rounding.x = uPosition.x < 32u ? mask.x : 0u;
rounding.y = uPosition.y < 32u ? mask.x : 0u;
rounding.z = uPosition.x < 32u ? mask.y : 0u;
rounding.w = uPosition.y < 32u ? mask.y : 0u;
//rounding = uPosition.xyxy * mask.xxyy;
vec4 lower_upper_snapped = vec4((uPosition.xyxy + rounding) & (~mask).xxyy);
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, fract_lod);
}
void main()
{
vec2 PatchPos = Patches[INSTANCE_ID].Position.xz * InvOceanSize_PatchScale.zw;
vec2 WarpedPos = warp_position();
vec2 VertexPos = PatchPos + WarpedPos;
vec2 NormalizedPos = VertexPos * InvOceanSize_PatchScale.xy;
vec2 NormalizedTex = NormalizedPos * NormalTexCoordScale.zw;
vec2 lod = lod_factor(NormalizedPos);
vec2 Offset = exp2(lod.x) * InvOceanSize_PatchScale.xy * NormalTexCoordScale.zw;
vec3 Displacement =
mix(textureLod(TexDisplacement, NormalizedTex + 0.5 * Offset, lod.x).yxz,
textureLod(TexDisplacement, NormalizedTex + 1.0 * Offset, lod.x + 1.0).yxz,
lod.y);
vec3 WorldPos = vec3(NormalizedPos.x, 0.0, NormalizedPos.y) + Displacement;
WorldPos *= OceanScale.xyz;
WorldPos += OceanPosition.xyz;
EyeVec = WorldPos - g_CamPos.xyz;
TexCoord = vec4(NormalizedTex, NormalizedTex * NormalTexCoordScale.xy) + 0.5 * InvOceanSize_PatchScale.xyxy * NormalTexCoordScale.zwzw;
gl_Position = WorldPos.x * g_ViewProj_Row0 + WorldPos.y * g_ViewProj_Row1 + WorldPos.z * g_ViewProj_Row2 + g_ViewProj_Row3;
#if YFLIP
gl_Position *= vec4(1.0, -1.0, 1.0, 1.0);
#endif
}