Java tutorial
/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.graphics.g3d.lights; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; public class LightManager { public enum LightQuality { VERTEX, FRAGMENT }; public LightQuality quality; final public Array<PointLight> pointLights = new Array<PointLight>(false, 16); final private float[] positions; final private float[] colors; final private float[] intensities; public final int maxLightsPerModel; final public Color ambientLight = new Color(); /** Only one for optimizing - at least at now */ public DirectionalLight dirLight; public LightManager() { this(4, LightQuality.VERTEX); } public LightManager(int maxLightsPerModel, LightQuality lightQuality) { quality = lightQuality; this.maxLightsPerModel = maxLightsPerModel; colors = new float[3 * maxLightsPerModel]; positions = new float[3 * maxLightsPerModel]; intensities = new float[maxLightsPerModel]; } public void addLigth(PointLight light) { pointLights.add(light); } public void clear() { pointLights.clear(); } public void calculateAndApplyLightsToModel(Vector3 center, ShaderProgram shader) { this.calculateLights(center.x, center.y, center.z); this.applyLights(shader); } // TODO make it better if it slow // NAIVE but simple implementation of light choosing algorithm // currently calculate lights based on transformed center position of model // TODO one idea would be first cull lights that can't affect the scene with // frustum check. // TODO another idea would be first cut lights that are further from model // than x that would make sorted faster public void calculateLights(float x, float y, float z) { final int maxSize = pointLights.size; // solve what are lights that influence most if (maxSize > maxLightsPerModel) { for (int i = 0; i < maxSize; i++) { final PointLight light = pointLights.get(i); light.priority = (int) (PointLight.PRIORITY_DISCRETE_STEPS * (light.intensity / light.position.dst(x, y, z))); // if just linear fallof } pointLights.sort(); } // fill the light arrays final int size = maxLightsPerModel > maxSize ? maxSize : maxLightsPerModel; for (int i = 0; i < size; i++) { final PointLight light = pointLights.get(i); final Vector3 pos = light.position; positions[3 * i + 0] = pos.x; positions[3 * i + 1] = pos.y; positions[3 * i + 2] = pos.z; final Color col = light.color; colors[3 * i + 0] = col.r; colors[3 * i + 1] = col.g; colors[3 * i + 2] = col.b; intensities[i] = light.intensity; } // TODO might not be needed for (int i = size; i < maxLightsPerModel; i++) { intensities[i] = 0; } } /** Apply lights GLES1.0, call calculateLights before aplying */ public void applyLights() { } /** Apply lights GLES2.0, call calculateLights before aplying */ public void applyLights(ShaderProgram shader) { shader.setUniform3fv("lightsPos", positions, 0, maxLightsPerModel * 3); shader.setUniform3fv("lightsCol", colors, 0, maxLightsPerModel * 3); shader.setUniform1fv("lightsInt", intensities, 0, maxLightsPerModel); } public void applyGlobalLights() { // TODO fix me } public void applyGlobalLights(ShaderProgram shader) { shader.setUniformf("ambient", ambientLight.r, ambientLight.g, ambientLight.b); if (dirLight != null) { final Vector3 v = dirLight.direction; final Color c = dirLight.color; shader.setUniformf("dirLightDir", v.x, v.y, v.z); shader.setUniformf("dirLightCol", c.r, c.g, c.b); } } }