Java tutorial
/* * Veya * Copyright (C) 2015 s1mpl3x * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package eu.over9000.veya.rendering; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.*; import org.lwjgl.util.vector.Matrix4f; import org.lwjgl.util.vector.Vector3f; import eu.over9000.veya.Veya; import eu.over9000.veya.util.MatrixUtil; /** * Created by Jan on 22.07.2015. */ public class Shadow { public static final int SHADOW_WIDTH = 1024; public static final int SHADOW_HEIGHT = 1024; public static final float SHADOW_RANGE = 256f; public static final float SHADOW_NEAR = 200f; public static final float SHADOW_FAR = 600f; private int shadowFBO; private int depthMap; public void init() { depthMap = GL11.glGenTextures(); GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthMap); GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, (ByteBuffer) null); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER); shadowFBO = GL30.glGenFramebuffers(); GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, shadowFBO); GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthMap, 0); GL11.glDrawBuffer(GL11.GL_NONE); GL11.glReadBuffer(GL11.GL_NONE); GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0); } private void updateMatrixLightSpaceMatrixLocation() { final FloatBuffer matrixBufferShadow = BufferUtils.createFloatBuffer(16); final FloatBuffer matrixBufferNormal = BufferUtils.createFloatBuffer(16); final Matrix4f lightProjection = MatrixUtil.orthographic(-SHADOW_RANGE, +SHADOW_RANGE, -SHADOW_RANGE, +SHADOW_RANGE, SHADOW_NEAR, SHADOW_FAR); //final Matrix4f lightProjection = MatrixUtil.perspectiveRH(140, SHADOW_WIDTH, SHADOW_HEIGHT, SHADOW_NEAR, SHADOW_FAR); final Matrix4f lightView = MatrixUtil.lookAtCenter(Veya.scene.getLight().getPosition(), new Vector3f(0, 0, 0)); final Matrix4f lightSpaceMatrix = Matrix4f.mul(lightProjection, lightView, null); lightSpaceMatrix.store(matrixBufferShadow); lightSpaceMatrix.store(matrixBufferNormal); matrixBufferShadow.flip(); matrixBufferNormal.flip(); Veya.program_shadow.use(true); GL20.glUniformMatrix4(Veya.program_shadow.getUniformLocation("lightSpaceMatrix"), false, matrixBufferShadow); Veya.program_normal.use(true); GL20.glUniformMatrix4(Veya.program_normal.getUniformLocation("lightSpaceMatrix"), false, matrixBufferNormal); Veya.program_shadow.use(true); } public void preRender() { Veya.program_shadow.use(true); updateMatrixLightSpaceMatrixLocation(); GL11.glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, shadowFBO); GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); GL11.glCullFace(GL11.GL_FRONT); } public void postRender() { GL11.glCullFace(GL11.GL_BACK); // don't forget to reset original culling face GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0); Veya.program_normal.use(true); GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight()); GL13.glActiveTexture(GL13.GL_TEXTURE1); GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthMap); } int quadVAO = 0; int quadVBO; public void renderQuad() { if (quadVAO == 0) { final float[] quadVertices = { // Positions // Texture Coords -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, }; // Setup plane VAO final FloatBuffer fb = BufferUtils.createFloatBuffer(quadVertices.length); fb.put(quadVertices); fb.flip(); quadVAO = GL30.glGenVertexArrays(); quadVBO = GL15.glGenBuffers(); GL30.glBindVertexArray(quadVAO); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, quadVBO); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, fb, GL15.GL_STATIC_DRAW); GL20.glEnableVertexAttribArray(0); GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 5 * Float.BYTES, 0); GL20.glEnableVertexAttribArray(1); GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 5 * Float.BYTES, 3 * Float.BYTES); } GL30.glBindVertexArray(quadVAO); GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4); GL30.glBindVertexArray(0); } public int getDepthMap() { return depthMap; } }