JREGC

Главная | Регистрация | Вход Приветствую Вас Инопланетяне | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: wawe  
Форум » PROGRAMMING CATEGORY » Уроки LWJGL » LWJGL, Освещение
LWJGL, Освещение
waweДата: Понедельник, 14.01.2013, 14:23 | Сообщение # 1
Просто человек...
Группа: Администраторы
Сообщений: 50
Награды: 3
Статус: Offline
В openGL 3D объекты без освещения выглядят как простые двумерные фигуры.
По умолчанию освещение отключено, включается оно с помощью команды GL11.glEnable(GL11.GL_LIGHTING);
В OpenGL может быть и больше восьми источников света, но зачем нам столько?
Если вы хотите сделать много источников, то лучше всего использовать LightMap
этот способ не забирает много ресурсов и используется он чаще, но про это поговорим позже.
Вы здесь, чтобы узнать, как работает оригинальное OpenGL освещение.
Весь наш мир отражает, поглощает, рассеивает и т.д.
OpenGL рассчитывает свет и освещение так, как будто свет может быть разделен на красный, зеленый и синий компоненты.
Если вам требуется более точная (или просто другая) модель освещения, реализовывать ее вам нужно самостоятельно.
Для этого вам нужно очень хорошо знать физику освещения. Можете почитать разные книги.

Фоновое излучение – это свет, который настолько распределен средой (предметами, стенами и так далее), что его направление определить невозможно – кажется, что он исходит отовсюду. Лампа дневного света имеет большой фоновый компонент, поскольку большая часть света, достигающего вашего глаза, сначала отражается от множества поверхностей. Уличный фонарь имеет маленький фоновый компонент: большая часть его света идет в одном направлении, кроме того, поскольку он находится на улице, очень небольшая часть света попадает вам в глаз после того, как отразится от других объектов. Когда фоновый свет падает на поверхность, он одинаково распределяется во всех направлениях.

Диффузный компонент – это свет, идущий из одного направления, таким образом, он выглядит ярче, если падает на поверхность под прямым углом, и выглядит тусклым, если касается ее всего лишь вскользь. Однако, когда он падает на поверхность, он распределяется одинаково во всех направлениях, то есть его яркость одинакова вне зависимости от того, с какой стороны вы смотрите на поверхность. Вероятно, любой свет, исходящий из определенного направления или позиции, имеет диффузный компонент.

Зеркальный свет исходит из определенного направления и отражается от поверхности в определенном направлении. При отражении хорошо сфокусированного лазерного луча от качественного зеркала происходит почти 100 процентное зеркальное отражение. Блестящий метал или пластик имеет высокий зеркальный компонент, а кусок ковра или плюшевая игрушка – нет. Вы можете думать о зеркальности как о том, насколько блестящим выглядит материал.

Помимо фонового, диффузного и зеркального цветов, материалы могут также иметь исходящий цвет, имитирующий свет, исходящий от самого объекта. В модели освещения OpenGLисходящий свет поверхности добавляет объекту интенсивности, но на него не влияют никакие источники света, и он не производит дополнительного света для сцены в целом.

Хотя источник света излучает единое распределение частот, фоновый, диффузный и зеркальный компоненты могут быть различны. Например, если в вашей комнате красные стены и белый свет, то этот свет, отражаясь от стен будет скорее красным, чем белым (несмотря на то, что падающий на стену свет -- белый). OpenGL позволяет устанавливать значения красного, зеленого и синего независимо для каждого компонента света.

Для работоспособности вашего освещения, вам нужно задать нормали к объектам.

Нормали объекта задают его ориентацию относительно источников света. OpenGLиспользует нормаль вершины для определения того, как много света эта вершина получает от каждого источника. В приведенном примере процесс определения нормалей происходит внутри функции glutSolidSphere().

Для правильного освещения нормали поверхности должны иметь единичную длину. Вы должны быть осторожны и помнить, что матрица модельного преобразования не масштабирует вектора нормалей автоматически, и результирующие нормали могут уже не иметь единичную длину. Чтобы убедиться, что нормали имеют единичную длину, возможно, вам придется вызвать команду glEnable() с аргументами GL_NORMALIZE или GL_RESCALE_NORMAL.

GL_RESCALE_NORMALведет к тому, что каждый компонент вектора нормали к поверхности будет умножен на одно и то же число, извлеченное из матрицы модельных преобразований. Таким образом, операция работает корректно только в случае, если нормали масштабировались равномерно и изначально имели единичную длину.

GL_NORMALIZE– более сложная операция, чем GL_RESCALE_NORMAL. Когда активизирован механизм нормализации (GL_NORMALIZE), сначала вычисляется длина вектора нормали, а затем каждый из компонентов вектора делится на это число. Эта операция гарантирует, что результирующие нормали будут иметь единичную длину, но она может быть более затратной в смысле скорости, чем простое масштабирование нормалей.

Теперь вы знаете базовые знания по освещению
Код

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Sphere;
import org.lwjgl.util.vector.Vector3f;

public class Main {
       
    // вектора в трех направлениях
    Vector3f vector = new Vector3f();
    Vector3f rotation = new Vector3f();

    public Main() {
     // TODO Auto-generated constructor stub
    }
       
    // загрузка важных методов
    public void load() {
     displayApp();
     GL3D();
     running();
    }
       
    // обновление камеры
    private void updateCamera() {
     inputCamera(speedCamera * Timer.getDt());
    }
       
    // позиция камеры
    private void rotationCamera() {
     // вращение
     GL11.glRotatef(rotation.x, 1.0f, 0.0f, 0.0f);
     GL11.glRotatef(rotation.y, 0.0f, 1.0f, 0.0f);
     GL11.glRotatef(rotation.z, 0.0f, 0.0f, 1.0f);
     // позиция
     GL11.glTranslatef(-vector.x, -vector.y, -vector.z);
    }
       
    // управление камерой
    private void inputCamera(float distance) {
     if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
      vector.x += distance * (float) Math.sin(rotation.y * Math.PI / 180);
      vector.z += -distance * (float) Math.cos(rotation.y * Math.PI / 180);
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
      vector.x -= distance * (float) Math.sin(rotation.y * Math.PI / 180);
      vector.z -= -distance * (float) Math.cos(rotation.y * Math.PI / 180);
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
      vector.x += distance * (float) Math.sin((rotation.y - 90) * Math.PI / 180);
      vector.z += -distance * (float) Math.cos((rotation.y - 90) * Math.PI / 180);
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
      vector.x += distance * (float) Math.sin((rotation.y + 90) * Math.PI / 180);
      vector.z += -distance * (float) Math.cos((rotation.y + 90) * Math.PI / 180);
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
      vector.y += distance;
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
      vector.y -= distance;
     }
     if (Keyboard.isKeyDown(Keyboard.KEY_L)) {
      light_position = new float[] { vector.x, vector.y, vector.z, 1.0f };
      System.out.println(light_position[0] + " " + light_position[1] + " " + light_position[2]);
     }
     // обновление
     mouseUpdate();
    }
       
    // управление мышкой
    private void mouseUpdate() {
     if (Mouse.isGrabbed()) {
      float mouseDX = Mouse.getDX() * 0.8f * 0.16f;
      float mouseDY = Mouse.getDY() * 0.8f * 0.16f;
      if (rotation.y + mouseDX >= 360) {
       rotation.y = rotation.y + mouseDX - 360;
      } else if (rotation.y + mouseDX < 0) {
       rotation.y = 360 - rotation.y + mouseDX;
      } else {
       rotation.y += mouseDX;
      }
      if (rotation.x - mouseDY >= -89 && rotation.x - mouseDY <= 89) {
       rotation.x += -mouseDY;
      } else if (rotation.x - mouseDY < -89) {
       rotation.x = -89;
      } else if (rotation.x - mouseDY > 89) {
       rotation.x = 89;
      }
     }
    }
       
    // создание окна
    private void displayApp() {
     try {
      Display.setDisplayMode(new DisplayMode(800, 600));
      Display.setTitle("JregcTutorialLighting");
      Display.create();
     } catch (LWJGLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      exit(true);
     }
    }
       
    // настройка графики
    private void GL3D() {
     GL11.glMatrixMode(GL11.GL_PROJECTION);
     GL11.glLoadIdentity();
     GLU.gluPerspective(50.0f, 800.0f / 600.0f, 1.0f, 9600.0f);
     GL11.glMatrixMode(GL11.GL_MODELVIEW);
     GL11.glLoadIdentity();
     GL11.glShadeModel(GL11.GL_SMOOTH);
     GL11.glClearDepth(1.0);
     GL11.glEnable(GL11.GL_DEPTH_TEST);
     GL11.glDepthFunc(GL11.GL_LEQUAL);
     GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
     // включение нормализации
     GL11.glEnable(GL11.GL_NORMALIZE);
     // включение цвета материала
     GL11.glEnable(GL11.GL_COLOR_MATERIAL);
     // включение первого источника света, можно включить и больше GL11.glEnable(GL_LIGHT1);
     GL11.glEnable(GL11.GL_LIGHT0);
     // включение освещения
     GL11.glEnable(GL11.GL_LIGHTING);
     GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(light_ambient).flip());
    }
       
    // главный цикл программы
    private void running() {
     Timer.setLastFPS(Timer.getTime());
     Mouse.setGrabbed(true);
     while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
      render();
     }
     exit(false);
    }
       
    // шар
    Sphere sphere = new Sphere();
       
    ByteBuffer temp = ByteBuffer.allocateDirect(16).order(ByteOrder.nativeOrder());
       
    // рендер сцены
    private void render() {
     GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
     GL11.glLoadIdentity();
     // установка позиции камеры
     rotationCamera();
     // установка материала
     GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_DIFFUSE, (FloatBuffer) temp.asFloatBuffer().put(mat_diffuse).flip());
     GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_SPECULAR, (FloatBuffer) temp.asFloatBuffer().put(mat_specular).flip());
     GL11.glMaterialf(GL11.GL_FRONT_AND_BACK, GL11.GL_SHININESS, 50.0f);
     // отключение освещения
     GL11.glDisable(GL11.GL_LIGHT0);
     GL11.glDisable(GL11.GL_LIGHTING);
     //  меньший шар - источник освещения
     GL11.glColor3f(1.0f, 1.0f, 1.0f);
     GL11.glPushMatrix();
     GL11.glTranslatef(light_position[0], light_position[1], light_position[2]);
     sphere.draw(1.0f, 20, 20);
     GL11.glPopMatrix();
     // включение освещения
     GL11.glEnable(GL11.GL_LIGHT0);
     GL11.glEnable(GL11.GL_LIGHTING);
     // установка источника освещения
     GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, (FloatBuffer) temp.asFloatBuffer().put(light_position).flip());
     // рисование большого шара
     GL11.glPushMatrix();
     sphere.draw(10.0f, 50, 50);
     GL11.glPopMatrix();
     // рисование пирамиды
     GL11.glPushMatrix();
     GL11.glTranslatef(20.0f, 2.0f, 0.0f);
     GL11.glBegin(GL11.GL_TRIANGLES);
     // создание нормали стороны пирамиды
     GL11.glNormal3f(0.0f, 0.0f, 1.0f);
     GL11.glVertex3f(0.0f, 10.0f, 0.0f);                  // Верх треугольника (Передняя)
     GL11.glVertex3f(-10.0f,-10.0f, 10.0f);                  // Левая точка
     GL11.glVertex3f(10.0f,-10.0f, 10.0f);                  // Правая точка
        
     GL11.glNormal3f(1.0f, 0.0f, 0.0f);
     GL11.glVertex3f( 0.0f, 10.0f, 0.0f);                  // Верх треугольника (Правая)
     GL11.glVertex3f( 10.0f,-10.0f, 10.0f);                  // Лево треугольника (Правая)
     GL11.glVertex3f( 10.0f,-10.0f, -10.0f);                 // Право треугольника (Правая)
        
     GL11.glNormal3f(0.0f, 0.0f, -1.0f);
     GL11.glVertex3f( 0.0f, 10.0f, 0.0f);                  // Низ треугольника (Сзади)
     GL11.glVertex3f( 10.0f,-10.0f, -10.0f);                 // Лево треугольника (Сзади)
     GL11.glVertex3f(-10.0f,-10.0f, -10.0f);                 // Право треугольника (Сзади)
        
     GL11.glNormal3f(-1.0f, 0.0f, 0.0f);
     GL11.glVertex3f( 0.0f, 10.0f, 0.0f);                  // Верх треугольника (Лево)
     GL11.glVertex3f(-10.0f,-10.0f,-10.0f);                  // Лево треугольника (Лево)
     GL11.glVertex3f(-10.0f,-10.0f, 10.0f);                  // Право треугольника (Лево)
     GL11.glEnd();
     GL11.glPopMatrix();
     // обновление таймера
     Timer.syncUpdateApp();
     Timer.updateFPS();
     // обновление камеры
     updateCamera();
     // обновление окна
     Display.update();
     // максимальный фпс - 120
     Display.sync(120);
    }
       
    // разрушение приложения и освобождение ресурсов
    private void exit(boolean asCrash) {
     Display.destroy();
     System.exit(asCrash ? 1 : 0);
    }

    // инитиализация
    public static void main(String[] args) {
     new Main().load();
    }
       
    // скорость камеры
    private float speedCamera = 20.0f;
    // позиция источника света
    private float light_position[] = {31.84215f, 36.019997f, 28.262873f, 1.0f};
    // цвет фонового света
    private float light_ambient[] = { 0.0f, 0.0f, 0.3f, 1.0f };
    // настройка материалов
    private float mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    private float mat_diffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f };
}
 
Форум » PROGRAMMING CATEGORY » Уроки LWJGL » LWJGL, Освещение
  • Страница 1 из 1
  • 1
Поиск:

Copyright MyCorp © 2024
Используются технологии uCoz