Opengl Es Shader And Matrix Question


Capn_Fish

Member
Joined
Oct 12, 2008
Messages
200
I'm having a good deal of trouble understanding how the whole shader and matrix things work in OGLES. I get that shaders replaced the fixed functions of OpenGL, but I guess I don't exactly know what that means. I guess I'd like some examples of what shaders are commonly used for (not code examples, just something to the effect of "If FOO, use a shader to do BAR") as well as a general definition.

On a related (directly, so far as I can gather) topic, how exactly does the matrix stuff work in OGLES? In OpenGL, you can us glOrtho to set the Matrix "resolution"/size, but I haven't really seen anything to that effect yet.

Also, the whole matrix transformation thing is being confusing. In OGL, you just rotated/translated the "local" coordinate system, drew, then reverted back to the original one. I haven't really figured out how that works in OGLES.

I think all of that stuff is related, but I don't have a good enough grasp of them to know for sure. :blink:

I have the OGLES VM code examples to look at, but they all use a "PVR Shell," which seems to be made for demos, and obfuscates the actual OGLES stuff. I also have the Gold Book code examples (and the book itself), but they use a util lib that does a similar thing (yes I have tried to look at the source for that, but it makes it quite difficult to learn, all of the going between source files, etc.).

Thanks in advance. I'm hoping that once this stuff is cleared up, everything should become a good deal easier (I feel like I'm missing some obvious stuff), and I won't have to ask TOO many more questions.

EDIT: I'm talking about OGLES 2.0, FWIW
 
QUOTE

The 'esOrtho' function is the ES 2.0 equivalent of glOrtho and appears to allow setting of matrix size (left, right, bottom, top, near-z, far-z).

Other transformation functions include esFrustum, esPerspective, esScale, esTranslate, esRotate, esMatrixMultiply and esMatrixLoadIdentity.

