Матричные операции, выполняемые на графическом процессоре, могут быть довольно сложными для отладки, потому что операции с графическим процессором на самом деле не допускают консольные журналы.
Я написал один, разработанный для движка 2D-рендеринга в реальном времени, основанный на очень простой форме, я думаю, что можно назвать преобразованием лучей, и у меня возникают проблемы с выяснением, что с ним не так (он выводит [0,0,0,255,0,0,0,255,...]
вместо заполнения цвета).
this.thread.x
- индекс текущей единицы измерения (цветовой канал) в используемой матрице.
scene
- это буфер, состоящий из 6-ю блоков, каждое значение которых содержит в порядке:
Тип сущности, в данном случае всегда 1
для «спрайта».
Идентификатор спрайта, соответствующий индексу в this.constants.textures
, содержащему буфер для спрайта объекта.
X смещение, левый край спрайта
Y смещение, верхний край спрайта
ширина спрайта
высота спрайта
bufferWidth
- ширина области рендеринга, умноженная на 4 канала.
this.constants.textures
- это массив, содержащий буферы каждого спрайта, на которые ссылаются идентификаторы спрайта из scene
.
Примечание. Для любопытных это делается с помощью GPU.js , библиотеки JavaScript, которая преобразует функцию JS в код GLSL для запуска через WebGL.
function(scene, sceneLength, bufferWidth) {
var channel = this.thread.x % 4;
if (channel === 3) {
return 255;
}
var x = this.thread.x % bufferWidth;
var y = Math.floor(this.thread.x / bufferWidth);
for (let i1 = 0; i1 < sceneLength; i1 += 6) {
var id = scene[i1 + 1];
var x1 = scene[i1 + 2];
var y1 = scene[i1 + 3];
var w1 = scene[i1 + 4];
var h1 = scene[i1 + 5];
var r1 = scene[i1 + 6];
var offsetX1 = x1 - x;
if (offsetX1 > 0 && offsetX1 < w1) {
var offsetY1 = y1 - y;
if (offsetY1 > 0 && offsetY1 < h1) {
var c1 = offsetY1 * w1 * 4 + offsetX1 * 4;
var c1R = c1 - (c1 % 4);
var c1A = c1R + 3;
if (this.constants.textures[id][c1A] != 0) {
return this.constants.textures[id][c1];
}
}
}
}
return 0;
}
Объяснение концепции, которую я пытаюсь реализовать:
В матричной операции, когда вы хотите нарисовать спрайт, если бы вы выполняли проход по всей области рендеринга, вы выполняли бы гораздо больше работы, чем необходимо. Если вы разбиваете область рендеринга на куски и обновляете только секции, задействованные в прорисовываемом спрайте, это будет вполне приличный способ сделать это. Это было бы достаточно для рендеринга игр в реальном времени. Это был бы многопроходный подход, когда спрайты отображаются по одному.
В качестве альтернативы, для того, что мне кажется наиболее оптимальным подходом, вместо этого мы можем использовать однопроходный подход, который выполняет одну матричную операцию для всей области рендеринга, оценивая для каждого цветового канала то, что должно быть основанный на выполнении очень простой формы обнаружения столкновений с каждым спрайтом в сцене и соответствующим пикселем в этом спрайте.