Opengl Es Shader And Matrix Question


Other stuff has worked fine. Mesa covers up the fact that it doesn't support OpenGL hardware acceleration quite nicely :)
 
Capn_Fish said:
Other stuff has worked fine. Mesa covers up the fact that it doesn't support OpenGL hardware acceleration quite nicely :)
Well, it probably works as long as you do not use any funky extensions - Mesa does not know OGL 2 in software, AFAIK.
 
Last edited by a moderator:
Wow, I KNEW I was doing something stupidly wrong... I was passing (EGLNativeWindowType)&sdlwminfo.info.x11.window instead of (EGLNativeWindowType)sdlwminfo.info.x11.window. :angry:

Thanks for helping! I'm going to go code! :D
 
Back on the topic of matrices...

I'm trying to figure out how to set up a basic matrix for an Orthographic projection. In OGL, you could just set the "resolution" of that area with simple "left, right, bottom, top, close, far" or similar parameters. I found the ESUtil functions that do the same thing (more or less, so I gather, I do know that it needs to be implemented in the vertex shader):

CODE
void ESUTIL_API

esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)

{

float deltaX = right - left;

float deltaY = top - bottom;

float deltaZ = farZ - nearZ;

ESMatrix ortho;



if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )

return;



esMatrixLoadIdentity(&ortho);

ortho.m[0][0] = 2.0f / deltaX;

ortho.m[3][0] = -(right + left) / deltaX;

ortho.m[1][1] = 2.0f / deltaY;

ortho.m[3][1] = -(top + bottom) / deltaY;

ortho.m[2][2] = -2.0f / deltaZ;

ortho.m[3][2] = -(nearZ + farZ) / deltaZ;



esMatrixMultiply(result, &ortho, result);

}





void ESUTIL_API

esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB)

{

ESMatrix tmp;

int i;



for (i=0; i<4; i++)

{

tmp.m[0] = (srcA->m[0] * srcB->m[0][0]) +

(srcA->m[1] * srcB->m[1][0]) +

(srcA->m[2] * srcB->m[2][0]) +

(srcA->m[3] * srcB->m[3][0]);



tmp.m[1] = (srcA->m[0] * srcB->m[0][1]) +

(srcA->m[1] * srcB->m[1][1]) +

(srcA->m[2] * srcB->m[2][1]) +

(srcA->m[3] * srcB->m[3][1]);



tmp.m[2] = (srcA->m[0] * srcB->m[0][2]) +

(srcA->m[1] * srcB->m[1][2]) +

(srcA->m[2] * srcB->m[2][2]) +

(srcA->m[3] * srcB->m[3][2]);



tmp.m[3] = (srcA->m[0] * srcB->m[0][3]) +

(srcA->m[1] * srcB->m[1][3]) +

(srcA->m[2] * srcB->m[2][3]) +

(srcA->m[3] * srcB->m[3][3]);

}

memcpy(result, &tmp, sizeof(ESMatrix));

}





void ESUTIL_API

esMatrixLoadIdentity(ESMatrix *result)

{

memset(result, 0x0, sizeof(ESMatrix));

result->m[0][0] = 1.0f;

result->m[1][1] = 1.0f;

result->m[2][2] = 1.0f;

result->m[3][3] = 1.0f;

}


Anyway, I'm having trouble wrapping my head around how this is set up/what exactly it's doing (I suspect looking at a math textbook wouldn't hurt, but still). Could somebody be so kind as to explain it (I hope this is my last question as well...)?

Edited to fix one of my stupidest errors yet...
 
Capn_Fish said:
Back on the topic of matrices...

I'm trying to figure out how to set up a basic matrix for an Orthopedic projection. In OGL, you could just set the "resolution" of that area with simple "left, right, bottom, top, close, far" or similar parameters. I found the ESUtil functions that do the same thing (more or less, so I gather, I do know that it needs to be implemented in the vertex shader):

<code snipped>

Anyway, I'm having trouble wrapping my head around how this is set up/what exactly it's doing (I suspect looking at a math textbook wouldn't hurt, but still). Could somebody be so kind as to explain it (I hope this is my last question as well...)?
an othographic projection matrix, or any other projection matrix, for that matter, is not meant to give the 'resolution' of the view space, but rather its extents, or what is known as the view volume. clip space is based on that volume, and is where your projection matrix sends your vertices for futher processing - namely, clipping versus the view volume (ergo, the term 'clip space').

in this regard, the code you cited does the vanilla/canonical/your-everyday/etc othographic projection matrix composition. you can see that in almost every opengl specification document. its specifics are:

the clip space produced is cuboid-al (the whole 'ortho' in the name comes to signify that), and the homogeneous component of your vertices passing through it is quaranted not to be altered (i.e. w remains unaltered, usually at 1). also, it switches the handedness of the coord system from right-handed (the habitual gl camera space), to left handed (gl's clip space). that's about it, basically.

ps: don't build your projection matrix in your shaders - it really does not belong there, regardless how smart modern shader compilers are.

edited for relevance and clarity.
 
Last edited by a moderator:
Shows how much attention I was paying (fixed, BTW)...

I know the "resolution" bit was off, but I couldn't come up with a better word at the time (hence the quotation marks, I should fix that as well...). I also had no intention of building it into the shader, but rather passing it TO the shader, as that's what I gather should be done from reading various samples. Please correct me (once again) if that's wrong.

I'm thinking I should also rephrase my question, though it appears my time would be better spent just looking at the code and relearning my matrix stuff. Anyway, moving on.

The biggest thing I don't get at the moment is that in esOrtho, you pass what is likely an empty matrix, meaning that all of the values are at the default 0.

I what the lines dealing with "ortho" are doing, but when you get into the esMatrixMultiply lines, since the matrix full of 0s is always in the multiplication, shouldn't you always end up with 0 as the answer and have the whole activity become pointless (I'm feeling something obvious that I somehow missed coming on, again...:()?
 
Capn_Fish said:
The biggest thing I don't get at the moment is that in esOrtho, you pass what is likely an empty matrix, meaning that all of the values are at the default 0.

I what the lines dealing with "ortho" are doing, but when you get into the esMatrixMultiply lines, since the matrix full of 0s is always in the multiplication, shouldn't you always end up with 0 as the answer and have the whole activity become pointless (I'm feeling something obvious that I somehow missed coming on, again...:()?
And because this would be pointless you obviously don't pass a matrix full of 0s. Usually you'd pass an identity matrix.
 
Last edited by a moderator:
Xmas said:
Capn_Fish said:
The biggest thing I don't get at the moment is that in esOrtho, you pass what is likely an empty matrix, meaning that all of the values are at the default 0.

I what the lines dealing with "ortho" are doing, but when you get into the esMatrixMultiply lines, since the matrix full of 0s is always in the multiplication, shouldn't you always end up with 0 as the answer and have the whole activity become pointless (I'm feeling something obvious that I somehow missed coming on, again...:()?
And because this would be pointless you obviously don't pass a matrix full of 0s. Usually you'd pass an identity matrix.

This is the part where I start kicking myself.

Thank you! I think I shall refrain from posting OGLES questions for a while.
 
Last edited by a moderator:
Now that a while has passed, I really hope this one isn't obvious:

My question now is regarding rotation. I have the following code (in actual code, of course):

CODE
clear buffer
draw triangle
rotate
draw similar triangle in different location (separate vertex list, no translation involved)
swap buffers
reset rotation


Now I expected this to give me two triangles, one rotated and one not. I end up with both triangles not rotated. Could anybody explain to me how that works? I get a similar thing when I try to rotate, draw, rotate, draw, repeat (for an animation of sorts): Both triangles just rotate on the same plane, at the same speed, etc.

What am I doing wrong here (I can post my code if necessary, but it's really messy, due to being fiddled with, copied and pasted, etc.)?
 
post the code. you can strip it of any non-transformational stuff, for readability's sake.
 
I can't believe I just did this, but I deleted my code! I still have the transformation code:

CODE
#include <iostream>
#include <cmath>
#include <cstring>

#include <GLES2/gl2.h>

#include "matrix.hpp"

void CreateIdentityMatrix(Matrix* target)
{
memset( target, 0x0, sizeof(Matrix) );
for(int i = 0; i < 4; i++)
{
target->m = 1.0f;
}
}

void MultiplyMatrices(Matrix* target, Matrix* Input1, Matrix* Input2)
{
Matrix tmp;

for(int i = 0; i < MATRIX_SIZE; i++)
{
tmp.m[0] = ( (Input1->m[0] * Input2->m[0][0]) +
(Input1->m[1] * Input2->m[1][0]) +
(Input1->m[2] * Input2->m[2][0]) +
(Input1->m[3] * Input2->m[3][0]) );

tmp.m[1] = ( (Input1->m[0] * Input2->m[0][1]) +
(Input1->m[1] * Input2->m[1][1]) +
(Input1->m[2] * Input2->m[2][1]) +
(Input1->m[3] * Input2->m[3][1]) );

tmp.m[2] = ( (Input1->m[0] * Input2->m[0][2]) +
(Input1->m[1] * Input2->m[1][2]) +
(Input1->m[2] * Input2->m[2][2]) +
(Input1->m[3] * Input2->m[3][2]) );

tmp.m[3] = ( (Input1->m[0] * Input2->m[0][3]) +
(Input1->m[1] * Input2->m[1][3]) +
(Input1->m[2] * Input2->m[2][3]) +
(Input1->m[3] * Input2->m[3][3]) );
}

memcpy( target, &tmp, sizeof(Matrix) );
}

bool CreateOrthographicMatrix(Matrix* target, float left, float right, float bottom, float top, float nearZ, float farZ)
{
float deltaX = right - left;
float deltaY = top - bottom;
float deltaZ = farZ - nearZ;
Matrix ortho;

CreateIdentityMatrix(target);

if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )
{
return false;
}

CreateIdentityMatrix(&ortho);
ortho.m[0][0] = 2.0f / deltaX;
ortho.m[3][0] = -(right + left) / deltaX;
ortho.m[1][1] = 2.0f / deltaY;
ortho.m[3][1] = -(top + bottom) / deltaY;
ortho.m[2][2] = -2.0f / deltaZ;
ortho.m[3][2] = -(nearZ + farZ) / deltaZ;

MultiplyMatrices(target, &ortho, target);

return true;
}

void ScaleMatrix(Matrix* target, GLfloat scaleX, GLfloat scaleY, GLfloat scaleZ)
{
target->m[0][0] *= scaleX;
target->m[0][1] *= scaleX;
target->m[0][2] *= scaleX;
target->m[0][3] *= scaleX;

target->m[1][0] *= scaleY;
target->m[1][1] *= scaleY;
target->m[1][2] *= scaleY;
target->m[1][3] *= scaleY;

target->m[2][0] *= scaleZ;
target->m[2][1] *= scaleZ;
target->m[2][2] *= scaleZ;
target->m[2][3] *= scaleZ;
}

void TranslateMatrixRelative(Matrix* target, GLfloat translateX, GLfloat translateY, GLfloat translateZ)
{
target->m[3][0] += (target->m[0][0] * translateX + target->m[1][0] * translateY + target->m[2][0] * translateZ);
target->m[3][1] += (target->m[0][1] * translateX + target->m[1][1] * translateY + target->m[2][1] * translateZ);
target->m[3][2] += (target->m[0][2] * translateX + target->m[1][2] * translateY + target->m[2][2] * translateZ);
target->m[3][3] += (target->m[0][3] * translateX + target->m[1][3] * translateY + target->m[2][3] * translateZ);
}

void TranslateMatrixAbsolute(Matrix* target, GLfloat translateX, GLfloat translateY, GLfloat translateZ)
{
target->m[3][0] = (target->m[0][0] * translateX + target->m[1][0] * translateY + target->m[2][0] * translateZ);
target->m[3][1] = (target->m[0][1] * translateX + target->m[1][1] * translateY + target->m[2][1] * translateZ);
target->m[3][2] = (target->m[0][2] * translateX + target->m[1][2] * translateY + target->m[2][2] * translateZ);
target->m[3][3] = (target->m[0][3] * translateX + target->m[1][3] * translateY + target->m[2][3] * translateZ);
}

bool RotateMatrix(Matrix* target, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
GLfloat magnitude = sqrtf(x * x + y * y + z * z);

if (magnitude <= 0.0f)
{
return false;
}

GLfloat sinAngle = sinf(angle * PI / 180.0f);
GLfloat cosAngle = cosf(angle * PI / 180.0f);

Matrix rotationmatrix;

x /= magnitude;
y /= magnitude;
z /= magnitude;

GLfloat xx = x * x;
GLfloat yy = y * y;
GLfloat zz = z * z;
GLfloat xy = x * y;
GLfloat yz = y * z;
GLfloat zx = z * x;
GLfloat xs = x * sinAngle;
GLfloat ys = y * sinAngle;
GLfloat zs = z * sinAngle;
GLfloat oneMinusCos = 1.0f - cosAngle;

rotationmatrix.m[0][0] = (oneMinusCos * xx) + cosAngle;
rotationmatrix.m[0][1] = (oneMinusCos * xy) - zs;
rotationmatrix.m[0][2] = (oneMinusCos * zx) + ys;
rotationmatrix.m[0][3] = 0.0F;

rotationmatrix.m[1][0] = (oneMinusCos * xy) + zs;
rotationmatrix.m[1][1] = (oneMinusCos * yy) + cosAngle;
rotationmatrix.m[1][2] = (oneMinusCos * yz) - xs;
rotationmatrix.m[1][3] = 0.0F;

rotationmatrix.m[2][0] = (oneMinusCos * zx) - ys;
rotationmatrix.m[2][1] = (oneMinusCos * yz) + xs;
rotationmatrix.m[2][2] = (oneMinusCos * zz) + cosAngle;
rotationmatrix.m[2][3] = 0.0F;

rotationmatrix.m[3][0] = 0.0F;
rotationmatrix.m[3][1] = 0.0F;
rotationmatrix.m[3][2] = 0.0F;
rotationmatrix.m[3][3] = 1.0F;

MultiplyMatrices(target, &rotationmatrix, target);
}


That was mostly copied from the OpenGL ES 2.0 Programming Guide.

The relevant header parts:

CODE
#define MATRIX_SIZE 4
#define PI 3.1415926535897932384626433832795f

typedef struct
{
GLfloat m[MATRIX_SIZE][MATRIX_SIZE];
} Matrix;


The vertex shader was something like this:

CODE

attribute highp vec4 myVertex;
uniform mediump mat4 myPMVMatrix;
uniform mediump mat4 modelMatrix;
void main(void)
{
gl_Position = myPMVMatrix * (myVertex * modelMatrix);
}


The fragment shader was simple:

CODE
void main (void)
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}


The code that was being used for rotations (approx):

CODE
Matrix ModelMatrix;
Matrix ProjectionMatrix;

CreateIdentityMatrix(&ModelMatrix);
CreateOrthographicMatrix(&ProjectionMatrix, -320.0f, 320.0f, -240.0f, 240.0f, -240.0f, 240.0f);

(compile shaders, set what is passed to them, etc.)

(vertices for 2 different triangles, one with 0-2, the other with 3-5)

for(int i = 0; i < 200; i++)
{
RotateMatrix(&ModelMatrix, 45.0f, 0.0, 0.0, 1.0);
glDrawArrays(GL_TRIANGLES, 0, 3);
CreateIdentityMatrix(&ModelMatrix);
glDrawArrays(GL_TRIANGLES, 3, 3);

(swap buffers)
}


What I would expect from this is one triangle rotated 45 degrees (so it appears "thinner") and one not so, but neither of them is rotated.
 
You need to actually pass the changes you make to your matrices to OpenGL. I.e. you need to call glUniformMatrix4fv before the draw calls.

And your matrices seem to be a mix between row-major and column-major. You shouldn't mix M*V and V*M unless you really know what you're doing.
 
What do you mean by "row major" and "column major?" Which piece of code are you talking about?

I think you've answered my other question, however, for which I am much appreciative.

EDIT: I gather you're talking about "matrix * vector" and "vector * matrix," no? I'd still like to hear an explanation, if you would be so kind.
 
hey, people are still discussing dev topics in this corner of this board! /sarcasm

Capn_Fish said:
What do you mean by "row major" and "column major?" Which piece of code are you talking about?

I think you've answered my other question, however, for which I am much appreciative.

EDIT: I gather you're talking about "matrix * vector" and "vector * matrix," no? I'd still like to hear an explanation, if you would be so kind.
your shader mixes operator * vector and vector * operator for no clear reason.

whether a matrix keeps a vector basis in its columns, or its rows, defines whether the matrix is column- or row-major, respectively.

column-major matrices follow the rule 'operator-leftism', where the matrices stand to the left of the vector (and the vector itself is a column-vector) during multiplication.

row-major matrices are the trasposed version of the above - they follow 'opetator-rightism' where the matrices sit to the right of the vector, which itself is a row-vector.

actually, i believe we've already touched on the subject of how transformations stack in the column-major case, which is the one used by ogl (for reference, d3d uses row-major principles) - you may want to check that older post for reference. here, let me fetch it for you:

http://www.gp32x.de/board/index.php?showtopic=45979#

apropos, post #8 a bit further down from there talks about passing uniform params to shaders : )
 
Last edited by a moderator:
Back
Top