Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Статьи
        Освещение
            SpotLight and Shadow

SpotLight and Shadow

Опубликованно: 22.08.2015, 22:15
Последняя редакция, AdiDOS: 07.05.2017 9:19

В интернете я наткнулся на неплохую 3D модель уличного фонаря и решил написать эту  статью , SpotLight(Пятно света) — этот источник света я  охарактеризовал так , рассеянный направленный источник света имеющий форму конуса.

Я думаю можно перейти к коду.

package test;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.light.AmbientLight;
import com.jme3.light.PointLight;
import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.shadow.EdgeFilteringMode;
import com.jme3.shadow.SpotLightShadowRenderer;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;

public class TestSpotLightShadow extends SimpleApplication {

 public static void main(String[] args) {
   new TestSpotLightShadow().start();

 }

 @Override
 public void simpleInitApp() {
   flyCam.setMoveSpeed(20);

   createScene();
   createSpotShadowLight();
   createAmbienLight();
   createPointLight();

 }
 //Создание сцены
 private void createScene(){
   Material matGrass = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
   Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg");
   grass.setWrap(WrapMode.Repeat);
   matGrass.setTexture("DiffuseMap", grass);

   Box box1 = new Box(20, 1, 20);
   Geometry geomBox1 = new Geometry("box1", box1); 

   geomBox1.setMaterial(matGrass);
   rootNode.attachChild(geomBox1);
   assetManager.registerLocator("E:/Models/StreetLight/", FileLocator.class);
   Spatial streetlamp = assetManager.loadModel("streetlamp.obj"); 

   streetlamp.setLocalTranslation(0, 15, 0);
   rootNode.attachChild(streetlamp);

   Material matPond = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
   matPond.getTextureParam("DiffuseMap").getTextureValue().setWrap(WrapMode.Repeat);
   matPond.getTextureParam("NormalMap").getTextureValue().setWrap(WrapMode.Repeat);
   matPond.setBoolean("UseMaterialColors", true);
   matPond.setColor("Diffuse", ColorRGBA.White.clone());
   matPond.setColor("Ambient", ColorRGBA.White.clone());
   matPond.setFloat("Shininess", 0);

   Box box2 = new Box(1, 1, 1);
   Geometry geomBox2 = new Geometry("box2", box2);
   geomBox2.setLocalTranslation(2, 5, 0);

   geomBox2.setMaterial(matPond);
   rootNode.attachChild(geomBox2);

 }

 // Создание источника света Spot Light
 private void createSpotShadowLight() {
   SpotLight spot = new SpotLight();
   spot.setSpotRange(100f); // Дистанция
   spot.setSpotInnerAngle(15f * FastMath.DEG_TO_RAD); // Начальный радиус
   spot.setSpotOuterAngle(50f * FastMath.DEG_TO_RAD); // Конечный радиус
   spot.setColor(ColorRGBA.White.mult(2.3f)); // Цвет
   spot.setPosition(new Vector3f(0.4f, 14.5f, 0)); // Позиция
   spot.setDirection(new Vector3f(0, -5, 0)); // Направление
   rootNode.addLight(spot);

   rootNode.setShadowMode(ShadowMode.CastAndReceive);// Включаем отражения
   SpotLightShadowRenderer slsr = new SpotLightShadowRenderer(assetManager, 512);
   slsr.setLight(spot); // Установка освещения
   slsr.setShadowIntensity(0.6f); // Интенсивность отражения
   slsr.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON);// Режим фильтрации тени

   viewPort.addProcessor(slsr);

 }

 // Создание точечного света
 private void createPointLight() {
   PointLight pointLight = new PointLight();
   pointLight.setColor(ColorRGBA.Yellow);
   pointLight.setRadius(4f);
   pointLight.setPosition(new Vector3f(0.8f, 14.0f, 0));
   rootNode.addLight(pointLight);
 }

 // Рассеянный свет
 private void createAmbienLight() {
   AmbientLight al = new AmbientLight();
   al.setColor(ColorRGBA.White.mult(0.72f));
   rootNode.addLight(al);
 }
}

SpotLight  очень хорошо использовать в таких вещах как фонари прожекторы ну и так далее ,в этом коде я привел пример освещения уличного фонаря  а так же тени.

1

3

2

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

В классе  SpotLight по сравнению с другими источниками света он имеет больше настроек что на мое мнение придает ему огромные преимущества в использовании,  ну а теперь перейдем к описании создания данного источника света и тени.

Эта функция установки дистанции освещения (в пикселях) , то есть если установленное значение будет меньше от отражаемого объекта то вы там ничего не увидите.

spot.setSpotRange(100f);

Начальный радиус источника света

spot.setSpotInnerAngle(15f * FastMath.DEG_TO_RAD);

Конечный радиус источника света

spot.setSpotOuterAngle(50f * FastMath.DEG_TO_RAD);

Цвет  источника света где входящий параметр функции mult(2.3f) говорит об интенсивности освещения

spot.setColor(ColorRGBA.White.mult(2.3f));

Начальная позиция

spot.setPosition(new Vector3f(0.4f, 14.5f, 0));

Функция указывает направление

spot.setDirection(new Vector3f(0, -5, 0));

Ну а теперь функции создание теней.

Класс SpotLightShadowRenderer(assetManager, 512) он предназначен для прорисовки теней assetManager нужен ему для загрузки шейдеров , а второй параметр нужен для создания карты теней он может быть размером кратно (512,1024,2048 и тд) , а простыми словами чем больше число тем детальней будет прорисовка теней.

Функция говорит что в данном узле нужно разрешить отражения

rootNode.setShadowMode(ShadowMode.CastAndReceive);

Установка нашего источника света

slsr.setLight(spot);

Функция интенсивности освещения, чем больше параметр тем ярче освещение

slsr.setShadowIntensity(0.6f);

Функция установка сглаживания теней

slsr.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON);

Добавление процессора для пост обработки теней ну короче без этого работать не будет

viewPort.addProcessor(slsr);

Ну наверно все что я хотел дополнить  не завышайте размер  карты теней так как на вашей видео карте оно может работать нормально а на другой более слабой очень снизится fps , да и модель фонаря вы можете скачать по ссылке .

Спасибо за внимание!!

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.