Браузеры и драйверы

Разбор этой технологии стоит предварить ремаркой о том, как вообще получить к ней доступ. В настоящий момент вполне корректно отображает OpenGL контент-браузер Google Crome (или Chromium) — там она включена по умолчанию. Обозреватели Mozilla Fire-fox, Safari имеют поддержку WebGL в современных версиях, но ее нужно специально, явным образом включать. В 12-й версии Opera такая поддержка тоже была заявлена.

Internet Explorer… для него существуют плагины Chrome Frame и IEWebGL, которые помогут приобщиться к этой технологии пользователей данного браузера.

Гораздо большие проблемы может доставить неподходящая видеокарта. Для работы WebGL необходима поддержка последней, как минимум OpenGL 2. Если у вас относительно свежая графическая карта от ATI или Nvidia, проблем, скорее всего, не будет, а вот с оборудованием от Intel трудности могут возникнуть (хотя и не обязательно).

Вперед, в 3D!

Вообще говоря, сама по себе работа с 3D-графикой довольно сложна, и хоть сложность эта и не космического масштаба, описание математических методов расчета 3D-представлений, применение матричных вычислений лежит немного в стороне от темы нашего исследования, поэтому при малейшей необходимости мы будем пользоваться специальной JavaScript-библиотекой, принимающей на себя такого рода деятельность.

В любом случае, приступим. Для начала создадим HTML-разметку:

<html>

<head>

<script>

</script>

</head>

<body onload="init();">

<canvas id="webGLcanvas" style="border: none;" width="500" height="500"></ canvas>

</body>

</html>

На этом с HTML мы закончим. Все остальное будет делать JavaScript. Прежде всего напишем код инициализации WebGL-контекста:

Var gl;

Function init() {

Var canv = document. getElementById("webGLcanvas");

Gl = canv. getContext("experimental-webgl");

Gl. viewportHeight = canv. height;

Gl. viewportWidth = canv. width;

Gl. clearColor(1.0, 0.0, 1.0, 1.0);

Gl. clearDepth(1,0);

Gl. enable(gl. DEPTH_TEST);

Gl. clear(gl. COLOR_BUFFER_BIT | gl. DEPTH_BUFFER_BIT);

}

Если данный код у вашего браузера возражений не вызывает, значит, все в порядке. Результат же правильной работы тут не пока не очень впечатляет. Это просто неинтересный розовый квадрат.

Прежде чем двинуться дальше, давайте посмотрим, что мы тут, собственно, сделали?

Для начала мы инициализировали объект WebGL Rendering Context (gl), затем установили некоторые настройки — размеры, цвет фона. Установка enable(gl. DEPTH_TEST) отвечает за режим отображения фигур (в данном случае задние фигуры будут скрыты).

Последняя строчка выводит нашу сцену в браузер.

Сейчас я должен предупредить, что до момента появления какого-либо осмысленного результата, прежде чем будет нарисована самая примитивная картинка, нам придется сделать довольно много. Но зато доступ в мир WebGL мы гарантированно получим.

Впрочем, все не так страшно. Но для начала нам придется освоить несколько концепций, и прежде всего концепцию буфера. В данном случае буфер — это участок памяти видеокарты, куда мы записываем координаты вершин фигуры, которую хотим изобразить. Приступим:

MyShapeBuffer = gl. freateBuffer();

Gl. bindBuffer(gl. ARRAY_BUFFER, myShapeBuffer);

Var vertices =

[

0.0,

1.0,

0.0,

-0.7,

0.7,

0.0,

-1.0,

0.0,

0.0,

-0.7,

-0.7,

0.0,

0.0,

-1.0,

0.0,

0.7,

-0.7,

0.0,

1.0,

0.0,

0.0,

0.7,

0.7,

0.0,

0.0,

1.0,

0.0

];

Gl. bufferData(gl. ARRAY_BUFFER, new Float32Array(vertices), gl. STATIC_DRAW); myShapeBuffer. itemSize = 3; myShapeBuffer. гumltems = 8;

Для того чтобы понять, что мы делаем, сразу смотрим на рис. 63. Да, результат будет таким скромным, но надо же с чего-то начинать. Дальше будет интересней, обещаю.

Итак, в первой строчке мы создаем новый буфер. Далее задаем его тип и связываем с описанием вершин будущей фигуры.

Рис. 63. WebGL — начинаем создавать сцену

Вершины мы описываем массивом координат — по три цифры на вершину. Им соответствуют обычные координаты по трем осям, с началом координат в центре холста.

Далее мы снабжаем наш объект информацией о количестве цифр, описывающих вершину (itemSize), и количестве этих вершин. Все, объект в буфере мы построили, осталась мелочь — отрисовать его в браузере.

