From f22e1bdeb3fd373a69728a6e4af6c4f71adf0213 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 29 Mar 2020 17:08:25 -0400 Subject: [PATCH] Added planet atmosphere shader --- core/assets/shaders/atmosphere.frag | 120 ++++++++++++++++++ core/assets/shaders/atmosphere.vert | 13 ++ core/assets/shaders/planet.vert | 2 +- core/src/mindustry/content/Planets.java | 1 + core/src/mindustry/graphics/Shaders.java | 30 +++++ core/src/mindustry/type/Planet.java | 7 + .../mindustry/ui/dialogs/PlanetDialog.java | 58 ++++++--- .../mindustry/desktop/DesktopLauncher.java | 9 +- 8 files changed, 212 insertions(+), 28 deletions(-) create mode 100644 core/assets/shaders/atmosphere.frag create mode 100644 core/assets/shaders/atmosphere.vert diff --git a/core/assets/shaders/atmosphere.frag b/core/assets/shaders/atmosphere.frag new file mode 100644 index 0000000000..1c54340eda --- /dev/null +++ b/core/assets/shaders/atmosphere.frag @@ -0,0 +1,120 @@ +const float PI = 3.14159265359; +const float MAX = 10000.0; + +const float PEAK = 0.1; +const float FLARE = 0.0025; +const float INTENSITY = 14.3; +const float G_M = -0.85; + +const float INNER_RADIUS = 1.02; +const float OUTER_RADIUS = 1.3; + +const int numOutScatter = 10; +const float fNumOutScatter = 10.0; +const int numInScatter = 10; +const float fNumInScatter = 10.0; + +varying vec4 v_position; +varying mat4 v_model; + +uniform vec3 u_color; +uniform vec2 u_resolution; +uniform float u_time; +uniform vec3 u_campos; +uniform vec3 u_rcampos; +uniform mat4 u_invproj; +uniform vec3 u_light; + +vec2 rayIntersection(vec3 p, vec3 dir, float radius) { + float b = dot(p, dir); + float c = dot(p, p) - radius * radius; + + float d = b * b - c; + if (d < 0.0) { + return vec2(MAX, -MAX); + } + d = sqrt(d); + + float near = -b - d; + float far = -b + d; + + return vec2(near, far); +} + +float miePhase(float g, float c, float cc) { + float gg = g * g; + + float a = (1.0 - gg) * (1.0 + cc); + + float b = 1.0 + gg - 2.0 * g * c; + b *= sqrt(b); + b *= 2.0 + gg; + + return 1.5 * a / b; +} + +float rayleighPhase(float cc) { + return 0.75 * (1.0 + cc); +} + +float density(vec3 p) { + return exp(-(length(p) - INNER_RADIUS) * (4.0 / (OUTER_RADIUS - INNER_RADIUS))); +} + +float optic(vec3 p, vec3 q) { + vec3 step = (q - p) / fNumOutScatter; + vec3 v = p + step * 0.5; + + float sum = 0.0; + for (int i = 0; i < numOutScatter; i++) { + sum += density(v); + v += step; + } + sum *= length(step)*(1.0 / (OUTER_RADIUS - INNER_RADIUS)); + return sum; +} + +vec3 inScatter(vec3 o, vec3 dir, vec2 e, vec3 l) { + float len = (e.y - e.x) / fNumInScatter; + vec3 step = dir * len; + vec3 p = o + dir * e.x; + vec3 v = p + dir * (len * 0.5); + + vec3 sum = vec3(0.0); + for(int i = 0; i < numInScatter; i++){ + vec2 f = rayIntersection(v, l, OUTER_RADIUS); + vec3 u = v + l * f.y; + float n = (optic(p, v) + optic(v, u))*(PI * 4.0); + + sum += density(v) * exp(-n * (PEAK * u_color + FLARE)); + v += step; + } + sum *= len * (1.0 / (OUTER_RADIUS - INNER_RADIUS)); + float c = dot(dir, -l); + float cc = c * c; + return sum * (PEAK * u_color * rayleighPhase(cc) + FLARE * miePhase(G_M, c, cc)) * INTENSITY; +} + +vec3 rayDirection(){ + vec4 ray = v_model*v_position - vec4(u_campos, 1.0); + return normalize(vec3(ray)); +} + +void main(){ + vec3 dir = rayDirection(); + vec3 eye = u_rcampos; + + vec3 l = u_light; + + vec2 e = rayIntersection(eye, dir, OUTER_RADIUS); + if (e.x > e.y){ + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + vec2 f = rayIntersection(eye, dir, INNER_RADIUS); + e.y = min(e.y, f.x); + + vec3 result = inScatter(eye, dir, e, l); + + gl_FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/core/assets/shaders/atmosphere.vert b/core/assets/shaders/atmosphere.vert new file mode 100644 index 0000000000..6899e0f0f4 --- /dev/null +++ b/core/assets/shaders/atmosphere.vert @@ -0,0 +1,13 @@ +attribute vec4 a_position; + +varying vec4 v_position; +varying mat4 v_model; + +uniform mat4 u_model; +uniform mat4 u_projection; + +void main(){ + v_position = a_position; + v_model = u_model; + gl_Position = u_projection*u_model*a_position; +} \ No newline at end of file diff --git a/core/assets/shaders/planet.vert b/core/assets/shaders/planet.vert index 58ed7b7258..5fd51806d7 100755 --- a/core/assets/shaders/planet.vert +++ b/core/assets/shaders/planet.vert @@ -9,7 +9,7 @@ uniform vec3 u_ambientColor; varying vec4 v_col; -const vec3 diffuse = vec3(0.2); +const vec3 diffuse = vec3(0); void main(){ vec3 norc = u_ambientColor * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0))); diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index dd25efd89c..0f370551fc 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -38,6 +38,7 @@ public class Planets implements ContentList{ starter = new Planet("TODO", sun, 3, 1){{ generator = new TODOPlanetGenerator(); meshLoader = () -> new HexMesh(this, 6); + atmosphereColor = Color.valueOf("3c1b8f"); }}; } } diff --git a/core/src/mindustry/graphics/Shaders.java b/core/src/mindustry/graphics/Shaders.java index c6b009c10c..e9a960d896 100644 --- a/core/src/mindustry/graphics/Shaders.java +++ b/core/src/mindustry/graphics/Shaders.java @@ -3,12 +3,14 @@ package mindustry.graphics; import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; +import arc.graphics.g3d.*; import arc.graphics.gl.*; import arc.math.*; import arc.math.geom.*; import arc.scene.ui.layout.*; import arc.util.ArcAnnotate.*; import arc.util.*; +import mindustry.type.*; public class Shaders{ public static Shadow shadow; @@ -22,6 +24,7 @@ public class Shaders{ public static PlanetShader planet; public static PlanetGridShader planetGrid; public static SunShader sun; + public static AtmosphereShader atmosphere; public static void init(){ shadow = new Shadow(); @@ -43,6 +46,33 @@ public class Shaders{ planet = new PlanetShader(); planetGrid = new PlanetGridShader(); sun = new SunShader(); + atmosphere = new AtmosphereShader(); + } + + public static class AtmosphereShader extends LoadShader{ + public Camera3D camera; + public Planet planet; + + Mat3D mat = new Mat3D(); + + public AtmosphereShader(){ + super("atmosphere", "atmosphere"); + } + + @Override + public void apply(){ + setUniformf("u_resolution", Core.graphics.getWidth(), Core.graphics.getHeight()); + + setUniformf("u_time", Time.globalTime() / 10f); + setUniformf("u_campos", camera.position); + setUniformf("u_rcampos", Tmp.v31.set(camera.position).sub(planet.position)); + setUniformf("u_light", planet.getLightNormal()); + setUniformf("u_color", planet.atmosphereColor.r, planet.atmosphereColor.g, planet.atmosphereColor.b); + + setUniformMatrix4("u_model", planet.getTransform(mat).val); + setUniformMatrix4("u_projection", camera.combined.val); + setUniformMatrix4("u_invproj", camera.invProjectionView.val); + } } public static class PlanetShader extends LoadShader{ diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index ec43b3362e..6d0aec0fb2 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -8,6 +8,7 @@ import arc.math.geom.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.ArcAnnotate.*; +import arc.util.*; import arc.util.io.*; import mindustry.*; import mindustry.ctype.*; @@ -49,6 +50,8 @@ public class Planet extends UnlockableContent{ public boolean bloom = false; /** For suns, this is the color that shines on other planets. Does nothing for children. */ public Color lightColor = Color.white.cpy(); + /** Atmosphere tint for landable planets. */ + public Color atmosphereColor = new Color(0.3f, 0.7f, 1.0f); /** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system.*/ public @Nullable Planet parent; /** The root parent of the whole solar system this planet is in. */ @@ -128,6 +131,10 @@ public class Planet extends UnlockableContent{ } } + public Vec3 getLightNormal(){ + return Tmp.v31.set(solarSystem.position).sub(position).nor(); + } + /** Calculates orbital rotation based on universe time.*/ public float getOrbitAngle(){ //applies random offset to prevent planets from starting out in a line diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index f6845e3ef6..a9e15f2080 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -1,6 +1,7 @@ package mindustry.ui.dialogs; import arc.*; +import arc.fx.util.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.graphics.g3d.*; @@ -51,7 +52,19 @@ public class PlanetDialog extends FloatingDialog{ private Planet planet = Planets.starter; private float lastX, lastY; private @Nullable Sector selected, hovered; - private Table stable, infoTable; + private Table stable; + private ScreenQuad quad = new ScreenQuad(); + private Mesh atmosphere = MeshBuilder.buildHex(new HexMesher(){ + @Override + public float getHeight(Vec3 position){ + return 0; + } + + @Override + public Color getColor(Vec3 position){ + return Color.white; + } + }, 3, false, 1.5f, 0f); public PlanetDialog(){ super("", Styles.fullDialog); @@ -103,17 +116,8 @@ public class PlanetDialog extends FloatingDialog{ } }); - infoTable = new Table(); - - stable = new Table(t -> { - t.background(Styles.black3); - t.margin(12f); - t.add("this is some arbitrary text."); - }); - - stable.act(1f); - stable.pack(); - stable.setPosition(0, 0, Align.center); + stable = new Table(); + stable.background(Styles.black3); shown(this::setup); } @@ -145,14 +149,11 @@ public class PlanetDialog extends FloatingDialog{ projector.proj(cam.combined()); batch.proj(cam.combined()); - bloom.capture(); + //bloom.capture(); renderPlanet(solarSystem); - if(planet.isLandable()){ - renderSectors(planet); - } - bloom.render(); + //bloom.render(); Gl.enable(Gl.blend); @@ -189,10 +190,28 @@ public class PlanetDialog extends FloatingDialog{ private void renderPlanet(Planet planet){ //render planet at offsetted position in the world - planet.mesh.render(cam.combined(), planet.getTransform(mat)); + planet.mesh.render(cam.combined, planet.getTransform(mat)); renderOrbit(planet); + if(planet.isLandable() && planet == this.planet){ + renderSectors(planet); + } + + if(planet.parent != null){ + Gl.blendFunc(Gl.one, Gl.one); + Gl.enable(Gl.blend); + + Shaders.atmosphere.camera = cam; + Shaders.atmosphere.planet = planet; + Shaders.atmosphere.bind(); + Shaders.atmosphere.apply(); + + atmosphere.render(Shaders.atmosphere, Gl.triangles); + + Gl.blendFunc(Blending.normal.src, Blending.normal.dst); + } + for(Planet child : planet.children){ renderPlanet(child); } @@ -218,7 +237,7 @@ public class PlanetDialog extends FloatingDialog{ } if(sec.hostility >= 0.02f){ - drawSelection(sec, Color.scarlet, 0.11f * sec.hostility); + //drawSelection(sec, Color.scarlet, 0.11f * sec.hostility); } } @@ -230,6 +249,7 @@ public class PlanetDialog extends FloatingDialog{ if(selected != null){ drawSelection(selected); drawBorders(selected, borderColor); + } batch.flush(Gl.triangles); diff --git a/desktop/src/mindustry/desktop/DesktopLauncher.java b/desktop/src/mindustry/desktop/DesktopLauncher.java index 15bc0424b0..c9c446bce3 100644 --- a/desktop/src/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/mindustry/desktop/DesktopLauncher.java @@ -23,7 +23,6 @@ import mindustry.type.*; import java.io.*; import java.net.*; -import java.nio.charset.*; import java.util.*; import static mindustry.Vars.*; @@ -31,15 +30,9 @@ import static mindustry.Vars.*; public class DesktopLauncher extends ClientLauncher{ public final static String discordID = "610508934456934412"; - boolean useDiscord = OS.is64Bit, loadError = false; + boolean useDiscord = OS.is64Bit && !OS.hasProp("nodiscord"), loadError = false; Throwable steamError; - static{ - if(!Charset.forName("US-ASCII").newEncoder().canEncode(System.getProperty("user.name", ""))){ - System.setProperty("com.codedisaster.steamworks.SharedLibraryExtractPath", new File("").getAbsolutePath()); - } - } - public static void main(String[] arg){ try{ Vars.loadLogger();