Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
323 views
in Technique[技术] by (71.8m points)

attributes - Stride vs offset for mat4 attrib

I was reading this answer on SO where someone was pulling a mat4 attribute.

When setting up the vertex attrib array, there was one thing I noticed:

gl.vertexAttribPointer(row3Location, floatsPerRow, gl.FLOAT, 
                   false, bytesPerMatrix, row3Offset);

I understand that the mat4 being supplied takes up 4 attribute slots, but why do we pass bytesPerMatrix as the stride instead of something like bytesPerRow? Shouldn't each attribute slot pull 16 bytes from its offset instead of 64?

This is how I imagine a stride of 16 bytes and offsets being multiples of 16.

0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF
^---------------
                ^---------------
                                ^---------------
                                                ^---------------

And this is how I imagine a stride of 64 bytes and offsets being multiples of 16.

0000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF
^---------------------------------------------------------------
                ^---------------------------------------------------------------
                                ^---------------------------------------------------------------
                                                ^---------------------------------------------------------------
^ considerable overlap when pulling attributes for matrix

So, clearly my mental model of stride and offset is wrong. How does this actually work? Why does the stride need to be the size of the whole matrix when this attribute is only pulling the equivalent of a vec4 at a time?

question from:https://stackoverflow.com/questions/65907954/stride-vs-offset-for-mat4-attrib

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The stride is how many bytes to skip to get to the next value for that attribute. For a mat3 there are 3 attributes, one for each row of the matrix. The data for each attribute, assuming you put your matrices in a buffer linearly next to each other, is:

|        Matrix0        |        Matrix1        |        Matrix2        | ...
| row0  | row1  | row2  | row0  | row1  | row2  | row0  | row1  | row2  | ...
| x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | ...

so the first attribute wants data for row0, for each matrix. To get from row0 in the first matrix to row0 in the second matrix is bytesPerMatrix

|        Matrix0        |        Matrix1        |        Matrix2        | ...
| row0  | row1  | row2  | row0  | row1  | row2  | row0  | row1  | row2  | ...
| x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | x,y,z | ...
| --- bytesPerMatrix -->|
                        | --- bytesPerMatrix -->|
                                                | --- bytesPerMatrix -->|

stride is how many bytes to skip to get to the next value, not how many bytes to read. How many bytes to read is defined by the size and type parameters of the attribute as in

const size = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = bytesPerMatrix;
const offset = row * bytesPerRow
gl.vertexAttribPointer(location, size, type, normalize, stride, offset);

So above because size = 3 and type = FLOAT it will read 12 bytes.

The process is

  1. start at offset bytes in the buffer
  2. read 12 bytes from the buffer and apply them to the attribute's value
  3. add stride to offset
  4. goto 2

for however many vertices you asked it to process.

note: that assumes you actually put your data in the buffer one matrix after another. You don't have to do that. You could put all row0s next to each other, followed by all row1s, followed by all row2s. Or you could even put all row0s in a different buffer from row1s and row2s. I don't think I've ever seen anyone do that but just pointing it out that the way described at the top is not set it stone. It's just the most common way.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...