implement sun
@@ -5,8 +5,8 @@ window.IngameOverlay = class extends Gui {
|
|||||||
this.minecraft = minecraft;
|
this.minecraft = minecraft;
|
||||||
this.window = window;
|
this.window = window;
|
||||||
|
|
||||||
this.textureCrosshair = Gui.loadTexture("icons.png");
|
this.textureCrosshair = Gui.loadTexture("gui/icons.png");
|
||||||
this.textureHotbar = Gui.loadTexture("gui.png");
|
this.textureHotbar = Gui.loadTexture("gui/gui.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
render(stack, mouseX, mouseY, partialTicks) {
|
render(stack, mouseX, mouseY, partialTicks) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ window.GuiLoadingScreen = class extends GuiScreen {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.textureBackground = Gui.loadTexture("background.png");
|
this.textureBackground = Gui.loadTexture("gui/background.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
drawScreen(stack, mouseX, mouseY, partialTicks) {
|
||||||
@@ -50,4 +50,8 @@ window.GuiLoadingScreen = class extends GuiScreen {
|
|||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyTyped(key) {
|
||||||
|
// Cancel key inputs
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
window.GuiButton = class extends Gui {
|
window.GuiButton = class extends Gui {
|
||||||
|
|
||||||
static textureGui = Gui.loadTexture("gui.png");
|
static textureGui = Gui.loadTexture("gui/gui.png");
|
||||||
|
|
||||||
constructor(string, x, y, width, height, callback) {
|
constructor(string, x, y, width, height, callback) {
|
||||||
super();
|
super();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ window.BlockRenderer = class {
|
|||||||
constructor(worldRenderer) {
|
constructor(worldRenderer) {
|
||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
this.tessellator = new Tessellator();
|
this.tessellator = new Tessellator();
|
||||||
this.tessellator.bindTexture(worldRenderer.terrainTexture);
|
this.tessellator.bindTexture(worldRenderer.textureTerrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBlock(world, block, x, y, z) {
|
renderBlock(world, block, x, y, z) {
|
||||||
|
|||||||
@@ -7,10 +7,15 @@ window.WorldRenderer = class {
|
|||||||
this.window = window;
|
this.window = window;
|
||||||
this.chunkSectionUpdateQueue = [];
|
this.chunkSectionUpdateQueue = [];
|
||||||
|
|
||||||
// Load terrain
|
// Load terrain texture
|
||||||
this.terrainTexture = new THREE.TextureLoader().load('src/resources/terrain.png');
|
this.textureTerrain = new THREE.TextureLoader().load('src/resources/terrain/terrain.png');
|
||||||
this.terrainTexture.magFilter = THREE.NearestFilter;
|
this.textureTerrain.magFilter = THREE.NearestFilter;
|
||||||
this.terrainTexture.minFilter = THREE.NearestFilter;
|
this.textureTerrain.minFilter = THREE.NearestFilter;
|
||||||
|
|
||||||
|
// Load sun texture
|
||||||
|
this.textureSun = new THREE.TextureLoader().load('src/resources/terrain/sun.png');
|
||||||
|
this.textureSun.magFilter = THREE.NearestFilter;
|
||||||
|
this.textureSun.minFilter = THREE.NearestFilter;
|
||||||
|
|
||||||
// Block Renderer
|
// Block Renderer
|
||||||
this.blockRenderer = new BlockRenderer(this);
|
this.blockRenderer = new BlockRenderer(this);
|
||||||
@@ -34,7 +39,8 @@ window.WorldRenderer = class {
|
|||||||
// Create web renderer
|
// Create web renderer
|
||||||
this.webRenderer = new THREE.WebGLRenderer({
|
this.webRenderer = new THREE.WebGLRenderer({
|
||||||
canvas: this.window.canvas,
|
canvas: this.window.canvas,
|
||||||
antialias: false
|
antialias: false,
|
||||||
|
alpha: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
@@ -45,6 +51,8 @@ window.WorldRenderer = class {
|
|||||||
this.webRenderer.sortObjects = false;
|
this.webRenderer.sortObjects = false;
|
||||||
this.webRenderer.setClearColor(0x000000, 0);
|
this.webRenderer.setClearColor(0x000000, 0);
|
||||||
this.webRenderer.clear();
|
this.webRenderer.clear();
|
||||||
|
|
||||||
|
this.generateSky();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(partialTicks) {
|
render(partialTicks) {
|
||||||
@@ -57,7 +65,10 @@ window.WorldRenderer = class {
|
|||||||
let cameraChunkZ = Math.floor(player.z >> 4);
|
let cameraChunkZ = Math.floor(player.z >> 4);
|
||||||
this.renderChunks(cameraChunkX, cameraChunkZ);
|
this.renderChunks(cameraChunkX, cameraChunkZ);
|
||||||
|
|
||||||
// Render actual scene and hud
|
// Render sky
|
||||||
|
this.renderSky(partialTicks);
|
||||||
|
|
||||||
|
// Render actual scene
|
||||||
this.webRenderer.render(this.scene, this.camera);
|
this.webRenderer.render(this.scene, this.camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,10 +93,10 @@ window.WorldRenderer = class {
|
|||||||
this.camera.updateProjectionMatrix();
|
this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
// Setup fog
|
// Setup fog
|
||||||
this.setupFog(player.isHeadInWater());
|
this.setupFog(x, z, player.isHeadInWater(), partialTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupFog(inWater) {
|
setupFog(x, z, inWater, partialTicks) {
|
||||||
if (inWater) {
|
if (inWater) {
|
||||||
let color = new THREE.Color(0.2, 0.2, 0.4);
|
let color = new THREE.Color(0.2, 0.2, 0.4);
|
||||||
this.scene.background = color;
|
this.scene.background = color;
|
||||||
@@ -93,8 +104,12 @@ window.WorldRenderer = class {
|
|||||||
} else {
|
} else {
|
||||||
let viewDistance = WorldRenderer.RENDER_DISTANCE * ChunkSection.SIZE;
|
let viewDistance = WorldRenderer.RENDER_DISTANCE * ChunkSection.SIZE;
|
||||||
|
|
||||||
let color = new THREE.Color(0x9299ff);
|
let color = this.minecraft.world.getSkyColor(x, z, partialTicks);
|
||||||
this.scene.background = color;
|
this.scene.background = new THREE.Color(
|
||||||
|
((color >> 16) & 0xFF) / 255,
|
||||||
|
((color >> 8) & 0xFF) / 255,
|
||||||
|
(color & 0xFF) / 255
|
||||||
|
);
|
||||||
this.scene.fog = new THREE.Fog(color, 0.0025, viewDistance);
|
this.scene.fog = new THREE.Fog(color, 0.0025, viewDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,4 +180,35 @@ window.WorldRenderer = class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateSky() {
|
||||||
|
// Create sky group
|
||||||
|
this.skyGroup = new THREE.Scene();
|
||||||
|
this.scene.add(this.skyGroup);
|
||||||
|
|
||||||
|
// Create sun
|
||||||
|
let geometry = new THREE.PlaneGeometry(1, 1);
|
||||||
|
let material = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0xffff00,
|
||||||
|
side: THREE.FrontSide,
|
||||||
|
map: this.textureSun,
|
||||||
|
alphaMap: this.textureSun,
|
||||||
|
blending: THREE.AdditiveBlending,
|
||||||
|
transparent: true
|
||||||
|
});
|
||||||
|
this.sun = new THREE.Mesh(geometry, material);
|
||||||
|
this.sun.translateZ(-2);
|
||||||
|
this.sun.renderOrder = 999;
|
||||||
|
this.sun.material.depthTest = false;
|
||||||
|
this.skyGroup.add(this.sun);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSky(partialTicks) {
|
||||||
|
// Center sky
|
||||||
|
this.skyGroup.position.copy(this.camera.position);
|
||||||
|
|
||||||
|
// Rotate sky
|
||||||
|
let angle = this.minecraft.world.getCelestialAngle(partialTicks);
|
||||||
|
this.skyGroup.rotation.set(angle * Math.PI * 2 + Math.PI / 2, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ window.FontRenderer = class {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.charWidths = [];
|
this.charWidths = [];
|
||||||
|
|
||||||
this.texture = Gui.loadTexture("font.png")
|
this.texture = Gui.loadTexture("gui/font.png")
|
||||||
|
|
||||||
let bitMap = this.createBitMap(this.texture);
|
let bitMap = this.createBitMap(this.texture);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ window.World = class {
|
|||||||
this.chunks = new Map();
|
this.chunks = new Map();
|
||||||
this.lightUpdateQueue = [];
|
this.lightUpdateQueue = [];
|
||||||
|
|
||||||
|
this.time = 0;
|
||||||
|
|
||||||
// Load world
|
// Load world
|
||||||
this.generator = new WorldGenerator(this, Date.now() % 100000);
|
this.generator = new WorldGenerator(this, Date.now() % 100000);
|
||||||
|
|
||||||
@@ -36,6 +38,9 @@ window.World = class {
|
|||||||
let distance2 = Math.floor(Math.pow(b.chunkX - cameraChunkX, 2) + Math.pow(b.chunkZ - cameraChunkZ, 2));
|
let distance2 = Math.floor(Math.pow(b.chunkX - cameraChunkX, 2) + Math.pow(b.chunkZ - cameraChunkZ, 2));
|
||||||
return distance2 - distance1;
|
return distance2 - distance1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update world time
|
||||||
|
this.time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChunkAt(x, z) {
|
getChunkAt(x, z) {
|
||||||
@@ -133,7 +138,9 @@ window.World = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add light update region to queue
|
// Add light update region to queue
|
||||||
this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2));
|
if (this.lightUpdateQueue.length < 10000) {
|
||||||
|
this.lightUpdateQueue.push(new MetadataChunkBlock(sourceType, x1, y1, z1, x2, y2, z2));
|
||||||
|
}
|
||||||
|
|
||||||
// Max light updates in queue
|
// Max light updates in queue
|
||||||
if (this.lightUpdateQueue.length > 100000) {
|
if (this.lightUpdateQueue.length > 100000) {
|
||||||
@@ -414,7 +421,49 @@ window.World = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return lastHit;
|
return lastHit;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCelestialAngle(partialTicks) {
|
||||||
|
return MathHelper.calculateCelestialAngle(this.time, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTemperature(x, z) {
|
||||||
|
return 1.24;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSkyColor(x, z, partialTicks) {
|
||||||
|
let angle = this.getCelestialAngle(partialTicks);
|
||||||
|
let brightness = Math.cos(angle * 3.141593 * 2.0) * 2.0 + 0.5;
|
||||||
|
|
||||||
|
if (brightness < 0.0) {
|
||||||
|
brightness = 0.0;
|
||||||
|
}
|
||||||
|
if (brightness > 1.0) {
|
||||||
|
brightness = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let temperature = this.getTemperature(x, z);
|
||||||
|
let rgb = this.getSkyColorByTemp(temperature);
|
||||||
|
|
||||||
|
let red = (rgb >> 16 & 0xff) / 255;
|
||||||
|
let green = (rgb >> 8 & 0xff) / 255;
|
||||||
|
let blue = (rgb & 0xff) / 255;
|
||||||
|
|
||||||
|
red *= brightness;
|
||||||
|
green *= brightness;
|
||||||
|
blue *= brightness;
|
||||||
|
|
||||||
|
return (Math.round(red * 255) << 16) | (Math.round(green * 255) << 8) | Math.round(blue * 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSkyColorByTemp(temperature) {
|
||||||
|
temperature /= 3;
|
||||||
|
if (temperature < -1) {
|
||||||
|
temperature = -1;
|
||||||
|
}
|
||||||
|
if (temperature > 1.0) {
|
||||||
|
temperature = 1.0;
|
||||||
|
}
|
||||||
|
return MathHelper.hsbToRgb(0.6222222 - temperature * 0.05, 0.5 + temperature * 0.1, 1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -16,4 +16,67 @@ window.MathHelper = class {
|
|||||||
return degree * (Math.PI / 180);
|
return degree * (Math.PI / 180);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static calculateCelestialAngle(time, partialTicks) {
|
||||||
|
let modTime = (time % 24000);
|
||||||
|
let angle = (modTime + partialTicks) / 24000.0 - 0.25;
|
||||||
|
|
||||||
|
if (angle < 0.0) {
|
||||||
|
angle++;
|
||||||
|
}
|
||||||
|
if (angle > 1.0) {
|
||||||
|
angle--;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle = 1.0 - ((Math.cos(angle * Math.PI) + 1.0) / 2.0);
|
||||||
|
angle = angle + (angle - angle) / 3.0;
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hsbToRgb(hue, saturation, brightness) {
|
||||||
|
let r = 0, g = 0, b = 0;
|
||||||
|
if (saturation === 0) {
|
||||||
|
r = g = b = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
} else {
|
||||||
|
let h = (hue - Math.floor(hue)) * 6.0;
|
||||||
|
let f = h - Math.floor(h);
|
||||||
|
let p = brightness * (1.0 - saturation);
|
||||||
|
let q = brightness * (1.0 - saturation * f);
|
||||||
|
let t = brightness * (1.0 - (saturation * (1.0 - f)));
|
||||||
|
switch (Math.floor(h)) {
|
||||||
|
case 0:
|
||||||
|
r = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
g = Math.floor(t * 255.0 + 0.5);
|
||||||
|
b = Math.floor(p * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = Math.floor(q * 255.0 + 0.5);
|
||||||
|
g = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
b = Math.floor(p * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r = Math.floor(p * 255.0 + 0.5);
|
||||||
|
g = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
b = Math.floor(t * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r = Math.floor(p * 255.0 + 0.5);
|
||||||
|
g = Math.floor(q * 255.0 + 0.5);
|
||||||
|
b = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
r = Math.floor(t * 255.0 + 0.5);
|
||||||
|
g = Math.floor(p * 255.0 + 0.5);
|
||||||
|
b = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
r = Math.floor(brightness * 255.0 + 0.5);
|
||||||
|
g = Math.floor(p * 255.0 + 0.5);
|
||||||
|
b = Math.floor(q * 255.0 + 0.5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 644 B After Width: | Height: | Size: 644 B |
|
After Width: | Height: | Size: 874 B |
|
After Width: | Height: | Size: 663 B |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
@@ -69,11 +69,13 @@ function updatePreStatus(message) {
|
|||||||
|
|
||||||
// Load textures
|
// Load textures
|
||||||
loadTexture([
|
loadTexture([
|
||||||
"font.png",
|
"gui/font.png",
|
||||||
"gui.png",
|
"gui/gui.png",
|
||||||
"background.png",
|
"gui/background.png",
|
||||||
"terrain.png",
|
"gui/icons.png",
|
||||||
"icons.png"
|
"terrain/terrain.png",
|
||||||
|
"terrain/sun.png",
|
||||||
|
"terrain/moon.png"
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
// Load scripts
|
// Load scripts
|
||||||
loadScripts([
|
loadScripts([
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
background-image: url(src/resources/background.png);
|
background-image: url(src/resources/gui/background.png);
|
||||||
background-size: 128px 128px;
|
background-size: 128px 128px;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
filter: brightness(0.5);
|
filter: brightness(0.5);
|
||||||
|
|||||||