Lighting with OpenGL 3+

Hi,

I’m currently trying to setup lighting for a project,

When I’m set to OpenGL 2.1 it seems to work fine but then once I switch to OpenGL 3.3 the light doesn’t seem to work at all unless I add a Material on every on my assets/geo. I need 3.3 for other feature in the project.

All I’m using for this exemple is a ofLight, OfDrawBox and a Gui to move my ofLight around.

Edit: I did Thormind’s post for OpenGL 3+ which mention briefly a ofLight issue, in my case there’s no multiple window setting or anything similar to his setup.

OpenGL 2.1:
OpenGL2.1

OpenGL 3.3:
OpenGL3.3

Hi, which OS are you using?

can you post the code you are using for this examples please?

I’m on Windows 10,

my main

ofGLFWWindowSettings settings;
settings.resizable = false;
settings.setSize(1440, 900);
settings.setGLVersion(3, 3);
ofCreateWindow(settings);
return ofRunApp(new ofApp);

my .h (Minus the usual setup,update,draw, etc)

	ofxPanel gui;
	ofParameter <ofVec3f> uiPosition;

	ofEasyCam camera;
	ofLight light_spot;

my .cpp

void ofApp::setup(){

	gui.setup();
	gui.add(uiPosition.set("position", ofVec3f(0, 0, 0), ofVec3f(-300, -300, -300), ofVec3f(300, 300, 300)));
}

void ofApp::update(){
	light_spot.setPosition(uiPosition->x, uiPosition->y, uiPosition->z);

}

void ofApp::draw(){
	gui.draw();
	ofEnableDepthTest();
	light_spot.enable();
	camera.begin();
	light_spot.draw();

	ofDrawBox(0, 0, 0, 25);

	camera.end();
	light_spot.disable();
	ofDisableDepthTest();
}

Did you try ofEnableLighting(); ?

1 Like

I did and it doesn’t change anything, thanks tho !

Hey @Frank1, thanks for posting some simple example code! I played around with it a bit, and yeah I’m thinking that for the programmable pipeline (openGL 3.x ?), the ofLights need an ofMaterial to react with. The /gl/multiLightExample has a few different kinds of lights and an ofMaterial. Also the ofLight section of the documentation has a decent explanation of lights, material, and camera.

So, you don’t need to use an ofMaterial with each individual 3d object, though you can if you want. A common use might be something like:

add to your ofApp.h:

ofMaterial material;

to your ofApp::setup():

// from the multiLightExample:
// shininess is a value between 0 - 128, 128 being the most shiny //
	material.setShininess( 120 );

in your ofApp::draw():

void ofApp::draw(){
    ofEnableDepthTest();
    ofEnableLighting();
    light_spot.enable();
    material.begin();
    camera.begin();
    light_spot.draw();
    ofDrawBox(0, 0, 0, 25);
    camera.end();
    material.end();
    light_spot.disable();
    ofDisableLighting();
    ofDisableDepthTest();
    
    gui.draw();
}

I’m not sure if the calls to ofEnableLighting() and ofDisableLighting are needed or not, though they were included in the multiLightExample.

1 Like

Thanks, I was looking for example and didn’t think of looking into the GL folder, this is really helpful.

I’m just confused about one thing you mentioned:

I’m thinking that for the programmable pipeline (openGL 3.x ?), the ofLights need an ofMaterial to react with.

Then

So, you don’t need to use an ofMaterial with each individual 3d object

Those two bit of information seems contradictory, you mention that indeed it needs a material to work but then that it’s not necessary, unless I’m misunderstanding something :sweat_smile:

Thanks again !

OK yes sure let me clarify a bit. So, you should have at least 1 ofMaterial, but you can also have more than 1. For example, if you had 5 different of3dPrimitives, you could have 5 different ofMaterial, 1 for each primitive. You could set different characteristics for each (shininess, ambient color, specular color, etc) so that they look and react differently. And for each ofMaterial, you’ll have 1 pair of calls to .begin() and .end(), and between those calls you’ll draw all of things you want that ofMaterial applied to.

If all 5 of your 3d objects can have the same ofMaterial characteristics, then you just need 1 ofMaterial, and draw all 5 of them between calls to .begin() and .end(). Does this make a bit more sense?

The /gl examples folder has lots of great projects. There is a separate /examples folder for shaders. And then some of the examples in the 3d folder have some of the gl classes in them too, like the 3dPrimitivesExample (ofLight, ofMaterial). So sometimes there is some overlap. But typically, if the oF class resides in the gl section of the documentation, the /examples/gl folder is a good place to look for examples with those classes.

1 Like

Yep make total sense, I was just testing out having a “global” material that is applied at first, then in between in I enable more Materials for specific Shapes which seems to work, thanks again.

I noticed that having a Material will overwrite any OfSetColor I would add to a 3dPrimitve, so I’m assuming that the color I’m setting with the later function should simply be set in the Material through Diffuse/Specular colors ?

For an easy exemple just take the code you’ve sent earlier and add a OfSetColor above the OfDrawBox and notice that the box will remain “grey” in this case.

I’m thinking too that ofDrawBox may not the same as drawing an ofBoxPrimitive, where you have an ofMesh. With an ofMesh, you can also set a color for each vertex. And I wanted to add to my previous post that you might need to set the normals in the mesh in order for the light to interact with it properly. Its been a few years since I’ve done anything nontrivial with ofLight, ofMaterial, etc. Usually I use textures with of3dPrimitives. So anyway just keep this thought in mind about setting the normals for an ofMesh if you can’t get things to look quite right.

I thought the light looked a bit “flat” from ofDrawBox and a fairly shiny ofMaterial. Its what got me thinking about the normals.

As for the color, you’ll have to experiment a bit more. I would speculate that colors from ofMaterial and ofLight will override ofSetColor, and maybe the colors of the vertices in an ofMesh. But definitely please post a comment if you find out differently. I think I remember reading somewhere (maybe in one of the oF header files) that oF uses a Phong shading approach for this kind of 3d rendering.

If you have few/lots of different 3d objects, each with a unique ofMaterial, you could use a struct or a small class that bundles the 3d object with an ofMaterial, colors, etc, plus any other similar variables or methods (to set themselves up, draw themselves, lerp their colors, increment position, etc).

1 Like

Just tried by replacing the ofDrawBox with BoxPrimitive and I’m getting the same results but so far it’s looking good enough for the purpose of the project.

I’ll keep experimenting, thanks again.

1 Like