Archived

This topic is now archived and is closed to further replies.

I'm very confused about the fixed function pipeline

This topic is 4944 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm coming from Direct3d, so there are similarties but also great differences. My short-term goal is to apply a normal map to my object (to do simple per pixel dot3 bumpmapping against a constant light direction). Until I can do that, I'm simply just trying to multitexture an object in OpenGL. I think I keep looking at code and tutorials and code for different versions of OpenGL or something. I read in the specifications that param 2 of the function glTexEnv must be either GL_TEXTURE_ENV_MODE or GL_TEXTURE_ENV_COLOR. And then I go and read code like this: glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2); Or worse: //Set up the blending of the 2 textures glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_INTERPOLATE_EXT); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_EXT,GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT,GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_EXT,GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_EXT,GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_EXT,GL_SRC_ALPHA); What is the specs talking about then? and where can I find all that's possible with this function?? Something must be wrong here. Not only that, but I'm totally confused when I should call glTexEnv (not in my render function, right?) and when I should enable/disable textures and such.. I'm using vertex buffer objects. So I suppose it should be something like glClientActiveTexture(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); glClientActiveTexture(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); Render(); or... what? Where can I find simple documentation on the GL_ARB_multitexture extension?? Believe me, I looked around and everything just seems to be scattered! Could somebody write a simple, clear explanation of the basic process of how this works. I don't expect an essay... I dunno, just a paragraph of how I should learn more about this. Thanks a lot! edit: Another thing I'm confused about. Where does glBlend() come into all of this? [edited by - okonomiyaki on May 28, 2004 8:12:53 PM]

Share this post


Link to post
Share on other sites
Well the specs u read are correct and yes it can be confusing :D

what u have with GL_COMBINE_ARB parameter is an extension to opengl. Extension is the mechinism that allows opengl to evlove and grow. Vendors (such as ati, nv) create exetensions to the opengl language. if these are popular or useful then at some point they will be promoted, refined and included in later versions of Opengl. FOr example (Occusion culling extension was created by HP, but Nvidia built on this and release better functionalty to that of the HP occusion extension, and finally, Occusion culling was promoted to the Core Opengl 1.5) so we can see how useful functionalty is revised and bubbles up to the core.

This specific "extension" is called Texture-Environment-Combiners and is defined by the extension string "GL_texture_env_combine". Now the specifications ur reading are probably for openGL 1.2 so the specification are correct (there are no "texture-env-combiner" functionality in gl 1.2), but functionalty that is not defined in the 1.2 specification can accessed thru extensions (this is how opengl gets past the limiations on the microsoft platforms,...but more on that later).

The texture_env_combine functionality was so popular (accepted by industry) that in one of the versions of opengl the incoporated it into the core. So if you read the 1.4 specs (or what ever version it was incoporated), it should have the proper ammendments made (this is true for other extensions that have been promoted to the core). IN the 1.4 specs the GL_COMBINE_ARB will loose the _ARB postfix (extension are noted with _ARB, _EXT, _ATI, _NV, _APPLE, depending on the status of the extension)

If you are working with opengl 1.2 and you want to access extensions then you should stick with the 1.2 specs but look up the specs for extesions under the extension registry:
http://oss.sgi.com/projects/ogl-sample/registry/

this is the specific registry for texture_Env_combine
http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt

more info on extension:
http://www.opengl.org/documentation/extension.html


anyways hope this clears things up (there might be more on extensions in the opengl forum faq). Oh ya, about Microsoft, they only support GL 1.2 (for one reason or another) so any sort of functionalty > 1.2 must be accessed thru the exteison mechinism (ie. if you want OpengL 1.4 functionalty,then you have to access it through extensions).



[edited by - _walrus on May 28, 2004 9:15:25 PM]

Share this post


Link to post
Share on other sites
I might not be the best to explain this, but i'll try.

