diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java index a118962b4..ff633d817 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java @@ -10,7 +10,7 @@ public enum ActorVertexAttributes implements IVertexAttrib { LIGHT("aModelLight", CommonAttributes.LIGHT), OFFSET("aOffset", CommonAttributes.FLOAT), AXIS("aAxis", CommonAttributes.NORMAL), - INSTANCE_ROTATION("aInstanceRot", CommonAttributes.VEC3), + INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION), ROTATION_CENTER("aRotationCenter", CommonAttributes.NORMAL), SPEED("aSpeed", CommonAttributes.FLOAT), ; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java index 6e41d205c..719825e17 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java @@ -6,6 +6,7 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.client.renderer.Vector3f; import net.minecraft.util.math.BlockPos; @@ -23,9 +24,10 @@ public class ContraptionActorData extends InstanceData { private byte rotationAxisX; private byte rotationAxisY; private byte rotationAxisZ; - private float localRotationX; - private float localRotationY; - private float localRotationZ; + private float qX; + private float qY; + private float qZ; + private float qW; private byte rotationCenterX = 64; private byte rotationCenterY = 64; private byte rotationCenterZ = 64; @@ -88,15 +90,11 @@ public class ContraptionActorData extends InstanceData { return this; } - public ContraptionActorData setLocalRotation(Vector3f axis) { - setLocalRotation(axis.getX(), axis.getY(), axis.getZ()); - return this; - } - - public ContraptionActorData setLocalRotation(float localRotationX, float localRotationY, float localRotationZ) { - this.localRotationX = localRotationX; - this.localRotationY = localRotationY; - this.localRotationZ = localRotationZ; + public ContraptionActorData setLocalRotation(Quaternion q) { + this.qX = q.getX(); + this.qY = q.getY(); + this.qZ = q.getZ(); + this.qW = q.getW(); return this; } @@ -106,7 +104,7 @@ public class ContraptionActorData extends InstanceData { putVec2(buf, blockLight, skyLight); put(buf, rotationOffset); putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ); - putVec3(buf, localRotationX, localRotationY, localRotationZ); + putVec4(buf, qX, qY, qZ, qW); putVec3(buf, rotationCenterX, rotationCenterY, rotationCenterZ); put(buf, speed); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java index 958670ede..525b3e4bb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java @@ -10,6 +10,7 @@ import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.util.Direction; public class DrillActorInstance extends ActorInstance { @@ -25,8 +26,15 @@ public class DrillActorInstance extends ActorInstance { BlockState state = context.state; facing = state.get(DrillBlock.FACING); - float eulerX = AngleHelper.verticalAngle(facing) + ((facing.getAxis() == Direction.Axis.Y) ? 180 : 0); - float eulerY = facing.getHorizontalAngle(); + + Direction.Axis axis = facing.getAxis(); + float eulerX = AngleHelper.verticalAngle(facing); + + float eulerY; + if (axis == Direction.Axis.Y) + eulerY = 0; + else + eulerY = facing.getHorizontalAngle() + ((axis == Direction.Axis.X) ? 180 : 0); drillHead = renderMaterial.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance(); @@ -35,7 +43,7 @@ public class DrillActorInstance extends ActorInstance { .setBlockLight(localBlockLight()) .setRotationOffset(0) .setRotationAxis(0, 0, 1) - .setLocalRotation(eulerX, eulerY, 0) + .setLocalRotation(new Quaternion(eulerX, eulerY, 0, true)) .setSpeed(getSpeed(facing)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java index f0431d63a..16a07d2a6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java @@ -8,6 +8,7 @@ import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.client.renderer.Vector3f; import net.minecraft.util.Direction; import net.minecraft.world.LightType; @@ -32,13 +33,14 @@ public class HarvesterActorInstance extends ActorInstance { harvester = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); + float horizontalAngle = facing.getHorizontalAngle() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); harvester.getInstance() .setPosition(context.localPos) .setBlockLight(localBlockLight()) .setRotationOffset(0) .setRotationCenter(rotOffset) .setRotationAxis(-1, 0, 0) - .setLocalRotation(0, facing.getHorizontalAngle(), 0) + .setLocalRotation(new Quaternion(Vector3f.POSITIVE_Y, horizontalAngle, true)) .setSpeed(getSpeed(facing)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java index 8ac245d1c..bb12c93dd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java @@ -31,6 +31,8 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance float zRot; float zRotPole; + float progress = Float.NaN; + public DeployerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); } @@ -57,13 +59,19 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance @Override public void tick() { - updateHandPose(); + boolean newHand = updateHandPose(); + + float newProgress = getProgress(AnimationTickHolder.getPartialTicks()); + + if (!newHand && MathHelper.epsilonEquals(newProgress, progress)) return; + + progress = newProgress; MatrixStack ms = new MatrixStack(); MatrixStacker msr = MatrixStacker.of(ms); msr.translate(getFloatingPos()) - .translate(getHandOffset(AnimationTickHolder.getPartialTicks())); + .translate(getHandOffset()); transformModel(msr, pole, hand, yRot, zRot, zRotPole); @@ -99,13 +107,7 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance return true; } - protected Vec3d getHandOffset(float partialTicks) { - float progress = 0; - if (tile.state == DeployerTileEntity.State.EXPANDING) - progress = 1 - (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; - if (tile.state == DeployerTileEntity.State.RETRACTING) - progress = (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; - + protected Vec3d getHandOffset() { float handLength = tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 : tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; float distance = Math.min(MathHelper.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); @@ -113,6 +115,14 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance return offset; } + private float getProgress(float partialTicks) { + if (tile.state == DeployerTileEntity.State.EXPANDING) + return 1 - (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; + if (tile.state == DeployerTileEntity.State.RETRACTING) + return (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; + return 0; + } + static void transformModel(MatrixStacker msr, InstanceKey pole, InstanceKey hand, float yRot, float zRot, float zRotPole) { msr.centre(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java index 9f6db3daf..610b71f4e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java @@ -8,6 +8,7 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.client.renderer.texture.TextureAtlasSprite; public class BeltData extends KineticData { @@ -16,9 +17,10 @@ public class BeltData extends KineticData { .addAttributes(BeltVertexAttributes.class) .build(); - private float rotX; - private float rotY; - private float rotZ; + private float qX; + private float qY; + private float qZ; + private float qW; private float sourceU; private float sourceV; private float minU; @@ -31,10 +33,11 @@ public class BeltData extends KineticData { super(owner); } - public BeltData setRotation(float rotX, float rotY, float rotZ) { - this.rotX = rotX; - this.rotY = rotY; - this.rotZ = rotZ; + public BeltData setRotation(Quaternion q) { + this.qX = q.getX(); + this.qY = q.getY(); + this.qZ = q.getZ(); + this.qW = q.getW(); return this; } @@ -61,7 +64,7 @@ public class BeltData extends KineticData { public void write(ByteBuffer buf) { super.write(buf); - putVec3(buf, rotX, rotY, rotZ); + putVec4(buf, qX, qY, qZ, qW); putVec2(buf, sourceU, sourceV); putVec4(buf, minU, minV, maxU, maxV); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java index ed4794e76..1891a7a2b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java @@ -13,9 +13,11 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.item.DyeColor; import net.minecraft.util.Direction; import net.minecraft.world.LightType; @@ -114,10 +116,10 @@ public class BeltInstance extends KineticTileInstance { private float getScrollSpeed() { float speed = tile.getSpeed(); if (((facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ^ upward) ^ - ((alongX && !diagonal) || (alongZ && diagonal)) ^ (vertical && facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE)) { + ((alongX && !diagonal) || (alongZ && diagonal))) { speed = -speed; } - if (sideways && (facing == Direction.SOUTH || facing == Direction.WEST)) + if (sideways && (facing == Direction.SOUTH || facing == Direction.WEST) || (vertical && facing == Direction.EAST)) speed = -speed; return speed; @@ -155,15 +157,18 @@ public class BeltInstance extends KineticTileInstance { } private InstanceKey setup(InstanceKey key, boolean bottom, SpriteShiftEntry spriteShift) { - float rotX = (!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0) + (beltSlope == BeltSlope.DOWNWARD ? 180 : 0); - float rotY = facing.getHorizontalAngle() + (upward ? 180 : 0) + (sideways ? 90 : 0); - float rotZ = sideways ? 90 : ((vertical && facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ? 180 : 0); + boolean downward = beltSlope == BeltSlope.DOWNWARD; + float rotX = (!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0) + (downward ? 180 : 0) + (sideways ? 90 : 0) + (vertical && alongZ ? 180 : 0); + float rotY = facing.getHorizontalAngle() + ((diagonal ^ alongX) && !downward ? 180 : 0) + (sideways && alongZ ? 180 : 0) + (vertical && alongX ? 90 : 0); + float rotZ = (sideways ? 90 : 0) + (vertical && alongX ? 90 : 0); + + Quaternion q = new Quaternion(rotX, rotY, rotZ, true); key.getInstance() .setTileEntity(tile) .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) .setSkyLight(world.getLightLevel(LightType.SKY, pos)) - .setRotation(rotX, rotY, rotZ) + .setRotation(q) .setRotationalSpeed(getScrollSpeed()) .setRotationOffset(bottom ? 0.5f : 0f) .setScrollTexture(spriteShift) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java index 678b29c73..b5888c49b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java @@ -6,7 +6,7 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; public enum BeltVertexAttributes implements IVertexAttrib { - INSTANCE_ROTATION("aInstanceRot", CommonAttributes.VEC3), + INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION), SOURCE_TEX("aSourceTexture", CommonAttributes.UV), SCROLL_TEX("aScrollTexture", CommonAttributes.VEC4), SCROLL_MULT("aScrollMult", CommonAttributes.NORMALIZED_BYTE), diff --git a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java index 916d8c478..485eb3889 100644 --- a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java +++ b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java @@ -108,7 +108,7 @@ public class AllProgramSpecs { private static ResourceLocation loc(String name) { - return new ResourceLocation(Create.ID, "shader/" + name); + return new ResourceLocation(Create.ID, name); } } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java index 9d718384e..3c3891c17 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java @@ -1,36 +1,26 @@ package com.simibubi.create.foundation.render.backend; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; import java.nio.FloatBuffer; -import java.util.EnumMap; import java.util.HashMap; import java.util.Map; -import java.util.function.Predicate; import com.simibubi.create.foundation.render.backend.gl.GlFog; -import com.simibubi.create.foundation.render.backend.gl.GlFogMode; import com.simibubi.create.foundation.render.backend.gl.shader.*; import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat; import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; import net.minecraft.world.World; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryUtil; import com.simibubi.create.foundation.config.AllConfigs; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.resources.IReloadableResourceManager; import net.minecraft.resources.IResourceManager; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.resource.IResourceType; import net.minecraftforge.resource.ISelectiveResourceReloadListener; -import net.minecraftforge.resource.VanillaResourceType; public class Backend { public static final Boolean SHADER_DEBUG_OUTPUT = true; @@ -38,8 +28,8 @@ public class Backend { public static final Logger log = LogManager.getLogger(Backend.class); public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16); - private static final Map> registry = new HashMap<>(); - private static final Map, ProgramGroup> programs = new HashMap<>(); + static final Map> registry = new HashMap<>(); + static final Map, ProgramGroup> programs = new HashMap<>(); private static boolean enabled; @@ -102,85 +92,13 @@ public class Backend { IResourceManager manager = mc.getResourceManager(); if (manager instanceof IReloadableResourceManager) { - ISelectiveResourceReloadListener listener = Backend::onResourceManagerReload; + ISelectiveResourceReloadListener listener = ShaderLoader::onResourceManagerReload; ((IReloadableResourceManager) manager).addReloadListener(listener); } } - private static void onResourceManagerReload(IResourceManager manager, Predicate predicate) { - if (predicate.test(VanillaResourceType.SHADERS)) { - capabilities = GL.createCapabilities(); - compat = new GlFeatureCompat(capabilities); - - OptifineHandler.refresh(); - refresh(); - - if (gl20()) { - - programs.values().forEach(ProgramGroup::delete); - programs.clear(); - for (ProgramSpec shader : registry.values()) { - loadProgram(manager, shader); - } - - log.info("Loaded all shader programs."); - } - } - } - public static void refresh() { enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); } - private static

> void loadProgram(IResourceManager manager, S programSpec) { - try { - Map programGroup = new EnumMap<>(GlFogMode.class); - - for (GlFogMode fogMode : GlFogMode.values()) { - programGroup.put(fogMode, loadProgram(manager, programSpec, fogMode)); - } - - programs.put(programSpec, new ProgramGroup<>(programGroup)); - - log.debug("Loaded program {}", programSpec.name); - } catch (IOException ex) { - log.error("Failed to load program {}", programSpec.name, ex); - return; - } - } - - private static

> P loadProgram(IResourceManager manager, S programSpec, GlFogMode fogMode) throws IOException { - GlShader vert = null; - GlShader frag = null; - try { - ShaderConstants defines = new ShaderConstants(programSpec.defines); - - defines.defineAll(fogMode.getDefines()); - - vert = loadShader(manager, programSpec.getVert(), ShaderType.VERTEX, defines); - frag = loadShader(manager, programSpec.getFrag(), ShaderType.FRAGMENT, defines); - - GlProgram.Builder builder = GlProgram.builder(programSpec.name, fogMode).attachShader(vert).attachShader(frag); - - programSpec.attributes.forEach(builder::addAttribute); - - return builder.build(programSpec.factory); - - } finally { - if (vert != null) vert.delete(); - if (frag != null) frag.delete(); - } - } - - private static GlShader loadShader(IResourceManager manager, ResourceLocation name, ShaderType type, GlShader.PreProcessor preProcessor) throws IOException { - try (InputStream is = new BufferedInputStream(manager.getResource(name).getInputStream())) { - String source = TextureUtil.func_225687_b_(is); - - if (source == null) { - throw new IOException("Could not load program " + name); - } else { - return new GlShader(type, name, source, preProcessor); - } - } - } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java new file mode 100644 index 000000000..a9a4119e5 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java @@ -0,0 +1,202 @@ +package com.simibubi.create.foundation.render.backend; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.foundation.render.backend.gl.GlFogMode; +import com.simibubi.create.foundation.render.backend.gl.shader.*; +import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.resource.IResourceType; +import net.minecraftforge.resource.VanillaResourceType; +import org.lwjgl.opengl.GL; +import org.lwjgl.system.MemoryUtil; + +import java.io.*; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.util.*; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ShaderLoader { + public static final String SHADER_DIR = "flywheel/shaders/"; + public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); + + static final Map shaderSource = new HashMap<>(); + + static void onResourceManagerReload(IResourceManager manager, Predicate predicate) { + if (predicate.test(VanillaResourceType.SHADERS)) { + Backend.capabilities = GL.createCapabilities(); + Backend.compat = new GlFeatureCompat(Backend.capabilities); + + OptifineHandler.refresh(); + Backend.refresh(); + + if (Backend.gl20()) { + shaderSource.clear(); + loadShaderSources(manager); + + Backend.programs.values().forEach(ProgramGroup::delete); + Backend.programs.clear(); + Backend.registry.values().forEach(ShaderLoader::loadProgram); + + Backend.log.info("Loaded all shader programs."); + } + } + } + + private static void loadShaderSources(IResourceManager manager){ + Collection allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> { + for (String ext : EXTENSIONS) { + if (s.endsWith(ext)) return true; + } + return false; + }); + + for (ResourceLocation location : allShaders) { + try { + IResource resource = manager.getResource(location); + + String file = readToString(resource.getInputStream()); + + ResourceLocation name = new ResourceLocation(location.getNamespace(), + location.getPath().substring(SHADER_DIR.length())); + + shaderSource.put(name, file); + } catch (IOException e) { + + } + } + } + + static

> void loadProgram(S programSpec) { + Map programGroup = new EnumMap<>(GlFogMode.class); + + for (GlFogMode fogMode : GlFogMode.values()) { + programGroup.put(fogMode, loadProgram(programSpec, fogMode)); + } + + Backend.programs.put(programSpec, new ProgramGroup<>(programGroup)); + + Backend.log.debug("Loaded program {}", programSpec.name); + } + + private static

> P loadProgram(S programSpec, GlFogMode fogMode) { + GlShader vert = null; + GlShader frag = null; + try { + ShaderConstants defines = new ShaderConstants(programSpec.defines); + + defines.defineAll(fogMode.getDefines()); + + vert = loadShader(programSpec.getVert(), ShaderType.VERTEX, defines); + frag = loadShader(programSpec.getFrag(), ShaderType.FRAGMENT, defines); + + GlProgram.Builder builder = GlProgram.builder(programSpec.name, fogMode).attachShader(vert).attachShader(frag); + + programSpec.attributes.forEach(builder::addAttribute); + + return builder.build(programSpec.factory); + + } finally { + if (vert != null) vert.delete(); + if (frag != null) frag.delete(); + } + } + + private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); + + private static String processIncludes(ResourceLocation baseName, String source) { + HashSet seen = new HashSet<>(); + seen.add(baseName); + + return includeRecursive(source, seen).collect(Collectors.joining("\n")); + } + + private static Stream includeRecursive(String source, Set seen) { + return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { + + Matcher matcher = includePattern.matcher(line); + + if (matcher.find()) { + String includeName = matcher.group(1); + + ResourceLocation include = new ResourceLocation(includeName); + + if (seen.add(include)) { + String includeSource = shaderSource.get(include); + + if (includeSource != null) { + return includeRecursive(includeSource, seen); + } + } + } + + return Stream.of(line); + }); + } + + private static GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { + String source = shaderSource.get(name); + + source = processIncludes(name, source); + + if (defines != null) + source = defines.process(source); + + + return new GlShader(type, name, source); + } + + public static String readToString(InputStream is) { + RenderSystem.assertThread(RenderSystem::isOnRenderThread); + ByteBuffer bytebuffer = null; + + try { + bytebuffer = readToBuffer(is); + int i = bytebuffer.position(); + ((Buffer)bytebuffer).rewind(); + return MemoryUtil.memASCII(bytebuffer, i); + } catch (IOException e) { + + } finally { + if (bytebuffer != null) { + MemoryUtil.memFree(bytebuffer); + } + + } + + return null; + } + + public static ByteBuffer readToBuffer(InputStream is) throws IOException { + ByteBuffer bytebuffer; + if (is instanceof FileInputStream) { + FileInputStream fileinputstream = (FileInputStream)is; + FileChannel filechannel = fileinputstream.getChannel(); + bytebuffer = MemoryUtil.memAlloc((int)filechannel.size() + 1); + + while (filechannel.read(bytebuffer) != -1) { } + } else { + bytebuffer = MemoryUtil.memAlloc(8192); + ReadableByteChannel readablebytechannel = Channels.newChannel(is); + + while (readablebytechannel.read(bytebuffer) != -1) { + if (bytebuffer.remaining() == 0) { + bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2); + } + } + } + + return bytebuffer; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoadingException.java b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoadingException.java new file mode 100644 index 000000000..50b1c916a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoadingException.java @@ -0,0 +1,23 @@ +package com.simibubi.create.foundation.render.backend; + +public class ShaderLoadingException extends RuntimeException { + + public ShaderLoadingException() { + } + + public ShaderLoadingException(String message) { + super(message); + } + + public ShaderLoadingException(String message, Throwable cause) { + super(message, cause); + } + + public ShaderLoadingException(Throwable cause) { + super(cause); + } + + public ShaderLoadingException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java index f6daa58c6..acc24f822 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java @@ -9,6 +9,7 @@ public class CommonAttributes { public static final VertexAttribSpec VEC2 = new VertexAttribSpec(GlPrimitiveType.FLOAT, 2); public static final VertexAttribSpec FLOAT = new VertexAttribSpec(GlPrimitiveType.FLOAT, 1); + public static final VertexAttribSpec QUATERNION = new VertexAttribSpec(GlPrimitiveType.FLOAT, 4); public static final VertexAttribSpec NORMAL = new VertexAttribSpec(GlPrimitiveType.BYTE, 3, true); public static final VertexAttribSpec UV = new VertexAttribSpec(GlPrimitiveType.FLOAT, 2); diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java index dae037bdb..922b81b47 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java @@ -12,18 +12,11 @@ public class GlShader extends GlObject { public final ResourceLocation name; public final ShaderType type; - public GlShader(ShaderType type, ResourceLocation name, String source, PreProcessor preProcessor) { + public GlShader(ShaderType type, ResourceLocation name, String source) { this.type = type; this.name = name; int handle = GL20.glCreateShader(type.glEnum); - if (preProcessor != null) { - source = preProcessor.process(source); - - if (Backend.SHADER_DEBUG_OUTPUT) - Backend.log.debug("Preprocessor run on " + name);// + ":\n" + source); - } - GL20.glShaderSource(handle, source); GL20.glCompileShader(handle); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java index 57d2c92b0..9404b3544 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java @@ -147,9 +147,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka @SuppressWarnings("unchecked") public T getBehaviour(BehaviourType type) { - if (behaviours.containsKey(type)) - return (T) behaviours.get(type); - return null; + return (T) behaviours.get(type); } protected boolean isItemHandlerCap(Capability cap) { diff --git a/src/main/resources/assets/create/shader/belt.vert b/src/main/resources/assets/create/flywheel/shaders/belt.vert similarity index 52% rename from src/main/resources/assets/create/shader/belt.vert rename to src/main/resources/assets/create/flywheel/shaders/belt.vert index 81f9054d5..08e776ef6 100644 --- a/src/main/resources/assets/create/shader/belt.vert +++ b/src/main/resources/assets/create/flywheel/shaders/belt.vert @@ -1,6 +1,10 @@ #version 110 #define PI 3.1415926538 +#flwinclude <"create:core/quaternion.glsl"> +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; @@ -10,7 +14,7 @@ attribute vec2 aLight; attribute vec3 aNetworkTint; attribute float aSpeed; attribute float aOffset; -attribute vec3 aInstanceRot; +attribute vec4 aInstanceRot; attribute vec2 aSourceTexture; attribute vec4 aScrollTexture; attribute float aScrollMult; @@ -38,54 +42,24 @@ uniform vec3 uCameraPos; varying float FragDistance; #endif -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - 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., - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1.); -} - -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - -mat4 rotation(vec3 rot) { - return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); -} - -mat4 localRotation() { - vec3 rot = fract(aInstanceRot / 360.) * PI * 2.; - return rotation(rot); -} - void main() { - mat4 localRotation = localRotation(); - vec4 worldPos = localRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); + vec3 rotated = rotateVertexByQuat(aPos - .5, aInstanceRot) + aInstancePos + .5; - #ifdef CONTRAPTION + vec4 worldPos = vec4(rotated, 1.); + + vec3 norm = rotateVertexByQuat(aNormal, aInstanceRot); + +#ifdef CONTRAPTION worldPos = uModel * worldPos; - mat4 normalMat = uModel * localRotation; + norm = normalize(modelToNormal(uModel) * norm); BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; #if defined(USE_FOG) FragDistance = length(worldPos.xyz); #endif - #else - mat4 normalMat = localRotation; - - #if defined(USE_FOG) +#elif defined(USE_FOG) FragDistance = length(worldPos.xyz - uCameraPos); - #endif - #endif - - vec3 norm = normalize(normalMat * vec4(aNormal, 0.)).xyz; +#endif float scrollSize = aScrollTexture.w - aScrollTexture.y; float scroll = fract(aSpeed * uTime / (31.5 * 16.) + aOffset) * scrollSize * aScrollMult; diff --git a/src/main/resources/assets/create/shader/contraption.frag b/src/main/resources/assets/create/flywheel/shaders/contraption.frag similarity index 100% rename from src/main/resources/assets/create/shader/contraption.frag rename to src/main/resources/assets/create/flywheel/shaders/contraption.frag diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert new file mode 100644 index 000000000..b58a4df0e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert @@ -0,0 +1,71 @@ +#version 110 +#define PI 3.1415926538 + +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/quaternion.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + +// model data +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +// instance data +attribute vec3 aInstancePos; +attribute vec2 aModelLight; +attribute float aOffset; +attribute vec3 aAxis; +attribute vec4 aInstanceRot; +attribute vec3 aRotationCenter; +attribute float aSpeed; + + +varying float Diffuse; +varying vec2 TexCoords; +varying vec4 Color; +varying vec3 BoxCoord; +varying vec2 Light; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; + +uniform float uTime; +uniform mat4 uViewProjection; +uniform int uDebug; + +uniform vec3 uCameraPos; + +#if defined(USE_FOG) +varying float FragDistance; +#endif + +void main() { + float degrees = aOffset + uTime * aSpeed / 20.; + //float angle = fract(degrees / 360.) * PI * 2.; + + vec4 kineticRot = quat(aAxis, degrees); + vec3 rotated = rotateVertexByQuat(aPos - aRotationCenter, kineticRot) + aRotationCenter; + vec3 localPos = rotateVertexByQuat(rotated - .5, aInstanceRot) + aInstancePos + .5; + + vec4 worldPos = uModel * vec4(localPos, 1.); + + vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, kineticRot), aInstanceRot); + norm = modelToNormal(uModel) * norm; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + Diffuse = diffuse(norm); + TexCoords = aTexCoords; + Light = aModelLight; + gl_Position = uViewProjection * worldPos; + + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz); + #endif + + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/contraption_structure.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert similarity index 56% rename from src/main/resources/assets/create/shader/contraption_structure.vert rename to src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert index 0e053db27..dbcf4a595 100644 --- a/src/main/resources/assets/create/shader/contraption_structure.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert @@ -1,6 +1,9 @@ #version 110 #define PI 3.1415926538 +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; @@ -27,24 +30,6 @@ uniform vec3 uCameraPos; varying float FragDistance; #endif -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - 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., - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1.); -} - -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - void main() { vec4 viewPos = uModel * vec4(aPos, 1.); diff --git a/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl b/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl new file mode 100644 index 000000000..bc5792231 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl @@ -0,0 +1,5 @@ + +float diffuse(vec3 normal) { + vec3 n2 = normal * normal * vec3(.6, .25, .8); + return min(n2.x + n2.y * (3. + normal.y) + n2.z, 1.); +} diff --git a/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl b/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl new file mode 100644 index 000000000..f7c846e71 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl @@ -0,0 +1,42 @@ + +//mat4 rotate(vec3 axis, float angle) { +// float s = sin(angle); +// float c = cos(angle); +// float oc = 1. - 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., +// oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1. +// ); +//} + +mat4 rotate(vec3 axis, float angle) { + float s = sin(angle); + float c = cos(angle); + float oc = 1. - c; + + vec3 sa = axis * s; + + mat4 mr = mat4(1.); + mr[0].xyz = oc * axis.xxz * axis.xyx + vec3(c, sa.z, -sa.y); + mr[1].xyz = oc * axis.xyy * axis.yyz + vec3(-sa.z, c, sa.x); + mr[2].xyz = oc * axis.zyz * axis.xzz + vec3(sa.y, -sa.x, c); + + return mr; +} + +mat4 rotation(vec3 rot) { + return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); +} + +mat3 modelToNormal(mat4 mat) { + // Discard the edges. This won't be accurate for scaled or skewed matrices, + // but we don't have to work with those often. + mat3 m; + m[0] = mat[0].xyz; + m[1] = mat[1].xyz; + m[2] = mat[2].xyz; + return m; +} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl b/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl new file mode 100644 index 000000000..cbfff38ee --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl @@ -0,0 +1,56 @@ + +#define PIOVER2 1.5707963268 + +vec4 quat(vec3 axis, float angle) { + float halfAngle = angle * PIOVER2 / 180.0; + vec2 cs = sin(vec2(PIOVER2 - halfAngle, halfAngle)); // compute sin and cos in one instruction + return vec4(axis.xyz * cs.y, cs.x); +} + +vec4 quatMult(vec4 q1, vec4 q2) { + // disgustingly vectorized quaternion multiplication + vec4 a = q1.w * q2.xyzw; + vec4 b = q1.x * q2.wzxy * vec4(1., -1., 1., -1.); + vec4 c = q1.y * q2.zwxy * vec4(1., 1., -1., -1.); + vec4 d = q1.z * q2.yxwz * vec4(-1., 1., 1., -1.); + + return a + b + c + d; +} +// +//vec4 exp(vec4 q) { +// vec3 i = q.xyz; +// float r = sqrt(dot(i, i)); +// float et = exp(q.w); +// float s = et * sin(r) / r; +// +// vec4 qr; +// qr.w = et * cos(r); +// qr.xyz = i * s; +// +// return qr; +//} +// +//vec4 ln(vec4 q) { +// vec3 i = q.xyz; +// float r = sqrt(dot(i, i)); +// float t = atan(r, q.w) / r; +// +// vec4 qr; +// qr.w = log(dot(q, q)) * 0.5; +// qr.xyz = i * t; +// +// return qr; +//} +// +//vec4 pow(vec4 q, float n) { +// return exp(ln(q) * n); +//} + +vec3 rotateVertexByQuat(vec3 v, vec4 q) { + vec3 i = q.xyz; + return v + 2.0 * cross(i, cross(i, v) + q.w * v); +} + +vec3 rotateAbout(vec3 v, vec3 axis, float angle) { + return rotateVertexByQuat(v, quat(axis, angle)); +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/flap.vert b/src/main/resources/assets/create/flywheel/shaders/flap.vert similarity index 54% rename from src/main/resources/assets/create/shader/flap.vert rename to src/main/resources/assets/create/flywheel/shaders/flap.vert index a70fdf1ad..496051288 100644 --- a/src/main/resources/assets/create/shader/flap.vert +++ b/src/main/resources/assets/create/flywheel/shaders/flap.vert @@ -1,6 +1,10 @@ #version 110 #define PI 3.1415926538 +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/quaternion.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; @@ -40,24 +44,6 @@ uniform vec3 uCameraPos; varying float FragDistance; #endif -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - 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., - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1.); -} - float toRad(float degrees) { return fract(degrees / 360.) * PI * 2.; } @@ -72,35 +58,32 @@ float getFlapAngle() { float which = step(0., aFlapness); float degrees = which * halfAngle + (1. - which) * angle; // branchless conditional multiply - return -toRad(degrees); + return degrees; } void main() { float flapAngle = getFlapAngle(); - mat4 orientation = rotate(vec3(0., 1., 0.), toRad(aHorizontalAngle)); - mat4 flapRotation = rotate(vec3(1., 0., 0.), flapAngle); + vec4 orientation = quat(vec3(0., 1., 0.), -aHorizontalAngle); + vec4 flapRotation = quat(vec3(1., 0., 0.), flapAngle); - vec4 worldPos = flapRotation * vec4(aPos - aPivot, 1.) + vec4(aPivot + aSegmentOffset, 0.); - worldPos = orientation * vec4(worldPos.xyz - .5, 1.) + vec4(aInstancePos + .5, 0.); + vec3 rotated = rotateVertexByQuat(aPos - aPivot, flapRotation) + aPivot + aSegmentOffset; + rotated = rotateVertexByQuat(rotated - .5, orientation) + aInstancePos + .5; + + vec4 worldPos = vec4(rotated, 1.); + vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, flapRotation), orientation); #ifdef CONTRAPTION worldPos = uModel * worldPos; - mat4 normalMat = uModel * orientation * flapRotation; + norm = modelToNormal(uModel) * norm; BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; #if defined(USE_FOG) FragDistance = length(worldPos.xyz); #endif - #else - mat4 normalMat = orientation * flapRotation; - - #if defined(USE_FOG) + #elif defined(USE_FOG) FragDistance = length(worldPos.xyz - uCameraPos); #endif - #endif - - vec3 norm = normalize(normalMat * vec4(aNormal, 0.)).xyz; Diffuse = diffuse(norm); TexCoords = aTexCoords; diff --git a/src/main/resources/assets/create/shader/model.frag b/src/main/resources/assets/create/flywheel/shaders/model.frag similarity index 100% rename from src/main/resources/assets/create/shader/model.frag rename to src/main/resources/assets/create/flywheel/shaders/model.frag diff --git a/src/main/resources/assets/create/shader/model.vert b/src/main/resources/assets/create/flywheel/shaders/model.vert similarity index 73% rename from src/main/resources/assets/create/shader/model.vert rename to src/main/resources/assets/create/flywheel/shaders/model.vert index 54bf4ba4b..9767a122c 100644 --- a/src/main/resources/assets/create/shader/model.vert +++ b/src/main/resources/assets/create/flywheel/shaders/model.vert @@ -1,5 +1,8 @@ #version 110 +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; @@ -32,23 +35,6 @@ uniform vec3 uCameraPos; varying float FragDistance; #endif -mat3 modelToNormal(mat4 mat) { - // Discard the edges. This won't be accurate for scaled or skewed matrices, - // but we don't have to work with those often. - mat3 m; - m[0] = mat[0].xyz; - m[1] = mat[1].xyz; - m[2] = mat[2].xyz; - return m; -} - -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - void main() { vec4 worldPos = aTransform * vec4(aPos, 1.); diff --git a/src/main/resources/assets/create/flywheel/shaders/rotating.vert b/src/main/resources/assets/create/flywheel/shaders/rotating.vert new file mode 100644 index 000000000..53d258bfd --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/rotating.vert @@ -0,0 +1,82 @@ +#version 110 +#define PI 3.1415926538 + +#flwinclude <"create:core/quaternion.glsl"> +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +attribute vec3 aInstancePos; +attribute vec2 aLight; +attribute vec3 aNetworkTint; +attribute float aSpeed; +attribute float aOffset; +attribute vec3 aAxis; + +varying vec2 TexCoords; +varying vec4 Color; +varying float Diffuse; +varying vec2 Light; + +#if defined(CONTRAPTION) +varying vec3 BoxCoord; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; +#endif + +uniform float uTime; +uniform mat4 uViewProjection; +uniform int uDebug; + +uniform vec3 uCameraPos; + +#if defined(USE_FOG) +varying float FragDistance; +#endif + +void main() { + float degrees = aOffset + uTime * aSpeed * 3./10.; + vec4 kineticRot = quat(aAxis, degrees); + + vec4 worldPos = vec4(rotateVertexByQuat(aPos - .5, kineticRot) + aInstancePos + .5, 1.); + + vec3 norm = rotateVertexByQuat(aNormal, kineticRot); + + #ifdef CONTRAPTION + worldPos = uModel * worldPos; + norm = modelToNormal(uModel) * norm; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz); + #endif + #elif defined(USE_FOG) + FragDistance = length(worldPos.xyz - uCameraPos); + #endif + + Diffuse = diffuse(norm); + TexCoords = aTexCoords; + Light = aLight; + gl_Position = uViewProjection * worldPos; + + #ifdef CONTRAPTION + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #else + if (uDebug == 1) { + Color = vec4(aNetworkTint, 1.); + } else if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #endif +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/contraption_actor.vert b/src/main/resources/assets/create/shader/contraption_actor.vert deleted file mode 100644 index 31cdd6799..000000000 --- a/src/main/resources/assets/create/shader/contraption_actor.vert +++ /dev/null @@ -1,94 +0,0 @@ -#version 110 -#define PI 3.1415926538 -// model data -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; - -// instance data -attribute vec3 aInstancePos; -attribute vec2 aModelLight; -attribute float aOffset; -attribute vec3 aAxis; -attribute vec3 aInstanceRot; -attribute vec3 aRotationCenter; -attribute float aSpeed; - - -varying float Diffuse; -varying vec2 TexCoords; -varying vec4 Color; -varying vec3 BoxCoord; -varying vec2 Light; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - 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., - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1.); -} - -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - -mat4 rotation(vec3 rot) { - return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); -} - -mat4 kineticRotation() { - float degrees = aOffset + uTime * aSpeed / 20.; - float angle = fract(degrees / 360.) * PI * 2.; - - return rotate(normalize(aAxis), -angle); -} - -void main() { - mat4 kineticRotation = kineticRotation(); - vec4 localPos = kineticRotation * vec4(aPos - aRotationCenter, 1.) + vec4(aRotationCenter, 0.); - - vec3 rot = fract(aInstanceRot / 360.) * PI * 2.; - mat4 localRot = rotation(rot); - localPos = localRot * vec4(localPos.xyz - .5, 1.) + vec4(aInstancePos + .5, 0.); - - vec4 worldPos = uModel * localPos; - - vec3 norm = normalize(uModel * localRot * kineticRotation * vec4(aNormal, 0.)).xyz; - - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aModelLight; - gl_Position = uViewProjection * worldPos; - - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif - - if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } -} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/rotating.vert b/src/main/resources/assets/create/shader/rotating.vert deleted file mode 100644 index afa32c38c..000000000 --- a/src/main/resources/assets/create/shader/rotating.vert +++ /dev/null @@ -1,108 +0,0 @@ -#version 110 -#define PI 3.1415926538 -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; - -attribute vec3 aInstancePos; -attribute vec2 aLight; -attribute vec3 aNetworkTint; -attribute float aSpeed; -attribute float aOffset; -attribute vec3 aAxis; - -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - 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., - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 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., 1.); -} - -float diffuse(vec3 normal) { - float x = normal.x; - float y = normal.y; - float z = normal.z; - return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); -} - -mat4 rotation(vec3 rot) { - return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); -} - -mat4 kineticRotation() { - float degrees = aOffset + uTime * aSpeed * -3./10.; - float angle = fract(degrees / 360.) * PI * 2.; - - return rotate(aAxis, angle); -} - -void main() { - mat4 kineticRotation = kineticRotation(); - vec4 worldPos = kineticRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); - - #ifdef CONTRAPTION - worldPos = uModel * worldPos; - mat4 normalMat = uModel * kineticRotation; - - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif - #else - mat4 normalMat = kineticRotation; - - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); - #endif - #endif - - vec3 norm = normalize(normalMat * vec4(aNormal, 0.)).xyz; - - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aLight; - gl_Position = uViewProjection * worldPos; - - #ifdef CONTRAPTION - if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } - #else - if (uDebug == 1) { - Color = vec4(aNetworkTint, 1.); - } else if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } - #endif -} \ No newline at end of file