@@ -197,4 +197,197 @@ v_color, который мы объявили.
197
197
198
198
// ищем, куда должны идти данные вершин.
199
199
var positionLocation = gl.getAttribLocation(program, "a_position");
200
- + var colorLocation = gl.getAttribLocation(program, "a_color");
200
+ + var colorLocation = gl.getAttribLocation(program, "a_color");
201
+ ...
202
+ + // Создаем буфер для цветов.
203
+ + var buffer = gl.createBuffer();
204
+ + gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
205
+ +
206
+ + // Устанавливаем цвета.
207
+ + setColors(gl);
208
+
209
+ // настраиваем атрибуты
210
+ ...
211
+ + // говорим атрибуту цвета, как извлекать данные из текущего ARRAY_BUFFER
212
+ + gl.enableVertexAttribArray(colorLocation);
213
+ + var size = 4;
214
+ + var type = gl.FLOAT;
215
+ + var normalize = false;
216
+ + var stride = 0;
217
+ + var offset = 0;
218
+ + gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
219
+
220
+ ...
221
+
222
+ +// Заполняем буфер цветами для 2 треугольников
223
+ +// которые составляют прямоугольник.
224
+ +function setColors(gl) {
225
+ + // Выбираем 2 случайных цвета.
226
+ + var r1 = Math.random();
227
+ + var b1 = Math.random();
228
+ + var g1 = Math.random();
229
+ +
230
+ + var r2 = Math.random();
231
+ + var b2 = Math.random();
232
+ + var g2 = Math.random();
233
+ +
234
+ + gl.bufferData(
235
+ + gl.ARRAY_BUFFER,
236
+ + new Float32Array(
237
+ + [ r1, b1, g1, 1,
238
+ + r1, b1, g1, 1,
239
+ + r1, b1, g1, 1,
240
+ + r2, b2, g2, 1,
241
+ + r2, b2, g2, 1,
242
+ + r2, b2, g2, 1]),
243
+ + gl.STATIC_DRAW);
244
+ +}
245
+
246
+ И вот результат.
247
+
248
+ {{{example url="../webgl-2d-rectangle-with-2-colors.html" }}}
249
+
250
+ Обратите внимание, что у нас есть 2 треугольника сплошного цвета. Тем не менее, мы передаем значения
251
+ в * varying* , поэтому они варьируются или интерполируются по
252
+ треугольнику. Просто мы использовали тот же цвет на каждой из 3 вершин
253
+ каждого треугольника. Если мы сделаем каждый цвет разным, мы увидим
254
+ интерполяцию.
255
+
256
+ // Заполняем буфер цветами для 2 треугольников
257
+ // которые составляют прямоугольник.
258
+ function setColors(gl) {
259
+ // Делаем каждую вершину разным цветом.
260
+ gl.bufferData(
261
+ gl.ARRAY_BUFFER,
262
+ new Float32Array(
263
+ * [ Math.random(), Math.random(), Math.random(), 1,
264
+ * Math.random(), Math.random(), Math.random(), 1,
265
+ * Math.random(), Math.random(), Math.random(), 1,
266
+ * Math.random(), Math.random(), Math.random(), 1,
267
+ * Math.random(), Math.random(), Math.random(), 1,
268
+ * Math.random(), Math.random(), Math.random(), 1]),
269
+ gl.STATIC_DRAW);
270
+ }
271
+
272
+ И теперь мы видим интерполированный * varying* .
273
+
274
+ {{{example url="../webgl-2d-rectangle-with-random-colors.html" }}}
275
+
276
+ Не очень захватывающе, я полагаю, но это демонстрирует использование более чем одного
277
+ атрибута и передачу данных от вершинного шейдера к фрагментному шейдеру. Если
278
+ вы посмотрите на [ примеры обработки изображений] ( webgl-image-processing.html ) ,
279
+ вы увидите, что они также используют дополнительный атрибут для передачи координат текстуры.
280
+
281
+ ## Что делают эти команды буфера и атрибута?
282
+
283
+ Буферы - это способ получения данных вершин и других данных на вершину на
284
+ GPU. ` gl.createBuffer ` создает буфер.
285
+ ` gl.bindBuffer ` устанавливает этот буфер как буфер для работы.
286
+ ` gl.bufferData ` копирует данные в текущий буфер.
287
+
288
+ Как только данные находятся в буфере, нам нужно сказать WebGL, как извлекать данные из
289
+ него и предоставлять их атрибутам вершинного шейдера.
290
+
291
+ Для этого сначала мы спрашиваем WebGL, какие локации он назначил
292
+ атрибутам. Например, в коде выше у нас есть
293
+
294
+ // ищем, куда должны идти данные вершин.
295
+ var positionLocation = gl.getAttribLocation(program, "a_position");
296
+ var colorLocation = gl.getAttribLocation(program, "a_color");
297
+
298
+ Как только мы знаем локацию атрибута, мы выдаем 2 команды.
299
+
300
+ gl.enableVertexAttribArray(location);
301
+
302
+ Эта команда говорит WebGL, что мы хотим предоставить данные из буфера.
303
+
304
+ gl.vertexAttribPointer(
305
+ location,
306
+ numComponents,
307
+ typeOfData,
308
+ normalizeFlag,
309
+ strideToNextPieceOfData,
310
+ offsetIntoBuffer);
311
+
312
+ И эта команда говорит WebGL получать данные из буфера, который был последним
313
+ привязан с gl.bindBuffer, сколько компонентов на вершину (1 - 4), какой
314
+ тип данных (` BYTE ` , ` FLOAT ` , ` INT ` , ` UNSIGNED_SHORT ` , и т.д.), шаг
315
+ который означает, сколько байт пропустить, чтобы получить от одного куска данных к
316
+ следующему куску данных, и смещение для того, как далеко в буфере находятся наши данные.
317
+
318
+ Количество компонентов всегда от 1 до 4.
319
+
320
+ Если вы используете 1 буфер на тип данных, то и шаг, и смещение могут
321
+ всегда быть 0. 0 для шага означает "использовать шаг, который соответствует типу и
322
+ размеру". 0 для смещения означает начать с начала буфера. Установка
323
+ их в значения, отличные от 0, более сложна, и хотя это может иметь некоторые
324
+ преимущества с точки зрения производительности, это не стоит усложнения, если только
325
+ вы не пытаетесь довести WebGL до его абсолютных пределов.
326
+
327
+ Я надеюсь, что это проясняет буферы и атрибуты.
328
+
329
+ Вы можете взглянуть на эту
330
+ [ интерактивную диаграмму состояния] ( /webgl/lessons/resources/webgl-state-diagram.html )
331
+ для другого способа понимания того, как работает WebGL.
332
+
333
+ Далее давайте пройдемся по [ шейдерам и GLSL] ( webgl-shaders-and-glsl.html ) .
334
+
335
+ <div class =" webgl_bottombar " ><h3 >Для чего нужен normalizeFlag в vertexAttribPointer?</h3 >
336
+ <p >
337
+ Флаг нормализации предназначен для всех не-плавающих типов. Если вы передаете
338
+ false, то значения будут интерпретироваться как тип, которым они являются. BYTE идет
339
+ от -128 до 127, UNSIGNED_BYTE идет от 0 до 255, SHORT идет от -32768 до 32767 и т.д...
340
+ </p >
341
+ <p >
342
+ Если вы устанавливаете флаг нормализации в true, то значения BYTE (-128 до 127)
343
+ представляют значения -1.0 до +1.0, UNSIGNED_BYTE (0 до 255) становятся 0.0 до +1.0.
344
+ Нормализованный SHORT также идет от -1.0 до +1.0, просто у него больше разрешения, чем у BYTE.
345
+ </p >
346
+ <p >
347
+ Самое распространенное использование нормализованных данных - для цветов. Большую часть времени цвета
348
+ идут только от 0.0 до 1.0. Использование полного float для каждого красного, зеленого, синего и альфа
349
+ использовало бы 16 байт на вершину на цвет. Если у вас сложная геометрия, это
350
+ может сложиться в много байт. Вместо этого вы могли бы конвертировать ваши цвета в UNSIGNED_BYTE,
351
+ где 0 представляет 0.0, а 255 представляет 1.0. Теперь вам понадобилось бы только 4 байта на цвет
352
+ на вершину, экономия 75%.
353
+ </p >
354
+ <p >Давайте изменим наш код, чтобы делать это. Когда мы говорим WebGL, как извлекать наши цвета, мы бы использовали</p >
355
+ <pre class =" prettyprint showlinemods " >
356
+ var size = 4;
357
+ * var type = gl.UNSIGNED_BYTE;
358
+ * var normalize = true;
359
+ var stride = 0;
360
+ var offset = 0;
361
+ gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
362
+ </pre >
363
+ <p >И когда мы заполняем наш буфер цветами, мы бы использовали</p >
364
+ <pre class =" prettyprint showlinemods " >
365
+ // Заполняем буфер цветами для 2 треугольников
366
+ // которые составляют прямоугольник.
367
+ function setColors(gl) {
368
+ // Выбираем 2 случайных цвета.
369
+ var r1 = Math.random() * 256; // 0 до 255.99999
370
+ var b1 = Math.random() * 256; // эти значения
371
+ var g1 = Math.random() * 256; // будут обрезаны
372
+ var r2 = Math.random() * 256; // когда сохранены в
373
+ var b2 = Math.random() * 256; // Uint8Array
374
+ var g2 = Math.random() * 256;
375
+
376
+ gl.bufferData(
377
+ gl.ARRAY_BUFFER,
378
+ new Uint8Array( // Uint8Array
379
+ [ r1, b1, g1, 255,
380
+ r1, b1, g1, 255,
381
+ r1, b1, g1, 255,
382
+ r2, b2, g2, 255,
383
+ r2, b2, g2, 255,
384
+ r2, b2, g2, 255]),
385
+ gl.STATIC_DRAW);
386
+ }
387
+ </pre >
388
+ <p >
389
+ Вот этот пример.
390
+ </p >
391
+
392
+ {{{example url="../webgl-2d-rectangle-with-2-byte-colors.html" }}}
393
+ </div >
0 commit comments