The functions are used within shaders to transform vertex positions from local to clip space and can also alter other attributes like texture coordinates (I think that's right).

Also:

"A new type ESMatrix is defined in the ES 2.0 framework. This is used to represent a 4 x 4 floating-point matrix and is declared as follows:"

CODE

typedef struct {
GLfloat m[4][4];
ESMatrix;




I have no idea if that helps at all...

[Edit] I don't know if these are actually from the same Util API that you mentioned.
 
Unfortunately they are... :(

I'd like to avoid using other libs firstly in order to better learn the API and secondly to prevent having more deps than necessary in my programs.
 
Capn_Fish said:
just something to the effect of "If FOO, use a shader to do BAR") as well as a general definition.

when you want to process your vertices 1:1 - i.e. not create/destroy vertices, but, say, transform them from model space to wherever - you use vertex shaders.

when you want to compute any kind of pixel color - you use pixel (aka fragment) shaders.

most generally said, a vertex shader takes a vertex, computes whatever your shading model needs from that to be passed for rasterization (as a minimum - a position in clip space). the rasterizer (a fixed, non-programmable part) then interpolates said data accordingly and feeds them, as needed, to the fragment shader, which eventually computes a pixel's color, before the latter gets blended with whatever framebuffer it's destined for. the end.

QUOTE
On a related (directly, so far as I can gather) topic, how exactly does the matrix stuff work in OGLES? In OpenGL, you can us glOrtho to set the Matrix "resolution"/size, but I haven't really seen anything to that effect yet.

matrices in gl/es define the transformations applied to vertices, normals, and a bunch of other things you may not care about right now.

for the purpose gl/es1.x maintains a bunch of transformation stacks, which work as accumulators of transformations, ie every matrix you place on the respective stack becomes one more operator in the T0 * T1 * .. * Tn-1 * Tn transformation sequence. note that a chronologically-later push on the respective stack gives a higher index for the respective matrix in the cumulative sequence.

on the right-most of that sequence sits your raw vertex, which is being transformed. i.e. T0 * T1 * .. * Tn-1 * Tn * V. as mentioned, the matrix at the top of the transformation stack sits right to the left of the vertex being transformed.

by pushing matrices on the gl/es1.x model-view and projection stacks, you build up that transformation sequence, like this:

P0 * P1 * ... Pn-1 * Pn * MV0 * MV1 * .. * MVn-1 * MVn * V

QUOTE
Also, the whole matrix transformation thing is being confusing. In OGL, you just rotated/translated the "local" coordinate system, drew, then reverted back to the original one. I haven't really figured out how that works in OGLES.


there's no difference between es1.x an gl in this regard. re es2.x - it just does not have those transform stacks - managing matrices is entirely your obligation, and you may keep transforms in whatever structures you deem appropriate, as long as you manage to pass them down to the vertex shaders (as uniform arguments) when needed.
 
Last edited by a moderator:
So, if I'm gathering correctly, I use the Vertex shader to render my models (as defined by a set of vertexes) in the correct places, much like shifting the "local" coordinate system in OpenGL.

For instance, if I wanted my 1-unit cube to be rendered x units away from the origin and rotated 45 degrees, I'd define a transformation matrix, pass it to the vertex shader, which would be coded to multiply the "normal" matrix by that to get the final place to render the cube?

I only need to deal with the fragment shader if I want to do blending/fog/lighting effects and the like, no?

Thank you very much for the quick, helpful response!
 
Capn_Fish said:
So, if I'm gathering correctly, I use the Vertex shader to render my models (as defined by a set of vertexes) in the correct places, much like shifting the "local" coordinate system in OpenGL.

precisely.

QUOTE

For instance, if I wanted my 1-unit cube to be rendered x units away from the origin and rotated 45 degrees, I'd define a transformation matrix, pass it to the vertex shader, which would be coded to multiply the "normal" matrix by that to get the final place to render the cube?

almost. as a rule, you don't do matrix compositing in your vertex shader - you pre-compute your MVP (model-view-projection), or any other matrix you may need to transform by, and pass those to the shader. the reason for that is that doing some T0 * T1 * .. * Tn-1 * Tn compositing in the shader would be an utter waste of computations - remember, the shader is called per vertex, whereas the data you'd make it compute in this case varies per primitive call, at most.

QUOTE

I only need to deal with the fragment shader if I want to do blending/fog/lighting effects and the like, no?

well, not really. blending with the framebuffer is not done by the fragment shader - it's done by the ROPs. other than that, you need a fragment shader for practically any kind of color computation, including a constant color, IIRC*, not just what you listed.

QUOTE
Thank you very much for the quick, helpful response!

don't mention it.

* but you may want to check that with the specs - there may be some minimal functionality giving a constant-color 'built-in' shader, i don't remember precisely.
 
Last edited by a moderator:
But these MVPs aren't like shaders in that you compile them before the application really gets going, right? It's more like:

-define vertex array
-define transformation matrix
-compile transformation matrix
-pass to vertex shader along with vertexes

no?

On the topic of fragment shaders, I know I need SOME sort of shader, just not anything too fancy for doing solid-color rendering (and hopefully nothing too fancy for directional lighting), right?

(refrained from giving thanks as requested ;))
 
Capn_Fish said:
But these MVPs aren't like shaders in that you compile them before the application really gets going, right? It's more like:

-define vertex array
-define transformation matrix
-compile transformation matrix
-pass to vertex shader along with vertexes

no?
yep. to pass the matrix to your shader, use either

CODE

void glUniform4fv(
GLint location,
GLsizei count,
const GLfloat *value);



with a count of 4 for a 4-row matrix, or some of the matrix-specific uniform helpers, e.g.

CODE

void glUniformMatrix4fv(
GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat *value);



QUOTE
On the topic of fragment shaders, I know I need SOME sort of shader, just not anything too fancy for doing solid-color rendering (and hopefully nothing too fancy for directional lighting), right?

correct.

QUOTE

(refrained from giving thanks as requested ;))


that's better ; )
 
Last edited by a moderator:
Wonderful! Now all I need to do is figure out how to get SDL working with OGLES, and I'm set!
 
QUOTE
Wonderful! Now all I need to do is figure out how to get SDL working with OGLES, and I'm set!
You can create a window in SDL then pass the handle & device to egl for context creation. Since the actual code is a bit verbose, Here's the basic process i use:

