glBegin(GL_TRIANGLES);
glColor3d(1,0,0);
glVertex3d(1,2,3);
glColor3d(0,1,0);
glVertex3d(4,5,6);
glColor3d(0,0,1);
glVertex3d(7,8,9);
glVertex3d - это вершины нашего треугольника, Название функции интуитивно понятно, но 3d, как ни странно, не означает «трехмерный»; точнее, 3 - как раз означает, а вот d - это тип аргументов (double). GL_TRIANGLES указывает, что все последующие вершины будут последовательно образовывать треугольники (если бы у нас было не три, а шесть вершин - получилось бы два треугольника). glColor3d принимает на вход цветовые компоненты RGB, и все вершины, идущие после него и до следующего вызова glColor, будут иметь соответствующий цвет.
В D3D перед рисованием необходимо подготовить специальную структуру данных:
struct CUSTOMVERTEX { FLOAT x, y, z, rhw; DWORD color;};
CUSTOMVERTEX g_Vertices[] =
{1, 2, 3, 1, 0xffff0000},
{4, 5, 6, 1, 0xff00ff00},
{7, 8, 9, 1, 0xff0000ff},
LPDIRECT3DVERTEXBUFFER8 p_VertexBuffer = NULL;
Эта структура содержит и координаты вершин, и их цвета. p_VertexBuffer - указатель на нашу структуру, для хранения вершин.
Теперь напишем следующее:
d3d_Device-›CreateVertexBuffer (3*sizeof(CUSTOMVERTEX),
0, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, amp;p_VertexBuffer);
VOID* pVertices;
p_VertexBuffer-›Lock (0, sizeof(g_Vertices), (BYTE**) amp;pVertices, 0);
memcpy (pVertices, g_Vertices, sizeof(g_Vertices));
p_VertexBuffer-›Unlock();
CreateVertexBuffer - выделяет место на устройстве под три вершины (3*sizeof(CUSTOMVERTEX),) и присваивает его нашему указателю (p_VertexBuffer). Далее «запираем» (Lock()) буфер вершин, чтобы случайно его не повредить. Копируем весь наш буфер (memcpy()) в буфер видеокарты. И снова разрешаем доступ (Unlock();).
И наконец, мы готовы к рисованию:
d3d_Device-›BeginScene ();
d3d_Device-›SetVertexShader (D3DFVF_CUSTOMVERTEX);
d3d_Device-›SetStreamSource (0, p_VertexBuffer, sizeof(CUSTOMVERTEX));
d3d_Device-›DrawPrimitive (D3DFVF_XYZRHW | D3DFVF_DIFFUSE, 0, 1);
d3d_Device-›EndScene ();
SetVertexShader() определяет тип вершин. SetStreamSource() задает поток для дальнейшей работы. Здесь 0 - номер потока, второй параметр - данные, которые присваиваются к этому потоку, и третий параметр - размер, занимаемый в памяти одной вершиной. DrawPrimitive - рисует примитивы на экране, принимает на вход (в порядке следования) тип примитивов для отрисовки, индекс первой вершины, с которой нужно начать рисование, и количество примитивов в последовательности.