Создание карты нормалей из карты высот в вычислительном шейдере?

Проблема в том, что когда я пытался преобразовать карту высот в карту нормалей. Результаты неверны. По какой-то причине в текстуре есть 3 источника света, которые излучают сверху (зеленый), справа (красный) и слева (синий).

Это код GeoMath.hlsl, который я использую

static const float PI = 3.141592653589793238462643383279;

float2 longitudeLatitudeToUV(float2 longLat) {
    float longitude = longLat[0];
    float latitude = longLat[1];
    
    float u = longitude / (2 * PI) + 0.5;
    float v = latitude / PI + 0.5;
    return float2(u,v);
}

float3 longitudeLatitudeToPoint(float2 longLat) {
    float longitude = longLat[0];
    float latitude = longLat[1];

    float x;
    float y;
    float z;

    y = sin(latitude);
    float r = cos(latitude);
    x = sin(longitude) * r;
    z = -cos(longitude) * r;

    return float3(x, y, z);
}

float2 uvToLongitudeLatitude(float2 uv) {
    float longitude = (uv.x - 0.5) * (2 * PI);
    float latitude = (uv.y - 0.5) * PI;
    return float2(longitude, latitude);
}

float2 pointToLongitudeLatitude(float3 p) {
    float longitude = atan2(p.x, p.z);
    float latitude = asin(p.y);
    return float2(longitude, latitude);
}

float2 pointToUV(float3 p) {
    p = normalize(p);
    return longitudeLatitudeToUV(pointToLongitudeLatitude(p));
}

Это вычислительный шейдер, который я использую для преобразования карты высот в карту нормалей.

#pragma kernel CSMain
#include "GeoMath.hlsl"

Texture2D<float> _HeightMap;
RWTexture2D<float4> _NormalMap;
int _TextureSize_Width;
int _TextureSize_Height;
float _WorldRadius;
float _HeightMultiplier;

float3 CalculateWorldPoint(uint2 texCoord)
{
    float2 uv = texCoord / float2(_TextureSize_Width - 1, _TextureSize_Height - 1);
    float2 longLat = uvToLongitudeLatitude(uv);
    float3 spherePoint = longitudeLatitudeToPoint(longLat);

    float height01 = _HeightMap[texCoord].r + 1.0;
    float worldHeight = _WorldRadius + height01 * _HeightMultiplier;

    return spherePoint * worldHeight;
}

uint2 WrapIndex(uint2 texCoord)
{
    texCoord.x = (texCoord.x + _TextureSize_Width) % _TextureSize_Width;
    texCoord.y = max(min(_TextureSize_Height - 1, texCoord.y), 0);
    return texCoord;
}

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    float3 normalVector;

    float3 posNorth = CalculateWorldPoint(WrapIndex(id.xy + uint2(0, 1)));
    float3 posSouth = CalculateWorldPoint(WrapIndex(id.xy + uint2(0, -1)));
    float3 posEast = CalculateWorldPoint(WrapIndex(id.xy + uint2(1, 0)));
    float3 posWest = CalculateWorldPoint(WrapIndex(id.xy + uint2(-1, 0)));

    float3 dirNorth = normalize(posNorth - posSouth);
    float3 dirEast = normalize(posEast - posWest);
    normalVector = normalize(cross(dirNorth, dirEast));

    _NormalMap[id.xy] = float4(normalVector, 1.0);
}

И это результат, который я получаю, ниже карты высот (вверху), сгенерированной карты нормалей из кода выше (внизу)

Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
0
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я считаю, что вы пытаетесь получить нормали пространства объектов. Но не хватает крошечной детали. Возможные значения для нормализованного вектора3: -1..1 для каждой оси. И возможные значения для пикселя: 0..1.

Вам просто нужно настроить диапазоны.

Эта строка примерно решает проблему:

_NormalMap[id.xy] = float4(normalVector / 2 + float3(0.5, 0.5, 0.5), 1.0);

Результат

Большое спасибо, что указали на это. Эта проблема висела несколько дней.

Ann Anjell 18.11.2022 20:33

Другие вопросы по теме