SDL_Init()
SDL_SetVideoMode()
SDL_GetWMInfo()
eglGetDisplay()
eglInitialize()
eglChooseConfig()
eglCreateWindowSurface()
eglBindAPI()
eglCreateContext()
eglMakeCurrent()

Its very likely that the Pandora SDL port will, at some point, just allow you to pass SDL_OPENGL_ES2.0 as a flag to SDL_SetVideoMode().... like OGL on the PC SDL.
 
Capn_Fish said:
I have the OGLES VM code examples to look at, but they all use a "PVR Shell," which seems to be made for demos, and obfuscates the actual OGLES stuff.

The PowerVR OpenGL ES 2.0 SDK starts with two tutorials (Initialization and HelloTriangle) which don't use PVRShell, to introduce the code required for EGL surface and context initialization.

PVRShell doesn't really hide any OGLES stuff, only EGL and platform specific things (window creation, render loop, input).
darkblu said:
for the purpose gl/es1.x maintains a bunch of transformation stacks, which work as accumulators of transformations, ie every matrix you place on the respective stack becomes one more operator in the T0 * T1 * .. * Tn-1 * Tn transformation sequence. note that a chronologically-later push on the respective stack gives a higher index for the respective matrix in the cumulative sequence.

That's not quite what happens. Only the top elements of the matrix stacks are used for the transformation calculation, but most matrix operations (glRotate, glTranslate, etc.) multiply the current matrix instead of replacing it. Push and pop are used to save and restore nodes in a transformation hierarchy.

darkblu said:
almost. as a rule, you don't do matrix compositing in your vertex shader - you pre-compute your MVP (model-view-projection), or any other matrix you may need to transform by, and pass those to the shader. the reason for that is that doing some T0 * T1 * .. * Tn-1 * Tn compositing in the shader would be an utter waste of computations - remember, the shader is called per vertex, whereas the data you'd make it compute in this case varies per primitive call, at most.

The shader compiler is clever enough to detect computations consisting entirely of uniforms and constants. Such expressions will indeed be evaluated only once per draw call.

QUOTE
* but you may want to check that with the specs - there may be some minimal functionality giving a constant-color 'built-in' shader, i don't remember precisely.
Nope, no default shaders. Draw calls need a complete shader program in ES 2.0.
 
Last edited by a moderator:
Xmas said:
That's not quite what happens. Only the top elements of the matrix stacks are used for the transformation calculation, but most matrix operations (glRotate, glTranslate, etc.) multiply the current matrix instead of replacing it. Push and pop are used to save and restore nodes in a transformation hierarchy.

of course you're right, but by a stack i was referring to semantical behavior of the top element of the physical gl stack(s), where except for the glLoad* group, every new matrix operator passed is catenated to the right of the composite expression, 'stacking transformations' as it goes. i shouldn't have used the term stack in this case, i guess - it was a Freudian slip.

QUOTE
The shader compiler is clever enough to detect computations consisting entirely of uniforms and constants. Such expressions will indeed be evaluated only once per draw call.

nice. is it a consistent behavior mandated by some spec, or is that just a nicety of some (most?) glsl shader compilers?

QUOTE
Nope, no default shaders. Draw calls need a complete shader program in ES 2.0.
well, suspected as much.
 
Last edited by a moderator:
I heavily recommend RenderMonkey to have some examples for OGLES Shaders if you are on windows.
And as others already said: the ATI SDK and the PowerVR SDK have some good examples which are usuallly pretty basic
 
I really really recommend this book:

http://www.amazon.com/OpenGL-ES-2-0-Progra...e/dp/0321502795

I was a newb for all things opengl. I have only glanced at tutorials and other books for OpenGl 1.x stuff before.
I read through this book I believe that I have a fairly good understanding of OpenGl ES 2.0. I don't know a whole lot about the fixed function API stuff but it seems to me that programmable shaders are easier because there is less API calls to remember.

I am currently writing a slide show demo that will use 3D transitions. I am still waiting for drivers for the BeagleBoard but as someone else suggested the first 2 training courses in the PowerVR SDK are a good starting point.
 
