Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package com.gtnewhorizon.gtnhlib.client.renderer.shader;

import java.nio.FloatBuffer;

import net.minecraft.client.Minecraft;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.client.event.TextureStitchEvent;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL20;

import com.gtnewhorizon.gtnhlib.GTNHLib;
import com.gtnewhorizon.gtnhlib.eventbus.EventBusSubscriber;
import com.gtnewhorizon.gtnhlib.mixins.early.EntityRendererAccessor;

import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.common.gameevent.TickEvent.RenderTickEvent;

/// This was largely copied from avaritia
@EventBusSubscriber
public class UniverseShader extends ShaderProgram {

public static final UniverseShader INSTANCE = new UniverseShader();

private UniverseShader() {
super(GTNHLib.MODID, "shaders/universe/universe.vert", "shaders/universe/universe.frag");
}

private static final int COSMIC_COUNT = 10;
public static final String[] COSMIC_TEXTURES = new String[COSMIC_COUNT];

static {
for (int i = 0; i < COSMIC_COUNT; i++) {
COSMIC_TEXTURES[i] = GTNHLib.MODID + ":universe/cosmic" + i;
}
}

public static final FloatBuffer COSMIC_UVS = BufferUtils.createFloatBuffer(4 * COSMIC_TEXTURES.length);
public static final IIcon[] COSMIC_ICONS = new IIcon[COSMIC_TEXTURES.length];

public static final float[] LIGHT_LEVEL = new float[3];

@SubscribeEvent
public static void letsMakeAQuilt(TextureStitchEvent.Pre event) {
if (event.map.getTextureType() != 0) {
return;
}

for (int i = 0; i < COSMIC_TEXTURES.length; i++) {
IIcon icon = event.map.registerIcon(COSMIC_TEXTURES[i]);
COSMIC_ICONS[i] = icon;
}
}

@SubscribeEvent
public static void pushTheCosmicFancinessToTheLimit(RenderTickEvent event) {
if (event.phase == Phase.START) {
for (IIcon icon : COSMIC_ICONS) {
COSMIC_UVS.put(icon.getMinU());
COSMIC_UVS.put(icon.getMinV());
COSMIC_UVS.put(icon.getMaxU());
COSMIC_UVS.put(icon.getMaxV());
}

COSMIC_UVS.flip();
}
}

private static boolean inventoryRender = false;

@SubscribeEvent
public static void makeCosmicStuffLessDumbInGUIs(GuiScreenEvent.DrawScreenEvent.Pre event) {
inventoryRender = true;
}

@SubscribeEvent
public static void finishMakingCosmicStuffLessDumbInGUIs(GuiScreenEvent.DrawScreenEvent.Post event) {
inventoryRender = false;
}

@Override
public void use() {
super.use();

Minecraft mc = Minecraft.getMinecraft();

float yaw = 0;
float pitch = 0;
float scale = 1.0f;

if (!inventoryRender) {
yaw = (float) ((mc.thePlayer.rotationYaw * 2 * Math.PI) / 360.0);
pitch = -(float) ((mc.thePlayer.rotationPitch * 2 * Math.PI) / 360.0);
} else {
scale = 25.0f;
}

int time2 = INSTANCE.getUniformLocation("time2");
GL20.glUniform1f(time2, mc.thePlayer.ticksExisted);

int x = INSTANCE.getUniformLocation("yaw");
GL20.glUniform1f(x, yaw);

int z = INSTANCE.getUniformLocation("pitch");
GL20.glUniform1f(z, pitch);

int l = INSTANCE.getUniformLocation("lightlevel");
GL20.glUniform3f(l, LIGHT_LEVEL[0], LIGHT_LEVEL[1], LIGHT_LEVEL[2]);

int lightmix = INSTANCE.getUniformLocation("lightmix");
GL20.glUniform1f(lightmix, 0.2f);

int uvs = INSTANCE.getUniformLocation("cosmicuvs");
GL20.glUniformMatrix2(uvs, false, COSMIC_UVS);

int s = INSTANCE.getUniformLocation("externalScale");
GL20.glUniform1f(s, scale);

int o = INSTANCE.getUniformLocation("opacity");
GL20.glUniform1f(o, 1f);
}

public static void setLightFromLocation(World world, int x, int y, int z) {
if (world == null) {
setLightLevel(1.0f);
return;
}

int coord = world.getLightBrightnessForSkyBlocks(x, y, z, 0);

int[] map = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapColors();

if (map == null) {
setLightLevel(1.0f);
return;
}

int mx = (coord % 65536) / 16;
int my = (coord / 65536) / 16;

int lightColour = map[Math.max(0, Math.min(map.length - 1, my * 16 + mx))];

setLightLevel(
((lightColour >> 16) & 0xFF) / 256.0f,
((lightColour >> 8) & 0xFF) / 256.0f,
((lightColour) & 0xFF) / 256.0f);
}

public static void setLightLevel(float level) {
setLightLevel(level, level, level);
}

public static void setLightLevel(float r, float g, float b) {
LIGHT_LEVEL[0] = Math.max(0.0f, Math.min(1.0f, r));
LIGHT_LEVEL[1] = Math.max(0.0f, Math.min(1.0f, g));
LIGHT_LEVEL[2] = Math.max(0.0f, Math.min(1.0f, b));
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/mixins/Mixins.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public enum Mixins implements IMixins {
"block_sounds.MixinPlayerControllerMP")
.addClientMixins("block_sounds.MixinRenderGlobal").setPhase(Phase.EARLY)
.setApplyIf(() -> GTNHLibConfig.blockSoundMixins)),
ENTITY_RENDERER_ACCESSOR(new MixinBuilder("Accesses the lightmap property of EntityRenderer").setPhase(Phase.EARLY)
.addCommonMixins("EntityRendererAccessor")),
//
;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gtnewhorizon.gtnhlib.mixins.early;

import net.minecraft.client.renderer.EntityRenderer;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(EntityRenderer.class)
public interface EntityRendererAccessor {

@Accessor("lightmapColors")
int[] getLightmapColors();
}
180 changes: 180 additions & 0 deletions src/main/resources/assets/gtnhlib/shaders/universe/universe.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#version 120

#define M_PI 3.1415926535897932384626433832795

const int cosmiccount = 10;
const int cosmicoutof = 101;

uniform sampler2D texture0;
uniform vec3 lightlevel;

uniform float time2;

uniform float yaw;
uniform float pitch;
uniform float externalScale;

uniform float lightmix;
uniform float opacity;

uniform mat2 cosmicuvs[cosmiccount];

varying vec3 position;

float rand2d(vec2 x) {
return fract(sin(mod(dot(x, vec2(12.9898, 78.233)), 3.14)) * 43758.5453);
}

mat4 rotationMatrix(vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;

return mat4(
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
0.0, 0.0, 0.0, 1.0);
}

void main (void) {
vec4 light = gl_Color;
vec4 mask = texture2D(texture0, gl_TexCoord[0].xy);
light.rgb *= lightlevel;
float correctTime = mod(time2,12000);

float oneOverExternalScale = 1.0/externalScale;

int uvtiles = 16;

// background colour
vec4 col = vec4(0.1,0.0,0.0,1.0);

float pulse = mod(correctTime,400)/400.0;

col.g = sin(pulse*M_PI*2) * 0.075 + 0.225;
col.b = cos(pulse*M_PI*2) * 0.05 + 0.3;

// get ray from camera to fragment
vec4 dir = normalize(vec4( -position, 0));

// rotate the ray to show the right bit of the sphere for the angle
float sb = sin(pitch);
float cb = cos(pitch);
dir = normalize(vec4(dir.x, dir.y * cb - dir.z * sb, dir.y * sb + dir.z * cb, 0));

float sa = sin(-yaw);
float ca = cos(-yaw);
dir = normalize(vec4(dir.z * sa + dir.x * ca, dir.y, dir.z * ca - dir.x * sa, 0));

vec4 ray;

// draw the layers
for (int i=0; i<16; i++) {
int mult = 16-i;

// get semi-random stuff
int j = i + 7;
float rand1 = (j * j * 4321 + j * 8) * 2.0;
int k = j + 1;
float rand2 = (k * k * k * 239 + k * 37) * 3.6;
float rand3 = rand1 * 347.4 + rand2 * 63.4;

// random rotation matrix by random rotation around random axis
vec3 axis = normalize(vec3(sin(rand1), sin(rand2) , cos(rand3)));

// apply
ray = dir * rotationMatrix(axis, mod(rand3, 2*M_PI));

// calcuate the UVs from the final ray
float rawu = 0.5 + (atan(ray.z,ray.x)/(2*M_PI));
float rawv = 0.5 + (asin(ray.y)/M_PI);

// get UV scaled for layers and offset by time;
float scale = mult*0.5 + 2.75;
float u = rawu * scale * externalScale;
//float v = (rawv + time * 0.00006) * scale * 0.6;
float v = (rawv + correctTime * 0.0002 * oneOverExternalScale) * scale * 0.6 * externalScale;

vec2 tex = vec2( u, v );

// tile position of the current uv
int tu = int(mod(floor(u*uvtiles),uvtiles));
int tv = int(mod(floor(v*uvtiles),uvtiles));

// get pseudorandom variants
int symbol = int(rand2d(vec2(tu, tv + i * 10.0)) * cosmicoutof);
int rotation = int(mod(pow(tu,float(tv)) + tu + 3 + tv*i, 8));
bool flip = false;
if (rotation >= 4) {
rotation -= 4;
flip = true;
}

// if it's an icon, then add the colour!
if (symbol >= 0 && symbol < cosmiccount) {

vec2 cosmictex = vec2(1.0,1.0);
vec4 tcol = vec4(1.0,0.0,0.0,1.0);

// get uv within the tile
float ru = clamp(mod(u,1.0)*uvtiles - tu, 0.0, 1.0);
float rv = clamp(mod(v,1.0)*uvtiles - tv, 0.0, 1.0);

if (flip) {
ru = 1.0 - ru;
}

float oru = ru;
float orv = rv;

// rotate uvs if necessary
if (rotation == 1) {
oru = 1.0-rv;
orv = ru;
} else if (rotation == 2) {
oru = 1.0-ru;
orv = 1.0-rv;
} else if (rotation == 3) {
oru = rv;
orv = 1.0-ru;
}

// get the iicon uvs for the tile
float umin = cosmicuvs[symbol][0][0];
float umax = cosmicuvs[symbol][1][0];
float vmin = cosmicuvs[symbol][0][1];
float vmax = cosmicuvs[symbol][1][1];

// interpolate based on tile uvs
cosmictex.x = umin * (1.0-oru) + umax * oru;
cosmictex.y = vmin * (1.0-orv) + vmax * orv;

tcol = texture2D(texture0, cosmictex);

// set the alpha, blending out at the bunched ends
float a = tcol.r * (0.5 + (1.0/mult) * 1.0) * (1.0-smoothstep(0.15, 0.48, abs(rawv-0.5)));

// get fancy colours
float r = (mod(rand1, 29.0)/29.0) * 0.3 + 0.4;
float g = (mod(rand2, 35.0)/35.0) * 0.4 + 0.6;
float b = (mod(rand1, 17.0)/17.0) * 0.3 + 0.7;

// mix the colours
//col = col*(1-a) + vec4(r,g,b,1)*a;
col = col + vec4(r,g,b,1)*a;
}
}

// apply lighting
vec3 shade = light.rgb * (lightmix) + vec3(1.0-lightmix,1.0-lightmix,1.0-lightmix);
col.rgb *= shade;

// apply mask
col.a *= mask.a * opacity;

col = clamp(col,0.0,1.0);

gl_FragColor = col;
}
Loading