Shader with dissolve and blue pulse on block previews.

Floor mode.
Block preview sorting based on player distance.
This commit is contained in:
Christian Knaapen
2019-02-06 00:09:11 +01:00
parent ba82449632
commit dfc2b11e94
12 changed files with 555 additions and 27 deletions

View File

@@ -57,5 +57,8 @@ public class BuildConfig {
public static class Visuals { public static class Visuals {
@Comment({"Show a block preview if you have a block in hand on build mode Normal"}) @Comment({"Show a block preview if you have a block in hand on build mode Normal"})
public boolean alwaysShowBlockPreview = false; public boolean alwaysShowBlockPreview = false;
@Comment({"Use fancy shaders while placing blocks"})
public boolean useShaders = true;
} }
} }

View File

@@ -3,34 +3,136 @@ package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList; import java.util.*;
import java.util.List;
public class Floor implements IBuildMode { public class Floor implements IBuildMode {
Dictionary<UUID, Integer> rightClickNrTable = new Hashtable<>();
Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
@Override @Override
public void initialize(EntityPlayer player) { public void initialize(EntityPlayer player) {
rightClickNrTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) {
return new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
int rightClickNr = rightClickNrTable.get(player.getUniqueID());
rightClickNr++;
rightClickNrTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickNrTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place wall
list = findCoordinates(player, blockPos);
rightClickNrTable.put(player.getUniqueID(), 0);
}
return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) {
return new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
int rightClickNr = rightClickNrTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
//try on z axis
double y = firstPos.getY();
//then x and z are
double x = (y - start.y) / look.y * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z;
Vec3d yBound = new Vec3d(x, y, z);
//distance to player
double yDistSquared = yBound.subtract(start).lengthSquared();
int reach = ReachHelper.getMaxReach(player); //4 times as much as normal placement reach
//check if its not behind the player and its not too close and not too far
boolean yValid = yBound.subtract(start).dotProduct(look) > 0 &&
yDistSquared > 4 && yDistSquared < reach * reach;
//select the one that is closest to the player and is valid
Vec3d selected = null;
if (yValid) selected = yBound;
if (selected == null) return list;
//check if it doesnt go through blocks
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, false, false);
if (rayTraceResult != null && rayTraceResult.typeOfHit != RayTraceResult.Type.BLOCK) {
//return empty list
return list;
}
BlockPos secondPos = new BlockPos(selected);
//Add whole wall
//Limit amount of blocks you can place per row
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
//check if whole row fits within limit
if (Math.abs(y1 - y2) < limit - list.size()) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
}
return list;
} }
@Override @Override
public EnumFacing getSideHit(EntityPlayer player) { public EnumFacing getSideHit(EntityPlayer player) {
return null; return sideHitTable.get(player.getUniqueID());
} }
@Override @Override
public Vec3d getHitVec(EntityPlayer player) { public Vec3d getHitVec(EntityPlayer player) {
return null; return hitVecTable.get(player.getUniqueID());
} }
} }

View File

@@ -5,7 +5,6 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*; import java.util.*;

View File

