Sign in to follow this  
kevape

Lighting position problem

Recommended Posts

Hi Guys, Can anyone help me, i am new to java 3D, i am using JOGL but code is similar to C++ etc any way. private float[] lightPosition = { 0.0f, 0.0f, 2.0f, 1.0f }; the tutorial on NeHe says set your z position to 2.0f so that the light source should be in line with the monitor, basically the light source should come from right infront of the cube, however, when i spin the cube using the up/down/left and right keys, the light seems to be moving aswell as the cube, so sometimes the cube is in complete darkness. can anyone help me, the complete code is here, if you spot anything ill much appreciate it. import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.io.*; import java.net.*; import java.nio.*; import javax.imageio.*; import net.java.games.jogl.*; import net.java.games.jogl.util.*; public class Lesson02 { static Animator animator = null; static class Renderer implements GLEventListener, KeyListener { private float xrota; // five variables to control rotation of cube and speed private float xspeed; private float yspeed; private float yrota; private float z = -5.0f; private float x = 0.0f; private float y = 0.0f; // Lighting variables private boolean light; //Light on or off private boolean lp; //"L" pressed on keyboard? private boolean fp; //"F" pressed on keyboard? private float[] lightAmbient = { 0.5f, 0.5f, 0.5f, 1.0f }; private float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; private float[] lightPosition = { 0.0f, 0.0f, 2.0f, 1.0f }; int filter; private int[] texture = new int[3]; // stores bricks.png and stores [1)glnearest(no smoothing), // 2)gllinear(smoothing) & 3)mipmapped(best looking)] public void display(GLDrawable gLDrawable) { final GL gl = gLDrawable.getGL(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); //LEFT/RIGHT(X), UP/DOWN(Y), FORWARD/BACK(Z) gl.glTranslatef(this.x, this.y, this.z); // z is equal to -5.0f gl.glRotatef(xrota, 1.0f, 0.0f, 0.0f); gl.glRotatef(yrota, 0.0f, 1.0f, 0.0f); gl.glBindTexture(GL.GL_TEXTURE_2D, texture[filter]); if (light) gl.glEnable(GL.GL_LIGHTING); else gl.glDisable(GL.GL_LIGHTING); gl.glBegin(GL.GL_QUADS); // FRONT gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); // BACK gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); // TOP gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); // BOTTOM gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); // RIGHT gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, -1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f); gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f); // LEFT gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f); gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f); gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f); gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, -1.0f); xrota += xspeed; // set both xrota & yrota variables to x & yspeed variables as yrota += yspeed; // these change depending on key presses from user gl.glEnd(); gl.glFlush(); } public void displayChanged(GLDrawable gLDrawable, boolean modeChanged, boolean deviceChanged) { } public void init(GLDrawable gLDrawable) { final GL gl = gLDrawable.getGL(); final GLU glu = gLDrawable.getGLU(); gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background gl.glClearDepth(1.0f); // Depth Buffer Setup gl.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing gl.glDepthFunc(GL.GL_LEQUAL); // The Type Of Depth Testing To Do gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Really Nice Perspective Calculations gl.glEnable(GL.GL_TEXTURE_2D); gLDrawable.addKeyListener(this); BufferedImage img = readPNGImage("data/bricks.png"); gl.glGenTextures(3, this.texture); // begin to set up three available texture settings // glnearest, linear and mipmapped //nearest - 0 gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, false); //linear - 1 gl.glBindTexture(GL.GL_TEXTURE_2D, texture[1]); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, false); // mipmap - 2 gl.glBindTexture(GL.GL_TEXTURE_2D, texture[2]); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR); gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, false); //lighting gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, this.lightAmbient); //uses built in java property gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, this.lightDiffuse); // and applies it gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION,this.lightPosition); //to the variables i set up at top of page gl.glEnable(GL.GL_LIGHT1); gl.glEnable(GL.GL_LIGHTING); this.light = true; } public void reshape(GLDrawable gLDrawable, int x, int y, int width, int height) { final GL gl = gLDrawable.getGL(); final GLU glu = gLDrawable.getGLU(); if (height <= 0) // avoid a divide by zero error! height = 1; final float h = (float)width / (float)height; gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective(45.0f, h, 1.0, 20.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glLoadIdentity(); } public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_L: this.light = !this.light; break; case KeyEvent.VK_F: this.filter += 1; if (filter > 2) filter = 0; break; case KeyEvent.VK_PAGE_UP: this.z -= 0.02f; break; case KeyEvent.VK_PAGE_DOWN: this.z += 0.02f; break; case KeyEvent.VK_UP: this.xspeed -= 0.01f; //increase speed, clockwise break; case KeyEvent.VK_DOWN: //increase speed, spin anit clockwise this.xspeed += 0.01f; break; case KeyEvent.VK_RIGHT: //increase speed, spin anit clockwise this.yspeed += 0.01f; break; case KeyEvent.VK_LEFT: //increase speed, clockwise this.yspeed -= 0.01f; break; case KeyEvent.VK_7: // move up this.x -= 0.02; break; case KeyEvent.VK_8: // move down this.x += 0.02; break; case KeyEvent.VK_9: // move left this.y -= 0.02; break; case KeyEvent.VK_0: // move right this.y += 0.02; break; case KeyEvent.VK_ESCAPE: animator.stop(); System.exit(0); break; } } public void keyReleased(KeyEvent e) {} // required method for Renderer public void keyTyped(KeyEvent e) {} //required method for Renderer private BufferedImage readPNGImage(String resourceName) { try { URL url = getResource(resourceName); if (url == null) { throw new RuntimeException("Error reading resource " + resourceName); } BufferedImage img = ImageIO.read(url); java.awt.geom.AffineTransform tx = java.awt.geom.AffineTransform.getScaleInstance(1, -1); tx.translate(0, -img.getHeight(null)); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); img = op.filter(img, null); return img; } catch (IOException e) { throw new RuntimeException(e); } } private void makeRGBTexture(GL gl, GLU glu, BufferedImage img, int target, boolean mipmapped) { ByteBuffer dest = null; switch (img.getType()) { case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_CUSTOM: { byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData(); dest = ByteBuffer.allocateDirect(data.length); dest.order(ByteOrder.nativeOrder()); dest.put(data, 0, data.length); break; } case BufferedImage.TYPE_INT_RGB: { int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); dest = ByteBuffer.allocateDirect(data.length * BufferUtils.SIZEOF_INT); dest.order(ByteOrder.nativeOrder()); dest.asIntBuffer().put(data, 0, data.length); break; } default: throw new RuntimeException("Unsupported image type " + img.getType()); } if (mipmapped) { glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest); } else { gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest); } } private int genTexture(GL gl) { final int[] tmp = new int[1]; gl.glGenTextures(1, tmp); return tmp[0]; } } public final static URL getResource(final String filename) { // Try to load resource from jar URL url = ClassLoader.getSystemResource(filename); // If not found in jar, then load from disk if (url == null) { try { url = new URL("file", "localhost", filename); } catch (Exception urlException){} // ignore } return url; } public static void main(String[] args) { Frame frame = new Frame("JOGL Kevin - Lesson 1 - 7"); GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); canvas.addGLEventListener(new Renderer()); frame.add(canvas); frame.setSize(640, 480); animator = new Animator(canvas); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { animator.stop(); System.exit(0); } }); frame.show(); animator.start(); canvas.requestFocus(); } }

Share this post


Link to post
Share on other sites
The reason why the light seems to be moving is because if you call glLightfv before setting up viewing transformations the light coordinates won't be transformed into eye space.

To make the light stationary you have to transform the light position and orientation by the viewing transformation matrix. To do this, call this function

gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION,this.lightPosition);

right after glTranslate, glRotate, etc.

EDIT: remember, OpenGL stores light coordinates and orientation in eye space, so it immediately transforms them by the current transformation matrix.

Share this post


Link to post
Share on other sites
Hiya thanks for the info, but it still doesnt seem to work, there doesnt seem to be a light at all now. it looks identical to a tutorial im following, i dont understand it.

anymore suggestions ?

Share this post


Link to post
Share on other sites
Never mind, you are not doing any camera transformations that would cause the light to move. I guess what is happening, if you rotate the cube, the light rotates with it? Try putting gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION,this.lightPosition) right after glLoadIdentity() and before glTranslate().

Share this post


Link to post
Share on other sites
Thank you very much for your help, but it doesnt seem to be working. Im loosing my mind over it, as im new to JOGL im finding it difficult to think of solutions. If you have any other suggestions feel free to reply. But i feel bad for taking up so much of your time.


Thanks Kevin

Share this post


Link to post
Share on other sites
DeathCrush is right about the gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION,this.lightPosition) function. glTranslate, glRotate and glScale affect the position. So in your case the light rotates with it.

But you did not see any light at all...

Think you forgot all about normals.
OpenGL calculates the intensity of the light on each object, and herefore it uses the normals of the polygons. I guess normals are (0, 0, 0) by default, so there is no lighting.

Try adding normals. (with length 1.0f)
Hope this helps...

Share this post


Link to post
Share on other sites
thankyou very much guys i added gl.glNormal3f(0.0f, 1.0f, 0.0f); to each side of the wuad and it now works, changing the values though, depending on the side. can u explain though in simple turns what this line of code does. As i am new to JOGL and 3D programming, thanks again. kevin

Share this post


Link to post
Share on other sites
A normal defines what direction is perpendicular to the face.
If a light shines perpendicular on a face, the reflection is higher.
So the intensity of the reflection can be calculated by dotProduct(faceNormal, lightDirection).

Why doesn't opengl calculate the normals?
if you have a sphere and you calculate the normals perpendicular to the faces you get this:


if you calculate the normals not perpendicular to the faces, but perpendicular to a perfect sphere you get this:
(In this case different points of the same face have different normals, but coincident points have the same normals)


Note that this is only how diffuse light works.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this