Конвейер WebGL

Последнее обновление: 1.11.2015

Прежде чем приступить непосредственно к рисованию и созданию объектов, посмотрим, что собой представляет конвейер WebGL. Схематично его можно представить следующим образом:

Конвейер WebGL

Теперь разберем поэтапно.

  1. Вначале мы создаем набор вершин в буфере вершин (Vertex Buffer). По этим вершинам впоследствии будут составлены геометрические примитивы, а из примитивов - объекты. И проводим некоторую предобработку.

  2. Затем содержимое буфера вершин поступает на обработку в вершинный шейдер (Vertex Shader). Шейдер производит над вершинами некоторые трансформации, например, применяет матрицы преобразования и т.д. Шейдеры пишутся самим разработчиком, поэтому программист может применить различные преобразования по своему усмотрению.

  3. На следующем этапе (Primitive Assembly) конвейер получает результат вершинного шейдера и пытается измененные вершины сопоставить в отдельные примитивы - линии, треугольники, спрайты. Также на этом этапе определяется, входит ли примитив в видимое пространство. Если нет, то он обрезается. Оставшиеся примитивы передаются на следующий этап конвейера.

  4. Далее на этапе растеризации (Rasterization) полученные примитивы преобразуются в фрагменты, которые можно представить как пиксели, которые затем будут отрисованы на экране

  5. И затем в дело вступает фрагментный шейдер (Fragment shader). (В технологиях Direct3D, XNAпрямым аналогом является пиксельный шейдер). Фрагментый шейдер производит преобразования с цветовой составляющей примитивов, наполняет их цветом, точнее окрашивает пиксели, и в качестве вывода передает на следующий этап измененные фрагменты.

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

    1. Scissor Test: на этом этапе проверяется, находится ли фрагмент в пределах отсекающего прямоугольника. Если фрагмент находится в пределах этого прямоугольника, то он передается на следующий этап. Если же нет, то он отбрасывается и больше не принимает участия в обработке.

    2. Multisample Fragment Operations: на данном этапе у каждого фрагмента изменяются цветовые составляющие, производится сглаживание (anti-alising), чтобы объект выглядел более плавно на экране.

    3. Stencil Test: здесь фрагмент передается в буфер трафаретов (stencil buffer). Если вкратце, то в этом буфере дополнительно отбрасываются те фрагменты, которые не должны отображаться на экране. Как правило, данный буфер используется для создания различного рода эффектов, например, эффект теней.

    4. Depth Buffer Test - тест буфера глубины. В буфере глубины (depth buffer, а также называется, z-buffer) сравнивается z-компонента фрагмента, и если она больше значения в буфере глубины, то, следовательно, данный фрагмент расположен к смотрящему на трехмерную сцену ближе, чем предыдущий фрагмент, поэтому текущий фрагмент проходит тест. Если же z-компонента больше значения в буфере глубины, то, следовательно, данный фрагмент находится дальше, поэтому он не должен быть виден и отбрасывается.

    5. Blending: на данном этапе происходите небольшое смешение цветов, например, для создания прозрачных объектов.

    6. Dithering: здесь происходит смешение цветов, для создания тонов и полутонов.

  7. Frame Buffer: и здесь наконец полученные после предобработки фрагменты превращаются в пиксели на экране.

Итак, мы рассмотрели этапы конвейера. Данные этапы рисуют нам некоторый алгоритм действий, от которого затем мы будет отталкиваться. И реальности создание программы разбивается также на некоторые этапы:

  1. Создание и настройка шейдеров

  2. Создание и настройка буфера вершин, которые в последствии образуют геометрическую фигуру

  3. Отрисовка фигуры

Если мы посмотрим на простейшую программу по отрисовке треугольника из предыдущей главы, то увидим, что сначала срабатывают функция initShaders(), производящая инициализацию шейдеров и их настройку. Шейдеры являются обязательным звеном в конвейере WebGL, поэтому без них нам сложно будет построить программу.

