Наземні зміни ландшафтів. Тонкощі вертикального планування ділянки

AlexWIN32 20 серпня 2017 о 13:36

Планетарний ландшафт

  • API ,
  • C++,
  • Розробка ігор
  • Tutorial

Важко посперечатися, що ландшафт є невід'ємною частиною більшості комп'ютерних ігор на відкритих просторах. Традиційний метод реалізації зміни рельєфу навколишнього гравця поверхні наступний - беремо сітку (Mesh), що представляє собою площину і для кожного примітиву в цій сітці зміщуємо по нормалі до цієї площини на значення, конкретне для даного примітиву. Говорячи простими словами, у нас є одноканальна текстура розміром 256 на 256 пікселів та сітка площини. Для кожного примітиву за його координатами на площині беремо значення текстури. Тепер просто зміщуємо за нормаллю до площини координати примітиву на отримане значення (рис.1)

Рис.1 карта висот + площина = ландшафт

1. Сектор

Очевидно, що не розумно будувати ландшафт одразу для всієї сфери – більшу її частину не буде видно. Тому нам потрібно створити якусь мінімальну область простору - примітив, з яких складатиметься рельєф видимої частини сфери. Я назву його сектор. Як нам його отримати? Отже, подивіться на рис. Зелений осередок – це наш сектор. Далі збудуємо шість сіток, кожна з яких є гранню куба (рис.2b). Тепер нормалізуємо координати примітивів, які формують сітки (рис.2с).


Рис.2

У результаті ми отримали спроектований на сферу куб, де сектором є область на одній із його граней. Чому це працює? Розглянемо довільну точку на сітці вектор від початку координат. Що таке нормалізація вектора? Це перетворення заданого вектора на вектор у тому напрямі, але з одиничною довжиною. Процес наступний: спочатку знайдемо довжину вектора в евклідовій метриці згідно з теоремою Піфагора

Потім поділимо кожен із компонентів вектора на це значення

Тепер спитаємо себе, що таке сфера? Сфера - це безліч точок, що рівно віддалені від заданої точки. Параметричне рівняння сфери виглядає так

Де x0, y0, z0 – координати центру сфери, а R – її радіус. У нашому випадку центр сфери – це початок координат, а радіус дорівнює одиниці. Підставляємо відомі значення та беремо корінь від двох частин рівняння. Виходить наступне

Буквально останнє перетворення говорить нам таке: «Для того, щоб належати сфері, довжина вектора має дорівнювати одиниці». Цього ми й добилися нормалізацією.

А якщо сфера має довільний центр і радіус? Знайти точку, яка їй належить, можна за допомогою наступного рівняння

Де pS – точка на сфері, C – центр сфери, pNorm – раніше нормалізований вектор і R – радіус сфери. Говорячи простими словами, тут відбувається таке – «ми переміщаємося від центру сфери у напрямку до точки на сітці на відстань R». Оскільки кожен вектор має одиничну довжину, то результаті всі точки рівновіддалені від центру сфери на відстань її радіуса, що робить істинним рівняння сфери.

2. Управління

Нам потрібно отримати групу секторів, які потенційно помітні з точки зору. Але як це зробити? Припустимо, що у нас є сфера з центром у певній точці. Також у нас є сектор, який розташований на сфері та точка P, розташована у просторі біля сфери. Тепер побудуємо два вектори – один спрямований від центру сфери до центру сектора, інший – від центру сфери до точки огляду. Подивіться на рис.3 - сектор може бути видно лише якщо абсолютне значення кута між цими векторами менше 90 градусів.


Рис.3 a - кут менше 90 - сектор потенційно видно. b - кут більше 90 - сектор не видно

Як отримати цей кут? Для цього потрібно використовувати скалярний добуток векторів. Для тривимірного випадку воно обчислюється так:

Скалярний твір має дистрибутивну властивість:

Раніше ми визначили рівняння довжини вектора - тепер можемо сказати, що довжина вектора дорівнює кореню від скалярного добутку цього вектора себе. Або навпаки - скалярне твори вектора самого на себе дорівнює квадрату його довжини.

Тепер давайте звернемося до закону косинусів. Одне з двох його формулювань виглядає так (рис.4):


Рис.4 Закон косинусів

Якщо взяти за a та b довжини наших векторів, тоді кут alfa – те, що ми шукаємо. Але як нам отримати значення з? Дивіться: якщо ми заберемо a від b, то отримаємо вектор, спрямований від a до b, оскільки вектор характеризується лише напрямом і довжиною, ми можемо графічно розташувати його початок кінці вектора a. Виходячи з цього, ми можемо сказати, що дорівнює довжині вектора b - a. Отже, у нас вийшло

Виразимо квадрати довжин як скалярні твори

Розкриємо дужки, користуючись дистрибутивною властивістю

Трохи скоротимо

І нарешті, поділивши обидві честі рівняння на мінус два, отримаємо

Це ще одна властивість скалярного твору. У нашому випадку треба нормалізувати вектори, щоб їх довжини дорівнювали одиниці. Кут нам обчислювати не обов'язково – достатньо значення косинуса. Якщо воно менше нуля – то можна сміливо стверджувати, що цей сектор нас не цікавить

3. Сітка

Час задуматися про те, як малювати примітиви. Як я говорив раніше, сектор є основним компонентом у нашій схемі, тому для кожного потенційно видимого сектора ми малюватимемо сітку, примітиви якої формуватимуть ландшафт. Кожне з її осередків можна відобразити за допомогою двох трикутників. Через те, що кожен осередок має суміжні грані, значення більшості вершин трикутників повторюються для двох чи більше осередків. Щоб не дублювати дані у буфері вершин, заповнимо буфер індексів. Якщо індекси використовуються, то з їх допомогою графічний конвеєр визначає який примітив у буфері вершин йому обробляти. (Мал.5) Вибрана мною топологія - triangle list (D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)


Рис.5 Візуальне відображення індексів та примітивів

Створювати окремий буфер вершин для кожного сектора занадто накладно. Набагато ефективніше використовувати один буфер з координатами у просторі сітки, тобто x – стовпець, а у – рядок. Але як із них отримати точку на сфері? Сектор є квадратною областю з початком в якійсь точці S. Всі сектори мають однакову довжину грані - назвемо її SLen. Сітка покриває всю площу сектора і має однакову кількість рядків і стовпців, тому для знаходження довжини грані осередку ми можемо побудувати наступне рівняння

Де СLen – довжина грані осередку, MSize – кількість рядків або стовпців сітки. Ділимо обидві частини на MSize та отримуємо CLen


Рис.6 Наочне відображення формування точки на сітці

Щоб отримати точку на сфері, скористаємось рівнянням, виведеним раніше

4. Висота

Все, чого ми досягли цього моменту, мало нагадує ландшафт. Настав час додати те, що зробить його таким - різниця висот. Уявімо, що у нас є сфера одиничного радіусу з центром на початку координат, а також безліч точок (P0, P1, P2… PN), які розташовані на цій сфері. Кожну з цих точок можна як одиничний вектор від початку координат. Тепер уявіть, що ми маємо набір значень, кожне з яких є довжиною конкретного вектора (рис.7).

Зберігати ці значення я буду у двомірній текстурі. Нам потрібно знайти зв'язок між координатами пікселя текстури та вектором-точкою на сфері. Приступимо.

Крім декартової, точка на сфері може бути описана за допомогою сферичної системи координат. У цьому випадку її координати будуть складатися з трьох елементів: азимутного кута, полярного кута та значення найкоротшої відстані від початку координат до точки. Азімутний кут - це кут між віссю X та проекцією променя від початку координат до точки на площину XZ. Він може набувати значень від нуля до 360 градусів. Полярний кут - кут між віссю Y та променем від початку координат до точки. Він також може називатися зенітним чи нормальним. Приймає значення від нуля до 180 градусів. (Див. рис.8)


Рис.8 Сферичні координати

Для переходу з декартової системи в сферичну я користуюся такими рівняннями (я вважаю, що вісь Y спрямована вгору):

Де d – відстань до точки, a – полярний кут, b – азимутний кут. Параметр d можна описати як «довжина вектора від початку координат до точки»(що видно з рівняння). Якщо ми використовуємо нормалізовані координати, можемо уникнути розподілу при знаходженні полярного кута. Власне, навіщо нам ці кути? Розділивши кожен з них на його максимальний діапазон, ми отримаємо коефіцієнти від нуля до одиниці і за їх допомогою зробимо вибірку з текстури в шейдері. При отриманні коефіцієнта для полярного кута необхідно враховувати чверть, де розташований кут. «Але ж значення виразу z/x не визначено при x рівному нулю» - скажете ви. Я навіть скажу - при z рівному нулю кут буде нульовим незалежно від значення x.

Давайте додамо кілька особливих випадків для цих значень. У нас є нормалізовані координати (нормаль) - додамо кілька умов: якщо значення X нормалі дорівнює нулю і значення Z більше за нуль - тоді коефіцієнт дорівнює 0.25, якщо X нульове і Z менше за нуль - то буде 0.75. Якщо значення Z дорівнює нулю і X менше нуля, то цьому випадку коефіцієнт дорівнюватиме 0.5. Все це легко перевірити на колі. Але як вчинити, якщо Z нульове і X більше за нуль - адже в такому випадку будуть коректними як 0 так і 1? Уявимо, що ми вибрали 1 - щож, давайте візьмемо сектор із мінімальним азимутним кутом 0 і максимальним - 90 градусів. Тепер розглянемо перші три вершини в першому рядку сітки, що відображає цей сектор. Для першої вершини у нас виконалася умова і ми встановили для текстурної координати X значення 1. Очевидно, що для наступних двох вершин ця умова не виконається - кути для них знаходяться в першій чверті і в результаті ми отримаємо приблизно такий набір - (1.0, 0.05, 0.1). Але для сектора з кутами від 270 до 360 для останніх трьох вершин у тому ж рядку все буде коректно – спрацює умова для останньої вершини, і ми отримаємо набір (0.9, 0.95, 1.0). Якщо ж ми виберемо як результат нуль, то отримаємо набори (0.0, 0.05, 0.1) і (0.9, 0.95, 0.0) - у будь-якому випадку це призведе до досить помітних спотворень поверхні. Тому давайте застосуємо таке. Візьмемо центр сектора, потім нормалізуємо центр, перемістивши цим на сферу. Тепер обчислимо скалярний добуток нормалізованого центру на вектор (0, 0, 1). Формально кажучи, цей вектор є нормаллю до площини XY, і обчисливши його скалярне твір з нормалізованим вектором центру сектора, ми зможемо зрозуміти, з якого боку центр знаходиться. Якщо воно менше нуля, то сектор знаходиться позаду площини і нам потрібно значення 1. Якщо скалярний добуток більший за нуль, то сектор знаходиться спереду від площини і тому граничним значенням буде 0.(див. рис.9)


Рис.9 Проблема вибору між 0 та 1 для текстурних координат

Ось код отримання текстурних координат із сферичних. Зверніть увагу - через похибки у обчисленнях ми не можемо перевіряти значення нормалі на рівність нулю, натомість ми повинні порівнювати їх абсолютні величини з якимось граничним значенням (наприклад 0.001)

//norm - нормалізовані координати точки, для якої ми отримуємо текстурні координати //offset - нормалізовані координати центру сектора, якому належить norm //zeroTreshold - граничне значення (0.001) float2 GetTexCoords(float3 norm, float3 offset) ( float tX = 0 , tY = 0.0f, bool normXIsZero = abs(norm.x)< zeroTreshold; bool normZIsZero = abs(norm.z) < zeroTreshold; if(normXIsZero || normZIsZero){ if(normXIsZero && norm.z >0.0f) tX = 0.25f; else if(norm.x< 0.0f && normZIsZero) tX = 0.5f; else if(normXIsZero && norm.z < 0.0f) tX = 0.75f; else if(norm.x >0.0f && normZIsZero)( if(dot(float3(0.0f, 0.0f, 1.0f), offset))< 0.0f) tX = 1.0f; else tX = 0.0f; } }else{ tX = atan(norm.z / norm.x); if(norm.x < 0.0f && norm.z >0.0f) tX += 3.141592; else if(norm.x< 0.0f && norm.z < 0.0f) tX += 3.141592; else if(norm.x >0.0f && norm.z< 0.0f) tX = 3.141592 * 2.0f + tX; tX = tX / (3.141592 * 2.0f); } tY = acos(norm.y) / 3.141592; return float2(tX, tY); }
наведу проміжний варіант вершинного шейдера

//startPos - початок грані куба //vec1, vec2 - вектори напрямку грані куба //gridStep - розмір комірки //sideSize - довжина ребра сектора //GetTexCoords() - перетворює сферичні координати на текстурні VOut ProcessVertex(VIn input) ( float3 planePos = startPos + vec1 * input.netPos.x * gridStep.x + vec2 * input.netPos.y * gridStep.y; float3 sphPos = normalize (planePos); 0.5f);float2 tc = GetTexCoords(sphPos, normOffset);float height = mainHeightTex.SampleLevel(mainHeightTexSampler, tc, 0).x; (posL, 1.0f), worldViewProj);output.texCoords = tc; return output;

5. Висвітлення

Щоб реалізувати залежність кольору ландшафту від освітлення, скористаємося наступним рівнянням:

Де I - колір точки, Ld - колір джерела світла, Kd - колір матеріалу поверхні, що освітлюється, a - кут між вектором на джерело і нормаллю до поверхні, що освітлюється. Це окремий випадок закону косінусів Ламберта. Розберемося, що тут і чому. Під множенням Ld на Kd мається на увазі покомпонентне множення кольорів, тобто (Ld.r*Kd.r, Ld.g*Kd.g, Ld.b*Kd.b). Можливо буде простіше зрозуміти сенс, якщо уявити таку ситуацію: припустимо, ми хочемо висвітлити об'єкт зеленим джерелом світла, тому очікуємо, що колір об'єкта буде у градаціях зеленого. Результат (0 * Kd.r, 1 * Kd.g, 0 * Kd.b) дає (0, Kd.g, 0) - рівно те, що нам потрібно. Ідемо далі. Як було озвучено раніше, косинус кута між нормалізованими векорами є їх скалярний твір. Давайте розглянемо його максимальне та мінімальне значення на наш погляд. Якщо косинус кута між векторами дорівнює 1, цей кут дорівнює 0 - отже, обидва вектори колінеарні (лежать на одній прямій).

Те саме справедливо і для значення косинуса -1, тільки в цьому випадку вектори вказують у протилежних напрямках. Виходить, чим ближче вектор нормалі і вектор джерела світла до стану колінеарності - тим вище коефіцієнт освітленості поверхні, якій належить нормаль. Також передбачається, що поверхня не може бути освітлена, якщо її нормаль вказує на протилежну по відношенню до напрямку на джерело сторону - саме тому я використовую тільки позитивні значення косинуса.

Я використовую паралельне джерело, тому його позицію можна знехтувати. Єдине, що потрібно врахувати те, що ми використовуємо вектор на джерело світла. Тобто, якщо напрямок променів (1.0, -1.0, 0) нам треба використовувати вектор (-1.0, 1.0, 0). Єдине, що для нас становить труднощі – вектор нормалі. Обчислити нормаль до площини просто – нам треба зробити векторний добуток двох векторів, що її описують. Важливо пам'ятати, що векторний твір антикоммутативно - потрібно враховувати порядок множників. У нашому випадку отримати нормаль до трикутника, знаючи координати його вершин у просторі сітки, можна наступним чином (Зверніть увагу, що я не враховую граничні випадки для p.x та p.y)

Float3 p1 = GetPosOnSphere(p); float3 p2 = GetPosOnSphere(float2(p.x + 1, p.y)); float3 p3 = GetPosOnSphere(float2(p.x, p.y + 1)); float3 v1 = p2 - p1; float3 v2 = p3 - p1; float3 n = normalzie(cross(v1, v2));
Але це ще не все. Більшість вершин сітки належать одразу чотирьом площинам. Щоб отримати прийнятний результат, треба обчислити усереднену нормаль таким чином:

Na = normalize(n0 + n1 + n2 + n3)
Реалізувати цей метод на GPU досить затратно - нам знадобиться два етапи на обчислення нормалей та їх усереднення. До того ж, ефективність залишає бажати кращого. Тому я вибрав інший спосіб - використовувати карту нормалей.(рис.10)


Рис.10 Карта нормалей

Принцип роботи з нею такий самий, як і з картою висот – перетворюємо сферичні координати вершини сітки в текстурні та робимо вибірку. Тільки ось безпосередньо ці дані ми використовувати не зможемо - адже ми працюємо зі сферою, і вершина має свою нормаль, яку потрібно враховувати. Тому дані карти нормалей ми будемо використовувати як координати TBN базису. Що таке базис? Ось вам такий приклад. Уявіть, що ви космонавт і сидите на маячку десь у космосі. Вам із ЦУПу надходить повідомлення: «Тобі потрібно переміститися від маячка на 1 метр вліво, на 2 метри вгору та на 3 метри вперед». Як це можна висловити математично? (1, 0, 0) * 1 + (0, 1, 0) * 2 + (0, 0, 1) * 3 = (1,2,3). У матричній формі це рівняння можна виразити так:

Тепер уявіть, що ви також сидите на маячку, тільки тепер вам із ЦУПа пишуть: «ми там тобі вектори напрямів надіслали – ти маєш просунутися 1 метр за першим вектором, 2 метри за другим і 3 – за третім». Рівняння для нових координат буде таким:

Покомпонентний запис виглядає так:

Або в матричній формі:

Так ось, матриця з векторами V1, V2 і V3 – це базис, а вектор (1,2,3) – координати у просторі цього базису.

Уявимо тепер, що у вас є набір векторів (база M) і ви знаєте, де ви знаходитесь щодо маячка (точка P). Вам потрібно дізнатися ваші координати в просторі цього базису - на скільки вам потрібно просунутися цими векторами, щоб опинитися в тому ж місці. Представимо шукані координати (X)

Якби P, M і X числами, ми просто розділили б обидві частини рівняння на M, але на жаль… Підемо іншим шляхом - відповідно до властивості зворотної матриці

Де I це поодинока матриця. У нашому випадку вона виглядає так

Що нам це дає? Спробуйте помножити цю матрицю на X і ви отримаєте

Також треба уточнити, що множення матриць має властивість асоціативності.

Вектор цілком законно можемо розглядати як матрицю 3 на 1

Враховуючи все вищесказане, можна зробити висновок, що щоб отримати Х у правій частині рівняння, нам потрібно в правильному порядку помножити обидві частини на зворотну M матрицю

Цей результат знадобиться нам надалі.

Тепер повернемось до нашої проблеми. Я використовуватиму ортонормований базис - це означає, що V1, V2 і V3 ортогональні по відношенню один до одного (утворюють кут 90 градусів) і мають одиничну довжину. Як V1 виступатиме tangent вектор, V2 - bitangent вектор, V3 - нормаль. У традиційному для DirectX транспонованому вигляді матриця виглядає так:

Де T - tangent вектор, B - bitangent вектор і N - нормаль. Давайте знайдемо їх. З нормаллю найпростіше - це нормалізовані координати точки. Bitangent вектор дорівнює векторному добутку нормалі та вектор tangent. Найскладніше доведеться з tangent вектором. Він дорівнює напрямку дотичної до кола в точці. Давайте розберемо цей момент. Спочатку знайдемо координати точки на одиничному колі в площині XZ для деякого кута a

Напрямок дотичної до кола у цій точці можна знайти двома способами. Вектор до точки на колі та вектор дотичної ортогональні - тому, оскільки функції sin і cos періодичні - ми можемо просто додати pi/2 до кута a і отримаємо напрямок, що шукається. Відповідно до властивості зміщення на pi/2:

У нас вийшов наступний вектор:

