Листинг 1

struct MyVertexInputs {
	float3 vxPosition : POSITION;
	float3 vxNormal : NORMAL;
	};

Листинг 2

technique noPixelShaderVersion
{...};
technique PixelShaderVersion
{...};
technique FixedFunctionVersion
{...};
technique LowDetailVersion
{...};

Листинг 3

technique PixelShaderVersion
{
	pass p0 {
	VertexShader = compile vs_1_1 goochVS(wvp,liteColor,lightPos);
	}
}

Листинг 4

vertexOutput vertexShader(
	appdata IN,
	uniform float4 liteColor,
	uniform float4 darkColor,
	uniform float3 LightPos)
{
		vertexOutput OUT;
/* Здесь проводим всевозможные вычисления c данными вершин и записываем их в OUT */
		return OUT;
		}
pixelOutput pixelShader(
	vertexOutput IN,
	uniform sampler2D colorMap)
{
	pixelOutput OUT;
/* Здесь проводим всевозможные вычисления c данными пикселов и записываем их в OUT */
	return OUT;
}

Листинг 5

float4 lightPos : Position
<
	string Object = ?PointLight?;
	string Space = ?World?;
	> = {100.0f, 100.0f, 100.0f, 0.0f};

float4 liteColor : Diffuse
<
	string Desc = ?Basic Surface Color?;
	> = {0.8f, 0.5f, 0.1f, 1.0f}; 

Листинг 6

/* Первые две строки позволяют задать текстовое описание шейдера,
 которое будет отображено в поле настройки */
string Category = ?Учебные шейдеры?;
string description = ?Мой первый шейдер?;
/* Ниже мы объявляем внешнюю переменную — видовую матрицу преобразования.
 Ее использование обязательно
 в вершинном шейдере для корректного отображения модели */
float4x4 wvp : WorldViewProj;

float4 lightPos : Position
<
	string Object = ?PointLight?;
	string Space = ?World?;
> = {100.0f, 100.0f, 100.0f, 0.0f};

float4 liteColor : Diffuse
<
	string Desc = ?Basic Surface Color?;
> = {0.8f, 0.5f, 0.1f, 1.0f};

/* Объявим структуру входных данных для вершинного шейдера. На его вход будут поданы
 координаты вершины (POSITION) и ее нормаль (NORMAL) */
struct appdata {
	float4 Position	: POSITION;
	float4 Normal	: NORMAL;
};
/* Выходная структура, в которой используется дополнительное поле цвета вершины */
struct vertexOutput {
	float4 ps	: POSITION;
	float4 diffCol	: COLOR0;
};
/* Объявляем функцию, выполняющую роль вершинного шейдера, в ее входных параметрах задаются
 импортированные из внешней программы переменные */
vertexOutput goochVS(appdata IN,
	uniform float4x4 wvp,
	uniform float4 liteColor,
	uniform float4 LightPos) 
{
/* OUT - структура, которую мы после возвратим из функции */
	vertexOutput OUT;
/* Это простейший пример преобразований в шейдере.
 Сначала мы находим скалярное произведение между нормалью
 к вершине и позицией источника света.
 Напомню, что его значение будет стремиться к нулю,
 если угол между векторами приближается к 90°.
 Далее полю цвета выходной структуры присваиваем
 заданный пользователем цвет, деленный на косинус полученного значения.
 Поделив цвет на косинус, мы тем самым создаем неравномерное
 распределение цветовых составляющих в пространстве.
 Результат смотрите на рис.3 */
	float ug = dot(IN.Normal, LightPos);
	OUT.diffCol = liteColor/cos(ug); 
/* Это обязательная операция для всех вершинных шейдеров. Каждая вершина
 перемножается на видовую матрицу преобразований */
	OUT.ps = mul(wvp, IN.Position);
/* И наконец, возвращаем результат пиксельному шейдеру, которого
 в нашем случае просто нет, а значит, результат поступает сразу на выход из шейдера */
	return OUT;
}

technique PixelShaderVersion
{
	pass p0 {
/* Таким образом мы определяем, что вышеописанная функция
 является шейдером и должна быть компилирована.
 На самом деле в теле эффектов можно использовать
 и старый ?ассемблероподобный? код, но тогда нужно указывать asm вместо compile.
 Аббревиатура vs_1_1 определяет версию требуемого оборудования,
 на котором сможет работать данный шейдер.
 В данном случае речь идет об оборудовании,
 поддерживающем шейдеры версии 1.1 (GeForce3 поддерживает 1.3) */
	VertexShader = compile vs_1_1 goochVS(wvp,liteColor,lightPos);
	}
}

technique NoPixelShaderVersion
{
	pass p0 {
	VertexShader = compile vs_1_1 goochVS(wvp,liteColor,lightPos);
	}
}
502