Pages: 1
  Print  
Author Topic: Matrix Math extension?  (Read 3512 times)
Offline (Unknown gender) orange451
Posted on: December 29, 2014, 01:10:27 am
Member
Joined: Mar 2013
Posts: 16

View Profile Email
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?
« Last Edit: December 29, 2014, 01:42:30 am by orange451 » Logged
Offline (Unknown gender) TheExDeus
Reply #1 Posted on: December 29, 2014, 08:05:05 am

Developer
Joined: Apr 2008
Posts: 1860

View Profile
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.
« Last Edit: December 29, 2014, 08:09:37 am by TheExDeus » Logged
Offline (Male) Goombert
Reply #2 Posted on: December 29, 2014, 08:12:46 am

Developer
Location: Cappuccino, CA
Joined: Jan 2013
Posts: 2993

View Profile
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.
Logged
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.

Offline (Unknown gender) TheExDeus
Reply #3 Posted on: December 29, 2014, 08:21:00 am

Developer
Joined: Apr 2008
Posts: 1860

View Profile
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));
  }
}
Logged
Offline (Male) Goombert
Reply #4 Posted on: December 29, 2014, 08:29:53 am

Developer
Location: Cappuccino, CA
Joined: Jan 2013
Posts: 2993

View Profile
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: TheExDeus
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:
That sounds fine to me for now, having it work is better than nothing at all. Josh can weigh in if you like.
Logged
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.

Offline (Unknown gender) TheExDeus
Reply #5 Posted on: December 29, 2014, 09:02:26 pm

Developer
Joined: Apr 2008
Posts: 1860

View Profile
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.
« Last Edit: December 29, 2014, 09:04:15 pm by TheExDeus » Logged
Offline (Unknown gender) orange451
Reply #6 Posted on: December 30, 2014, 05:52:12 pm
Member
Joined: Mar 2013
Posts: 16

View Profile Email
edit: (nevermind)
Logged
Offline (Unknown gender) TheExDeus
Reply #7 Posted on: December 31, 2014, 06:39:28 am

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Is it working for you too?
Logged
Offline (Unknown gender) orange451
Reply #8 Posted on: December 31, 2014, 07:50:12 pm
Member
Joined: Mar 2013
Posts: 16

View Profile Email
Is it working for you too?
Yes :)
Logged
Pages: 1
  Print