Ми також можемо скористатися диференціюванням - докладніше див. Додаток 3. Отже, на малюнку 11 ви можете бачити сферу, для кожної вершини якої побудований базис. Сині вектори позначені нормалі, червоні - tangent вектори, зелені - bitangent вектори.


Рис.11 Сфера з TBN базисами у кожній вершині. Червоні - tangent вектори, зелені - bitangent вектори, сині вектори - нормалі

З базисом розібралися – тепер давайте отримаємо карту нормалей. Для цього скористаємось фільтром Собеля. Фільтр Собеля обчислює градієнт яскравості зображення у кожній точці (грубо кажучи, вектор зміни яскравості). Принцип дії фільтра полягає в тому, що потрібно застосувати якусь матрицю значень, яка називається "Ядром", до кожного пікселя та його сусідів у межах розмірності цієї матриці. Припустимо, що ми обробляємо піксель P ядром K. Якщо він знаходиться на межі зображення, він має вісім сусідів - лівий верхній, верхній, правий верхній тощо. Назвемо їх tl, t, tb, l, r, bl, b, br. Так ось, застосування ядра K до цього пікселя полягає в наступному:

Pn = tl * K (0, 0) + t * K (0,1) + tb * K (0,2) +
* K (1, 0) + P * K (1,1) + r * K (1,2) +
* K (2, 0) + b * K (2,1) + br * K (2,2) nbsp

Цей процес називається «Згортка». Фільтр Собеля використовує два ядра для обчислення градієнта по вертикалі та горизонталі. Позначимо їх як Kx і Kу:

Основа є – можна приступати до реалізації. Спершу нам треба вирахувати яскравість пікселя. Я користуюсь перетворенням з колірної моделі RGB на модель YUV для системи PAL:

Але оскільки наше зображення спочатку у градаціях сірого, цей етап можна пропустити. Тепер нам потрібно "згорнути" вихідне зображення з ядрами Kx та Ky. Так ми отримаємо компоненти X та Y градієнта. Також дуже корисним може бути значення нормалі цього вектора - його ми використовувати не будемо, але у зображень, що містять нормалізовані значення нормалі градієнта, є кілька корисних застосувань. Під нормалізацією я маю на увазі наступне рівняння

Де V – значення, яке нормалізуємо, Vmin та Vmax – область цих значень. У нашому випадку мінімальне та максимальне значення відстежуються у процесі генерації. Ось приклад реалізації фільтра Собеля:

Float SobelFilter::GetGrayscaleData(const Point2 &Coords) ( Point2 coords; coords.x = Math::Saturate(Coords.x, RangeI(0, image.size.width - 1)); coords.y = Math::Saturate( Coords.y, RangeI(0, image.size.height - 1)), int32_t offset = (coords.y * image.size.width + coords.x) * image.pixelSize; return (image.pixelFormat == PXL_FMT_R8) pixel : (0.30f * pixel + //R 0.59f * pixel + //G 0.11f * pixel); //B ) void SobelFilter::Process() ( RangeF dirXVr, dirYVr, magNormVr;for(int32_t y = 0; y< image.size.height; y++) for(int32_t x = 0; x < image.size.width; x++){ float tl = GetGrayscaleData({x - 1, y - 1}); float t = GetGrayscaleData({x , y - 1}); float tr = GetGrayscaleData({x + 1, y - 1}); float l = GetGrayscaleData({x - 1, y }); float r = GetGrayscaleData({x + 1, y }); float bl = GetGrayscaleData({x - 1, y + 1}); float b = GetGrayscaleData({x , y + 1}); float br = GetGrayscaleData({x + 1, y + 1}); float dirX = -1.0f * tl + 0.0f + 1.0f * tr + -2.0f * l + 0.0f + 2.0f * r + -1.0f * bl + 0.0f + 1.0f * br; float dirY = -1.0f * tl + -2.0f * t + -1.0f * tr + 0.0f + 0.0f + 0.0f + 1.0f * bl + 2.0f * b + 1.0f * br; float magNorm = sqrtf(dirX * dirX + dirY * dirY); int32_t ind = y * image.size.width + x; dirXData = dirX; dirYData = dirY; magNData = magNorm; dirXVr.Update(dirX); dirYVr.Update(dirY); magNormVr.Update(magNorm); } if(normaliseDirections){ for(float &dirX: dirXData) dirX = (dirX - dirXVr.minVal) / (dirXVr.maxVal - dirXVr.minVal); for(float &dirY: dirYData) dirY = (dirY - dirYVr.minVal) / (dirYVr.maxVal - dirYVr.minVal); } for(float &magNorm: magNData) magNorm = (magNorm - magNormVr.minVal) / (magNormVr.maxVal - magNormVr.minVal); }
Треба сказати, що фільтр Собеля має властивість лінійної сепарабельності, тому даний метод може бути оптимізований.

Складна частина закінчилася - залишилося записати X і Y координати напрямку градієнта в R і G канали пікселів карти нормалей. Для координати Z я використовую одиниця. Також я використовую тривимірний вектор коефіцієнтів для налаштування цих значень. Далі наведено приклад генерації карти нормалей із коментарями:

//ImageProcessing::ImageData Image - оригінальне зображення. Структор містить формат пікселя і дані зображення ImageProcessing::SobelFilter sobelFilter; sobelFilter.Init(Image); sobelFilter.NormaliseDirections() = false; sobelFilter.Process(); const auto &resX =sobelFilter.GetFilteredData(ImageProcessing::SobelFilter::SOBEL_DIR_X); const auto &resY =sobelFilter.GetFilteredData(ImageProcessing::SobelFilter::SOBEL_DIR_Y); ImageProcessing::ImageData destImage = (DXGI_FORMAT_R8G8B8A8_UNORM, Image.size); size_t dstImageSize = Image.size.width * Image.size.height * destImage.pixelSize; std::vector dstImgPixels(dstImageSize); for(int32_t d = 0; d< resX.size(); d++){ //используем вектор настроечных коэффициентов. У меня он равен (0.03, 0.03, 1.0) Vector3 norm = Vector3::Normalize({resX[d] * NormalScalling.x, resY[d] * NormalScalling.y, 1.0f * NormalScalling.z}); Point2 coords(d % Image.size.width, d / Image.size.width); int32_t offset = (coords.y * Image.size.width + coords.x) * destImage.pixelSize; uint8_t *pixel = &dstImgPixels; //переводим значения из области [-1.0, 1.0] в а затем в область pixel = (0.5f + norm.x * 0.5f) * 255.999f; pixel = (0.5f + norm.y * 0.5f) * 255.999f; pixel = (0.5f + norm.z * 0.5f) * 255.999f; } destImage.pixels = &dstImgPixels; SaveImage(destImage, OutFilePath);
Тепер наведу приклад використання карти нормалей у шейдері:

//texCoords - текстурні коорлінати які ми отримали способом, описаним у п.4 //normalL - нормаль вершини //lightDir - вектор на джерело світла //Ld - колір джерела світла //Kd - колір матеріалу поверхні float4 normColor = mainNormalTex. SampleLevel(mainNormalTexSampler, texCoords, 0); //перекладаємо значення з області [-1.0, 1.0] і нормалізуємо результат float3 normalT = normalize(2.0f * mainNormColor.rgb - 1.0f); //перекладаємо текстурну координату Х з області float ang = texCoords.x * 3.141592f * 2.0f; float3 tangent; tangent.x=-sin(ang); tangent.y = 0.0f; tangent.z = cos(ang); float3 bitangent = normalize(cross(normalL, tangent)); float3x3 tbn = float3x3(tangent, bitangent, normalL); float3 resNormal = mul(normalT, tbn); float diff = saturate(dot(resNormal, lightDir.xyz)); float4 resColor = Ld * Kd * diff;

6. Level Of Detail

Ну от тепер наш ландшафт освітлений! Можна летіти на Місяць - загураємо карту висот, ставимо колір матеріалу, завантажуємо сектори, встановлюємо розмір сітки рівним (16, 16) і ... Так, щось замало - поставлю ка я (256, 256) - ой, щось все гальмує , та й навіщо висока деталізація на далеких секторах? До того ж, що ближче спостерігач до планети, то менше секторів він може побачити. Так… походу у нас ще багато роботи! Спершу розберемося, як відсікти зайві сектори. Визначальною величиною тут буде висота спостерігача від поверхні планети - чим вона вища, тим більше секторів може побачити (рис.12)


Рис.12 Залежність висоти спостерігача від кількості оброблюваних секторів

Висоту знаходимо так - будуємо вектор від позиції спостерігача на центр сфери, обчислюємо його довжину і віднімаємо від неї значення радіусу сфери. Раніше я говорив, що якщо скельний твір вектора на спостерігача і вектора на центр сектора менший за нуль, то цей сектор нас не цікавить - тепер замість нуля ми будемо використовувати значення, лінійно залежне від висоти. Спершу давайте визначимося зі змінними – отже, у нас будуть мінімальне та максимальне значення скалярного твору та мінімальне та максимальне значення висоти. Побудуємо наступну систему рівнянь

Тепер висловимо А у другому рівнянні

Підставимо А з другого рівняння до першого

Виразимо B з першого рівняння

Підставимо B з першого рівняння до другого

Тепер підставимо змінні на функцію

І отримаємо

Де Hmin та Hmax – мінімальне та максимальне значення висоти, Dmin та Dmax – мінімальне та максимальне значення скалярного твору. Це завдання можна вирішити інакше - див. додаток 4.

Тепер слід розібратися з рівнями деталізації. Кожен із них визначатиме область значення скалярного твору. У псевдокод процес визначення належності сектора певному рівню виглядає так:

Цикл по всіх секторах обчислюємо скалярний добуток вектора на спостерігача і вектора на центр сектора якщо скалярний добуток менший за мінімальний поріг, обчислений раніше переходимо до наступного сектора цикл за рівнями деталізації якщо скалярний добуток знаходиться в рамках певних для цього рівня додаємо сектор до цього рівня кінець циклу рівням деталізації кінець циклу по всіх секторах
Нам треба обчислити область значення кожного рівня. Спочатку побудуємо систему із двох рівнянь

Вирішивши її, отримаємо

Використовуючи ці коефіцієнти, визначимо функцію

Де Rmax це область значення скалярного твору (D(H) – Dmin), Rmin – мінімальна область, яка визначається рівнем. Я використовую 0.01. Тепер нам потрібно відібрати результат від Dmax

За допомогою цієї функції ми отримаємо області для всіх рівнів. Ось приклад:

Const float dotArea = dotRange.maxVal - dotRange.minVal; const float Rmax = dotArea, Rmin = 0.01f; float lodsCnt = lods.size(); float A = Rmax; float B = powf(Rmin/Rmax, 1.0f/(lodsCnt - 1.0f)); for(size_t g = 0; g< lods.size(); g++){ lods[g].dotRange.minVal = dotRange.maxVal - A * powf(B, g); lods[g].dotRange.maxVal = dotRange.maxVal - A * powf(B, g + 1); } lods.dotRange.maxVal = 1.0f;
Тепер ми можемо визначити, якого рівня деталізації належить сектор (рис.13).


Рис.13 Колірна диференціація секторів згідно з рівнями деталізації

Далі треба розібратися із розмірами сіток. Зберігати для кожного рівня свою сітку буде дуже невигідно - набагато ефективніше змінювати деталізацію однієї сітки на льоту за допомогою тесселяції. Для цього нам треба окрім звичних вершинного та піксельного, також реалізувати hull та domain шейдери. У Hull шейдері основне завдання – підготувати контрольні точки. Він складається з двох частин - основної функції та функції, що обчислює параметри контрольної точки. Обов'язково потрібно вказати значення для наступних атрибутів:

domain
partitioning
outputtopology
outputcontrolpoints
patchconstantfunc
Ось приклад Hull шейдера для розбиття трикутниками:

Struct PatchData ( float edges : SV_TessFactor; float inside: SV_InsideTessFactor; ); PatchData GetPatchData(InputPatch Patch, uint PatchId: SV_PrimitiveID) ( PatchData output; flloat tessFactor = 2.0f; output.edges = tessFactor; output.edges = tessFactor; output.edges = tessFactor; output.inside = tessFactor; return Patch, uint PointId: SV_OutputControlPointID, uint PatchId: SV_PrimitiveID) ( return Patch; )
Бачте, основна робота виконується у GetPatchData(). Її завдання – встановити фактор тесселяції. Про нього ми поговоримо пізніше-зараз перейдемо до Domain шейдера. Він отримує контрольні точки від Hull шейдера та координати від теселятора. Нове значення позиції чи текстурних координат у разі розбиття трикутниками потрібно обчислювати за такою формулою

N = C1 * F.x + C2 * F.y + C3 * F.z

Де C1, C2 і C3 – значення контрольних точок, F – координати теселятора. Також у Domain шейдері потрібно встановити атрибут domain, значення якого відповідає тому, що було вказано у Hull шейдері. Ось приклад Domain шейдера:

Cbuffer buff0: register(b0) ( matrix worldViewProj; ) struct PatchData ( float edges : SV_TessFactor; float inside: SV_InsideTessFactor; ); PIn ProcessDomain(PatchData Patch, float3 Coord: SV_DomainLocation, const OutputPatch Tri) (float3 posL = Tri.posL * Coord.x + Tri.posL * Coord.y + Tri.posL * Coord.z; float2 texCoords = Tri.texCoords * Coord.x + Tri.texCoords * Coord.y + Tri .texCoords * Coord.z; PIN output; output.posH = mul(float4(posL, 1.0f), worldViewProj); output.normalW = Tri.normalW;
Роль вершинного шейдера в цьому випадку зведена до мінімуму – у мене він просто «прокидає» дані на наступний етап.

Тепер треба реалізувати щось схоже. Наше першорядне завдання – обчислити фактор тесселяції, а якщо точніше, то побудувати його залежність від висоти спостерігача. Знову побудуємо систему рівнянь

Вирішивши її в такий же спосіб, як і раніше, отримаємо

Де Tmin та Tmax – мінімальний та максимальний коефіцієнти тесселяції, Hmin та Hmax – мінімальне та максимальне значення висоти спостерігача. Мінімальний коефіцієнт тесселяції у мене дорівнює одиниці. максимальний встановлюється окремо для кожного рівня
(наприклад, 1, 2, 4, 16).

Надалі нам буде необхідно, щоб зростання фактора було обмежено найближчим ступенем двійки. тобто для значень від двох до трьох ми встановлюємо значення два, для значень від 4 до 7 встановимо 4, при значеннях від 8 до 15 фактор дорівнює 8 і т.д. Давайте розв'яжемо це завдання для фактора 6. Спершу вирішимо наступне рівняння

Давайте візьмемо десятковий логарифм від двох частин рівняння

Відповідно до властивості логарифмів, ми можемо переписати рівняння в такий спосіб

Тепер нам залишається розділити обидві частини на log(2)

Але це ще не все. Х дорівнює приблизно 2.58. Далі потрібно скинути дробову частину і звести двійку в ступінь числа. Ось код обчислення факторів тесселяції для рівнів деталізації

Float h = camera-> GetHeight (); const RangeF &hR = heightRange; for(LodsStorage::Lod &lod: lods)( //derived from system //A + B * Hmax = Lmin //A + B * Hmin = Lmax //and gettting A the substitution B in second equality float mTf = (float )lod.GetMaxTessFactor(); (1.0f, mTf));float nearPowOfTwo = pow(2.0f, floor(log(tessFactor) / log(2)));lod.SetTessFactor(nearPowOfTwo);

7. Шум

Давайте подивимося, як можна збільшити деталізацію ландшафту, не змінюючи розмір карти висот. Мені на думку спадає наступне - змінювати значення висоти на значення, отримане з текстури градієнтного шуму. Координати, за якими ми здійснюватимемо вибірку, будуть у N разів більшими за основні. Під час вибірки буде задіяний дзеркальний тип адресації (D3D11_TEXTURE_ADDRESS_MIRROR) (див. рис.14).


Рис.14 Сфера з картою висот + сфера з шумовою картою = сфера з підсумковою висотою

У цьому випадку висота обчислюватиметься таким чином:

//float2 tc1 - текстурні координати, отримані з нормалізованої точки, як було //розказано раніше //texCoordsScale - множник текстурних координат. У моєму випадку дорівнює значенню 300 //mainHeightTex, mainHeightTexSampler – текстура карти висот // distHeightTex, distHeightTexSampler – текстура градієнтного шуму //maxTerrainHeight – максимальна висота ландшафту. У моєму випадку 0.03 float2 tc2 = tc1*texCoordsScale; float4 mainHeighTexColor = mainHeightTex.SampleLevel(mainHeightTexSampler, tc1, 0); float4 distHeighTexColor = distHeightTex.SampleLevel(distHeightTexSampler, tc2, 0); float height = (mainHeighTexColor.x + distHeighTexColor.x) * maxTerrainHeight;
Поки що періодичний характер виражається значно, але з додаванням освітлення та текстурування ситуація зміниться на краще. А що таке являє собою текстура градієнтного шуму? Грубо кажучи, це грати з випадкових значень. Давайте розберемося, як зіставити розміри ґрат розміру текстури. Припустимо, ми хочемо створити шумову текстуру розміру 256 на 256 пікселів. Все просто, якщо розміри решітки збігаються з розмірами текстури – у нас вийде щось подібне до білого шуму в телевізорі. А як бути, якщо наша решітка має розміри, скажімо, 2 на 2? Відповідь проста - використовувати інтерполяцію. Одне з формулювань лінійної інтерполяції має такий вигляд:

Це найшвидший, але в той же час найменш підходящий нам варіант. Краще використовувати інтерполяцію на основі косинуса:

Але ми не можемо просто інтерполювати між значеннями по краях діагоналі (лівим нижнім та правим верхнім кутом осередку). У нашому випадку інтерполяцію потрібно буде застосовувати двічі. Давайте представимо одну з осередків решітки. У неї є чотири кути – назвемо їх V1, V2, V3, V4. Також усередині цього осередку буде своя двовимірна система координат, де точка (0, 0) відповідає V1 і точка (1, 1) - V3 (див. рис.15a). Для того, щоб отримати значення з координатами (0.5, 0.5), нам спершу потрібно отримати два інтерпольовані по Х значення між V1 і V4 і між V2 і V3, і нарешті інтерполювати по Y між цими значеннями (рис.15b).

Ось приклад:

Float2 coords(0.5f, 0.5f) float4 P1 = lerp(V1, V4, coords.x); float4 P2 = lerp(V2, V3, coords.x); float4 P = lerp(P1, P2, coords.y)


Рис.15 a - Зображення осередку решітки з координатами V1, V2, V3 та V4. b - Послідовність двох інтерполяцій на прикладі комірки

Тепер давайте зробимо наступне - для кожного пікселя шумової текстури візьмемо інтерполіроване значення для сітки 2х2, потім додамо до нього інтерполіроване значення для сітки 4х4, помножене на 0.5, потім для сітки 8х8, помножене на 0.25 і т.д до октав (рис.16). Формула виглядає так:


Рис.16 Приклад додавання октав

Ось приклад реалізації:

For(int32_t x = 0; x< size.width; x++) for(int32_t y = 0; y < size.height; y++){ float val = 0.0f; Vector2 normPos = {(float)x / (float)(sideSize - 1), (float)y / (float)(sideSize - 1)}; for(int32_t o = 0; o < octavesCnt; o++){ float frequency = powf(2.0f, (float)(startFrequency + o)); float intencity = powf(intencityFactor, (float)o); Vector2 freqPos = normPos * frequency; Point2 topLeftFreqPos = Cast(freqPos); Point2 btmRightFreqPos = topLeftFreqPos + Point2(1, 1); float xFrac = freqPos.x - (float)topLeftFreqPos.x; float yFrac = freqPos.y - (float)topLeftFreqPos.y; float iVal = GetInterpolatedValue(topLeftFreqPos, btmRightFreqPos, xFrac, yFrac); val += iVal * intencity; ) noiseValues ​​= val; )
Також для V1, V2, V3 та V4 ви можете отримати суму від самого значення та його сусідів наступним чином:

Float GetSmoothValue(const Point2 &Coords) ( float corners = (GetValue((Coords.x - 1, Coords.y - 1)) + GetValue((Coords.x + 1, Coords.y - 1)) + GetValue(Co .x - 1, Coords.y + 1)) + GetValue((Coords.x + 1, Coords.y + 1))) / 16.0f; )) + GetValue((Coords.x + 1, Coords.y)) + GetValue((Coords.x, Coords.y - 1)) + GetValue((Coords.x, Coords.y + 1))) / 8.0 f; float center = GetValue(Coords) / 4.0f; return center + sides + corners;
та використовувати ці значення при інтерполяції. Ось решта коду:

Float GetInterpolatedValue(const Point2 &TopLeftCoord, const Point2 &BottomRightCoord, float XFactor, float YFactor) ( Point2 tlCoords(TopLeftCoord.x, TopLeftCoord.y); .y), Point2 blCoords(TopLeftCoord.x, BottomRightCoord.y); float br = (useSmoothValues) ? GetSmoothValue(brCoords) : GetValue(brCoords) : topVal = Math::CosInterpolation(tl, tr, XFactor);
У висновку підрозділу хочу сказати, що все описане мною до цього моменту - дещо відмінна від канонічної реалізація шуму Перліна.
З висотою розібралися – тепер давайте подивимося, як бути з нормалями. Як і у випадку з основною картою висот, з текстри шуму нам треба згенерувати карту нормалей. Потім у шейдері ми просто складаємо нормаль із основної карти з нормаллю із шумової текстури. Слід сказати, що це не зовсім коректно, але дає прийнятний результат. Ось приклад:
//float2 texCoords1 - текстурні координати, отримані з нормалізованої точки, як було розказано раніше //mainNormalTex, mainNormalTexSampler - основна карта нормалей //distNormalTex, distNormalTexSampler - карта нормалей градієнтного шуму float2 texCoords float4 mainNormColor = mainNormalTex.SampleLevel(mainNormalTexSampler, TexCoords1, 0); float4 distNormColor = distNormalTex.SampleLevel(distNormalTexSampler, TexCoords2, 0); float3 mainNormal = 2.0f * mainNormColor.rgb - 1.0f; float3 distNormal = 2.0f * distNormColor.rgb - 1.0f; float3 normal = normalize(mainNormal + distNormal);

8. Hardware Instancing

Займемося оптимізацією. Зараз цикл відмальовування секторів у псевдокоді виглядає так

Цикл по всіх секторах обчислюємо скалярний добуток вектора на точку і вектора на центр сектора якщо він більше нуля встановлюємо значення S даних шейдера встановлюємо значення V1 даних шейдера встановлюємо значення V2 даних шейдера малюємо сітку кінець умови кінець циклу по всіх секторах
продуктивність цього підходу надзвичайно мала. Варіантів оптимізації декілька – можна побудувати квадродерево для кожної площини куба, щоб не обчислювати скалярний добуток для кожного сектора. Також можна оновлювати значення V1 і V2 не для кожного сектора, а для шести площин куба, яким вони належать. Я вибрав третій варіант – Instancing. Коротко про те, що це таке. Допустимо, ви хочете намалювати ліс. Ви маєте модель дерева, також є набір матриць перетворень - позиції дерев, можливе масштабування або поворот. Ви можете створити один буфер, в якому будуть утримуватися перетворені на світовий простір вершини всіх дерев - варіант непоганий, ліс по карті не бігає. А якщо вам треба реалізовувати перетворення - скажімо, похитування дерев на вітрі. Можна зробити так - копіюємо дані вершин моделі N раз на один буфер, додаючи до даних вершини індекс дерева (від 0 до N). Далі оновлюємо масив матриць перетворень і передаємо його як змінну шейдер. У шейдері вибираємо потрібну матрицю за індексом дерева. Як можна уникнути дублювання даних? Для початку хочу звернути вашу увагу, що ці вершини можна зібрати з кількох буферів. Для опису вершини необхідно вказати індекс джерела в полі InputSlot структури D3D11_INPUT_ELEMENT_DESC. Це можна використовувати при реалізації лицьової анімації - скажімо у вас є два буфери вершин, що містили два стани особи, і ви хочете лінійно інтерполювати ці значення. Ось як треба описати вершину:

D3D11_INPUT_ELEMENT_DESC desc = ( /*part1*/ ("POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0), ("NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0), ("TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0), /*part2*/ ("POSITION", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0), ("NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA , 0), ("TEXCOORD", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 24, D3D11_INPUT_PER_VERTEX_DATA, 0) )
у шейдері вершину потрібно описати так:

Struct VIn ( float3 position1: POSITION0; float3 normal1: NORMAL0; float2 tex1: TEXCOORD0; float3 position2: POSITION1; float3 normal2: NORMAL1; float2 tex2: TEXCOORD1; )
далі ви просто інтерполюєте значення

Float3 res = lerp (input.position1, input.position2, factor);
Навіщо я це? Повернемося, наприклад, з деревами. Вершину збиратимемо з двох джерел - перший міститиме позицію в локальному просторі, текстурні координати і нормаль, другий - матрицю перетворення у вигляді чотирьох чотиривимірних векторів. Опис вершини виглядає так:

D3D11_INPUT_ELEMENT_DESC desc = ( /*part1*/ ("POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0), ("NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0), ("TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0), /*part2*/ ("WORLD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("WORLD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA , 1), ("WORLD", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("WORLD", 3, DXGI_FORMAT_R32G32B32A
Зверніть увагу, що в другій частині поле InputSlotClass дорівнює D3D11_INPUT_PER_INSTANCE_DATA і поле InstanceDataStepRate дорівнює одиниці (Короткий опис поля InstanceDataStepRate див. у додатку 1). У цьому випадку збирач буде використовувати дані всього буфера з джерела типу D3D11_INPUT_PER_VERTEX_DATA для кожного елемента джерела з типом D3D11_INPUT_PER_INSTANCE_DATA. При цьому в шейдері дані вершини можна описати так:

Struct VIn ( float3 posL: POSITION; float3 normalL: NORMAL; float2 tex: TEXCOORD; row_major float4x4 world: WORLD; );
Створивши другий буфер з атрибутами D3D11_USAGE_DYNAMIC та D3D11_CPU_ACCESS_WRITE, ми зможемо оновлювати його з боку CPU. Відображувати таку геометрію потрібно за допомогою викликів DrawInstanced() або DrawIndexedInstanced(). Є ще виклики DrawInstancedIndirect() і DrawIndexedInstancedIndirect() - про них див. у додатку 2.

Наведу приклад установки буферів та використання функції DrawIndexedInstanced():

//vb - вершинний буфер //tb - "істансний" буфер //ib - індексний буфер //vertexSize - розмір елемента у вершинному буфері //instanceSize - розмір елемента в "інстансному" буфері //indicesCnt - кількість індексів //instancesCnt - кількість "інстансів" std::vector buffers = (vb, tb); std::vector strides = (vertexSize, instanceSize); std::vector offsets = (0, 0); deviceContext->IASetVertexBuffers(0,buffers.size(),&buffers,&strides,&offsets); deviceContext->IASetIndexBuffer(ib, DXGI_FORMAT_R32_UINT, 0); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->DrawIndexedInstanced(indicesCnt, instancesCnt, 0, 0, 0);
Тепер нарешті повернемося до нашої теми. Сектор мужньо описати крапкою на площині, якій належить і двома векторами, які цю площину описують. Отже вершина складатиметься із двох джерел. Перший – координати у просторі сітки, другий – дані сектора. Опис вершини виглядає так:

Std::vector meta = ( //координати у просторі сітки ("POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0) //перший вектор грані ("TEXCOORD", 0, DXGI_FORM_ /другий вектор грані ("TEXCOORD", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_INSTANCE_DATA, 1), //початок грані ("TEXCOORD", 2, DXGI_FORMAT_R2,
Зауважте, що для зберігання координат у просторі сітки я використовую тривимірний вектор (координата z не використовується)

9. Frustum culling

Ще один важливий компонент оптимізації - відсікання по піраміді видимості (Frustum culling). Піраміда видимості – це та область сцени, яку «бачить» камера. Як її збудувати? Спершу згадаємо, що точка може бути в чотирьох системах координат – локальній, світовій, видовій та системі координат проекції. Перехід між ними здійснюється за допомогою матриць - світової, видової та матриці проекції, причому перетворення повинні проходити послідовно - від локального до світового, зі світового до видового і нарешті з видового до простору проекції. Всі ці перетворення можна поєднати в одне за допомогою множення цих матриць.

Ми використовуємо перспективну проекцію, яка має на увазі так званий «однорідний поділ» - після множення вектора (Px, Py, Pz, 1) на матрицю проекції його компоненти слід розділити на компонент W цього вектора. Після переходу в простір проекції та однорідного поділу точка опиняється у NDC просторі. NDC простір являє собою набір із трьох координат x, y, z, де x і y належать [-1, 1], а z - (Треба сказати, що в OpenGL параметри дещо інші).

Тепер давайте приступимо до вирішення нашого завдання. У моєму випадку піраміда розташована у видовому просторі. Нам потрібно шість площин, що її описують (рис.17а). Площину можна описати за допомогою нормалі та точки, яка цій площині належить. Спершу давайте отримаємо точки - для цього візьмемо наступний набір координат у просторі NDC:

Std::vector PointsN = ((-1.0f, -1.0f, 0.0f, 1.0f), (-1.0f, 1.0f, 0.0f, 1.0f), (1.0f, 1.0f, 0.0f, 1.0f), (1.0 f, -1.0f, 0.0f, 1.0f), (-1.0f, -1.0f, 1.0f, 1.0f), (-1.0f, 1.0f, 1.0f, 1.0f), ( 1.0f, 1.0f) , 1.0f, 1.0f), (1.0f, -1.0f, 1.0f, 1.0f));
Подивіться, у перших чотирьох точках значення z дорівнює 0 - це означає, що вони належать ближній площині відсікання, в останніх чотирьох z дорівнює 1 - вони належать дальній площині відсікання. Тепер ці точки потрібно перетворити на видовий простір. Але як?

Пам'ятайте приклад про космонавта - отож тут теж саме. Нам потрібно помножити крапки на зворотну матрицю проекції. Щоправда, після цього потрібно поділити кожен із новачків з його координату W. У результаті отримаємо потрібні координати (рис.17b). Давайте тепер розберемося з нормалями – вони мають бути спрямовані всередину піраміди, тому нам треба вибрати необхідний порядок обчислення векторного твору.

Matrix4x4 invProj = Matrix4x4::Inverse(camera->GetProjMatrix()); std::vector PointsV; for(const Point4F &pN: pointsN)( Point4F pV = invProj.Transform(pN); pV /= pV.w; pointsV.push_back(Cast (pV)); ) planes = (pointsV, pointsV, pointsV); //near plane planes = (pointsV, pointsV, pointsV); //far plane planes = (pointsV, pointsV, pointsV); //Left plane planes = (pointsV, pointsV, pointsV); //right plane planes = (pointsV, pointsV, pointsV); //top plane planes = (pointsV, pointsV, pointsV); //bottom plane planes.normal *= -1.0f; planes.normal *=-1.0f;


Рис.17 Піраміда видимості

Піраміда побудована – настав час її використати. Ті сектори, які не потрапляють усередину піраміди, ми не малюємо. Для того, щоб визначити, чи знаходиться сектор всередині піраміди видимості, ми перевірятимемо сферу, що обмежує, розташовану в центрі цього сектора. Це не дає точних результатів, але в даному випадку я не бачу нічого страшного в тому, що буде намальовано кілька зайвих секторів. Радіус сфери обчислюється так:

Де TR – правий верхній кут сектора, BL – лівий нижній кут. Оскільки всі сектори мають однакову площу, то радіус достатньо обчислити один раз.

Як нам визначити, чи знаходиться сфера, що описує сектор, усередині піраміди видимості? Спершу нам потрібно визначити, чи перетинається сфера з площиною і якщо ні, то з якого боку вона знаходиться. Давайте отримаємо вектор на центр сфери

Де P – точка на площині та S – центр сфери. Тепер обчислимо скалярний добуток цього вектора на нормаль площині. Орієнтацію можна визначити за допомогою знака скалярного твору - як говорилося раніше, якщо він позитивний, то сфера знаходиться спереду від площини, якщо негативний, сфера знаходиться позаду. Залишилося визначити, чи сфера перетинає площину. Давайте візьмемо два вектори - N (вектор нормалі) і V. Тепер побудуємо вектор від N до V - назвемо його K. Так ось, нам треба знайти таку довжину N, щоб він з K утворював кут 90 градусів (формально кажучи, щоб N і K були ортогональні). Оки доки, подивіться на рис.18a - з властивостей прямокутного трикутника ми знаємо, що

Потрібно знайти косинус. Використовуючи раніше згадану властивість скалярного твору

Ділимо обидві частини на | V | * | N | і отримуємо

Використовуємо цей результат:

Оскільки |V| це просто число, можна скоротити на |V|, і тоді ми отримаємо

Так як вектор N нормалізований, то останнім кроком ми просто помножимо його на значення, що вийшло, в іншому випадку вектор слід нормалізувати - в цьому випадку кінцеве рівняння виглядає так:

Де D це наш новий вектор. Цей процес називається "Векторна проекція" (рис.18b). Але навіщо це нам? Ми знаємо, що вектор визначається довжиною і напрямом і ніяк не змінюється від його положення - це означає, що якщо ми розташуємо D так, щоб він вказував на S, то його довжина дорівнюватиме мінімальній відстані від S до площини (рис.18с)


Рис.18 a Проекція N на V, b Наочне відображення довжини спроектованого N стосовно точки, з Наочне відображення
довжини спроектованого N стосовно сфери з центром у S

Так як у нас немає потреби у спроектованому векторі, достатньо лише обчислити його довжину. Враховуючи, що N це одиничний вектор, нам потрібно лише обчислити скалярний твір V на N. Зібравши все докупи, ми можемо нарешті укласти, що сфера перетинає площину, якщо значення скалярного твору вектора на центр сфери і нормалі до площини більше нуля і менше значення радіуса цієї сфери.

Для того, щоб стверджувати, що сфера знаходиться всередині піраміди видимості, нам треба переконатися, що вона або перетинає одну з площин або знаходиться спереду від кожної з них. Можна поставити питання по іншому - якщо сфера не перетинає і знаходиться позаду хоча б однієї з площин - вона безперечно поза пірамідою видимості. Так ми зробимо. Зверніть увагу, що я перекладаю центр сфери в простір, в якому розташована піраміда - в простір виду.

Bool Frustum :: TestSphere (const Point3F &Pos, float Radius, const Matrix4x4 &WorldViewMatrix) const ( Point3F posV = WorldViewMatrix.Transform(Pos); for(const Plane &pl: planes)( Vector3 toSphPos = posV - pl.pos; ::Dot(toSphPos, pl.normal)< -Radius) return false; } return true; }

10. Тріщини

Ще одна проблема, яку нам належить вирішити – тріщини на межах рівнів деталізації (рис.19).


Рис.19 демонстрація тріщин ландшафту

Насамперед нам треба визначити ті сектори, які лежать на межі рівнів деталізації. На перший погляд здається, що це ресурсомістке завдання - адже кількість секторів на кожному рівні постійно змінюється. Але якщо використовувати ці суміжності, то рішення значно спрощується. Що таке дані суміжності? Дивіться, кожен сектор має чотирьох сусідів. Набір посилань на них - чи то покажчики чи індекси - і є дані суміжності. З їхньою допомогою ми легко визначимо, який сектор лежить на кордоні – достатньо перевірити, до якого рівня належать його сусіди.

Ну що ж, знайдемо сусідів кожного сектора. І знову ж таки нам не потрібно перебирати в циклі всі сектори. Уявімо, що ми працюємо з сектором з координатами X та Y у просторі сітки.

Якщо він не стосується ребра куба, то координати його сусідів будуть такими:

Сусід зверху - (X, Y - 1)
Сусід знизу - (X, Y + 1)
Сусід зліва - (X - 1, Y)
Сусід праворуч - (X + 1, Y)

Якщо ж сектор стосується ребра, ми поміщаємо його спеціальний контейнер. Після обробки всіх шести граней у ньому будуть утримуватися всі граничні сектори куба. Ось у цьому контейнері нам і належить здійснювати перебір. Заздалегідь обчислимо ребра для кожного сектора:

Struct SectorEdges ( CubeSectors::Sector *owner; typedef std::pair Edge; Edge edges; ); std::vector сектори Edges; //borderSectors - контейнер з граничними секторами for(CubeSectors::Sector &sec: borderSectors)( // кожен сектор містить два вектори, які описують грань куба, // якій він належить Vector3 v1 = sec.vec1 * sec.sideSize; Vector3 v2 = sec.vec2 * sec.sideSize;//sec.startPos - початок сектора в локальному просторі SectorEdges secEdges;secEdges.owner=secEdges.edges=(sec.startPos, sec.startPos+v1); startPos, sec.startPos + v2), secEdges.edges = (sec.startPos + v2, sec.startPos + v2 + v1); .push_back(secEdges);
Далі йде сам перебір

For(SectorEdges &edgs: sectorsEdges) for(size_t e = 0; e< 4; e++) if(edgs.owner->adjacency[e] == nullptr) FindSectorEdgeAdjacency(edgs, (AdjacencySide)e, sectorsEdges);
Функція FindSectorEdgeAdjacency() виглядає так

Void CubeSectors::FindSectorEdgeAdjacency(SectorEdges &Sector, CubeSectors::AdjacencySide Side, std::vector &Neibs) ( SectorEdges::Edge &e = Sector.edges; for(SectorEdges &edgs2: Neibs)( if(edgs2.owner == Sector.owner) continue; for(size_t e = 0; e< 4; e++){ SectorEdges::Edge &e2 = edgs2.edges[e]; if((Math::Equals(e.first, e2.first) && Math::Equals(e.second, e2.second)) || (Math::Equals(e.second, e2.first) && Math::Equals(e.first, e2.second))) { Sector.owner->adjacency = edgs2.owner; edgs2.owner->adjacency[e] = Sector.owner; return; ) ) ) )
Зверніть увагу, що ми оновлюємо дані суміжності для двох секторів - шуканого (Sector) та знайденого сусіда.

Тепер, використовуючи отримані нами дані суміжності, ми маємо знайти ті ребра секторів, які належать межі рівнів деталізації. План такий – перед відмальовуванням знайдемо граничні сектори. Потім для кожного сектора в Instance buffer крім основної
інформації запишемо коефіцієнт тесселяції та чотиривимірний вектор коефіцієнтів тесселяції для сусідніх секторів. Опис вершини тепер виглядатиме так:

Std::vector meta = ( //координати в просторі сітки ("POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0) //перший вектор грані ("TEXCOORD", 0, DXGI_FORM__AT, /второй вектор грани ("TEXCOORD", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_INSTANCE_DATA, 1), //начало грани ("TEXCOORD", 2, DXGI_FORMAT_R32G32B32_FLOAT, 1, 24, D3D11_INPUT_PER_INSTANCE_DATA, 1), //коэффициенты тесселяции соседних секторов ("TEXCOORD", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 36, D3D11_INPUT_PER_INSTANCE_DATA, 1), //коефіцієнт тесселяції сектора ("TEXCOORD", 4, DXGI_3_DAT,
Після того, як ми розподілили сектори за рівнями деталізації, визначимо сусідні коефіцієнти тесселяції для кожного сектора:

For(LodsStorage::Lod &lod: lods)( const std::vector §ors = lod.GetSectors(); bool lastLod = lod.GetInd() == lods.GetCount() - 1; for(Sector *s: sectors)( int32_t tessFacor = s->GetTessFactor(); s->GetBorderTessFactor() = ( GetNeibTessFactor(s, Sector::ADJ_BOTTOM, tessFacor, lastLod), GetNeibTess tessFacor, lastLod), GetNeibTessFactor(s, Sector::ADJ_TOP, tessFacor, lastLod), GetNeibTessFactor(s, Sector::ADJ_RIGHT, tessFacor, lastLod) ); ) )
Функція, яка шукає сусідній фактор тесселяції:

Float Terrain::GetNeibTessFactor(Sector *Sec, Sector::AdjacencySide Side, int32_t TessFactor, bool IsLastLod) ( Sector *neib = Sec->GetAdjacency(); int32_t neibTessFactor = neib->Get< TessFactor) ? (float)neibTessFactor: 0.0f; }
Якщо ми повертаємо нуль, то сусід на боці Side не є для нас інтересом. Забігу вперед і скажу, що нам потрібно усувати тріщини з боку рівня з більшим коефіцієнтом тесселяції.

Тепер перейдемо до шейдера. Нагадаю, що спершу нам потрібно отримати координати сітки, використовуючи координати теселятора. Потім ці координати перетворюються на точку на межі куба, ця точка нормалізується - і ось ми маємо точку на сфері:

Float3 p = Tri.netPos * Coord.x + Tri.netPos * Coord.y + Tri.netPos * Coord.z; float3 planePos = Tri.startPos + Tri.vec1 * p.x * gridStep.x + Tri.vec2 * p.y * gridStep.y; float3 sphPos = normalize(planePos);
Спершу нам треба з'ясувати, чи належить вершина або першому або останньому рядку сітки, або першому або останньому стовпцю - у цьому випадку вершина належить ребру сектора. Але цього мало - нам необхідно визначити, чи належить вершина межі рівнів деталізації. Для цього використовуємо інформацію про сусідні сектори, а точніше їх рівні тесселяції:

Float4 bTf = Tri.borderTessFactor; bool isEdge = (bTf.x != 0.0f && p.y == 0.0f) || //bottom (bTf.y != 0.0f && p.x == 0.0f) || //left (bTf.z != 0.0f && p.y == gridSize.y) || //top (bTf.w != 0.0f && p.x == gridSize.x) //right
Тепер головний етап – власне, усунення тріщин. Подивіться на рис.20. Червона лінія - грань вершини, що належить до другого рівня деталізації. Дві сині лінії – межі третього рівня деталізації. Нам потрібно, щоб V3 належала червоній лінії – тобто лежала на межі другого рівня. Як висоти V1 і V2 рівні обох рівнів, V3 можна знайти з допомогою лінійної інтерполяції з-поміж них


Рис.20 Демонстрація граней, що утворюють тріщину, як ліній

Поки що ми маємо ні V1 і V2, ні коефіцієнта F. Спочатку потрібно знайти індекс точки V3. Тобто якщо сітка має розмір 32 на 32 і коефіцієнт тесселяції дорівнює чотирьом, цей індекс буде від нуля до 128 (32 * 4). У нас вже є координати в просторі сітки p - в рамках цього прикладу вони можуть бути, наприклад (15.5, 16). Для отримання індексу потрібно помножити одну з координат на коефіцієнт тесселяції. Нам також знадобиться початок грані та направлення на її кінець – один із кутів сектора.

Float edgeVertInd = 0.0f; float3 edgeVec = float3(0.0f, 0.0f, 0.0f); float3 startPos = float3(0.0f, 0.0f, 0.0f); uint neibTessFactor = 0; if(bTf.x != 0.0f && p.y == 0.0f)( // bottom edgeVertInd = p.x * Tri.tessFactor; edgeVec = Tri.vec1; startPos = Tri.startPos; neibTessFactor = (uint)Tri.borderTessFactor. ; )else if(bTf.y != 0.0f && p.x == 0.0f)( // left edgeVertInd = p.y * Tri.tessFactor; edgeVec = Tri.vec2; startPos = Tri.startPos; neibTessFactor = (uint)Tri. borderTessFactor.y; )else if(bTf.z != 0.0f && p.y == gridSize.y)( // top edgeVertInd = p.x * Tri.tessFactor; edgeVec = Tri.vec1; startPos = Tri.startPos + Tri.vec2 * (gridStep.x * gridSize.x);neibTessFactor = (uint)Tri.borderTessFactor.z; )else if(bTf.w! .tessFactor;edgeVec = Tri.vec2; startPos = Tri.startPos + Tri.vec1 * (gridStep.x * gridSize.x); neibTessFactor = (uint) Tri.borderTessFactor.w;
Далі нам потрібно знайти індекси для V1 та V2. Уявіть, що у вас є число 3. Вам потрібно знайти два найближчих числа, кратних двом. Для цього ви обчислюєте залишок від поділу трьох на два - він дорівнює одиниці. Потім ви віднімаєте або додаєте цей залишок до трьох і отримуєте необхідний результат. Також з індексами тільки замість двох у нас буде співвідношення коефіцієнтів тесселяції рівнів деталізації. Тобто якщо у третього рівня коефіцієнт дорівнює 16, а у другого 2, то співвідношення дорівнюватиме 8. Тепер, щоб отримати висоти, спершу треба отримати відповідні точки на сфері, нормалізувавши точки на межі. Початок та напрямок ребра ми вже підготували - залишилося обчислити довжину вектора від V1 до V2. Так як довжина ребра осередку оригінальної сітки дорівнює gridStep.x, то потрібна нам довжина дорівнює gridStep.x/Tri.tessFactor. Потім за точками на сфері ми отримаємо висоту, як було розказано раніше.

Float GetNeibHeight(float3 EdgeStartPos, float3 EdgeVec, float VecLen, float3 NormOffset) (float3 neibPos = EdgeStartPos + EdgeVec * VecLen; neibPos = normalize(neibPos); tessFactor; uint tessRatio=(uint)tessFactor/(uint)neibTessFactor; uint ind = (uint) edgeVertInd % tessRatio; uint leftNeibInd = (uint)edgeVertInd - ind; float leftNeibHeight = GetNeibHeight(startPos, edgeVec, vertOffset * leftNeibInd, normOffset); uint rightNeibInd = (uint)edgeVertInd + ind; float rightNeibHeight = GetNeibHeight(startPos, edgeVec, vertOffset * rightNeibInd, normOffset);
Ну і останній компонент - фактор F. Його ми отримаємо розділивши залишок від поділу на співвідношення коефіцієнтів (ind) на співвідношення коефіцієнтів (tessRatio)

Float factor = (float)ind / (float)testRatio;
Завершальний етап - лінійна інтерполяція висот та отримання нової вершини

Float avgHeight = lerp(leftNeibHeight, rightNeibHeight, factor); posL = sphPos * (sphereRadius + avgHeight);
Також може з'явитися тріщина в місці, де межують сектори з текстурними координатами ребер, рівними 1 або 0. У цьому випадку я беру середнє значення між висотами для двох координат:

Float GetHeight(float2 TexCoords) (float2 texCoords2 = TexCoords * texCoordsScale; float mHeight = mainHeightTex.SampleLevel(mainHeightTexSampler, TexCoords, 0).x; float dHexTex dHeight) * maxTerrainHeight; ) float GetHeight(float3 SphPos, float3 NormOffset) ( float2 texCoords1 = GetTexCoords(SphPos, NormOffset); float height = GetHeight(texCoords1); ; float2(0.0f, texCoords1.y));return lerp(height, height2, 0.5f); ;return lerp(height, height2, 0.5f); )else return height;

11. Обробка на GPU

Давайте перенесемо обробку секторів на GPU. У нас буде два Compute шейдери - перший виконає відсікання по піраміді видимості та визначить рівень деталізації, другий отримає граничні коефіцієнти тесселяції для усунення тріщин. Поділ на два етапи потрібний тому, що як і у випадку з CPU, ми не можемо корректно визначити сусідів для секторів доти, доки не зробимо відсікання. Так як обидва шейдери будуть використовувати дані рівнів деталізації та працювати з секторами, я ввів дві загальні структури: Sector та Lod

Struct Sector ( float3 vec1, vec2; float3 startPos; float3 normCenter; int adjacency; float borderTessFactor; int lod; ); struct Lod ( RangeF dotRange; float tessFactor; float padding; float4 color; );
Ми будемо використовувати три основні буфери - вхідний (містить початкову інформацію про сектори), проміжний (в ньому знаходяться дані секторів, отриманих в результаті роботи першого етапу) і підсумковий (Передаватиметься на малювання). Дані вхідного буфера не будуть змінюватися, тому в полі Usage структури D3D11_BUFFER_DESC розумно використовувати значення D3D11_USAGE_IMMUTABLE Ми просто запишемо в нього дані всіх секторів з єдиною різницею, що для даних суміжності ми використовуватимемо індекси секторів, а не покажчики на них. Для індексу рівня деталізації та граничних коефіцієнтів тесселяції встановимо нульові значення:

Static const size_t sectorSize = sizeof(Vector3) + //vec1 sizeof(Vector3) + //vec2 sizeof(Point3F) + //normCenter sizeof(Point3F) + //startPos sizeof(Point4) + //adjacency sizeof(Vector4) + //borderTessFactor sizeof(int32_t);//lod size_t sectorsDataSize = sectors.GetSectors().size() * sectorSize; std::vector sectorsData(sectorsDataSize); char* ptr = const Sector* firstPtr = §ors.GetSectors(); for(const Sector &sec: sectors)( Utils::AddToStream (ptr, sec.GetVec1()); Utils::AddToStream (ptr, sec.GetVec2()); Utils::AddToStream (ptr, sec.GetStartPos()); Utils::AddToStream (ptr, sec.GetNormCenter()); Utils::AddToStream (ptr, sec.GetAdjacency() - firstPtr); Utils::AddToStream (ptr, sec.GetAdjacency() - firstPtr); Utils::AddToStream (ptr, sec.GetAdjacency() - firstPtr); Utils::AddToStream (ptr, Vector4()); Utils::AddToStream (ptr, 0); ) inputData = Utils::DirectX::CreateBuffer(§orsData,//Raw data sectorsDataSize,//Buffer size D3D11_BIND_SHADER_RESOURCE,//bind flags D3D11_USAGE_IMMUTABLE,//usage 0,//CPU //structure byte stride
Тепер кілька слів про проміжний буфер. Він гратиме дві ролі - вихідного для першого шейдера і вхідного для другого, тому ми вкажемо в полі BindFlags значення D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE. Також створимо для нього два відображення UnorderedAccessView, яке дозволить шейдеру записувати в нього результат роботи і ShaderResourceView, за допомогою якого ми будемо використовувати буфер як вхідний. Розмір його буде таким самим, як у раніше створеного вхідного буфера

UINT miscFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; intermediateData = Utils::DirectX::CreateBuffer(sectors.GetSectors().size() * sectorSize,//Buffer size miscFlags, D3D11_USAGE_DEFAULT,//usage 0,//CPU access flags D3D11_RESOURCE_MI /structure byte stride intermediateUAW = Utils::DirectX::CreateUnorderedAccessView(intermediateData, D3D11_BUFFER_UAV(0, sectors.GetSectors().size(), 0)); intermediateSRV = Utils::DirectX::CreateShaderResourceView(intermediateData, D3D11_BUFFEREX_SRV(0, sectors.GetSectors().size(), 0));
Далі я наведу основну функцію першого шейдера:

СтруктурованийБуфер inputData: register(t0); RWStructuredBuffer outputData: register(u0); Process(int3 TId: SV_DispatchThreadID) ( int ind = TId.x; Sector sector = inputData; float dotVal = dot(toWorldPos, sector.normCenter); if(dotVal< dotRange.minVal || dotVal >dotRange.maxVal)( outputData = sector; return; ) if(!IsVisible(sector.normCenter))( outputData = sector; return; ) for(int l = 0; l< 4; l++){ Lod lod = lods[l]; if(dotVal >= lod.dotRange.minVal && dotVal<= lod.dotRange.maxVal) sector.lod = l + 1; } outputData = sector; }
Після обчислення скалярного твору ми перевіряємо, чи сектор знаходиться у потенційно видимій області. Далі ми уточнюємо факт його видимості за допомогою виклику IsVisible(), який ідентичний виклику Frustum::TestSphere(), показаному раніше. Робота функції залежить від змінних worldView, sphereRadius, frustumPlanesPosV і frustumPlanesNormalsV, значення яких потрібно передати в шейдер заздалегідь. Далі ми визначаємо рівень деталізації. Зверніть увагу, що індекс рівня ми вказуємо від одиниці - це потрібно для того, щоб на другому етапі відкинути ті сектори, рівень деталізації яких дорівнює нулю.

Тепер нам потрібно підготувати буфер для другого етапу. Ми хочемо використовувати буфер як вихідний у Compute шейдера і вхідний для теселятора - для цього нам потрібно вказати в полі BindFlags значення D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_VERTEX_BUFFER. Нам доведеться працювати з даними буфера безпосередньо, тому вкажемо в полі MiscFlags значення D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS Для відображення такого буфера ми будемо використовувати значення DXGI_FORMAT_R32_TYPELESS у полі Flags, а в полі NumElements

Size_t instancesByteSize = instanceByteSize * sectors.GetSectors().size(); outputData = Utils::DirectX::CreateBuffer(instancesByteSize, D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0, D3D11_RESOURCE_MISC_BUFFER; D3D11_BUFFER_UAV uavParams = (0, instancesByteSize / 4, D3D11_BUFFER_UAV_FLAG_RAW); outputUAW = Utils::DirectX::CreateUnorderedAccessView(outputData, uavParams, DXGI_FORMAT_R32_TYPELESS);
Нам також буде потрібно лічильник. З його допомогою ми здійснимо адресацію пам'яті в шейдері і використовуємо його кінцеве значення в аргументі instanceCount виклику DrawIndexedInstanced(). Лічильник я реалізував у вигляді буфера розміром 16 байтів. Також при створенні відображення у полі Flags поля D3D11_BUFFER_UAV я використав значення D3D11_BUFFER_UAV_FLAG_COUNTER

Counter = Utils::DirectX::CreateBuffer(sizeof(UINT), D3D11_BIND_UNORDERED_ACCESS, D3D11_USAGE_DEFAULT, 0, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED, 4); D3D11_BUFFER_UAV uavParams = (0, 1, D3D11_BUFFER_UAV_FLAG_COUNTER); counterUAW = Utils::DirectX::CreateUnorderedAccessView(counter, uavParams);
Настав час навести код другого шейдера

СтруктурованийБуфер inputData: register(t0); RWByteAddressBuffer outputData: register(u0); RWStructuredBuffer counter: register(u1); Process(int3 TId: SV_DispatchThreadID) ( int ind = TId.x; Sector sector = inputData; if(sector.lod != 0)( sector.borderTessFactor = GetNeibTessFactor(sector, 0); //Bottom sector.borderTessFactor (sector, 1);//Left sector.borderTessFactor = GetNeibTessFactor(sector, 2); ; outputData.Store(c * dataSize + 0, asuint(sector.startPos.x)); , asuint(sector.startPos.z)); outputData.Store(c * dataSize + 12, asuint(sector.vec1.x)); ; outputData.Store(c * dataSize + 20, asuint(sector.vec1.z)); , asuint(sector.vec2.y));outputData.Store(c * dataSize + 32, asuint(sector.vec2.z));outputData.S tore(c * dataSize + 36, asuint(sector.borderTessFactor)); outputData.Store(c * dataSize + 40, asuint(sector.borderTessFactor)); outputData.Store(c * dataSize + 44, asuint(sector.borderTessFactor)); outputData.Store(c * dataSize + 48, asuint(sector.borderTessFactor)); outputData.Store(c * dataSize + 52, asuint(sector.lod)); )
Код функції GetNeibTessFactor() практично ідентичний її CPU аналогу. Єдина відмінність у тому, що ми використовуємо індекси сусідів, а не вказівники на них. Буфер outputData має тип RWByteAddressBuffer, для роботи з ним ми використовуємо метод Store(in uint address, in uint value). Значення змінної dataSize дорівнює розміру даних вершини з класом D3D11_INPUT_PER_INSTANCE_DATA, Опис вершини можна переглянути у розділі 10. Загалом це традиційна для C/С++ робота з покажчиками. Після виконання двох шейдерів ми можемо використовувати outputData як InstanceBuffer. Процес малювання виглядає так

Utils::DirectX::SetPrimitiveStream((vb, outputData), ib, (vertexSize, instanceByteSize), D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST); DeviceKeeper::GetDeviceContext()->CopyStructureCount(indirectArgs, 4, counterUAW); Shaders::Apply(terrainShaders, [&]() ( DeviceKeeper::GetDeviceContext()->DrawIndexedInstancedIndirect(indirectArgs, 0); )); Utils::DirectX::SetPrimitiveStream((nullptr, nullptr), nullptr, (0, 0));
За більш детальною інформацією про методи DrawIndexedInstancedIndirect() та CopyStructureCount() звертайтеся до додатка 2

12. Камера

Напевно, вам відомо, як подивитися модель простої FPS (First Person Shooter) камери. Я дію за таким сценарієм:
  • 1. З двох кутів отримую вектор напряму
  • 2. за допомогою вектора напрямку та вектора (0, 1, 0) отримую базис
  • 3. згідно з вектором напрямку та вактором вправо, отриманим у п.2 змінюю позицію камери

У нашому випадку ситуація дещо ускладнюється - по-перше, ми повинні рухатися щодо центру планети, по-друге, при побудові базису замість вектора (0, 1, 0) ми повинні використовувати нормаль сфери в точці, якою зараз перебуваємо. Щоб досягти бажаних результатів, я використовуватиму два базиси. Згідно з першим змінюватиметься позиція, другий описуватиме орієнтацію камери. Базиси взаємозалежні, але першим я обчислюю базис позиції, тож почну з нього. Припустимо, що у нас є початковий базис позиції (pDir, pUp, pRight) і вектор напряму vDir, яким ми хочемо просунутися на деяку відстань. Насамперед нам треба обчислити проекції vDir на pDir та pRight. Склавши їх, ми отримаємо оновлений вектор напряму (рис.21).


Рис.21 Наочний процес отримання projDir

Де P це позиція камери, mF і mS - коефіцієнти, отже скільки нам необхідно просунутися вперед чи вбік.

Ми не можемо використовувати PN як нову позицію камери, тому що PN не належить сфери. Натомість ми знаходимо нормаль сфери в точці PN, і ця нормаль буде новим значенням вектора вгору. Тепер ми можемо сформувати оновлений базис

Vector3 nUp = Vector3::Normalize(PN - spherePos); Vector3 nDir = projDir Vector3 nRight = Vector3::Normalize(Vector3::Cross(pUp, pDir))
де spherePos - центр сфери.

Нам треба зробити так, щоб кожен із його векторів був ортогональним по відношенню до двох інших. Відповідно до властивості векторного твору nRight задовольняє цю умову. Залишилося досягти того ж для nUp і nDir. Для цього спроектуємо nDir на nUp і віднімемо вектор, що вийшов, від nDir (рис.22)


Рис.22 Ортогоналізація nDir по відношенню до nUp

Ми могли б зробити те саме з nUp, але тоді він змінив би свій напрямок, що в нашому випадку неприйнятно. Тепер нормалізуємо nDir та отримаємо оновлений ортонормований базис напрямку.

Другим ключовим етапом є побудова базису орієнтації. Основну складність становить отримання вектора напрямку. найбільш підходяще рішення - перевести точку з полярним кутом a, азимутним кутом b і відстанню від початку координат рівним одиниці зі сферичних координат в декартові. Тільки якщо ми здійснимо такий перехід для точки з полярним кутом, що дорівнює нулю, то отримаємо вектор, що дивиться вгору. Нам це не зовсім підходить, тому що ми інкрементуватимемо кути і припускаємо, що такий вектор буде дивитися вперед. Банальне зміщення кута на 90 градусів вирішить проблему, але елегантніше буде скористатися правилом зміщення кута, яке свідчить, що

Так і зробимо. У результаті у нас виходить таке

Де a – полярний кут, b – азимутний кут.

Цей результат нам не зовсім підходить – нам потрібно побудувати вектор напряму щодо базису позиції. Давайте перепишемо рівняння для vDir:

Все, як у космонавтів - у цьому напрямку стільки, тому стільки. Тепер має бути очевидним, що якщо ми замінимо вектори стандартного базису на pDir, pUp та pRight, то отримаємо потрібний нам напрямок. Ось так

Можна уявити те саме у вигляді матричного множення

Вектор vUp спочатку дорівнюватиме pUp. Обчисливши векторний твір vUp та vDir, ми отримаємо vRight

Тепер ми зробимо так, щоб vUp був ортогональним по відношенню до інших векторів базису. Принцип той же, що і при роботі з nDir

З базисами розібралися – лишилося вирахувати позицію камери. Це робиться так

Де spherePos - центр сфери, sphereRadius - радіус сфери і height - висота над поверхнею сфери. Наведу код роботи описаної камери:

Float moveFactor = 0.0f, sideFactor = 0.0f, heightFactor = 0.0f; DirectInput::GetInsance()->ProcessKeyboardDown(( ( (DIK_W, [&]()(moveFactor = 1.0f;)), (DIK_S, [&]()(moveFactor = -1.0f;)), (DIK_D, [ &]()(sideFactor = 1.0f;)), (DIK_A, [&]()(sideFactor = -1.0f;)), (DIK_Q, [&]()(heightFactor = 1.0f;)), (DIK_E , [&]()(heightFactor = -1.0f;)) )); if(moveFactor != 0.0f || sideFactor != 0.0f)( Vector3 newDir = Vector3::Normalize(pDir * Vector3::Dot(pDir, vDir) + pRight * Vector3::Dot(pRight, vDir))); newPos = pos + (newDir * moveFactor + pRight * sideFactor) * Tf * speed; pDir = newDir; pUp = Vector3::Normalize(newPos - spherePos); );pDir = Vector3::Normalize(pDir - pUp * Vector3::Dot(pUp, pDir));pos = spherePos + pUp * (sphereRadius + height);angles.x = 0.0f; f)( height = Math::Saturate(height + heightFactor * Tf * speed, heightRange); pos = spherePos + pUp * (sphereRadius + height); ) DirectInput::MouseState ); if(mState.x != 0 || mState.y != 0 || moveFactor != 0.0f || sideFactor != 0.0f)( if(mState.x != 0) angles.x = angles.x + mState .x / 80.0f; if(mState.y != 0) angles.y = Math::Saturate(angles.y + mState.y / 80.0f, RangeF(-Pi * 0.499f, Pi * 0.499f)); vDir = Vector3::Normalize(pRight * sinf(angles.x) * cosf(angles.y) + pUp * -sinf(angles.y) + pDir * cosf(angles.x) * cosf(angles.y)); vUp = pUp; vRight = Vector3::Normalize(Vector3::Cross(vUp, vDir)); vUp = Vector3::Normalize(vUp - vDir * Inverse(((vRight, 0.0f), (vUp, 0.0f), (vDir, 0.0f), (pos, 1.0f)));
Зверніть увагу, що ми обнулюємо angles.x після того, як оновили базис позиції. Це дуже важливо. Давайте уявимо, що ми одночасно змінюємо кут огляду та переміщуємося по сфері. Спершу ми спроектуємо вектор напряму на pDir та pRight, отримаємо зсув (newPos) і на його основі оновимо базис позиції. Також спрацює друга умова, і ми почнемо оновлювати базис орієнтації. Але так як pDir і pRight вже були змінені в залежності від vDir, то без скидання азимутного кута (angles.x) поворот буде більш «крутим»

Висновок

Я дякую читачеві за виявлений інтерес до статті. Сподіваюся, що інформація, в ній викладена, була йому доступна, цікава та корисна. Пропозиції та зауваження можете надсилати мені поштою [email protected]або залишати у вигляді коментарів.

Бажаю вам успіху!

Додаток 1

поле InstanceDataStepRate містить інформацію про те, скільки разів малювати дані D3D11_INPUT_PER_VERTEX_DATA для одного елемента D3D11_INPUT_PER_INSTANCE_DATA. У нашому прикладі все просто – один до одного. «Але навіщо нам малювати одне й теж кілька разів?» - Запитайте ви. Розумне питання. Вірменське радіо відповідає – припустимо, у нас є 99 куль трьох різних кольорів. Ми можемо описати вершину таким чином:

UINT colorsRate = 99/3; std::vector meta = ( ("POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0), ("NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0), ("TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0), ("WORLD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("WORLD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("WORLD", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("WORLD", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1), ("COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 2, 0, D3D11_INPUT_PER_INSTANCE_DATA, colorsRate), );
Зверніть увагу, що вершина збирається з трьох джерел, причому дані останнього оновлюються раз на 33 інстанси. У результаті ми отримаємо 33 інстанси першого кольору, ще 33 – другого тощо. Тепер створимо буфери. Причому, оскільки кольори не змінюватимуться, буфер із квітами можемо створити з прапором D3D11_USAGE_IMMUTABLE. Це означає, що після того, як буфер буде ініціалізований, тільки GPU матиме доступ до його даних, при чому тільки для читання. Ось код створення буферів:

MatricesTb = Utils::DirectX::CreateBuffer(sizeof(Matrix4x4) * 99, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); colorsTb = Utils::DirectX::CreateBuffer(colors, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE, 0);
далі по потребі оновлюємо буфер із матрицями (я використовую функції своєї бібліотеки - сподіваюся, що все буде ясно)

Utils::DirectX::Map (matricesTb, [&](Matrix4x4 *Data) ( //спочатку записуємо в буфер дані для куль першого кольору //потім для другого і т.д. Зверніть увагу, що потрібну відповідність //даним кольорам потрібно забезпечити на етапі формування даних буфера ));
Доступ до даних у шейдері можна реалізувати також, як я описав раніше


Додаток 2

На відміну від DrawIndexedInstanced() виклик DrawIndexedInstancedIndirect() приймає як аргумент буфер, який містить всю інформацію, яку ви використовуєте для виклику DrawIndexedInstanced(). Причому створювати цей буфер треба з прапором D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS. Ось приклад створення буфера:

//indicesCnt - кількість індексів, яку ми хочемо відобразити //instancesCnt - кількість "інстансів", яку ми хочемо відобразити std::vector args = ( indicesCnt, //IndexCountPerInstance instancesCnt,//InstanceCount 0,//StartIndexLocation 0,//BaseVertexLocation 0//StartInstanceLocation ); D3D11_BUFFER_DESC bd = (); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(UINT) * args.size(); bd.BindFlags = 0; bd.CPUAccessFlags = 0; bd.MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; bd.StructureByteStride = 0; ID3D11Buffer* buffer; D3D11_SUBRESOURCE_DATA initData = (); initData.pSysMem = HR(DeviceKeeper::GetDevice()->CreateBuffer(&bd, &initData, &buffer)); приклад виклику DrawIndexedInstancedIndirect(): DeviceKeeper::GetDeviceContext()->DrawIndexedInstancedIndirect(indirectArgs, 0);
Другим аргументом ми передаємо зміщення в байтах від початку буфера, з якого потрібно починати читати дані. Як це можна використати? Наприклад, при реалізації відсікання невидимої геометрії на GPU. Загалом хронологія така - спершу в Compute шейдері ми заповнюємо AppendStructuredBuffer, що містить дані видимої геометрії. Потім за допомогою CopyStructureCount() ми встановлюємо значення кількості «інстансів», які хочемо відобразити рівною кількістю записів у цьому буфері і викликаємо DrawIndexedInstancedIndirect()


Додаток 3

Давайте припустимо, що значення координати х дорівнює результату функції X з аргументом a, а значення координати z - результату функції Z з тим самим аргументом:

Тепер нам потрібно для кожної функції обчислити похідну. По суті, похідна функції у заданій точці дорівнює швидкості зміни значень функції саме у цій точці. Відповідно до правил диференціювання тригонометричних функцій:

Що в результаті дає нам той самий результат:

Чому ми можемо використовувати значення швидкості як компоненти вектора напряму? Я це розумію так. Уявіть, що ми маємо векторну функцію (для t >= 0):

Обчислимо похідну координати X

Тепер для Y

У нас вийшло, що вектор швидкості дорівнює (2, 3), тепер знайдемо початкову точку

Через війну функцію P(t) ми можемо висловити так:

Що простими словами можна описати як "точка рухається від початку з координатами (3, 2) на t за напрямом (2, 3)". Тепер давайте інший приклад:

Знову обчислимо похідну координати X

І для координати Y

Тепер вектор швидкості змінюється залежно аргументу. У цьому випадку простими словами ситуацію можна описати так: «Точка рухається від початку з координатами (3, 2), і напрямок її руху постійно змінюється».


Додаток 4

Давайте визначимо функцію F(H), яка прийматиме висоту в області та повертатиме значення від 0 до 1, де F(Hmin) = 0 та F(Hmax) = 1. Розв'язавши системи рівнянь

Я отримав

В результаті цього функція F набуває вигляду

Тепер нам потрібна функція, яка набирає коефіцієнт висоти від 0 до 1 і повертає мінімальне значення для скалярного твору. Нам треба врахувати, що чим ближче спостерігач до поверхні – тим воно більше. Виходить наступне рівняння:

Розкриємо дужки

Спростимо та отримаємо

Тепер висловимо D(F(H)) та отримаємо

Теги:

  • directx11
  • terrain render
Додати теги

ЛАНДШАФТ АНТРОПОГЕННИЙ - ландшафт, властивості якого зумовлені діяльністю людини (див. також Ландшафт техногенний). За співвідношенням цілеспрямованих та ненавмисних змін розрізняють навмисно змінені та ненавмисно змінені ландшафти. е.. Гадач запропонував за першими зберегти назву «антропогенних», а другі називати «антропічними». Розрізняють також культурний ландшафт (свідомо змінений господарською діяльністю людини для задоволення своїх потреб і постійно підтримується в потрібному для нього стані) і акультурний, що виникає в результаті нераціональної діяльності або несприятливих впливів сусідніх ландшафтів (крайнім членом у цьому ряду є деградований ландшафт). .]

Зміна рівня ґрунтових вод в результаті їх техногенного спрацювання або підйому здатна пожвавити гравітаційні геологічні процеси -зсуви, спливини, оврагоутворення з негативними геоекологічними наслідками, зі зміною ландшафту та умов проживання живих організмів.

Догляд за ландшафтом - планомірне підтримання та множення природних цінностей ландшафту, у якому успішно виконуються покладені нею соціально-економічні функції. Основна мета – попередження небажаних змін ландшафту в умовах його інтенсивного використання (особливо для курортних та лікувально-оздоровчих територій). Догляд включає санітарні рубання лісу, прибирання сміття, лісовідновлення та ін Догляд за ландшафтом є однією з форм регулювання процесів з метою збереження екологічної рівноваги і важливим елементом охорони. Тут доречні слова І. В. Гете: «Думати і діяти, діяти і думати - ось підсумок усієї мудрості... Те й інше, як видих і вдих, має завжди чергуватись, як питання і відповідь, одне не повинно бути без іншого» .[...]

Поліпшення ландшафтів - система заходів, спрямованих на зміну ландшафтів з метою формування або вдосконалення сприятливих, з точки зору людини, властивостей ландшафтів як ресурсовідтворювальних і середотворчих систем і як умов діяльності. У. л. включає рекультивацію, меліорацію, оздоровлення ландшафтів та ін.

Під негативними змінами в природному середовищі тут маються на увазі порушення природних структур і зв'язків угруповань живих організмів, деструктивні зміни ландшафтів і біогеохімічних процесів, що протікають в природі, порушення екологічних рівноваг і т.п., під погіршенням здоров'я людей - виникнення різноманітних патологічних явищ і захворювань , включаючи і захворювання з летальним результатом, причиною яких є шкідливі впливи техногенного та природного характеру.

Загалом на півночі зміни ландшафтів та ґрунтів були значними. Після періоду похолодання (пізній дріас) на початку голоцену пройшло різке потепління, що супроводжувалося деградацією льодовиків та мерзлоти. Під час кліматичного оптимуму голоцену 8-5 т. л. Полярний басейн був вільний від льодів, а багаторічна мерзлота на прилеглих до нього територіях протаяла на 100-200 м (Ігнатенко, 1979). Даних з еволюції грунтів тундри небагато.

РОЗВИТОК (еволюція) ЛАНДШАФТА - вища ланка в ланцюзі понять, що характеризують різні типи змін ландшафтів: функціонування - динаміка - розвиток. Р.Л. супроводжується незворотними поступальними змінами, що призводять до зміни структури ландшафту, заміни одного інваріанту ін. Р.Л. обумовлено як змінами зовнішніх факторів (активізація тектонічних рухів, морські трансгресії), так і внутрішніми причинами (саморозвиток ландшафту).

Корінні (первинні) ландшафти - це зональні типи ландшафту, які не зазнали прямого впливу господарської діяльності, тобто практично не трансформовані. У деяких випадках на них можуть вплинути локальні фактори господарювання у минулому чи сьогоденні, що не призводять, однак, до якісних змін ландшафту. Тому правильніше називати ці типи ландшафтів умовно корінними.

Як створювалося зрушення у зміні ландшафту гірськими розробками та відбувалося переключення на планове будівництво нового культурного землекористування, можна простежити у практичних справах гірничодобувних підприємств та, зокрема, Камиш-Бу-рунського залізорудного комбінату на Керченському півострові. Цей комбінат, що включає рудник, збагачувальну та агломераційну фабрики, був побудований і вступив в дію діючих підприємств у 1940 р. Під час Великої Вітчизняної війни він був зруйнований і відновлений в 1950 [...]

Початок антропогенної зміни середовища в районі Куликова поля відноситься до XII-XIV ст. У разі запустіння, в Х ОСУП ст., мав місце етап відновлення ландшафтів. Наприкінці XVII ст. починається основний етап зміни ландшафтів і ґрунтів лісостепу (вирубування лісів та оранка), що охоплює останні 300 років (Олександрівський та ін., 1996). Протягом XVIII ст. Залісненість території знизилася на 30-50% (Цвєтков, 1957). Вона продовжувала знижуватися надалі, що свідчать старі карти XVIII - початку XX ст. У західних районах лісостепу землеробство виникло набагато раніше (Краснов, 1971). Олександрівський, Жаріков, 1991). На місці зведених лісів в першу чергу поширюється лугово-степова рослинність, і сірі лісові грунти починають трансформуватися у бік чорноземів через накопичення гумусу та вплив степових гризунів-землероїв (суслики, сліпаки та ін.). Землеробство довгий час не вело до деградації ґрунтів, воно було переложнозависимым з перервами, під час яких розвивалися лугово-степові біоми. Все це сприяло розвитку процесу проградації ґрунтів (протилежного процесу деградації під лісом), що йде у напрямку від сірих лісових ґрунтів до темно-сірих, чорноземів опідзолених, вилужених і переритих (Олександровський, 1987, 1990).

Грунт непорушений. НЕЗворотне ЗМІНА ЛАНДШАФТУ - зміни в ландшафті, що ведуть до порушення екологічної рівноваги і, як наслідок, до зміни інваріанту ландшафту або його деградації.

Під впливом розуміється будь-яка зміна природної чи антропологічної рівноваги (вплив транспорту на повітряне середовище, забруднення води, ґрунту, флори та фауни, шумове та електромагнітне забруднення), зміна ландшафту тощо [...]

Разом взяті ці властивості антропогенно змінених ландшафтів визначають диференційовану реакцію живих організмів на нові умови і лежать в основі антропогенних сукцесій перетворюваних людиною екосистем.

При критичній ситуації виникають значні та слабокомпенсовані зміни ландшафтів, відбувається швидке наростання загрози виснаження або втрати природних ресурсів (в т.ч. генофонду), унікальних природних об'єктів, спостерігається стійке зростання кількості захворювань через різке погіршення умов проживання. Антропогенні навантаження, як правило, перевищують встановлені нормативні величини та екологічні вимоги. При зменшенні або припиненні антропогенних впливів та проведенні природоохоронних заходів можлива нормалізація екологічної обстановки, покращення умов проживання населення, підвищення якості окремих природних ресурсів та часткове відновлення ландшафтів.

Безпосередньою причиною появи, посилення чи ослаблення процесів зміни ландшафтів та ґрунтів є зміна теплового балансу на денній поверхні. Часткове порушення або повне видалення рослинного покриву в зоні тундри збільшує радіаційний баланс поверхні на 5-15 %, що спричинює підвищення середньорічної температури на 0,7 -2,0 ° С та зростання глибини літнього протаювання в 2 - 3 рази. Інтенсивність техногенних порушень теплового балансу ґрунтів та ґрунтів у кількісному відношенні на кілька порядків більша, ніж при природних його змінах.

Наслідки впливу газової промисловості на літосферу різноманітні: зміна ландшафту (земляні роботи, система очищення промивного розчину, забудова, переміщення вантажів волоком), вирубування лісів, забруднення ґрунту нафтопродуктами, руйнування пластів надр та ін.

У зоні степів та частково лісостепів відповідно до цих співвідношень відзначено переважання змінених ландшафтів над природними та природно-антропогенними, яке свідчить про можливість виникнення небезпечних для людини несприятливих процесів та явищ незворотного характеру, пов'язаних із підвищеним антропогенним навантаженням.

Палепідґрунтові та палеоботанічні дані показують, що основні зміни педогенезу та ландшафтів на переході пізньолідника до голоцену визначалися змінами температур. У голоцені тренди зміни ландшафтів і грунтів, крім північних широт, були зумовлені головним чином зміною зволоженості клімату.

ПІДХІД ІСТОРИЧНИЙ - загальнонауковий підхід, що передбачає, що сучасний і майбутній стан ландшафтів тією чи іншою мірою визначено процесами і змінами, що відбувалися раніше. Вивчення історії ландшафтів дозволяє виявити їх змінні та стійкі стани, циклічність чи спрямованість змін, тенденції розвитку, роль зовнішніх та внутрішніх факторів у зміні ландшафту. За методикою розрізняють дві групи історичних досліджень ландшафтів: палеогеографічні (за викопними залишками компонентів ландшафту, механічним складом і структурою відкладень, залишками організмів, викопними ґрунтами, накопиченнями органічних і відсталих речовин тощо) і власне історичні (за археологічними знахідками та письмовими документами) ).

У попередньому розділі розглянуто по суті дві великі категорії антропогенних впливів: а) зміна ландшафтів та цілісності природних комплексів; і б) вилучення природних ресурсів. Ця глава присвячена техногенному забруднення екосфери та довкілля людини. Техногенне забруднення середовища є найбільш очевидним та швидкодіючим негативним причинним зв'язком у системі екосфери: «економіка, виробництво, техніка, середовище». Воно зумовлює значну частину природоємності техносфери та призводить до деградації екологічних систем, глобальних кліматичних та геохімічних змін, до поразок людей. На запобігання забруднення природи та навколишнього середовища спрямовані основні зусилля прикладної екології.

Але в складі екосистем, що піддаються антропогенному впливу, завжди є види, що отримують у змінених ландшафтах достатні можливості для реалізації екологічних вимог до середовища, а в ряді випадків навіть певні переваги. Такі види зустрічаються в культурних ландшафтах більшою кількістю, а часом повністю поривають зв'язки з вихідними спільнотами. Так формуються екосистеми сільськогосподарських ландшафтів, населених пунктів, зон відпочинку і т. п., що включають широке коло видів аж до синантроп-тварин, спрямовано еволюціонують по лінії зв'язку з людиною і в даний час майже не зустрічаються поза сферою впливу його діяльності. .]

Поряд із прямим впливом людство всіма формами своєї діяльності неминуче вносить непрямі зміни до складу та умов існування природних спільнот. Розвиток транспорту та зв'язку, грандіозні масштаби гідротехнічного будівництва та меліоративних робіт, суттєві, якщо не катастрофічні, зміни ландшафтів, а також індустріалізація сільського господарства – все це незалежно від бажання людини докорінно змінює умови існування оточуючих її екосистем та окремих видів живих організмів. Реакція живого «населення» Землі на ці зміни в принципі ґрунтується на основоположних механізмах організмового, популяційного та біоценотичного рівнів, які вже були розглянуті вище. У цілому нині ці механізми визначають розвиток екосистем за умов наростаючого антропогенного стресу, а знання цих механізмів дозволяє прогнозувати напрям формування стійких і продуктивних співтовариств і створюваних культурних ландшафтів.

Рекреаційне навантаження, що розглядається в нашому випадку, це ступінь безпосереднього впливу людей (відвідувачів) на конкретний ландшафт, виражена їх кількістю на одиниці площі в певний проміжок часу. Розрізняють навантаження оптимальні та деструкційні (згубні), які визначаються ступенем впливу на екосистему: від слабкої, що не призводить до суттєвих змін ландшафту, до фази катастрофи, в період якої екосистема остаточно руйнується.

Недоцільно на великій протязі дороги створювати декоративне озеленення одного типу. Потрібно змінювати типи посадок відповідно до зміни ландшафту. Чергування та періодична поява нових типів насаджень сприяє більш чіткому та рельєфному сприйняттю навколишнього простору під час руху. Протяжність окремих посадок слід призначати так, щоб проїжджаючий спостерігав їх зміну через 2... 5 хв (при середній швидкості руху транспортного потоку 60...70 км/год це відповідає 2,5...3,5 км). Правилами озеленення передбачено, щоб характер озеленення змінювався не частіше ніж через 2...3 км і не рідше ніж через 10 км.

З використанням структурних "чисел" відомого грецьким архітектором С.А. Доксіадіса (Реймерс, 1985), що враховують співвідношення природних та антропогенно змінених ландшафтів, ідеальна структура категорій та видів земель на освоєних територіях має виглядати такою: землі сільськогосподарського призначення, включаючи населені пункти – 22,5%; промисловість, транспорт – 2,5%, лісового фонду 18%; державного запасу, заповідників, національних парків, регульованих рекреаційних зон – 57%. Ця структура сильно відрізняється від сформованої в Московській області, де землі сільськогосподарського призначення займають 46,7%, міст і населених пунктів - 4,8%, промисловості та транспорту - 8,3%, лісового фонду - 39,4%, державного запасу - 0,8%. Насамперед, в області потрібно значно зменшити площу сільськогосподарських, промислових і транспортних земель і збільшити площу територій, що особливо охороняються. Тільки така збалансована структура землекористування значно покращить екологічний стан Московської області.

При створенні степових заповідників з огляду на їх кластерний характер ландшафтний ряд заповідних ділянок може відображати як зональні, так і провінційні зміни ландшафтів.

Екологічні наслідки аварій і катастроф, в більшості випадків, не обмежуються забрудненням навколишнього середовища і змінами, що відбуваються потім з цієї причини. Вони також значною мірою, а іноді і в основному, обумовлюються впливом термобаричних полів, гідродинамічних хвиль і потоків, інших факторів, що виникають при вибухах, пожежах та інших проявах техногенних аварій і катастроф. При такого роду впливах на довкілля екологічні наслідки можуть виражатися в дуже різких і великих за масштабами змінах довкілля людини. Вони пов'язані з руйнуванням життєзабезпечених структурних елементів територіально-виробничих комплексів та інших природно-господарських утворень, деструктивною зміною ландшафтів та екосистем тощо [...]

Процес синантропізації - поступовий та досить тривалий. Починається він із переважного поселення представників будь-якого виду в антропогенно змінених ландшафтах. Відомо, наприклад, що в Європі ряд видів птахів (чорний та співочий дрозди, вяхир, кільчаста горлиця та ін.) у деревних насадженнях міст та інших населених пунктів досягають більшої чисельності та щільності населення, ніж у природних біотопах. Білі трясогузки у Фінляндії у 85% випадків гніздяться у будівлях людини; у Підмосков'ї ця цифра ще вища. Причина полягає в тому, що культурне лісове господарство передбачає розчищення лісу від бурелому, купа хмизу, повалені дуплисті дерева, тоді як у будівлях людини глибокі притулки, необхідні для гніздування трясопузи, дуже численні. Та ж тенденція властива багатьом іншим закритогнездящимся видам птахів і кажанів.

Вплив людини на тварин виражається як у прямому переслідуванні та порушенні структури популяції, так і в зміні місць їх проживання. Останнім часом до загальних змін умов проживання додався такий потужний фактор, як забруднення природного середовища, особливо пестицидами. Найчастіше пряме переслідування (полювання) супроводжувалося зміною ландшафту, тобто. ці чинники діяли одночасно. Слід зазначити, що значення прямого переслідування скорочення чисельності тварин у останнє століття різко знизилося. Тож якщо у XVII в. пряме переслідування стало причиною загибелі видів у 86% випадків, а непряме - у 14%, то у XX ст. це співвідношення різко змінилося і становило відповідно 28 і 72%.

Другий аспект досліджень пов'язаний з тим, що навіть за відсутності прямих впливів на природні системи людство всією своєю повсякденною діяльністю змінює умови їхнього існування. Зміна ландшафтів, режиму вод, ненавмисне завезення багатьох видів за межі природних ареалів, як і багато інших впливів, ведуть до перебудови складу та структури екосистем. Міста та промислові райони, агроценози та біокультури - нові екосистеми, що виникли на технологічній основі, але живуть за екологічними законами. Постає завдання свідомого управління екологічними системами з метою підвищення продуктивності, конструювання стійких в умовах антропогенних ландшафтів екосистем різного цільового призначення.

ВИТРАТИ ЕКОЛОГІЧНОГО ГРОМАДСЬКОГО ВИРОБНИЦТВА - витрати на заходи, що знижують викиди і скиди забруднюючих речовин в навколишнє середовище (вдосконалення технології, зміна складу вихідних матеріалів, будівництво очисних споруд тощо), а також на заходи, що не знижують ступінь їхнього впливу на природу (будівництво високих труб, розведення, поховання відходів, встановлення санітарних зон навколо підприємств тощо). ВИМИКАННЯ - випромінювання атомних частинок або електромагнітних хвиль та утворення їхнього поля. Альфа-, Бета-, Гамма-, Рентгенівське І., Іонізуюче І.. Космічне І. ЗМІНА КЛІМАТУ - див/задоволені зміни клімату. ЗМІНА ЛАНДШАФТУ - придбання ландшафтом нових або втрата колишніх властивостей під впливом зовнішніх факторів або саморозвитку. У природоохоронній літературі займає серединне становище у ланцюжку понять: вплив на ландшафт - І.Л. - Наслідки у господарській діяльності або у здоров'ї населення. Розрізняють прямі та опосередковані І.Л., І.Л. в ході функціонування, динаміки або розвитку ландшафту, оборотні та незворотні І.л., прогресивні та регресивні І.л., цілеспрямовані та побічні І.л., спонтанні (пов'язані з ендогенними факторами) та зовнішні (зумовлені екзогенними факторами), І.І. л. в цілому або зміна окремих компонентів ландшафту.

Навколишнє середовище крім природного (загального для всіх тварин) включає створене людиною матеріальне середовище, що складається з елементів природного середовища, перетворених людиною (змінені ландшафти, змінений склад організмів і т.д.), штучних елементів, споруд, фізичних полів, матеріалів, виробів та ін. Таке середовище, зване техногенним, підрозділяється на селітебне - середовище жител і населених пунктів і виробниче - середовище виробничих приміщень та робочих місць.

Екологічна експертиза визнана дати оцінку впливу споруджуваного об'єкта на екологічні ніші живих організмів, що у зоні впливу об'єкта, на сукупність екологічних чинників та його зміна результаті впливу об'єкта. У результаті експертизи мають бути також отримані оцінки зміни ландшафтів, структури екологічних систем, зміни популяцій живих організмів, оцінки можливих глобальних наслідків.

Порушення ґрунтового покриву при освоєнні північних родовищ та відповідне порушення температурного режиму ґрунтів призводить до розвитку різноманітних процесів, що згодом мають лавинний характер змін ландшафтів.

Як об'єкт прогнозування нами обрано рослинний покрив. Подібний підхід до визначення стійкості обумовлений розумінням рослинності як центральної ланки геосистем. Рослинність грає в тундрових ландшафтах основну системоутворюючу і стабілізуючу роль, визначаючи динамічну рівновагу теплового балансу в системі "багаторічномерзлі породи - сезонно-талий шар - атмосфера ". Деградація рослинності веде до активізації термоерозійних процесів і корінних змін ландшафту. , 1969, 1974; Д. Д. Савінов, 1981)./ 3,4,5 /.

При енергетичному використанні торфу має ряд негативних наслідків для навколишнього середовища, що виникають в результаті видобутку торфу в широких масштабах. До них відносяться: порушення режиму водних екосистем, зміна ландшафту та ґрунтового покриву в місцях торфовидобутку, погіршення якості місцевих джерел прісної води та забруднення повітряного басейну, різке погіршення умов існування тварин. Значні екологічні проблеми виникають у зв'язку з необхідністю перевезення та зберігання.

Зазвичай геотермальні станції або потребують додаткових джерел води, або самі виробляють велику кількість води. Це призводить до «циркуляції» значних обсягів води та порушення природної рівноваги внаслідок зміни сольового складу вод. Буріння свердловин, прокладання трубопроводів, будівництво геотермальних станцій та вплив гарячої пари та води можуть стати причиною серйозної зміни ландшафту та ерозії ґрунтів. Зміна водного балансу в глибинах землі може призвести до зміни сейсмічної активності у вказаному районі.

І та й інша – результат взаємодії материків та океанів. Перша виражає падіння океанічного впливу - наростання континентальності ландшафтів - від океанічного узбережжя у глиб материка. Саме з цирком мокеанічної зональністю пов'язане явище секторності, або меридіональної зональності. Але секторність відбиває цир-кумокеанічну зональність у спотвореному вигляді, обмежуючись лише фіксацією змін ландшафтів на західних і східних океанічних околицях материків, що найбільш чітко простежуються на території СРСР, і залишаючи осторонь океанічний вплив на північну та південну околиці материків. А тим часом цей вплив на арктичне узбережжя СРСР дуже велике (охолодний вплив влітку, що опалює - взимку, при вітрах «мусонної тенденції»), хоча він і затушований активним західним переносом.

При санітарно-токсикологічному моніторингу здійснюють спостереження за якістю навколишнього середовища, ступенем його забруднення шкідливими речовинами, шумами, патогенними мікроорганізмами, проводять вивчення впливу шкідливих факторів БГЦ на рослинний та тваринний світ на людину. Про негативні зміни ландшафтів судять за екологічними ознаками, що свідчать про порушення земель при розробці родовищ нафти, газу, руд, про забруднення території викидами та стоками тваринницьких комплексів, пестицидами, важкими металами, радіонуклідами.

Як альтернативний розглянемо випадок «ландшафтного контролю», який знаходить все ширше застосування. При його здійсненні роблять зйомки з Землі, з повітря або з Космосу. За зробленими в різні періоди Знімками однієї і тієї ж території, які, потім обробляють або «дешифрують», до змін ландшафту, що спостерігаються на них, роблять висновок про екологічний вектор даної території. Помічені зміни кваліфікують для ландшафту як «корисні» чи «шкідливі».

Білогрудий їжак (Erinaceus concolor Martin, 1838) - широко поширений, звичайний вид комахоїдних (Insectívora) ссавців біля республіки. Має стабільну і досить високу середню щільність населення у різних типах лісу в літній період: від 4 до 60 особин на квадратний кілометр у сосняку мохистому та діброві орляковій відповідно. Антропогенна зміна ландшафтів створює ряд умов, що сприятливо позначаються на його розселенні: поява розріджених насаджень в результаті рубання лісу, лісосмуг, формування лісопаркових екосистем. Відомо, що їжак віддає перевагу біотопам з чагарниковою рослинністю, виявляє виражену тенденцію до синантропізації. Широкому розселенню сприяє і традиційне гуманне ставлення людей до звірка.

Вплив людини на природу, пов'язаний з розвитком промисловості, почав набувати дедалі більшого значення з середини XIX ст. Людина почала наступ на природу, відвойовуючи землі під міста, дороги, заводи, аеродроми, полігони, засмічуючи і їх, і площі, що обробляються, і ще не експлуатовані своїми побутовими, промисловими і військовими відходами. Цей вплив супроводжувався і супроводжується змінами ландшафту (можна сказати, радикальною зміною географії) внаслідок видобутку корисних копалин, будівництва великомасштабних об'єктів типу ГЕС та надходженням у навколишнє середовище забруднень - нових, не характерних для неї речовин - або перевищенням природного рівня цих речовин у середовищі. ...]

Сільське господарство. Однією з найважливіших прикладних проблем екологічної науки вивчення закономірностей формування та функціонування агроекосистем. Їхнє місце на земній кулі неухильно зростає. Тільки за чверть століття-з 1950 по 1975 р - площа, зайнята зерновими культурами, зросла на 1,25 10е км1, тобто майже на 1% вільної від льоду поверхні суші (К. Prentice, J. Coiner, 1980) . Землеробство пов'язане з докорінною зміною ландшафту у вигляді вирубування лісу, оранки цілинних земель, різних форм меліорації тощо [...]

Перша - обґрунтувати гранично можливі обсяги вилучення стоку, тому що були досить вагомі підстави вважати, що скорочення обсягу стоку Обі та Іртиша вже на першому етапі, а на другому тим більше негативно впливатиме на природно-екологічні умови в басейні та перспективи розвитку водоспоживаючих галузей. господарства Сибіру Істотних збитків міг бути завдано умовам проживання риб, режиму річкових заплав - основний кормової основі тваринництва північ від Західного Сибіру. Можливі були порушення умов проростання та відтворення лісів, зміни ландшафтів внаслідок зміни режиму ґрунтових вод, що у взаємозв'язку з річковим стоком. Обсяги вилучення та внутрішньорічний їх розподіл мали бути пов'язані з водністю різних років і сезонів.

Це завдання лише частково виконується у межах програм збереження біорізноманіття. Насправді завдання забезпечення здоров'я середовища виявляється набагато ширшим. Її рішення необхідне як на тлі колишнього біорізноманіття та природної структури співтовариств на територіях, що охороняються, так і при їх неминучій трансформації при антропогенному впливі. Середовище може бути несприятливим для здоров'я людини і при колишньому біорізноманітності (внаслідок радіаційного, хімічного та інших видів забруднення), і навпаки, навіть при трансформованому біорізноманітності та зміненому ландшафті вона може бути сприятливою для живих істот і людини. Як свідчить досвід розвинених країн, підтримання здоров'я середовища та забезпечення екологічної безпеки можливе навіть на тлі неминуче збідненого біорізноманіття в антропогенно виміряних ландшафтах.

Пропонована авторами таблиця основних нормованих показників ендогенних, екзогенних та техногенних процесів у ГС та суміжних середовищах містить 4 категорії стійкості геологічного середовища (геологічного стану) – від стійкого (сприятливого) до критично нестійкого (дуже несприятливого). Ці категорії кореспондують з переліченими вище категоріями за речовинним складом порід і доповнюються ендогенними геологічними процесами (інтенсивністю землетрусів); екзогенними геологічними процесами та геоекологічними умовами у зоні прояву багаторічномерзлих порід; ступенем зміни ландшафту у верхній частині ГС, потужністю зони аерації, забрудненням порід та ґрунтів, донних опадів радіонуклідами та нафтопродуктами, підземних та поверхневих вод та ін.

Найбільш поширена класифікація рік по довжині. За цією класифікацією до малих віднесено річки коротші за 100 км (Водогрецький, 1990). Поняття малі річки нерідко застосовується до всіх річок, що мають лише місцеве значення, та відображає вплив місцевих фізико-географічних факторів у масштабі великого регіону. Слід зазначити, що площа річкових басейнів менше 2000 км2 відповідає граничним умовам формування підземного стоку. Як правило, річки з такою площею дренують лише верхній малопотужний водоносний горизонт (води четвертинних відкладень). Цим, мабуть, і пояснюється вразливість водного режиму малої річки за зміни ландшафту її водозбору.

Для подібного типу викидів на деякій відстані від джерела у напрямку вітру на поверхні землі формується зона розподілу концентрацій умовно еліптичної форми (рис.1), в межах якої концентрація ЗВ буде вищою за задану граничну, а отже, з'явиться вже ненульова ймовірність негативного впливу на прийнятих до розгляду реципієнтів. Характерні розміри (масштаби) конкретної зони негативного впливу Ъх є при цьому у випадку випадковими величинами і визначаються комбінаціями наступних формують чинників: параметрами “джерела“ викиду ЗВ; силою вітру та класом стабільності атмосфери; сезонними змінами ландшафту (“шорсткості” поверхні).

Загальний висновок оцінок біорізноманіття у забруднених районах: в екологічно несприятливих місцях хімічного чи радіаційного забруднення біорізноманіття зберігається колишньому рівні і навіть вище, ніж навколишніх і екологічно сприятливіших територіях. Види, що мешкають тут, не ошушують небезпечного впливу і за рахунок інтенсивного розмноження підтримують свою високу чисельність. Відомо, що в зонах інтенсивного радіаційного впливу продовжують гніздитися червонокнижні види птахів, так само як люди продовжують жити в районах забруднення, не відчуваючи небезпеки, що нависла над ними. Види, що мешкають тут, не можуть бути замінені іншими. Справа тут у тому, що скорочення чисельності певного виду або зміна біорізноманіття загалом спостерігається при фізичній зміні метопроживання. При зміні ландшафту (при вирубці або оранні) на зміну колишнім видам приходять інші. При забрудненні зміни видів зазвичай не відбувається через те, що ні для яких видів ці умови не є оптимальними.

Планети, що належать до земної групи, - Меркурій, Венера, Земля, Марс - мають невеликі розміри і маси, середня щільність цих планет у кілька разів перевищує щільність води; вони повільно обертаються навколо осей; у них мало супутників (у Меркурія та Венери їх взагалі немає, у Марса – два крихітних, у Землі – один).

Риси подібності та відмінності виявляються також при вивченні атмосфер планет земної групи Хорошавіна С.Г. Концепція сучасного природознавства. Курс лекцій - Ростов-на-Дону, 2006.

Меркурій

Меркурій - четверта по блиску планета: у максимумі блиску вона майже така ж яскрава, як Сіріус, яскравіше за неї бувають тільки Венера, Марс і Юпітер. Тим не менш, Меркурій - дуже важкий об'єкт для спостережень через невелику кількість його орбіти і, отже, близькості до Сонця. Для неозброєного ока Меркурій - світла точка, а у сильний телескоп у нього вигляд серпика чи неповного кола. Зміни виду (фаз) планети з часом показують, що Меркурій - це куля, з одного боку освітлена Сонцем, а з іншого - зовсім темна. Діаметр цієї кулі – 4870 км.

Меркурій повільно обертається навколо своєї осі, будучи завжди зверненим до Сонця однією стороною. Отже період обертання навколо Сонця (меркуріанський рік) становить близько 88 земних діб, а період обертання навколо осі - 58 діб. Виходить, що від сходу Сонця до заходу на Меркурії минає рік, тобто 88 земних діб. І справді, поверхня Меркурія багато в чому подібна до поверхні Місяця, хоча ми й не знаємо, чи дійсно на поверхні Меркурія є моря і кратери. Меркурій має відносно велику щільність серед планет Сонячної системи - близько 5,44 г/см3. Вчені припускають, що це обумовлено наявністю масивного металевого ядра (імовірно з розплавленого заліза щільністю до 10 г/см3, що має температуру близько 2000 К), що містить понад 60% маси планети та оточеного силікатною мантією і, ймовірно, корою 60 - 100 км завтовшки .

Венера

Венера спостерігається і як "вечірня зірка" і як "ранкова зірка" - Hesperus та Phosphorus, так називали її в античному світі. Після сонця та Місяця Венера – найяскравіше небесне світило, а вночі освітлені нею предмети можуть відкидати тіні. Також Венера - найближча до Землі планета. Її навіть називають "сестрою Землі". І справді - радіус Венери майже дорівнює земному (0,95), її маса - 0,82 маси Землі. Венера досить добре вивчена людьми - до планети наближалися як радянські АМС серії "Венера", так і американські Маринери. Венера звертається навколо Сонця за 224,7 земної доби, але з цією цифрою, на відміну від Меркурія, нічого цікавого не пов'язано. Дуже цікавий факт пов'язаний з періодом обертання самої планети навколо своєї осі - 243 земні доби (у зворотному напрямку) і періодом обертання потужної венеріанської атмосфери, яка здійснює повний оберт навколо планети за... 4 дні! Це відповідає швидкості вітру біля поверхні Венери 100 м/с або 360 км/год! Вона має атмосферу, вперше відкриту М. В. Ломоносовим в 1761 під час проходження планети по диску сонця. Планета огорнута густим шаром білих хмар, що приховують її поверхню. Наявність в атмосфері Венери густих хмар, що ймовірно складаються з крижаних кристалів, пояснює високу відбивну здатність планети - 60% падаючого сонячного світла відбивається від неї. Сучасні вчені встановили, що венеріанська атмосфера на 96% складається із вуглекислого газу СО2. Присутні тут також азот (майже 4%), кисень, водяні пари, благородні гази та ін. (Всіх менше 0,1%). Основою густого хмарного шару, розташованого на висоті 50 - 70 км, є дрібні краплі сірчаної кислоти з концентрацією 75-80% (решта - вода, що активно "вбирається" крапельками кислоти). На Венері існують вулкани, що діють, так, як достовірно відомо, що сейсмічна і тектонічна діяльність на Венері була дуже активна порівняно недавно. Внутрішня будова цього псевдоблизня Землі також подібна до будови нашої планети.

Земля

Наша земля здається нам такою великою і міцною і такою важливою для нас, що ми схильні забувати про те скромне становище, яке воно займає в сім'ї планет сонячної системи. Правда у Землі все ж таки є досить товста атмосфера, що прикриває тонкий неоднорідний шар води, і навіть титулований супутник діаметром приблизно в ? її діаметра. Однак ці особливі прикмети Землі навряд чи можуть бути достатньою основою нашого космічного «егоцентризму». Але, будучи невеликим астрономічним тілом, Земля є найвідомішою для нас планетою. Радіус земної кулі R = 6378 км. Обертання земної кулі природно пояснює зміну дня і ночі, схід і захід світил. Деякі грецькі вчені здогадувалися і про річний рух Землі навколо Сонця. Річний рух Землі переміщує спостерігача і цим викликає видиме усунення ближчих зірок щодо більш далеких. Строго кажучи, навколо Сонця рухається центр ваги системи Земля - ​​Місяць, так званий баріцентр; навколо цього центру Земля та Місяць описують протягом місяця свої орбіти.

Наші уявлення про внутрішню будову та фізичний стан надр земної кулі засновані на різноманітних даних, серед яких істотне значення мають дані сейсмології (наука про землетруси та закони поширення пружних хвиль у земній кулі). Вивчення поширення в земній кулі пружних хвиль, що виникають при землетрусах або при потужних вибухах, дозволило відкрити і вивчити шаруватий будову земних надр.

Повітряний океан, що оточує Землю, - її атмосфера, - є ареною, де розігруються різноманітні метеорологічні явища. В основному земна атмосфера складається з азоту та кисню.

Атмосферу землі умовно ділять п'ять верств: тропосферу, стратосферу, мезосферу, іоносферу і екзосферу. Великий вплив на багато процесів, що відбуваються на нашій планеті, надає гідросфера, або Світовий океан, поверхня якого в 2,5 рази більша за площу суші. Земна куля має магнітне поле. За межами щільних шарів атмосфери він підперезаний невидимими хмарами з часток високої енергії, що дуже швидко рухаються. Це так звані пояси радіації. Будова та властивості поверхні нашої планети, її оболонок та надр, магнітного поля та поясів радіації досліджуються комплексом геофізичних наук.

Марс

Коли 1965 року американська станція Марінер-4 з малої відстані вперше отримала знімки Марса, ці фотографії викликали сенсацію. Астрономи були готові побачити будь що, тільки не місячний ландшафт. Саме на Марс покладали особливі сподівання ті, хто хотів знайти життя у космосі. Але ці сподівання не виправдалися - Марс виявився неживим. За сучасними даними радіус Марса майже вдвічі менший за земний (3390 км), а за масою Марс поступається Землі вдесятеро. Звертається навколо Сонця ця планета за 687 земних діб (1,88 року). Сонячна доба на Марсі практично дорівнює земним - 24 год 37 хв, а вісь обертання планети нахилена до площини орбіти на 25), що дозволяє зробити висновок про схожу із земною зміною (для Землі - 23 пори року.

Але всі мрії вчених про наявність життя на Червоній планеті розтанули після того, як було встановлено склад атмосфери Марса. Для початку слід зазначити, що тиск на поверхні планети в 160 разів менший за тиск земної атмосфери. А складається вона на 95% з вуглекислого газу, містить майже 3% азоту, більше 1,5% аргону, близько 1,3% кисню, 0,1% водяної пари, є також чадний газ, знайдені сліди криптону та ксенону. Зрозуміло, у такій розрідженій та негостинній атмосфері жодного життя існувати не може.

Середньорічна температура на Марсі становить приблизно -60 перепади температур протягом доби викликають сильні пилові бурі, під час яких густі хмари піску та пилу піднімаються до висот 20 км. Склад марсіанського грунту був остаточно виявлений при дослідженнях американських апаратів Вікінг-1 і Вікінг-2, що спускаються. Червоний блиск Марса викликаний великою кількістю у його поверхневих породах оксиду заліза III (охри). Рельєф Марса дуже цікавий. Тут присутні темні та світлі області, як і на Місяці, але на відміну від Місяця, на Марсі зміна кольору поверхні не пов'язана зі зміною висот: на одній висоті можуть бути як світлі, так і темні області.

Досі вченим не відома природа катаклізму, що спричинив глобальні зміни клімату на Марсі, що призвели до сучасних умов.

Поверхня Землі залишається незмінною. Протягом тих мільйонів років, що існує наша планета, її зовнішній вигляд постійно впливали різні природні сили. Зміни, які відбуваються на Землі, викликані як дією внутрішніх сил, і тим, що відбувається у атмосфері.

Так, гори утворилися внаслідок пересування земної кори. Товщі порід виштовхувалися на поверхню, змінюючись і розбиваючись, у результаті утворилися різні типи гір. Минав час, дощ та мороз дробили гори, створюючи окремі скелі та долини.

Деякі гори утворилися внаслідок виверження вулканів. Розплавлена ​​порода, пузирячись, виливалася на поверхню Землі через отвори в корі шар за шаром, поки зрештою не виникала гора. Везувій в Італії – гора вулканічного походження.

Вулканічні гори можуть формуватися під водою. Наприклад, Гавайські острови – це вершини вулканічних гір.

Сонце, вітер та вода викликають постійну руйнацію гірських порід. Цей процес називається ерозією. Але він може зачіпати не лише гірські породи. Так, ерозія за допомогою льоду, вітру та води вимиває земний ґрунт.

Льодовики у місцях сповзання на морі розрізають рівнини, утворюючи долини і фіорди — вузькі і звивисті морські затоки.

Фіорди утворилися під час льодовикового періоду, коли континенти були покриті товстим шаром льоду та снігу.

Ці льоди, у свою чергу, викликали утворення льодовиків, які являють собою річки льоду, що повільно рухаються.

Сповзаючи з гір у долини, льодовики, товщина льоду в яких іноді сягала кількох десятків метрів, пробивали собі шляхи. Сила їхнього руху була дуже велика.

Спочатку шляхом льодовиків утворювалися вузькі ущелини, потім жахлива сила льодовика збільшувала їх, відкриваючи собі шлях вниз. Поступово цей простір ставав дедалі глибшим і ширшим.

Після закінчення льодовикового періоду лід та сніг почали танути. У міру танення льоду ширина річок зростала. Одночасно рівень моря піднімався. Так на місці рік утворилися фіорди.

Береги фіордів зазвичай являють собою скелясті укоси, що іноді досягають висоти в 1000 метрів (3000 футів).

Деякі фьорди такі глибокі, що у них можливий рух суден.

Велика кількість фіордів розташована на узбережжях Фінляндії та Гренландії. Але найкрасивіші фьорди знаходяться в Норвегії. Найдовший фьорд також знаходиться в Норвегії. Він називається Согні-фіорд. Його довжина - 180 кілометрів (113 миль).

Після танення льоду залишаються морени - скупчення уламків гірських порід - і формуються зигзагоподібні вершини гір. Річки пробивають у пухких породах яри, а деяких місцях і величезні каньйони (глибокі річкові долини з крутими східчастими схилами), такі, наприклад, як Великий Каньйон в Аризоні (США). Він простягається на 349 кілометрів завдовжки.

Дощі та вітри є справжніми скульпторами та висікають справжні скульптурні групи, різні фігури. В Австралії знаходяться так звані Вітряні скелі, а неподалік Красноярська знаходяться кам'яні стовпи. І ті, й інші утворилися внаслідок вітрової ерозії.

Ерозія земної поверхні – процес далеко не нешкідливий. Щорічно завдяки їй зникають багато десятків гектарів орних земель. У річки виноситься велика кількість родючого ґрунту, на освіту якого в природних умовах йдуть сотні років. Тому людина намагається всіма можливими способами боротися із ерозією.

Головний напрямок цієї боротьби - запобігання розмиванню ґрунту. Якщо на ґрунті відсутній рослинний покрив, то вітер і вода легко забирають родючий шар і земля стає безплідною. Тому в районах з інтенсивними вітрами застосовують способи обробки землі, що зберігають, наприклад безвідвальну оранку.

Крім того, ведеться боротьба з ярами. Для цього береги річок засаджують різними рослинами, зміцнюють схили. На морських та річкових узбережжях, де відбувається сильне розмивання берега, роблять спеціальне відсипання гравію та встановлюють захисні греблі, що запобігають перенесенню піску.


Міністерство освіти та науки Російської Федерації
Саратовський Державний Університет
ім. Н. Г. Чернишевського

Кафедра геоекології

ЗМІНИ ЛАНДШАФТІВ В ІСТОРІЇ ЗЕМЛІ

РЕФЕРАТ

Спеціальність 020401 – Географія.
Студент 5 курсу географічного факультету.
Невечора Костянтина Сергійовича

Викладач
геоекології _______________ А. М. Іванов

Саратов, 2011

Вступ 3
4
Фактори, що змінюють ландшафт 11
11
Землетруси 12
Вулкани. Типи вивержень 14
Висновок 17
Список використаних джерел 18


Вступ

Ландшафт (нім. Landschaft, вид місцевості, від Land – земля та schaft – суфікс, що виражає взаємозв'язок, взаємозалежність) – одне з фундаментальних понять географії, 1) характер геопросторової структури ділянки земної поверхні; 2) конкретна частина земної поверхні з єдиною структурою та динамікою.
Під ландшафтом у географії також розуміють повторювану мозаїку взаємодіючих місцеперебування та організацію візуального малюнка земної поверхні. Під ландшафтом у географії зазвичай мають на увазі ділянки землі та їх властивості, зумовлені взаємодією рельєфу, клімату, геологічної структури, ґрунтів, рослинного та тваринного світу та людської діяльності. У той самий час використовуються терміни «грунтовий ландшафт», «ландшафт рослинності» тощо. буд. для позначення монокомпонентних утворень. Розміри ландшафтів становлять від кількох кілометрів і від: називати ландшафтами менші території - недоцільно. Водночас у ландшафтній екології виділяють ландшафти окремих видів тварин, розміри яких залежать від їх екологічних характеристик: від десятків квадратних метрів для комах до сотень квадратних кілометрів для великих ссавців та птахів.
Іноді ландшафтом називають основну одиницю фізико-географічного районування території; генетично єдиний район з однотипним рельєфом, геологічною будовою, кліматом, загальним характером поверхневих та підземних вод, закономірним поєднанням ґрунтів, рослинних та тваринних угруповань. Таке вживання даного терміна слід вважати застарілим, оскільки відсутні чіткі критерії однотипності та генетичної спільності характеристик, що використовуються при виділенні таких одиниць.


Мінливість, стійкість та динаміка ландшафту

Мінливість ландшафтів обумовлена ​​багатьма причинами, вона має складну природу і виявляється у різних формах. Насамперед, слід розрізняти у ландшафтах два основних типи змін (за Л.С.Бергом) оборотні та незворотні. Зміни першого типу не призводять до якісного перетворення ландшафту, вони відбуваються, як зазначив В.Б.Сочава, у межах одного інваріанту, на відміну змін другого типу, які ведуть до трансформації структур, тобто. до зміни ландшафтів. Усі оборотні зміни ландшафту утворюють його динаміку, тоді як незворотні зміни становлять сутність його розвитку. Інваріант - це сукупність можливих щодо оборотних станів геосистеми, у межах якої її можна ідентифікувати собі. Під станом геосистеми мається на увазі упорядковане співвідношення параметрів її структури та функцій у певний проміжок часу.
Динаміка (зміни) ландшафту пов'язані з його стійкістю: саме оборотні динамічні зміни свідчить про здатність ландшафту повертатися до вихідного стану, тобто. з його стійкість. Під стійкістю системи мається на увазі її здатність зберігати структуру при дії факторів, що обурюють, або повертатися в колишній стан після порушення. Проблема стійкості ландшафту набуває важливого практичного значення у зв'язку з наростаючим техногенним "тиском".
Помітний вклад в. вивчення та розуміння даної властивості ландшафтних геосистем внесли вчені Іркутської, Московської та Ленінградської ландшафтознавчих шкіл - В.Б. Сочава, А.Г. Ісаченко, В.А. Миколаїв, М.А. Глазовська, І.І. Мамай, К.М. Дияконів, Н.Л. Беручашвілі, А.А. Краукліс та ін.
Стан природної геосистеми - це певний тип та впорядковане співвідношення параметрів її структури та функціонування, обмежені деяким відрізком часу. Зміна одного стану іншим, що супроводжується зміною структури та функціонування геосистеми, називається динамікою геосистем. Тобто динаміка геосистем – це просторово-часові зміни їхнього стану. При зміні погодних умов, часу доби та року, різних за кліматичними параметрами років та багаторічних періодів, пов'язаних із циклами сонячної активності, геосистеми, змінюючи структуру та функціонування (стану), адаптивно підлаштовуються до них. Приклади станів: а) зимові, літні; б) вологі; посушливі тощо. Так було в ландшафтах середньої смуги Росії протягом року спостерігаються такі зміни станів. Взимку немає фотосинтезу, уповільнюються процеси розкладання та мінералізації органіки, практично відсутній поверхневий стік на міжріччях; у структурі геосистем бере участь сезонний компонент - сніговий покрив, що формує свій геогоризонт, промерзають ґрунти, утворюється крижаний покрив на водоймах. Навесні процеси сніготанення супроводжуються стоком талих вод, активним площинним змивом і лінійною ерозією на схилах, особливо на слабозадернованих ділянках, повіньми на річках. З квітня та влітку активно йде фотосинтез, біопродукування та мінералізація органічних залишків. Тобто від сезону до сезону та в різних погодних умовах природні геосистеми змінюють свої стани, а саме по-різному функціонують і навіть бувають представлені різними варіантами їхньої вертикальної та горизонтальної структури.
Геосистеми змінюють свої структури та функціонування та при переході від однієї стадії розвитку до іншої (молодості-зрілості-старіння). Отже, динаміка геосистем – це зміна їх станів. Розрізняють кілька видів природної ландшафтної динаміки:
динаміка функціонування,
розвитку, еволюції,
катастроф (або революцій)
відновлювальних сукцесій.
Кожен із них характеризується переважанням тієї чи іншої форми розгортання подій (змін станів) у часі.
Динаміка функціонування - провідна роль належить ритмічній зміні оборотних станів геосистем, пов'язаних з кругообігом речовини та енергії та з ритмами зовнішнього середовища (планетарними, сонячними). Якщо говорити про функціональну динаміку геосистем взагалі, то просторову та тимчасову її характеристики розглядають як відносно рівнозначні складові. Наприклад, зміна хімічного складу, швидкості чи положення забрудненої маси води у водотоку при його переміщенні (зміні положення) у просторі, або добові та сезонні (тимчасові) зміни у ландшафтах – все це їхня динаміка. Однак, враховуючи, що ландшафтні геосистеми мають жорсткий, відносно інертний літогенний каркас, просторові характеристики їх функціональної динаміки має сенс аналізувати лише для їх мобільних компонентних структур: повітря, води та тваринного населення. Тому щодо функціональної динаміки ландшафтної геосистеми загалом, якщо вона відчуває аномальних зовнішніх впливів (антропогенних чи природних), основний акцент зазвичай робиться на вивченні змін її станів у часі.
Отже, функціональна динаміка ландшафтних геосистем включає: - процеси обміну речовиною та енергією із зовнішнім середовищем (метаболізм геосистеми), які можна розглядати як ланок речовинно-енергетичних кругообігів у суміжних геосистемах; - внутрішні круговороти речовини та енергії в геосистемі; - адаптивні оборотні функціональні зміни стану геосистеми під впливом ритмічних та випадкових змін довкілля в межах певного її інваріанту. Функціональна динаміка характеризується та проявляється в основному у формі ритмів та циклів.
Ритмічність - це закономірне чергування явищ через певний проміжок часу (період) чи просторі (дихання, біопродукування, чергування форм рельєфу у просторі). Цикл (греч, - коло) - це сукупність взаємозалежних процесів і явищ, що означають завершеність процесу від початку до кінця - закінчене коло розвитку чогось (добовий цикл, життєвий цикл чи етап, цикл лекцій, цикл біопродукування). Тобто динаміка функціонування - це переважно періодично повторювані у певній послідовності серії станів геосистеми (добових, сезонних, погодних та інших), які відрізняються специфікою структури та функціонування. Бувають ритми і з більшою періодичністю - 11-річною, 30-річною, віковою та ін. Ландшафтні ритми з різними періодами накладаються один на одного. Короткочасні відбуваються і натомість середньочасних, а середньочасні - і натомість довготривалих.
Крім того, для функціональної динаміки дуже характерні і неперіодичні, аритмічні оборотні зміни станів, пов'язані, насамперед, із змінами погодних умов. Прикладами функціональної динаміки в геосистемах можуть бути активний фотосинтез зелених рослин, що повторюються щорічно в помірних широтах, цвітіння, вегетація, дозрівання насіння; активні біогеохімічні кругообіги, пов'язані з накопиченням елементів мінерального живлення в рослинах, мінералізацією відмерлих залишків рослин, надходженням елементів у ґрунт, а з неї знову в рослини; активне функціонування яружно-балкових систем у теплі та вологі сезони року та припинення або різке загасання процесів фотосинтезу та вегетації рослин у холодні, морозні та сухі сезони. Отже, динаміці функціонування природних геосистем насамперед властиві ритміка і циклічність, а також незначні аритмічні коливання найбільш мобільних параметрів, що характеризуються оборотними змінами їх станів.
Однак оборотність стану геосистем відносна, оскільки в процесі функціонування та життєдіяльності в них накопичуються незворотні зміни («не можна двічі увійти в ту саму річку»). Коливальні оборотні зміни в геосистемах нанизані на процес спрямованих, незворотних змін як у самій геосистемі, так і в зовнішньому природному середовищі. За різномаштабною ритмікою цей процес часом буває важко вловимим, оскільки протікає значно повільніше. Коли природна геосистема характеризується певною спрямованістю розвитку, спрямованої динамікою, то говорять про тренди розвитку та еволюції (наприклад, заростання озера, прогресуюче заболочування тайгового ландшафту, ерозійне розчленування тощо).
До теперішнього часу сформувалася ландшафтна оболонка, насичена життям, біотичною та біокосною речовиною, у біосфері виділилася людина, яка надає своєю діяльністю та антропогенними речовинами все більший вплив на ландшафтну оболонку. Провідними чинниками довкілля, які сильно впливають на тренди еволюційного розвитку геосистем, є енергія Сонця та ендогенна енергія землі, що визначають гідрокліматичні та геолого-геоморфологічні особливості територій (геома). Серед факторів спонтанного розвитку геосистем значна роль належить біоті та екзогенним внутрішньоландшафтним процесам. Саме завдяки діяльності біоти ландшафтна оболонка за 2-2,5 млрд років зазнала кардинальних змін структури та функціонування. Проте еволюційна динаміка, обумовлена ​​зародженням і саморозвитком нових геосистемних елементів, вимагає наявності певних структурно-генетичних передумов, ув'язнених як і самих ландшафтних комплексах, і у зовнішньому середовищі. Тобто спонтанна еволюційна динаміка готується попереднім історичним розвитком геосистеми, а особливо активно реалізується у періоди чи фази екстремального прояву зовнішніх впливів. Такі впливи зазвичай пов'язані або з багаторічними циклами функціонування та розвитку глобальних геосистем, або з накладенням та «інтерференцією» різних видів зовнішніх планетарних та космічних процесів. Наприклад, вологі чи сухі епохи, зумовлені багатовіковими зовнішніми ритмами, неоднаково впливають саморозвиток елювіальних (вододільних) і акумулятивних геокомплексів; активна оранка вододілів і схилів під час вологих багаторічних періодів (фаз) веде до зародження і подальшого розвитку безлічі різноманітних яружно-балкових геокомплексів і до кращої дренованості ландшафтів, що вміщають їх.
Отже, на еволюцію природних геосистем впливають процеси в зовнішньому середовищі, що змінюється, і спонтанні процеси саморозвитку. Однак вони тісно пов'язані один з одним. Динаміка катастроф чи революцій (лат. revolutio - поворот) - це уривчасте, стрибкоподібне якісне перетворення одного стану та самих геосистем на інші. Реалізується у формі епізодичних катастроф і криз, що швидко розгортаються в часі, пов'язаних з екстремальними стихійними явищами, що ведуть до корінної зміни структур геокомплексів. До них відносяться такі руйнівні процеси, як обвали, лавини і сіли в горах, урагани, катастрофічні зливи і повені, вулканічні виверження, пожежі, непомірна господарська діяльність та ін. відрізки часу і спричиняє руйнування чи повне знищення біоти і грунтового покриву, а часом і зміни літогенної основи. Ландшафту після таких катастроф потрібно кілька десятків, а то й сотні років на відновлення вертикальної та горизонтальної структури або на становлення оновлених геокомплексів на новій літогенній основі. Причому суттєві зміни літогенної основи ландшафтів можуть докорінно змінити напрямок їх розвитку та еволюції. Тобто динаміка революцій чи катастроф є ще одним із факторів, що визначають структурну організацію, розвиток та еволюцію геосистем.
Динаміка відновлювальних сукцесій - завершення короткочасних деструктивних фаз епізодичних екстремальних природних та антропогенних явищ, що ведуть до руйнування частини структурних елементів геосистем, і наступні за ними тренди тривало похідних змін їх станів, спрямованих на відновлення ґрунтово-рослинного покриву та стабілізацію геосистем. Динаміка саморозвитку природних геосистем після таких катаклізмів супроводжується такими стадіями:
1. Зародження геосистеми на новій літогенній основі (наприклад, осушене дно озера після прориву завалу, свіжий осип біля підніжжя схилу, відкладення селю в долинах гірських річок і у підніжжя гір, промоїни на схилі та потужні пролювіальні наноси після екстремальних злив. .).
2. Становлення геосистеми, що характеризується підвищеною функціональною та структурною мінливістю, виникненням рослинного та ґрунтового покриву.
3. Стадія зрілості (клімакс) геосистеми, що характеризується її стабілізацією та відповідністю всіх елементів її структури існуючим умовам середовища.
4. Відмирання однієї і зародження на її місці нової, геосистеми (на місці озерного геокомплексу, що заростає, виникає низинне болото, воно змінюється верховим, а верхове болото може змінитися заболоченим лісом).
Тобто після епізодичних катастрофічних порушень геосистеми проходять серії певних стадій саморозвитку чи відновлювальних сукцесій (відновлення деревостою та ґрунтів на місці вирубки чи згарищ). Отже, послідовне стадійне зміна ландшафту після припинення природних чи антропогенних його порушень від початку відновлення чи зародження до стійкого еквіфінального стану (клімаксу) називається динамікою відновлювальних сукцесій. Ландшафтна динаміка відновлювальних сукцесій – це послідовна зміна станів геосистеми, спрямована на її стабілізацію у навколишньому середовищі.
Становлення геосистеми на новій літогенній основі зі знищеним рослинним покривом називається первинною сукцесією. Вторинна сукцесія - це відновлення і деструкція поч-венно-рослинного покриву вже геосистемі (на місці згарищ, вирубок). Залежно від ступеня та типу порушеності геосистеми та її внутрішніх здібностей до самовідновлення характерні часи періоду відновлювальних сукцесій (релаксацій) суттєво різняться. Так, відновна сукцесія у середній тайзі після суцільних рубок, без порушення ґрунтового покриву, характеризується 100-200-річним періодом релаксації та приблизно наступними стадіями: розрізнених трав'янистих рослинних угруповань; трав'яно-чагарникових угруповань; дрібнолистяного трав'яно-чагарникового молодого лісу; дрібнолисті ліси з підростом хвойних порід; хвойного лісу з домішкою дрібнолистяних дерев; типового середньотаїжного хвойного зеленомошно-чагарникового (клімаксового) лісу. При фрагментарних порушеннях верхніх горизонтів ґрунтів – 400-800 років,
За фактором, що зумовив початок відновної сукцесії, розрізняють:
а) природно-катастрофічні (лісові пожежі, вітряки, лавини та ін.);
б) антропогенні (вирубка, пасовищна дигресія, рілля).
Крім того, зараз все більшу роль у «житті», геосистем грає антропогенна динаміка, яка може проявлятися і в особливостях функціонування, і в розвитку, і в еволюції, а часто проявляється у формі катастроф чи революцій та відновлювальних сукцесій. Все це йде на тлі випадкових змін параметрів як самих геосистем, пов'язаних із «помилками» або неточностями їхнього функціонування та розвитку, так і зовнішнього середовища.
Антропогенна динаміка геосистем обумовлена ​​господарськими впливами на природне середовище. Цей вид динаміки проявляється стосовно:
а) до рослинності: вирубування та інші види механічного знищення деревно-чагарникової рослинності, що супроводжуються скороченням площі та змінами якості лісів, розорювання степів та луків;
б) до ґрунтів та рельєфу: прискорена сільськогосподарська ерозія та дефляція ґрунтів, пов'язані з механічними пошкодженнями рослинного та ґрунтового покривів, дигресія пасовищ та розвіювання пісків, опустелювання, зміни рельєфу та ландшафтних геосистем у цілому кар'єрно-відвальними комплексами, деградація та корінні перетворення та промислових зонах та ін;
в) до гідросфери заболочування підтоплених водосховищами узбереж та вторинне засолення грунтів на зрошуваних землях в аридних районах;
г) забруднення природного середовища та супроводжуючі його порушення рослинності, ґрунтів, тваринного населення. Антропогенна динаміка геосистем у більшості випадків здійснюється природними процесами (ерозія, заболочування), але процеси, спричинені господарською діяльністю та ведуть до деградації, руйнування ландшафтних комплексів. Наприклад, інтенсивна ерозія ґрунтів та кор вивітрювання в горах після зведення лісів (Древня Греція); дефляція ґрунтів, еолове рельєфоутворення. опустелювання після сильної дигресії пустельних або степових пасовищ; всихання, відмирання та зміна рослинності в містах та забруднених промзонах.
Отже, розрізняють кілька видів ландшафтної динаміки: - динаміка функціонування; - динаміка розвитку; - еволюційна динаміка; - динаміка природних катастроф чи революцій; - динаміка відновлювальних сукцесій; - Антропогенна динаміка. Динаміки функціонування та відновлювальних сукцесій стабілізують геосистеми (стабілізуючі динаміки), підвищують їхню стійкість. Вони характеризуються відносною оборотністю змін станів геосистем у межах їхнього інваріанту. Динаміки еволюції та розвитку, що характеризуються трендами, динаміка природних катастроф та антропогенна динаміка ведуть до різких, незворотних якісних змін та перетворень ландшафтів. Всі види динаміки, накладаючись один на одного, нерозривно пов'язані між собою та характеризують минуле, сучасне та майбутнє геосистем. Динаміка розвитку та функціонування ландшафту – це конкретний сучасний етап ландшафтної еволюції. Тобто динаміку ландшафту загалом можна визначити як сукупність змін станів ландшафту, що мають як оборотний (стабілізуючий), так і незворотний (перетворюючий) характер, зумовлених зовнішніми та внутрішніми факторами. Однією з внутрішніх причин, що породжують динаміку еволюції та розвитку геосистем, є різна інерційність їх природних компонентів та геокомплексів. Тобто вони реагують на зміни довкілля з різною швидкістю.


Фактори, що змінюють ландшафт

Ерозія грунту: вітрова та водна

Сильні вітри, що викликають пилові бурі в степу, бурхливі потоки каламутної води і маленькі струмки, що стікають схилами рано навесні або влітку після зливи, завдають великої шкоди народному господарству. Під час запорошених бур зноситься родючий шар ґрунту, з його складу видується мілкозем, внаслідок чого поверхня поля стає нерівною. Води, що стікають, утворюють промоїни і яри, вимивають і відносять в гідрографічну мережу поживні речовини.
Під впливом сильних вітрів та неврегульованого стоку поля стають незручними для обробки, а ґрунти поступово втрачають свою родючість – це і є ерозія ґрунту. За визначенням академіка Л.І. Прасолова, " під загальним поняттям ерозії грунту розуміються різноманітні і поширені явища руйнації і зносу грунтів і пухких порід потоками води та вітру " .
Особливості розвитку та прояви сучасних ерозійних процесів дають можливість виділити нормальну та прискорену ерозію ґрунту. Нормальна ерозія протікає дуже повільно, а тому незначні втрати верхніх шарів ґрунту від видування та змиву відновлюються під час ґрунтоутворювального процесу. Така ерозія має місце на ґрунтах, поверхня яких не порушена господарською діяльністю. Нормальну ерозію називають геологічною.
Прискорена ерозія ґрунту має місце у районах, де нераціональна господарська діяльність людини активізує природні ерозійні процеси, доводячи їх до руйнівної стадії. Прискорена ерозія є наслідком інтенсивного використання ґрунту без дотримання протиерозійних заходів (розорювання схилів, суцільна вирубка лісів, нераціональне освоєння незайманих степів, неврегульований випас худоби, що призводить до знищення природної трав'янистої рослинності).
Розрізняють вітрову та водну ерозію ґрунтів. У вітровій ерозії (дефляції) розрізняють курні бурі (чорні бурі) та повсякденну (місцеву) вітрову ерозію. Під час запорошених бур вітри досягають великих швидкостей і охоплюють величезні території. На окремих ділянках за один-два дні зноситься верхній обрій ґрунту потужністю до 25 см, знищуються посіви на величезних площах.
Повсякденна, або місцева, вітрова ерозія грунтів має локальний характер і охоплює невеликі площі. Найчастіше вона проявляється на пісках та площах з легкими ґрунтами, а також на карбонатних суглинистих ґрунтах. Місцева вітрова ерозія проявляється й узимку, коли сильні вітри здувають сніг. У цьому випадку ґрунт на оголених ділянках, насамперед на опуклих схилах, швидко втрачає вологу та руйнується повітряними потоками.
Водну ерозію ґрунту поділяють на змив ґрунтів (площинна ерозія) та яружну (лінійну). Мікрорельєф ґрунту не буває ідеально рівним. У зв'язку з цим поверхневий стік атмосферних вод здійснюється цівками і струмками різної величини. Концентровані потоки талої, зливової та дощової води створюють промоїни та водорийни, частіше невеликих розмірів. За рік поле втрачає з верхнього горизонту б-12 т/га матеріалу, а в окремих випадках, за сильних злив, з гектара змивається до 200 т найродючішого ґрунту. При цьому ґрунти на полі, покритому рослинністю, змиваються меншою мірою, ніж оголеним.
Таким чином, із розораних площ, розташованих на схилах, внаслідок неврегульованого поверхневого стоку спостерігається видалення родючого шару ґрунту. Цей малопомітний, але найнебезпечніший і шкідливий процес зветься змив грунтів (площинна ерозія). На крутих і довгих схилах стік може призвести до утворення великих струменевих і струмкових розмивів, з якими вже не можна боротися звичайним обробітком грунту. Це так званий струменевий змив ґрунтів. У цьому випадку розмиви, що утворилися, необхідно спеціально зарівнювати, так як в іншому випадку вони надалі переростуть в яри.

Землетруси

Землетруси - коливання Землі, викликані раптовими змінами у стані надр планети. Ці коливання є пружними хвилями, що поширюються з високою швидкістю в товщі гірських порід. Найбільш сильні землетруси іноді відчуваються на відстанях понад 1500 км від вогнища і можуть бути зареєстровані сейсмографами (спеціальними високочутливими приладами) навіть у протилежній півкулі. Район, де зароджуються коливання, називається осередком землетрусу, яке проекція на поверхню Землі – епіцентром землетрусу. Вогнища більшої частини землетрусів лежать у земній корі на глибинах трохи більше 16 км, проте у деяких районах глибини вогнищ досягають 700 км. Щодня відбуваються тисячі землетрусів, але лише деякі з них відчуваються людиною.
Наслідки землетрусів. Сильні землетруси залишають безліч слідів, особливо в районі епіцентру: найбільшого поширення мають зсуви та осипи пухкого ґрунту та тріщини на земній поверхні. Характер таких порушень значною мірою визначається геологічним будовою місцевості. У рихлому та водонасиченому грунті на крутих схилах часто відбуваються зсуви та обвали, а потужна товща водонасиченого алювію в долинах деформується легше, ніж тверді породи. На поверхні алювію утворюються осадові улоговини, що заповнюються водою. І навіть не дуже сильні землетруси відбиваються в рельєфі місцевості.
Зміщення по розломах або виникнення поверхневих розривів можуть змінити планове та висотне положення окремих точок земної поверхні вздовж лінії розлому, як це сталося під час землетрусу 1906 р. у Сан-Франциско. При землетрусі в жовтні 1915 в долині Плезант в Неваді на розломі утворився уступ довжиною 35 км і висотою до 4,5 м. При землетрусі в травні 1940 в долині Імпіріал в Каліфорнії зрушення відбулися на 55-кілометровій ділянці ,5 м. У результаті Ассамського землетрусу (Індія) у червні 1897 р. в епіцентральній області висота місцевості змінилася не менше, ніж на 3 м.
Значні поверхневі деформації простежуються не тільки поблизу розломів і призводять до зміни напрямку річкового стоку, підпружування або розривів водотоків, порушення режиму джерел води, причому деякі з них тимчасово або назавжди перестають функціонувати, але водночас можуть з'явитися нові. Криниці та свердловини запливають брудом, а рівень води в них відчутно змінюється. При сильних землетрусах вода, рідкий бруд або пісок можуть фонтанами викидатися з ґрунту.
При зміщенні розломів відбуваються пошкодження автомобільних і залізниць, будівель, мостів та інших інженерних споруд. Проте якісно збудовані будинки рідко руйнуються повністю. Зазвичай ступінь руйнувань знаходиться у прямій залежності від типу споруди та геологічної будови місцевості. При землетрусах помірної сили можуть відбуватися часткові пошкодження будівель, а якщо вони невдало спроектовані або неякісно збудовані, то можливе їх повне руйнування.
При дуже сильних поштовхах можуть обрушитися і постраждати споруди, побудовані без урахування сейсмічної небезпеки. Зазвичай не обрушуються одно- і двоповерхові будівлі, якщо вони не дуже важкі дахи. Однак буває, що вони зміщуються з фундаментів і часто у них розтріскується та відвалюється штукатурка.
Диференційовані рухи можуть призводити до того, що мости зсуваються зі своїх опор, а інженерні комунікації та водопровідні труби розриваються. При інтенсивних коливаннях покладені в ґрунт труби можуть «складатися», всовуючись одна в іншу, або вигинатися, виходячи на поверхню, а залізничні колії деформуватися. У сейсмонебезпечних районах споруди повинні проектуватися та будуватися з дотриманням будівельних норм, прийнятих для цього району відповідно до карти сейсмічного районування.
У густонаселених районах чи не більші збитки, ніж самі землетруси, завдають пожежі, що виникають внаслідок розриву газопроводів та ліній електропередач, перекидання печей, плит та різних нагрівальних приладів. Боротьба з пожежами утруднюється через те, що водопровід виявляється пошкодженим, а вулиці непроїжджими внаслідок завалів, що утворилися.

Вулкани. Типи вивержень

Вулкани - (на ім'я бога вогню Вулкана), геологічне утворення, що виникає над каналами і тріщинами в земній корі, за якими вивергаються на земну поверхню з глибини магматичних джерел лави, гарячі гази та уламки гірських порід. Зазвичай вулкани становлять окремі гори, складені продуктами вивержень.
Вулкани поділяються на діючі, заснули і згаслі. До перших відносять вулкани, що вивергаються нині постійно чи періодично. До тих, хто заснув, відносять вулкани, про виверження яких немає відомостей, але вони зберегли свою форму і під ними відбуваються локальні землетруси. Згаслими називаються сильно зруйновані та розмиті вулкани без будь-яких проявів вулканічної активності.
і т.д.................

Останні матеріали розділу:

Дати та події великої вітчизняної війни
Дати та події великої вітчизняної війни

О 4-й годині ранку 22 червня 1941 року війська фашистської Німеччини (5,5 млн осіб) перейшли кордони Радянського Союзу, німецькі літаки (5 тис) почали...

Все, що ви повинні знати про радіацію Джерела радіації та одиниці її виміру
Все, що ви повинні знати про радіацію Джерела радіації та одиниці її виміру

5. Дози випромінювання та одиниці виміру Дія іонізуючих випромінювань є складним процесом. Ефект опромінення залежить від величини...

Мізантропія, або Що робити, якщо я ненавиджу людей?
Мізантропія, або Що робити, якщо я ненавиджу людей?

Шкідливі поради: Як стати мізантропом і всіх радісно ненавидіти Ті, хто запевняє, що людей треба любити незалежно від обставин або...