Цвета в WebGL

Установка цвета вершины

Последнее обновление: 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">
varying highp vec4 vColor;
  void main(void) {
    gl_FragColor = vColor;
  }
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexColor;
varying highp vec4 vColor;
void main(void) {
    gl_Position = vec4(aVertexPosition, 1.0);
    vColor = vec4(aVertexColor, 1.0);
}
</script>
<script type="text/javascript">
var gl;
var shaderProgram;
var vertexBuffer; // буфер вершин
var colorBuffer; //буфер цветов
// установка шейдеров
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);

	gl.linkProgram(shaderProgram);
	 
	if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
		alert("Не удалось установить шейдеры");
	}
	 
	gl.useProgram(shaderProgram);

	shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
	shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
    gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
}
// Функция создания шейдера
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() {

var vertices = [
         0.0,  0.5,  0.0,
        -0.5, -0.5,  0.0,
         0.5, -0.5,  0.0
  ];
  // установка буфера вершин
  vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  vertexBuffer.itemSize = 3;
  vertexBuffer.numberOfItems = 3;
  var сolors = [
        1.0, 0.0, 0.0,
        0.0, 0.0, 1.0,
        0.0, 1.0, 0.0
	];
	colorBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(сolors), gl.STATIC_DRAW);
}
 // отрисовка
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.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                         vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, 
						vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
	
	gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems);
}
 
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>

После запуска у нас получится следующий красивый треугольничек:

Теперь разберем, что же тут происходит. Вначале рассмотрим основную программу WebGL, а потом шейдеры.

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

shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

Затем в функции initBuffers() задаем два буфера. Задание буфера цветов во многом похоже на буфер вершин:

var сolors = [
        1.0, 0.0, 0.0,
        0.0, 0.0, 1.0,
        0.0, 1.0, 0.0
	];
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(сolors), gl.STATIC_DRAW);

Значения 1.0, 0.0, 0.0 передает цвет первой вершины, в данном случае это красный цвет. Следующая тройка 0.0, 0.0, 1.0, окрашивает вторую вершину в синий цвет, а третья тройка - в зеленый.

Если при определении буфера вершин каждая тройка обозначает соответственно координаты x, y, z, то при определении буфера цветов три компоненты отвечают за значения rgb - то есть цветовые компоненты.

И далее похожим образом создаем буфер цветов и связываем с контекстом WebGL. Затем уже в функции отрисовки draw() у нас возникает проблема, что надо установить два атрибута - для передачи вершин и цветов. Поэтому мы производим установку последовательно: сначала для одного, потом для другого. А общий принцип одинаков для всех. Теперь перейдем к шейдерам, где эти атрибуты используются.

В вершинном шейдере мы получаем атрибуты, установленные в основной программе WebGL:

attribute vec3 aVertexPosition;
attribute vec3 aVertexColor;

Следующая переменная varying highp vec4 vColor; будет передавать цвет из вершинного шейдера во фрагментный. Поэтому у нее используется модификатор varying.

Затем в самой программе устанавливаются значения:

gl_Position = vec4(aVertexPosition, 1.0);
vColor = vec4(aVertexColor, 1.0);

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

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