PDA

View Full Version : glInterleavedArrays - OpenGL ES 2.0???



thesaint
04-11-2011, 12:27 AM
I am having some trouble in porting my OpenGL application to "OpenGL ES 2.0" (namely WebGL). Besides the issue that arises below, I further noticed that neither glInterleavedArrays nor
glEnableClientState nor gl*Pointer calls seems to be part of any OpenGL ES implementation, let it be OpenTK, JoGL or WebGL. So I wonder how to use geometry batching through VBOs at all?

So how do I replace my glInterleavedArrays call properly in OpenGL ES? And maybe if someone knows, why does the following replacement crash in the latest JoGL implementation (and maybe also everywhere else)?

// using

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, m_VertexBufID);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, m_IndexBufID);
gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY) ;
gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 32, 0);
gl.glNormalPointer(GL.GL_FLOAT, 32, 8);
gl.glVertexPointer(3, GL.GL_FLOAT, 32, 20);

// to replace the following

gl.glInterleavedArrays(GL2.GL_T2F_N3F_V3F, 0, 0);

// results in a memory access violation in

gl.glDrawElements(GL.GL_TRIANGLES, xCount * IndicesPerBlock,
GL.GL_UNSIGNED_INT,(offset + xBlock * IndicesPerBlock) * 4);

thanks for your help
chris

Alfonse Reinheart
04-11-2011, 12:36 AM
Besides the issue that arises below, I further noticed that neither glInterleavedArrays nor
glEnableClientState nor gl*Pointer calls seems to be part of any OpenGL ES implementation, let it be OpenTK, JoGL or WebGL.

I can't speak to JoGL or OpenTK, but WebGL is based on OpenGL ES 2.0.

And ES 2.0 is a lot like core GL 3.0 and above: shaders only.

So no glVertexPointer, glTexCoordPointer, etc. Only generic vertex attributes: glVertexAttribPointer and glEnable/DisableVertexAttribArray are available. This also means that you must use custom attributes in your vertex shaders.

Besides, you shouldn't have been using glInterleavedArrays even in regular OpenGL. Avoiding that (and manually interleaving) has been the recommendation for years.

Foobarbazqux
04-11-2011, 03:33 AM
gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY) ;
gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 32, 0);
gl.glNormalPointer(GL.GL_FLOAT, 32, 8);
gl.glVertexPointer(3, GL.GL_FLOAT, 32, 20);



You enable texture coord array, color array and vertex array, but you set the pointers for texture coord array, normal array and vertex array.

You probably want something like


gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY) ;
gl.glEnableClientState(GL2.GL_NORMAL_ARRAY); <-
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 32, 0);
gl.glNormalPointer(GL.GL_FLOAT, 32, 8);
gl.glVertexPointer(3, GL.GL_FLOAT, 32, 20);

Alfonse Reinheart
04-11-2011, 03:39 AM
He's using GL ES 2.0/WebGL; those functions don't exist.

thesaint
04-11-2011, 08:38 AM
@Alfonse Reinheart: >This also means that you must use custom attributes in your vertex shaders.

Well sorry, I am one of these Direct X guys ;). I recently switched to OpenGL due to interoperability and I like the new way without fixed functions, since I am not used to anything else in DirectX 10. But I barely know the API! Could you please give me some hints for a good tutorial or something alike where I can read about those custom attributes?!

As far as I noticed, the new OpenGL APIs are rarely documented, its very hard to find resources or tutorials, so I am a little lost right now!

regards
chris

thesaint
04-11-2011, 08:42 AM
@Foobarbazqux: Gee thats a stupid mistake ;). Just happens when you copy paste code you don't know about xD. Indeed fixed the access violation but that doesn't help me much for now, since the methods involved here are not supported in OpenGL ES... :(

thesaint
04-11-2011, 09:10 AM
I figured out I need to do something like this:

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, m_VertexBufID);

gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 2, GL.GL_FLOAT, false, 32, 0);
gl.glEnableVertexAttribArray(1);
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 32, 8);
gl.glEnableVertexAttribArray(2);
gl.glVertexAttribPointer(2, 3, GL.GL_FLOAT, false, 32, 20);

gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, m_IndexBufID);

But it delivers a black screen. Provided that my above sample code is working, what can be wrong here? Do I have to further enable some render states? Huh, one thing that comes into my mind right now is that this way OpenGL doesn't now what is actually stored in there... *sight* but how can I tell it how to thread this data?

BionicBytes
04-11-2011, 09:14 AM
and how have you associated the vertex attribute arrays with the shader?
ie the vertex attribute bind locations?

thesaint
04-11-2011, 09:19 AM
Well right at this moment I also noticed that this is a little underspecified by me ;). But I wonder what I have to do to tell OpenGL those things? Seems like I have to attach these streams to shader uniforms? But this is a little too much for me right now... Where can I find an example? BTW I am already familar with uniforms and also passing the world/proj matricies this way... But how does the thing work with vertex data?

BionicBytes
04-11-2011, 09:38 AM
When you compile a shader program and then link it you need to track where in the program all those uniforms and vertex attributes have been put. I do this by querying GL and looping over the number of uniforms/vertex attributes returned.





compileshader (s,l, glslProgramContext,glslVertexShader, GL_VERTEX_SHADER,VS_Compile_error,loadOK);
..
compileshader (s,l, glslProgramContext,glslGeometryShader, GL_GEOMETRY_SHADER,GS_Compile_error,loadOK);
..

glLinkProgram (glslProgramContext);
glGetProgramiv (glslProgramContext, GL_LINK_STATUS, @loadOK);
glgetProgramiv (glslProgramContext, GL_ACTIVE_UNIFORMS , @NumActiveUniforms);
glgetProgramiv (glslProgramContext, GL_ACTIVE_UNIFORM_MAX_LENGTH , @UniformBuffsize);
glgetProgramiv (glslProgramContext, GL_ACTIVE_ATTRIBUTES, @NumActiveAttributes);
glgetProgramiv (glslProgramContext, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH , @AttributeBuffsize);
glgetProgramiv (glslProgramContext, GL_ACTIVE_UNIFORM_BLOCKS, @NumActiveUniformsBlocks);
glgetProgramiv (glslProgramContext, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH , @UniformBlockBuffsize);
setlength (ActiveUniformList.Uniform, NumActiveUniforms);
setlength (ActiveUniformList.Attribute, NumActiveAttributes);
setlength (ActiveUniformList.UniformBlock, NumActiveUniformsBlocks);

//loop through list of shader attributes, and update the index reference in our attribute list to match.
for i := 0 to NumActiveAttributes -1 do
begin
glGetActiveAttrib (glslProgramContext,i, AttributeBuffsize, nil, @_size, @_type, @error[0]);
ActiveUniformList.Attribute[i].name := ansistring (error); //record the list of attributes returned by the compiler.
ActiveUniformList.Attribute[i].valueTypes := _type;
ActiveUniformList.Attribute[i].ValueTypeAsString := GLUniformTypeToString (_type);
ActiveUniformList.Attribute[i].Location := glGetAttribLocation (glslProgramContext, error);

for j := low(VertexAttributes) to high (VertexAttributes) do
begin
if VertexAttributes[j].index <> -2 then continue; //-2 = auto bind.
if NOT (string (error) = VertexAttributes[j].attribname) then continue;
VertexAttributes[j].index := glGetAttribLocation (glslProgramContext, pglchar (VertexAttributes[j].attribname) );
end;
end;