Затем в дело вступает функция initBuffers(), устанавливающая буфер точек, по которым идет отрисовка.

И на финальном этапе происходит отрисовка в функции draw() - при помощи шейдеров буфер вершин превращается в геометрическую фигуру.

Далее приводится полный код программы:

<!DOCTYPE html>
<html>
<head>
<title>Привет WebGL!</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas3D" width="400" height="300">Ваш браузер не поддерживает элемент canvas</canvas>
<!-- фрагментный шейдер -->
<script id="shader-fs" type="x-shader/x-fragment">
  void main(void) {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
  }
</script>
<!-- вершинный шейдер -->
<script id="shader-vs" type="x-shader/x-vertex">
  attribute vec3 aVertexPosition;
  void main(void) {
    gl_Position = vec4(aVertexPosition, 1.0);
  }
</script>
<script type="text/javascript">
var gl;
var shaderProgram;
var vertexBuffer;
// установка шейдеров
function initShaders() {
	// получаем шейдеры
	var fragmentShader = getShader(gl.FRAGMENT_SHADER, 'shader-fs');
	var vertexShader = getShader(gl.VERTEX_SHADER, 'shader-vs');
	//создаем объект программы шейдеров
	shaderProgram = gl.createProgram();
	// прикрепляем к ней шейдеры
	gl.attachShader(shaderProgram, vertexShader);
	gl.attachShader(shaderProgram, fragmentShader);
	// связываем программу с контекстом webgl
	gl.linkProgram(shaderProgram);
	 
	if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
		alert("Не удалсь установить шейдеры");
	}
	 
	gl.useProgram(shaderProgram);
	// установка атрибута программы
	shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
	// подключаем атрибут для использования
	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
}
// Функция создания шейдера по типу и id источника в структуре DOM
function getShader(type,id) {
	var source = document.getElementById(id).innerHTML;
	// создаем шейдер по типу
	var shader = gl.createShader(type);
	// установка источника шейдера
	gl.shaderSource(shader, source);
	// компилируем шейдер
	gl.compileShader(shader);
  
	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
		alert("Ошибка компиляции шейдера: " + gl.getShaderInfoLog(shader));
		gl.deleteShader(shader);   
		return null;
	}
	return shader;  
}
// установка буфера вершин 
function initBuffers() {
 // установка буфера вершин
  vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // массив координат вершин объекта
  var triangleVertices = [
         0.0,  0.5,  0.0,
        -0.5, -0.5,  0.0,
         0.5, -0.5,  0.0
  ];
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
  // указываем кол-во точек
  vertexBuffer.itemSize = 3;
  vertexBuffer.numberOfItems = 3;
}
// отрисовка 
function draw() {    
	// установка области отрисовки
	gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);

	gl.clear(gl.COLOR_BUFFER_BIT);
  
	// указываем, что каждая вершина имеет по три координаты (x, y, z)
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
    // отрисовка примитивов - треугольников          
	gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems);
}
 
window.onload=function(){
	// получаем элемент canvas
	var canvas = document.getElementById("canvas3D");
	try {
		// Сначала пытаемся получить стандартный контекст WegGK. 
		// Если не получится, обращаемся к экспериментальному контексту
		gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
	}
	catch(e) {}
  
	// Если контекст не удалось получить, выводим сообщение
	  if (!gl) {
		alert("Ваш браузер не поддерживает WebGL");
	  }
	if(gl){
		// установка размеров области рисования
		gl.viewportWidth = canvas.width;
		gl.viewportHeight = canvas.height;
		// установка шейдеров 
		initShaders();
		// установка буфера вершин
		initBuffers();
		// покрасим в красный цвет фон
		gl.clearColor(1.0, 0.0, 0.0, 1.0);
		// отрисовка сцены
		draw();  
	}
}
</script>
</body>
</html>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850