Adventus said:
QUOTE
Wonderful! Now all I need to do is figure out how to get SDL working with OGLES, and I'm set!
You can create a window in SDL then pass the handle & device to egl for context creation. Since the actual code is a bit verbose, Here's the basic process i use:

SDL_Init()
SDL_SetVideoMode()
SDL_GetWMInfo()
eglGetDisplay()
eglInitialize()
eglChooseConfig()
eglCreateWindowSurface()
eglBindAPI()
eglCreateContext()
eglMakeCurrent()

Its very likely that the Pandora SDL port will, at some point, just allow you to pass SDL_OPENGL_ES2.0 as a flag to SDL_SetVideoMode().... like OGL on the PC SDL.

What exactly do I pass to eglGetDisplay and eglCreateWindowSurface? I've tried "(EGLNativeDisplayType)EGL_DEFAULT_DISPLAY" and variations on "(EGLNativeWindowType)&sdlwminfo[.info[.x11[.window]]]", respectively.

Thanks.
 
Last edited by a moderator:
QUOTE
What exactly do I pass to eglGetDisplay and eglCreateWindowSurface? I've tried "(EGLNativeDisplayType)EGL_DEFAULT_DISPLAY" and variations on "(EGLNativeWindowType)&sdlwminfo[.info[.x11[.window]]]", respectively.
For eglGetDisplay, You must get the device. In Windows you can call GetDC() with the window handle as an argument, I'm not completely sure how to accomplish this in x11 Linux. Looking at the source to SDL, it appears to be one of these SDL_SysWMinfo.info.x11.display or SDL_SysWMinfo.info.x11.gfxdisplay.
Your probably correct on eglCreateWindowSurface.

So in pseudo code:
SDL_SysWMinfo wminfo;
SDL_GetWMInfo(&wminfo);
EGLDisplay Display = eglGetDisplay(wminfo.info.x11.display);
.....
EGLSurface Surface = eglCreateWindowSurface(Display, Config, wminfo.info.x11.window, NULL);
 
Now I'm getting errors from

CODE
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, ai32ContextAttribs);


CODE
X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
Major opcode of failed request: 55 (X_CreateGC)
Resource id in failed request: 0x0
Serial number of failed request: 21
Current serial number in output stream: 23


I get two such errors if I switch in the commented line for the uncommented one:

CODE
//eglDisplay = eglGetDisplay((EGLNativeDisplayType)sdlwminfo.info.x11.display);



eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);


Any ideas?

Thanks a bunch, by the way. I appreciate it.

My setup: Gentoo, ~x86, PowerVR OGLES-2.0 wrapper libs, Mesa OGL libs, Intel 855GM graphics
 
QUOTE
Any ideas?
Hmmm I'm not sure if its your problem but, i probably should have mentioned that messing with sdlwminfo.info.x11.display requires you to call sdlwminfo.info.x11.lock_func() and sdlwminfo.info.x11.unlock_func() before and after. Have you tried gfxdisplay?

QUOTE
My setup: Gentoo, ~x86, PowerVR OGLES-2.0 wrapper libs, Mesa OGL libs, Intel 855GM graphics
Does this setup support OpenGL 2.0? The Intel Extreme 2 doesn't support hardware OGL2, but maybe the Mesa library will software render....
 
The OGLES demos built and ran OK, so software rendering is working fine.

Using gfxdisplay didn't change anything that I noticed.

Calling the lock/unlock stuff around the eglGetDisplay line didn't change anything I could see.
 
From the PowerVR site:
QUOTE
Note: Our OpenGL ES 2.0 PC Emulation requires a graphics card which supports OpenGL 2.0, or OpenGL 1.5 and the GL_ARB_shading_language_100 extension. The SDK has been successfully tested with ATI Radeon X1000 series and newer graphics cards, and NVIDIA GeForce 6 series and newer graphics cards. Most Intel integrated graphics chipsets are not supported.


So you are out of luck, your graphics card is quite ancient, I suppose. Just like mine;).
 
Back
Top