diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md new file mode 100644 index 00000000..e7cce9cd --- /dev/null +++ b/docs/wiki/Home.md @@ -0,0 +1,113 @@ +# Overview + +Lodestone is a library containing all the code that I throughout my time in the modding scene have found useful. It contains utilities such as a rendering system, static config initialization, simplified block entities & inventories, a simple multiblock system, a custom fire effects, and so on. Just a bunch of random useful stuff that I needed in my other projects. + +The way I approach writing this wiki will essentially work on a priority system. You are free to ping me at any time in my discord asking for help with a certain thing, and if I have time I will write about that thing here. After enough time the wiki will contain everything, with the most frequently used things being prioritized. + +# Setup Guide + +Like any other mod, Lodestone needs to be added to the project. +This can be done using the [Blamejared Maven](https://maven.blamejared.com/team/lodestar/lodestone/lodestone/). + +## Forge + +On Forge, Lodestone requires [Curios](https://github.com/TheIllusiveC4/Curios). +```groovy +repositories { + mavenCentral() + maven { + name 'Curios maven' + url = "https://maven.theillusivec4.top/" + } + maven { url = 'https://maven.blamejared.com/' } +} + +dependencies { + minecraft "net.minecraftforge:forge:${project.minecraftVersion}-${project.forgeVersion}" + implementation fg.deobf("team.lodestar.lodestone:lodestone:${minecraft_version}-${lodestone_version}") + //1.18.2 Example: implementation fg.deobf("team.lodestar.lodestone:lodestone:1.18.2-1.4.1.435") + //1.19.2 Example: implementation fg.deobf("team.lodestar.lodestone:lodestone:1.19.2-1.4.2.83") + //1.20.1 Example: implementation fg.deobf("team.lodestar.lodestone:lodestone:1.20.1-1.4.2.62") + + compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${minecraft_version}:api") + runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${minecraft_version}") +} +``` + +### Mixins + +Lodestone utilizes mixins, and without the appropriate plugin present in your Lodestone-dependent project the game will refuse to launch. + +```groovy +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' + } +} + +apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'eclipse' +apply plugin: 'maven-publish' +apply plugin: 'org.spongepowered.mixin' +``` + +I believe writing your buildscript as such, and making sure to apply the `'org.spongepowered.mixin'` plugin is enough. For reference, the buildscript is the very first codeblock in your build.gradle file. It should be right at the very top. + +For more info, consult the [Mixin wiki](https://github.com/SpongePowered/Mixin/wiki/Mixins-on-Minecraft-Forge). + +## Fabric + +On Fabric, Lodestone requires [Cardinal Components](https://github.com/Ladysnake/Cardinal-Components-API), [Trinkets](https://github.com/emilyploszaj/trinkets), [Porting Lib](https://github.com/Fabricators-of-Create/Porting-Lib), and [Reach Entity Attributes](https://github.com/JamiesWhiteShirt/reach-entity-attributes). +```txt +port_lib_version = 2.3.4+1.20.1 +port_lib_modules = \ + accessors,\ + base,\ + blocks,\ + core,\ + data,\ + extensions,\ + lazy_registration,\ + model_generators,\ + models,\ + networking,\ + tool_actions +``` +```groovy + +repositories { + maven {url = 'https://maven.blamejared.com/' } + maven {url = "https://mvn.devos.one/releases/" } + maven {url = "https://api.modrinth.com/maven" } + maven {url = "https://maven.theillusivec4.top/"} + maven {url = "https://maven.jamieswhiteshirt.com/libs-release"} + maven {url = 'https://maven.ladysnake.org/releases'} + maven {url = "https://maven.terraformersmc.com/"} +} + +dependencies { + modImplementation("team.lodestar.lodestone:lodestone:${project.minecraft_version}-${project.lodestone_version}-fabric") + //For this you also need the following + modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cca_version}") + modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:${project.cca_version}") + modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-world:${project.cca_version}") + + modImplementation("dev.emi:trinkets:${project.trinkets_version}") + for (String module in port_lib_modules.split(",")) { + modImplementation("io.github.fabricators_of_create.Porting-Lib:$module:$port_lib_version") + } + modImplementation("com.jamieswhiteshirt:reach-entity-attributes:${project.rea_version}") +} + +``` + + +# Documented Features +- [InWorld Particles](https://github.com/LodestarMC/Lodestone/wiki/InWorld-Particles) +- [Post Processing Shaders](https://github.com/LodestarMC/Lodestone/wiki/Post-Processing-Shaders) \ No newline at end of file diff --git a/docs/wiki/InWorld-Particles.md b/docs/wiki/InWorld-Particles.md new file mode 100644 index 00000000..976d1e48 --- /dev/null +++ b/docs/wiki/InWorld-Particles.md @@ -0,0 +1,62 @@ +One of the more sought out and key features of Lodestone is the Particle System. +Lodestone Particles are still based on the Particle Engine, it's not a brand new thing with no connection to minecraft, but it is quite elaborate. +The basic premise is to allow Lodestone Particles to have everything about them defined by the WorldParticleBuilder, hopefully preventing the need for any hardcoded behavior. + +To begin, you will need to instantiate a WorldParticleBuilder using `WorldParticleBuilder.create` +```java + var builder = WorldParticleBuilder.create(LodestoneParticleRegistry.WISP_PARTICLE) +``` +The Particle Builder will require a particle type and nothing else. Once that's done, you are free to edit the properties that your particle will be spawned with in any way you want. And once you're done, simply use one of the `spawn` methods provided by the builder. + +Here's an example of an actual effect: +```java +import net.minecraft.client.*; +import net.minecraft.client.player.*; +import net.minecraft.world.level.*; +import net.minecraft.world.phys.*; +import net.minecraftforge.api.distmarker.*; +import net.minecraftforge.event.*; +import net.minecraftforge.eventbus.api.*; +import net.minecraftforge.fml.common.*; +import team.lodestar.lodestone.registry.common.particle.*; +import team.lodestar.lodestone.systems.easing.*; +import team.lodestar.lodestone.systems.particle.builder.*; +import team.lodestar.lodestone.systems.particle.data.*; +import team.lodestar.lodestone.systems.particle.data.color.*; +import team.lodestar.lodestone.systems.particle.data.spin.*; + +import java.awt.Color; + +@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE) +public class ExampleParticleEffect { + + @SubscribeEvent + public static void clientTick(TickEvent.ClientTickEvent event) { + final LocalPlayer player = Minecraft.getInstance().player; + if (player != null) { + spawnExampleParticles(player.level(), player.position()); + } + } + + public static void spawnExampleParticles(Level level, Vec3 pos) { + Color startingColor = new Color(100, 0, 100); + Color endingColor = new Color(0, 100, 200); + WorldParticleBuilder.create(LodestoneParticleRegistry.WISP_PARTICLE) + .setScaleData(GenericParticleData.create(0.5f, 0).build()) + .setTransparencyData(GenericParticleData.create(0.75f, 0.25f).build()) + .setColorData(ColorParticleData.create(startingColor, endingColor).setCoefficient(1.4f).setEasing(Easing.BOUNCE_IN_OUT).build()) + .setSpinData(SpinParticleData.create(0.2f, 0.4f).setSpinOffset((level.getGameTime() * 0.2f) % 6.28f).setEasing(Easing.QUARTIC_IN).build()) + .setLifetime(40) + .addMotion(0, 0.01f, 0) + .enableNoClip() + .spawn(level, pos.x, pos.y, pos.z); + } +} +``` + +The given codeblock is a class that when present in your mod will spawn a particle every tick at the player's position. +Worth noting is; for scale, transparency, color, and spin you will be using ParticleData classes. +These include: `ColorParticleData` for color, `SpinParticleData` for rotation and `GenericParticleData` for everything else. +Any of these are simply instantiated using an appropriate `#create` function, and here you will define things such as starting, middle and ending values, a lifetime coefficient, as well as easings. Finalize this by using `#build` + +For more examples of InWorld Particle Effects please look at this area of the Malum Repository: [Example Visual Effects](https://github.com/SammySemicolon/Malum-Mod/tree/1.6-1.20.1/src/main/java/com/sammy/malum/visual_effects) \ No newline at end of file diff --git a/docs/wiki/Post-Processing-Shaders.md b/docs/wiki/Post-Processing-Shaders.md new file mode 100644 index 00000000..306f0c09 --- /dev/null +++ b/docs/wiki/Post-Processing-Shaders.md @@ -0,0 +1,438 @@ +A post processing shader is a type of shader applied to the game's render output after the scene has been rendered, but before the final display on the screen. This allows you to modify the final image that is displayed in many ways. You can read up on Minecraft shaders [here](https://docs.google.com/document/d/15TOAOVLgSNEoHGzpNlkez5cryH3hFF3awXL5Py81EMk/edit). + +# Basic Post Processing Shaders +Lodestone introduces the [`PostProcessor`](https://github.com/LodestarMC/Lodestone/blob/main/src/main/java/team/lodestar/lodestone/systems/postprocess/PostProcessor.java) class, designed to facilitate the integration of post-processing shaders into Minecraft, allowing you to get started with post processing shaders within minutes. + +In this guide I will walk you through creating a shader that will tint your screen pink. + +## Setup +To begin, create a new class that extends Lodestone's [`PostProcessor`](https://github.com/LodestarMC/Lodestone/blob/main/src/main/java/team/lodestar/lodestone/systems/postprocess/PostProcessor.java) class, see example below. +```java +package dev.cryptic.aspect.client.shader.lodestone.post; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.resources.ResourceLocation; +import team.lodestar.lodestone.systems.postprocess.PostProcessor; + +public class TintPostProcessor extends PostProcessor { + @Override + public ResourceLocation getPostChainLocation() { + return null; + } + + @Override + public void beforeProcess(PoseStack poseStack) { + + } + + @Override + public void afterProcess() { + + } +} +``` +There are a few things you must do to setup this class, mainly you should modify the `getPostChainLocation()` method to return a new ResourceLocation which contains your mod's ID and the name of the shader. Next you should create a static instance of your post processor making it a singleton class. +```java +public static final TintPostProcessor INSTANCE = new TintPostProcessor(); + +@Override +public ResourceLocation getPostChainLocation() { + return new ResourceLocation(Aspect.MOD_ID, "tint_post"); +} +``` +## Register Post Processor +Now you must register your new post processor using [`PostProcessorHandler`](https://github.com/LodestarMC/Lodestone/blob/main/src/main/java/team/lodestar/lodestone/systems/postprocess/PostProcessHandler.java), this will happen in the `FMLClientSetupEvent`, see example below. +```java +@Mod.EventBusSubscriber(modid = Aspect.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ClientModEvents +{ + @SubscribeEvent + public static void onClientSetup(FMLClientSetupEvent event) { + PostProcessHandler.addInstance(TintPostProcessor.INSTANCE); + } +} +``` +## Create your "Post" JSON file +Now your TintPostProcessor is registered! However nothing will happen just yet because we have not created the post file and program. +Remember how we had to define a ResourceLocation earlier in the method `getPostChainLocation()`? +In my example I used +```java +new ResourceLocation(Aspect.MOD_ID, "tint_post") +``` +which directly correlates with the file location `assets/aspect/shaders/post/tint_post.json` This is your "Post" JSON file and it will hold the instructions for your shader. + +Below is a basic Post JSON which takes in the game's render output `minecraft:main`, hands it off to our program `aspect:tint`, and then passes it to Minecraft's `blit` program where it then **replaces** `minecraft:main`. +```json +{ + "targets": [ + "final" + ], + "passes": [ + { + "name": "aspect:tint", + "intarget": "minecraft:main", + "outtarget": "final" + }, + { + "name": "blit", + "intarget": "final", + "outtarget": "minecraft:main" + } + ] +} +``` +Now you are done with your "Post" JSON file! + +## Shader Programs +When writing our "Post" JSON file it referenced something called `aspect:tint`, this is whats called a program. Essentially it is a function that we pass `minecraft:main` into before it returns the out target of `final`. +Now this is where the real magic happens. +In `assets/aspect/shaders/program/` create a new JSON file called `tint.json` +There are many values in this program file but the main ones we want to pay attention to right now are the `vertex` and `fragment` values. These specify which vertex and fragment shaders the program will use. For now keep the vertex shader as `blit`, we dont need to change that. +```json +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "blit", + "fragment": "aspect:tint", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" } + ], + "uniforms": [ + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] +} +``` +Now that our program has been created we can begin creating our fragment shader (fsh)! +In the same folder as the program `tint.json`, create the fragment shader file `tint.fsh`. +```glsl +#version 150 +// The game's render output +uniform sampler2D DiffuseSampler; +// The texture coordinate represented as a 2D vector (x,y) +in vec2 texCoord; +// The output color of each pixel represented as a 4D vector (r,g,b,a) +out vec4 fragColor; + +void main() { + // Extract the original color of the pixel from the DiffuseSampler + vec4 original = texture(DiffuseSampler, texCoord); + // Pink! + vec3 tintColor = vec3(1.0,0.0,1.0) + // Multiply each rgba value by the tint color. + vec4 result = original * vec4(tintColor, 1.0); + + // Set the fragColor output as the result + fragColor = result; +} +``` +Now when you launch the game everything should be pink! +## Tips +If you want to be able to turn your shader on and off you can use +```java +TintPostProcessor.INSTANCE.setActive(boolean); +``` +To toggle the shader on and off you can use +```java +TintPostProcessor.INSTANCE.setActive(!TintPostProcessor.INSTANCE.isActive()); +``` +If you dont want the shader to be active by default you can add a static block to your `PostProcessor` +```java +public class TintPostProcessor extends PostProcessor { + public static final TintPostProcessor INSTANCE = new TintPostProcessor(); + // Static block added to turn the shader off by default + static { + INSTANCE.setActive(false); + } + + @Override + public ResourceLocation getPostChainLocation() { + return new ResourceLocation(Aspect.MODID, "tint"); + } + + @Override + public void beforeProcess(PoseStack poseStack) { + + } + + @Override + public void afterProcess() { + + } +} +``` + +# Multi-Instance Post Processing Shaders +Lodestone introduces the [`MultiInstancePostProcessor`](https://github.com/LodestarMC/Lodestone/blob/1.20/src/main/java/team/lodestar/lodestone/systems/postprocess/MultiInstancePostProcessor.java) class, which extends the functionality of the [`PostProcessor`](https://github.com/LodestarMC/Lodestone/blob/main/src/main/java/team/lodestar/lodestone/systems/postprocess/PostProcessor.java) allowing developers to easily create multiple instances of a post-processing effect with just one shader applied. This is done by creating instances of a [`DynamicShaderFxInstance`](https://github.com/LodestarMC/Lodestone/blob/1.20/src/main/java/team/lodestar/lodestone/systems/postprocess/DynamicShaderFxInstance.java) which is then added to your MultiInstancePostProcessor. Then the processor will compile every uniform expressed as floats into a single DataBuffer that is then passed to the shader. + +In this guide, we'll walk through creating a multi-instance post-processing shader that applies a glowing effect to specific areas in the world. + +For this example you will need to utilize the Depth Buffer, you can follow [this tutorial](https://github.com/LodestarMC/Lodestone/wiki/Post-Processing-Shaders#accessing-the-depth-buffer) for more information. + +## Setup + +### Create DynamicShaderFxInstance + +Start by creating a class that extends `DynamicShaderFxInstance`. This class will represent a single instance of your shader effect and will contain the necessary uniforms: `center`, `color` + +```java +package dev.cryptic.aspect.client.shader.lodestone.post.multi.glow; + +import org.joml.Vector3f; +import team.lodestar.lodestone.systems.postprocess.DynamicShaderFxInstance; +import java.util.function.BiConsumer; + +public class LightingFx extends DynamicShaderFxInstance { + public Vector3f center; + public Vector3f color; + + public LightingFx(Vector3f center, Vector3f color) { + this.center = center; + this.color = color; + } + + @Override + public void writeDataToBuffer(BiConsumer writer) { + writer.accept(0, center.x()); + writer.accept(1, center.y()); + writer.accept(2, center.z()); + writer.accept(3, color.x()); + writer.accept(4, color.y()); + writer.accept(5, color.z()); + } +} +``` + +### Create MultiInstancePostProcessor + +Next, create a class that extends `MultiInstancePostProcessor`. This class will manage all instances of your shader effect. + +```java +package dev.cryptic.aspect.client.shader.lodestone.post.multi.glow; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.cryptic.aspect.Aspect; +import team.lodestar.lodestone.systems.postprocess.MultiInstancePostProcessor; +import net.minecraft.client.renderer.EffectInstance; +import net.minecraft.resources.ResourceLocation; + +public class GlowPostProcessor extends MultiInstancePostProcessor { + public static final GlowPostProcessor INSTANCE = new GlowPostProcessor(); + private EffectInstance effectGlow; + + @Override + public ResourceLocation getPostChainLocation() { + return new ResourceLocation(Aspect.MOD_ID, "glow"); + } + // Max amount of FxInstances that can be added to the post processor at once + @Override + protected int getMaxInstances() { + return 16; + } + + // We passed in a total of 6 floats/uniforms to the shader inside our LightingFx class so this should return 6, will crash if it doesn't match + @Override + protected int getDataSizePerInstance() { + return 6; + } + + @Override + public void init() { + super.init(); + if (postChain != null) { + effectGlow = effects[0]; + } + } + + @Override + public void beforeProcess(PoseStack viewModelStack) { + super.beforeProcess(viewModelStack); + setDataBufferUniform(effectGlow, "DataBuffer", "InstanceCount"); + } +} +``` + +### Register Your MultiInstancePostProcessor +```java +@Mod.EventBusSubscriber(modid = Aspect.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ClientModEvents { + @SubscribeEvent + public static void onClientSetup(FMLClientSetupEvent event) { + PostProcessHandler.addInstance(GlowPostProcessor.INSTANCE); + } +} +``` + +### Retrieving Uniforms in Shader +Your `glow.json` file should define 2 new uniforms, a DataBuffer and InstanceCount both as `"type": "int"` +```json +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "aspect:glow", + "fragment": "aspect:glow", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" }, + { "name": "MainDepthSampler" } + ], + "uniforms": [ + { "name": "DataBuffer", "type": "int", "count": 1, "values": [ 0 ] }, + { "name": "InstanceCount", "type": "int", "count": 1, "values": [ 0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "invProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "invViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "cameraPos", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] }, + { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] + +} +``` +Now your `glow.fsh` and/or `glow.vsh` files should be able to access the DataBuffer and InstanceCount uniforms. +Its important to note that the data buffer stores the data for all instances of the shader, so you will need to retrieve it using texelFetch. +![](https://i.gyazo.com/d690184cc2faa24af91acd2fdea8b276.png) +The diagram above is an example of how our `DataBuffer` is structured with two instances of our shader effect. + +The first 6 values are the data for the first instance, and the next 6 values are the data for the second instance. + +In each instance the first 3 values are the center of the effect, and the next 3 values are the color of the effect. + +Knowing this we can define a for loop in our fragment shader to loop through all instances of the effect. +```glsl +for (int instance = 0; instance < InstanceCount; instance++) { + int index = instance * 6; // Each instance has 6 values + // 0-2: center, 3-5: color + vec3 center = fetch3(DataBuffer, index); + vec3 color = fetch3(DataBuffer, index + 3); + + // Per instance logic here +} +``` + +Now to complete the shader... + +```glsl +#version 150 + +#moj_import + +// Samplers +uniform sampler2D DiffuseSampler; +uniform sampler2D MainDepthSampler; +// Multi-Instance uniforms +uniform samplerBuffer DataBuffer; +uniform int InstanceCount; +// Matrices needed for world position calculation +uniform mat4 invProjMat; +uniform mat4 invViewMat; + +in vec2 texCoord; +out vec4 fragColor; + +void main() { + vec4 diffuseColor = texture(DiffuseSampler, texCoord); + vec3 worldPos = getWorldPos(MainDepthSampler, texCoord, invProjMat, invViewMat, cameraPos); + // Its important to set the fragColor to the diffuseColor before applying the effect! + fragColor = diffuseColor; + + float radius = 10.0; // Change this value to modify the falloff of the light, or make it a uniform + for (int instance = 0; instance < InstanceCount; instance++) { + int index = instance * 6;// Each instance has 6 values + // 0-2: center, 3-5: color + vec3 center = fetch3(DataBuffer, index); + vec3 color = fetch3(DataBuffer, index + 3); + + float distance = length(worldPos - center); + if (distance <= radius) { + float falloff = 1.0 - clamp(distance / radius, 0.0, 1.0); + fragColor.rgb *= (color * falloff + 1.0); + } + } +} +``` +Its important that you import Lodestone's [common functions](https://github.com/LodestarMC/Lodestone/blob/1.20/src/main/resources/assets/lodestone/shaders/include/common_math.glsl) in your shader file or else fetch3 and getWorldPos will not work. +```glsl +#moj_import +``` + + +### Congratulations! You have made your first Multi-Instance Post Processing Shader! +Spawn a few instances of your shader effect in the world and watch them glow! +```java +Vector3f center = new Vector3f(0, 0, 0); +Vector3f color = new Vector3f(1, 0, 1); +GlowPostProcessor.INSTANCE.addInstance(new LightingFx(center, color)); +``` + +# Accessing the Depth Buffer +A Depth Buffer is a type of image that stores the depth of each pixel in the scene. + +This is useful for post processing shaders as it allows you to create effects such as depth of field, fog, and more. +![](https://i.imgur.com/kV4nqnE.png) + +Lodestone takes care of copying the Depth Buffer so you can utilize it inside of your post processing shaders. To allow your shader program to access the depth buffer you must add "depthMain" to the targets in your "Post" JSON file. + +You will also need to add an auxtarget pointed at depthMain:depth in your "Post" JSON file. +```json +{ + "targets": [ + "final", + "depthMain" + ], + "passes": [ + { + "name": "aspect:multi/glow", + "intarget": "minecraft:main", + "outtarget": "final", + "auxtargets": [ + { + "name": "MainDepthSampler", + "id": "depthMain:depth" + } + ], + "uniforms": [ + ] + }, + { + "name": "blit", + "intarget": "final", + "outtarget": "minecraft:main" + } + ] +} +``` +Now inside of your Program JSON file, add a new Sampler with the same name as the Depth Sampler specified previously, in this case that would be "MainDepthSampler". +```json +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "aspect:glow", + "fragment": "aspect:glow", + "attributes": [ "Position" ], + "samplers": [ + { "name": "DiffuseSampler" }, + { "name": "MainDepthSampler" } + ], + "uniforms": [ + { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] +} +``` +Inside of either your vertex and/or fragment shader you now can call on MainDepthSampler as a sampler2D. +```glsl +uniform sampler2D MainDepthSampler; +``` +Now you can use the depth buffer in your shader to create effects such as depth of field, fog, and more! \ No newline at end of file diff --git a/docs/wiki/Recipe-Builders.md b/docs/wiki/Recipe-Builders.md new file mode 100644 index 00000000..95f1981e --- /dev/null +++ b/docs/wiki/Recipe-Builders.md @@ -0,0 +1,47 @@ +# Overview +As of Lodestone 1.21-1.8 + +Lodestone includes a small package built on top of vanilla recipe builders. The basic classes are `LodestoneRecipeBuilder`, `AutonamedRecipeBuilder` and a `Lodestone[Type]RecipeBuilder` for each of the different vanilla `[Type]RecipeBuilder` types. + +These implementations have the following use cases: +- `LodestoneRecipeBuilder`: For creating your own recipe builder, offers a default save function and others +- `AutonamedRecipeBuilder`: Extension of `LodestoneRecipeBuilder`, with the output-based naming function of vanilla `RecipeBuilder`s. Prefer vanilla if you want to allow additional unlock criteria or add the recipe into a certain group. +- `Lodestone[Type]RecipeBuilder`: Extension of it's corresponding `[Type]RecipeBuilder`. Implements `LodestoneRecipeBuilder` and is intended chiefly for adding additional parameters or modifying save paths. + + +# Lodestone recipe builders +A basic implementation of `LodestoneRecipeBuilder` looks like this: +```java +public class TestRecipeBuilder implements LodestoneRecipeBuilder { + protected final ItemStack ing1, ing2, output; + + // Advancement will be saved in recipes/misc/ + protected final RecipeCategory category = RecipeCategory.MISC; + + // Automatically added to the built advancement + protected final Map> criteria = new LinkedHashMap(); + + public TestRecipeBuilder(ItemStack ing1, ItemStack ing2, ItemStack output) { + this.ing1 = ing1; + this.ing2 = ing2; + this.output = output; + } + + @Override + public TestRecipe build(ResourceLocation id) { + // Custom ID check implementation if you feel like it + return new TestRecipe(ing1, ing2, output); + } + + @Override + public void save(RecipeOutput recipeOutput, ResourceLocation id) { + defaultSaveFunc(recipeOutput, id) + } + + // Optional + @Override + public void tweakAdvancement(Advancement.Builder advancement) { + // advancement.doSomething... + } +} +``` \ No newline at end of file diff --git a/docs/wiki/Render-Types.md b/docs/wiki/Render-Types.md new file mode 100644 index 00000000..fc795d42 --- /dev/null +++ b/docs/wiki/Render-Types.md @@ -0,0 +1,44 @@ +# Overview + +Lodestone makes it easier to create custom RenderTypes for all of your rendering needs. It's simply an extension of the vanilla RenderType system, so it's advised you familiarize yourself with that. + +To make a LodestoneRenderType, either use an existing rendertype provider and apply your texture, or make your own. Most of the existing RenderTypeProviders are located in [LodestoneRenderTypeRegistry](https://github.com/LodestarMC/Lodestone/blob/main/src/main/java/team/lodestar/lodestone/setup/LodestoneRenderTypeRegistry.java). + +```java +public static final ResourceLocation TEXTURE = new ResourceLocation("modid", "path/to/texture.png"); + +//Using an existing RenderTypeProvider +public static final LodestoneRenderType MY_RENDER_TYPE = LodestoneRenderTypeRegistry.TRANSPARENT_TEXTURE.apply(RenderTypeToken.createToken(TEXTURE); + +//Existing RenderTypeProvider with modifications +public static final LodestoneRenderType RENDER_TYPE_MODIFIED = LodestoneRenderTypeRegistry.TRANSPARENT_TEXTURE.applyWithModifier(RenderTypeToken.createToken(TEXTURE), builder -> { + builder + .setShaderState(MY_SHADER) + .setCullState(LodestoneRenderTypeRegistry.NO_CULL); + //etc. + } +); + +//Creating your own RenderTypeProvider +public static final RenderTypeProvider MY_PROVIDER = new RenderTypeProvider(token -> + LodestoneRenderType.createGenericRenderType("name", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, VertexFormat.Mode.QUADS, LodestoneRenderTypeRegistry.builder() + .setShaderState(MY_SHADER) + .setTransparencyState(StateShards.ADDITIVE_TRANSPARENCY) + .setLightmapState(LodestoneRenderTypeRegistry.LIGHTMAP) + .setTextureState(token.get()) + ) +); +public static final LodestoneRenderType RENDER_TYPE_CUSTOM = MY_PROVIDER.apply(RenderTypeToken.create(TEXTURE)); +``` + +Note: generally, try to create rendertypes in a **static** context. If you need to create a rendertype in a *nonstatic* context use `RenderTypeProvider#applyAndCache` instead of `RenderTypeProvider#apply`. + +# Delayed Renderer + +WIP + +# Shaders + +By default, any RenderTypes using Lodestone's Delayed Renderers will have the depth buffer (`"SceneDepthBuffer"`) and inverse projection matrix (`"InvProjMat"`) passed in automatically. + +TODO: Add code snippets demonstrating how to pass in custom uniforms. diff --git a/docs/wiki/World-Events.md b/docs/wiki/World-Events.md new file mode 100644 index 00000000..fa768936 --- /dev/null +++ b/docs/wiki/World-Events.md @@ -0,0 +1,23 @@ +# WIP DOCS | Any code here is subject to major change +World Events are designed to solve the biggest issues with entities being that entities will only be ticked/loaded when the chunks they are in are loaded. Instead they are ticked on the level for both the server and client. + +# Getting Started +As of Lodestone 1.21-1.7 +To create your first world event type you must register it with a custom DeferredRegister. Lodestone has some helper methods to make this process easier for you. +```java +public class WorldEventTypeRegistry { + private static final DeferredRegister WORLD_EVENT_TYPES = LodestoneWorldEventTypeRegistry.createRegister("mymod"); + private static final Registry REGISTRY = LodestoneWorldEventTypeRegistry.makeRegistry(WORLD_EVENT_TYPES); + + public static final Supplier EXAMPLE_WORLD_EVENT = WORLD_EVENT_TYPES.register("example_event", () -> + WorldEventType.Builder.of(ExampleWorldEvent::new, ResourceLocation.fromNamespaceAndPath("mymod", "example_event")) + .clientSynced(null) // Null = no renderer but still sync to client + .build() + ); + + public static void init(IEventBus eventBus) { + WORLD_EVENT_TYPES.register(eventBus); + } + +} +``` \ No newline at end of file diff --git a/docs/wiki/_Overview.md b/docs/wiki/_Overview.md new file mode 100644 index 00000000..9622fdba --- /dev/null +++ b/docs/wiki/_Overview.md @@ -0,0 +1,5 @@ +Lodestone is a library containing all the code that I throughout my time in the modding scene have found useful. +It contains utilities such as a rendering system, static config initialization, simplified block entities & inventories, a simple multiblock system, a custom fire effects, and so on. +Just a bunch of random useful stuff that I needed in my other projects. + +The way I approach writing this wiki will essentially work on a priority system. You are free to ping me at any time in my discord asking for help with a certain thing, and if I have time I will write about that thing here. After enough time the wiki will contain everything, with the most frequently used things being prioritized. \ No newline at end of file