//loop through list of shader uniforms
for i := 0 to NumActiveUniforms -1 do
begin
//legacy API - default uniform block
glGetActiveUniform (glslProgramContext,i, UniformBuffsize, nil, @_size, @_type, @error[0]);
ActiveUniformList.Uniform[i].name := ansistring (error); //record the list of uniforms returned by the compiler.
ActiveUniformList.Uniform[i].valueTypes := _type;
ActiveUniformList.Uniform[i].ValueTypeAsString := GLUniformTypeToString (_type);
ActiveUniformList.Uniform[i].Location := glGetUniformLocation(glslProgramContext, error);

//uniform blocks - handle separately....
ActiveUniformList.Uniform[i].Indicies := -1;
ActiveUniformList.Uniform[i].GL_UNIFORM_BLOCK_INDEX := -1;
ActiveUniformList.Uniform[i].GL_UNIFORM_OFFSET := 0;
if ActiveUniformList.Uniform[i].Location > -1 then
begin
uniformlist := pglchar(ActiveUniformList.Uniform[i].name);
glGetUniformIndices(glslProgramContext, 1, @uniformlist, @ActiveUniformList.Uniform[i].Indicies);

if ActiveUniformList.Uniform[i].Indicies > -1 then //block uniform found
begin
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_TYPE, @ActiveUniformList.Uniform[i].GL_UNIFORM_TYPE);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_SIZE, @ActiveUniformList.Uniform[i].GL_UNIFORM_SIZE);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_NAME_LENGTH, @ActiveUniformList.Uniform[i].GL_UNIFORM_NAME_LENGTH);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_BLOCK_INDEX, @ActiveUniformList.Uniform[i].GL_UNIFORM_BLOCK_INDEX);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_OFFSET, @ActiveUniformList.Uniform[i].GL_UNIFORM_OFFSET);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_ARRAY_STRIDE, @ActiveUniformList.Uniform[i].GL_UNIFORM_ARRAY_STRIDE);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_MATRIX_STRIDE, @ActiveUniformList.Uniform[i].GL_UNIFORM_MATRIX_STRIDE);
glGetActiveUniformsiv (glslProgramContext, 1, @ActiveUniformList.Uniform[i].Indicies, GL_UNIFORM_IS_ROW_MAJOR, @ActiveUniformList.Uniform[i].GL_UNIFORM_IS_ROW_MAJOR);

addUniformBlock (index, i, UniformBlockBuffsize);
end;
end;


fillmemory ( @error[0], 4095, 0);
glGetProgramInfoLog(shaders[index].glslProgramContext, 4095, NIL, @error[0]);

The more modern OpenGL 3.3 way is to explicitly tell GL the bind locations of these resources. The choice is yours and I have no need to alter what I have since it works reasonably well.

thesaint
04-11-2011, 09:54 AM
Thanks ;). OK I got it now by the following replacement for glInterleavedArrays():

int locPosition = gl.glGetAttribLocation(m_Engine.getTerrainShader() .getProgramID(), "Position");
int locTexCoord = gl.glGetAttribLocation(m_Engine.getTerrainShader() .getProgramID(), "TexCoords");
int locNormal = gl.glGetAttribLocation(m_Engine.getTerrainShader() .getProgramID(), "Normal");

gl.glEnableVertexAttribArray(locTexCoord);
gl.glVertexAttribPointer(locTexCoord, 2, GL.GL_FLOAT, false, 32, 0);
gl.glEnableVertexAttribArray(locNormal);
gl.glVertexAttribPointer(locNormal, 3, GL.GL_FLOAT, false, 32, 8);
gl.glEnableVertexAttribArray(locPosition);
gl.glVertexAttribPointer(locPosition, 3, GL.GL_FLOAT, false, 32, 20);

gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, m_IndexBufID);

=======================

And the in the shader added:

attribute vec3 Position;
attribute vec2 TexCoords;
attribute vec3 Normal;

to replace the builtin "gl_Vertex", etc. placeholders...

Well I guess this was rather easy but I wonder why there is no clean and easy tutorial showing this stuff? Its a matter of minutes to set it up once you have understood it but at the beginning you are totally lost.