@@ -12,7 +12,7 @@ import nl.requios.effortlessbuilding.EffortlessBuilding;
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
public class RandomizerBagGuiContainer extends GuiContainer { public class RandomizerBagGuiContainer extends GuiContainer {
private static final ResourceLocation guiTextures = private static final ResourceLocation guiTextures =
new ResourceLocation(EffortlessBuilding.MODID + ":textures/gui/container/randomizerbag.png"); new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png");
private final InventoryPlayer inventoryPlayer; private final InventoryPlayer inventoryPlayer;
private final IItemHandler inventoryBag; private final IItemHandler inventoryBag;

View File

@@ -1,17 +1,21 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockDirt;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
@@ -35,13 +39,18 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL14;
import org.lwjgl.util.Color; import org.lwjgl.util.Color;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
@Mod.EventBusSubscriber(Side.CLIENT) @Mod.EventBusSubscriber(Side.CLIENT)
public class RenderHelper implements IWorldEventListener { public class RenderHelper implements IWorldEventListener {
@@ -56,6 +65,8 @@ public class RenderHelper implements IWorldEventListener {
private static List<BlockPos> previousCoordinates; private static List<BlockPos> previousCoordinates;
private static final int secondaryTextureUnit = 7;
private static void begin(float partialTicks) { private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
@@ -89,14 +100,17 @@ public class RenderHelper implements IWorldEventListener {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT); GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glEnable(GL11.GL_CULL_FACE); GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_TEXTURE_2D);
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_color.png"));
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png"));
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.enableBlend(); GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_CONSTANT_ALPHA, GL11.GL_ONE_MINUS_CONSTANT_ALPHA); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f); GL14.glBlendColor(1F, 1F, 1F, 0.8f);
} }
private static void endBlockPreviews() { private static void endBlockPreviews() {
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); ShaderHelper.releaseShader();
GlStateManager.disableBlend(); GlStateManager.disableBlend();
GL11.glPopAttrib(); GL11.glPopAttrib();
} }
@@ -241,6 +255,9 @@ public class RenderHelper implements IWorldEventListener {
if (sideHit != null) { if (sideHit != null) {
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
float percentile = ClientProxy.ticksInGame / 100f % 1f;
//TODO test
percentile = 1f;
//get coordinates //get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos); List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos);
@@ -253,6 +270,13 @@ public class RenderHelper implements IWorldEventListener {
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
Collections.sort(newCoordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
//check if they are different from previous //check if they are different from previous
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates; previousCoordinates = newCoordinates;
@@ -275,6 +299,8 @@ public class RenderHelper implements IWorldEventListener {
if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) && if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) &&
SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, true, EnumFacing.UP, player) && SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, true, EnumFacing.UP, player) &&
SurvivalHelper.canReplace(player.world, player, blockPos)) { SurvivalHelper.canReplace(player.world, player, blockPos)) {
ShaderHelper.useShader(ShaderHelper.psiBar, generateCallback(percentile, new Vec3d(blockPos), i == 0 || i == newCoordinates.size() - 1));
renderBlockPreview(dispatcher, blockPos, blockState); renderBlockPreview(dispatcher, blockPos, blockState);
} }
} }
@@ -395,6 +421,40 @@ public class RenderHelper implements IWorldEventListener {
tessellator.draw(); tessellator.draw();
} }
private static Consumer<Integer> generateCallback(final float percentile, final Vec3d blockpos, final boolean highlight) {
Minecraft mc = Minecraft.getMinecraft();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "percentile");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");
//image
OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE/*new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_color.png")*/).getGlTextureId());
ARBShaderObjects.glUniform1iARB(imageUniform, 0);
OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
GlStateManager.enableTexture2D();
GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
//mask
GL11.glBindTexture(GL11.GL_TEXTURE_2D,
mc.renderEngine.getTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")).getGlTextureId());
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit);
//blockpos
ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z);
//percentile
ARBShaderObjects.glUniform1fARB(percentileUniform, percentile);
//highlight
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0);
};
}
//IWORLDEVENTLISTENER IMPLEMENTATION //IWORLDEVENTLISTENER IMPLEMENTATION
@Override @Override
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) { public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {

View File

@@ -0,0 +1,195 @@
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Modified by Requios
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)]
*/
package nl.requios.effortlessbuilding.helper;
import net.minecraft.client.renderer.OpenGlHelper;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.logging.log4j.Level;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public final class ShaderHelper {
private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static final int VERT = 1;
private static final int FRAG = 2;
private static final String VERT_EXTENSION = ".vert";
private static final String FRAG_EXTENSION = ".frag";
public static int rawColor;
public static int psiBar;
public static void init() {
if(!doUseShaders())
return;
rawColor = createProgram("/assets/effortlessbuilding/shaders/raw_color", FRAG);
psiBar = createProgram("/assets/effortlessbuilding/shaders/dissolve", FRAG);
}
public static void useShader(int shader, Consumer<Integer> callback) {
if(!doUseShaders())
return;
ARBShaderObjects.glUseProgramObjectARB(shader);
if(shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientProxy.ticksInGame);
if(callback != null)
callback.accept(shader);
}
}
public static void useShader(int shader) {
useShader(shader, null);
}
public static void releaseShader() {
useShader(0);
}
public static boolean doUseShaders() {
return BuildConfig.visuals.useShaders && OpenGlHelper.shadersSupported;
}
private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;
return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}
// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT_ST);
if(frag != null)
fragId = createShader(frag, FRAG_ST);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
StringBuilder source = new StringBuilder();
InputStream in = ShaderHelper.class.getResourceAsStream(filename);
Exception exception = null;
BufferedReader reader;
if(in == null)
return "";
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
Exception innerExc= null;
try {
String line;
while((line = reader.readLine()) != null)
source.append(line).append('\n');
} catch(Exception exc) {
exception = exc;
} finally {
try {
reader.close();
} catch(Exception exc) {
innerExc = exc;
}
}
if(innerExc != null)
throw innerExc;
} catch(Exception exc) {
exception = exc;
} finally {
try {
in.close();
} catch(Exception exc) {
if(exception == null)
exception = exc;
else exc.printStackTrace();
}
if(exception != null)
throw exception;
}
return source.toString();
}
}

