Как я могу установить цвет пикселя на холсте, используя WebGL?

Я очень новичок в WebGL, но не Javascript или Canvas. По сути, мне нужен очень быстрый способ, чтобы иметь возможность изменять цвет пикселя на холсте по любой координате. Я чувствую, что это можно сделать с помощью фрагментных шейдеров WebGL. Возможно ли это, и есть ли лучший способ? Как бы я поступил так?

 Stefan Haustein17 июн. 2012 г., 23:49
Всего один пиксель? Или много пикселей? Для одного пикселя издержки вызова могут быть хуже, чем просто использование Canvas2D.
 nondefault18 июн. 2012 г., 00:03
Много пикселей. Это возможно с imageData, но слишком медленно для 400x400 пикселей.
 nondefault18 июн. 2012 г., 05:44
Возможно, они будут из массива. Спасибо за помощь, хотя!
 Stefan Haustein18 июн. 2012 г., 00:25
Откуда вы получаете данные пикселей? Если вы можете вычислить значения в шейдере все в одном пакете, WebGL будет быстрее. Если вы получаете данные из массива, WebGL может быть не намного быстрее, чем imageData.

Ответы на вопрос(3)

вы бы передавали массив точек в GPU вместе с цветами и позициями. Затем вы вызываете drawArrays с правильными данными.

Это может быть слишком связано с другими вещами, но это может помочь вам:

https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L126

https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L260

Вот так я рендерил несколько точек в примитивном блоке для chesterGL.

вам, вероятно, лучше использовать Canvas 2d.

В противном случае вы, вероятно, сможете понять это из этого урока, который рисует прямоугольники в пиксельных единицах, поэтому установите ширину и высоту равными 1x1, и вы получите отдельные пиксели.

http://games.greggman.com/game/webgl-fundamentals/

Решение Вопроса

потому что оно не включает в себя биты об управлении шейдерами; вместо этого он фокусируется на том, как на самом деле выполняется рисование примитивов WebGL, и как использовать ортографическую проекцию для точного позиционирования вершин на экране.

Для получения дополнительной информации я настоятельно рекомендую эти источники:

Learning WebGL - tutorials The WebGL specification The Typed Arrays specification

WebGL выполняет все свои чертежи с использованием объектов Vertex Buffer (VBO), поэтому вам необходимо скомпилировать все ваши данные в трехмерные вершины и отправить их на видеокарту за минимально возможное количество VBO (чтобы максимизировать производительность).

VBO может быть создан в WebGL следующим образом:

var vbo = gl.createBuffer();

Затем вам нужно отправить данные в буфер, обычно в видеFloat32Array, Если у вас уже есть данные в виде обычного массива JavaScript, вы можете использоватьnew Float32Array(jsArray) инициализироватьFloat32Array отjsArrayсодержание. Попробуйте сделать это редко, хотя. Типизированные массивы очень быстрые, но инициализируются очень медленно. Лучше всего создать их один раз и использовать их всякий раз, когда это возможно.

Как только у вас естьFloat32ArrayВы можете передать данные в буфер следующим образом:

gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);

Вам необходимо выполнитьbufferData или жеbufferSubData звоните каждый раз, когда данные изменяются.

К этому времени данные уже на видеокарте, так что вам нужно только на самом делеdraw Это:

// bind the VBO to be drawn if you haven't already
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// send the vertex data to the shader program
gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// draw the buffer
gl.drawArrays(gl.POINTS, 0, float32Data.length / 3);

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

Причина длиныFloat32Array делится на 3, потому что каждый отдельный элемент данных является 3D (X, Y, Z) координатой, поэтому каждый элемент данных состоит из 3-х компонентов с плавающей точкой. Обратите внимание, что первый аргументgl.drawArrays былоgl.POINTS, Это дает графической карте команду рисовать одну точку (по умолчанию размер одного пикселя) для каждого элемента в массиве. Есть и другие способы рисования, и если вам нужноfill группа пикселей, один из других режимов рисования (например,gl.TRIANGLES) может быть больше по вкусу.

Что касается освещения определенных пикселей, это зависит от того, как пишется шейдер, ноmost likely Вы используете матрицу вида модели и матрицу проекции. Матрица просмотра модели представляет ориентацию камеры относительно нарисованных точек, а матрица проекции представляет размеры камеры (ширина и высота, поле обзора, ближайшие и самые дальние видимые диапазоны и т. Д.). Поэтому, если вы хотите осветить определенные пиксели, лучше всего применитьorthographic проекционная матрица с шириной и высотой, равной ширине и высоте холста; и матрицу вида модели, установленную на идентичность (без преобразования). В ортогональной проекции объекты не уменьшаются по мере удаления от камеры, поэтому они очень полезны для определения точных положений относительно экрана. Кроме того, если вы дадите им правильные размеры, вы можете очень точно расположить вершины -at specific pixelsесли хочешь.

Разные матричные библиотеки работают по-разному, но, например, для настройки орфографической матрицы вл-матрица, вы можете сделать это так:

var ortho = mat4.ortho(left, right, bottom, top, near, far);

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

var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);

Обратите внимание, что значение Z каждой точки все еще должно лежать междуnear а такжеfar для того, чтобы быть оказанным, однако, иnear значение не может быть установлено в0.

Дайте мне знать, если что-то из этого требует уточнения.

Ваш ответ на вопрос