2016-08-09 4 views
0

В некоторых WebGL приложения, давайте предположим, что у нас есть вершинный шейдер GLSL, которая начинается так:WebGL: Как привязать значения к атрибуту mat4?

attribute vec4 foo1; 
attribute vec4 foo2; 
attribute vec4 foo3; 
attribute vec4 foo4; 

и некоторые соответствующий Javascript код для привязки структуры данных для этих атрибутов:

var buf = gl.createBuffer(), loc; 
gl.bindBuffer(gl.ARRAY_BUFFER, buf); 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([…])); 

loc = gl.getAttribLocation(program, 'foo1'); 
gl.enableVertexArray(loc); 
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 0); 

loc = gl.getAttribLocation(program, 'foo2'); 
gl.enableVertexArray(loc); 
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 4); 

loc = gl.getAttribLocation(program, 'foo3'); 
gl.enableVertexArray(loc); 
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 8); 

loc = gl.getAttribLocation(program, 'foo4'); 
gl.enableVertexArray(loc); 
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 12); 

сейчас , в соответствии со спецификациями GL ES 2.0 атрибут вершинного шейдера может быть определен как float, vec2, vec3, vec4, mat2, mat3 или mat4.

Так что, если изменить код вершинного шейдера определить только один атрибут mat4, как так ...

attribute mat4 foo; 

... вопрос в том , что соответствующий JS-код, чтобы связать некоторые указатели на mat4 атрибут?

Я нашел вопрос mat3 attribute in WebGL, но ответ не достаточно явный. Читая ответы и некоторые другие документы, то кажется, что правильное решение по линиям:

loc = gl.getAttribLocation(program, 'foo'); 
gl.enableVertexArray(loc); 
gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 16, 0); 
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 16, 4); 
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 16, 8); 
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 16, 12); 

я прав в предположении, что расположение 4 vec4 компонентов mat4 соседствовали всегда и в порядке возрастания? Является ли это документированным где-то?

Помимо этих местоположений, считающихся с пределом MAX_VERTEX_ATTRIBS (обычно 16 в WebGL), есть ли какая-либо другая хорошая практика, о которой нужно знать?

ответ

3

Вы правы. From the spec раздел 2.10.4

Когда переменная атрибут объявлен как mat2, ее столбцы матрицы взяты из (x, y) компонентов общих атрибутов i и i + 1. Когда переменная атрибута объявляется как mat3, ее столбцы матрицы берутся из компонентов (x, y, z) общих атрибутов i - i + 2. Когда переменная атрибута объявляется как mat4, ее столбцы матрицы берутся из компонентов (x, y, z, w) общих атрибутов i - i + 3.

шага и смещения в WebGL в байтах, так что я подозреваю, что вы хотели

gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 64, 0); 
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 64, 16); 
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 64, 32); 
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 64, 48); 

Давайте проверим

var vs = ` 
 
attribute mat4 matrix; 
 
attribute vec4 color; 
 

 
varying vec4 v_color; 
 

 
void main() { 
 
    gl_PointSize = 10.0; 
 
    gl_Position = matrix * vec4(0, 0, 0, 1); 
 
    v_color = color; 
 
} 
 
`; 
 
var fs = ` 
 
precision mediump float; 
 

 
varying vec4 v_color; 
 

 
void main() { 
 
    gl_FragColor = v_color; 
 
} 
 
`; 
 

 
var m4 = twgl.m4; 
 
var gl = document.querySelector("canvas").getContext("webgl"); 
 
var program = twgl.createProgramFromSources(gl, [vs, fs]); 
 

 
var matrixLoc = gl.getAttribLocation(program, "matrix"); 
 
var colorLoc = gl.getAttribLocation(program, "color"); 
 

 
function r(min, max) { 
 
    if (max === undefined) { 
 
    max = min; 
 
    min = 0; 
 
    } 
 
    return Math.random() * (max - min) + min; 
 
} 
 

 
var numPoints = 100; 
 
var matrices = []; 
 
var colors = []; 
 
for (var ii = 0; ii < numPoints; ++ii) { 
 
    matrices.push.apply(matrices, m4.translation([r(-1,1), r(-1,1), 0])); 
 
    colors.push(r(1), r(1), r(1), 1); 
 
} 
 

 
var buffers = twgl.createBuffersFromArrays(gl, { 
 
    matrices: matrices, 
 
    colors: colors, 
 
}); 
 

 
gl.useProgram(program); 
 

 
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.matrices); 
 
for (var ii = 0; ii < 4; ++ii) { 
 
    gl.enableVertexAttribArray(matrixLoc + ii); 
 
    gl.vertexAttribPointer(matrixLoc + ii, 4, gl.FLOAT, 0, 64, ii * 16); 
 
} 
 

 
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.colors); 
 
gl.enableVertexAttribArray(colorLoc); 
 
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, 0, 0, 0); 
 

 
gl.drawArrays(gl.POINTS, 0, numPoints);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/twgl-full.min.js"></script> 
 
<canvas></canvas>

+0

Спасибо - что особенно немного спецификации ускользала от меня ! (также я скопировал код слишком быстро, чтобы указать байты из 4-байтных групп отдельно) – IvanSanchez