View File

@@ -6,6 +6,7 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureMap;
@@ -51,6 +52,7 @@ import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui; import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.RenderHelper; import nl.requios.effortlessbuilding.helper.RenderHelper;
import nl.requios.effortlessbuilding.helper.ShaderHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage; import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
@@ -70,10 +72,13 @@ public class ClientProxy implements IProxy {
public static RayTraceResult currentLookAt; public static RayTraceResult currentLookAt;
private static int breakCooldown = 0; private static int breakCooldown = 0;
public static int ticksInGame = 0;
private static final HashMap<BuildModes.BuildModeEnum, RadialMenu.SpriteIconPositioning> buildModeIcons = new HashMap<>(); private static final HashMap<BuildModes.BuildModeEnum, RadialMenu.SpriteIconPositioning> buildModeIcons = new HashMap<>();
@Override @Override
public void preInit(FMLPreInitializationEvent event) { public void preInit(FMLPreInitializationEvent event) {
ShaderHelper.init();
} }
@Override @Override
@@ -142,6 +147,10 @@ public class ClientProxy implements IProxy {
} }
} }
/**
* From Chisels and Bits by AlgorithmX2
* https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/core/ClientSide.java
*/
private static void loadIcon(final TextureMap map, final BuildModes.BuildModeEnum mode) { private static void loadIcon(final TextureMap map, final BuildModes.BuildModeEnum mode) {
final RadialMenu.SpriteIconPositioning sip = new RadialMenu.SpriteIconPositioning(); final RadialMenu.SpriteIconPositioning sip = new RadialMenu.SpriteIconPositioning();
@@ -284,6 +293,11 @@ public class ClientProxy implements IProxy {
//QuickReplace toggle //QuickReplace toggle
if (keyBindings[1].isPressed()) { if (keyBindings[1].isPressed()) {
//TODO testing
EffortlessBuilding.log(player, "ShaderHelper init");
ShaderHelper.init();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace()); modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + ( EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (
@@ -304,8 +318,7 @@ public class ClientProxy implements IProxy {
@SubscribeEvent @SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) { public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase == TickEvent.Phase.START) {
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return; if (objectMouseOver == null) return;
@@ -321,12 +334,19 @@ public class ClientProxy implements IProxy {
currentLookAt = objectMouseOver; currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver; previousLookAt = objectMouseOver;
} else { } else {
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()){ if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()) {
previousLookAt = currentLookAt; previousLookAt = currentLookAt;
currentLookAt = objectMouseOver; currentLookAt = objectMouseOver;
} }
} }
} }
} else if (event.phase == TickEvent.Phase.END){
GuiScreen gui = Minecraft.getMinecraft().currentScreen;
if(gui == null || !gui.doesGuiPauseGame()) {
ticksInGame++;
}
}
} }
@SubscribeEvent @SubscribeEvent

