2011-01-26 2 views
9

Я пишу шейдер (HLSL), и мне нужно упаковать значение цвета в формат R32. Я нашел различные фрагменты кода для упаковки float в формат R8G8B8A8, но ни один из них, похоже, не работает в обратном порядке. Я нацелен на SM3.0, поэтому (afaik) бит-операции не являются опцией.Пакет четыре байта в поплавке

Подводя итог, я должен быть в состоянии сделать это:

float4 color = ...; // Where color ranges from 0 -> 1 
float packedValue = pack(color); 

Любой знает, как это сделать?

UPDATE
Я получил некоторых продвижения вперед ... возможно, это поможет прояснить этот вопрос.
Мое временное решение как таковое:

const int PRECISION = 64; 

float4 unpack(float value) 
{ 
    float4 color; 

    color.a = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.b = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.g = value % PRECISION; 
    value = floor(value/PRECISION); 

    color.r = value; 

    return color/(PRECISION - 1); 
} 

float pack(float4 color) 
{ 
    int4 iVal = floor(color * (PRECISION - 1)); 

    float output = 0; 

    output += iVal.r * PRECISION * PRECISION * PRECISION; 
    output += iVal.g * PRECISION * PRECISION; 
    output += iVal.b * PRECISION; 
    output += iVal.a; 

    return output; 
} 

Я в основном ... делая вид, я использую целые типы: S
Через предположение и проверить, 64 было наибольшее число я мог бы использовать при сохранении a [0 ... 1]. К сожалению, это также означает, что я теряю некоторую точность - 6 бит вместо 8.

+2

В конце концов, вас спросят, так что вы могли бы также решить это. Почему вы должны использовать R32 вместо целочисленного формата? – eodabash

+0

Хех ... Я знал, что это придет, но все же ... На самом деле, я использую R32G32B32A32, я только сказал, что R32 упрощает. Я просто пытаюсь понять, как я могу записать как можно больше информации в одну цель рендеринга. Конечно, мне все же нужно делать некоторые измерения, но я думаю, что все мои данные в одну цель визуализации немного дешевле, чем использование четырех через MRT. – YellPika

+0

Я с нетерпением жду, чтобы узнать, какие ответы люди могут придумать для этого вопроса. – Olhovsky

ответ

1

взглянуть на: http://diaryofagraphicsprogrammer.blogspot.com/2009/10/bitmasks-packing-data-into-fp-render.html

Короткий ответ, что это невозможно сделать без потерь упаковки 4 поплавков в 1 поплавок.

Даже если вы нашли способ упаковать 4 поплавки, сохранив их экспоненту и значимость, процесс упаковки и распаковки может быть непомерно дорогостоящим.

+1

Ну, на самом деле (и, как говорится в названии) я пытаюсь собрать четыре байта, а не четыре поплавка. Я видел этот пост раньше, хотя. К сожалению, в коде используются битовые операторы - не произойдет с использованием SM3.0 ... :( – YellPika

+0

Вы можете заменить биты с умножениями. Например, 'x << 16' - это то же самое, что и' x * = 2^16' – Olhovsky

+0

Oh , хотя он использует битмаски, и вы не можете использовать их в SM3.0. – Olhovsky

1

Похоже, что ваш образец кода для 3-х компонентов упаковывает их в s = значение и выполняет exp2 (color.g) (1 + s), чтобы упаковать другой компонент в экспоненту. Вы по-прежнему теряете точность, но это будет не так плохо, как если бы вы пытались упаковать все в значимые, как вы, кажется, делаете.

К сожалению, нет возможности избежать потери точности, так как есть куча значений поплавка NaN и Inf, которые неотличимы друг от друга и с трудом работают (и, возможно, даже не поддерживаются вашим GPU, в зависимости от того, сколько лет это).

Смежные вопросы