-1

enter image description here

I want to create two objects with different light position. But the light position of second object (Gold sphere) is always the same as the first object (Silver sphere) even I have set different position parameter.

I have enable both light one after another object. But the second one is always the same as the first/above one.

    // light from top right
    GLfloat light_position_top_right[] = { 1.0, 1.0, 1.0, 0.0 };
    // light from bottom left
    GLfloat light_position_bottom_left[] = { -1.0, -1.0, 1.0, 0.0 };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLightfv(GL_LIGHT0, GL_POSITION, light_position_top_right);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position_bottom_left);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glEnable(GL_DEPTH_TEST);

You can find complete code in this gist.

I expect the second object to have light position from bottom left. But it shows from top right as the first object.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Pirun Seng
  • 443
  • 1
  • 4
  • 20

2 Answers2

1

The fourth coordinate of your light positions must be 1.0 instead of 0.0, otherwise due to how projective transformations work the lights will behave as if they are infinitely far away in the specified direction.

With a fourth coordinate of 0.0:

Lights are infinitely far away

With a fourth coordinate of 1.0:

Lights are properly located

As for why there are two highlights instead of just one, you forgot to set the proper glLight* settings for your lights. By default, GL_LIGHT0 begins with white diffuse and specular color, but all other lights have black diffuse and specular color by default.


EDIT:

If you want separate spheres to use separate lights, you'll need to initialize the lights during init(). But instead of glEnableing the lights right then, do the following:

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(1.0, 0.0, -1.0);
    glEnable(GL_LIGHT0);
    drawGraySphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT0);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-0.75, -0.8, 0.0);
    glEnable(GL_LIGHT1);
    drawGoldSphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT1);
    glPopMatrix();

    glFlush();
}

Alternatively, you have the option to just use a single light, and change its parameters using glLight* each frame, before rendering each sphere. This is the better option if you plan on having a bunch of objects, each with their own light.

Magma
  • 566
  • 2
  • 8
  • Sorry, but not so clear. `GLfloat light_position_top_right[] = { 1.0, 1.0, 1.0, 1.0 };` and `GLfloat light_position_bottom_left[] = { -1.0, -1.0, 1.0, 1.0 };` I've updated the fourth coordinate, but the result is not as expected. – Pirun Seng Aug 12 '19 at 01:57
  • I've just updated my gist by adding my expectation. – Pirun Seng Aug 12 '19 at 02:03
  • Ah, you want to use GL_LIGHT0 for the first object and GL_LIGHT1 for the second object? In that case you need to use `glEnable(GL_LIGHT*)` and `glDisable(GL_LIGHT*)` between both objects properly. Don't worry, you don't need to set the light parameters again after reenabling them. – Magma Aug 12 '19 at 08:24
  • Alternatively, you could just reuse `GL_LIGHT0` all the time and always set the parameters as necessary between objects. – Magma Aug 12 '19 at 08:24
  • Yes, my first object is GL_LIGHT0, and second object is GL_LIGHT1. However, I try enable and disable light as this, but no luck. It has no light at all. `glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDisable(GL_LIGHT0);glEnable(GL_LIGHT1);glDisable(GL_LIGHT1);glEnable(GL_DEPTH_TEST);` – Pirun Seng Aug 12 '19 at 09:29
  • Interesting, but could you provide a complete code with the functions please? Because I'm still having issue for the light, and I'm not clear which should I keep/remove from the `init()` function. – Pirun Seng Aug 12 '19 at 10:24
0

Here's your code, modified to do what you want it to do:

#include<windows.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void drawGoldSphere() {
    GLfloat mat_specular[] = { 0.628281, 0.555802, 0.366065, 1.0 };
    GLfloat mat_shininess[] = { 51.2 };
    GLfloat mat_ambient[] = { 0.24725, 0.1995, 0.0745, 1.0 };
    GLfloat mat_diffuse[] = { 0.75164, 0.60648, 0.22648, 1.0 };
    //Material Properties
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

void drawGraySphere() {
    GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

void init(void)
{
    // light from middle left
    //GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
    // light from top right
    GLfloat light_position_top_right[] = { 1.0, 1.0, 1.0, 0.0 };
    // light from bottom left
    GLfloat light_position_bottom_left[] = { -1.0, -1.0, 1.0, 0.0 };
    // light from bottom left
    //GLfloat light_position[] = { -0.1, -0.1, -0.1, 0.0 };
    // light from middle top
    //GLfloat light_position[] = { 0.0, 1.0, 0.0, 0.0 };
    // light from middle right
    //GLfloat light_position[] = { 1.0, 0.0, 0.0, 0.0 };
    // light from middle middle
    //GLfloat light_position[] = { 0.0, 0.0, 1.0, 0.0 };
    // light from middle bottom
    //GLfloat light_position[] = { 0.0, -1.0, 1.0, 0.0 };


    GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat high_shininess[] = { 100.0 };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position_top_right);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position_bottom_left);

    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(1.0, 0.0, -1.0);
    glEnable(GL_LIGHT0);
    drawGraySphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT0);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-0.75, -0.8, 0.0);
    glEnable(GL_LIGHT1);
    drawGoldSphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT1);
    glPopMatrix();

    glFlush();
}
void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
    glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
    1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
    else
    glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
    1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

Render result:

enter image description here

Magma
  • 566
  • 2
  • 8