Specular lights on cube in opengl es

2.8k views Asked by At

In some tutorials where the lighting is introduced, people would start with an example of a sphere, lit by all three types of lights: ambient, diffuse and specular. One can then easily see, e.g. by switching off individual lights, that the ambient one is responsible for uniform lighting of the object, the diffuse one comes from a specific direction, and thanks to the specular light we can observe a bright spot on the surface.

I tried to repeat the same steps with a simpler example, a cube that the user can arbitrarily rotate. What I actually expected to see was a similar picture: I presume OpenGL should to some extent follow the rules of geometrical optics, and, if positions of both the light source and the camera are specified, there should be only one bright spot on one of the cube faces, the one that reflects the light source directly onto the camera.

However, I could only obtain uniformly lit faces, never a bright spot. So, my question is, is it actually possible to get it? Forgot to mention, I used the simplest possible triangulation -- 2 triangles per face. Another thing, I am using OpenGL ES 1.1 so, no shaders.

3

There are 3 answers

0
Diversity On

The lighting strongly depends on the amount of vertices you have for each side of your cube. Since you are not using shaders the lighting is calcalulated per Vertex. But the calculation depends on the surface normal which is orientated perpendicular to the face and is calculated per face means 3 vertices.The normals are the same for each vertex of the face thats why the light intensity for each vertex is also the same, so that you can't see any lighting effect. If you calculate the normals correctly you must see a difference in the color of the different sides of the cube. To achieve some spot on one side you have to increase the grid resolution of each side of the cube and you have to apply an approriate angle for the cone of the spot light or you minimize the distance of the spotlight to the cube.

            n1         n2
           /          /
          /          /
        v1 ---------- v2
         |         / 
         |       /
         |  n3 /    
         | / /
         |//
         |
        v3            v4

Take a look at this nice tutorial. It explains the basic mechanism in an very understandable way: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-8-basic-shading/

0
user1781290 On

There are some issues with your example.

You need to distinguish between a point light and directional light. You did not explicitely state in your question which you use (EDIT: You get a directional light if your 4th coordinate of the light is 0, else you get a point light)

There is a nice picture showing the difference in this question

https://i.stack.imgur.com/3udUJ.gif(from okino.com)

If you use a directional light source, then of course all the points on one side of your cube will have the same lighting calculation and thus the same resulting color. If you use a sphere instead, you will get highlights.

If you use a point light, then you run into trouble because of OpenGL (ES) - fixed pipeline lighting model. It calculated lighting per-vertex. Since you only use 5 different vertices per cube side, you again end up with little differences in lighting. You can get around this by using a per-pixel-lighting shader or tesselating your cube into smaller triangles.

Of course there are also a number of minor "traps", you need to make sure, that your different lights (sources and types) don't emit too much light when combined, this will mess up your lighting. Also be sure that the normals are set correctly.

0
6502 On

Lighting calculation in OpenGL is computed per-vertex and the result is then interpolated linearly (possibly with perspective correction) over the pixels of each face.

This means that if you model a cube with just four vertices there is no way you can get a bright reflection spot in the middle of a face. The cube face lighting will always be composed of just two gradients: one for each of the two triangular faces.

To approximate a per-pixel lightning you need to subdivide the faces in a lot of small triangles... or you need to use other techniques: for example using "pixel/fragment shaders" to compute a per-pixel lightning or texture mapping tricks to emulate the same.

For an explanation of fragment shaders on OpenGL ES see http://www.learnopengles.com/android-lesson-three-moving-to-per-fragment-lighting/

Using texture mapping tricks (normally called the "environment mapping" approach) it's easy to even emulate convincing shiny objects that can reflect the environment and not only the light sources on a per-pixel basis.

http://raksy.dyndns.org/torus.html is a web canvas demo where the shiny reflection is indeed computed using a texture mapping trick. Actually that code doesn't depend on any 3d support at all and draws the triangles using just 2d transformation matrices that the html5 canvas object provides.

As you can notice the object geometry is very rough (each patch on the torus is just 9 vertices) but the light source reflection is defined and you can even see the distorted reflection of the tiled floor.

environment mapping trick