package projectzombie.display; import static org.lwjgl.opengl.GL11.GL_FLOAT; import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; import static org.lwjgl.opengl.GL20.glVertexAttribPointer; import java.nio.IntBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.glfw.GLFW; import org.lwjgl.opengl.GL33; import gl_engine.graphics.GraphicsHelpers; import gl_engine.graphics.GraphicsShader; import mainloop.task.IMainloopTask; import projectzombie.Main; import projectzombie.init.Resources; import projectzombie.input.CursorEnterCallback; import projectzombie.input.CursorPosCallback; import projectzombie.input.JoystickCallback; import projectzombie.input.KeyCallback; import projectzombie.input.KeyCharCallback; import projectzombie.input.MouseButtonCallback; import projectzombie.input.ScrollWheelCallback; import projectzombie.mainloop.MainloopEventHandler; import projectzombie.menu.MenuSettings; import projectzombie.settings.Settings; public class DisplayWindow implements IMainloopTask { public static boolean fullscreen = true; private long window; private long monitor; private int width; private int height; private boolean mouseVisibility_last = false; public int texture_max_size; public static int fps = 0; public GraphicsShader environmentRenderer; public GraphicsShader effectRenderer; public int effect_vao; public int glsl_mist; public int glsl_color; public int glsl_contrast; public int glsl_discard_coords; public int glsl_model; public int glsl_camera; public int glsl_projection; public int glsl_projection_sun; public int glsl_rotated; public int glsl_billboard; public int glsl_mode; public int glsl_time; public int glsl_day_low; public int glsl_day_high; public int glsl_lightmap_offset; public int glsl_lightmap_size; public int glsl_effect_time; public int glsl_effect_red; public int glsl_effect_vortex; public int glsl_effect_vsnow; public int glsl_effect_red_freq; public int glsl_effect_chill; public int getWidth() { return this.width; } public int getHeight() { return this.height; } void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } public void init() { // Initialize GLFW if(!GLFW.glfwInit()) { throw new RuntimeException("Failed to initialize GLFW"); } // Get the monitor size IntBuffer w = BufferUtils.createIntBuffer(1); IntBuffer h = BufferUtils.createIntBuffer(1); monitor = GLFW.glfwGetPrimaryMonitor(); GLFW.glfwGetMonitorPhysicalSize(monitor, w, h); width = w.get()*4; height = h.get()*4; //GLFW.glfwWindowHint(GLFW.GLFW_DOUBLEBUFFER, GLFW.GLFW_FALSE); // Create the window window = GraphicsHelpers.initWindow("Project Zombie", width, height, fullscreen ? monitor : 0); // Make the context current GLFW.glfwMakeContextCurrent(this.window); // Set the key handlers GLFW.glfwSetCursorPosCallback(this.window, new CursorPosCallback()); GLFW.glfwSetCharCallback(this.window, new KeyCharCallback()); GLFW.glfwSetCursorEnterCallback(this.window, new CursorEnterCallback()); GLFW.glfwSetMouseButtonCallback(this.window, new MouseButtonCallback()); GLFW.glfwSetKeyCallback(this.window, new KeyCallback()); GLFW.glfwSetJoystickCallback(JoystickCallback.JOYSTICK_CALLBACK); GLFW.glfwSetScrollCallback(this.window, new ScrollWheelCallback()); // Make the cursor invisible GLFW.glfwSetInputMode(this.window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN); GLFW.glfwSwapInterval(0); // Show the window //GLFW.glfwShowWindow(this.window); environmentRenderer = new GraphicsShader("/resources/shader/environmentRenderer"); environmentRenderer.use(); glsl_mist = GL33.glGetUniformLocation(environmentRenderer.program, "mist"); glsl_model = GL33.glGetUniformLocation(environmentRenderer.program, "model"); glsl_camera = GL33.glGetUniformLocation(environmentRenderer.program, "camera"); glsl_rotated = GL33.glGetUniformLocation(environmentRenderer.program, "rotated"); glsl_projection = GL33.glGetUniformLocation(environmentRenderer.program, "projection"); glsl_projection_sun = GL33.glGetUniformLocation(environmentRenderer.program, "projection_sun"); glsl_time = GL33.glGetUniformLocation(environmentRenderer.program, "time"); glsl_discard_coords = GL33.glGetUniformLocation(environmentRenderer.program, "discard_coords"); glsl_color = GL33.glGetUniformLocation(environmentRenderer.program, "color"); glsl_contrast = GL33.glGetUniformLocation(environmentRenderer.program, "contrast"); glsl_billboard = GL33.glGetUniformLocation(environmentRenderer.program, "billboard"); glsl_mode = GL33.glGetUniformLocation(environmentRenderer.program, "mode"); glsl_day_low = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_day_low"); glsl_day_high = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_day_high"); glsl_lightmap_offset = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap_offset"); glsl_lightmap_size = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap_size"); int glsl_atlas = GL33.glGetUniformLocation(environmentRenderer.program, "atlas"); int glsl_lightmap = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap"); int glsl_depthmap = GL33.glGetUniformLocation(environmentRenderer.program, "depthmap"); GL33.glUniform1i(glsl_atlas, 0); GL33.glUniform1i(glsl_lightmap, 1); GL33.glUniform1i(glsl_depthmap, 2); effectRenderer = new GraphicsShader("/resources/shader/effectRenderer"); effectRenderer.use(); glsl_effect_time = GL33.glGetUniformLocation(effectRenderer.program, "time"); glsl_effect_red = GL33.glGetUniformLocation(effectRenderer.program, "red"); glsl_effect_vsnow = GL33.glGetUniformLocation(effectRenderer.program, "vsnow"); glsl_effect_vortex = GL33.glGetUniformLocation(effectRenderer.program, "vortex"); glsl_effect_red_freq = GL33.glGetUniformLocation(effectRenderer.program, "red_freq"); glsl_effect_chill = GL33.glGetUniformLocation(effectRenderer.program, "chill"); //GL33.glUniform1i(GL33.glGetUniformLocation(effectRenderer.program, "shadowMap"), 2); effect_vao = GL33.glGenVertexArrays(); GL33.glBindVertexArray(effect_vao); int effect_vbo = GL33.glGenBuffers(); GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, effect_vbo); GL33.glBufferData(GL33.GL_ARRAY_BUFFER, new float[] { -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, }, GL33.GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, false, Float.BYTES * 2, 0); glEnableVertexAttribArray(0); int[] ptr = new int[1]; GL33.glGetIntegerv(GL33.GL_MAX_TEXTURE_SIZE, ptr); texture_max_size = ptr[0]; System.out.println("Max texture size: " + texture_max_size); DisplayRender.init(); } public void render() { // Set the framebuffer size int w[] = {0}; int h[] = {0}; GLFW.glfwGetFramebufferSize(this.window, w, h); width = w[0]; height = h[0]; environmentRenderer.use(); DisplayLighting.updateLighting(); GL33.glUniform1f(glsl_mist, 0); if(Main.player.getHydration() < 0.2) { GL33.glUniform1f(glsl_contrast, (float)(0.2 - Main.player.getHydration()) * 1.6f); } else { GL33.glUniform1f(glsl_contrast, 0); } // Bind the texture atlas GL33.glActiveTexture(GL33.GL_TEXTURE0); Resources.ATLAS.bind(); // Bind the lightmap GL33.glActiveTexture(GL33.GL_TEXTURE1); GL33.glBindTexture(GL33.GL_TEXTURE_2D, DisplayLighting.lightmap); // Bind the shadow depth map GL33.glActiveTexture(GL33.GL_TEXTURE2); GL33.glBindTexture(GL33.GL_TEXTURE_2D, DisplayRender.shadow_depth); // Render everything DisplayRender.render(w[0], h[0]); // Use the effect shader effectRenderer.use(); // Bind the shadow depth map GL33.glActiveTexture(GL33.GL_TEXTURE0); GL33.glBindTexture(GL33.GL_TEXTURE_2D, DisplayRender.shadow_depth); // Send extra data to the shader if(!Main.player.dead && Main.menu.doGameloop) { GL33.glUniform1i(glsl_effect_time, (int)System.currentTimeMillis()); } if(Main.player.getHydration() < 0.2) { GL33.glUniform1f(glsl_effect_vsnow, (float)(0.2 - Main.player.getHydration())); GL33.glUniform1f(glsl_effect_vortex, (float)(0.2 - Main.player.getHydration()) / 10); } else { GL33.glUniform1f(glsl_effect_vsnow, 0); GL33.glUniform1f(glsl_effect_vortex, 0); } double player_health = Main.player.getHealth() / Main.player.maxHealth(); if(player_health < 0.25) { GL33.glUniform1f(glsl_effect_red, (float)Math.min(2 * (0.25 - player_health), 0.5)); GL33.glUniform1i(glsl_effect_red_freq, 20); } else { GL33.glUniform1f(glsl_effect_red, 0); } if(Main.player.getTemperature() < 0.3) { GL33.glUniform1f(glsl_effect_chill, (float)(0.3 - Main.player.getTemperature()) / 3 * 10); } else { GL33.glUniform1f(glsl_effect_chill, 0); } // Draw a quad to the whole screen for the effects GL33.glBindVertexArray(effect_vao); GL33.glDrawArrays(GL33.GL_TRIANGLES, 0, 6); // Swap the framebuffers and poll events GLFW.glfwSwapBuffers(window); GLFW.glfwPollEvents(); fps += 1; } public void toggleFullscreen() { // Exit fullscreen if the window is in fullscreen if(fullscreen) { fullscreen = false; GLFW.glfwSetWindowMonitor(window, 0, 1, 1, width, height, GLFW.GLFW_DONT_CARE); } // Enter fullscreen if the window is windowed else { // Get the monitor size IntBuffer w = BufferUtils.createIntBuffer(1); IntBuffer h = BufferUtils.createIntBuffer(1); GLFW.glfwGetMonitorPhysicalSize(monitor, w, h); width = w.get()*4; height = h.get()*4; // Enter fullscreen mode fullscreen = true; GLFW.glfwSetWindowMonitor(window, monitor, 0, 0, width, height, GLFW.GLFW_DONT_CARE); } // Update the settings file Settings.update(); if(Main.menu instanceof MenuSettings) { ((MenuSettings) Main.menu).buttonFullscreen.setText( "Fullscreen: " + (fullscreen ? "On" : "Off")); } } public void setMouseVisibility(boolean status) { if(status != mouseVisibility_last) { mouseVisibility_last = status; if(status) { GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); } else { GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN); } } } public boolean shouldClose() { return GLFW.glfwWindowShouldClose(window); } public void makeContextCurrent() { GLFW.glfwMakeContextCurrent(window); } @Override public boolean MainLoopDelay(long millis) { return millis > MainloopEventHandler.MAINLOOP_EVENT_HANDLER.mspf; } @Override public boolean MainLoopRepeat() { return true; } @Override public void MainLoopUpdate() { this.render(); } public void setTitle(String string) { GLFW.glfwSetWindowTitle(window, string); } }