Упаковка int16 в fixed2 (красный + зеленый)

В Unity карта высот внутренне закорочена как Int16 (обратите внимание, что используется только 0-32767). Я хочу отправить карту высот в графический процессор, и в идеале использовать только 16-битные.

Кажется, что лучший способ сделать это - закодировать значение карты высот в текстуру рендеринга RG16 (поскольку в Unity я не могу выбрать одноканальный 16-битный целочисленный формат) и при необходимости упаковать / распаковать.

Вот текстура карты высот, которую я отправляю в графический процессор (через скрипт C# на стороне процессора):

const int Size = 1024;
Color32[] colours = new Color32[Size * Size];
for (int y = 0; y < Size; y++) {
    for (int x = 0; x < Size; x++) {
        float height = heights[y, x]; // With Unity it's correct to flip the x/y axes
        short s = (short)(heights[y, x] * short.MaxValue);

        byte upper = (byte)(s >> 7); // Shift 7 and not 8 since we don't want values outside of 0-32767 anyway.
        byte lower = (byte)(s & 255);

        colours[y * size + x] = new Color32(upper, lower, 0, 0);
    }
}
tex.SetPixels32(colours);
tex.Apply();

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

float HeightmapSample(float u, float v) {
    fixed2 height  = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
    int2 heightInt = height * 255.f;
    int unpacked   = (heightInt.r << 7) | heightInt.g;
    return unpacked / 32767.f; // Renormalize
}

И (возможно) прикольный метод с плавающей точкой:

float HeightmapSample(float u, float v) {
    fixed2 height = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
    return height.r + (height.g / 128.f) - (1.f / 128.f);
}

Оба метода не дают даже близких к основному факту: Что я получаю

1 ответ

Решение

После почти 2 дней поиска виновника я понял, что у меня есть шейдер, который неправильно кодирует карту высот каждый раз, когда загружается мой плагин. Я намеренно не исправил этот шейдер, потому что вместо этого сосредоточился на проблеме выше, но это оказалось проблемой!

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