netlib.narod.ru | < Назад | Оглавление | Далее > |
В каждом шейдере есть таблица констант, используемая для хранения его переменных. Библиотека D3DX обеспечивает приложению доступ к таблице констант шейдера через интерфейс ID3DXConstantTable. Через этот интерфейс мы можем устанавливать значения переменных шейдера из кода нашего приложения.
Сейчас мы приведем сокращенный список методов, реализуемых интерфейсом ID3DXConstantTable. Если вам необходим полный список, обратитесь к документации Direct3D.
Чтобы установить значение какой-нибудь переменной шейдера из кода нашего приложения, необходим способ сослаться на эту переменную. Для этой цели применяется тип D3DXHANDLE. Приведенный ниже метод возвращает значение типа D3DXHANDLE, указывающее на переменную шейдера с заданным именем:
D3DXHANDLE ID3DXConstantTable::GetConstantByName( D3DXHANDLE hConstant, // область видимости LPCSTR pName // имя );
hConstant — Значение D3DXHANDLE задающее родительскую структуру запрашиваемой переменной, определяющую время ее жизни. Например, если мы хотим получить дескриптор отдельного члена объявленной в шейдере структуры данных, то здесь нам надо указать дескриптор этой структуры. Если мы получаем дескриптор переменной самого верхнего уровня, в этом параметре передается 0.
pName — указанное в исходном коде шейдера имя переменной, для которой мы получаем дескриптор.
Например, если имя переменной в коде шейдера ViewProjMatrix и это переменная верхнего уровня, то для получения дескриптора следует написать:
// Получение дескриптора переменной шейдера ViewProjMatrix D3DXHANDLE h0; h0 = ConstTable->GetConstantByName(0, "ViewProjMatrix");
Как только наше приложение получило значение D3DXHANDLE, ссылающееся на требуемую переменную в коде шейдера, мы можем установить значение этой переменной из нашего приложения с помощью метода ID3DXConstantTable::SetXXX, где XXX заменяется на название типа переменной, значение которой устанавливается. Например, если мы хотим установить значения массива векторов, следует воспользоваться методом SetVectorArray.
Общий синтаксис всех методов ID3DXConstantTable::SetXXX выглядит так:
HRESULT ID3DXConstantTable::SetXXX( LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, XXX value );
pDevice — Указатель на устройство с которым связана таблица констант.
hConstant — Дескриптор, ссылающийся на переменную, значение которой мы устанавливаем.
value — Присваиваемое переменной значение, где XXX заменяется на название типа переменной, значение которой мы устанавливаем. Для некоторых значений (bool, int, float) мы передаем само значение, а для других (векторы, матрицы, структуры) — ссылку на значение.
Если мы инициализируем массив, то у метода SetXXX появляется дополнительный четвертый параметр, задающий количество элементов массива. Например, прототип метода для установки значений массива четырехмерных векторов, выглядит так:
HRESULT ID3DXConstantTable::SetVectorArray( LPDIRECT3DDEVICE9 pDevice, // связанное устройство D3DXHANDLE hConstant, // дескриптор переменной шейдера CONST D3DXVECTOR4* pVector, // указатель на массив UINT Count // количество элементов массива );
Приведенный ниже список описывает типы, которые мы можем инициализировать с помощью интерфейса ID3DXConstantTable. Подразумевается, что корректное устройство (Device) и корректный дескриптор переменной (handle) уже получены.
SetBool — используется для установки логических значений. Пример вызова:
bool b = true; ConstTable->SetBool(Device, handle, b);
SetBoolArray — Используется для установки массива логических значений. Пример вызова:
bool b[3] = {true, false, true}; ConstTable->SetBoolArray(Device, handle, b, 3);
SetFloat — Используется для установки значения с плавающей точкой. Пример вызова:
float f = 3.14f; ConstTable->SetFloat(Device, handle, f);
SetFloatArray — Используется для установки массива значений с плавающей точкой. Пример вызова:
float f[2] = {1.0f, 2.0f}; ConstTable->SetFloatArray(Device, handle, f, 2);
SetInt — Используется для установки целочисленного значения. Пример вызова:
int x = 4; ConstTable->SetInt(Device, handle, x);
SetIntArray — Используется для установки массива целых чисел. Пример вызова:
int x[4] = {1, 2, 3, 4}; ConstTable->SetIntArray(Device, handle, x, 4);
SetMatrix — Используется для установки матрицы 4 × 4. Пример вызова:
D3DXMATRIX M(...); ConstTable->SetMatrix(Device, handle, &M);
SetMatrixArray — Используется для установки массива матриц 4 × 4. Пример вызова:
D3DXMATRIX M[4]; // ...Инициализация матриц ConstTable->SetMatrixArray(Device, handle, M, 4);
SetMatrixPointerArray — Используется для установки массива указателей на матрицы 4 × 4. Пример вызова:
D3DXMATRIX* M[4]; // ...Выделение памяти и инициализация указателей ConstTable->SetMatrixPointerArray(Device, handle, M, 4);
SetMatrixTranspose — используется для установки транспонированной матрицы 4 × 4. Пример вызова:
D3DXMATRIX M(...); D3DXMatrixTranspose(&M, &M); ConstTable->SetMatrixTranspose(Device, handle, &M);
SetMatrixTransposeArray — Используется для установки массива транспонированных матриц 4 × 4. Пример вызова:
D3DXMATRIX M[4]; // ...Инициализация матриц и их транспонирование ConstTable->SetMatrixTransposeArray(Device, handle, M, 4);
SetMatrixTransposePointerArray — Используется для установки массива указателей на транспонированные матрицы 4 × 4. Пример вызова:
D3DXMATRIX* M[4]; // ...Выделение памяти, инициализация указателей и транспонирование ConstTable->SetMatrixTransposePointerArray(Device, handle, M, 4);
SetVector — Используется для установки переменной типа D3DXVECTOR4. Пример вызова:
D3DXVECTOR4 v(1.0f, 2.0f, 3.0f, 4.0f); ConstTable->SetVector(Device, handle, &v);
SetVectorArray — Используется для установки массива векторов. Пример вызова:
D3DXVECTOR4 v[3]; // ...Инициализация векторов ConstTable->SetVectorArray(Device, handle, v, 3);
SetValue — Используется для установки значения произвольного размера, например, структуры. В приведенном примере мы используем SetValue для установки значений D3DXMATRIX:
D3DXMATRIX M(...); ConstTable->SetValue(Device, handle, (void*)&M, sizeof(M));
Приведенный ниже метод присваивает всем константам значения по умолчанию, то есть те значения, которые были заданы при объявлении переменных. Метод должен вызываться один раз при инициализации данных приложения.
HRESULT ID3DXConstantTable::SetDefaults( LPDIRECT3DDEVICE9 pDevice );
pDevice — Указатель на связанное с таблицей констант устройство.
Мы можем скомпилировать шейдер, код которого хранится в текстовом файле, с помощью следующей функции:
HRESULT D3DXCompileShaderFromFile( LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable );
pSrcFile — Имя текстового файла, содержащего исходный код шейдера, который вы хотите скомпилировать.
pDefines — Необязательный параметр, и в данной книге мы всегда будем указывать в нем null.
pInclude — Указатель на интерфейс ID3DXInclude. Этот интерфейс разработан для тех приложений, которым требуется переопределить устанавливаемое по умолчанию поведение включения. В общем случае поведение по умолчанию замечательно работает и поэтому мы игнорируем данный параметр, передавая в нем null.
pFunctionName — Строка, задающая имя функции, являющейся точкой входа. Например, если точкой входа шейдера является функция с именем Main, мы должны передать в этом параметре строку «Main».
pTarget — Строка, задающая версию шейдеров для которой будет компилироваться исходный код HLSL. Для вершинных шейдеров доступны версии vs_1_1, vs_2_0, vs_2_sw. Для пиксельных шейдеров доступны версии ps_1_1, ps_1_2, ps_1_3, ps_1_4, ps_2_0, ps_2_sw. Например, если мы хотим чтобы наш вершинный шейдер был скомпилирован для версии 2.0, надо указать в этом параметре vs_2_0.
Flags — Необязательные флаги компиляции; если флаги не нужны, укажите 0. Можно использовать следующие значения:
D3DXSHADER_DEBUG — Приказывает компилятору включать в скомпилированный файл отладочную информацию.
D3DXSHADER_SKIPVALIDATION — Приказывает компилятору не выполнять проверку корректности кода. Этот флаг следует использовать только при работе с теми шейдерами в правильности кода которых вы абсолютно уверены.
D3DXSHADER_SKIPOPTIMIZATION — Приказывает компилятору не выполнять оптимизацию кода. Обычно этот флаг используется при отладке, когда вы не хотите, чтобы компилятор вносил какие-либо изменения в код.
ppShader — Возвращает указатель на интерфейс ID3DXBuffer, который содержит скомпилированный код шейдера. Этот скомпилированный код затем передается в параметре другой функции, которая выполняет фактическое создание вершинного или пиксельного шейдера.
ppErrorMsgs — Возвращает указатель на интерфейс ID3DXBuffer, содержащий строку с кодами обнаруженых при компиляции ошибок и их описанием.
ppConstantTable — Возвращает указатель на интерфейс ID3DXConstantTable, содержащий данные таблицы констант шейдера.
Вот пример вызова функции D3DXCompileShaderFromFile:
// // Компиляция шейдера // ID3DXConstantTable* TransformConstantTable = 0; ID3DXBuffer* shader = 0; ID3DXBuffer* errorBuffer = 0; hr = D3DXCompileShaderFromFile( "transform.txt", // имя файла шейдера 0, 0, "Main", // имя точки входа "vs_2_0", // версия шейдеров D3DXSHADER_DEBUG, // компиляция для отладки &shader, &errorBuffer, &TransformConstantTable); // Выводим сообщения об ошибках if(errorBuffer) { ::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0); d3d::Release<ID3DXBuffer*>(errorBuffer); } if(FAILED(hr)) { ::MessageBox(0, "D3DXCreateEffectFromFile() - FAILED", 0, 0); return false; }
netlib.narod.ru | < Назад | Оглавление | Далее > |