mosaicmap/app/glsl/radar/verx.glsl
2025-08-13 21:54:20 +08:00

128 lines
4.9 KiB
GLSL

#version 300 es
layout(location = 0) in vec2 a_pos;
layout(location = 1) in vec2 a_tex_coord;
const float PI = 3.141592653589793;
uniform mat4 u_projection_matrix;
#define GLOBE_RADIUS 6371008.8
uniform highp vec4 u_projection_tile_mercator_coords;
uniform highp vec4 u_projection_clipping_plane;
uniform highp float u_projection_transition;
uniform mat4 u_projection_fallback_matrix;
vec3 globeRotateVector(vec3 vec,vec2 angles) {
vec3 axisRight=vec3(vec.z,0.0,-vec.x);
vec3 axisUp=cross(axisRight,vec);
axisRight=normalize(axisRight);
axisUp=normalize(axisUp);
vec2 t=tan(angles);
return normalize(vec+axisRight*t.x+axisUp*t.y);
}
mat3 globeGetRotationMatrix(vec3 spherePos) {
vec3 axisRight=vec3(spherePos.z,0.0,-spherePos.x);
vec3 axisDown=cross(axisRight,spherePos);
axisRight=normalize(axisRight);
axisDown=normalize(axisDown);
return mat3(axisRight,axisDown,spherePos);
}
float circumferenceRatioAtTileY(float tileY) {
float mercator_pos_y = u_projection_tile_mercator_coords.y + u_projection_tile_mercator_coords.w*tileY;
float spherical_y = 2.0*atan(exp(PI-(mercator_pos_y*PI*2.0))) - PI*0.5;return cos(spherical_y);
}
float projectLineThickness(float tileY) {
float thickness=1.0/circumferenceRatioAtTileY(tileY);
if (u_projection_transition < 0.999) {
return mix(1.0,thickness,u_projection_transition);
} else {
return thickness;
}
}
vec3 projectToSphere(vec2 translatedPos,vec2 rawPos) {
vec2 mercator_pos = u_projection_tile_mercator_coords.xy+u_projection_tile_mercator_coords.zw*translatedPos;
vec2 spherical;
spherical.x=mercator_pos.x*PI*2.0+PI;
spherical.y=2.0*atan(exp(PI-(mercator_pos.y*PI*2.0)))-PI*0.5;
float len=cos(spherical.y);
vec3 pos=vec3(sin(spherical.x)*len,sin(spherical.y),cos(spherical.x)*len);
if (rawPos.y <-32767.5) {
pos = vec3(0.0,1.0,0.0);
}
if (rawPos.y > 32766.5) {
pos=vec3(0.0,-1.0,0.0);
}
return pos;
}
vec3 projectToSphere(vec2 posInTile) {
return projectToSphere(posInTile,vec2(0.0,0.0));
}
vec2 computeLatLon(vec2 posInTile) {
vec2 mercator_pos = u_projection_tile_mercator_coords.xy + u_projection_tile_mercator_coords.zw * posInTile;
vec2 spherical;
spherical.x = mercator_pos.x * PI * 2.0 + PI; // 经度(弧度)
spherical.y = 2.0 * atan(exp(PI - (mercator_pos.y * PI * 2.0))) - PI * 0.5; // 纬度(弧度)
vec2 lonlat_degrees;
lonlat_degrees.x = spherical.x * 180.0 / PI; // 经度(角度)
lonlat_degrees.y = spherical.y * 180.0 / PI; // 纬度(角度)
// 确保经度在0-360范围内
lonlat_degrees.x = mod(lonlat_degrees.x + 360.0, 360.0);
return lonlat_degrees;
}
float globeComputeClippingZ(vec3 spherePos) {
return (1.0-(dot(spherePos,u_projection_clipping_plane.xyz)+u_projection_clipping_plane.w));
}
vec4 interpolateProjection(vec2 posInTile,vec3 spherePos,float elevation) {
vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);
vec4 globePosition=u_projection_matrix*vec4(elevatedPos,1.0);
globePosition.z=globeComputeClippingZ(elevatedPos)*globePosition.w;
if (u_projection_transition > 0.999) {return globePosition;}
vec4 flatPosition=u_projection_fallback_matrix*vec4(posInTile,elevation,1.0);
const float z_globeness_threshold=0.2;
vec4 result=globePosition;result.z=mix(0.0,globePosition.z,clamp((u_projection_transition-z_globeness_threshold)/(1.0-z_globeness_threshold),0.0,1.0));result.xyw=mix(flatPosition.xyw,globePosition.xyw,u_projection_transition);if ((posInTile.y <-32767.5) || (posInTile.y > 32766.5)) {result=globePosition;const float poles_hidden_anim_percentage=0.02;result.z=mix(globePosition.z,100.0,pow(max((1.0-u_projection_transition)/poles_hidden_anim_percentage,0.0),8.0));}return result;}vec4 interpolateProjectionFor3D(vec2 posInTile,vec3 spherePos,float elevation) {vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);vec4 globePosition=u_projection_matrix*vec4(elevatedPos,1.0);
if (u_projection_transition > 0.999) {return globePosition;}
vec4 fallbackPosition=u_projection_fallback_matrix*vec4(posInTile,elevation,1.0);
return mix(fallbackPosition,globePosition,u_projection_transition);
}
vec4 projectTile(vec2 posInTile) {
return interpolateProjection(posInTile,projectToSphere(posInTile),0.0);
}
vec4 projectTile(vec2 posInTile,vec2 rawPos) {
return interpolateProjection(posInTile,projectToSphere(posInTile,rawPos),0.0);
}
vec4 projectTileWithElevation(vec2 posInTile,float elevation) {
return interpolateProjection(posInTile,projectToSphere(posInTile),elevation);
}
vec4 projectTileFor3D(vec2 posInTile,float elevation) {
vec3 spherePos=projectToSphere(posInTile,posInTile);
return interpolateProjectionFor3D(posInTile,spherePos,elevation);
}
#define GLOBE
out vec2 lonlat;
void main() {
gl_Position = projectTile(a_pos);
lonlat = computeLatLon(a_pos);
}