Pages: 1
Author Topic: Matrix Math extension?  (34,828 Views)
Offline (Unknown gender) orange451

Member
Joined: Mar 2013
Posts: 16
View profile
Posted on: December 29, 2014, 06:10:27 AM
How do I use it? I need to invert the projection matrix, and I don't want to do it in a shader (faster on the CPU end).

Also, how do you send a matrix to a shader in Enigma?
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #1 Posted on: December 29, 2014, 01:05:05 PM
That extension doesn't work yet in ENIGMA. It was written as a pure C++ thing and the idea was that EDL will support classes and templates at some point. So then you could use it. It wasn't meant to be for graphics either, as it's not optimized for that. That matrix class allows arbitrary size and type matrices which is useful when making things like filters (in my case, a scientific direction), but probably won't be that useful for generic GM/ENIGMA user.

Graphics system uses a specific matrix classes that are optimized for 3x3 and 4x4 matrices. It is not available in EDL though and is used only internally. GM:S has functions for getting matrices into arrays (matrix_get, matrix_set, matrix_build, matrix_multiply), but they haven't been implemented in ENIGMA. I haven't got around to that, as we lack a way to return EDL/GML arrays or pointer from a function. The only way to change the internal matrices are to use the transformation and projection functions.

edit: I also implemented functions for sending matrices to shaders - glsl_uniform_matrix2fv, glsl_uniform_matrix3fv, glsl_uniform_matrix4fv - which are the GL equivalents. Sadly, I don't think they work in EDL either, as I don't think we can pass arrays to functions. I haven't tested that though. They are used internally to pass matrices to shaders, so they do work in pure C++. I will test and see if I can use them in EDL right now.
Offline (Unknown gender) Goombert

Developer
Joined: Jan 2013
Posts: 2,991
View profile
Reply #2 Posted on: December 29, 2014, 01:12:46 PM
Because array names are just const pointers essentially they can be passed to functions in ENIGMA. You just can't get the size, but that doesn't matter because they are a prefixed size. Second I think the functions should actually take a var array because it can be double or float like drawing functions, and var arrays can tell us their size. I don't know about returning arrays, but I have already outlined the functions. I encourage you to at least take a crack at it Harri and let us know of any parsing bugs and I may be able to help fix them.
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #3 Posted on: December 29, 2014, 01:21:00 PM
And how exactly can I pass a var array to function? How does the C++ declaration look?
Because it seems the function parser has ignored my functions which require a pointer to an array, so these functions are in the header, but not visible in LGM:
Code (C++) Select
void glsl_uniform1fv(int location, int size, const float *value);
void glsl_uniform2fv(int location, int size, const float *value);
void glsl_uniform3fv(int location, int size, const float *value);
void glsl_uniform4fv(int location, int size, const float *value);

void glsl_uniform1iv(int location, int size, const float *value);
void glsl_uniform2iv(int location, int size, const float *value);
void glsl_uniform3iv(int location, int size, const float *value);
void glsl_uniform4iv(int location, int size, const float *value);

void glsl_uniform1uiv(int location, int size, const float *value);
void glsl_uniform2uiv(int location, int size, const float *value);
void glsl_uniform3uiv(int location, int size, const float *value);
void glsl_uniform4uiv(int location, int size, const float *value);

void glsl_uniform_matrix2fv(int location, int size, const float *matrix);
void glsl_uniform_matrix3fv(int location, int size, const float *matrix);
void glsl_uniform_matrix4fv(int location, int size, const float *matrix);
I still need to cast the var array as floats, which I don't know how effective will be. Right now I just assume they are floats and do a memcpy:
Code (C++) Select
void glsl_uniform_matrix4fv(int location, int size, const float *matrix){
  get_uniform(it,location,16);
  if (std::equal(it->second.data.begin(), it->second.data.end(), matrix, enigma::UATypeFComp) == false){
    glUniformMatrix4fv(location, size, true, matrix);
    memcpy(&it->second.data[0], &matrix[0], it->second.data.size() * sizeof(enigma::UAType));
  }
}
Offline (Unknown gender) Goombert