I had my own problems about a month ago with this, and i must say that this was (in my opinion) horribly disigned. Any way, here it goes:


This says OGL you are going to use the Combine Extension.
It lets you define a set of blending functions that you couldnt define with the standard way.
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT);

Now, you can define wich type of combiner function you want to use. Here the parameter GL_INTERPOLATE_EXT defines you want an interpolator function.
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_INTERPOLATE_EXT);

Now you must say to OpenGL wich are the parameters for the function (operands). Each function has 2 or 3 arguments. You can find this functions in the spec.
Each operand is defined by two different things, the source itself and "the information you want from the source". For example:
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_EXT,GL_SRC_COLOR);

You are saying here that Operand0(GL_OPERAND0_RGB_EXT) = rgb_color(GL_SRC_COLOR) from the previous texture applyed (GL_PREVIOUS_EXT).

The same way, you are saying here that operand1 = rgb from the actual texture.

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_EXT,GL_SRC_COLOR);

etc.

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_EXT,GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_EXT,GL_SRC_ALPHA);


Now, be aware that you can define diferent functions for ALPHA and RGB, hence the _RGB behind enums like GL_OPERAND0_RGB_EXT.

As i said, take a look at the specs for other posible functions. Its easyer to understand with anything other than INTERPOLATE

I know what you are thinking... this is mad. It is. I hate it with all my heart. Thank goodness programable hardware will be a standard relatively soon.

As for when exactly you have to call all this, i can't say for sure. Im doing it every time I do a material change and it does work ok. That is, everytime after I define all the texture unit's textures.

glBlend is another matter. glBlend is a blending process done between your final texel and the pixel already drawn in the frame buffer, at the end of the pipeline process. Hence you can and have to define diferent independent functions.

EDIT: Umm, someone was faster than me. Still, this can help.

[edited by - BahamutCube on May 28, 2004 9:17:57 PM]

Share this post


Link to post
Share on other sites
quote:

What is the specs talking about then? and where can I find all that''s possible with this function?? Something must be wrong here.


You seem to have old specs. The constants you mentioned (GL_COMBINE_ARB) are defined by an extension, ARB_texture_env_combine in this case. You can recognize extension specific functions or constants by the suffix: ARB, EXT, NV, ATI, and so on. Functions and constants without suffix are part of the OpenGL core.

Now, GL_COMBINE (notice the lack of ARB) is defined in the core since OpenGL version 1.3 (current version is 1.5). You probably have an old 1.1 spec document. Of course, if you are working under Windows, you cannot access core features above version 1.1 anyway. But they are still fully available as extensions. You can find a complete list of all available extensions at the official extension registry.

quote:

Not only that, but I''m totally confused when I should call glTexEnv (not in my render function, right?)


glTexEnv() sets up the combiner pipeline. It''s for the fixed function pipeline what fragment programs are for the programmable pipeline. You can call them wherever you want (except in IM, within a begin/end pair), the texture combining equation will change from the moment you issued the calls. Typically, they are called whenever you want to render a new material or surface type.

I''ll give you an example:

// Set combiner mode
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

// Fragment colours come from primary colour source
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);

// Draw the object: it will be rendered using the interpolated colour values
glDrawElements(...)

// Fragment colours now come from the texture unit 0
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);

// Draw the object again: it will now by using the colours from texture 0
glDrawElements(...)


quote:

and when I should enable/disable textures and such


This function is pretty obsolete on todays hardware, as you can route the combiner modes independently of active or inactive units (especially when using fragment programs). For now, don''t worry about that. Simply enable all units you will use at startup, and disable them at shutdown.

quote:

Where can I find simple documentation on the GL_ARB_multitexture extension?? Believe me, I looked around and everything just seems to be scattered!


It''s in the recent OpenGL specs. There is a link somewhere on opengl.org to download the PDF.

quote:

Could somebody write a simple, clear explanation of the basic process of how this works


OK, there you go:

At startup, enable all the units you''ll use. For two units, that''s:

glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);

Now, you create and load all your textures, setup the vertex buffers and index buffers (if any), init everything.

For each mesh or object you want to render, you do the following:


// Setup the combine environment mode for the object
glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
... etc ...

// Bind the textures the mesh will use on each unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, &the_texture_for_0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, &the_texture_for_1);
glActiveTexture(GL_TEXTURE0);

// Set the vertex array pointers to the object''s mesh data
// again, for each unit
glClientActiveTexture(GL_TEXTURE0);
glVertexPointer(...)
glClientActiveTexture(GL_TEXTURE1);
glVertexPointer(...)
glClientActiveTexture(GL_TEXTURE0);

// And finally, draw the object
glDrawElements(...)

Repeat for every object to render.

Now, this skeleton will work, but is very unoptimized. There is a lot of modifications you can do to make it run faster. First of all, you''ll want to batch your objects, in order to reduce the number of environment mode changes and texture binds. Then, you can compile complex glTexEnv() sequences into a display list beforehand, and simply call the list to activate the combine mode. That''s both cleaner and faster, as it saves function call overhead.

Last but not least, the example above uses plain vertex arrays, and should be rewritten to VBOs for the sake of good performance.

quote:

edit: Another thing I''m confused about. Where does glBlend() come into all of this?


glBlend() controls the blending unit. It''s used to blend the outgoing fragment (from the fixed or programmable pipeline) with the current contents of the framebuffer. It''s typically used for transparency effects and such.

Share this post


Link to post
Share on other sites
_walrus, thanks, I have a pretty good grasp on extensions. I''m using VBO''s and it works great. Problem was, I just couldn''t find any clear explanation of what was the current way of using the multitexture extension (or texture_env_combine, nobody told me about that ). Thanks though.

quote:

I know what you are thinking... this is mad. It is. I hate it with all my heart. Thank goodness programable hardware will be a standard relatively soon.


Ah, thanks a ton for the examples. That answers my main question. That''s not too bad.. it''s actually similar to DirectX''s way of doing it (int terms of setting the operands and sources and such, I know the system is very different). I understand it now. I am going to use shaders at some point, but I figured that I should get it working first without shaders. If I can''t do it without shaders, that doesn''t say much about my understanding of OpenGL.
I understand the difference between glBlend now as well. Cool. Thanks!

quote:

glTexEnv() sets up the combiner pipeline. It''s for the fixed function pipeline what fragment programs are for the programmable pipeline. You can call them wherever you want (except in IM, within a begin/end pair), the texture combining equation will change from the moment you issued the calls. Typically, they are called whenever you want to render a new material or surface type.



Ok, that''s what I wanted to believe. Thanks so much for the examples, that clears up so much.

quote:

This function is pretty obsolete on todays hardware, as you can route the combiner modes independently of active or inactive units (especially when using fragment programs). For now, don''t worry about that. Simply enable all units you will use at startup, and disable them at shutdown.



Ok, great! Because every code I saw, every frame they did
glActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
...

And I''m thinking, what the heck? I don''t see why you would do that. Thanks for clearing that up

quote:

Repeat for every object to render.

Now, this skeleton will work, but is very unoptimized. There is a lot of modifications you can do to make it run faster. First of all, you''ll want to batch your objects, in order to reduce the number of environment mode changes and texture binds. Then, you can compile complex glTexEnv() sequences into a display list beforehand, and simply call the list to activate the combine mode. That''s both cleaner and faster, as it saves function call overhead.

Last but not least, the example above uses plain vertex arrays, and should be rewritten to VBOs for the sake of good performance.



Awesome. That makes it so much clearer. Yay I can finally play around with it. Thanks! I have VBO''s running, and display lists aren''t very hard. I mainly just wanted to see the basic order of rendering with it.

Thanks again guys. It''s a whole lot clearer now.

Share this post


Link to post
Share on other sites