Итак, для тех кто незнаком с этой чудесной технологией(вот как я например пару месяцев назад), и кому она интересна, предлагаю небольшой HelloWorld - на выходе получаем трехмерную вращающуюся пирамиду! (браузер firefox).
Официальна поддержка WebGL заявлена начиная с версий - opera 12, chrome 17, ff 4, safari 4
Данный пример будет полезен людям, имеющим опыт программирования на javascript которые теряются в спецификациях WebGL и не имеют опыта программирование на OpenGL ES2
Данный файл служит точкой входа в приложение. Он пробует подключить файл core.js и после его включения загружает и выполяет файл program1.js для свежесозданного canvas'а
Данный файл выполяет всю рутинную работу - он умеет создавать канвасы, и сокращает объем рутинных операций с инстансом webgl - контекста канвасов.
28.11.2012, 20:34
Arks
loader.js
(function(){
var glob = this, OK = true, scriptID = 0;
var map = function(ns, context) {
var parts = ns.split('.');
var cur = context || glob, next = parts.shift();
while(next) {
if(cur[next] == undefined) {
cur[next] = {};
}
cur = cur[next];
next = parts.shift();
}
return cur;
};
if(typeof(glob.XMLHttpRequest) !== 'function') {
OK = false;
}
glob.load = function(url, cb, ns, context, returnRaw) {
var xhr;
if(!OK) {
throw 'loader is not available';
}
xhr = new glob.XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send(null);
xhr.onreadystatechange = function(){
var resource, script;
if(xhr.readyState == 4) {
if(xhr.status == 200 || (xhr.status == 0 && glob.document.domain.length == 0)) {
var obj;
if(returnRaw == undefined) {
resource = glob.document.createElement('script');
resource.id = 'src_'+(++scriptID).toString();
resource.innerHTML = xhr.responseText;
glob.document.head.appendChild(resource);
if(glob.onload != undefined) {
obj = map(ns, context);
glob.onload.call(obj || glob);
delete glob.module;
script = document.getElementById('src_'+scriptID);
script.parentNode.removeChild(script);
if(cb != undefined) cb.call(obj || glob);
return;
}
throw('modules should provide method onload() to init theirs functions');
} else {
obj = map(ns, context);
if(cb != undefined) cb.call((obj || glob), xhr.responseText);
return;
}
}
throw('requested url is not available and return error status: '+xhr.status);
}
}
}
return glob.load;
})();
данный файл просто загружает другие файлы, и умеет или включать их в контекст другого json-объекта или просто отдает полученное содержимое. В зависимости от того что требуется
28.11.2012, 20:36
Arks
pyramyd.ibo
[
0,1,4,
1,2,4,
2,3,4,
3,0,4
]
данный файл содержит ID вершин - которые будут связаны между собой линиями, или в моем примере - образуют треугольники.
данный файл содержит код пиксельного шейдера, с помощью которого видеокарта осуществляет интерполяцию цветов пикселей, находящихся между опорными вершинами
данный файл содержит код вершинного шейдера, с помощью которого видеокарта преобразует исходные координаты объекта к координатам относительно наблюдателя.
Самый главный файл WebGL-приложения, который фактически и содержит всю внутреннюю логику и отвечает за рисование
28.11.2012, 21:28
Arks
Расскажу о терминологии WebGL и ее частей применительно к js(ES5):
типизированные массивы - встроенный объект js ES5
тут все просто - имеем массив например Uint16Array в который передаем в конструктор обычный массив. Видеокарточка и OpenGL понимает только подобные строго-типизированные массивы.
шейдер
является способом вывода картинки на экран. Шейдеры работают через физические конвейеры видеокарточки - конвейеров очень много так что шейдеры обрабатываются параллельно. Шейдеры пишутся на языке шейдеров OSL, который является по сути оберткой и вместе с тем урезанной версией C
пиксельный(или фрагментный) -
например у нас в 3-мерном пространстве заданы 3 точки, которые образуют в 3-мерном пространстве треугольник. Чтобы нарисовать его на экране не просто как 3 точки, а как часть плоскости заключенной между ними видеокарточка рассчитывает цвет каждого физического пикселя на экране, сравнивая по сложному интегральному алгоритму удаленность пикселя от 3 точек и "взвешивая" их цвета. В моем примере пиксельный шейдер просто возвращает один цвет(серый) для каждого пикселя. В реальной жизни используются модели Фонга, Блинна, Орена-Нейера и прочие их разновидности. Лично я изучал геометрическую и прочую оптику в институте и поэтому меня от их упрощений тошнит.
вершинный
например у нас в 3-мерном пространстве заданы 3 точки. Вершинный шейдер это просто функция, которая применяется к каждой из этих точек и позволяет преобразовать исходные координаты в 2-мерные координаты "на экране
буфер
разновидность хеш-объекта который хранится в памяти видеокарты. Так уж сложилось что в процессе выполнения программы, она работает одновременно лишь с один выбранным буфером (gl.bindBuffer). Соответственно между буферами можно переключаться, менять их содержимое, рисовать их содержимое(передавать в так называемый frame-буффер) и т.д.
атрибут
переменная в памяти видеокарты которая относится к шейдеру и позволяет передать в него данные "извне", т.е. из javascript
постоянная(uniform)
переменная в памяти видеокарты, которая относится к программе(ко всем шейдерам) и позволяет передать в них данные "извне" - не может меняться в процессе обработки внутри шейдеров
переменная шейдеров(varying)
переменная которая служит для передачи данных из вершинного шейдера в пиксельный(в моем примере оно не нужно и не используется)
матрицы, векторы
типы данных языка шейдеров. фактически обычные массивы(2-х, 3-х и 4-х элементные), расширенные доп. плюшками из алгебры - типа быстрых алгоритмов перемножения. Для javascript в моем примере их возможности эмулируются сторонней библиотекой gl-matrix-min.js
Часто бывает удобно, пусть и более медленно, один раз рассчитать матрицу на js чем почти мгновенно, но 100500 раз в каждом шейдере(помните, вершинный шейдер применяется к каждой вершине)
вершины
не относятся как таковые к терминологии. Фактически явлются хеш-объектами вида { <index>: [<x>,<z>,<y>]}
отсюда и взялось разделение на буферы координат вершин и буферы индексов вершин
программа
некая муть содержащая скомпилированные в машинный код шейдеры, заполненные координатами/индексами буферы, а также константы(uniform) и атрибуты(attribute) для передачи в шейдеры
28.11.2012, 21:43
Arks
Небольшая памятка по часто-используемым функциям:
gl.clearColor(float r, float g, float b, float a): void
установка gl.COLOR_CLEAR_VALUE, установка цвета для gl.clear
gl.getParameter(gl.COLOR_CLEAR_VALUE): Float32Array
получение цвета для очистки холста в удобочитаемом виде
gl.clear(gl.COLOR_BUFFER_BIT):void
очистка холста
gl.viewport(x,y,w,h)
установка поля зрения
gl.createBuffer():WebGLBuffer
создание буффера
gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUF FER, WebGLBuffer buffer):void
переключение буффера в работу
gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUF FER, null):void
отключение от текущего буффера
gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUF FER, data, <type>):void
установка данных в буффер; константы STATIC, DYNAMYC, STREAM
gl.createShader(gl.FRAGMENT_SHADER|gl.VERTEX_SHADE R):glShader
создание шейдера заданного типа
gl.shaderSource(glShader shader, sourceString):void
установка текста шейдера
gl.compileShader(glShader shader):void
компиляция шейдера в инструкции GPU
gl.createProgram():glProgram
создание программы обработки
gl.attachShader(glProgram program, glShader shader):void
привязка шейдера к программе
gl.linkProgram(glProgram program):void
линковка скомпилированных шейдеров в исполняемый код программы
gl.getProgramParameter(glProgram program, gl.LINK_STATUS)
получение статуса сборки программы
gl.useProgram(glProgram program):void
установка готовой собранной программы для GPU
gl.getAttribLocation(glProgram program, nameString):reference
получение ссылки на атрибут где-то в собранной программе
gl.getUniformLocation(glProgram program, nameString):reference
получение ссылки на константу выполнения
30.11.2012, 01:23
Arks
Предлагаю также тыкнуть на "спасибку" всем кому эта тема была интересна. А то, может, и зря старался...
Напомниаю - вопросы по WebGL, этому коду или технологии в ваших решениях можете смело задавать в skype
Буду рад ответить как новичкам, так и по вопросам расчета сложной оптики и освещения по законам геометрической оптики, дисперсии, дифракции, интерференции и расчету интенсивности и спектра отраженных лучей.
Планирую в дальшейшем расписать в теме законы преломления и отражения света приманительно к матричной алгебре если время до НГ позволит...
Тему открыл, но будет очень жесткая модерация.
Так что пишите свои пожелания по освещению вопросов WebGL