Developer
Joined: Jan 2013
Posts: 2,991
View profile
Reply #4 Posted on: December 29, 2014, 01:29:53 PM
What? That isn't the case at all, all the matrix_functions I prototyped are showing in the function list.

Code (EDL) Select

matrix_build : gs_scalar *matrix_build(gs_scalar x, gs_scalar y, gs_scalar z, gs_scalar xrotation, gs_scalar yrotation, gs_scalar zrotation, gs_scalar xscale, gs_scalar yscale, gs_scalar zscale);
matrix_get : gs_scalar *matrix_get(int type);
matrix_multiply : gs_scalar *matrix_multiply(gs_scalar *matrix1, gs_scalar *matrix2);
matrix_set : void matrix_set(int type, gs_scalar *matrix);


Quote from: TheExDeusI still need to cast the var array as floats, which I don't know how effective will be. Right now I just assume they are floats and do a memcpy:
That sounds fine to me for now, having it work is better than nothing at all. Josh can weigh in if you like.
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #5 Posted on: December 30, 2014, 02:02:26 AM
I was not able to get variable arrays working right now (still don't know how the definition must look like, probably will take a peek at string() which should have it), but due to recent fixes with typed array's, I was able to test it like this:
Code (edl) Select

//Create event
//Lets make a 4x4 identity matrix
local float mat[16];
mat[0] = 1;
mat[1] = 0;
mat[2] = 0;
mat[3] = 0;

mat[4] = 0;
mat[5] = 1;
mat[6] = 0;
mat[7] = 0;

mat[8] = 0;
mat[9] = 0;
mat[10] = 1;
mat[11] = 0;

mat[12] = 0;
mat[13] = 0;
mat[14] = 0;
mat[15] = 1;

//Draw event
mat[3] = sin(get_timer()/1000000);
mat[7] = cos(get_timer()/1000000);

shader_set(shr_simple);
glsl_uniform_matrix4fv(glsl_get_uniform_location(shr_simple, "myMatrix"), 1, mat);
draw_rectangle(250,250,350,350,0);
shader_reset();

//shr_simple vertex shader
in vec3 in_Position; // (x,y,z)

uniform mat4 myMatrix = mat4(1.0); //Default set to identity matrix

void main()
{
    gl_Position = viewMatrix * myMatrix * projectionMatrix * vec4( in_Position.xyz, 1.0);
}

//shr_simple pixel shader
out vec4 out_FragColor;

void main()
{
    out_FragColor = vec4(1,0,0,1); //Output red rectangle
}
And it worked. I got a moving rectangle on the screen by manually replacing the modelMatrix with myMatrix. This should also allow writing over built-in matrices, like viewMatrix, projectionMatrix etc. There could be problems with that though, as the matrices are calculated only when needed and when drawing. Which means your custom changes could be overridden in code like this:
Code (edl) Select
shader_set(shr_simple);
d3d_transform_set_translation(10,10,10); //We change the enigma::Matrix4 model_matrix
glsl_uniform_matrix4fv(glsl_get_uniform_location(shr_simple, "modelMatrix "), 1, mat); //We write over shader's built-in modelMatrix
draw_rectangle(250,250,350,350,0); //We draw something, so all the matrices are calculated (view_matrix * model_matrix etc.) and sent to shader via glsl_uniform_matrix4fv, thus overriding the previous line
shader_reset();
This is the place where the matrix_ functions come in. Still, somehow not feeling implementing them right now.

I added the egm to this post. Please test.
Offline (Unknown gender) orange451

Member
Joined: Mar 2013
Posts: 16
View profile
Reply #6 Posted on: December 30, 2014, 10:52:12 PM
edit: (nevermind)
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #7 Posted on: December 31, 2014, 11:39:28 AM
Is it working for you too?
Offline (Unknown gender) orange451

Member
Joined: Mar 2013
Posts: 16
View profile
Reply #8 Posted on: January 01, 2015, 12:50:12 AM
Quote from: TheExDeus on December 31, 2014, 11:39:28 AM
Is it working for you too?
Yes :)
Pages: 1