PS: For DirectX there are tons of tutorials dealing with this stuff, also excellent ones. In my eyes, if you are a beginner in computer graphics (I am not), you will rather give up OpenGL and instead stick with DirectX because it is much easier to learn from the perspective of available resource. Or I am just to dumb to find them (talking about the new API of course)...

V-man
04-11-2011, 03:30 PM
You seem to be asking about GL ES 2.0 and these forums are for OpenGL. There are some similarities so if you really want to, you can read the Wiki.
http://www.opengl.org/wiki/Main_Page

There are some GL 3.x tutorials : http://www.opengl.org/wiki/Tutorials

and information about GLSL : http://www.opengl.org/wiki/Shading_languages

etc. etc. etc.

As for GL ES, the site is at www.khronos.org (http://www.khronos.org) and they have their own forums. I don't know if they have a Wiki and such so you should ask them.

Alfonse Reinheart
04-11-2011, 03:30 PM
As far as I noticed, the new OpenGL APIs are rarely documented, its very hard to find resources or tutorials, so I am a little lost right now!

You must not have looked. You cannot possibly have looked. Either that, or your Google-Fu is very weak.

When I Googled for "OpenGL API" (http://www.google.com/search?source=ig&amp;hl=en&amp;rlz=&amp;q=OpenGL+API&amp;btnG=Goog le+Search), this was the very first hit. (http://www.opengl.org/documentation/) This page has direct links to the reference documentation for GL 2.1, 3.3, and 4.1.

The OpenGL Wiki (http://www.opengl.org/wiki/Main_Page) contains answers for everything you asked. Indeed, if you searched for "glVertexAttribPointer" (http://www.opengl.org/wiki/GlVertexAttribPointer), it would take you to a page with step-by-step instructions on how to use this function. Even if you Googled for "glVertexAttribPointer" (http://www.google.com/search?hl=en&amp;q=glVertexAttribPointer&amp;aq=f&amp;aqi=g10&amp; aql=&amp;oq=), the OpenGL Wiki article is the third page.

If you had searched for "Tutorials" in the OpenGL Wiki, you would have found a page that links to two tutorials that explain exactly what you're trying to do.

And if you did something as simple as click on the link in my signature, you would have been taken to a tutorial site that would explain a great deal about shaders, vertex attributes, and feeding OpenGL data.

So don't act like the information doesn't exist.

thesaint
04-12-2011, 12:57 AM
Well I didn't want to start a discussion about this. You are right, the following page shows such a tutorial:

"http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders _%28C_/_SDL%29"

I am not saying that it is hard to find tutorials or docs for OpenGL in general. I am only talking about the "fresh new" API, which in fact is the only one competive to DirectX. Of course most of this stuff has been there before, but now that so many methods have vanished, most of the existing tutorials and docs are either deprecated or don't work at all. Maybe all those docs drown in all the "old" OpenGL docs...

I never even look at signatures so don't mind ;). They are not in my field of view. Seems to be quite a collection you've got there.

Didn't mean to offend you; I am just a little complicated, I always want information to be presented to me in a "perfect" way, like I try when I present something to my audience. But after all, a few screams and I will also consume any kind of material as long as it helps me to solve the problem...

Alfonse Reinheart
04-12-2011, 01:17 AM
I am only talking about the "fresh new" API, which in fact is the only one competive to DirectX.

There's the first problem. There is no "fresh new" API. Core 3.1 and above is simply missing some functions; the API is no more "fresh" than 3.0 or prior.

More to the point, there is nothing stopping you from just using the compatibility profile. All of the OpenGL implementations support it, and due to the need to support legacy applications, they will support it indefinitely.

In short: all of those old tutorials are just as functional nowadays as they were before.

The second problem is one that many people have: thinking that OpenGL ES is OpenGL. It is not.

OpenGL ES is a different specification from OpenGL. It certainly has some similarities in function names, enumerators, and functionality. But it's not the same thing. OpenGL ES 2.0 is not the same thing as OpenGL 3.1 core profile.