Cg (сокращение от C for Graphics[1]) — высокоуровневый язык программирования, разработанный Nvidia в тесном сотрудничестве с Microsoft для программирования шейдеров. Cg основан на языке программирования C. Несмотря на то, что они имеют один и тот же синтаксис, некоторые функции C были изменены и добавлены новые типы данных, чтобы сделать Cg более подходящим для программирования графических процессоров. Этот язык специализирован для программирования графического процессора и не используется для GPGPU. Компилятор Cg выводит программы шейдеров DirectX или OpenGL. С 2012 года Cg устарела, без дополнительной поддержки.[2]
Из-за технических достижений в компьютерной графике некоторые области программирования 3D-графики стали довольно сложными. Чтобы упростить процесс, к графическим картам были добавлены новые функции, в том числе возможность изменять свои конвейеры рендеринга с использованием шейдеров.
Вначале шейдеры программировались на очень низком уровне и только на языке ассемблера. Хотя использование языка ассемблера дало программисту полный контроль над кодом и гибкостью, его было довольно сложно использовать. Был необходим более удобный язык высокого уровня для программирования графического процессора, поэтому Cg был создан для решения этих проблем и упрощения разработки шейдеров.
Некоторые из преимуществ Cg:
Cg имеет шесть основных типов данных. Некоторые из них такие же, как в C, но есть и другие, специально добавленные для программирования графического процессора. Эти типы:
float
— 32-битное число с плавающей запятойhalf
— 16-битное число с плавающей запятойint
— 32-битное целое числоfixed
— 12-битное число с фиксированной запятойbool
— логическая переменнаяsampler*
— представляет собой объект текстурыCg также содержит векторные и матричные типы данных, основанные на базовых типах данных, такие как float3
и float4x4
. Такие типы данных довольно распространены при работе с 3D программированием. Cg также имеет типы данных структуры и массива, которые работают аналогично их C-эквивалентам.
Cg поддерживает широкий диапазон операторов, включая общие арифметические операторы из C, эквивалентные арифметические операторы для векторных и матричных типов данных и общие логические операторы.
Cg поддерживает основные структуры управления из C, такие как if ... else
, while
и for
. Он также имеет аналогичный способ определения функций.
Как и в C, Cg имеет набор функций для общих задач программирования графического процессора. Некоторые из функций имеют эквиваленты в C, как математические функции abs
и sin
, в то время как другие специализируются на задачах графического программирования, такие как функции отображения текстуры tex1D
и tex2D
.
Программы Cg — это только шейдеры, и им нужны поддерживающие программы, которые обрабатывают остальную часть процесса рендеринга. Cg можно использовать с двумя графическими API: OpenGL или DirectX. Каждый из них имеет свой собственный набор функций для связи с программой Cg, например, с установкой текущего шейдера Cg, передачей параметров и т. п.
Помимо возможности скомпилировать исходный код Cg для сборки, время выполнения Cg также имеет возможность компилировать шейдеры во время выполнения поддерживающей программы. Это позволяет компиляции шейдера с помощью последних оптимизаций, доступных для аппаратного обеспечения, на котором в данный момент выполняется программа. Однако для этого метода требуется, чтобы исходный код для шейдера был доступен в виде обычного текста компилятору, позволяя пользователю программы получить доступ к исходному коду для шейдера. Некоторые разработчики рассматривают это как главный недостаток этой техники.
Чтобы избежать раскрытия исходного кода шейдера и по-прежнему поддерживать некоторые из конкретных аппаратных оптимизаций, была разработана концепция профилей. Шейдеры могут быть скомпилированы в соответствии с различными графическими аппаратными платформами (в соответствии с профилями). При выполнении поддерживающей программы наиболее оптимизированный шейдер загружается в соответствии с его профилем. Например, может быть профиль для видеокарты, поддерживающей сложные шейдеры, и другой профиль, который поддерживает только минимальные шейдеры. Создавая шейдер для каждого из этих профилей, поддерживающая программа увеличивает количество поддерживаемых платформ, не жертвуя качеством изображения на мощных системах.
// input vertex
struct VertIn {
float4 pos : POSITION;
float4 color : COLOR0;
};
// output vertex
struct VertOut {
float4 pos : POSITION;
float4 color : COLOR0;
};
// vertex shader main entry
VertOut main(VertIn IN, uniform float4x4 modelViewProj) {
VertOut OUT;
OUT.pos = mul(modelViewProj, IN.pos); // calculate output coords
OUT.color = IN.color; // copy input color to output
OUT.color.z = 1.0f; // blue component of color = 1.0f
return OUT;
}