View File

@@ -0,0 +1,134 @@
#version 120
uniform int time; // Passed in, see ShaderHelper.java
uniform float percentile; // Passed in via Callback
uniform int highlight;
uniform vec3 blockpos;
uniform sampler2D image;
uniform sampler2D mask;
// Simplex 3D Noise
// by Ian McEwan, Ashima Arts
//
vec4 permute(vec4 x) {return mod(((x*34.0)+1.0)*x, 289.0);}
vec4 taylorInvSqrt(vec4 r) {return 1.79284291400159 - 0.85373472095314 * r;}
float snoise(vec3 v){
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy) );
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
// x0 = x0 - 0. + 0.0 * C
vec3 x1 = x0 - i1 + 1.0 * C.xxx;
vec3 x2 = x0 - i2 + 2.0 * C.xxx;
vec3 x3 = x0 - 1. + 3.0 * C.xxx;
// Permutations
i = mod(i, 289.0 );
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients
// ( N*N points uniformly over a square, mapped onto an octahedron.)
float n_ = 1.0/7.0; // N=7
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z *ns.z); // mod(p,N*N)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
void main() {
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 color = texture2D(image, texcoord);
vec3 relBlockPos = mod(blockpos, 32.0) / 32.0;
vec2 maskcoord = texcoord + vec2(relBlockPos.x + relBlockPos.y, relBlockPos.z + relBlockPos.y);
vec4 maskColor = texture2D(mask, maskcoord);
float maskgs = maskColor.r;
//maskgs = snoise(blockpos / 32.0 + );
float r = color.r * gl_Color.r;
float g = color.g * gl_Color.g;
float b = color.b * gl_Color.b;
float a = color.a; // Ignore gl_Color.a as we don't want to make use of that for the dissolve effect
float pulse = (sin(time / 10.0) + 1.0) / 2.0;
vec4 pulseColor = texture2D(mask, maskcoord + time / 1000.0);
vec4 pulseColor2 = texture2D(mask, vec2(maskcoord.x - time / 1300.0, maskcoord.y - time / 1300.0));
float pulseGreyScale = pulseColor.r + pulseColor2.r / 2.0;
g += (1.0 - g) * pulseGreyScale * pulse * 0.2;
b += (1.0 - b) * pulseGreyScale * pulse;
// float exr1 = sin(texcoord.x * 2 + texcoord.y * 10 + time * 0.035);
// float exr2 = sin(texcoord.x * 20 + texcoord.y * 2 + time * 0.15);
// float exr3 = sin(texcoord.x * 1 + texcoord.y * 90 + time * 0.75);
// float w1 = (cos(time * 0.1) + 1) * 0.5;
// float w2 = (sin(time * 0.08) + 1) * 0.5;
// float w3 = (cos(time * 0.001) + 1) * 0.5;
// float w = w1 + w2 + w3;
// float exr = (exr1 * w1 + exr2 * w2 + exr3 * w3) / w * 0.1;
// r += exr;
// g -= exr;
if(highlight == 1) {
r -= 0.2;
b -= 0.2;
g -= 0.2;
}
r = max(0, min(1, r));
g = max(0, min(1, g));
b = max(0, min(1, b));
if(maskgs <= percentile)
gl_FragColor = vec4(r, g, b, a);
else gl_FragColor = vec4(r, g, b, 0);
}

View File

@@ -0,0 +1,15 @@
#version 120
uniform sampler2D bgl_RenderedTexture;
void main() {
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 color = texture2D(bgl_RenderedTexture, texcoord);
float r = color.b * gl_Color.r;
float g = color.g * gl_Color.g;
float b = color.r * gl_Color.b;
float a = color.a * gl_Color.a;
gl_FragColor = vec4(r, g, b, a);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB