/* * Copyright 2016 MovingBlocks * * 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 org.terasology.rendering.backdrop; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.Sphere; import org.terasology.context.Context; import org.terasology.utilities.Assets; import org.terasology.math.TeraMath; import org.terasology.math.geom.Vector3f; import org.terasology.rendering.assets.material.Material; import org.terasology.rendering.cameras.Camera; import org.terasology.rendering.nui.properties.Range; import org.terasology.world.sun.CelestialSystem; import static org.lwjgl.opengl.GL11.GL_BACK; import static org.lwjgl.opengl.GL11.GL_FRONT; import static org.lwjgl.opengl.GL11.glCallList; import static org.lwjgl.opengl.GL11.glCullFace; import static org.lwjgl.opengl.GL11.glDepthMask; import static org.lwjgl.opengl.GL11.glEndList; import static org.lwjgl.opengl.GL11.glGenLists; import static org.lwjgl.opengl.GL11.glNewList; /** * Skysphere based on the Perez all weather luminance model. */ public class Skysphere implements BackdropProvider, BackdropRenderer { private static int displayListSphere = -1; @Range(min = 0.01f, max = 100.0f) private float colorExp = 0.01f; @Range(min = 2.0f, max = 32.0f) private float turbidity = 9.0f; private final CelestialSystem celSystem; public Skysphere(Context context) { celSystem = context.get(CelestialSystem.class); } @Override public void render(Camera camera) { glDepthMask(false); if (camera.isReflected()) { glCullFace(GL_BACK); } else { glCullFace(GL_FRONT); } Material shader = Assets.getMaterial("engine:prog.sky").get(); shader.enable(); // Draw the skysphere drawSkysphere(camera.getzFar()); if (camera.isReflected()) { glCullFace(GL_FRONT); } else { glCullFace(GL_BACK); } glDepthMask(true); } private void drawSkysphere(float zFar) { if (displayListSphere == -1) { displayListSphere = glGenLists(1); Sphere sphere = new Sphere(); sphere.setTextureFlag(true); glNewList(displayListSphere, GL11.GL_COMPILE); float skyBoxDistance = (zFar > 1024 ? 1024.0f : zFar * 0.95f); sphere.draw(skyBoxDistance, 16, 128); glEndList(); } glCallList(displayListSphere); } @Override public float getSunPositionAngle() { return celSystem.getSunPosAngle(); } @Override public float getDaylight() { float angle = (float) Math.toDegrees(TeraMath.clamp(Math.cos(getSunPositionAngle()))); float daylight = 1.0f; if (angle < 24.0f) { daylight = 1.0f - (24.0f - angle) / 24.0f; } return daylight; } @Override public float getTurbidity() { return turbidity; } @Override public float getColorExp() { return colorExp; } @Override public Vector3f getSunDirection(boolean moonlightFlip) { float sunAngle = getSunPositionAngle() + 0.0001f; Vector3f sunDirection = new Vector3f(0.0f, (float) Math.cos(sunAngle), (float) Math.sin(sunAngle)); // Moonlight flip if (moonlightFlip && sunDirection.y < 0.0f) { sunDirection.scale(-1.0f); } return sunDirection; } }