Использование шейдеров в программе

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

В прошлой главе мы рассмотрели настройку и использование буферов и отрисовку примитивов, оставив на будущее работу шейдеров. Теперь рассмотрим использование шейдеров в программе и для примера возьмем небольшое веб-приложение, которое рисует набор линий:

<!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(0.0, 1.0, 0.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; // буфер вершин
var indexBuffer; //буфер индексов
// установка шейдеров
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);
}
// Функция создания шейдера - запускается для обоих шейдеров
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() {

	vertices =[ -0.5, -0.5, 0.0,
				-0.5, 0.5, 0.0,
				 0.0, 0.0, 0.0,
				 0.5, 0.5, 0.0, 
				 0.5, -0.5, 0.0];

    indices = [0, 1, 1, 2, 2, 3, 3, 4];

  vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  vertexBuffer.itemSize = 3;
  
  indexBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
	gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
	indexBuffer.numberOfItems = indices.length;
}
 
function draw() {    
	gl.clearColor(0.0, 0.0, 0.0, 1.0);
	gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
	gl.clear(gl.COLOR_BUFFER_BIT);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
	gl.drawElements(gl.LINES, indexBuffer.numberOfItems, gl.UNSIGNED_SHORT,0);
}
 
window.onload=function(){

	var canvas = document.getElementById("canvas3D");
	try {
		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();
		
		draw();  
	}
}
</script>
</body>
</html>

Здесь нас интересуют две функции: initShaders() и getShader(). Поскольку создание обоих шейдеров предусматривает однотипные операции, все эти операции были вынесены в отдельную функцию getShader(). В эту функцию передаются два параметра: type (тип шейдера) и id элемента, который содержит код шейдера. Поскольку метод gl.createShader() может создавать шейдеры обоих типов, то в этот метод в качестве параметра и передаем тип создаваемого шейдера. В качестве типа используем встроенные константы gl.FRAGMENT_SHADER и gl.VERTEX_SHADER

В функции initShaders() мы создаем оба шейдера и инициализируем программу шейдеров shaderProgram и затем устанавливаем атрибут.

Потом уже в функции отрисовке через программу шейдеров мы используем ранее созданные шейдеры. Таков вкратце общий механизм использования шейдеров.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850