Giter Club home page Giter Club logo

Comments (4)

greggman avatar greggman commented on August 29, 2024 2

Sorry I didn't respond to this.

As the article says

OpenGL claims computer science rows are columns

So

[
   1, 2, 3, 4,
   5, 6, 7, 8,
   9,10,11,12,
  13,14,15,16,
]

Is interpreted as

[
  1, 5, 9,13,
  2, 6,10,14,
  3, 7,11,15,
  4, 8,12,16,
]

Another way to write your code would be like this

const firstColumn = 
  1,
  2,
  3,
  4,
];

const secondColumn = 
  5,
  6,
  7,
  8,
];

const thirdColumn = 
  9,
  10,
  11,
  12,
];

const forthColumn =
  13,
  14,
  15,
  16,
];

const mathMatrix = [ ...firstColumm, ...secondColumn, ...thirdColumn, ...forthColumn ];

I don't know if that helps visualize how OpenGL want's you to see it or not but above I declared four column looking things and then at the bottom I laid them left to right as columns.

If you print mathMatrix though it will print 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 which if interpreted as a 4x4 matrix in computer science is generally called considered row 1 being 1,2,3,4 but OpenGL says think of that as a column.

Then the math works as you expect right?

As for not being able to transpose the matrices I have no idea why they chose that except that OpenGL ES 2.0 was designed for fairly low powered machines. The transpose takes extra time so in the interest of pushing devs to write optimal code maybe they required it to be false. As for why it's there at all OpenGL ES 2.0 is based on or at least inspired by OpenGL (not ES) where that parameter already existed so rather than change the API to not have the parameter they left it there but require it to be false. Similar to the border parameter on texImage2D.

from webgl2-fundamentals.

frozar avatar frozar commented on August 29, 2024

First of all, thank you again for all the work you put in reading the WebGL fundation books, really useful. Thank to your sharing knowledge, I was able to build this tiny project to visualise a 3D mandelbrot fractal:
https://frozar.github.io/mandelbrot-viewer/

Satisfying 😄.

Back to your answer, I completely understand there's 2 way to interpret a 1D array as a 2D matrix: either the element are stored in a Row Major fashion or a Column Major fashion. The first time I've been sensitised to this fact was when I were using an old linear algebra library, LAPACK.
OpenGL uses the Column Major memory layout and math people likes to think in Row Major memory layout.

The reason why OpenGL uses the Column Major layout rather than the Row Major layout is arbitrary I think (or maybe impose by hardware and the way hardware works is arbitrary (until hardware will be AI driven designed))... But OpenGL, or at least WebGL, is able to transpose a matrix before to send it to the GPU. Even if they say that the transpose argument of gl.uniformMatrix* function must be false, it's not a requirement.

In my little fractal project, I set the transpose argument to true:

https://github.com/frozar/mandelbrot-viewer/blob/9ffad71e4212ad59df651c2137ab66c18a41cd9d/index.html#L565-L566

(the implementation is not the cleanest possible one, but still, it's shareable)

I do every matrix computation in the Row Major fashion and it works. Sure I pay an extra cost due to the transpose at each frame computation, but for me it's reasonable and now it's easier follow the computation.

This issue should be closed from my side.

from webgl2-fundamentals.

greggman avatar greggman commented on August 29, 2024

you're using WebGL2 which allows transpose be true. In WebGL1 it would generate an error

I'm also not sure what you mean by "it's easier to follow the computation"

To put another way, from the math POV, each column is a vector. So, just like the article points out, in C++ you'd do this

struct vec4 {
  float v[4];
}

struct mat4 {
  mat4(const mat4& col0, const mat4& col1, const mat4& col2, const mat4& col3) {
    columns[0] = col0;
    columns[1] = col1;
    columns[2] = col2;
    columns[3] = col3;
  }
  vec4 columns[4];
}

and you'd could build columns

vec4 xAxisColumn = 
  xx,
  xy,
  xz,
  0,
};
vec4 yAxisColumn = {
  yx,
  yy,
  yz,
  0,
}; 
vec4 yAxisColumn = {
  zx,
  zy,
  zz,
  0,
},
vec4 translationColumn = {
  tx,
  ty,
  tz,
  1,
};

and them make a matrix from those columns

mat4 matrix = mat4(xAxisColumn, yAxisColumn, zAxisColumn, translationColumn);

and you can pass that matrix directly into GL

glUniformMatrix4fv(someMatrixLocation, GL_FALSE, &matrix[0][0]);

And AFAIK it works as expected, the mathy way, including in GLSL

attribute vec4 somePosition;
uniform mat4 someMatrix;
...
  gl_Position = someMatrix * somePosition;

Those all work exactly how math people expect them to work. No reason to set transpose to true so I'm not convinced the reason it works this way in GL is arbitrary.

The only issue come up if you write them as a 4x4 matrix

mat4 m = {
   xx, xy, xz, 0,
   yx, yy, yz, 0,
   zx, zy, zz, 0,
   tx, ty, tz, 1,
};

That looks wrong to a math person's eyes.

Further, there are hardware issues. The math person wants to be able to pull out columns. Let's say you want the z-axis

vec4 zAxis = someMat4.columns[2]

just works.

vs if things are transposed you'd have to do grab every 4th float. That would be horribly slow.

you're free to do what you want but If you're setting transpose to true you're basically going against the tide of the entire graphics industry. There's nothing wrong with that except possible that you'll get used to a non-standard way and find all other examples and people's code to be confusing.

from webgl2-fundamentals.

frozar avatar frozar commented on August 29, 2024

I understand your answer, I think that I just get used to weird habit. For example, when I see a matrix like Rx(th) in the follow picture:
Image of rotation matrix

I use to implement it as:

mat4 Rx = {
   1,       0,        0, 0,
   0, cos(th), -sin(th), 0,
   0, sin(th),  cos(th), 0,
   0,       0,        0, 1,
};

And when I implement matrix multiplication, I use to implement it and think about it as shown in this picture:
https://texample.net/media/tikz/examples/PNG/matrix-multiplication.png

For me it's easier to think about implementation if 1D arrays are Row Major. I well understood that with this representation there is the downside that to retrieve retrieve a column you have to pick numbers every 4th float. And of course the cost of the transposition before to send it to the GPU.
I'm happy to know that WebGL2 allows the final transposition, it saves me.

Sad to know that generally code are implement Column Major manner. Thank you for your answer.

from webgl2-fundamentals.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.