Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package engine.rendering.lighting;
- import static org.lwjgl.opengl.GL11.*;
- import static org.lwjgl.opengl.GL15.*;
- import static org.lwjgl.opengl.GL20.*;
- import static org.lwjgl.opengl.GL30.*;
- import static org.lwjgl.opengl.GL32.GL_DEPTH_CLAMP;
- import java.io.File;
- import java.nio.FloatBuffer;
- import java.nio.ShortBuffer;
- import java.util.ArrayList;
- import org.lwjgl.BufferUtils;
- import org.lwjgl.util.vector.Matrix3f;
- import org.lwjgl.util.vector.Matrix4f;
- import org.lwjgl.util.vector.Quaternion;
- import org.lwjgl.util.vector.Vector3f;
- import org.lwjgl.util.vector.Vector4f;
- import engine.rendering.etc.FastArrayList;
- import engine.rendering.gl.culling.FrustumCuller;
- import engine.rendering.gl.shader.Shader;
- import engine.rendering.gl.shader.ShaderProgram;
- import engine.rendering.gl.view.RenderView;
- import engine.rendering.gl.view.ShadowView;
- import engine.rendering.gl.view.View;
- import engine.rendering.lighting.shadow.Rectangle;
- import engine.rendering.lighting.shadow.RectanglePacker;
- import engine.rendering.lighting.shadow.ShadowSystem;
- import engine.rendering.rt.RenderTargets;
- import engine.rendering.util.MatrixUtils;
- import engine.rendering.util.QuatUtils;
- import engine.rendering.util.ScalarUtils;
- import engine.rendering.util.TextureUtils;
- public class ConeLightRenderer {
- private static final float SHADOW_NEAR_PLANE = 0.125f;
- private RenderTargets renderTargets;
- private ShadowSystem shadowSystem;
- private int vbo, ibo;
- private int numIndices;
- private UnshadowedShader unshadowedShader;
- private ShadowedShader shadowedShader;
- private FloatBuffer matrixBuffer;
- private int unshadowedVAO, shadowedVAO;
- private Matrix3f tempMatrix;
- private FastArrayList<ConeLightImpl> lights0, lights1;
- private FastArrayList<ConeLightImpl> unshadowedLights;
- private FastArrayList<ConeLightImpl> shadowedLights;
- private RectanglePacker<ConeLightImpl> shadowMapPacker;
- public ConeLightRenderer(RenderTargets renderTargets, ShadowSystem shadowSystem, String shaderPath, int subdivisions) {
- this.renderTargets = renderTargets;
- this.shadowSystem = shadowSystem;
- generateCone(subdivisions);
- initShaders(shaderPath + "lighting/cone/");
- tempMatrix = new Matrix3f();
- lights0 = new FastArrayList<>();
- lights1 = new FastArrayList<>();
- unshadowedLights = new FastArrayList<>();
- shadowedLights = new FastArrayList<>();
- shadowMapPacker = new RectanglePacker<>(shadowSystem.getWidth(), shadowSystem.getHeight());
- }
- private void generateCone(int subdivisions) {
- ConeGenerator coneGenerator = new ConeGenerator();
- coneGenerator.create(subdivisions);
- vbo = glGenBuffers();
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- Vector3f[] positionData = coneGenerator.getPositions();
- FloatBuffer positionBuffer = BufferUtils.createFloatBuffer(positionData.length * 3);
- for(int i = 0; i < positionData.length; i++){
- Vector3f p = positionData[i];
- positionBuffer.put(p.x).put(p.y).put(p.z);
- }
- positionBuffer.flip();
- glBufferData(GL_ARRAY_BUFFER, positionBuffer, GL_STATIC_DRAW);
- ibo = glGenBuffers();
- glBindBuffer(GL_ARRAY_BUFFER, ibo);
- short[] indexData = coneGenerator.getIndices();
- ShortBuffer indexBuffer = BufferUtils.createShortBuffer(indexData.length);
- indexBuffer.put(indexData).flip();
- glBufferData(GL_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);
- numIndices = indexData.length;
- }
- private void initShaders(String shaderPath) {
- unshadowedShader = new UnshadowedShader(shaderPath);
- shadowedShader = new ShadowedShader(shaderPath, shadowSystem.getShadowSampleShader());
- matrixBuffer = BufferUtils.createFloatBuffer(16);
- unshadowedVAO = unshadowedShader.createVAO();
- shadowedVAO = shadowedShader.createVAO();
- }
- public ConeLight newLight(){
- ConeLightImpl l = new ConeLightImpl();
- lights0.add(l);
- return l;
- }
- public void clear() {
- lights0.clear();
- }
- public void cull(RenderView cameraView, ArrayList<View> result){
- MatrixUtils.extract(cameraView.getViewMatrix(), tempMatrix);
- FrustumCuller culler = cameraView.getCuller();
- Matrix4f viewMatrix = cameraView.getViewMatrix();
- int minResolution = shadowSystem.getMinShadowResolution();
- int maxResolution = shadowSystem.getMaxPointLightResolution();
- unshadowedLights.clear();
- shadowedLights.clear();
- for(int i = 0; i < lights0.size(); i++){
- ConeLightImpl cl = lights0.get(i);
- if(cl.disposed){
- continue;
- }
- lights1.add(cl);
- float intensity = cl.intensity;
- Vector4f position = cl.position;
- if(intensity > 0 && culler.sphereVisible(position, intensity)){
- cl.update(viewMatrix, tempMatrix);
- if(!cl.shadowsEnabled){
- unshadowedLights.add(cl);
- }else{
- cl.updateShadowResolution(minResolution, maxResolution);
- cl.updateShadowMatrix(cameraView);
- result.add(cl.view);
- shadowedLights.add(cl);
- }
- }
- }
- lights0.clear();
- FastArrayList<ConeLightImpl> temp = lights0;
- lights0 = lights1;
- lights1 = temp;
- }
- public void packShadowMaps(){
- shadowMapPacker.pack(shadowedLights);
- }
- public void renderUnshadowedLights(RenderView view){
- unshadowedShader.bind();
- glUniform2f(unshadowedShader.screenSizeLocation, 1f/renderTargets.getWidth(), 1f/renderTargets.getHeight());
- uploadMatrix4(view.getViewProjectionMatrix(), unshadowedShader.viewProjectionMatrixLocation);
- uploadMatrix4(view.getInverseProjectionMatrix(), unshadowedShader.inverseProjectionMatrixLocation);
- glEnable(GL_STENCIL_TEST);
- glBindVertexArray(unshadowedVAO);
- for(int j = 0; j < unshadowedLights.size(); j++){
- ConeLightImpl l = unshadowedLights.get(j);
- uploadMatrix4(l.objectMatrix, unshadowedShader.objectMatrixLocation);
- Vector4f p = l.eyeSpacePosition;
- glUniform3f(unshadowedShader.lightEyePositionLocation, p.x, p.y, p.z);
- Vector3f d = l.eyeSpaceDirection;
- glUniform3f(unshadowedShader.lightEyeDirectionLocation, d.x, d.y, d.z);
- glUniform3f(unshadowedShader.lightColorLocation, l.r, l.g, l.b);
- glUniform1f(unshadowedShader.lightIntensityLocation, l.intensity);
- glUniform1f(unshadowedShader.cosineCutoffLocation, l.cosineCutoff);
- glUniform1f(unshadowedShader.edgeDimmingLocation, l.edgeDimming);
- glCullFace(GL_BACK);
- glStencilFunc(GL_ALWAYS, 0, 0xFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
- glColorMask(false, false, false, false);
- glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
- glCullFace(GL_FRONT);
- glStencilFunc(GL_EQUAL, 0, 0xFF);
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
- glColorMask(true, true, true, true);
- glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
- }
- glDisable(GL_STENCIL_TEST);
- }
- public void renderShadowedLights(RenderView cameraView) {
- shadowedShader.bind();
- glUniform2f(shadowedShader.screenSizeLocation, 1f/renderTargets.getWidth(), 1f/renderTargets.getHeight());
- uploadMatrix4(cameraView.getViewProjectionMatrix(), shadowedShader.viewProjectionMatrixLocation);
- uploadMatrix4(cameraView.getInverseProjectionMatrix(), shadowedShader.inverseProjectionMatrixLocation);
- shadowMapPacker.pack(shadowedLights);
- int passes = shadowMapPacker.getNumPasses();
- for(int i = 0; i < passes; i++){
- FastArrayList<ConeLightImpl> lights = shadowMapPacker.getPass(i);
- int numLights = lights.size();
- shadowSystem.startShadowMapRendering(numLights);
- for(int j = 0; j < numLights; j++){
- ConeLightImpl l = lights.get(j);
- shadowSystem.renderShadowMap(l.x, l.y, l.requestedResolution, l.shadowBias, l.shadowSlopeBias, l.view);
- }
- shadowSystem.prefilter();
- renderTargets.bindAccumulationPassFBO();
- shadowedShader.bind();
- TextureUtils.setActiveUnit(0);
- renderTargets.getGBuffer0().bind();
- TextureUtils.setActiveUnit(1);
- renderTargets.getGBuffer1().bind();
- TextureUtils.setActiveUnit(2);
- renderTargets.getDepthBuffer().bind();
- shadowSystem.bindShadowMaps(3);
- TextureUtils.setActiveUnit(0);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_GREATER);
- glEnable(GL_DEPTH_CLAMP);
- glDepthMask(false);
- glBindVertexArray(shadowedVAO);
- for(int j = 0; j < numLights; j++){
- ConeLightImpl l = lights.get(j);
- uploadMatrix4(l.objectMatrix, shadowedShader.objectMatrixLocation);
- uploadMatrix4(l.inverseViewLightMatrix, shadowedShader.inverseViewLightMatrixLocation);
- glUniform2f(shadowedShader.shadowOffsetLocation, (float)l.x / shadowSystem.getWidth(), (float)l.y / shadowSystem.getHeight());
- glUniform2f(shadowedShader.shadowResolutionLocation, (float)l.requestedResolution / shadowSystem.getWidth(), (float)l.requestedResolution / shadowSystem.getHeight());
- Vector4f p = l.eyeSpacePosition;
- glUniform3f(shadowedShader.lightEyePositionLocation, p.x, p.y, p.z);
- Vector3f d = l.eyeSpaceDirection;
- glUniform3f(shadowedShader.lightEyeDirectionLocation, d.x, d.y, d.z);
- glUniform3f(shadowedShader.lightColorLocation, l.r, l.g, l.b);
- glUniform1f(shadowedShader.lightIntensityLocation, l.intensity);
- glUniform1f(shadowedShader.cosineCutoffLocation, l.cosineCutoff);
- glUniform1f(shadowedShader.edgeDimmingLocation, l.edgeDimming);
- glCullFace(GL_BACK);
- glStencilFunc(GL_ALWAYS, 0, 0xFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
- glColorMask(false, false, false, false);
- glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
- glCullFace(GL_FRONT);
- glStencilFunc(GL_EQUAL, 0, 0xFF);
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
- glColorMask(true, true, true, true);
- glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
- }
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_BLEND);
- glDisable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glDisable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glDepthMask(true);
- glDisable(GL_DEPTH_CLAMP);
- }
- shadowMapPacker.clear();
- }
- private void uploadMatrix4(Matrix4f matrix, int uniform) {
- matrix.store(matrixBuffer);
- matrixBuffer.flip();
- glUniformMatrix4(uniform, false, matrixBuffer);
- }
- public void setRenderTargets(RenderTargets renderTargets){
- this.renderTargets = renderTargets;
- }
- private class ConeLightImpl extends ConeLight implements Rectangle{
- private Vector3f normalizedDirection;
- private Matrix4f objectMatrix;
- private Vector4f eyeSpacePosition;
- private Vector3f eyeSpaceDirection;
- private float cosineCutoff;
- private boolean shadowsEnabled;
- private Vector3f up, target;
- private Matrix4f viewMatrix, projectionMatrix;
- private ShadowView view;
- private Matrix4f inverseViewLightMatrix;
- //Shadow map packing values
- private int requestedResolution;
- private int x, y;
- private boolean disposed;
- public ConeLightImpl() {
- normalizedDirection = new Vector3f();
- objectMatrix = new Matrix4f();
- eyeSpacePosition = new Vector4f();
- eyeSpaceDirection = new Vector3f();
- shadowsEnabled = false;
- disposed = false;
- }
- @Override
- public void dispose() {
- disposed = true;
- }
- @Override
- public boolean areShadowsEnabled() {
- return this.shadowsEnabled;
- }
- @Override
- public void setShadowsEnabled(boolean shadowsEnabled) {
- if(shadowsEnabled && viewMatrix == null){
- target = new Vector3f();
- up = new Vector3f();
- viewMatrix = new Matrix4f();
- projectionMatrix = new Matrix4f();
- view = new ShadowView(viewMatrix, projectionMatrix, true);
- inverseViewLightMatrix = new Matrix4f();
- }
- this.shadowsEnabled = shadowsEnabled;
- }
- public void update(Matrix4f viewMatrix, Matrix3f rotationMatrix){
- cosineCutoff = (float)Math.cos(Math.toRadians(fov*0.5f));
- normalizedDirection.set(direction).normalise();
- Vector3f f = new Vector3f(0, 0, 1);
- Vector3f v = new Vector3f();
- Vector3f.cross(f, normalizedDirection, v);
- float angle = (float)Math.acos(Vector3f.dot(f, normalizedDirection));
- Quaternion tempQuat = new Quaternion();
- QuatUtils.setFromAxis(tempQuat, v.x, v.y, v.z, angle);
- MatrixUtils.createMatrix(objectMatrix, tempQuat, position);
- //objectMatrix.setToRotation(new Vector3(0, 0, 1), normalizedDirection).setTranslation(position);
- Matrix4f.transform(viewMatrix, position, eyeSpacePosition);
- Matrix3f.transform(rotationMatrix, normalizedDirection, eyeSpaceDirection);
- }
- public void updateShadowResolution(int min, int max){
- float distance = Math.max(0, eyeSpacePosition.length() - intensity);
- requestedResolution = (int)ScalarUtils.clamp(renderTargets.getHeight() * intensity * shadowSystem.getResolutionMultiplier() / (cosineCutoff * distance), min, max);
- }
- public void updateShadowMatrix(RenderView cameraView){
- target.set(
- position.x + normalizedDirection.x,
- position.y + normalizedDirection.y,
- position.z + normalizedDirection.z
- );
- up.set(0, 1, 0);
- if(normalizedDirection.x == 0 && normalizedDirection.z == 0){
- up.set(0, 0, 1); //Ensure up is not equal to direction
- }
- MatrixUtils.createLookAtMatrix(viewMatrix, new Vector3f(position), target, up);
- MatrixUtils.createPerspectiveMatrix(projectionMatrix, fov, 1, SHADOW_NEAR_PLANE, intensity);
- view.update(position.x, position.y, position.z, SHADOW_NEAR_PLANE, intensity);
- //inverseViewLightMatrix.set(projectionMatrix).mul(viewMatrix).mul(cameraView.getInverseViewMatrix());
- Matrix4f.mul(projectionMatrix, viewMatrix, inverseViewLightMatrix);
- Matrix4f.mul(inverseViewLightMatrix, cameraView.getInverseViewMatrix(), inverseViewLightMatrix);
- }
- @Override
- public int getWidth() {
- return requestedResolution;
- }
- @Override
- public int getHeight() {
- return requestedResolution;
- }
- @Override
- public void setOffset(int x, int y) {
- this.x = x;
- this.y = y;
- }
- }
- private abstract class ConeLightShader extends ShaderProgram{
- protected int screenSizeLocation;
- protected int viewProjectionMatrixLocation;
- protected int objectMatrixLocation;
- protected int inverseProjectionMatrixLocation;
- protected int lightEyePositionLocation;
- protected int lightEyeDirectionLocation;
- protected int lightIntensityLocation;
- protected int lightColorLocation;
- protected int cosineCutoffLocation;
- protected int edgeDimmingLocation;
- protected int positionLocation;
- public ConeLightShader(String shaderPath, Shader... shaders) {
- attachShader(new Shader(Shader.VERTEX_SHADER, new File(shaderPath + "light.vert")));
- attachShader(new Shader(Shader.FRAGMENT_SHADER, new File(shaderPath + "light.frag")));
- bindFragDataLocation(0, "light");
- for(int i = 0; i < shaders.length; i++){
- attachShader(shaders[i]);
- }
- link();
- bind();
- glUniform1i(getUniformLocation("gBuffer0"), 0);
- glUniform1i(getUniformLocation("gBuffer1"), 1);
- glUniform1i(getUniformLocation("depthBuffer"), 2);
- screenSizeLocation = getUniformLocation("screenSize");
- viewProjectionMatrixLocation = getUniformLocation("viewProjectionMatrix");
- objectMatrixLocation = getUniformLocation("objectMatrix");
- inverseProjectionMatrixLocation = getUniformLocation("inverseProjectionMatrix");
- lightEyePositionLocation = getUniformLocation("lightEyePosition");
- lightEyeDirectionLocation = getUniformLocation("lightEyeDirection");
- lightIntensityLocation = getUniformLocation("lightIntensity");
- lightColorLocation = getUniformLocation("lightColor");
- cosineCutoffLocation = getUniformLocation("cosineCutoff");
- edgeDimmingLocation = getUniformLocation("edgeDimming");
- positionLocation = getAttribLocation("position");
- }
- public int createVAO(){
- int vao = glGenVertexArrays();
- glBindVertexArray(vao);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glEnableVertexAttribArray(positionLocation);
- glVertexAttribPointer(positionLocation, 3, GL_FLOAT, false, 0, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
- glBindVertexArray(0);
- return vao;
- }
- }
- private class UnshadowedShader extends ConeLightShader{
- public UnshadowedShader(String shaderPath) {
- super(shaderPath, new Shader(Shader.FRAGMENT_SHADER, new File(shaderPath + "no shadows.frag")));
- }
- }
- private class ShadowedShader extends ConeLightShader{
- private int inverseViewLightMatrixLocation;
- private int shadowOffsetLocation;
- private int shadowResolutionLocation;
- public ShadowedShader(String shaderPath, Shader shadowSampleShader) {
- super(shaderPath, new Shader(Shader.FRAGMENT_SHADER, new File(shaderPath + "shadows.frag")), shadowSampleShader);
- shadowSystem.uploadUniforms(this, 3);
- inverseViewLightMatrixLocation = getUniformLocation("inverseViewLightMatrix");
- shadowOffsetLocation = getUniformLocation("shadowOffset");
- shadowResolutionLocation = getUniformLocation("shadowResolution");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement