Světla

Nyní je krychle osvětlována zpředu bílým světlem. Klientská třída Lesson se opět nemění, rozdíly jsou pouze ve třídě Renderer. Klávesou L se zapíná a vypíná světlo.

Po spuštění níže uvedeného kódu uvidíte okno, jako je na obrázku.

Osvětlená krychle
Osvětlená krychle

Třída Renderer

Všechny metody, kromě níže uvedených, zůstávají shodné s metodami z kapitoly 4.4. Části kódu, které se nezměnily jsou napsány šedou barvou.

Při práci se světly je nutné nastavit ambientní světlo, které je všude a zdroj difúzního světla, u kterého je potřeba definovat i jeho polohu. Při inicializaci navíc zapneme jemné stínování, aby byla vyrenderovaná scéna opticky hezká. Nesmí se zapomenout dodefinovat ke každé ploše normálové vektory, aby OpenGL vědělo, jestli je daná plocha osvětlená a pokud ano, tak jakou intenzitou

Přidáme čtyři nové atributy, kde nastavíme barvu ambientního světla, barvu a polohu difúzního světla. Proměnná lightingEnabled slouží pro možnost zapínání a vypínání světla.

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, 5.0f, 1.0f};

private boolean lightingEnabled = true;

Důležité je správně nastavit normálové vektory ke všem plochám pomocí metody glNormal3f(), protože jinak bude světlo počítáno špatně. Normála je kolmý vektor na plochu, která má být osvícena. Kolmice vychází z té strany plochy, která má být osvětlena.

public void display(GLAutoDrawable gLDrawable)

{

gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

 

gl.glLoadIdentity();

 

gl.glTranslatef(0f, 0.0f, -5f);

gl.glRotatef(rotateX, 1.0f, 0.0f, 0.0f);

gl.glRotatef(rotateY, 0.0f, 1.0f, 0.0f);

gl.glRotatef(rotateZ, 0.0f, 0.0f, 1.0f);

 

if (lightingEnabled)

gl.glEnable(GL.GL_LIGHTING);

else

gl.glDisable(GL.GL_LIGHTING);

 

gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);

 

gl.glBegin(GL.GL_QUADS);

 

gl.glNormal3f(0.0f, 0.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);

gl.glTexCoord2f(0.0f, 1.0f);

gl.glVertex3f(-1.0f, 1.0f, 1.0f);

 

.

.

.

 

gl.glEnd();

 

rotateX += deltaX;

rotateY += deltaY;

rotateZ += deltaZ;

}

Metoda init() je téměř identická, pouze se nastavuje jemné stínování (GL_SMOOTH) metodou glShadeModel(), další možností stínování je GL_FLAT, které ovšem neinterpoluje hodnoty jasu z jednotlivých vrcholů; viz obrázek. Pak je nutné zavolat metodu setLights(), ve které se nastavují světla. Pokud je vyžadován drátěný model, doporučuji vypnout světla a textury. Pak použijeme v této metodě konstrukci gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE). Výsledek je vidět na obrázku.

Srovnání GL_SMOOTH a GL_FLAT stínování
Srovnání GL_SMOOTH a GL_FLAT stínování

Drátěný model
Drátěný model

Metoda nastavuje ambientní a difúzní světla, která pak zapne.

private void setLights()

{

gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, this.lightAmbient, 0);

gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, this.lightDiffuse, 0);

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

gl.glEnable(GL.GL_LIGHT1);

gl.glEnable(GL.GL_LIGHTING);

this.lightingEnabled = true;

}

Do metody keypressed() byla doplněna obsluha klávesy L.

public void keyPressed(KeyEvent e)

{

if (e.getKeyCode() == KeyEvent.VK_ESCAPE)

System.exit(0);

 

if (e.getKeyCode() == KeyEvent.VK_LEFT)

deltaX -= 0.05;

if (e.getKeyCode() == KeyEvent.VK_RIGHT)

deltaX += 0.05;

 

if (e.getKeyCode() == KeyEvent.VK_DOWN)

deltaY -= 0.05;

if (e.getKeyCode() == KeyEvent.VK_UP)

deltaY += 0.05;

 

if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN)

deltaZ -= 0.05;

if (e.getKeyCode() == KeyEvent.VK_PAGE_UP)

deltaZ += 0.05;

 

if (e.getKeyCode() == KeyEvent.VK_L)

lightingEnabled = !lightingEnabled;

}