| demo.design 3D programming FAQ | download | links | author

ОСВЕЩЕНИЕ
5.6. Как совместить текстуру и освещение

Прежде всего, немного теории. Нам понадобится знать то, что конечный цвет пиксела с составляющими (r,g,b) и освещенного цветом (light_r,light_g,light_b) считается как

result_r = r * light_r / max(light_r);
result_g = g * light_g / max(light_g);
result_b = b * light_b / max(light_b);

Здесь max(light_r) - это максимально возможное значение для light_r. Не максимальное по всем тем градациям освещенности, что мы используем, а вообще максимальное для всех возможных градаций. Например, если у нас значения для light_r могут гулять от 0 до 255, а текущий источник света имеет цвет (30, 40,50), то соответственно градации освещенности будут равны (k*30,k*40,k*50), где 0 <= k <= 1, то max(light_r) = 255, а не 30. Немного путаное объяснение, но вообще это известная и понятная почти всем вещь.

5.6.1. 256-цветные режимы

Метод 1: заранее посчитать таблицу, переводящую пару (цвет, освещенность) в цвет. Можно не менять палитру, а искать для каждой пары (цвет, освещенность) наилучшим образом приближающий ее цвет; а можно (как описано в demo.design FAQ) взять палитру и сгенерировать из нее true color картинку 256x256, в которой пиксел (x, y) нарисован цветом (уже true color!), соответствующим цвету x и освещенности y, а потом перевести ее чем-нибудь типа Image Alchemy в 256 цветов. После чего использовать палитру получившейся картинки, а в качестве таблицы (colorTable) будет сама получившаяся картинка:

outputColor = colorTable[intensity][color].

Метод 2: если нас устроит использовать немного цветов и градаций освещения, то тогда в палитру можно впихнуть все возможные градации всех используемых цветов. Тогда определение нужного индекса в палитре - это одно умножение, а лучше - сдвиг, и одно сложение. Пример: пусть у нас есть 8 цветов и 32 градации освещенности. Палитру заполняем так: 32 градации первого цвета, второго, ..., восьмого. Тогда (для этого примера)

outputColor = (color << 5) + intensity.

5.6.2. 24/32-битные режимы

Здесь все делается теми же самыми таблицами. Только таблица переводит не цвет в цвет, а компоненту цвета в компоненту цвета. То есть, создаем таблицы redTable[numShades], greenTable[numShades], blueTable[numShades], а потом для каждой компоненты каждого пиксела и нужной градации освещенности по этой таблице определяем выходное значение компоненты:

r = redTable[intensity],
g = greenTable[intensity],
b = blueTable[intensity].

Каждая компонента в этих режимах - это отдельный байт, поэтому никаких проблем не возникает.

5.6.3. 15/16-битные режимы

Метод 1: тупой, но действенный. Использовать большую таблицу и занести в нее все возможные комбинации цвета и градации освещения. Таблица получится совсем не маленькая, размером 65536*32 = 2 мегабайта. Я написал здесь 32, потому как в этих режимах на компоненту отводится по 5 бит (за исключением 6-битной зеленой компоненты в 16-битном режим), и делать больше градаций освещенности, чем 32, бессмысленно.

Метод 2: делать все так же, как в 24/32-битных режимах. Проблемы возникнут из-за того, что придется с муками выдирать нужные несколько бит компоненты из пиксела. Таблицы для компонент лучше заранее сделать со всеми нужными сдвигами, т.е. значения элементов таблиц должны быть такого вида:

    000bbbbb          - синий, 8 бит
    00000gggggg00000  - зеленый, 16 бит
    rrrrr000          - красный, 8 бит

Тогда конечный цвет считается примерно так:

    outputColor =
       (redTable[(color >> 10) & 0x2F] << 8) +
      greenTable[(color >> 5) & 0x1F] +
       blueTable[color & 0x1F].

На ассемблере это делается, видимо, побыстрее - и покрасивее. Примерно так:

    ; ...
    mov  bx,color
    shr  bx,10
    and  bx,02Fh
    mov  ah,redTable[bx]
    mov  bx,color
    and  bx,01Fh
    mov  al,blueTable[bx]
    mov  bx,color
    shr  bx,5      ; можно заменить на
    and  bx,01Fh   ;   shr  bx,4
    shl  bx,1      ;   and  bx,02Eh
    or   ax,greenTable[bx]
    mov  outputColor,ax
    ; ...

Метод 3: рисовать все в 24/32-бита, освещение соответсвенно с текстурой совмещать по пункту 5.6.2, а потом непосредственно при выводе на экран делать преобразование из 24/32-бит в 15/16. Или использовать PTC и предоставить делать нужное преобразование именно ему. PTC - это такая графическая система для C++, взять ее можно на http://www.gaffer.org/ptc.

| demo.design 3D programming FAQ | previous | content | next