ПРИЛОЖЕНИЕ А. Источники геоданных Существуют различные данные ДДЗ в свободном доступе в интернете, которые можно использовать для создания собственного глобуса.
Изображения Земли
Blue Marble Next Generation — самая известная коллекция изображений с разрешением 500м/пк. Создана NASA путем обработки снимков со спутника MODIS, сделанных в 2004 году. Имеются изображения для всех 12ти месяцев. Изображения 3х типов: плоские, с данными топографии, с данными топографии и батиметрии.
MODIS — спутниковые снимки с аппаратов MODIS, которые были запущены на спутниках Терра (1999) и Аква (2002). Максимальное разрешение 250м/пк. Обновляются раз в день для всей Земли в нескольких спектральных диапазонах.
Landsat — спутниковые снимки, сделанные спутником Landsat-7, который был запущен в 1999 году. Максимальное разрешение 15м/пк. Сделаны в нескольких спектральных диапазонах.
Высотные данные
GTOPO30 — глобальный набор высотных данных с разрешением 30 угловых секунд (~1км/пк). Создан в 1996 году Геологической службой США (USGS). Данные собраны из различных источников растровой и векторной топографической информации.
NASA Shuttle Radar Topography Mission (SRTM) — международный проект по получению высотных данных высокого разрешения между 56 S и 60 N. В феврале 2000 года была проведена радарная съемка земной поверхности с шаттла Эндевор в ходе 11ти-дневной миссии. Разрешение исходных данных — 1 угловая секунда (~30 метров/пк). Но данные такого разрешения были получены только для территории США. Для остальной части мира разрешение — 3 угловые секунды (~90 метров/пк). Вертикальная ошибка — примерно 16 метров. Исходные данные проекта SRTM содержат дыры, т.е. области без высотных данных. Эти дыры присутствуют в горных и пустынных районах. Для заполнения дыр применяются различные алгоритмы интерполяции.
ASTER Global Digital Elevation Model (ASTER GDEM) — самая полная на данный момент цифровая модель рельефа между 83 S и 83 N с разрешением 30м/пк. Выпущена в 2009 году. Получена на основе обработки стерео-пар спутниковых снимков с аппарата ASTER. Вертикальная ошибка составляет 20 метров.
Батиметрия
ETOPO1 — цифровая модель рельефа всей Земли, включая рельеф морского дна с разрешением 1 угловая минута (~1.8км/пк). Выпущена Национальным управлением океанических и атмосферных исследований США (NOAA).
SRTM30_PLUS — цифровая модель рельефа всей Земли, включая рельеф морского дна с разрешением 30 угловых секунд (~1км/пк).
Прочие данные
NASA регулярно публикует научные растровые данные для всей Земли [73, 140]. Сюда входят: температура суши и моря, толщина аэрозольного слоя, концентрация углекислого газа, плотность растительного покрова, альбедо поверхности.
Другие организации также выкладывают геопривязанные данные. Геологическая служба США (USGS) в реальном времени публикует землетрясения, происходящие в мире [100]. Также доступны архивные данные по землетрясениям. Проект OpenWeatherMap публикует текущие погодные данные в векторном и растровом форматах [141]. На сайте проекта DIVA-GIS опубликованы свободные векторные данные низкого разрешения для всех стран мира [142].
OpenStreetMap — картографический сервис, построенный про принципу вики [143]. Этот сервис позволят создавать и редактировать векторную карту Земли. Любой пользователь может нарисовать дороги, задать им свойства, отметить здания, парки, леса, реки, объекты инфраструктуры. Теоретически, возможны акты вандализма, когда вносятся заведомо недостоверные данные. Но за счет очень большого количества участников, которые отслеживают корректность данных, можно почти не сомневаться в точности. Данные сервиса свободно доступны в растровом и векторном форматах.
ПРИЛОЖЕНИЕ Б. Шейдеры для объемной визуализации 1-й проход
Вершинный шейдер:
varying vec3 position; void main(void)
{
position = gl_Vertex.xyz;
gl_Position = ftransform();
} Фрагментный шейдер:
varying vec3 position; void main(void)
{
gl_FragColor = vec4(position, 1.0);
} 2-й проход
Вершинный шейдер:
varying vec3 position;
varying vec3 lightDirection;
varying vec4 baseColor;
varying vec4 texBackCoord; //coord in offscreen texture void main(void)
{
position = gl_Vertex.xyz; gl_Position = ftransform(); texBackCoord = gl_ModelViewProjectionMatrix * gl_Vertex;
texBackCoord /= texBackCoord.w;
texBackCoord += vec4(1.0, 1.0, 1.0, 0.0);
texBackCoord *= vec4(0.5, 0.5, 0.5, 1.0);
baseColor = vec4(1.0, 1.0, 1.0, 1.0);
vec4 lightPosition = gl_ModelViewMatrixInverse * gl_LightSource[0].position;
if (lightPosition[3]==0.0)
{
// directional light source
lightDirection = -normalize(lightPosition.xyz);
}
else
{
// positional light source
lightDirection = normalize((lightPosition-gl_Vertex).xyz);
}
} Фрагментный шейдер:
uniform sampler3D baseTexture; uniform sampler1D tfTexture;
uniform float tfScale;
uniform float tfOffset; uniform sampler2D backTexture; uniform float SampleDensityValue;
uniform float TransparencyValue;
uniform float AlphaFuncValue; varying vec3 position;
varying vec4 baseColor;
varying vec4 texBackCoord; //coord in offscreen texture const float _radiusEquator = 6378137.0;
const float _radiusPolar = 6356752.3142;
const float flattening = (_radiusEquator-_radiusPolar)/_radiusEquator;
const float _eccentricitySquared = 2.0*flattening - flattening*flattening; const float lon1 = 2.094395102393;
const float lon2 = 3.141592653589;
const float lat1 = 0.174532925199;
const float lat2 = 1.221730476396;
const float z1 = -25000.0;
const float z2 = -600000.0; vec3 getTexCoord(vec3 pos)
{
float p = sqrt(pos.x*pos.x + pos.y*pos.y);
float theta = atan(pos.z*_radiusEquator, (p*_radiusPolar));
float eDashSquared = (_radiusEquator*_radiusEquator - _radiusPolar*_radiusPolar) / (_radiusPolar*_radiusPolar); float sin_theta = sin(theta);
float cos_theta = cos(theta); float latitude = atan((pos.z + eDashSquared*_radiusPolar*sin_theta*sin_theta*sin_theta) / (p - _eccentricitySquared*_radiusEquator*cos_theta*cos_theta*cos_theta));
float longitude = atan(pos.y,pos.x); float sin_latitude = sin(latitude);
float N = _radiusEquator / sqrt( 1.0 - _eccentricitySquared*sin_latitude*sin_latitude); float height = p/cos(latitude) - N; float s = (longitude - lon1) / (lon2 - lon1);
float t = (latitude - lat1) / (lat2 - lat1);
float z = (height - z2) / (z1 - z2); return vec3(s, t, z);
} void main(void)
{
vec3 pos0 = texture2D(backTexture, texBackCoord.st).xyz;
vec3 pos1 = position; const float max_iteratrions = 2048.0;
float num_iterations = ceil(1.0/SampleDensityValue);
if (num_iterations<2.0) num_iterations = 2.0; if (num_iterations>max_iteratrions)
{
num_iterations = max_iteratrions;
} vec3 deltaPosCoord=(pos1-pos0).xyz/float(num_iterations-1.0);
vec3 curpos = pos0; vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);
while(num_iterations>0.0)
{
vec3 texcoord = getTexCoord(curpos); float v = texture3D(baseTexture, texcoord).a * tfScale + tfOffset;
vec4 color = texture1D(tfTexture, v); float r = color[3]*TransparencyValue;
if (r>AlphaFuncValue)
{
fragColor.xyz = fragColor.xyz*(1.0-r)+color.xyz*r;
fragColor.w += r;
} if (fragColor.w {
fragColor = color;
}
curpos += deltaPosCoord; --num_iterations;
} fragColor.w *= TransparencyValue;
if (fragColor.w>1.0) fragColor.w = 1.0; fragColor *= baseColor; if (fragColor.wif (length(pos0.xyz) < 0.01)
{
discard;
} if (length(fragColor.rgb) < 0.01)
{
discard;
} gl_FragColor = fragColor;
}
При разработке шейдеров использовались формулы и фрагменты кода из работ [117, 110].
|