«Мелочь» тут, естественно, ирония, не будем забывать, что мы работаем с 3Б-сценой, где все непросто. Но и не смертельно сложно. Вперед. Код, отрисовывающий нашу фигуру, оформим в виде функции:

Function draw(varBuffer) {

Gl. viewport(0, 0, gl. viewportWidth, gl. viewportHeight): gl. clear(gl. COLOR_BUFFER_BIT | gl. DEPTH_BUFFER_BIT);

Mat4.perspective(45, gl. viewportWidth / gl. viewportHeight, 0.1, 100.0, pMatrix): mat4.identity(mvMatrix);

Mat4.translate(mvMatrix, [-0.5, -1.75, -5.0]); gl. bindBuffer(gl. ARRAY_BUFFER, varBuffer);

Gl. vertexAttribPointer(shaderProgram. vertexPositionAttribute, varBuffer. itemSize, gl. FLOAT, false, 0, 0); setMatrixUniforms();

Gl. drawArrays(gl. TRIANGLE_FAN, 0, varBuffer. numltems);

}

Здесь мы используем буферы, чтобы отрисовать изображения на холсте. Пройдемся пошагово по нашей функции:

Сначала мы сообщаем WebGL размеры холста:

Gl. viewport(0, 0, gl. viewportWidth, gl. viewportHeight):

Далее очищаем холст:

Gl. clear(gl. COLOR_BUFFER_BIT | gl. DEPTH_BUFFER_BIT);

Тут самое время вспомнить, что мы создаем ЗЭ-сцену, а это предполагает задание свойств перспективы и наблюдения. По умолчанию WebGL отрисовывает простую ортогональную проекцию. Чтобы изменить это положение вещей, выполняем следующую команду, устанавливающую перспективу и параметры, с которыми наблюдателю будет виден объект.

FluPerspective(45, gl. viewportWidth / gl. viewportHeight, 0.1, 100.0):

Тут мы задаем наше поле зрения по вертикали (45°), коэффициент ширины к высоте нашего холста и диапазон видимости (не ближе, чем 0,1 единицы к точке наблюдения, и не дальше, чем 100 от нее).

Все достаточно просто, но вот незадача: gluPerspective — это функция OpenGL, в WebGL ее нет, во всяком случае пока. Ее можно реализовать с помощью достаточно сложных и, самое главное, объемных матричных преобразований, воспроизводить и тем более излагать здесь которые у меня нет желания. Вместо этого мы (вслед за авторами пособия по WebGL Learning WebGL…lessons ‘n’ links… -Http://learningwebgl. com) воспользуемся JavaScript-библиотекой gl-matrix Брендона Джонса (Brandon Jones), реализующей матричные и векторные операции для WebGL. Скачать ее можно здесь: Https://github. com/toji/gl-matrix.

Подключаем gl-matrix в заголовке страницы:

<script type=”text/javascript” src=”glMatrix-0.9.5.js”></script>

Совершаем следующие подготовительные операции:

<script>

Var mvMatrix = mat4.create();

Function setMatrixUniforms() {

Gl. uniformMatrix4fv(shaderProgram. pMatrixUniform, false, pMatrix); gl. uniformMatrix4fv(shaderProgram. mvMatrixUniform, false, mvMatrix);

}

И используем:

Mat4.perspective(45, gl. viewportWidth / gl. viewportHeight, 0.1, 100.0, pMatrix); mat4.identity(mvMatrix);

В ранее объявленной переменной mvMatrix хранится модельно-видовая матрица нашей фигуры. Посредством метода identity мы преобразуем ее в единичную матрицу, устанавливая начальную точку нашей сцены. Ну а дальше начинаем движение:

Mat4.translate(mvMatrix, [-0.5, 0.0, -5.0]);

Тут мы перемещаем текущее положение внутри сцены влево и в глубину от наблюдателя.

Теперь связывааем с WebGL и ранее описанный буфер:

Gl. bindBuffer(gl. ARRAY_BUFFER, varBuffer);

Затем объявляем, что значения из него должны быть использованы как позиции вершин (это связано с понятием шейдеров, до которых мы еще доберемся):

Gl. vertexAttribPointer(shaderProgram. vertexPositionAttribute, varBuffer. itemSize, gl. FLOAT, false, 0, 0);

Следующим шагом будет транслирование наших преобразований в память видеокарты:

SetMatrixUniforms();

Эту функцию мы уже описали, ее загадочные компоненты будут рассмотрены позже.

Ну а теперь рисуем нашу фигуру:

Gl. drawArrays(gl. TRIANGLE_FAN, 0, varBuffer. numltems)

Тут мы «мостим» нашу фигуру треугольниками, создавая незаполненную область.

Все? К сожалению, нет. Сам по себе этот код ничего не нарисует. Но не стоит унывать, победа уже близка, осталось разобраться с понятием «шейдер».

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *