I learned enough OpenGL to create a sprite system using display lists. then I found out that all the methods I'm using are referred to as legacy and are all depreciated. I also found out that I would likely get better performance If I used modern OpenGL 3.1 code. and so I embarked on a quest to write a vertex shaders that could properly position a 2d sprite in an orthographic projection with rotation and a fragment shader that would properly texture said sprite made of two triangles to form a rectangle.
I'm getting really confused.
can some one help me out?
#move to the right position to draw the sprite
#(including ofset for mismatch caused by gl textures needing
#to be powers of 2 in width and length, and the atached image
#doesn't nessaceraly have to conform to that)
glTranslatef(pos[0]+self.ox, pos[1] + self.oy, 0)
#set the color
glColor4f(*self.color)
#set the rotation
glRotatef(self.rotation, 0, 0, 1)
#set the zoom level
glScalef(self.scalar, self.scalar, self.scalar)
thats the legacy code I need to replace with a shader program
EDIT:
I found this shader and it has some functions for some of the things I need to do. but I'm not familer enough with matrix math to figure out how to adept it
#version 110
uniform float timer;
attribute vec4 position;
varying vec2 texcoord;
varying float fade_factor;
mat4 view_frustum(
float angle_of_view,
float aspect_ratio,
float z_near,
float z_far
) {
return mat4(
vec4(1.0/tan(angle_of_view), 0.0, 0.0, 0.0),
vec4(0.0, aspect_ratio/tan(angle_of_view), 0.0, 0.0),
vec4(0.0, 0.0, (z_far+z_near)/(z_far-z_near), 1.0),
vec4(0.0, 0.0, -2.0*z_far*z_near/(z_far-z_near), 0.0)
);
}
mat4 scale(float x, float y, float z)
{
return mat4(
vec4(x, 0.0, 0.0, 0.0),
vec4(0.0, y, 0.0, 0.0),
vec4(0.0, 0.0, z, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
}
mat4 translate(float x, float y, float z)
{
return mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(x, y, z, 1.0)
);
}
mat4 rotate_x(float theta)
{
return mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, cos(timer), sin(timer), 0.0),
vec4(0.0, -sin(timer), cos(timer), 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
}
void main()
{
gl_Position = view_frustum(radians(45.0), 4.0/3.0, 0.5, 5.0)
* translate(cos(timer), 0.0, 3.0+sin(timer))
* rotate_x(timer)
* scale(4.0/3.0, 1.0, 1.0)
* position;
texcoord = position.xy * vec2(0.5) + vec2(0.5);
fade_factor = sin(timer) * 0.5 + 0.5;
}
I think you will have to learn how matrix operations are used in 3D. ._.
thought as much. here I come matrix math.
You don't actually need to know too much, just the basics. A Matrix can rotate and scale a vector. It does this by defining 3 new axes. The axes don't have to be normalized (1 unit length) or orthogonal (at right angles to each other). Let's take some examples:
We will start with the 3x3 identity matrix, which is the matrix representation of the number 1:
1 0 0
0 1 0
0 0 1
If you look at the columns of the matrix, you get 3 vectors:
(1, 0, 0), (0, 1, 0), (0, 0, 1)
These are the unit vectors for the x, y, and z axes, respectively.
When you multiply a matrix by a vector, you are transforming the vector into the coordinates of the matrix. For example, for the identity matrix, we can do
1 0 0 3
0 1 0 x 4
0 0 1 5
gives us the first component of the vector times the first column of the matrix plus the second component of the vector times the second column of the matrix plus the third component of the vector times the third column of the matrix:
3*(1, 0, 0) + 4*(0, 1, 0) + 5*(0, 0, 1) = (3, 4, 5)
As you can see, multiplying the identity matrix by any vector simply returns the original vector.
Now let's try a simple scaling matrix that scales the x component by a factor of 3, the y component by a factor of 1/2, and the z component by a factor of 3/5. To do this, we take the identity matrix, and multiply the x column by 3, the y column by 1/2, and the z column by 3/5:
3 0 0 3
0 1/2 0 x 4
0 0 3/5 5
now when we multiply by the original vector, we get:
3*(3, 0, 0) + 4*(0, 1/2, 0) + 5*(0, 0, 3/5) = (9, 2, 3)
Now let's try a simple rotation matrix that rotates the vector around the z axis by 90 degrees. To do this, the old x component will be the new y component, and the old y component will be the new -x component:
0 -1 0 3
1 0 0 x 4
0 0 1 5
now when we multiply by the original vector, we get:
3*(0, 1, 0) + 4*(-1, 0, 0) + 5*(0, 0, 1) = (-4, 3, 5)
In general, you can combine the scaling and rotating effect, and you can see matricies like this:
0 -1 3 3
1 0 0 x 4
2 4 1 5
3*(0, 1, 2) + 4*(-1, 0, 4) + 5*(3, 0, 1) = (11, 3, 27)
There's a lot of stuff I'm leaving out (like translation), but this is a good crash course that should let you understand most of the things you need to do.
Lol, I never actually got to learn that 3D-matrix operations stuff properly myself. xD A collegue keeps telling me how simple it is (and I know it is), but I never learned it. In any case, he's in charge of the 3D part of our rendering engine. I guess I will learn it when I have to refactor his code. xD
hey, thanks for the crash course winko. that will make the learning process a little shorter.
woo! I think I managed to create a function to create scaling translation matrix that normalizes xyz position to the display field.
written in python for the moment.
def orthomat(left, right, top, bottom, zfar, znear):
return mat([[2.0 / (right - left), 0, 0, 0],
[0, 2.0 / (top - bottom), 0, 0],
[0, 0, 2.0 / (zfar - znear), 0],
[-(right + left) / (right - left),
-(top + bottom) / (top - bottom),
-(zfar + znear) / (zfar - znear), 1]])
well. fuck it. despite my best effort my sprite class built on VBO's and shaders failed silently and I have now clue what is wrong.
the good news is that I finally figured out how to get Pyglet to draw in my window turns out all that is needed are three simple lines of code.