├── src ├── .gitignore └── main │ ├── resources │ ├── assets │ │ └── sodium │ │ │ ├── icon.png │ │ │ ├── textures │ │ │ └── gui │ │ │ │ └── arrows.png │ │ │ └── shaders │ │ │ ├── chunk_glsl110.v.glsl │ │ │ └── chunk_glsl110.f.glsl │ ├── pack.mcmeta │ ├── sodium.accesswidener │ ├── META-INF │ │ ├── accesstransformer.cfg │ │ └── mods.toml │ ├── fabric.mod.json │ └── chlorine.mixins.json │ └── java │ ├── me │ └── jellysquid │ │ └── mods │ │ └── sodium │ │ ├── client │ │ ├── model │ │ │ ├── light │ │ │ │ ├── LightMode.java │ │ │ │ ├── smooth │ │ │ │ │ └── AoCompletionFlags.java │ │ │ │ ├── data │ │ │ │ │ └── QuadLightData.java │ │ │ │ ├── LightPipelineProvider.java │ │ │ │ ├── LightPipeline.java │ │ │ │ ├── cache │ │ │ │ │ ├── HashLightDataCache.java │ │ │ │ │ └── ArrayLightDataCache.java │ │ │ │ └── flat │ │ │ │ │ └── FlatLightPipeline.java │ │ │ ├── ModelCuboidAccessor.java │ │ │ ├── quad │ │ │ │ ├── sink │ │ │ │ │ ├── ModelQuadSinkDelegate.java │ │ │ │ │ └── ModelQuadSink.java │ │ │ │ ├── ModelQuadEncoder.java │ │ │ │ ├── properties │ │ │ │ │ ├── ModelQuadFacing.java │ │ │ │ │ └── ModelQuadOrientation.java │ │ │ │ ├── blender │ │ │ │ │ ├── FlatBiomeColorBlender.java │ │ │ │ │ └── BiomeColorBlender.java │ │ │ │ ├── ModelQuadViewMutable.java │ │ │ │ └── ModelQuadView.java │ │ │ └── consumer │ │ │ │ ├── GlyphVertexConsumer.java │ │ │ │ ├── ParticleVertexConsumer.java │ │ │ │ └── QuadVertexConsumer.java │ │ ├── gui │ │ │ ├── options │ │ │ │ ├── TextProvider.java │ │ │ │ ├── storage │ │ │ │ │ ├── OptionStorage.java │ │ │ │ │ ├── MinecraftOptionsStorage.java │ │ │ │ │ └── SodiumOptionsStorage.java │ │ │ │ ├── OptionFlag.java │ │ │ │ ├── binding │ │ │ │ │ ├── OptionBinding.java │ │ │ │ │ ├── GenericBinding.java │ │ │ │ │ └── compat │ │ │ │ │ │ └── VanillaBooleanOptionBinding.java │ │ │ │ ├── control │ │ │ │ │ ├── Control.java │ │ │ │ │ ├── ControlValueFormatter.java │ │ │ │ │ └── ControlElement.java │ │ │ │ ├── Option.java │ │ │ │ ├── OptionImpact.java │ │ │ │ ├── OptionPage.java │ │ │ │ └── OptionGroup.java │ │ │ └── widgets │ │ │ │ └── FlatButtonWidget.java │ │ ├── render │ │ │ ├── texture │ │ │ │ ├── SpriteExtended.java │ │ │ │ └── SpriteUtil.java │ │ │ ├── chunk │ │ │ │ ├── passes │ │ │ │ │ ├── WorldRenderPhase.java │ │ │ │ │ ├── impl │ │ │ │ │ │ ├── TranslucentRenderPass.java │ │ │ │ │ │ ├── SolidRenderPass.java │ │ │ │ │ │ ├── MultiTextureRenderPipeline.java │ │ │ │ │ │ └── SingleTextureRenderPipeline.java │ │ │ │ │ ├── BlockRenderPass.java │ │ │ │ │ ├── BlockRenderPassManager.java │ │ │ │ │ └── BlockLayer.java │ │ │ │ ├── shader │ │ │ │ │ ├── texture │ │ │ │ │ │ ├── ChunkProgramTextureUnit.java │ │ │ │ │ │ ├── LightmapTextureManagerAccessor.java │ │ │ │ │ │ ├── ChunkProgramTextureComponent.java │ │ │ │ │ │ └── ChunkProgramSingleTexture.java │ │ │ │ │ ├── ShaderComponent.java │ │ │ │ │ ├── ChunkProgramComponentBuilder.java │ │ │ │ │ └── ChunkFogMode.java │ │ │ │ ├── lists │ │ │ │ │ └── ChunkRenderListIterator.java │ │ │ │ ├── ChunkGraphicsState.java │ │ │ │ ├── multidraw │ │ │ │ │ ├── ChunkProgramMultiDraw.java │ │ │ │ │ ├── StructBuffer.java │ │ │ │ │ └── ChunkRenderBackendMultiDraw.java │ │ │ │ ├── ChunkCameraContext.java │ │ │ │ ├── compile │ │ │ │ │ └── ChunkBuildResult.java │ │ │ │ ├── oneshot │ │ │ │ │ ├── ChunkProgramOneshot.java │ │ │ │ │ └── ChunkOneshotGraphicsState.java │ │ │ │ ├── data │ │ │ │ │ ├── ChunkMeshData.java │ │ │ │ │ └── ChunkRenderBounds.java │ │ │ │ ├── tasks │ │ │ │ │ ├── ChunkRenderEmptyBuildTask.java │ │ │ │ │ └── ChunkRenderBuildTask.java │ │ │ │ ├── backends │ │ │ │ │ ├── gl43 │ │ │ │ │ │ └── GL43GraphicsState.java │ │ │ │ │ ├── gl20 │ │ │ │ │ │ └── GL20GraphicsState.java │ │ │ │ │ └── gl33 │ │ │ │ │ │ └── GL33GraphicsState.java │ │ │ │ └── region │ │ │ │ │ └── ChunkRegion.java │ │ │ ├── entity │ │ │ │ └── EntityLightSampler.java │ │ │ └── pipeline │ │ │ │ ├── RenderContextCommon.java │ │ │ │ └── context │ │ │ │ ├── GlobalRenderContext.java │ │ │ │ └── ChunkRenderContext.java │ │ ├── util │ │ │ ├── task │ │ │ │ └── CancellationSource.java │ │ │ ├── math │ │ │ │ ├── FrustumExtended.java │ │ │ │ ├── Matrix3fExtended.java │ │ │ │ ├── MatrixUtil.java │ │ │ │ └── Matrix4fExtended.java │ │ │ ├── MathUtil.java │ │ │ ├── color │ │ │ │ ├── ColorU8.java │ │ │ │ └── ColorARGB.java │ │ │ ├── Dim2i.java │ │ │ ├── BufferUtil.java │ │ │ ├── UnsafeUtil.java │ │ │ └── ModelQuadUtil.java │ │ ├── world │ │ │ ├── ChunkStatusListenerManager.java │ │ │ ├── ClientWorldExtended.java │ │ │ ├── biome │ │ │ │ ├── ItemColorsExtended.java │ │ │ │ ├── BlockColorsExtended.java │ │ │ │ ├── BiomeCache.java │ │ │ │ └── BiomeCacheManager.java │ │ │ └── ChunkStatusListener.java │ │ ├── gl │ │ │ ├── util │ │ │ │ ├── GlVendorUtil.java │ │ │ │ ├── BufferSlice.java │ │ │ │ ├── MemoryTracker.java │ │ │ │ ├── GlFogHelper.java │ │ │ │ └── GlMultiDrawBatch.java │ │ │ ├── shader │ │ │ │ ├── ShaderType.java │ │ │ │ ├── ShaderConstants.java │ │ │ │ └── ShaderLoader.java │ │ │ ├── buffer │ │ │ │ ├── VertexData.java │ │ │ │ ├── GlMutableBuffer.java │ │ │ │ └── GlBuffer.java │ │ │ ├── arena │ │ │ │ └── GlBufferRegion.java │ │ │ ├── sampler │ │ │ │ └── GlSampler.java │ │ │ ├── array │ │ │ │ └── GlVertexArray.java │ │ │ ├── attribute │ │ │ │ └── GlVertexAttributeFormat.java │ │ │ ├── GlObject.java │ │ │ └── func │ │ │ │ ├── GlInstancedArrayFunctions.java │ │ │ │ ├── GlIndirectMultiDrawFunctions.java │ │ │ │ ├── GlFunctions.java │ │ │ │ ├── GlBufferCopyFunctions.java │ │ │ │ └── GlVertexArrayFunctions.java │ │ └── SodiumClientMod.java │ │ ├── common │ │ ├── util │ │ │ ├── ListUtil.java │ │ │ ├── collections │ │ │ │ ├── DequeDrain.java │ │ │ │ └── FutureDequeDrain.java │ │ │ ├── DirectionUtil.java │ │ │ └── pool │ │ │ │ └── ReusableObject.java │ │ └── config │ │ │ └── Option.java │ │ └── mixin │ │ ├── features │ │ ├── entity │ │ │ ├── fast_render │ │ │ │ └── MixinCuboid.java │ │ │ ├── shadow_clipping │ │ │ │ └── MixinEntityRenderDispatcher.java │ │ │ └── smooth_lighting │ │ │ │ └── MixinEntityRenderer.java │ │ ├── options │ │ │ ├── MixinInGameHud.java │ │ │ ├── MixinMinecraftClient.java │ │ │ ├── MixinWorldRenderer.java │ │ │ ├── MixinOptionsScreen.java │ │ │ └── MixinGameOptions.java │ │ ├── chunk_rendering │ │ │ ├── MixinLightmapTextureManager.java │ │ │ ├── MixinChunkBuilder.java │ │ │ └── MixinClientWorld.java │ │ ├── texture_tracking │ │ │ └── MixinSpriteIdentifier.java │ │ ├── render_layer │ │ │ └── MixinRenderLayers.java │ │ ├── block │ │ │ ├── MixinBufferBuilder.java │ │ │ └── MixinWorldRenderer.java │ │ ├── matrix_stack │ │ │ ├── MixinMatrixStack.java │ │ │ └── MixinVertexConsumer.java │ │ ├── buffer_builder │ │ │ ├── intrinsics │ │ │ │ └── MixinSpriteTexturedVertexConsumer.java │ │ │ └── fast_advance │ │ │ │ └── MixinBufferBuilder.java │ │ ├── gui │ │ │ └── font │ │ │ │ └── MixinGlyphRenderer.java │ │ └── model │ │ │ └── MixinMultipartBakedModel.java │ │ └── core │ │ ├── model │ │ ├── MixinBlockColors.java │ │ └── MixinItemColors.java │ │ └── pipeline │ │ └── MixinVertexConsumer.java │ └── dev │ └── hanetzer │ └── chlorine │ ├── plugin │ └── ftb │ │ └── FTBChunksChecker.java │ └── common │ └── Chlorine.java ├── settings.gradle ├── lombok.config ├── .github ├── FUNDING.yml ├── workflows │ ├── gradle.yml │ └── publish.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── crash-report.md │ └── bug_report.md └── PULL_REQUEST_TEMPLATE │ ├── new_feature.md │ └── bug_fix.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── changelog.txt ├── gradle.properties ├── idea └── inspections.xml └── gradlew.bat /src/.gitignore: -------------------------------------------------------------------------------- 1 | jmh -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Chlorine' 2 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | # This file is generated by the 'io.freefair.lombok' Gradle plugin 2 | config.stopBubbling = true 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: jellysquid3 4 | patreon: jellysquid 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalogenMods/Chlorine/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/assets/sodium/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalogenMods/Chlorine/HEAD/src/main/resources/assets/sodium/icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/sodium/textures/gui/arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalogenMods/Chlorine/HEAD/src/main/resources/assets/sodium/textures/gui/arrows.png -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/LightMode.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light; 2 | 3 | public enum LightMode { 4 | SMOOTH, 5 | FLAT 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/TextProvider.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | public interface TextProvider { 4 | String getLocalizedName(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/texture/SpriteExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.texture; 2 | 3 | public interface SpriteExtended { 4 | void markActive(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/task/CancellationSource.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.task; 2 | 3 | public interface CancellationSource { 4 | boolean isCancelled(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/WorldRenderPhase.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes; 2 | 3 | public enum WorldRenderPhase { 4 | OPAQUE, 5 | TRANSLUCENT 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/OptionStorage.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.storage; 2 | 3 | public interface OptionStorage { 4 | T getData(); 5 | 6 | void save(); 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/OptionFlag.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | public enum OptionFlag { 4 | REQUIRES_RENDERER_RELOAD, 5 | REQUIRES_ASSET_RELOAD, 6 | REQUIRES_GAME_RESTART 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gradle 2 | 3 | .gradle/ 4 | build/ 5 | out/ 6 | classes/ 7 | 8 | # idea 9 | 10 | .idea/ 11 | *.iml 12 | *.ipr 13 | *.iws 14 | 15 | # vscode 16 | 17 | .settings/ 18 | .vscode/ 19 | bin/ 20 | .classpath 21 | .project 22 | 23 | # fabric 24 | 25 | run/ 26 | logs/ -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/binding/OptionBinding.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.binding; 2 | 3 | public interface OptionBinding { 4 | void setValue(S storage, T value); 5 | 6 | T getValue(S storage); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/math/FrustumExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.math; 2 | 3 | public interface FrustumExtended { 4 | boolean fastAabbTest(float minX, float minY, float minZ, float maxX, float maxY, float maxZ); 5 | } 6 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | 0.0.2: 2 | New 3 | - Update forge & mantle to new RB 4 | - Rename sodium mixin to chlorine to prevent confusion 5 | 6 | 0.0.1: 7 | Fixes 8 | - Tinting & rendering of non-vanilla fluids 9 | - DoubleSlabs mod models 10 | 11 | 0.0.0: 12 | New 13 | - Initial forge port 14 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/texture/ChunkProgramTextureUnit.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader.texture; 2 | 3 | public enum ChunkProgramTextureUnit { 4 | BLOCK_ATLAS, 5 | BLOCK_ATLAS_MIPPED, 6 | LIGHT_TEX 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/ModelCuboidAccessor.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model; 2 | 3 | import net.minecraft.client.renderer.model.ModelRenderer; 4 | 5 | public interface ModelCuboidAccessor { 6 | ModelRenderer.TexturedQuad[] getQuads(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "Chlorine resources", 4 | "pack_format": 6, 5 | "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListenerManager.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world; 2 | 3 | public interface ChunkStatusListenerManager { 4 | // TODO: allow multiple listeners to be added? 5 | void setListener(ChunkStatusListener listener); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/ClientWorldExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world; 2 | 3 | public interface ClientWorldExtended { 4 | /** 5 | * @return The world seed used for generating biome data on the client 6 | */ 7 | long getBiomeSeed(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/texture/LightmapTextureManagerAccessor.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader.texture; 2 | 3 | import net.minecraft.client.renderer.texture.Texture; 4 | 5 | public interface LightmapTextureManagerAccessor { 6 | Texture getTexture(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/sink/ModelQuadSinkDelegate.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.sink; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; 4 | 5 | public interface ModelQuadSinkDelegate { 6 | ModelQuadSink get(ModelQuadFacing facing); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/lists/ChunkRenderListIterator.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.lists; 2 | 3 | public interface ChunkRenderListIterator { 4 | T getGraphicsState(); 5 | int getVisibleFaces(); 6 | 7 | boolean hasNext(); 8 | void advance(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/biome/ItemColorsExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world.biome; 2 | 3 | import net.minecraft.client.renderer.color.IItemColor; 4 | import net.minecraft.item.ItemStack; 5 | 6 | public interface ItemColorsExtended { 7 | IItemColor getColorProvider(ItemStack stack); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/biome/BlockColorsExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world.biome; 2 | 3 | import net.minecraft.block.BlockState; 4 | import net.minecraft.client.renderer.color.IBlockColor; 5 | 6 | public interface BlockColorsExtended { 7 | IBlockColor getColorProvider(BlockState state); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/consumer/GlyphVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.consumer; 2 | 3 | import net.minecraft.util.math.vector.Matrix4f; 4 | 5 | public interface GlyphVertexConsumer { 6 | void vertexGlyph(Matrix4f matrix, float x, float y, float z, int color, float u, float v, int light); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/util/GlVendorUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.util; 2 | 3 | import org.lwjgl.opengl.GL11; 4 | 5 | import java.util.Objects; 6 | 7 | public class GlVendorUtil { 8 | public static boolean matches(String vendor) { 9 | return Objects.equals(GL11.glGetString(GL11.GL_VENDOR), vendor); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/MathUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util; 2 | 3 | public class MathUtil { 4 | /** 5 | * @return True if the specified number is greater than zero and is a power of two, otherwise false 6 | */ 7 | public static boolean isPowerOfTwo(int n) { 8 | return ((n & (n - 1)) == 0); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dev/hanetzer/chlorine/plugin/ftb/FTBChunksChecker.java: -------------------------------------------------------------------------------- 1 | package dev.hanetzer.chlorine.plugin.ftb; 2 | 3 | import com.feed_the_beast.mods.ftbchunks.client.FTBChunksClient; 4 | import net.minecraft.util.math.ChunkPos; 5 | 6 | public class FTBChunksChecker { 7 | public static void queueChunk(int x, int z) { 8 | FTBChunksClient.rerenderCache.add(new ChunkPos(x, z)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/resources/sodium.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | 3 | accessible class net/minecraft/client/model/ModelPart$Vertex 4 | accessible class net/minecraft/client/model/ModelPart$Quad 5 | accessible class net/minecraft/client/texture/Sprite$Interpolation 6 | 7 | accessible method net/minecraft/client/texture/Sprite$Interpolation apply ()V 8 | accessible method net/minecraft/client/render/Frustum isVisible (DDDDDD)Z -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/entity/EntityLightSampler.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.entity; 2 | 3 | import net.minecraft.entity.Entity; 4 | import net.minecraft.util.math.BlockPos; 5 | 6 | public interface EntityLightSampler { 7 | int bridge$getBlockLight(T entity, BlockPos pos); 8 | 9 | int bridge$getSkyLight(T entity, BlockPos pos); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/control/Control.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.control; 2 | 3 | import me.jellysquid.mods.sodium.client.gui.options.Option; 4 | import me.jellysquid.mods.sodium.client.util.Dim2i; 5 | 6 | public interface Control { 7 | Option getOption(); 8 | 9 | ControlElement createElement(Dim2i dim); 10 | 11 | int getMaxWidth(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/texture/SpriteUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.texture; 2 | 3 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 4 | 5 | public class SpriteUtil { 6 | public static void markSpriteActive(TextureAtlasSprite sprite) { 7 | if (sprite instanceof SpriteExtended) { 8 | ((SpriteExtended) sprite).markActive(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/ShaderComponent.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.shader.GlProgram; 4 | 5 | public interface ShaderComponent { 6 | void bind(); 7 | void unbind(); 8 | void delete(); 9 | 10 | interface Factory { 11 | C create(S shader); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/shader/ShaderType.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.shader; 2 | 3 | import org.lwjgl.opengl.GL20; 4 | 5 | /** 6 | * An enumeration over the supported OpenGL shader types. 7 | */ 8 | public enum ShaderType { 9 | VERTEX(GL20.GL_VERTEX_SHADER), 10 | FRAGMENT(GL20.GL_FRAGMENT_SHADER); 11 | 12 | public final int id; 13 | 14 | ShaderType(int id) { 15 | this.id = id; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/ChunkProgramComponentBuilder.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.shader.texture.ChunkProgramTextureComponent; 4 | 5 | public class ChunkProgramComponentBuilder { 6 | public ShaderComponent.Factory texture; 7 | public ShaderComponent.Factory fog; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/accesstransformer.cfg: -------------------------------------------------------------------------------- 1 | public net.minecraft.client.renderer.culling.ClippingHelper func_228953_a_(DDDDDD)Z #isBoxInFrustum 2 | 3 | public net.minecraft.client.renderer.model.ModelRenderer$PositionTextureVertex 4 | public net.minecraft.client.renderer.model.ModelRenderer$TexturedQuad 5 | 6 | public net.minecraft.client.renderer.texture.TextureAtlasSprite$InterpolationData 7 | public net.minecraft.client.renderer.texture.TextureAtlasSprite$InterpolationData func_229257_a_()V #uploadInterpolated -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/util/ListUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.util; 2 | 3 | import java.util.Collection; 4 | 5 | public class ListUtil { 6 | public static void updateList(Collection collection, Collection before, Collection after) { 7 | if (!before.isEmpty()) { 8 | collection.removeAll(before); 9 | } 10 | 11 | if (!after.isEmpty()) { 12 | collection.addAll(after); 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/smooth/AoCompletionFlags.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light.smooth; 2 | 3 | /** 4 | * Bit flags to indicate which light properties have been computed for a given face. 5 | */ 6 | class AoCompletionFlags { 7 | /** 8 | * The light data has been retrieved from the cache. 9 | */ 10 | public static final int HAS_LIGHT_DATA = 0b01; 11 | 12 | /** 13 | * The light data has been unpacked into normalized floating point values. 14 | */ 15 | public static final int HAS_UNPACKED_LIGHT_DATA = 0b10; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/util/collections/DequeDrain.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.util.collections; 2 | 3 | import java.util.Deque; 4 | import java.util.Iterator; 5 | 6 | public class DequeDrain implements Iterator { 7 | private final Deque deque; 8 | 9 | public DequeDrain(Deque deque) { 10 | this.deque = deque; 11 | } 12 | 13 | @Override 14 | public boolean hasNext() { 15 | return !this.deque.isEmpty(); 16 | } 17 | 18 | @Override 19 | public T next() { 20 | return this.deque.remove(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/buffer/VertexData.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.buffer; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | /** 8 | * Helper type for tagging the vertex format alongside the raw buffer data. 9 | */ 10 | public class VertexData { 11 | public final GlVertexFormat format; 12 | public final ByteBuffer buffer; 13 | 14 | public VertexData(ByteBuffer buffer, GlVertexFormat format) { 15 | this.format = format; 16 | this.buffer = buffer; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Java CI with Gradle 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Set up JDK 8 12 | uses: actions/setup-java@v1 13 | with: 14 | java-version: 8 15 | - name: Grant execute permission for gradlew 16 | run: chmod +x gradlew 17 | - name: Build with Gradle 18 | run: ./gradlew build 19 | - name: Upload build artifacts 20 | uses: actions/upload-artifact@v1 21 | with: 22 | name: build-artifacts 23 | path: build/libs 24 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/data/QuadLightData.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light.data; 2 | 3 | /** 4 | * Stores the computed light data for a block model quad. The vertex order of each array is defined as that of the 5 | * quad's vertex order. 6 | */ 7 | public class QuadLightData { 8 | /** 9 | * The brightness of each vertex in the quad as normalized floats. 10 | */ 11 | public final float[] br = new float[4]; 12 | 13 | /** 14 | * The lightmap texture coordinates for each vertex in the quad. 15 | */ 16 | public final int[] lm = new int[4]; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/arena/GlBufferRegion.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.arena; 2 | 3 | public class GlBufferRegion { 4 | private final GlBufferArena arena; 5 | private final int start; 6 | private final int len; 7 | 8 | GlBufferRegion(GlBufferArena arena, int start, int len) { 9 | this.arena = arena; 10 | this.start = start; 11 | this.len = len; 12 | } 13 | 14 | public int getStart() { 15 | return this.start; 16 | } 17 | 18 | public int getLength() { 19 | return this.len; 20 | } 21 | 22 | public void delete() { 23 | this.arena.free(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/pipeline/RenderContextCommon.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.pipeline; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.blender.BiomeColorBlender; 4 | import me.jellysquid.mods.sodium.client.model.quad.blender.FlatBiomeColorBlender; 5 | import me.jellysquid.mods.sodium.client.model.quad.blender.SmoothBiomeColorBlender; 6 | import net.minecraft.client.Minecraft; 7 | 8 | public class RenderContextCommon { 9 | public static BiomeColorBlender createBiomeColorBlender() { 10 | return Minecraft.getInstance().gameSettings.biomeBlendRadius <= 0 ? new FlatBiomeColorBlender() : new SmoothBiomeColorBlender(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/util/BufferSlice.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.util; 2 | 3 | public class BufferSlice { 4 | public final int start, len; 5 | 6 | public BufferSlice(int start, int len) { 7 | this.start = start; 8 | this.len = len; 9 | } 10 | 11 | public static long pack(int start, int len) { 12 | return (long) start & 0xffffffffL | ((long) len & 0xffffffffL) << 32; 13 | } 14 | 15 | public static int unpackStart(long slice) { 16 | return (int) (slice & 0xffffffffL); 17 | } 18 | 19 | public static int unpackLength(long slice) { 20 | return (int) (slice >>> 32 & 0xffffffffL); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkGraphicsState.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk; 2 | 3 | public abstract class ChunkGraphicsState { 4 | private final int x, y, z; 5 | 6 | protected ChunkGraphicsState(ChunkRenderContainer container) { 7 | this.x = container.getRenderX(); 8 | this.y = container.getRenderY(); 9 | this.z = container.getRenderZ(); 10 | } 11 | 12 | public abstract void delete(); 13 | 14 | public int getX() { 15 | return this.x; 16 | } 17 | 18 | public int getY() { 19 | return this.y; 20 | } 21 | 22 | public int getZ() { 23 | return this.z; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/util/collections/FutureDequeDrain.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.util.collections; 2 | 3 | import java.util.Deque; 4 | import java.util.Iterator; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | public class FutureDequeDrain implements Iterator { 8 | private final Deque> deque; 9 | 10 | public FutureDequeDrain(Deque> deque) { 11 | this.deque = deque; 12 | } 13 | 14 | @Override 15 | public boolean hasNext() { 16 | return !this.deque.isEmpty(); 17 | } 18 | 19 | @Override 20 | public T next() { 21 | return this.deque.remove().join(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/entity/fast_render/MixinCuboid.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.entity.fast_render; 2 | 3 | import me.jellysquid.mods.sodium.client.model.ModelCuboidAccessor; 4 | import net.minecraft.client.renderer.model.ModelRenderer; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | 9 | @Mixin(ModelRenderer.ModelBox.class) 10 | public class MixinCuboid implements ModelCuboidAccessor { 11 | @Shadow 12 | @Final 13 | private ModelRenderer.TexturedQuad[] quads; 14 | 15 | @Override 16 | public ModelRenderer.TexturedQuad[] getQuads() { 17 | return this.quads; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/color/ColorU8.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.color; 2 | 3 | public interface ColorU8 { 4 | /** 5 | * The maximum value of a color component. 6 | */ 7 | float COMPONENT_RANGE = 255.0f; 8 | 9 | /** 10 | * Constant value which can be multiplied with a floating-point color component to get the normalized value. The 11 | * multiplication is slightly faster than a floating point division, and this code is a hot path which justifies it. 12 | */ 13 | float NORM = 1.0f / COMPONENT_RANGE; 14 | 15 | /** 16 | * Normalizes a color component to the range of 0..1. 17 | */ 18 | static float normalize(float v) { 19 | return v * NORM; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/util/DirectionUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.util; 2 | 3 | import net.minecraft.util.Direction; 4 | 5 | /** 6 | * Contains a number of cached arrays to avoid allocations since calling Enum#values() requires the backing array to 7 | * be cloned every time. 8 | */ 9 | public class DirectionUtil { 10 | public static final Direction[] ALL_DIRECTIONS = Direction.values(); 11 | public static final int DIRECTION_COUNT = ALL_DIRECTIONS.length; 12 | 13 | // Provides the same order as enumerating Direction and checking the axis of each value 14 | public static final Direction[] HORIZONTAL_DIRECTIONS = new Direction[] { Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST }; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/options/MixinInGameHud.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.options; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import net.minecraft.client.gui.IngameGui; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | @Mixin(IngameGui.class) 11 | public class MixinInGameHud { 12 | @Redirect(method = "renderIngameGui", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;isFancyGraphicsEnabled()Z")) 13 | private boolean redirectFancyGraphicsVignette() { 14 | return Config.CLIENT.enableVignette.get(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Done to increase the memory available to gradle. 2 | org.gradle.jvmargs=-Xmx3G 3 | org.gradle.daemon=false 4 | 5 | mod_version=0.0.1 6 | minecraft_min=1.16.2 7 | minecraft_version=1.16.5 8 | minecraft_max=1.17 9 | 10 | # Mod Properties 11 | sodium_version=0.1.0 12 | 13 | # Forge Version Information 14 | javafml_min=33.0 15 | javafml_max=35.0 16 | forge_min=33.0.61 17 | forge_version=36.0.22 18 | forge_max=37.0.0 19 | 20 | # Mappings Information 21 | mappings_version=20201028-1.16.3 22 | 23 | # Build Dependencies 24 | fluidtests_version=0.0.0.+ 25 | mantle_version=1.6.79 26 | 27 | # JEI 28 | jei_version=7.6.1.71 29 | 30 | # FTB-Chunks 31 | ftb_chunks_version=1.1.2.36 32 | 33 | # Curse information 34 | curse_type=beta 35 | projectId=408362 36 | github_project=HalogenMods/Chlorine 37 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListener.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world; 2 | 3 | /** 4 | * Defines a listener that can be attached to a world's chunk manager to receive chunk load and unload events. 5 | */ 6 | public interface ChunkStatusListener { 7 | /** 8 | * Called after a chunk is added to the world and loaded. 9 | * @param x The x-coordinate of the loaded chunk 10 | * @param z The z-coordinate of the loaded chunk 11 | */ 12 | void onChunkAdded(int x, int z); 13 | 14 | /** 15 | * Called after a chunk is removed from the world and unloaded. 16 | * @param x The x-coordiante of the unloaded chunk 17 | * @param z The z-coordinate of the unloaded chunk 18 | */ 19 | void onChunkRemoved(int x, int z); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/Option.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | import me.jellysquid.mods.sodium.client.gui.options.control.Control; 4 | import me.jellysquid.mods.sodium.client.gui.options.storage.OptionStorage; 5 | import net.minecraft.util.text.ITextComponent; 6 | 7 | import java.util.Collection; 8 | 9 | public interface Option { 10 | String getName(); 11 | 12 | ITextComponent getTooltip(); 13 | 14 | Control getControl(); 15 | 16 | T getValue(); 17 | 18 | void setValue(T value); 19 | 20 | void reset(); 21 | 22 | OptionStorage getStorage(); 23 | 24 | boolean isAvailable(); 25 | 26 | boolean hasChanged(); 27 | 28 | void applyChanges(); 29 | 30 | Collection getFlags(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/binding/GenericBinding.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.binding; 2 | 3 | import java.util.function.BiConsumer; 4 | import java.util.function.Function; 5 | 6 | public class GenericBinding implements OptionBinding { 7 | private final BiConsumer setter; 8 | private final Function getter; 9 | 10 | public GenericBinding(BiConsumer setter, Function getter) { 11 | this.setter = setter; 12 | this.getter = getter; 13 | } 14 | 15 | @Override 16 | public void setValue(S storage, T value) { 17 | this.setter.accept(storage, value); 18 | } 19 | 20 | @Override 21 | public T getValue(S storage) { 22 | return this.getter.apply(storage); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/options/MixinMinecraftClient.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.options; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; 6 | import net.minecraft.client.Minecraft; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | 10 | @Mixin(Minecraft.class) 11 | public class MixinMinecraftClient { 12 | /** 13 | * @author JellySquid 14 | * @reason Make ambient occlusion user configurable 15 | */ 16 | @Overwrite 17 | public static boolean isAmbientOcclusionEnabled() { 18 | return Config.CLIENT.smoothLighting.get() != SodiumGameOptions.LightingQuality.OFF; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout sources 13 | uses: actions/checkout@v2 14 | - name: Set up JDK 8 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 8 18 | - name: Grant execute permission for gradlew 19 | run: chmod +x gradlew 20 | - name: Upload assets to CurseForge 21 | run: ./gradlew build 22 | env: 23 | BUILD_RELEASE: ${{ github.event.prerelease == false }} 24 | - name: Upload assets to GitHub 25 | uses: AButler/upload-release-assets@v2.0 26 | with: 27 | files: 'build/libs/*;LICENSE' 28 | repo-token: ${{ secrets.GITHUB_TOKEN }} 29 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/multidraw/ChunkProgramMultiDraw.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.multidraw; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgram; 4 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgramComponentBuilder; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | public class ChunkProgramMultiDraw extends ChunkProgram { 8 | private final int dModelOffset; 9 | 10 | public ChunkProgramMultiDraw(ResourceLocation name, int handle, ChunkProgramComponentBuilder components) { 11 | super(name, handle, components); 12 | 13 | this.dModelOffset = this.getAttributeLocation("d_ModelOffset"); 14 | } 15 | 16 | public int getModelOffsetAttributeLocation() { 17 | return this.dModelOffset; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/options/MixinWorldRenderer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.options; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.renderer.WorldRenderer; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | @Mixin(WorldRenderer.class) 11 | public class MixinWorldRenderer { 12 | @Redirect(method = "renderRainSnow", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;isFancyGraphicsEnabled()Z")) 13 | private boolean redirectGetFancyWeather() { 14 | return Config.CLIENT.weatherQuality.get().isFancy(Minecraft.getInstance().gameSettings.graphicFanciness); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/sink/ModelQuadSink.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.sink; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadViewMutable; 4 | 5 | /** 6 | * A "sink" interface which model quads can be written to for rendering. This is used as to provide an abstraction 7 | * over the various buffers and targets used by the game. The implementation may perform additional transformations 8 | * to the quad data which is passed to it. 9 | */ 10 | public interface ModelQuadSink { 11 | /** 12 | * Writes the specified quad to the sink. The implementation may transformed the input given to it to avoid memory 13 | * copies and allocations, and as such, the input {@param quad} will be undefined after calling this method. 14 | */ 15 | void write(ModelQuadViewMutable quad); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/consumer/ParticleVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.consumer; 2 | 3 | public interface ParticleVertexConsumer { 4 | /** 5 | * Writes a vertex directly into the consumer with no additional processing. This requires callers to do some 6 | * upfront work to encode their values. 7 | * 8 | * @param x The x-position of the vertex 9 | * @param y The y-position of the vertex 10 | * @param z The z-position of the vertex 11 | * @param u The u-position of the texture 12 | * @param v The v-position of the texture 13 | * @param color The color of the vertex in little-endian RGBA format 14 | * @param light The light of the vertex 15 | */ 16 | void vertexParticle(float x, float y, float z, float u, float v, int color, int light); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkCameraContext.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk; 2 | 3 | public class ChunkCameraContext { 4 | public final int blockOriginX, blockOriginY, blockOriginZ; 5 | public final float originX, originY, originZ; 6 | 7 | public ChunkCameraContext(double x, double y, double z) { 8 | this.blockOriginX = (int) x; 9 | this.blockOriginY = (int) y; 10 | this.blockOriginZ = (int) z; 11 | 12 | this.originX = (float) (x - this.blockOriginX); 13 | this.originY = (float) (y - this.blockOriginY); 14 | this.originZ = (float) (z - this.blockOriginZ); 15 | } 16 | 17 | public float getChunkModelOffset(int chunkBlockPos, int cameraBlockPos, float cameraPos) { 18 | int t = chunkBlockPos - cameraBlockPos; 19 | return t - cameraPos; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/MinecraftOptionsStorage.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.storage; 2 | 3 | import dev.hanetzer.chlorine.common.Chlorine; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import net.minecraft.client.GameSettings; 6 | import net.minecraft.client.Minecraft; 7 | 8 | public class MinecraftOptionsStorage implements OptionStorage { 9 | private final Minecraft client; 10 | 11 | public MinecraftOptionsStorage() { 12 | this.client = Minecraft.getInstance(); 13 | } 14 | 15 | @Override 16 | public GameSettings getData() { 17 | return this.client.gameSettings; 18 | } 19 | 20 | @Override 21 | public void save() { 22 | this.getData().saveOptions(); 23 | 24 | Chlorine.log.info("Flushed changes to Minecraft configuration"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/impl/TranslucentRenderPass.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes.impl; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockLayer; 4 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; 5 | import net.minecraft.client.renderer.RenderType; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | public class TranslucentRenderPass extends BlockRenderPass { 9 | public TranslucentRenderPass(int ordinal, ResourceLocation id, BlockLayer... layers) { 10 | super(ordinal, id, false, layers); 11 | } 12 | 13 | @Override 14 | public void beginRender() { 15 | RenderType.getTranslucent().setupRenderState(); 16 | } 17 | 18 | @Override 19 | public void endRender() { 20 | RenderType.getTranslucent().clearRenderState(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/chunk_rendering/MixinLightmapTextureManager.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.chunk_rendering; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.shader.texture.LightmapTextureManagerAccessor; 4 | import net.minecraft.client.renderer.LightTexture; 5 | import net.minecraft.client.renderer.texture.DynamicTexture; 6 | import net.minecraft.client.renderer.texture.Texture; 7 | import org.spongepowered.asm.mixin.Final; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | @Mixin(LightTexture.class) 12 | public class MixinLightmapTextureManager implements LightmapTextureManagerAccessor { 13 | @Shadow 14 | @Final 15 | private DynamicTexture dynamicTexture; 16 | 17 | @Override 18 | public Texture getTexture() { 19 | return this.dynamicTexture; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/binding/compat/VanillaBooleanOptionBinding.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.binding.compat; 2 | 3 | import me.jellysquid.mods.sodium.client.gui.options.binding.OptionBinding; 4 | import net.minecraft.client.GameSettings; 5 | import net.minecraft.client.settings.BooleanOption; 6 | 7 | public class VanillaBooleanOptionBinding implements OptionBinding { 8 | private final BooleanOption option; 9 | 10 | public VanillaBooleanOptionBinding(BooleanOption option) { 11 | this.option = option; 12 | } 13 | 14 | @Override 15 | public void setValue(GameSettings storage, Boolean value) { 16 | this.option.set(storage, value.toString()); 17 | } 18 | 19 | @Override 20 | public Boolean getValue(GameSettings storage) { 21 | return this.option.get(storage); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/OptionImpact.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | import net.minecraft.client.resources.I18n; 4 | import net.minecraft.util.text.TextFormatting; 5 | 6 | public enum OptionImpact { 7 | LOW(TextFormatting.GREEN, "sodium.option_impact.low"), 8 | MEDIUM(TextFormatting.YELLOW, "sodium.option_impact.medium"), 9 | HIGH(TextFormatting.GOLD, "sodium.option_impact.high"), 10 | EXTREME(TextFormatting.RED, "sodium.option_impact.extreme"), 11 | VARIES(TextFormatting.WHITE, "sodium.option_impact.varies"); 12 | 13 | private final TextFormatting color; 14 | private final String text; 15 | 16 | OptionImpact(TextFormatting color, String text) { 17 | this.color = color; 18 | this.text = text; 19 | } 20 | 21 | public String toDisplayString() { 22 | return this.color + I18n.format(this.text); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/ModelQuadEncoder.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * This interface is responsible for encoding model codes into a given vertex format which can then be passed to 7 | * the graphics card for rendering. This allows multiple alternative vertex format encodings to be used when the 8 | * hardware supports it without calling code being aware of the detail. 9 | */ 10 | public interface ModelQuadEncoder { 11 | /** 12 | * @param quad The quad data to write 13 | * @param buffer The buffer to write the encoded vertex data into 14 | * @param position The starting byte position from which the vertex data should be written into the buffer 15 | * @param mipped True if the quad is mipped 16 | */ 17 | void write(ModelQuadView quad, ByteBuffer buffer, int position, boolean mipped); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/SodiumOptionsStorage.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.storage; 2 | 3 | import dev.hanetzer.chlorine.common.Chlorine; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; 6 | 7 | public class SodiumOptionsStorage implements OptionStorage { 8 | // private final SodiumGameOptions options; 9 | 10 | public SodiumOptionsStorage() { 11 | // this.options = SodiumClientMod.options(); 12 | } 13 | 14 | @Override 15 | public SodiumGameOptions getData() { 16 | // return this.options; 17 | return null; 18 | } 19 | 20 | @Override 21 | public void save() { 22 | // this.options.writeChanges(); 23 | // this.options.notifyListeners(); 24 | 25 | Chlorine.log.info("Flushed changes to Sodium configuration"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/sampler/GlSampler.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.sampler; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.GlObject; 4 | import me.jellysquid.mods.sodium.client.gl.func.GlFunctions; 5 | 6 | public class GlSampler extends GlObject { 7 | public GlSampler() { 8 | this.setHandle(GlFunctions.SAMPLER.glGenSamplers()); 9 | } 10 | 11 | public void setParameter(int param, int value) { 12 | GlFunctions.SAMPLER.glSamplerParameteri(this.handle(), param, value); 13 | } 14 | 15 | public void bindToTextureUnit(int unit) { 16 | GlFunctions.SAMPLER.glBindSampler(unit, this.handle()); 17 | } 18 | 19 | public void unbindFromTextureUnit(int unit) { 20 | GlFunctions.SAMPLER.glBindSampler(unit, 0); 21 | } 22 | 23 | public void delete() { 24 | GlFunctions.SAMPLER.glDeleteSamplers(this.handle()); 25 | 26 | this.invalidateHandle(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[${javafml_min},${javafml_max})" 3 | issueTrackerURL="http://github.com/HalogenMods/Chlorine/issues" 4 | license="GNU Lesser General Public License v3.0" 5 | 6 | [[mods]] 7 | modId="chlorine" 8 | version="${version}" 9 | displayName="Chlorine" 10 | authors="JellySquid, hanetzer" 11 | description=''' 12 | Chlorine is an free and open-source optimization mod for Minecraft which improves frame rates and reduces lag spikes. 13 | Based on Sodium version ${sodium_version} 14 | ''' 15 | credits="JellySquid, hanetzer" 16 | 17 | [[dependencies.chlorine]] 18 | modId="forge" 19 | mandatory=true 20 | versionRange="[${forge_min},${forge_max})" 21 | ordering="NONE" 22 | side="BOTH" 23 | 24 | [[dependency.chlorine]] 25 | modId="minecraft" 26 | mandatory=true 27 | versionRange="[${minecraft_min},${minecraft_max})" 28 | ordering="NONE" 29 | side="BOTH" -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildResult.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.compile; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 4 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 5 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; 6 | 7 | /** 8 | * The result of a chunk rebuild task which contains any and all data that needs to be processed or uploaded on 9 | * the main thread. If a task is cancelled after finishing its work and not before the result is processed, the result 10 | * will instead be discarded. 11 | */ 12 | public class ChunkBuildResult { 13 | public final ChunkRenderContainer render; 14 | public final ChunkRenderData data; 15 | 16 | public ChunkBuildResult(ChunkRenderContainer render, ChunkRenderData data) { 17 | this.render = render; 18 | this.data = data; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/chunk_rendering/MixinChunkBuilder.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.chunk_rendering; 2 | 3 | import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.At; 6 | import org.spongepowered.asm.mixin.injection.ModifyVariable; 7 | 8 | @Mixin(ChunkRenderDispatcher.class) 9 | public class MixinChunkBuilder { 10 | @ModifyVariable( 11 | method = "(Lnet/minecraft/world/World;Lnet/minecraft/client/renderer/WorldRenderer;Ljava/util/concurrent/Executor;ZLnet/minecraft/client/renderer/RegionRenderCacheBuilder;I)V", 12 | index = 10, at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Lists;newArrayListWithExpectedSize(I)Ljava/util/ArrayList;", remap = false)) 13 | private int modifyThreadPoolSize(int prev) { 14 | // Do not allow any resources to be allocated 15 | return 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/texture_tracking/MixinSpriteIdentifier.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.texture_tracking; 2 | 3 | import me.jellysquid.mods.sodium.client.render.texture.SpriteUtil; 4 | import net.minecraft.client.renderer.model.RenderMaterial; 5 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 10 | 11 | @Mixin(RenderMaterial.class) 12 | public class MixinSpriteIdentifier { 13 | @Inject(method = "getSprite", at = @At("RETURN")) 14 | private void preReturnSprite(CallbackInfoReturnable cir) { 15 | TextureAtlasSprite sprite = cir.getReturnValue(); 16 | 17 | if (sprite != null) { 18 | SpriteUtil.markSpriteActive(sprite); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "sodium", 4 | "version": "${version}", 5 | "name": "Sodium", 6 | "description": "Sodium is a free and open-source optimization mod for Minecraft which improves frame rates and reduces lag spikes.", 7 | "authors": [ 8 | "JellySquid" 9 | ], 10 | "contact": { 11 | "homepage": "https://jellysquid.me", 12 | "sources": "https://github.com/jellysquid3/sodium" 13 | }, 14 | "license": "LGPL-3.0-only", 15 | "icon": "assets/sodium/icon.png", 16 | "environment": "client", 17 | "entrypoints": { 18 | "client": [ 19 | "me.jellysquid.mods.sodium.client.SodiumClientMod" 20 | ] 21 | }, 22 | "custom": { 23 | "fabric-renderer-api-v1:contains_renderer": true 24 | }, 25 | "accessWidener": "sodium.accesswidener", 26 | "mixins": [ 27 | "sodium.mixins.json" 28 | ], 29 | "depends": { 30 | "fabricloader": ">=0.8.0" 31 | }, 32 | "breaks": { 33 | "optifabric": "*", 34 | "canvas": "*" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/new_feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug fix 3 | about: Use this template if you're creating a pull request which adds a feature or other enhancement 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Preface 11 | 12 | Please read our [Contributor Guidelines](https://github.com/jellysquid3/sodium-fabric/blob/1.15.x/CONTRIBUTING.md) before 13 | submitting any pull requests to this repository. 14 | 15 | By submitting a pull request, you are indicating that you agree to the [Contributor License Agreement](https://github.com/jellysquid3/sodium-fabric/blob/1.15.x/CONTRIBUTING.md#contributor-license-agreement-cla) 16 | and that your code will be licensed irrecoverably under the GNU LGPLv3. If you do not agree to these terms, do not open 17 | a pull request. 18 | 19 | Please remove this section before submitting your pull request. Doing so indicates that you have read and acknowledged it. 20 | 21 | ### Proposed Changes 22 | Provide a detailed description of what your pull request changes. 23 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/properties/ModelQuadFacing.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.properties; 2 | 3 | import net.minecraft.util.Direction; 4 | 5 | public enum ModelQuadFacing { 6 | UP, 7 | DOWN, 8 | EAST, 9 | WEST, 10 | SOUTH, 11 | NORTH, 12 | NONE; 13 | 14 | public static final ModelQuadFacing[] VALUES = ModelQuadFacing.values(); 15 | public static final int COUNT = VALUES.length; 16 | 17 | public static ModelQuadFacing fromDirection(Direction dir) { 18 | switch (dir) { 19 | case DOWN: 20 | return DOWN; 21 | case UP: 22 | return UP; 23 | case NORTH: 24 | return NORTH; 25 | case SOUTH: 26 | return SOUTH; 27 | case WEST: 28 | return WEST; 29 | case EAST: 30 | return EAST; 31 | default: 32 | return NONE; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/impl/SolidRenderPass.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes.impl; 2 | 3 | import com.mojang.blaze3d.systems.RenderSystem; 4 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockLayer; 5 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; 6 | import net.minecraft.client.renderer.RenderType; 7 | import net.minecraft.util.ResourceLocation; 8 | 9 | public class SolidRenderPass extends BlockRenderPass { 10 | public SolidRenderPass(int ordinal, ResourceLocation id, BlockLayer... layers) { 11 | super(ordinal, id, true, layers); 12 | } 13 | 14 | @Override 15 | public void beginRender() { 16 | RenderType.getSolid().setupRenderState(); 17 | 18 | RenderSystem.enableAlphaTest(); 19 | } 20 | 21 | @Override 22 | public void endRender() { 23 | RenderSystem.disableAlphaTest(); 24 | 25 | RenderType.getSolid().clearRenderState(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/buffer/GlMutableBuffer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.buffer; 2 | 3 | import org.lwjgl.opengl.GL15; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | /** 8 | * A mutable buffer type which is supported with OpenGL 1.5+. The buffer's storage can be reallocated at any time 9 | * without needing to re-create the buffer itself. 10 | */ 11 | public class GlMutableBuffer extends GlBuffer { 12 | private final int hints; 13 | 14 | public GlMutableBuffer(int hints) { 15 | this.hints = hints; 16 | } 17 | 18 | @Override 19 | public void upload(int target, ByteBuffer buf) { 20 | GL15.glBufferData(target, buf, this.hints); 21 | this.size = buf.capacity(); 22 | } 23 | 24 | @Override 25 | public void allocate(int target, int size) { 26 | GL15.glBufferData(target, size, this.hints); 27 | this.size = size; 28 | } 29 | 30 | public void invalidate(int target) { 31 | this.allocate(target, 0); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/util/MemoryTracker.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.util; 2 | 3 | public class MemoryTracker { 4 | private int allocated, used; 5 | 6 | public void onMemoryAllocate(int mem) { 7 | this.allocated += mem; 8 | } 9 | 10 | public void onMemoryRelease(int mem) { 11 | this.allocated -= mem; 12 | } 13 | 14 | public void onMemoryUse(int mem) { 15 | this.used += mem; 16 | } 17 | 18 | public void onMemoryFree(int mem) { 19 | this.used -= mem; 20 | } 21 | 22 | public int getUsedMemory() { 23 | return this.used; 24 | } 25 | 26 | public int getAllocatedMemory() { 27 | return this.allocated; 28 | } 29 | 30 | public void onMemoryAllocateAndUse(int mem) { 31 | this.onMemoryAllocate(mem); 32 | this.onMemoryUse(mem); 33 | } 34 | 35 | public void onMemoryFreeAndRelease(int mem) { 36 | this.onMemoryFree(mem); 37 | this.onMemoryRelease(mem); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/dev/hanetzer/chlorine/common/Chlorine.java: -------------------------------------------------------------------------------- 1 | package dev.hanetzer.chlorine.common; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import net.minecraftforge.common.MinecraftForge; 5 | import net.minecraftforge.fml.ModList; 6 | import net.minecraftforge.fml.ModLoadingContext; 7 | import net.minecraftforge.fml.common.Mod; 8 | import net.minecraftforge.fml.config.ModConfig; 9 | import org.apache.logging.log4j.LogManager; 10 | import org.apache.logging.log4j.Logger; 11 | 12 | @Mod(Chlorine.modID) 13 | @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) 14 | public class Chlorine { 15 | public static final String modID = "chlorine"; 16 | 17 | public static final Logger log = LogManager.getLogger(modID); 18 | 19 | public static boolean ftbChunksLoaded; 20 | public Chlorine() { 21 | ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.clientSpec); 22 | ftbChunksLoaded = ModList.get().isLoaded("ftbchunks"); 23 | MinecraftForge.EVENT_BUS.register(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/OptionPage.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | 5 | public class OptionPage { 6 | private final String name; 7 | private final ImmutableList groups; 8 | private final ImmutableList> options; 9 | 10 | public OptionPage(String name, ImmutableList groups) { 11 | this.name = name; 12 | this.groups = groups; 13 | 14 | ImmutableList.Builder> builder = ImmutableList.builder(); 15 | 16 | for (OptionGroup group : groups) { 17 | builder.addAll(group.getOptions()); 18 | } 19 | 20 | this.options = builder.build(); 21 | } 22 | 23 | public ImmutableList getGroups() { 24 | return this.groups; 25 | } 26 | 27 | public ImmutableList> getOptions() { 28 | return this.options; 29 | } 30 | 31 | public String getName() { 32 | return this.name; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/array/GlVertexArray.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.array; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.GlObject; 4 | import me.jellysquid.mods.sodium.client.gl.func.GlFunctions; 5 | 6 | /** 7 | * Provides Vertex Array functionality on supported platforms. 8 | */ 9 | public class GlVertexArray extends GlObject { 10 | public GlVertexArray() { 11 | if (!GlFunctions.isVertexArraySupported()) { 12 | throw new UnsupportedOperationException("Vertex arrays are unsupported on this platform"); 13 | } 14 | 15 | this.setHandle(GlFunctions.VERTEX_ARRAY.glGenVertexArrays()); 16 | } 17 | 18 | public void unbind() { 19 | GlFunctions.VERTEX_ARRAY.glBindVertexArray(0); 20 | } 21 | 22 | public void bind() { 23 | GlFunctions.VERTEX_ARRAY.glBindVertexArray(this.handle()); 24 | } 25 | 26 | public void delete() { 27 | GlFunctions.VERTEX_ARRAY.glDeleteVertexArrays(this.handle()); 28 | 29 | this.invalidateHandle(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/multidraw/StructBuffer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.multidraw; 2 | 3 | import org.lwjgl.system.MemoryUtil; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public abstract class StructBuffer { 8 | protected ByteBuffer buffer; 9 | protected int count; 10 | 11 | private boolean isBuilding; 12 | 13 | protected StructBuffer(int bytes) { 14 | this.buffer = MemoryUtil.memAlloc(bytes); 15 | } 16 | 17 | public int getCount() { 18 | return this.count; 19 | } 20 | 21 | public void begin() { 22 | this.buffer.clear(); 23 | this.count = 0; 24 | 25 | this.isBuilding = true; 26 | } 27 | 28 | public void end() { 29 | this.isBuilding = false; 30 | } 31 | 32 | public boolean isBuilding() { 33 | return this.isBuilding; 34 | } 35 | 36 | public ByteBuffer getBuffer() { 37 | return this.buffer; 38 | } 39 | 40 | public void delete() { 41 | MemoryUtil.memFree(this.buffer); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/blender/FlatBiomeColorBlender.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.blender; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; 4 | import me.jellysquid.mods.sodium.client.util.color.ColorARGB; 5 | import net.minecraft.block.BlockState; 6 | import net.minecraft.client.renderer.color.IBlockColor; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.world.IBlockDisplayReader; 9 | 10 | import java.util.Arrays; 11 | 12 | /** 13 | * A simple colorizer which performs no blending between adjacent blocks. 14 | */ 15 | public class FlatBiomeColorBlender implements BiomeColorBlender { 16 | private final int[] cachedRet = new int[4]; 17 | 18 | @Override 19 | public int[] getColors(IBlockColor colorizer, IBlockDisplayReader world, BlockState state, BlockPos origin, 20 | ModelQuadView quad) { 21 | Arrays.fill(this.cachedRet, ColorARGB.toABGR(colorizer.getColor(state, world, origin, quad.getColorIndex()))); 22 | 23 | return this.cachedRet; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/crash-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Crash report 3 | about: Use this template if your game is crashing or failing to start correctly 4 | title: '' 5 | labels: crash 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Reproduction Steps 11 | Provide information on how to reproduce this game crash. This step is critical for ensuring that your crash can be debugged by other developers. You can either fill in the example below or do something else -- just make sure your instructions are minimal and clear. If applicable, provide a Minecraft save containing a minimal example on how to reproduce this crash as a compressed ZIP file. 12 | 13 | 1. Place a Redstone Lamp beside a Redstone Repeater 14 | 2. Use a Lever to activate the Redstone Repeater 15 | 3. The game crashes 16 | 17 | ### Crash Report File 18 | Please upload your crash report as a file to [GitHub Gist](https://gist.github.com/) and replace this text with a link to the uploaded report. 19 | 20 | ### Additional Information 21 | Provide any additional information or context which may be relevant to the issue. If you have none to add, you can remove this section. 22 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/LightPipelineProvider.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; 4 | import me.jellysquid.mods.sodium.client.model.light.flat.FlatLightPipeline; 5 | import me.jellysquid.mods.sodium.client.model.light.smooth.SmoothLightPipeline; 6 | 7 | import java.util.EnumMap; 8 | 9 | public class LightPipelineProvider { 10 | private final EnumMap lighters = new EnumMap<>(LightMode.class); 11 | 12 | public LightPipelineProvider(LightDataAccess cache) { 13 | this.lighters.put(LightMode.SMOOTH, new SmoothLightPipeline(cache)); 14 | this.lighters.put(LightMode.FLAT, new FlatLightPipeline(cache)); 15 | } 16 | 17 | public LightPipeline getLighter(LightMode type) { 18 | LightPipeline pipeline = this.lighters.get(type); 19 | 20 | if (pipeline == null) { 21 | throw new NullPointerException("No lighter exists for mode: " + type.name()); 22 | } 23 | 24 | return pipeline; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/texture/ChunkProgramTextureComponent.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader.texture; 2 | 3 | import com.mojang.blaze3d.platform.GlStateManager; 4 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ShaderComponent; 5 | import net.minecraft.client.renderer.texture.Texture; 6 | import org.lwjgl.opengl.GL15; 7 | import org.lwjgl.opengl.GL20; 8 | 9 | public abstract class ChunkProgramTextureComponent implements ShaderComponent { 10 | protected void bindTexture(Texture texture, ChunkProgramTextureUnit unit) { 11 | if (texture == null) { 12 | throw new IllegalStateException("Texture is absent for unit: " + unit); 13 | } 14 | 15 | GlStateManager.activeTexture(GL15.GL_TEXTURE0 + unit.ordinal()); 16 | GlStateManager.bindTexture(texture.getGlTextureId()); 17 | } 18 | 19 | protected void bindUniform(int location, ChunkProgramTextureUnit unit) { 20 | GL20.glUniform1i(location, unit.ordinal()); 21 | } 22 | 23 | public abstract void setMipmapping(boolean mipped); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes; 2 | 3 | 4 | import net.minecraft.util.ResourceLocation; 5 | 6 | public abstract class BlockRenderPass { 7 | private final ResourceLocation id; 8 | private final BlockLayer[] layers; 9 | private final boolean forward; 10 | private final int ordinal; 11 | 12 | public BlockRenderPass(int ordinal, ResourceLocation id, boolean forward, BlockLayer... layers) { 13 | this.ordinal = ordinal; 14 | this.id = id; 15 | this.layers = layers; 16 | this.forward = forward; 17 | } 18 | 19 | public abstract void beginRender(); 20 | 21 | public abstract void endRender(); 22 | 23 | public final boolean isForwardRendering() { 24 | return this.forward; 25 | } 26 | 27 | public final int ordinal() { 28 | return this.ordinal; 29 | } 30 | 31 | public final BlockLayer[] getLayers() { 32 | return this.layers; 33 | } 34 | 35 | public final ResourceLocation getId() { 36 | return this.id; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/LightPipeline.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.data.QuadLightData; 4 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; 5 | import net.minecraft.util.Direction; 6 | import net.minecraft.util.math.BlockPos; 7 | 8 | /** 9 | * Light pipelines allow model quads for any location in the world to be lit using various backends, including fluids 10 | * and block entities. 11 | */ 12 | public interface LightPipeline { 13 | /** 14 | * Calculates the light data for a given block model quad, storing the result in {@param out}. 15 | * @param quad The block model quad 16 | * @param pos The block position of the model this quad belongs to 17 | * @param out The data arrays which will store the calculated light data results 18 | * @param face The pre-computed facing vector of the quad 19 | * @param shade True if the block is shaded by ambient occlusion 20 | */ 21 | void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction face, boolean shade); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.attribute; 2 | 3 | import org.lwjgl.opengl.GL11; 4 | 5 | /** 6 | * An enumeration over the supported data types that can be used for vertex attributes. 7 | */ 8 | public class GlVertexAttributeFormat { 9 | public static final GlVertexAttributeFormat FLOAT = new GlVertexAttributeFormat(GL11.GL_FLOAT, 4); 10 | public static final GlVertexAttributeFormat UNSIGNED_SHORT = new GlVertexAttributeFormat(GL11.GL_UNSIGNED_SHORT, 2); 11 | public static final GlVertexAttributeFormat UNSIGNED_BYTE = new GlVertexAttributeFormat(GL11.GL_UNSIGNED_BYTE, 1); 12 | public static final GlVertexAttributeFormat UNSIGNED_INT = new GlVertexAttributeFormat(GL11.GL_UNSIGNED_INT, 1); 13 | 14 | private final int glId; 15 | private final int size; 16 | 17 | private GlVertexAttributeFormat(int glId, int size) { 18 | this.glId = glId; 19 | this.size = size; 20 | } 21 | 22 | public int getSize() { 23 | return this.size; 24 | } 25 | 26 | public int getGlFormat() { 27 | return this.glId; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/impl/MultiTextureRenderPipeline.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes.impl; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockLayer; 4 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPassManager; 5 | import me.jellysquid.mods.sodium.client.render.chunk.passes.WorldRenderPhase; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | public class MultiTextureRenderPipeline { 9 | public static final ResourceLocation SOLID_PASS = new ResourceLocation("sodium", "multi_texture/solid"); 10 | public static final ResourceLocation TRANSLUCENT_PASS = new ResourceLocation("sodium", "multi_texture/translucent"); 11 | 12 | public static BlockRenderPassManager create() { 13 | BlockRenderPassManager registry = new BlockRenderPassManager(); 14 | registry.add(WorldRenderPhase.OPAQUE, SOLID_PASS, SolidRenderPass::new, BlockLayer.SOLID, BlockLayer.SOLID_MIPPED); 15 | registry.add(WorldRenderPhase.TRANSLUCENT, TRANSLUCENT_PASS, TranslucentRenderPass::new, BlockLayer.TRANSLUCENT_MIPPED); 16 | 17 | return registry; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bug_fix.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug fix 3 | about: Use this template if you're creating a pull request which fixes another bug or issue 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Preface 11 | 12 | Please read our [Contributor Guidelines](https://github.com/jellysquid3/sodium-fabric/blob/1.15.x/CONTRIBUTING.md) before 13 | submitting any pull requests to this repository. 14 | 15 | By submitting a pull request, you are indicating that you agree to the [Contributor License Agreement](https://github.com/jellysquid3/sodium-fabric/blob/1.15.x/CONTRIBUTING.md#contributor-license-agreement-cla) 16 | and that your code will be licensed irrecoverably under the GNU LGPLv3. If you do not agree to these terms, do not open 17 | a pull request. 18 | 19 | Please remove this section before submitting your pull request. Doing so indicates that you have read and acknowledged it. 20 | 21 | ### Linked Issues 22 | Provide links to the issue(s) which will be closed upon merging this pull request. There must be an open issue for 23 | pull requests which fix bugs or other issues. 24 | 25 | ### Proposed Changes 26 | Provide a detailed description of what your pull request changes. 27 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/math/Matrix3fExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.math; 2 | 3 | 4 | import net.minecraft.util.Direction; 5 | import net.minecraft.util.math.vector.Quaternion; 6 | import net.minecraft.util.math.vector.Vector3f; 7 | 8 | public interface Matrix3fExtended { 9 | /** 10 | * Applies the specified rotation to this matrix in-place. 11 | * 12 | * @param quaternion The quaternion to rotate this matrix by 13 | */ 14 | void rotate(Quaternion quaternion); 15 | 16 | int computeNormal(Direction dir); 17 | 18 | float transformVecX(float x, float y, float z); 19 | 20 | float transformVecY(float x, float y, float z); 21 | 22 | float transformVecZ(float x, float y, float z); 23 | 24 | default float transformVecX(Vector3f dir) { 25 | return this.transformVecX(dir.getX(), dir.getY(), dir.getZ()); 26 | } 27 | 28 | default float transformVecY(Vector3f dir) { 29 | return this.transformVecY(dir.getX(), dir.getY(), dir.getZ()); 30 | } 31 | 32 | default float transformVecZ(Vector3f dir) { 33 | return this.transformVecZ(dir.getX(), dir.getY(), dir.getZ()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/OptionGroup.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.apache.commons.lang3.Validate; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class OptionGroup { 10 | private final ImmutableList> options; 11 | 12 | private OptionGroup(ImmutableList> options) { 13 | this.options = options; 14 | } 15 | 16 | public static Builder createBuilder() { 17 | return new Builder(); 18 | } 19 | 20 | public ImmutableList> getOptions() { 21 | return this.options; 22 | } 23 | 24 | public static class Builder { 25 | private final List> options = new ArrayList<>(); 26 | 27 | public Builder add(Option option) { 28 | this.options.add(option); 29 | 30 | return this; 31 | } 32 | 33 | public OptionGroup build() { 34 | Validate.notEmpty(this.options, "At least one option must be specified"); 35 | 36 | return new OptionGroup(ImmutableList.copyOf(this.options)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/entity/shadow_clipping/MixinEntityRenderDispatcher.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.entity.shadow_clipping; 2 | 3 | import com.mojang.blaze3d.vertex.IVertexBuilder; 4 | import net.minecraft.client.renderer.entity.EntityRendererManager; 5 | import net.minecraft.util.math.vector.Matrix4f; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | 10 | @Mixin(EntityRendererManager.class) 11 | public class MixinEntityRenderDispatcher { 12 | @Redirect(method = "shadowVertex", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/IVertexBuilder;pos(Lnet/minecraft/util/math/vector/Matrix4f;FFF)Lcom/mojang/blaze3d/vertex/IVertexBuilder;")) 13 | private static IVertexBuilder preWriteVertex(IVertexBuilder vertexConsumer, Matrix4f matrix, float x, float y, float z) { 14 | // FIX: Render the shadow slightly above the block to fix clipping issues 15 | // This happens in vanilla too, but is exacerbated by the Compact Vertex Format option. 16 | return vertexConsumer.pos(matrix, x, y + 0.001f, z); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/biome/BiomeCache.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world.biome; 2 | 3 | import me.jellysquid.mods.sodium.common.util.pool.ReusableObject; 4 | import net.minecraft.world.biome.Biome; 5 | import net.minecraft.world.biome.BiomeManager; 6 | import net.minecraft.world.biome.IBiomeMagnifier; 7 | 8 | import java.util.Arrays; 9 | 10 | public class BiomeCache extends ReusableObject { 11 | private final IBiomeMagnifier type; 12 | private final long seed; 13 | 14 | private final Biome[] biomes; 15 | 16 | public BiomeCache(IBiomeMagnifier type, long seed) { 17 | this.type = type; 18 | this.seed = seed; 19 | this.biomes = new Biome[16 * 16]; 20 | } 21 | 22 | public Biome getBiome(BiomeManager.IBiomeReader storage, int x, int z) { 23 | int idx = ((z & 15) << 4) | (x & 15); 24 | 25 | Biome biome = this.biomes[idx]; 26 | 27 | if (biome == null) { 28 | this.biomes[idx] = biome = this.type.getBiome(this.seed, x, 0, z, storage); 29 | } 30 | 31 | return biome; 32 | } 33 | 34 | @Override 35 | public void reset() { 36 | Arrays.fill(this.biomes, null); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/options/MixinOptionsScreen.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.options; 2 | 3 | import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; 4 | import net.minecraft.client.gui.screen.OptionsScreen; 5 | import net.minecraft.client.gui.screen.Screen; 6 | import net.minecraft.client.gui.widget.button.Button; 7 | import net.minecraft.util.text.ITextComponent; 8 | import org.spongepowered.asm.mixin.Dynamic; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | 14 | @Mixin(OptionsScreen.class) 15 | public class MixinOptionsScreen extends Screen { 16 | protected MixinOptionsScreen(ITextComponent title) { 17 | super(title); 18 | } 19 | 20 | // @Dynamic 21 | // @Inject(method = "func_213059_g(Lnet/minecraft/client/gui/widget/button/Button;)V", at = @At("HEAD"), cancellable = true, remap = false) 22 | private void open(Button widget, CallbackInfo ci) { 23 | this.minecraft.displayGuiScreen(new SodiumOptionsGUI(this)); 24 | 25 | ci.cancel(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/render_layer/MixinRenderLayers.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.render_layer; 2 | 3 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.client.renderer.RenderType; 6 | import net.minecraft.client.renderer.RenderTypeLookup; 7 | import net.minecraft.fluid.Fluid; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Mutable; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | import java.util.Map; 14 | 15 | @Mixin(RenderTypeLookup.class) 16 | public class MixinRenderLayers { 17 | @Mutable 18 | @Shadow 19 | @Final 20 | private static Map TYPES_BY_BLOCK; 21 | 22 | @Mutable 23 | @Shadow 24 | @Final 25 | private static Map TYPES_BY_FLUID; 26 | 27 | static { 28 | // Replace the backing collection types with something a bit faster, since this is a hot spot in chunk rendering. 29 | TYPES_BY_BLOCK = new Reference2ReferenceOpenHashMap<>(TYPES_BY_BLOCK); 30 | TYPES_BY_FLUID = new Reference2ReferenceOpenHashMap<>(TYPES_BY_FLUID); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.properties; 2 | 3 | /** 4 | * Defines the orientation of vertices in a model quad. This information be used to re-orient the quad's vertices to a 5 | * consistent order, eliminating a number of shading issues caused by anisotropy problems. 6 | */ 7 | public enum ModelQuadOrientation { 8 | NORMAL(new int[] { 0, 1, 2, 3 }), 9 | FLIP(new int[] { 1, 2, 3, 0 }); 10 | 11 | private final int[] indices; 12 | 13 | ModelQuadOrientation(int[] indices) { 14 | this.indices = indices; 15 | } 16 | 17 | /** 18 | * @return The re-oriented index of the vertex {@param idx} 19 | */ 20 | public int getVertexIndex(int idx) { 21 | return this.indices[idx]; 22 | } 23 | 24 | /** 25 | * Determines the orientation of the vertices in the quad. 26 | */ 27 | public static ModelQuadOrientation orient(float[] brightnesses) { 28 | // If one side of the quad is brighter, flip the sides 29 | if (brightnesses[0] + brightnesses[2] > brightnesses[1] + brightnesses[3]) { 30 | return NORMAL; 31 | } else { 32 | return FLIP; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /idea/inspections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/cache/HashLightDataCache.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light.cache; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap; 4 | import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.world.IBlockDisplayReader; 7 | 8 | /** 9 | * A light data cache which uses a hash table to store previously accessed values. 10 | */ 11 | public class HashLightDataCache extends LightDataAccess { 12 | private final Long2LongLinkedOpenHashMap map = new Long2LongLinkedOpenHashMap(1024, 0.50f); 13 | 14 | public HashLightDataCache(IBlockDisplayReader world) { 15 | this.world = world; 16 | } 17 | 18 | @Override 19 | public long get(int x, int y, int z) { 20 | long key = BlockPos.pack(x, y, z); 21 | long word = this.map.getAndMoveToFirst(key); 22 | 23 | if (word == 0) { 24 | if (this.map.size() > 1024) { 25 | this.map.removeLastLong(); 26 | } 27 | 28 | this.map.put(key, word = this.compute(x, y, z)); 29 | } 30 | 31 | return word; 32 | } 33 | 34 | public void clear() { 35 | this.map.clear(); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/GlObject.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl; 2 | 3 | /** 4 | * An abstract object used to represent objects in OpenGL code safely. This class hides the direct handle to a OpenGL 5 | * object, requiring that it first be checked by all callers to prevent null pointer de-referencing. However, this will 6 | * not stop code from cloning the handle and trying to use it after it has been deleted and as such should not be 7 | * relied on too heavily. 8 | */ 9 | public class GlObject { 10 | private static final int INVALID_HANDLE = Integer.MIN_VALUE; 11 | 12 | private int handle = INVALID_HANDLE; 13 | 14 | protected final void setHandle(int handle) { 15 | this.handle = handle; 16 | } 17 | 18 | public final int handle() { 19 | this.checkHandle(); 20 | 21 | return this.handle; 22 | } 23 | 24 | protected final void checkHandle() { 25 | if (!this.isHandleValid()) { 26 | throw new IllegalStateException("Handle is not valid"); 27 | } 28 | } 29 | 30 | protected final boolean isHandleValid() { 31 | return this.handle != INVALID_HANDLE; 32 | } 33 | 34 | protected final void invalidateHandle() { 35 | this.handle = INVALID_HANDLE; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/Dim2i.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util; 2 | 3 | public class Dim2i { 4 | private final int x; 5 | private final int y; 6 | private final int width; 7 | private final int height; 8 | 9 | public Dim2i(int x, int y, int width, int height) { 10 | this.x = x; 11 | this.y = y; 12 | this.width = width; 13 | this.height = height; 14 | } 15 | 16 | public int getOriginX() { 17 | return this.x; 18 | } 19 | 20 | public int getOriginY() { 21 | return this.y; 22 | } 23 | 24 | public int getWidth() { 25 | return this.width; 26 | } 27 | 28 | public int getHeight() { 29 | return this.height; 30 | } 31 | 32 | public int getLimitX() { 33 | return this.x + this.width; 34 | } 35 | 36 | public int getLimitY() { 37 | return this.y + this.height; 38 | } 39 | 40 | public boolean containsCursor(double x, double y) { 41 | return x >= this.x && x < this.getLimitX() && y >= this.y && y < this.getLimitY(); 42 | } 43 | 44 | public int getCenterX() { 45 | return this.x + (this.width / 2); 46 | } 47 | 48 | public int getCenterY() { 49 | return this.y + (this.height / 2); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/oneshot/ChunkProgramOneshot.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.oneshot; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgram; 4 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgramComponentBuilder; 5 | import net.minecraft.util.ResourceLocation; 6 | import org.lwjgl.opengl.GL20; 7 | import org.lwjgl.system.MemoryUtil; 8 | 9 | import java.nio.FloatBuffer; 10 | 11 | public class ChunkProgramOneshot extends ChunkProgram { 12 | // Uniform variable index for model offset 13 | private final int dModelOffset; 14 | 15 | // Scratch buffer 16 | private final FloatBuffer uModelOffsetBuffer; 17 | 18 | public ChunkProgramOneshot(ResourceLocation name, int handle, ChunkProgramComponentBuilder components) { 19 | super(name, handle, components); 20 | 21 | this.dModelOffset = this.getUniformLocation("d_ModelOffset"); 22 | this.uModelOffsetBuffer = MemoryUtil.memAllocFloat(4); 23 | } 24 | 25 | public void setModelOffset(float x, float y, float z) { 26 | FloatBuffer buf = this.uModelOffsetBuffer; 27 | buf.put(0, x); 28 | buf.put(1, y); 29 | buf.put(2, z); 30 | 31 | GL20.glUniform4fv(this.dModelOffset, buf); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/block/MixinBufferBuilder.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.block; 2 | 3 | import com.mojang.blaze3d.vertex.DefaultColorVertexBuilder; 4 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadViewMutable; 5 | import me.jellysquid.mods.sodium.client.model.quad.sink.ModelQuadSink; 6 | import me.jellysquid.mods.sodium.client.util.ModelQuadUtil; 7 | import net.minecraft.client.renderer.BufferBuilder; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | import java.nio.ByteBuffer; 12 | 13 | @Mixin(BufferBuilder.class) 14 | public abstract class MixinBufferBuilder extends DefaultColorVertexBuilder implements ModelQuadSink { 15 | @Shadow 16 | private int nextElementBytes; 17 | 18 | @Shadow 19 | private ByteBuffer byteBuffer; 20 | 21 | @Shadow 22 | protected abstract void growBuffer(int size); 23 | 24 | @Shadow 25 | private int vertexCount; 26 | 27 | @Override 28 | public void write(ModelQuadViewMutable quad) { 29 | this.growBuffer(ModelQuadUtil.VERTEX_SIZE_BYTES); 30 | 31 | quad.copyInto(this.byteBuffer, this.nextElementBytes); 32 | 33 | this.nextElementBytes += ModelQuadUtil.VERTEX_SIZE_BYTES; 34 | this.vertexCount += 4; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/func/GlInstancedArrayFunctions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.func; 2 | 3 | import org.lwjgl.opengl.ARBInstancedArrays; 4 | import org.lwjgl.opengl.GL33; 5 | import org.lwjgl.opengl.GLCapabilities; 6 | 7 | public enum GlInstancedArrayFunctions { 8 | CORE { 9 | @Override 10 | public void glVertexAttribDivisor(int index, int divisor) { 11 | GL33.glVertexAttribDivisor(index, divisor); 12 | } 13 | }, 14 | ARB { 15 | @Override 16 | public void glVertexAttribDivisor(int index, int divisor) { 17 | ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); 18 | } 19 | }, 20 | UNSUPPORTED { 21 | @Override 22 | public void glVertexAttribDivisor(int index, int divisor) { 23 | throw new UnsupportedOperationException(); 24 | } 25 | }; 26 | 27 | public static GlInstancedArrayFunctions load(GLCapabilities capabilities) { 28 | if (capabilities.OpenGL33) { 29 | return CORE; 30 | } else if (capabilities.GL_ARB_instanced_arrays) { 31 | return ARB; 32 | } else { 33 | return UNSUPPORTED; 34 | } 35 | } 36 | 37 | public abstract void glVertexAttribDivisor(int index, int divisor); 38 | } 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Use this template if you're running into bugs or other issues 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Expected Behavior 11 | Replace this text with what you expected to happen. 12 | _Example: The Piston should extend._ 13 | 14 | ### Actual Behavior 15 | Replace this text with what actually happened. 16 | _Example: The Piston does not extend._ 17 | 18 | ### Reproduction Steps 19 | Provide information on how to reproduce this game crash. You can either fill in the example below or do something else -- just make sure your instructions are minimal and clear! If applicable, please provide a world file as a compressed ZIP which contains a minimally reproducible example of the issue. 20 | 21 | 1. Place a Redstone Lamp beside a Redstone Repeater 22 | 2. Use a Lever to activate the Redstone Repeater 23 | 3. Nothing happens 24 | 25 | ### Attachments 26 | Add any relevant screenshots or videos to this issue as you feel necessary to explain the issue. 27 | 28 | ### System Information 29 | You can obtain this information from the in-game debug screen or through using [DxDiag](https://support.microsoft.com/en-us/help/4028644/windows-open-and-run-dxdiagexe) on Windows. 30 | 31 | - Java Version: [fill me in] 32 | - CPU: [fill me in] 33 | - GPU: [fill me in] 34 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/options/MixinGameOptions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.options; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; 6 | import net.minecraft.client.GameSettings; 7 | import net.minecraft.client.settings.CloudOption; 8 | import net.minecraft.client.settings.GraphicsFanciness; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(GameSettings.class) 14 | public class MixinGameOptions { 15 | @Shadow 16 | public int renderDistanceChunks; 17 | 18 | @Shadow 19 | public GraphicsFanciness graphicFanciness; 20 | 21 | /** 22 | * @author JellySquid 23 | * @reason Make the cloud render mode user-configurable 24 | */ 25 | @Overwrite 26 | public CloudOption getCloudOption() { 27 | Config.Client options = Config.CLIENT; 28 | 29 | if (this.renderDistanceChunks < 4 || !options.enableClouds.get()) { 30 | return CloudOption.OFF; 31 | } 32 | 33 | return options.cloudQuality.get().isFancy(this.graphicFanciness) ? CloudOption.FANCY : CloudOption.FAST; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/SodiumClientMod.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client; 2 | 3 | import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; 4 | import me.jellysquid.mods.sodium.client.util.UnsafeUtil; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import java.io.File; 9 | 10 | public class SodiumClientMod { 11 | private static SodiumGameOptions CONFIG; 12 | private static Logger LOGGER; 13 | 14 | public void onInitializeClient() { 15 | 16 | } 17 | 18 | // public static SodiumGameOptions options() { 19 | // if (CONFIG == null) { 20 | // CONFIG = loadConfig(); 21 | // } 22 | // 23 | // return CONFIG; 24 | // } 25 | 26 | public static Logger logger() { 27 | if (LOGGER == null) { 28 | LOGGER = LogManager.getLogger("Sodium"); 29 | } 30 | 31 | return LOGGER; 32 | } 33 | 34 | private static SodiumGameOptions loadConfig() { 35 | SodiumGameOptions config = SodiumGameOptions.load(new File("config/sodium-options.json")); 36 | onConfigChanged(config); 37 | 38 | return config; 39 | } 40 | 41 | public static void onConfigChanged(SodiumGameOptions options) { 42 | UnsafeUtil.setEnabled(options.advanced.useMemoryIntrinsics); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/blender/BiomeColorBlender.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad.blender; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; 4 | import net.minecraft.block.BlockState; 5 | import net.minecraft.client.renderer.color.IBlockColor; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.world.IBlockDisplayReader; 8 | 9 | public interface BiomeColorBlender { 10 | /** 11 | * Computes the blended biome colors and returns an an array containing the integer-encoded colors for each vertex. 12 | * The array returned by this method may be re-used in subsequent calls in order to reduce memory allocations, and 13 | * as such, the contents of an array returned by this method is undefined after a subsequent call. 14 | * 15 | * @param colorizer The color sampling source 16 | * @param world The world to sample biomes (and as a result, colors) from 17 | * @param state The block state being rendered 18 | * @param origin The position of the block being rendered 19 | * @param quad The quad which will be colorized 20 | * @return An array of integer colors in ABGR format 21 | */ 22 | int[] getColors(IBlockColor colorizer, IBlockDisplayReader world, BlockState state, BlockPos origin, 23 | ModelQuadView quad); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/multidraw/ChunkRenderBackendMultiDraw.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.multidraw; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.SodiumVertexFormats; 4 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 5 | import me.jellysquid.mods.sodium.client.gl.shader.ShaderConstants; 6 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 7 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgramComponentBuilder; 8 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkRenderShaderBackend; 9 | import net.minecraft.util.ResourceLocation; 10 | 11 | public abstract class ChunkRenderBackendMultiDraw extends ChunkRenderShaderBackend { 12 | public ChunkRenderBackendMultiDraw(GlVertexFormat format) { 13 | super(format); 14 | } 15 | 16 | @Override 17 | protected ChunkProgramMultiDraw createShaderProgram(ResourceLocation name, int handle, ChunkProgramComponentBuilder components) { 18 | return new ChunkProgramMultiDraw(name, handle, components); 19 | } 20 | 21 | 22 | @Override 23 | protected void addShaderConstants(ShaderConstants.Builder builder) { 24 | builder.define("USE_MULTIDRAW"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/impl/SingleTextureRenderPipeline.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes.impl; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockLayer; 4 | import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPassManager; 5 | import me.jellysquid.mods.sodium.client.render.chunk.passes.WorldRenderPhase; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | public class SingleTextureRenderPipeline { 9 | public static final ResourceLocation SOLID_PASS = new ResourceLocation("sodium", "single_texture/solid"); 10 | public static final ResourceLocation SOLID_MIPPED_PASS = new ResourceLocation("sodium", "single_texture/solid_mipped"); 11 | public static final ResourceLocation TRANSLUCENT_MIPPED_PASS = new ResourceLocation("sodium", "single_texture/translucent_mipped"); 12 | 13 | public static BlockRenderPassManager create() { 14 | BlockRenderPassManager registry = new BlockRenderPassManager(); 15 | registry.add(WorldRenderPhase.OPAQUE, SOLID_PASS, SolidRenderPass::new, BlockLayer.SOLID); 16 | registry.add(WorldRenderPhase.OPAQUE, SOLID_MIPPED_PASS, SolidRenderPass::new, BlockLayer.SOLID_MIPPED); 17 | registry.add(WorldRenderPhase.TRANSLUCENT, TRANSLUCENT_MIPPED_PASS, TranslucentRenderPass::new, BlockLayer.TRANSLUCENT_MIPPED); 18 | 19 | return registry; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/texture/ChunkProgramSingleTexture.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader.texture; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgram; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.inventory.container.PlayerContainer; 6 | import org.lwjgl.opengl.GL20; 7 | 8 | public class ChunkProgramSingleTexture extends ChunkProgramTextureComponent { 9 | private final int uBlockTex; 10 | private final int uLightTex; 11 | 12 | public ChunkProgramSingleTexture(ChunkProgram program) { 13 | this.uBlockTex = program.getUniformLocation("u_BlockTex"); 14 | this.uLightTex = program.getUniformLocation("u_LightTex"); 15 | } 16 | 17 | @Override 18 | public void bind() { 19 | GL20.glUniform1i(this.uBlockTex, ChunkProgramTextureUnit.BLOCK_ATLAS.ordinal()); 20 | GL20.glUniform1i(this.uLightTex, ChunkProgramTextureUnit.LIGHT_TEX.ordinal()); 21 | } 22 | 23 | @Override 24 | public void unbind() { 25 | 26 | } 27 | 28 | @Override 29 | public void delete() { 30 | 31 | } 32 | 33 | @Override 34 | public void setMipmapping(boolean mipped) { 35 | Minecraft.getInstance().getTextureManager() 36 | .getTexture(PlayerContainer.LOCATION_BLOCKS_TEXTURE) 37 | .setBlurMipmapDirect(false, mipped); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/math/MatrixUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.math; 2 | 3 | import me.jellysquid.mods.sodium.client.util.Norm3b; 4 | import net.minecraft.util.Direction; 5 | import net.minecraft.util.math.vector.Matrix3f; 6 | import net.minecraft.util.math.vector.Matrix4f; 7 | 8 | @SuppressWarnings("ConstantConditions") 9 | public class MatrixUtil { 10 | public static int computeNormal(Matrix3f normalMatrix, Direction facing) { 11 | return ((Matrix3fExtended) (Object) normalMatrix).computeNormal(facing); 12 | } 13 | 14 | public static Matrix4fExtended getExtendedMatrix(Matrix4f matrix) { 15 | return (Matrix4fExtended) (Object) matrix; 16 | } 17 | 18 | public static Matrix3fExtended getExtendedMatrix(Matrix3f matrix) { 19 | return (Matrix3fExtended) (Object) matrix; 20 | } 21 | 22 | public static int transformPackedNormal(int norm, Matrix3f matrix) { 23 | Matrix3fExtended mat = MatrixUtil.getExtendedMatrix(matrix); 24 | 25 | float normX1 = Norm3b.unpackX(norm); 26 | float normY1 = Norm3b.unpackY(norm); 27 | float normZ1 = Norm3b.unpackZ(norm); 28 | 29 | float normX2 = mat.transformVecX(normX1, normY1, normZ1); 30 | float normY2 = mat.transformVecY(normX1, normY1, normZ1); 31 | float normZ2 = mat.transformVecZ(normX1, normY1, normZ1); 32 | 33 | return Norm3b.pack(normX2, normY2, normZ2); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/func/GlIndirectMultiDrawFunctions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.func; 2 | 3 | import org.lwjgl.opengl.ARBMultiDrawIndirect; 4 | import org.lwjgl.opengl.GL43; 5 | import org.lwjgl.opengl.GLCapabilities; 6 | 7 | public enum GlIndirectMultiDrawFunctions { 8 | CORE { 9 | @Override 10 | public void glMultiDrawArraysIndirect(int mode, long indirect, int primcount, int stride) { 11 | GL43.glMultiDrawArraysIndirect(mode, indirect, primcount, stride); 12 | } 13 | }, 14 | ARB { 15 | @Override 16 | public void glMultiDrawArraysIndirect(int mode, long indirect, int primcount, int stride) { 17 | ARBMultiDrawIndirect.glMultiDrawArraysIndirect(mode, indirect, primcount, stride); 18 | } 19 | }, 20 | UNSUPPORTED { 21 | @Override 22 | public void glMultiDrawArraysIndirect(int mode, long indirect, int primcount, int stride) { 23 | throw new UnsupportedOperationException(); 24 | } 25 | }; 26 | 27 | public static GlIndirectMultiDrawFunctions load(GLCapabilities capabilities) { 28 | if (capabilities.OpenGL43) { 29 | return CORE; 30 | } else if (capabilities.GL_ARB_multi_draw_indirect) { 31 | return ARB; 32 | } else { 33 | return UNSUPPORTED; 34 | } 35 | } 36 | 37 | public abstract void glMultiDrawArraysIndirect(int mode, long indirect, int primcount, int stride); 38 | } -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPassManager.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes; 2 | 3 | 4 | import net.minecraft.util.ResourceLocation; 5 | 6 | import java.util.ArrayList; 7 | import java.util.EnumMap; 8 | import java.util.List; 9 | 10 | public class BlockRenderPassManager { 11 | private final EnumMap> byPhase = new EnumMap<>(WorldRenderPhase.class); 12 | private final List all = new ArrayList<>(); 13 | 14 | public BlockRenderPassManager() { 15 | for (WorldRenderPhase pass : WorldRenderPhase.values()) { 16 | this.byPhase.put(pass, new ArrayList<>()); 17 | } 18 | } 19 | 20 | public void add(WorldRenderPhase phase, ResourceLocation id, Factory factory, BlockLayer... layers) { 21 | R pass = factory.create(this.all.size(), id, layers); 22 | 23 | this.byPhase.get(phase).add(pass); 24 | this.all.add(pass); 25 | } 26 | 27 | public Iterable getSortedPasses() { 28 | return this.all; 29 | } 30 | 31 | public Iterable getPassesForPhase(WorldRenderPhase phase) { 32 | return this.byPhase.get(phase); 33 | } 34 | 35 | public int getPassCount() { 36 | return this.all.size(); 37 | } 38 | 39 | public interface Factory { 40 | R create(int ordinal, ResourceLocation id, BlockLayer[] layers); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/util/GlFogHelper.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.util; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import org.lwjgl.opengl.GL11; 5 | 6 | public class GlFogHelper { 7 | private static final float FAR_PLANE_THRESHOLD_EXP = (float) Math.log(1.0f / 0.0019f); 8 | private static final float FAR_PLANE_THRESHOLD_EXP2 = MathHelper.sqrt(FAR_PLANE_THRESHOLD_EXP); 9 | 10 | public static float getFogEnd() { 11 | return GL11.glGetFloat(GL11.GL_FOG_END); 12 | } 13 | 14 | public static float getFogStart() { 15 | return GL11.glGetFloat(GL11.GL_FOG_START); 16 | } 17 | 18 | public static float getFogDensity() { 19 | return GL11.glGetFloat(GL11.GL_FOG_DENSITY); 20 | } 21 | 22 | public static float getFogCutoff() { 23 | int mode = GL11.glGetInteger(GL11.GL_FOG_MODE); 24 | 25 | switch (mode) { 26 | case GL11.GL_LINEAR: 27 | return getFogEnd(); 28 | case GL11.GL_EXP: 29 | return FAR_PLANE_THRESHOLD_EXP / getFogDensity(); 30 | case GL11.GL_EXP2: 31 | return FAR_PLANE_THRESHOLD_EXP2 / getFogDensity(); 32 | default: 33 | return 0.0f; 34 | } 35 | } 36 | 37 | public static boolean isFogEnabled() { 38 | return GL11.glGetBoolean(GL11.GL_FOG); 39 | } 40 | 41 | public static boolean isFogLinear() { 42 | return GL11.glGetInteger(GL11.GL_FOG_MODE) == GL11.GL_LINEAR; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/data/ChunkMeshData.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.data; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; 4 | import me.jellysquid.mods.sodium.client.gl.buffer.VertexData; 5 | import me.jellysquid.mods.sodium.client.gl.util.BufferSlice; 6 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; 7 | 8 | import java.util.Map; 9 | 10 | public class ChunkMeshData { 11 | private final Map parts = new Object2ObjectLinkedOpenHashMap<>(); 12 | private VertexData vertexData; 13 | 14 | public void setVertexData(VertexData vertexData) { 15 | this.vertexData = vertexData; 16 | } 17 | 18 | public void setModelSlice(ModelQuadFacing facing, BufferSlice slice) { 19 | this.parts.put(facing, slice); 20 | } 21 | 22 | public VertexData takeVertexData() { 23 | VertexData data = this.vertexData; 24 | 25 | if (data == null) { 26 | throw new NullPointerException("No pending data to upload"); 27 | } 28 | 29 | this.vertexData = null; 30 | 31 | return data; 32 | } 33 | 34 | public int getVertexDataSize() { 35 | if (this.vertexData != null) { 36 | return this.vertexData.buffer.capacity(); 37 | } 38 | 39 | return 0; 40 | } 41 | 42 | public Iterable> getSlices() { 43 | return this.parts.entrySet(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/control/ControlValueFormatter.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.control; 2 | 3 | import net.minecraft.client.resources.I18n; 4 | 5 | public interface ControlValueFormatter { 6 | static ControlValueFormatter guiScale() { 7 | return (v) -> (v == 0) ? I18n.format("options.guiScale.auto") : v + "x"; 8 | } 9 | 10 | static ControlValueFormatter fpsLimit() { 11 | return (v) -> (v == 260) ? I18n.format("options.framerateLimit.max") : v + " FPS"; 12 | } 13 | 14 | static ControlValueFormatter brightness() { 15 | return (v) -> { 16 | if (v == 0) { 17 | return I18n.format("options.gamma.min"); 18 | } else if (v == 100) { 19 | return I18n.format("options.gamma.max"); 20 | } else { 21 | return v + "%"; 22 | } 23 | }; 24 | } 25 | 26 | String format(int value); 27 | 28 | static ControlValueFormatter percentage() { 29 | return (v) -> v + "%"; 30 | } 31 | 32 | static ControlValueFormatter multiplier() { 33 | return (v) -> v + "x"; 34 | } 35 | 36 | static ControlValueFormatter quantity(String name) { 37 | return (v) -> v + " " + name; 38 | } 39 | 40 | static ControlValueFormatter quantityOrDisabled(String name, String disableText) { 41 | return (v) -> v == 0 ? disableText : v + " " + name; 42 | } 43 | 44 | static ControlValueFormatter number() { 45 | return String::valueOf; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/func/GlFunctions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.func; 2 | 3 | import org.lwjgl.opengl.GL; 4 | import org.lwjgl.opengl.GLCapabilities; 5 | 6 | public class GlFunctions { 7 | private static final GLCapabilities capabilities = GL.getCapabilities(); 8 | 9 | public static final GlVertexArrayFunctions VERTEX_ARRAY = GlVertexArrayFunctions.load(capabilities); 10 | public static final GlBufferCopyFunctions BUFFER_COPY = GlBufferCopyFunctions.load(capabilities); 11 | public static final GlIndirectMultiDrawFunctions INDIRECT_DRAW = GlIndirectMultiDrawFunctions.load(capabilities); 12 | public static final GlInstancedArrayFunctions INSTANCED_ARRAY = GlInstancedArrayFunctions.load(capabilities); 13 | public static final GlSamplerFunctions SAMPLER = GlSamplerFunctions.load(capabilities); 14 | 15 | public static boolean isVertexArraySupported() { 16 | return VERTEX_ARRAY != GlVertexArrayFunctions.UNSUPPORTED; 17 | } 18 | 19 | public static boolean isBufferCopySupported() { 20 | return BUFFER_COPY != GlBufferCopyFunctions.UNSUPPORTED; 21 | } 22 | 23 | public static boolean isIndirectMultiDrawSupported() { 24 | return INDIRECT_DRAW != GlIndirectMultiDrawFunctions.UNSUPPORTED; 25 | } 26 | 27 | public static boolean isInstancedArraySupported() { 28 | return INSTANCED_ARRAY != GlInstancedArrayFunctions.UNSUPPORTED; 29 | } 30 | 31 | public static boolean isSamplerSupported() { 32 | return SAMPLER != GlSamplerFunctions.UNSUPPORTED; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/block/MixinWorldRenderer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.block; 2 | 3 | import com.mojang.blaze3d.matrix.MatrixStack; 4 | import me.jellysquid.mods.sodium.client.render.pipeline.context.GlobalRenderContext; 5 | import net.minecraft.client.renderer.ActiveRenderInfo; 6 | import net.minecraft.client.renderer.GameRenderer; 7 | import net.minecraft.client.renderer.LightTexture; 8 | import net.minecraft.client.renderer.WorldRenderer; 9 | import net.minecraft.util.math.vector.Matrix4f; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | @Mixin(WorldRenderer.class) 16 | public class MixinWorldRenderer { 17 | /** 18 | * Reset any global cached state before rendering a frame. This will hopefully ensure that any world state that has 19 | * changed is reflected in vanilla-style rendering. 20 | */ 21 | @Inject(method = "updateCameraAndRender(Lcom/mojang/blaze3d/matrix/MatrixStack;FJZLnet/minecraft/client/renderer/ActiveRenderInfo;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/util/math/vector/Matrix4f;)V", at = @At("HEAD")) 22 | private void reset(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, ActiveRenderInfo camera, 23 | GameRenderer gameRenderer, LightTexture lightmapTextureManager, Matrix4f matrix4f, 24 | CallbackInfo ci) { 25 | GlobalRenderContext.reset(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/func/GlBufferCopyFunctions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.func; 2 | 3 | import org.lwjgl.opengl.ARBCopyBuffer; 4 | import org.lwjgl.opengl.GL31; 5 | import org.lwjgl.opengl.GLCapabilities; 6 | 7 | /** 8 | * Requires OpenGL 3.1+ or the ARB_copy_buffer extension. 9 | */ 10 | public enum GlBufferCopyFunctions { 11 | CORE { 12 | @Override 13 | public void glCopyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size) { 14 | GL31.glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); 15 | } 16 | }, 17 | ARB { 18 | @Override 19 | public void glCopyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size) { 20 | ARBCopyBuffer.glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); 21 | } 22 | }, 23 | UNSUPPORTED { 24 | @Override 25 | public void glCopyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size) { 26 | throw new UnsupportedOperationException(); 27 | } 28 | }; 29 | 30 | static GlBufferCopyFunctions load(GLCapabilities capabilities) { 31 | if (capabilities.OpenGL31) { 32 | return GlBufferCopyFunctions.CORE; 33 | } else if (capabilities.GL_ARB_copy_buffer) { 34 | return GlBufferCopyFunctions.ARB; 35 | } else { 36 | return GlBufferCopyFunctions.UNSUPPORTED; 37 | } 38 | } 39 | 40 | public abstract void glCopyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/matrix_stack/MixinMatrixStack.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.matrix_stack; 2 | 3 | import com.mojang.blaze3d.matrix.MatrixStack; 4 | import me.jellysquid.mods.sodium.client.util.math.Matrix3fExtended; 5 | import me.jellysquid.mods.sodium.client.util.math.Matrix4fExtended; 6 | import me.jellysquid.mods.sodium.client.util.math.MatrixUtil; 7 | import net.minecraft.util.math.vector.Quaternion; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | import java.util.Deque; 14 | 15 | @Mixin(MatrixStack.class) 16 | public class MixinMatrixStack { 17 | @Shadow 18 | @Final 19 | private Deque stack; 20 | 21 | /** 22 | * @reason Use our faster specialized function 23 | * @author JellySquid 24 | */ 25 | @Overwrite 26 | public void translate(double x, double y, double z) { 27 | MatrixStack.Entry entry = this.stack.getLast(); 28 | 29 | Matrix4fExtended mat = MatrixUtil.getExtendedMatrix(entry.getMatrix()); 30 | mat.translate((float) x, (float) y, (float) z); 31 | } 32 | 33 | /** 34 | * @reason Use our faster specialized function 35 | * @author JellySquid 36 | */ 37 | @Overwrite 38 | public void rotate(Quaternion q) { 39 | MatrixStack.Entry entry = this.stack.getLast(); 40 | 41 | Matrix4fExtended mat4 = MatrixUtil.getExtendedMatrix(entry.getMatrix()); 42 | mat4.rotate(q); 43 | 44 | Matrix3fExtended mat3 = MatrixUtil.getExtendedMatrix(entry.getNormal()); 45 | mat3.rotate(q); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/buffer_builder/intrinsics/MixinSpriteTexturedVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.buffer_builder.intrinsics; 2 | 3 | import com.mojang.blaze3d.vertex.IVertexBuilder; 4 | import me.jellysquid.mods.sodium.client.model.consumer.ParticleVertexConsumer; 5 | import me.jellysquid.mods.sodium.client.model.consumer.QuadVertexConsumer; 6 | import net.minecraft.client.renderer.SpriteAwareVertexBuilder; 7 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(SpriteAwareVertexBuilder.class) 13 | public abstract class MixinSpriteTexturedVertexConsumer implements QuadVertexConsumer, ParticleVertexConsumer { 14 | @Shadow 15 | @Final 16 | private IVertexBuilder vertexBuilder; 17 | 18 | @Shadow 19 | @Final 20 | private TextureAtlasSprite atlasSprite; 21 | 22 | @Override 23 | public void vertexQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int norm) { 24 | u = this.atlasSprite.getInterpolatedU(u * 16.0F); 25 | v = this.atlasSprite.getInterpolatedV(v * 16.0F); 26 | 27 | ((QuadVertexConsumer) this.vertexBuilder).vertexQuad(x, y, z, color, u, v, light, overlay, norm); 28 | } 29 | 30 | @Override 31 | public void vertexParticle(float x, float y, float z, float u, float v, int color, int light) { 32 | u = this.atlasSprite.getInterpolatedU(u * 16.0F); 33 | v = this.atlasSprite.getInterpolatedV(v * 16.0F); 34 | 35 | ((ParticleVertexConsumer) this.vertexBuilder).vertexParticle(x, y, z, u, v, color, light); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/flat/FlatLightPipeline.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light.flat; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.LightPipeline; 4 | import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; 5 | import me.jellysquid.mods.sodium.client.model.light.data.QuadLightData; 6 | import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; 7 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags; 8 | import net.minecraft.util.Direction; 9 | import net.minecraft.util.math.BlockPos; 10 | 11 | import java.util.Arrays; 12 | 13 | import static me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess.unpackLM; 14 | 15 | /** 16 | * A light pipeline which implements "classic-style" lighting through simply using the light value of the adjacent 17 | * block to a face. 18 | */ 19 | public class FlatLightPipeline implements LightPipeline { 20 | /** 21 | * The cache which light data will be accessed from. 22 | */ 23 | private final LightDataAccess lightCache; 24 | 25 | public FlatLightPipeline(LightDataAccess lightCache) { 26 | this.lightCache = lightCache; 27 | } 28 | 29 | @Override 30 | public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction face, boolean shade) { 31 | // If the face is aligned, use the light data above it 32 | if ((quad.getFlags() & ModelQuadFlags.IS_ALIGNED) != 0) { 33 | Arrays.fill(out.lm, unpackLM(this.lightCache.get(pos, face))); 34 | } else { 35 | Arrays.fill(out.lm, unpackLM(this.lightCache.get(pos))); 36 | } 37 | 38 | Arrays.fill(out.br, this.lightCache.getWorld().func_230487_a_(face, shade)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/tasks/ChunkRenderEmptyBuildTask.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.tasks; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 4 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 5 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; 6 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildResult; 7 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; 8 | import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderContext; 9 | import me.jellysquid.mods.sodium.client.util.task.CancellationSource; 10 | 11 | /** 12 | * A build task which does no computation and always return an empty build result. These tasks are created whenever 13 | * chunk meshes need to be deleted as the only way to change graphics state is to send a message to the main 14 | * actor thread. In cases where new chunk renders are being created and scheduled, the scheduler will prefer to just 15 | * synchronously update the render's data to an empty state to speed things along. 16 | */ 17 | public class ChunkRenderEmptyBuildTask extends ChunkRenderBuildTask { 18 | private final ChunkRenderContainer render; 19 | 20 | public ChunkRenderEmptyBuildTask(ChunkRenderContainer render) { 21 | this.render = render; 22 | } 23 | 24 | @Override 25 | public ChunkBuildResult performBuild(ChunkRenderContext pipeline, ChunkBuildBuffers buffers, CancellationSource cancellationSource) { 26 | return new ChunkBuildResult<>(this.render, ChunkRenderData.EMPTY); 27 | } 28 | 29 | @Override 30 | public void releaseResources() { 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/consumer/QuadVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.consumer; 2 | 3 | import com.mojang.blaze3d.matrix.MatrixStack; 4 | import me.jellysquid.mods.sodium.client.util.math.Matrix4fExtended; 5 | import me.jellysquid.mods.sodium.client.util.math.MatrixUtil; 6 | 7 | public interface QuadVertexConsumer { 8 | /** 9 | * Writes a vertex directly into the consumer with no additional processing. This requires callers to do some 10 | * upfront work to encode their values. 11 | * @param x The x-position of the vertex 12 | * @param y The y-position of the vertex 13 | * @param z The z-position of the vertex 14 | * @param color The color of the vertex in little-endian RGBA format 15 | * @param u The u-position of the texture 16 | * @param v The v-position of the texture 17 | * @param light The light of the vertex 18 | * @param overlay The overlay (shadow) of the vertex 19 | * @param normal The normal of the vertex 20 | */ 21 | void vertexQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal); 22 | 23 | default void vertexQuad(MatrixStack.Entry entry, float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) { 24 | Matrix4fExtended modelMatrix = MatrixUtil.getExtendedMatrix(entry.getMatrix()); 25 | 26 | float x2 = modelMatrix.transformVecX(x, y, z); 27 | float y2 = modelMatrix.transformVecY(x, y, z); 28 | float z2 = modelMatrix.transformVecZ(x, y, z); 29 | 30 | int norm = MatrixUtil.transformPackedNormal(normal, entry.getNormal()); 31 | 32 | this.vertexQuad(x2, y2, z2, color, u, v, light, overlay, norm); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/util/pool/ReusableObject.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.util.pool; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | public abstract class ReusableObject { 6 | /** The number of active references to this object **/ 7 | private final AtomicInteger refCount = new AtomicInteger(0); 8 | 9 | /** 10 | * Acquires a reference for this object. This will prevent the object from being re-used until all references have 11 | * been released using {@link ReusableObject#releaseReference()}. 12 | */ 13 | final void acquireReference() { 14 | int count = this.refCount.getAndIncrement(); 15 | 16 | if (count <= 0) { 17 | throw new IllegalStateException("Reference cannot be acquired after all others have been dropped"); 18 | } 19 | } 20 | 21 | /** 22 | * Releases a reference for this object and performs finalizers as necessary. If no references are held, this 23 | * will throw an exception. 24 | */ 25 | final boolean releaseReference() { 26 | int count = this.refCount.decrementAndGet(); 27 | 28 | if (count < 0) { 29 | throw new IllegalStateException("No references are currently held"); 30 | } 31 | 32 | return count == 0; 33 | } 34 | 35 | /** 36 | * Called when the last reference is released. The implementation should release all resources of their own as to not 37 | * cause memory leaks when this object is added back to an pool. 38 | */ 39 | protected abstract void reset(); 40 | 41 | public void acquireOwner() { 42 | if (!this.refCount.compareAndSet(0, 1)) { 43 | throw new IllegalStateException("Object in pool still has references"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/resources/assets/sodium/shaders/chunk_glsl110.v.glsl: -------------------------------------------------------------------------------- 1 | #version 110 2 | 3 | attribute vec4 a_Pos; // The position of the vertex, with the w-component being the mipmap blend factor 4 | attribute vec4 a_Color; // The color of the vertex 5 | attribute vec2 a_TexCoord; // The block texture coordinate of the vertex 6 | attribute vec2 a_LightCoord; // The light map texture coordinate of the vertex 7 | 8 | varying vec4 v_Color; 9 | varying vec2 v_TexCoord; 10 | varying vec2 v_LightCoord; 11 | 12 | #ifdef USE_MULTITEX 13 | varying float v_MipFactor; 14 | #endif 15 | 16 | #ifdef USE_FOG 17 | varying float v_FragDistance; 18 | #endif 19 | 20 | uniform mat4 u_ModelViewProjectionMatrix; 21 | uniform vec3 u_ModelScale; 22 | 23 | // The model translation for this draw call. 24 | // If multi-draw is enabled, then the model offset will come from an attribute buffer. 25 | #ifdef USE_MULTIDRAW 26 | attribute vec4 d_ModelOffset; 27 | #else 28 | uniform vec4 d_ModelOffset; 29 | #endif 30 | 31 | void main() { 32 | // Translates the vertex position around the position of the camera 33 | // This can be used to calculate the distance of the vertex from the camera without needing to 34 | // transform it into model-view space with a matrix, which is much slower. 35 | vec3 pos = (a_Pos.xyz * u_ModelScale) + d_ModelOffset.xyz; 36 | 37 | #ifdef USE_FOG 38 | v_FragDistance = length(pos); 39 | #endif 40 | 41 | // Transform the vertex position into model-view-projection space 42 | gl_Position = u_ModelViewProjectionMatrix * vec4(pos, 1.0); 43 | 44 | // Pass the color and texture coordinates to the fragment shader 45 | v_Color = a_Color; 46 | v_TexCoord = a_TexCoord; 47 | v_LightCoord = a_LightCoord; 48 | 49 | #ifdef USE_MULTITEX 50 | v_MipFactor = a_Pos.w; 51 | #endif 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/core/model/MixinBlockColors.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.core.model; 2 | 3 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; 4 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; 5 | import me.jellysquid.mods.sodium.client.world.biome.BlockColorsExtended; 6 | import net.minecraft.block.Block; 7 | import net.minecraft.block.BlockState; 8 | import net.minecraft.client.renderer.color.BlockColors; 9 | import net.minecraft.client.renderer.color.IBlockColor; 10 | import net.minecraftforge.registries.IRegistryDelegate; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | @Mixin(BlockColors.class) 17 | public class MixinBlockColors implements BlockColorsExtended { 18 | private Reference2ReferenceMap, IBlockColor> blocksToColor; 19 | 20 | private static final IBlockColor DEFAULT_PROVIDER = (state, view, pos, tint) -> -1; 21 | 22 | @Inject(method = "", at = @At("RETURN")) 23 | private void init(CallbackInfo ci) { 24 | this.blocksToColor = new Reference2ReferenceOpenHashMap<>(); 25 | this.blocksToColor.defaultReturnValue(DEFAULT_PROVIDER); 26 | } 27 | 28 | @Inject(method = "register", at = @At("HEAD")) 29 | private void preRegisterColor(IBlockColor provider, Block[] blocks, CallbackInfo ci) { 30 | for (Block block : blocks) { 31 | this.blocksToColor.put(block.delegate, provider); 32 | } 33 | } 34 | 35 | @Override 36 | public IBlockColor getColorProvider(BlockState state) { 37 | return this.blocksToColor.get(state.getBlock().delegate); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/common/config/Option.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.common.config; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.LinkedHashSet; 6 | import java.util.Set; 7 | 8 | public class Option { 9 | private final String name; 10 | 11 | private Set modDefined = null; 12 | private boolean enabled; 13 | private boolean userDefined; 14 | 15 | public Option(String name, boolean enabled, boolean userDefined) { 16 | this.name = name; 17 | this.enabled = enabled; 18 | this.userDefined = userDefined; 19 | } 20 | 21 | public void setEnabled(boolean enabled, boolean userDefined) { 22 | this.enabled = enabled; 23 | this.userDefined = userDefined; 24 | } 25 | 26 | public void addModOverride(boolean enabled, String modId) { 27 | this.enabled = enabled; 28 | 29 | if (this.modDefined == null) { 30 | this.modDefined = new LinkedHashSet<>(); 31 | } 32 | 33 | this.modDefined.add(modId); 34 | } 35 | 36 | public boolean isEnabled() { 37 | return this.enabled; 38 | } 39 | 40 | public boolean isOverridden() { 41 | return this.isUserDefined() || this.isModDefined(); 42 | } 43 | 44 | public boolean isUserDefined() { 45 | return this.userDefined; 46 | } 47 | 48 | public boolean isModDefined() { 49 | return this.modDefined != null; 50 | } 51 | 52 | public String getName() { 53 | return this.name; 54 | } 55 | 56 | public void clearModsDefiningValue() { 57 | this.modDefined = null; 58 | } 59 | 60 | public Collection getDefiningMods() { 61 | return this.modDefined != null ? Collections.unmodifiableCollection(this.modDefined) : Collections.emptyList(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/matrix_stack/MixinVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.matrix_stack; 2 | 3 | import com.mojang.blaze3d.vertex.IVertexBuilder; 4 | import me.jellysquid.mods.sodium.client.util.math.Matrix3fExtended; 5 | import me.jellysquid.mods.sodium.client.util.math.Matrix4fExtended; 6 | import me.jellysquid.mods.sodium.client.util.math.MatrixUtil; 7 | import net.minecraft.util.math.vector.Matrix3f; 8 | import net.minecraft.util.math.vector.Matrix4f; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(IVertexBuilder.class) 14 | public interface MixinVertexConsumer { 15 | @Shadow 16 | IVertexBuilder normal(float x, float y, float z); 17 | 18 | @Shadow 19 | IVertexBuilder pos(double x, double y, double z); 20 | 21 | /** 22 | * @reason Avoid allocations 23 | * @author JellySquid 24 | */ 25 | @Overwrite 26 | default IVertexBuilder pos(Matrix4f matrix, float x, float y, float z) { 27 | Matrix4fExtended ext = MatrixUtil.getExtendedMatrix(matrix); 28 | float x2 = ext.transformVecX(x, y, z); 29 | float y2 = ext.transformVecY(x, y, z); 30 | float z2 = ext.transformVecZ(x, y, z); 31 | 32 | return this.pos(x2, y2, z2); 33 | } 34 | 35 | /** 36 | * @reason Avoid allocations 37 | * @author JellySquid 38 | */ 39 | @Overwrite 40 | default IVertexBuilder normal(Matrix3f matrix, float x, float y, float z) { 41 | Matrix3fExtended ext = MatrixUtil.getExtendedMatrix(matrix); 42 | float x2 = ext.transformVecX(x, y, z); 43 | float y2 = ext.transformVecY(x, y, z); 44 | float z2 = ext.transformVecZ(x, y, z); 45 | 46 | return this.normal(x2, y2, z2); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/passes/BlockLayer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.passes; 2 | 3 | import it.unimi.dsi.fastutil.objects.Reference2IntArrayMap; 4 | import net.minecraft.client.renderer.RenderType; 5 | 6 | // TODO: Move away from using an enum, make this extensible 7 | public enum BlockLayer { 8 | SOLID_MIPPED(true), 9 | SOLID(false), 10 | TRANSLUCENT_MIPPED(true); 11 | 12 | public static final BlockLayer[] VALUES = BlockLayer.values(); 13 | public static final int COUNT = VALUES.length; 14 | 15 | private final boolean mipped; 16 | 17 | BlockLayer(boolean mipped) { 18 | this.mipped = mipped; 19 | } 20 | 21 | public boolean isMipped() { 22 | return this.mipped; 23 | } 24 | 25 | public int getExpectedSize() { 26 | return 2097152; // TODO: tweak this 27 | } 28 | 29 | private static final Reference2IntArrayMap layerMappings; 30 | 31 | static { 32 | layerMappings = new Reference2IntArrayMap<>(); 33 | layerMappings.defaultReturnValue(-1); 34 | 35 | layerMappings.put(RenderType.getSolid(), BlockLayer.SOLID_MIPPED.ordinal()); 36 | layerMappings.put(RenderType.getCutoutMipped(), BlockLayer.SOLID_MIPPED.ordinal()); 37 | layerMappings.put(RenderType.getCutout(), BlockLayer.SOLID.ordinal()); 38 | layerMappings.put(RenderType.getTripwire(), BlockLayer.SOLID.ordinal()); 39 | layerMappings.put(RenderType.getTranslucent(), BlockLayer.TRANSLUCENT_MIPPED.ordinal()); 40 | } 41 | 42 | public static int fromRenderLayer(RenderType layer) { 43 | int pass = layerMappings.getInt(layer); 44 | 45 | if (pass < 0) { 46 | throw new NullPointerException("No render pass exists for layer: " + layer); 47 | } 48 | 49 | return pass; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/core/model/MixinItemColors.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.core.model; 2 | 3 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; 4 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; 5 | import me.jellysquid.mods.sodium.client.world.biome.ItemColorsExtended; 6 | import net.minecraft.client.renderer.color.IItemColor; 7 | import net.minecraft.client.renderer.color.ItemColors; 8 | import net.minecraft.item.Item; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.util.IItemProvider; 11 | import net.minecraftforge.registries.IRegistryDelegate; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | 17 | @Mixin(ItemColors.class) 18 | public class MixinItemColors implements ItemColorsExtended { 19 | private Reference2ReferenceMap, IItemColor> itemsToColor; 20 | 21 | private static final IItemColor DEFAULT_PROVIDER = (stack, tintIdx) -> -1; 22 | 23 | @Inject(method = "", at = @At("RETURN")) 24 | private void init(CallbackInfo ci) { 25 | this.itemsToColor = new Reference2ReferenceOpenHashMap<>(); 26 | this.itemsToColor.defaultReturnValue(DEFAULT_PROVIDER); 27 | } 28 | 29 | @Inject(method = "register", at = @At("HEAD")) 30 | private void preRegisterColor(IItemColor mapper, IItemProvider[] convertibles, CallbackInfo ci) { 31 | for (IItemProvider convertible : convertibles) { 32 | this.itemsToColor.put(convertible.asItem().delegate, mapper); 33 | } 34 | } 35 | 36 | @Override 37 | public IItemColor getColorProvider(ItemStack stack) { 38 | return this.itemsToColor.get(stack.getItem().delegate); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/buffer/GlBuffer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.buffer; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.GlObject; 4 | import me.jellysquid.mods.sodium.client.gl.func.GlFunctions; 5 | import org.lwjgl.opengl.GL15; 6 | import org.lwjgl.opengl.GL31; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | public abstract class GlBuffer extends GlObject { 11 | protected int vertexCount = 0; 12 | protected int size; 13 | 14 | protected GlBuffer() { 15 | this.setHandle(GL15.glGenBuffers()); 16 | } 17 | 18 | public void unbind(int target) { 19 | GL15.glBindBuffer(target, 0); 20 | } 21 | 22 | public void bind(int target) { 23 | GL15.glBindBuffer(target, this.handle()); 24 | } 25 | 26 | public abstract void upload(int target, ByteBuffer buf); 27 | 28 | public abstract void allocate(int target, int size); 29 | 30 | public void upload(int target, VertexData data) { 31 | this.vertexCount = data.buffer.remaining() / data.format.getStride(); 32 | 33 | this.upload(target, data.buffer); 34 | } 35 | 36 | public void delete() { 37 | GL15.glDeleteBuffers(this.handle()); 38 | 39 | this.invalidateHandle(); 40 | this.size = 0; 41 | } 42 | 43 | public static void copy(GlBuffer src, GlBuffer dst, int readOffset, int writeOffset, int copyLen, int bufferSize) { 44 | src.bind(GL31.GL_COPY_READ_BUFFER); 45 | 46 | dst.bind(GL31.GL_COPY_WRITE_BUFFER); 47 | dst.allocate(GL31.GL_COPY_WRITE_BUFFER, bufferSize); 48 | 49 | GlFunctions.BUFFER_COPY.glCopyBufferSubData(GL31.GL_COPY_READ_BUFFER, GL31.GL_COPY_WRITE_BUFFER, readOffset, writeOffset, copyLen); 50 | 51 | dst.unbind(GL31.GL_COPY_WRITE_BUFFER); 52 | src.unbind(GL31.GL_COPY_READ_BUFFER); 53 | } 54 | 55 | public int getSize() { 56 | return this.size; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/util/GlMultiDrawBatch.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.util; 2 | 3 | import org.lwjgl.opengl.GL14; 4 | import org.lwjgl.system.MemoryUtil; 5 | 6 | import java.nio.IntBuffer; 7 | 8 | /** 9 | * Provides a fixed-size queue for batching draw calls for vertex data in the same buffer. This internally 10 | * uses {@link GL14#glMultiDrawArrays(int, IntBuffer, IntBuffer)} and should be compatible on any relevant platform. 11 | */ 12 | public class GlMultiDrawBatch { 13 | private final IntBuffer bufIndices; 14 | private final IntBuffer bufLen; 15 | private int count; 16 | private boolean isBuilding; 17 | 18 | public GlMultiDrawBatch(int capacity) { 19 | this.bufIndices = MemoryUtil.memAllocInt(capacity); 20 | this.bufLen = MemoryUtil.memAllocInt(capacity); 21 | } 22 | 23 | public IntBuffer getIndicesBuffer() { 24 | return this.bufIndices; 25 | } 26 | 27 | public IntBuffer getLengthBuffer() { 28 | return this.bufLen; 29 | } 30 | 31 | public void begin() { 32 | this.bufIndices.clear(); 33 | this.bufLen.clear(); 34 | this.count = 0; 35 | 36 | this.isBuilding = true; 37 | } 38 | 39 | public void end() { 40 | this.bufIndices.limit(this.count); 41 | this.bufLen.limit(this.count); 42 | 43 | this.isBuilding = false; 44 | } 45 | 46 | public boolean isEmpty() { 47 | return this.count <= 0; 48 | } 49 | 50 | public void addChunkRender(int first, int count) { 51 | int i = this.count++; 52 | this.bufIndices.put(i, first); 53 | this.bufLen.put(i, count); 54 | } 55 | 56 | public boolean isBuilding() { 57 | return this.isBuilding; 58 | } 59 | 60 | public void delete() { 61 | MemoryUtil.memFree(this.bufIndices); 62 | MemoryUtil.memFree(this.bufLen); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/buffer_builder/fast_advance/MixinBufferBuilder.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.buffer_builder.fast_advance; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.mojang.blaze3d.vertex.DefaultColorVertexBuilder; 5 | import net.minecraft.client.renderer.BufferBuilder; 6 | import net.minecraft.client.renderer.vertex.VertexFormat; 7 | import net.minecraft.client.renderer.vertex.VertexFormatElement; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(BufferBuilder.class) 13 | public abstract class MixinBufferBuilder extends DefaultColorVertexBuilder { 14 | @Shadow 15 | private VertexFormat vertexFormat; 16 | 17 | @Shadow 18 | private VertexFormatElement vertexFormatElement; 19 | 20 | @Shadow 21 | private int nextElementBytes; 22 | 23 | @Shadow 24 | private int vertexFormatIndex; 25 | 26 | /** 27 | * @author JellySquid 28 | * @reason Remove modulo operations and recursion 29 | */ 30 | @Overwrite 31 | public void nextVertexFormatIndex() { 32 | ImmutableList elements = this.vertexFormat.getElements(); 33 | 34 | do { 35 | this.nextElementBytes += this.vertexFormatElement.getSize(); 36 | 37 | // Wrap around the element pointer without using modulo 38 | if (++this.vertexFormatIndex >= elements.size()) { 39 | this.vertexFormatIndex -= elements.size(); 40 | } 41 | 42 | this.vertexFormatElement = elements.get(this.vertexFormatIndex); 43 | } while (this.vertexFormatElement.getUsage() == VertexFormatElement.Usage.PADDING); 44 | 45 | if (this.defaultColor && this.vertexFormatElement.getUsage() == VertexFormatElement.Usage.COLOR) { 46 | this.color(this.defaultRed, this.defaultGreen, this.defaultBlue, this.defaultAlpha); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/light/cache/ArrayLightDataCache.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.light.cache; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.data.LightDataAccess; 4 | import net.minecraft.world.IBlockDisplayReader; 5 | 6 | import java.util.Arrays; 7 | 8 | /** 9 | * A light data cache which uses a flat-array to store the light data for the blocks in a given chunk and its direct 10 | * neighbors. This is considerably faster than using a hash table to lookup values for a given block position and 11 | * can be re-used by {@link me.jellysquid.mods.sodium.client.world.WorldSlice} to avoid allocations. 12 | */ 13 | public class ArrayLightDataCache extends LightDataAccess { 14 | private final long[] light; 15 | private final int xSize, ySize, zSize; 16 | private int xOffset, yOffset, zOffset; 17 | 18 | public ArrayLightDataCache(int size) { 19 | this(size, size, size); 20 | } 21 | 22 | public ArrayLightDataCache(int xSize, int ySize, int zSize) { 23 | this.xSize = xSize; 24 | this.ySize = ySize; 25 | this.zSize = zSize; 26 | 27 | int len = xSize * ySize * zSize; 28 | 29 | this.light = new long[len]; 30 | } 31 | 32 | public void init(IBlockDisplayReader world, int x, int y, int z) { 33 | this.world = world; 34 | this.xOffset = x; 35 | this.yOffset = y; 36 | this.zOffset = z; 37 | 38 | Arrays.fill(this.light, 0L); 39 | } 40 | 41 | private int index(int x, int y, int z) { 42 | // TODO: simplify 43 | return (z - this.zOffset) * this.xSize * this.ySize + (y - this.yOffset) * this.zSize + x - this.xOffset; 44 | } 45 | 46 | @Override 47 | public long get(int x, int y, int z) { 48 | int l = this.index(x, y, z); 49 | 50 | long word = this.light[l]; 51 | 52 | if (word != 0) { 53 | return word; 54 | } 55 | 56 | return this.light[l] = this.compute(x, y, z); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/oneshot/ChunkOneshotGraphicsState.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.oneshot; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 4 | import me.jellysquid.mods.sodium.client.gl.util.BufferSlice; 5 | import me.jellysquid.mods.sodium.client.gl.util.MemoryTracker; 6 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; 7 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 8 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 9 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkMeshData; 10 | 11 | import java.util.Arrays; 12 | import java.util.Map; 13 | 14 | public abstract class ChunkOneshotGraphicsState extends ChunkGraphicsState { 15 | protected final MemoryTracker memoryTracker; 16 | private final long[] parts; 17 | 18 | protected ChunkOneshotGraphicsState(MemoryTracker memoryTracker, ChunkRenderContainer container) { 19 | super(container); 20 | 21 | this.memoryTracker = memoryTracker; 22 | this.parts = new long[ModelQuadFacing.COUNT]; 23 | } 24 | 25 | public long getModelPart(int facing) { 26 | return this.parts[facing]; 27 | } 28 | 29 | protected void setModelPart(ModelQuadFacing facing, long slice) { 30 | this.parts[facing.ordinal()] = slice; 31 | } 32 | 33 | public abstract void upload(ChunkMeshData mesh); 34 | 35 | public abstract void bind(); 36 | 37 | protected void setupModelParts(ChunkMeshData meshData, GlVertexFormat vertexFormat) { 38 | int stride = vertexFormat.getStride(); 39 | 40 | Arrays.fill(this.parts, 0L); 41 | 42 | for (Map.Entry entry : meshData.getSlices()) { 43 | ModelQuadFacing facing = entry.getKey(); 44 | BufferSlice slice = entry.getValue(); 45 | 46 | this.setModelPart(facing, BufferSlice.pack(slice.start / stride, slice.len / stride)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/pipeline/context/GlobalRenderContext.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.pipeline.context; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.LightPipelineProvider; 4 | import me.jellysquid.mods.sodium.client.model.light.cache.HashLightDataCache; 5 | import me.jellysquid.mods.sodium.client.model.quad.blender.BiomeColorBlender; 6 | import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer; 7 | import me.jellysquid.mods.sodium.client.render.pipeline.RenderContextCommon; 8 | import net.minecraft.client.Minecraft; 9 | import net.minecraft.world.IBlockDisplayReader; 10 | 11 | import java.util.WeakHashMap; 12 | 13 | public class GlobalRenderContext { 14 | private static final WeakHashMap INSTANCES = new WeakHashMap<>(); 15 | 16 | private final BlockRenderer blockRenderer; 17 | private final HashLightDataCache lightCache; 18 | 19 | private GlobalRenderContext(IBlockDisplayReader world) { 20 | Minecraft client = Minecraft.getInstance(); 21 | 22 | this.lightCache = new HashLightDataCache(world); 23 | 24 | BiomeColorBlender biomeColorBlender = RenderContextCommon.createBiomeColorBlender(); 25 | LightPipelineProvider lightPipelineProvider = new LightPipelineProvider(this.lightCache); 26 | 27 | this.blockRenderer = new BlockRenderer(client, lightPipelineProvider, biomeColorBlender); 28 | } 29 | 30 | public BlockRenderer getBlockRenderer() { 31 | return this.blockRenderer; 32 | } 33 | 34 | public static GlobalRenderContext getInstance(IBlockDisplayReader world) { 35 | return INSTANCES.computeIfAbsent(world, GlobalRenderContext::createInstance); 36 | } 37 | 38 | private static GlobalRenderContext createInstance(IBlockDisplayReader world) { 39 | return new GlobalRenderContext(world); 40 | } 41 | 42 | public static void reset() { 43 | for (GlobalRenderContext context : INSTANCES.values()) { 44 | context.lightCache.clear(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/backends/gl43/GL43GraphicsState.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.backends.gl43; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.arena.GlBufferRegion; 4 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 5 | import me.jellysquid.mods.sodium.client.gl.util.BufferSlice; 6 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; 7 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 8 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 9 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkMeshData; 10 | import me.jellysquid.mods.sodium.client.render.chunk.region.ChunkRegion; 11 | 12 | import java.util.Map; 13 | 14 | public class GL43GraphicsState extends ChunkGraphicsState { 15 | private final ChunkRegion region; 16 | 17 | private final GlBufferRegion segment; 18 | private final long[] parts; 19 | 20 | public GL43GraphicsState(ChunkRenderContainer container, ChunkRegion region, GlBufferRegion segment, ChunkMeshData meshData, GlVertexFormat vertexFormat) { 21 | super(container); 22 | 23 | this.region = region; 24 | this.segment = segment; 25 | 26 | this.parts = new long[ModelQuadFacing.COUNT]; 27 | 28 | for (Map.Entry entry : meshData.getSlices()) { 29 | ModelQuadFacing facing = entry.getKey(); 30 | BufferSlice slice = entry.getValue(); 31 | 32 | int start = (segment.getStart() + slice.start) / vertexFormat.getStride(); 33 | int count = slice.len / vertexFormat.getStride(); 34 | 35 | this.parts[facing.ordinal()] = BufferSlice.pack(start, count); 36 | } 37 | } 38 | 39 | @Override 40 | public void delete() { 41 | this.segment.delete(); 42 | } 43 | 44 | public ChunkRegion getRegion() { 45 | return this.region; 46 | } 47 | 48 | public long getModelPart(int facing) { 49 | return this.parts[facing]; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/shader/ChunkFogMode.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.shader; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.jellysquid.mods.sodium.client.gl.shader.ShaderConstants; 5 | import me.jellysquid.mods.sodium.client.gl.util.GlFogHelper; 6 | import org.lwjgl.opengl.GL11; 7 | 8 | import java.util.List; 9 | 10 | public enum ChunkFogMode { 11 | NONE(ChunkShaderFogComponent.None::new, ImmutableList.of()), 12 | LINEAR(ChunkShaderFogComponent.Linear::new, ImmutableList.of("USE_FOG", "USE_FOG_LINEAR")), 13 | EXP2(ChunkShaderFogComponent.Exp2::new, ImmutableList.of("USE_FOG", "USE_FOG_EXP2")); 14 | 15 | private final ShaderComponent.Factory factory; 16 | private final List defines; 17 | 18 | ChunkFogMode(ShaderComponent.Factory factory, List defines) { 19 | this.factory = factory; 20 | this.defines = defines; 21 | } 22 | 23 | public ShaderComponent.Factory getFactory() { 24 | return this.factory; 25 | } 26 | 27 | public List getDefines() { 28 | return this.defines; 29 | } 30 | 31 | /** 32 | * Retrieves the current fog mode from the fixed-function pipeline. 33 | */ 34 | public static ChunkFogMode getActiveMode() { 35 | if (!GlFogHelper.isFogEnabled()) { 36 | return ChunkFogMode.NONE; 37 | } 38 | 39 | int mode = GL11.glGetInteger(GL11.GL_FOG_MODE); 40 | 41 | switch (mode) { 42 | case GL11.GL_EXP2: 43 | case GL11.GL_EXP: 44 | return ChunkFogMode.EXP2; 45 | case GL11.GL_LINEAR: 46 | return ChunkFogMode.LINEAR; 47 | default: 48 | throw new UnsupportedOperationException("Unknown fog mode: " + mode); 49 | } 50 | } 51 | 52 | public void addConstants(ShaderConstants.Builder constants) { 53 | for (String define : this.defines) { 54 | constants.define(define); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/ModelQuadViewMutable.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | 6 | /** 7 | * Provides a mutable view to a model quad. 8 | */ 9 | public interface ModelQuadViewMutable extends ModelQuadView { 10 | /** 11 | * Sets the x-position of the vertex at index {@param idx} to the value {@param x} 12 | */ 13 | void setX(int idx, float x); 14 | 15 | /** 16 | * Sets the y-position of the vertex at index {@param idx} to the value {@param y} 17 | */ 18 | void setY(int idx, float y); 19 | 20 | /** 21 | * Sets the z-position of the vertex at index {@param idx} to the value {@param z} 22 | */ 23 | void setZ(int idx, float z); 24 | 25 | /** 26 | * Sets the integer-encoded color of the vertex at index {@param idx} to the value {@param color} 27 | */ 28 | void setColor(int idx, int color); 29 | 30 | /** 31 | * Sets the texture x-coordinate of the vertex at index {@param idx} to the value {@param u} 32 | */ 33 | void setTexU(int idx, float u); 34 | 35 | /** 36 | * Sets the texture y-coordinate of the vertex at index {@param idx} to the value {@param v} 37 | */ 38 | void setTexV(int idx, float v); 39 | 40 | /** 41 | * Sets the light map texture coordinate of the vertex at index {@param idx} to the value {@param light} 42 | */ 43 | void setLight(int idx, int light); 44 | 45 | /** 46 | * Sets the integer-encoded normal vector of the vertex at index {@param idx} to the value {@param light} 47 | */ 48 | void setNormal(int idx, int norm); 49 | 50 | /** 51 | * Sets the bit-flag field which contains the {@link ModelQuadFlags} for this quad 52 | */ 53 | void setFlags(int flags); 54 | 55 | /** 56 | * Sets the sprite used by this quad 57 | */ 58 | void setSprite(TextureAtlasSprite sprite); 59 | 60 | /** 61 | * Sets the color index used by this quad 62 | */ 63 | void setColorIndex(int index); 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/backends/gl20/GL20GraphicsState.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.backends.gl20; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 4 | import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; 5 | import me.jellysquid.mods.sodium.client.gl.buffer.GlMutableBuffer; 6 | import me.jellysquid.mods.sodium.client.gl.buffer.VertexData; 7 | import me.jellysquid.mods.sodium.client.gl.util.MemoryTracker; 8 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 9 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkMeshData; 10 | import me.jellysquid.mods.sodium.client.render.chunk.oneshot.ChunkOneshotGraphicsState; 11 | import org.lwjgl.opengl.GL15; 12 | 13 | public class GL20GraphicsState extends ChunkOneshotGraphicsState { 14 | private final GlBuffer vertexBuffer; 15 | private GlVertexFormat vertexFormat; 16 | 17 | public GL20GraphicsState(MemoryTracker memoryTracker, ChunkRenderContainer container) { 18 | super(memoryTracker, container); 19 | 20 | this.vertexBuffer = new GlMutableBuffer(GL15.GL_STATIC_DRAW); 21 | } 22 | 23 | @Override 24 | public void delete() { 25 | this.memoryTracker.onMemoryFreeAndRelease(this.vertexBuffer.getSize()); 26 | 27 | this.vertexBuffer.delete(); 28 | } 29 | 30 | @Override 31 | public void upload(ChunkMeshData meshData) { 32 | VertexData data = meshData.takeVertexData(); 33 | 34 | this.vertexBuffer.bind(GL15.GL_ARRAY_BUFFER); 35 | 36 | this.memoryTracker.onMemoryFreeAndRelease(this.vertexBuffer.getSize()); 37 | this.vertexBuffer.upload(GL15.GL_ARRAY_BUFFER, data); 38 | this.memoryTracker.onMemoryAllocateAndUse(this.vertexBuffer.getSize()); 39 | 40 | this.vertexBuffer.unbind(GL15.GL_ARRAY_BUFFER); 41 | 42 | this.vertexFormat = data.format; 43 | 44 | this.setupModelParts(meshData, this.vertexFormat); 45 | } 46 | 47 | @Override 48 | public void bind() { 49 | this.vertexBuffer.bind(GL15.GL_ARRAY_BUFFER); 50 | this.vertexFormat.bindVertexAttributes(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/options/control/ControlElement.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.options.control; 2 | 3 | import com.mojang.blaze3d.matrix.MatrixStack; 4 | import me.jellysquid.mods.sodium.client.gui.options.Option; 5 | import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; 6 | import me.jellysquid.mods.sodium.client.util.Dim2i; 7 | import net.minecraft.util.text.TextFormatting; 8 | 9 | public class ControlElement extends AbstractWidget { 10 | protected final Option option; 11 | 12 | protected final Dim2i dim; 13 | 14 | protected boolean hovered; 15 | 16 | public ControlElement(Option option, Dim2i dim) { 17 | this.option = option; 18 | this.dim = dim; 19 | } 20 | 21 | public boolean isHovered() { 22 | return this.hovered; 23 | } 24 | 25 | @Override 26 | public void render(MatrixStack matrixStack, int mouseX, int mouseY, float delta) { 27 | String name = this.option.getName(); 28 | String label; 29 | 30 | if (this.hovered && this.font.getStringWidth(name) > (this.dim.getWidth() - this.option.getControl().getMaxWidth())) { 31 | name = name.substring(0, Math.min(name.length(), 10)) + "..."; 32 | } 33 | 34 | if (this.option.isAvailable()) { 35 | if (this.option.hasChanged()) { 36 | label = TextFormatting.ITALIC + name + " *"; 37 | } else { 38 | label = TextFormatting.WHITE + name; 39 | } 40 | } else { 41 | label = String.valueOf(TextFormatting.GRAY) + TextFormatting.STRIKETHROUGH + name; 42 | } 43 | 44 | this.hovered = this.dim.containsCursor(mouseX, mouseY); 45 | 46 | 47 | this.drawRect(this.dim.getOriginX(), this.dim.getOriginY(), this.dim.getLimitX(), this.dim.getLimitY(), this.hovered ? 0xE0000000 : 0x90000000); 48 | this.drawString(matrixStack, label, this.dim.getOriginX() + 6, this.dim.getCenterY() - 4, 0xFFFFFFFF); 49 | } 50 | 51 | public Option getOption() { 52 | return this.option; 53 | } 54 | 55 | public Dim2i getDimensions() { 56 | return this.dim; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/BufferUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util; 2 | 3 | import org.lwjgl.system.MemoryUtil; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class BufferUtil { 8 | /** 9 | * Copies a slice of integers from the source array into the destination buffer at its current position. This exists 10 | * to facilitate fast copies of integer arrays from heap memory to native memory since the ByteBuffer interface 11 | * doesn't provide an optimized code path for it. 12 | * 13 | * If the destination buffer is a direct buffer to native memory, unsafe code will be used to copy the integer 14 | * array using intrinsics. Otherwise, the (slower) fallback path will be used which will work in any situation. 15 | * 16 | * @param data The source integer array 17 | * @param limit The number of integers to be copied 18 | * @param offset The starting offset in the source array to copy from 19 | * @param buffer The destination buffer 20 | */ 21 | public static void copyIntArray(int[] data, int limit, int offset, ByteBuffer buffer) { 22 | if (limit > data.length) { 23 | throw new IllegalArgumentException("Source array is too small"); 24 | } 25 | 26 | int bytes = limit * 4; 27 | 28 | // Underflow check 29 | if (buffer.capacity() - offset < bytes) { 30 | throw new IllegalArgumentException("Destination buffer is too small"); 31 | } 32 | 33 | if (UnsafeUtil.isAvailable() && buffer.isDirect()) { 34 | copyIntArrayUnsafe(data, limit, offset, MemoryUtil.memAddress(buffer)); 35 | } else { 36 | copyIntArrayDefault(data, limit, offset, buffer); 37 | } 38 | } 39 | 40 | private static void copyIntArrayUnsafe(int[] data, int limit, int offset, long addr) { 41 | UnsafeUtil.instance().copyMemory(data, UnsafeUtil.INT_ARRAY_OFFSET, null, addr + offset, limit * 4); 42 | } 43 | 44 | private static void copyIntArrayDefault(int[] data, int limit, int offset, ByteBuffer buffer) { 45 | for (int i = 0; i < limit; i++) { 46 | buffer.putInt(offset + (i * 4), data[i]); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/math/Matrix4fExtended.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.math; 2 | 3 | import net.minecraft.util.math.vector.Quaternion; 4 | 5 | public interface Matrix4fExtended { 6 | /** 7 | * Applies the specified rotation to this matrix in-place. 8 | * 9 | * @param quaternion The quaternion to rotate this matrix by 10 | */ 11 | void rotate(Quaternion quaternion); 12 | 13 | /** 14 | * Applies the specified translation to this matrix in-place. 15 | * 16 | * @param x The x-component of the translation 17 | * @param y The y-component of the translation 18 | * @param z The z-component of the translation 19 | */ 20 | void translate(float x, float y, float z); 21 | 22 | /** 23 | * Applies this matrix transformation to the given input vector, returning the x-component. Avoids the lack of 24 | * struct types in Java and allows for allocation-free return. 25 | * @param x The x-component of the vector 26 | * @param y The y-component of the vector 27 | * @param z The z-component of the vector 28 | * @return The x-component of the transformed input vector 29 | */ 30 | float transformVecX(float x, float y, float z); 31 | 32 | /** 33 | * Applies this matrix transformation to the given input vector, returning the y-component. Avoids the lack of 34 | * struct types in Java and allows for allocation-free return. 35 | * @param x The x-component of the vector 36 | * @param y The y-component of the vector 37 | * @param z The z-component of the vector 38 | * @return The y-component of the transformed input vector 39 | */ 40 | float transformVecY(float x, float y, float z); 41 | 42 | /** 43 | * Applies this matrix transformation to the given input vector, returning the z-component. Avoids the lack of 44 | * struct types in Java and allows for allocation-free return. 45 | * @param x The x-component of the vector 46 | * @param y The y-component of the vector 47 | * @param z The z-component of the vector 48 | * @return The z-component of the transformed input vector 49 | */ 50 | float transformVecZ(float x, float y, float z); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/shader/ShaderConstants.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.shader; 2 | 3 | import java.util.*; 4 | 5 | public class ShaderConstants { 6 | private final List defines; 7 | 8 | private ShaderConstants(List defines) { 9 | this.defines = defines; 10 | } 11 | 12 | public List getDefineStrings() { 13 | return this.defines; 14 | } 15 | 16 | public static ShaderConstants fromStringList(List defines) { 17 | ShaderConstants.Builder builder = new ShaderConstants.Builder(); 18 | 19 | for (String define : defines) { 20 | builder.define(define); 21 | } 22 | 23 | return builder.build(); 24 | } 25 | 26 | public static ShaderConstants.Builder builder() { 27 | return new Builder(); 28 | } 29 | 30 | public static class Builder { 31 | private static final String EMPTY_VALUE = ""; 32 | 33 | private final HashMap constants = new HashMap<>(); 34 | 35 | private Builder() { 36 | 37 | } 38 | 39 | public void define(String name) { 40 | this.define(name, EMPTY_VALUE); 41 | } 42 | 43 | public void define(String name, String value) { 44 | String prev = this.constants.get(name); 45 | 46 | if (prev != null) { 47 | throw new IllegalArgumentException("Constant " + name + " is already defined with value " + prev); 48 | } 49 | 50 | this.constants.put(name, value); 51 | } 52 | 53 | public ShaderConstants build() { 54 | List defines = new ArrayList<>(this.constants.size()); 55 | 56 | for (Map.Entry entry : this.constants.entrySet()) { 57 | String key = entry.getKey(); 58 | String value = entry.getValue(); 59 | 60 | if (value.length() <= 0) { 61 | defines.add("#define " + key); 62 | } else { 63 | defines.add("#define " + key + " " + value); 64 | } 65 | } 66 | 67 | return new ShaderConstants(Collections.unmodifiableList(defines)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/func/GlVertexArrayFunctions.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.func; 2 | 3 | import org.lwjgl.opengl.ARBVertexArrayObject; 4 | import org.lwjgl.opengl.GL30; 5 | import org.lwjgl.opengl.GLCapabilities; 6 | 7 | /** 8 | * Requires OpenGL 3.0+ or the ARB_vertex_array_object extension. 9 | */ 10 | public enum GlVertexArrayFunctions { 11 | BASE { 12 | @Override 13 | public void glBindVertexArray(int id) { 14 | GL30.glBindVertexArray(id); 15 | } 16 | 17 | @Override 18 | public int glGenVertexArrays() { 19 | return GL30.glGenVertexArrays(); 20 | } 21 | 22 | @Override 23 | public void glDeleteVertexArrays(int id) { 24 | GL30.glDeleteVertexArrays(id); 25 | } 26 | }, 27 | ARB { 28 | @Override 29 | public void glBindVertexArray(int id) { 30 | ARBVertexArrayObject.glBindVertexArray(id); 31 | } 32 | 33 | @Override 34 | public int glGenVertexArrays() { 35 | return ARBVertexArrayObject.glGenVertexArrays(); 36 | } 37 | 38 | @Override 39 | public void glDeleteVertexArrays(int id) { 40 | ARBVertexArrayObject.glDeleteVertexArrays(id); 41 | } 42 | }, 43 | UNSUPPORTED { 44 | @Override 45 | public void glBindVertexArray(int id) { 46 | throw new UnsupportedOperationException(); 47 | } 48 | 49 | @Override 50 | public int glGenVertexArrays() { 51 | throw new UnsupportedOperationException(); 52 | } 53 | 54 | @Override 55 | public void glDeleteVertexArrays(int id) { 56 | throw new UnsupportedOperationException(); 57 | } 58 | }; 59 | 60 | static GlVertexArrayFunctions load(GLCapabilities capabilities) { 61 | if (capabilities.OpenGL30) { 62 | return BASE; 63 | } else if (capabilities.GL_ARB_vertex_array_object) { 64 | return ARB; 65 | } 66 | 67 | return UNSUPPORTED; 68 | } 69 | 70 | public abstract void glBindVertexArray(int id); 71 | 72 | public abstract int glGenVertexArrays(); 73 | 74 | public abstract void glDeleteVertexArrays(int id); 75 | } 76 | -------------------------------------------------------------------------------- /src/main/resources/chlorine.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "me.jellysquid.mods.sodium.mixin", 3 | "required": true, 4 | "compatibilityLevel": "JAVA_8", 5 | "refmap": "chlorine.refmap.json", 6 | "plugin": "me.jellysquid.mods.sodium.mixin.SodiumMixinPlugin", 7 | "injectors": { 8 | "defaultRequire": 1 9 | }, 10 | "client": [ 11 | "core.frustum.MixinFrustum", 12 | "core.matrix.MixinMatrix3f", 13 | "core.matrix.MixinMatrix4f", 14 | "core.model.MixinBlockColors", 15 | "core.model.MixinItemColors", 16 | "core.pipeline.MixinBakedQuad", 17 | "core.pipeline.MixinVertexConsumer", 18 | "features.block.MixinBlockModelRenderer", 19 | "features.block.MixinBufferBuilder", 20 | "features.block.MixinWorldRenderer", 21 | "features.buffer_builder.fast_advance.MixinBufferBuilder", 22 | "features.buffer_builder.fast_sort.MixinBufferBuilder", 23 | "features.buffer_builder.intrinsics.MixinBufferBuilder", 24 | "features.buffer_builder.intrinsics.MixinSpriteTexturedVertexConsumer", 25 | "features.chunk_rendering.MixinChunkBuilder", 26 | "features.chunk_rendering.MixinClientWorld", 27 | "features.chunk_rendering.MixinLightmapTextureManager", 28 | "features.chunk_rendering.MixinWorldRenderer", 29 | "features.debug.MixinDebugHud", 30 | "features.entity.fast_render.MixinCuboid", 31 | "features.entity.fast_render.MixinModelPart", 32 | "features.entity.shadow_clipping.MixinEntityRenderDispatcher", 33 | "features.entity.smooth_lighting.MixinEntityRenderer", 34 | "features.gui.MixinDebugHud", 35 | "features.gui.font.MixinGlyphRenderer", 36 | "features.matrix_stack.MixinMatrixStack", 37 | "features.matrix_stack.MixinVertexConsumer", 38 | "features.model.MixinMultipartBakedModel", 39 | "features.options.MixinGameOptions", 40 | "features.options.MixinInGameHud", 41 | "features.options.MixinMinecraftClient", 42 | "features.options.MixinOptionsScreen", 43 | "features.options.MixinWorldRenderer", 44 | "features.particle.cull.MixinParticleManager", 45 | "features.particle.fast_render.MixinBillboardParticle", 46 | "features.render_layer.MixinRenderLayers", 47 | "features.texture_tracking.MixinSprite", 48 | "features.texture_tracking.MixinSpriteIdentifier", 49 | "features.world_ticking.MixinClientWorld" 50 | ] 51 | } -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gl/shader/ShaderLoader.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gl.shader; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import org.apache.commons.io.IOUtils; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.List; 10 | 11 | public class ShaderLoader { 12 | /** 13 | * Creates an OpenGL shader from GLSL sources. The GLSL source file should be made available on the classpath at the 14 | * path of `/assets/{namespace}/shaders/{path}`. User defines can be used to declare variables in the shader source 15 | * after the version header, allowing for conditional compilation with macro code. 16 | * 17 | * @param type The type of shader to create 18 | * @param name The identifier used to locate the shader source file 19 | * @param constants A list of constants for shader specialization 20 | * @return An OpenGL shader object compiled with the given user defines 21 | */ 22 | public static GlShader loadShader(ShaderType type, ResourceLocation name, ShaderConstants constants) { 23 | return new GlShader(type, name, getShaderSource(getShaderPath(name)), constants); 24 | } 25 | 26 | /** 27 | * Use {@link ShaderLoader#loadShader(ShaderType, ResourceLocation, ShaderConstants)} instead. This will be removed. 28 | */ 29 | @Deprecated 30 | public static GlShader loadShader(ShaderType type, ResourceLocation name, List constants) { 31 | return new GlShader(type, name, getShaderSource(getShaderPath(name)), ShaderConstants.fromStringList(constants)); 32 | } 33 | 34 | private static String getShaderPath(ResourceLocation name) { 35 | return String.format("/assets/%s/shaders/%s", name.getNamespace(), name.getPath()); 36 | } 37 | 38 | private static String getShaderSource(String path) { 39 | try (InputStream in = ShaderLoader.class.getResourceAsStream(path)) { 40 | if (in == null) { 41 | throw new RuntimeException("Shader not found: " + path); 42 | } 43 | 44 | return IOUtils.toString(in, StandardCharsets.UTF_8); 45 | } catch (IOException e) { 46 | throw new RuntimeException("Could not read shader sources", e); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/gui/font/MixinGlyphRenderer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.gui.font; 2 | 3 | import com.mojang.blaze3d.vertex.IVertexBuilder; 4 | import me.jellysquid.mods.sodium.client.model.consumer.GlyphVertexConsumer; 5 | import me.jellysquid.mods.sodium.client.util.color.ColorABGR; 6 | import net.minecraft.client.gui.fonts.TexturedGlyph; 7 | import net.minecraft.util.math.vector.Matrix4f; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Overwrite; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(TexturedGlyph.class) 14 | public class MixinGlyphRenderer { 15 | @Shadow 16 | @Final 17 | private float minX; 18 | 19 | @Shadow 20 | @Final 21 | private float maxX; 22 | 23 | @Shadow 24 | @Final 25 | private float minY; 26 | 27 | @Shadow 28 | @Final 29 | private float maxY; 30 | 31 | @Shadow 32 | @Final 33 | private float u0; 34 | 35 | @Shadow 36 | @Final 37 | private float u1; 38 | 39 | @Shadow 40 | @Final 41 | private float v0; 42 | 43 | @Shadow 44 | @Final 45 | private float v1; 46 | 47 | /** 48 | * @reason Use intrinsics 49 | * @author JellySquid 50 | */ 51 | @Overwrite 52 | public void render(boolean italic, float x, float y, Matrix4f matrix, IVertexBuilder vertexConsumer, float red, float green, float blue, float alpha, int light) { 53 | float x1 = x + this.minX; 54 | float x2 = x + this.maxX; 55 | float y1 = this.minY - 3.0F; 56 | float y2 = this.maxY - 3.0F; 57 | float h1 = y + y1; 58 | float h2 = y + y2; 59 | float w1 = italic ? 1.0F - 0.25F * y1 : 0.0F; 60 | float w2 = italic ? 1.0F - 0.25F * y2 : 0.0F; 61 | 62 | int color = ColorABGR.pack(red, green, blue, alpha); 63 | 64 | GlyphVertexConsumer glyphs = ((GlyphVertexConsumer) vertexConsumer); 65 | glyphs.vertexGlyph(matrix, x1 + w1, h1, 0.0F, color, this.u0, this.v0, light); 66 | glyphs.vertexGlyph(matrix, x1 + w2, h2, 0.0F, color, this.u0, this.v1, light); 67 | glyphs.vertexGlyph(matrix, x2 + w2, h2, 0.0F, color, this.u1, this.v1, light); 68 | glyphs.vertexGlyph(matrix, x2 + w1, h1, 0.0F, color, this.u1, this.v0, light); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/tasks/ChunkRenderBuildTask.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.tasks; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 4 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; 5 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildResult; 6 | import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderContext; 7 | import me.jellysquid.mods.sodium.client.util.task.CancellationSource; 8 | 9 | /** 10 | * Build tasks are immutable jobs (with optional prioritization) which contain all the necessary state to perform 11 | * chunk mesh updates or quad sorting off the main thread. 12 | * 13 | * When a task is constructed on the main thread, it should copy all the state it requires in order to complete the task 14 | * without further synchronization. The task will then be scheduled for async execution on a thread pool. 15 | * 16 | * After the task completes, it returns a "build result" which contains any computed data that needs to be handled 17 | * on the main thread. 18 | * 19 | * @param The graphics state of the chunk render 20 | */ 21 | public abstract class ChunkRenderBuildTask { 22 | /** 23 | * Executes the given build task asynchronously from the calling thread. The implementation should be careful not 24 | * to access or modify global mutable state. 25 | * 26 | * @param pipeline The render pipeline to use for building this chunk 27 | * @param buffers The temporary scratch buffers for rendering block data 28 | * @param cancellationSource The cancellation source which can be used to query if the task is cancelled 29 | * @return The build result of this task, containing any data which needs to be uploaded on the main-thread, or null 30 | * if the task was cancelled. 31 | */ 32 | public abstract ChunkBuildResult performBuild(ChunkRenderContext pipeline, ChunkBuildBuffers buffers, 33 | CancellationSource cancellationSource); 34 | 35 | /** 36 | * Called on the main render thread when the task's execution returns. The implementation should release any 37 | * resources it's still holding onto at this point. 38 | */ 39 | public abstract void releaseResources(); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/chunk_rendering/MixinClientWorld.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.chunk_rendering; 2 | 3 | import me.jellysquid.mods.sodium.client.world.ClientWorldExtended; 4 | import me.jellysquid.mods.sodium.client.world.SodiumChunkManager; 5 | import net.minecraft.client.multiplayer.ClientChunkProvider; 6 | import net.minecraft.client.network.play.ClientPlayNetHandler; 7 | import net.minecraft.client.renderer.WorldRenderer; 8 | import net.minecraft.client.world.ClientWorld; 9 | import net.minecraft.profiler.IProfiler; 10 | import net.minecraft.util.RegistryKey; 11 | import net.minecraft.world.DimensionType; 12 | import net.minecraft.world.World; 13 | import org.spongepowered.asm.mixin.Dynamic; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.Redirect; 18 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 19 | 20 | import java.util.function.Supplier; 21 | 22 | @Mixin(ClientWorld.class) 23 | public abstract class MixinClientWorld implements ClientWorldExtended { 24 | private long biomeSeed; 25 | 26 | /** 27 | * Captures the biome generation seed so that our own caches can make use of it. 28 | */ 29 | @Inject(method = "", at = @At("RETURN")) 30 | private void init(ClientPlayNetHandler netHandler, ClientWorld.ClientWorldInfo properties, RegistryKey worldKey, 31 | DimensionType dimensionType, int loadDistance, Supplier profiler, WorldRenderer renderer, 32 | boolean debugWorld, long seed, CallbackInfo ci) { 33 | this.biomeSeed = seed; 34 | } 35 | 36 | /** 37 | * Replace the client world chunk manager with our own implementation that is both faster and contains additional 38 | * features needed to pull off event-based rendering. 39 | */ 40 | @Dynamic 41 | @Redirect(method = "", at = @At(value = "NEW", target = "net/minecraft/client/multiplayer/ClientChunkProvider")) 42 | private static ClientChunkProvider redirectCreateChunkManager(ClientWorld world, int renderDistance) { 43 | return new SodiumChunkManager(world, renderDistance); 44 | } 45 | 46 | @Override 47 | public long getBiomeSeed() { 48 | return this.biomeSeed; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/UnsafeUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util; 2 | 3 | import dev.hanetzer.chlorine.common.Chlorine; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import sun.misc.Unsafe; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | public class UnsafeUtil { 10 | private static final boolean SUPPORTED; 11 | private static boolean AVAILABLE; 12 | 13 | private static final Unsafe UNSAFE; 14 | 15 | /** 16 | * The byte offset of the first element in an int[]. If unsafe intrinsics are not available on this platform, 17 | * the value will be -1. 18 | */ 19 | public static final long INT_ARRAY_OFFSET; 20 | 21 | static { 22 | UNSAFE = findUnsafe(); 23 | SUPPORTED = UNSAFE != null; 24 | 25 | if (SUPPORTED) { 26 | INT_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(int[].class); 27 | } else { 28 | INT_ARRAY_OFFSET = -1; 29 | } 30 | 31 | setEnabled(true); 32 | } 33 | 34 | private static Unsafe findUnsafe() { 35 | try { 36 | Field field = Unsafe.class.getDeclaredField("theUnsafe"); 37 | field.setAccessible(true); 38 | 39 | return (Unsafe) field.get(null); 40 | } catch (ReflectiveOperationException e) { 41 | Chlorine.log.warn("Could not find Unsafe intrinsics", e); 42 | } 43 | 44 | return null; 45 | } 46 | 47 | /** 48 | * @return True if unsafe intrinsics are available and enabled 49 | */ 50 | public static boolean isAvailable() { 51 | return AVAILABLE; 52 | } 53 | 54 | /** 55 | * @return True if unsafe intrinsics are supported on this platform 56 | */ 57 | public static boolean isSupported() { 58 | return SUPPORTED; 59 | } 60 | 61 | /** 62 | * Returns an exposed instance of {@link Unsafe}. 63 | * @throws UnsupportedOperationException If {@link UnsafeUtil#isAvailable()} is false 64 | */ 65 | public static Unsafe instance() { 66 | if (!isAvailable()) { 67 | throw new UnsupportedOperationException("Unsafe intrinsics are not available"); 68 | } 69 | 70 | return UNSAFE; 71 | } 72 | 73 | public static Unsafe instanceNullable() { 74 | return UNSAFE; 75 | } 76 | 77 | public static void setEnabled(boolean enabled) { 78 | AVAILABLE = isSupported() && enabled; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/region/ChunkRegion.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.region; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 4 | import me.jellysquid.mods.sodium.client.gl.arena.GlBufferArena; 5 | import me.jellysquid.mods.sodium.client.gl.array.GlVertexArray; 6 | import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; 7 | import me.jellysquid.mods.sodium.client.gl.util.MemoryTracker; 8 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFacing; 9 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; 10 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildResult; 11 | import me.jellysquid.mods.sodium.client.render.chunk.multidraw.ChunkDrawCallBatcher; 12 | 13 | public class ChunkRegion { 14 | private static final int EXPECTED_CHUNK_SIZE = 4 * 1024; 15 | 16 | private final GlBufferArena arena; 17 | private final GlVertexArray vao; 18 | private final ChunkDrawCallBatcher batch; 19 | 20 | private final ObjectArrayList> uploads; 21 | 22 | private GlBuffer prevBuffer; 23 | 24 | public ChunkRegion(MemoryTracker memoryTracker, int size) { 25 | int arenaSize = EXPECTED_CHUNK_SIZE * size; 26 | 27 | this.arena = new GlBufferArena(memoryTracker, arenaSize, arenaSize); 28 | this.uploads = new ObjectArrayList<>(); 29 | this.vao = new GlVertexArray(); 30 | 31 | this.batch = ChunkDrawCallBatcher.create(size * ModelQuadFacing.COUNT); 32 | } 33 | 34 | public GlBufferArena getBufferArena() { 35 | return this.arena; 36 | } 37 | 38 | public boolean isArenaEmpty() { 39 | return this.arena.isEmpty(); 40 | } 41 | 42 | public void deleteResources() { 43 | this.arena.delete(); 44 | this.vao.delete(); 45 | this.batch.delete(); 46 | } 47 | 48 | public ObjectArrayList> getUploadQueue() { 49 | return this.uploads; 50 | } 51 | 52 | public ChunkDrawCallBatcher getDrawBatcher() { 53 | return this.batch; 54 | } 55 | 56 | public GlVertexArray getVertexArray() { 57 | return this.vao; 58 | } 59 | 60 | public boolean isDirty() { 61 | return this.prevBuffer != this.arena.getBuffer(); 62 | } 63 | 64 | public void markClean() { 65 | this.prevBuffer = this.arena.getBuffer(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/backends/gl33/GL33GraphicsState.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.backends.gl33; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.array.GlVertexArray; 4 | import me.jellysquid.mods.sodium.client.gl.attribute.GlVertexFormat; 5 | import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; 6 | import me.jellysquid.mods.sodium.client.gl.buffer.GlMutableBuffer; 7 | import me.jellysquid.mods.sodium.client.gl.buffer.VertexData; 8 | import me.jellysquid.mods.sodium.client.gl.util.MemoryTracker; 9 | import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; 10 | import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkMeshData; 11 | import me.jellysquid.mods.sodium.client.render.chunk.oneshot.ChunkOneshotGraphicsState; 12 | import org.lwjgl.opengl.GL15; 13 | 14 | public class GL33GraphicsState extends ChunkOneshotGraphicsState { 15 | private final GlVertexArray vertexArray; 16 | private final GlBuffer vertexBuffer; 17 | 18 | public GL33GraphicsState(MemoryTracker memoryTracker, ChunkRenderContainer container) { 19 | super(memoryTracker, container); 20 | 21 | this.vertexBuffer = new GlMutableBuffer(GL15.GL_STATIC_DRAW); 22 | this.vertexArray = new GlVertexArray(); 23 | } 24 | 25 | @Override 26 | public void upload(ChunkMeshData meshData) { 27 | VertexData vertexData = meshData.takeVertexData(); 28 | 29 | this.vertexArray.bind(); 30 | 31 | this.vertexBuffer.bind(GL15.GL_ARRAY_BUFFER); 32 | 33 | this.memoryTracker.onMemoryFreeAndRelease(this.vertexBuffer.getSize()); 34 | this.vertexBuffer.upload(GL15.GL_ARRAY_BUFFER, vertexData); 35 | this.memoryTracker.onMemoryAllocateAndUse(this.vertexBuffer.getSize()); 36 | 37 | GlVertexFormat vertexFormat = vertexData.format; 38 | vertexFormat.bindVertexAttributes(); 39 | vertexFormat.enableVertexAttributes(); 40 | 41 | this.setupModelParts(meshData, vertexFormat); 42 | 43 | this.vertexBuffer.unbind(GL15.GL_ARRAY_BUFFER); 44 | this.vertexArray.unbind(); 45 | } 46 | 47 | @Override 48 | public void bind() { 49 | this.vertexArray.bind(); 50 | } 51 | 52 | @Override 53 | public void delete() { 54 | this.memoryTracker.onMemoryFreeAndRelease(this.vertexBuffer.getSize()); 55 | 56 | this.vertexBuffer.delete(); 57 | this.vertexArray.delete(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/resources/assets/sodium/shaders/chunk_glsl110.f.glsl: -------------------------------------------------------------------------------- 1 | #version 110 2 | 3 | // Interpolated vertex attributes 4 | varying vec4 v_Color; // The interpolated vertex color 5 | varying vec2 v_TexCoord; // The interpolated block texture coordinates 6 | varying vec2 v_LightCoord; // The interpolated light map texture coordinates 7 | varying float v_MipFactor; 8 | 9 | // Uniforms 10 | uniform sampler2D u_BlockTex; // The block texture sampler 11 | uniform sampler2D u_LightTex; // The light map texture sampler 12 | 13 | #ifdef USE_MULTITEX 14 | uniform sampler2D u_BlockTexMipped; // The block texture sampler (with mipmapping) 15 | #endif 16 | 17 | #ifdef USE_FOG 18 | varying float v_FragDistance; 19 | uniform vec4 u_FogColor; // The color of the fog 20 | #endif 21 | 22 | #ifdef USE_FOG_EXP2 23 | uniform float u_FogDensity; 24 | 25 | // e^(-density * c^2) 26 | float getFogFactor() { 27 | float dist = v_FragDistance * u_FogDensity; 28 | return 1.0 / exp2(dist * dist); 29 | } 30 | #endif 31 | 32 | #ifdef USE_FOG_LINEAR 33 | uniform float u_FogLength; // FogStart - FogEnd 34 | uniform float u_FogEnd; 35 | 36 | // (end - dist) / (end - start) 37 | float getFogFactor() { 38 | return (u_FogEnd - v_FragDistance) / u_FogLength; 39 | } 40 | #endif 41 | 42 | void main() { 43 | vec4 sampleBlockTex; 44 | 45 | #ifdef USE_MULTITEX 46 | sampleBlockTex = mix( 47 | texture2D(u_BlockTex, v_TexCoord), 48 | texture2D(u_BlockTexMipped, v_TexCoord), 49 | v_MipFactor); 50 | #else 51 | sampleBlockTex = texture2D(u_BlockTex, v_TexCoord); 52 | #endif 53 | 54 | // TODO: Mipmap textures have partial transparency and render as black 55 | // We should try to fix this outside of shader code 56 | // This re-implements the glAlphaFunc call that Minecraft uses for cutout rendering 57 | if (sampleBlockTex.a < 0.5) { 58 | sampleBlockTex.a = 0.0; 59 | } 60 | 61 | // Light map texture sample 62 | vec4 sampleLightTex = texture2D(u_LightTex, v_LightCoord); 63 | 64 | // Blend the colors from both textures and the vertex itself 65 | vec4 diffuseColor = sampleBlockTex * sampleLightTex * v_Color; 66 | 67 | #ifdef USE_FOG 68 | float fogFactor = clamp(getFogFactor(), 0.0, 1.0); 69 | 70 | gl_FragColor = mix(u_FogColor, diffuseColor, fogFactor); 71 | gl_FragColor.a = diffuseColor.a; 72 | #else 73 | // No fog is being used, so the fragment color is just that of the blended texture color 74 | gl_FragColor = diffuseColor; 75 | #endif 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/gui/widgets/FlatButtonWidget.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.gui.widgets; 2 | 3 | import com.mojang.blaze3d.matrix.MatrixStack; 4 | import me.jellysquid.mods.sodium.client.util.Dim2i; 5 | import net.minecraft.client.gui.IRenderable; 6 | 7 | public class FlatButtonWidget extends AbstractWidget implements IRenderable { 8 | private final Dim2i dim; 9 | private final String label; 10 | private final Runnable action; 11 | 12 | private boolean selected; 13 | private boolean enabled = true; 14 | private boolean visible = true; 15 | 16 | public FlatButtonWidget(Dim2i dim, String label, Runnable action) { 17 | this.dim = dim; 18 | this.label = label; 19 | this.action = action; 20 | } 21 | 22 | @Override 23 | public void render(MatrixStack matrixStack, int mouseX, int mouseY, float delta) { 24 | if (!this.visible) { 25 | return; 26 | } 27 | 28 | boolean hovered = this.dim.containsCursor(mouseX, mouseY); 29 | 30 | int backgroundColor = this.enabled ? (hovered ? 0xE0000000 : 0x90000000) : 0x60000000; 31 | int textColor = this.enabled ? 0xFFFFFFFF : 0x90FFFFFF; 32 | 33 | int strWidth = this.font.getStringWidth(this.label); 34 | 35 | this.drawRect(this.dim.getOriginX(), this.dim.getOriginY(), this.dim.getLimitX(), this.dim.getLimitY(), backgroundColor); 36 | this.drawString(matrixStack, this.label, this.dim.getCenterX() - (strWidth / 2), this.dim.getCenterY() - 4, textColor); 37 | 38 | if (this.enabled && this.selected) { 39 | this.drawRect(this.dim.getOriginX(), this.dim.getLimitY() - 1, this.dim.getLimitX(), this.dim.getLimitY(), 0xFF94E4D3); 40 | } 41 | } 42 | 43 | public void setSelected(boolean selected) { 44 | this.selected = selected; 45 | } 46 | 47 | @Override 48 | public boolean mouseClicked(double mouseX, double mouseY, int button) { 49 | if (!this.enabled) { 50 | return false; 51 | } 52 | 53 | if (button == 0 && this.dim.containsCursor(mouseX, mouseY)) { 54 | this.action.run(); 55 | this.playClickSound(); 56 | 57 | return true; 58 | } 59 | 60 | return false; 61 | } 62 | 63 | public void setEnabled(boolean enabled) { 64 | this.enabled = enabled; 65 | } 66 | 67 | public void setVisible(boolean visibel) { 68 | this.visible = visibel; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/color/ColorARGB.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util.color; 2 | 3 | /** 4 | * Provides some utilities for packing and unpacking color components from packed integer colors in ARGB format. This 5 | * packed format is used by most of Minecraft, but special care must be taken to pack it into ABGR format before passing 6 | * it to OpenGL attributes. 7 | * 8 | * | 32 | 24 | 16 | 8 | 9 | * | 0110 1100 | 0110 1100 | 0110 1100 | 0110 1100 | 10 | * | Alpha | Red | Green | Blue | 11 | */ 12 | public class ColorARGB implements ColorU8 { 13 | /** 14 | * Packs the specified color components into big-endian format for consumption by OpenGL. 15 | * @param r The red component of the color 16 | * @param g The green component of the color 17 | * @param b The blue component of the color 18 | * @param a The alpha component of the color 19 | */ 20 | public static int pack(int r, int g, int b, int a) { 21 | return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); 22 | } 23 | 24 | /** 25 | * @param color The packed 32-bit ARGB color to unpack 26 | * @return The red color component in the range of 0..255 27 | */ 28 | public static int unpackAlpha(int color) { 29 | return color >> 24 & 0xFF; 30 | } 31 | 32 | /** 33 | * @param color The packed 32-bit ARGB color to unpack 34 | * @return The red color component in the range of 0..255 35 | */ 36 | public static int unpackRed(int color) { 37 | return color >> 16 & 0xFF; 38 | } 39 | 40 | /** 41 | * @param color The packed 32-bit ARGB color to unpack 42 | * @return The green color component in the range of 0..255 43 | */ 44 | public static int unpackGreen(int color) { 45 | return color >> 8 & 0xFF; 46 | } 47 | 48 | /** 49 | * @param color The packed 32-bit ARGB color to unpack 50 | * @return The blue color component in the range of 0..255 51 | */ 52 | public static int unpackBlue(int color) { 53 | return color & 0xFF; 54 | } 55 | 56 | /** 57 | * Re-packs the ARGB color into a aBGR color with the specified alpha component. 58 | */ 59 | public static int toABGR(int color, int alpha) { 60 | return Integer.reverseBytes(color << 8 | alpha); 61 | } 62 | 63 | public static int toABGR(int color) { 64 | return Integer.reverseBytes(color << 8); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/world/biome/BiomeCacheManager.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.world.biome; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2ReferenceLinkedOpenHashMap; 4 | import me.jellysquid.mods.sodium.client.world.WorldSlice; 5 | import me.jellysquid.mods.sodium.common.util.pool.ObjectPool; 6 | import net.minecraft.util.math.SectionPos; 7 | import net.minecraft.world.biome.IBiomeMagnifier; 8 | 9 | public class BiomeCacheManager { 10 | private static final int CACHE_SIZE = 256; 11 | private static final int ARENA_SIZE = 64; 12 | 13 | private final ObjectPool pool; 14 | private final Long2ReferenceLinkedOpenHashMap caches = new Long2ReferenceLinkedOpenHashMap<>(CACHE_SIZE, 0.5f); 15 | 16 | public BiomeCacheManager(IBiomeMagnifier type, long seed) { 17 | this.pool = new ObjectPool<>(ARENA_SIZE, () -> new BiomeCache(type, seed)); 18 | } 19 | 20 | public void populateArrays(int centerX, int centerY, int centerZ, BiomeCache[] array) { 21 | int minX = centerX - 1; 22 | int minZ = centerZ - 1; 23 | 24 | int maxX = centerX + 1; 25 | int maxZ = centerZ + 1; 26 | 27 | for (int x = minX; x <= maxX; x++) { 28 | for (int z = minZ; z <= maxZ; z++) { 29 | long key = SectionPos.asLong(x, centerY, z); 30 | 31 | BiomeCache cache = this.caches.getAndMoveToFirst(key); 32 | 33 | if (cache == null) { 34 | if (this.caches.size() >= CACHE_SIZE) { 35 | this.release(this.caches.removeLast()); 36 | } 37 | 38 | this.caches.put(key, cache = this.pool.allocate()); 39 | } 40 | 41 | this.pool.acquireReference(cache); 42 | 43 | array[WorldSlice.getLocalChunkIndex(x - minX, z - minZ)] = cache; 44 | } 45 | } 46 | } 47 | 48 | public void dropCachesForChunk(int centerX, int centerZ) { 49 | for (int x = centerX - 1; x <= centerX; x++) { 50 | for (int z = centerZ - 1; z <= centerZ; z++) { 51 | for (int y = 0; y <= 16; y++) { 52 | BiomeCache column = this.caches.remove(SectionPos.asLong(x, y, z)); 53 | 54 | if (column != null) { 55 | this.release(column); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | public void release(BiomeCache cache) { 63 | this.pool.release(cache); 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/util/ModelQuadUtil.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.util; 2 | 3 | import me.jellysquid.mods.sodium.common.util.DirectionUtil; 4 | import net.minecraft.util.Direction; 5 | 6 | /** 7 | * Provides some utilities and constants for interacting with vanilla's model quad vertex format. 8 | * 9 | * This is the current vertex format used by Minecraft for chunk meshes and model quads. Internally, it uses integer 10 | * arrays for store baked quad data, and as such the following table provides both the byte and int indices. 11 | * 12 | * Byte Index Integer Index Name Format Fields 13 | * 0 ..11 0..2 Position 3 floats x, y, z 14 | * 12..15 3 Color 4 unsigned bytes a, r, g, b 15 | * 16..23 4..5 Block Texture 2 floats u, v 16 | * 24..27 6 Light Texture 2 shorts u, v 17 | * 28..30 7 Normal 3 unsigned bytes x, y, z 18 | * 31 Padding 1 byte 19 | */ 20 | public class ModelQuadUtil { 21 | // Integer indices for vertex attributes, useful for accessing baked quad data 22 | public static final int POSITION_INDEX = 0, 23 | COLOR_INDEX = 3, 24 | TEXTURE_INDEX = 4, 25 | LIGHT_INDEX = 6, 26 | NORMAL_INDEX = 7; 27 | 28 | // Size of vertex format in 4-byte integers 29 | public static final int VERTEX_SIZE = 8; 30 | public static final int VERTEX_SIZE_BYTES = VERTEX_SIZE * 4; 31 | 32 | // Cached array of normals for every facing to avoid expensive computation 33 | static final int[] NORMALS = new int[DirectionUtil.ALL_DIRECTIONS.length]; 34 | 35 | static { 36 | for (int i = 0; i < NORMALS.length; i++) { 37 | NORMALS[i] = Norm3b.pack(DirectionUtil.ALL_DIRECTIONS[i].getDirectionVec()); 38 | } 39 | } 40 | 41 | /** 42 | * Returns the normal vector for a model quad with the given {@param facing}. 43 | */ 44 | public static int getFacingNormal(Direction facing) { 45 | return NORMALS[facing.ordinal()]; 46 | } 47 | 48 | /** 49 | * @param vertexIndex The index of the vertex to access 50 | * @return The starting offset of the vertex's attributes 51 | */ 52 | public static int vertexOffset(int vertexIndex) { 53 | return vertexIndex * VERTEX_SIZE; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/model/MixinMultipartBakedModel.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.model; 2 | 3 | import net.minecraft.block.BlockState; 4 | import net.minecraft.client.renderer.model.BakedQuad; 5 | import net.minecraft.client.renderer.model.IBakedModel; 6 | import net.minecraft.client.renderer.model.MultipartBakedModel; 7 | import net.minecraft.util.Direction; 8 | import net.minecraftforge.client.model.data.IModelData; 9 | import org.apache.commons.lang3.tuple.Pair; 10 | import org.spongepowered.asm.mixin.Final; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Overwrite; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Inject; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | 18 | import java.util.*; 19 | import java.util.function.Predicate; 20 | 21 | @Mixin(MultipartBakedModel.class) 22 | public class MixinMultipartBakedModel { 23 | private Map> stateCacheFast; 24 | 25 | @Shadow 26 | @Final 27 | private List, IBakedModel>> selectors; 28 | 29 | 30 | @Inject(method = "", at = @At("RETURN")) 31 | private void init(List, IBakedModel>> components, CallbackInfo ci) { 32 | this.stateCacheFast = new IdentityHashMap<>(); 33 | } 34 | 35 | /** 36 | * @author JellySquid 37 | * @reason Avoid expensive allocations and replace bitfield indirection 38 | */ 39 | @Overwrite(remap = false) 40 | public List getQuads(BlockState state, Direction face, Random random, IModelData modelData) { 41 | if (state == null) { 42 | return Collections.emptyList(); 43 | } 44 | 45 | List models = this.stateCacheFast.get(state); 46 | 47 | if (models == null) { 48 | models = new ArrayList<>(this.selectors.size()); 49 | 50 | for (Pair, IBakedModel> pair : this.selectors) { 51 | if ((pair.getLeft()).test(state)) { 52 | models.add(pair.getRight()); 53 | } 54 | } 55 | 56 | this.stateCacheFast.put(state, models); 57 | } 58 | 59 | List list = new ArrayList<>(); 60 | 61 | long seed = random.nextLong(); 62 | 63 | for (IBakedModel model : models) { 64 | random.setSeed(seed); 65 | 66 | list.addAll(model.getQuads(state, face, random, modelData)); 67 | } 68 | 69 | return list; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinVertexConsumer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.core.pipeline; 2 | 3 | import com.mojang.blaze3d.vertex.IVertexBuilder; 4 | import me.jellysquid.mods.sodium.client.model.consumer.GlyphVertexConsumer; 5 | import me.jellysquid.mods.sodium.client.model.consumer.ParticleVertexConsumer; 6 | import me.jellysquid.mods.sodium.client.model.consumer.QuadVertexConsumer; 7 | import me.jellysquid.mods.sodium.client.util.Norm3b; 8 | import me.jellysquid.mods.sodium.client.util.color.ColorABGR; 9 | import net.minecraft.util.math.vector.Matrix4f; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(IVertexBuilder.class) 14 | public interface MixinVertexConsumer extends ParticleVertexConsumer, QuadVertexConsumer, GlyphVertexConsumer { 15 | @Shadow 16 | IVertexBuilder pos(double x, double y, double z); 17 | 18 | @Shadow 19 | IVertexBuilder tex(float u, float v); 20 | 21 | @Shadow 22 | IVertexBuilder color(int red, int green, int blue, int alpha); 23 | 24 | @Shadow 25 | IVertexBuilder lightmap(int uv); 26 | 27 | @Shadow 28 | IVertexBuilder overlay(int uv); 29 | 30 | @Shadow 31 | IVertexBuilder normal(float x, float y, float z); 32 | 33 | @Shadow 34 | void endVertex(); 35 | 36 | @Override 37 | default void vertexParticle(float x, float y, float z, float u, float v, int color, int light) { 38 | this.pos(x, y, z); 39 | this.tex(u, v); 40 | this.color(ColorABGR.unpackRed(color), ColorABGR.unpackGreen(color), ColorABGR.unpackBlue(color), ColorABGR.unpackAlpha(color)); 41 | this.lightmap(light); 42 | this.endVertex(); 43 | } 44 | 45 | @Override 46 | default void vertexQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) { 47 | this.pos(x, y, z); 48 | this.color(ColorABGR.unpackRed(color), ColorABGR.unpackGreen(color), ColorABGR.unpackBlue(color), ColorABGR.unpackAlpha(color)); 49 | this.tex(u, v); 50 | this.overlay(overlay); 51 | this.lightmap(light); 52 | this.normal(Norm3b.unpackX(normal), Norm3b.unpackY(normal), Norm3b.unpackZ(normal)); 53 | this.endVertex(); 54 | } 55 | 56 | @Override 57 | default void vertexGlyph(Matrix4f matrix, float x, float y, float z, int color, float u, float v, int light) { 58 | this.pos(x, y, z); 59 | this.color(ColorABGR.unpackRed(color), ColorABGR.unpackGreen(color), ColorABGR.unpackBlue(color), ColorABGR.unpackAlpha(color)); 60 | this.tex(u, v); 61 | this.lightmap(light); 62 | this.endVertex(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/chunk/data/ChunkRenderBounds.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.chunk.data; 2 | 3 | 4 | import net.minecraft.util.math.SectionPos; 5 | 6 | public class ChunkRenderBounds { 7 | public final float x1, y1, z1; 8 | public final float x2, y2, z2; 9 | 10 | public ChunkRenderBounds(float x1, float y1, float z1, float x2, float y2, float z2) { 11 | this.x1 = x1; 12 | this.y1 = y1; 13 | this.z1 = z1; 14 | 15 | this.x2 = x2; 16 | this.y2 = y2; 17 | this.z2 = z2; 18 | } 19 | 20 | public ChunkRenderBounds(SectionPos origin) { 21 | this.x1 = origin.getWorldStartX(); 22 | this.y1 = origin.getWorldStartY(); 23 | this.z1 = origin.getWorldStartZ(); 24 | 25 | this.x2 = origin.getWorldEndX() + 1; 26 | this.y2 = origin.getWorldEndY() + 1; 27 | this.z2 = origin.getWorldEndZ() + 1; 28 | } 29 | 30 | public static class Builder { 31 | private int x1 = Integer.MAX_VALUE, y1 = Integer.MAX_VALUE, z1 = Integer.MAX_VALUE; 32 | private int x2 = Integer.MIN_VALUE, y2 = Integer.MIN_VALUE, z2 = Integer.MIN_VALUE; 33 | 34 | private boolean empty = true; 35 | 36 | public void addBlock(int x, int y, int z) { 37 | if (x < this.x1) { 38 | this.x1 = x; 39 | } 40 | 41 | if (x > this.x2) { 42 | this.x2 = x; 43 | } 44 | 45 | if (y < this.y1) { 46 | this.y1 = y; 47 | } 48 | 49 | if (y > this.y2) { 50 | this.y2 = y; 51 | } 52 | 53 | if (z < this.z1) { 54 | this.z1 = z; 55 | } 56 | 57 | if (z > this.z2) { 58 | this.z2 = z; 59 | } 60 | 61 | this.empty = false; 62 | } 63 | 64 | public ChunkRenderBounds build(SectionPos origin) { 65 | if (this.empty) { 66 | return new ChunkRenderBounds(origin); 67 | } 68 | 69 | // Expand the bounding box by 8 blocks (half a chunk) in order to deal with diagonal surfaces 70 | return new ChunkRenderBounds( 71 | Math.max(this.x1, origin.getWorldStartX()) - 8.0f, 72 | Math.max(this.y1, origin.getWorldStartY()) - 8.0f, 73 | Math.max(this.z1, origin.getWorldStartZ()) - 8.0f, 74 | 75 | Math.min(this.x2 + 1, origin.getWorldEndX()) + 8.0f, 76 | Math.min(this.y2 + 1, origin.getWorldEndY()) + 8.0f, 77 | Math.min(this.z2 + 1, origin.getWorldEndZ()) + 8.0f 78 | ); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/mixin/features/entity/smooth_lighting/MixinEntityRenderer.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.mixin.features.entity.smooth_lighting; 2 | 3 | import dev.hanetzer.chlorine.common.config.Config; 4 | import me.jellysquid.mods.sodium.client.SodiumClientMod; 5 | import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; 6 | import me.jellysquid.mods.sodium.client.model.light.EntityLighter; 7 | import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; 8 | import me.jellysquid.mods.sodium.client.render.entity.EntityLightSampler; 9 | import net.minecraft.client.renderer.culling.ClippingHelper; 10 | import net.minecraft.client.renderer.entity.EntityRenderer; 11 | import net.minecraft.entity.Entity; 12 | import net.minecraft.util.math.BlockPos; 13 | import org.spongepowered.asm.mixin.Mixin; 14 | import org.spongepowered.asm.mixin.Shadow; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 18 | 19 | @Mixin(EntityRenderer.class) 20 | public abstract class MixinEntityRenderer implements EntityLightSampler { 21 | @Shadow 22 | protected abstract int getBlockLight(T entity, BlockPos blockPos); 23 | 24 | @Shadow 25 | protected abstract int func_239381_b_(T entity, BlockPos blockPos); 26 | 27 | @Inject(method = "getPackedLight", at = @At("HEAD"), cancellable = true) 28 | private void preGetLight(T entity, float tickDelta, CallbackInfoReturnable cir) { 29 | // Use smooth entity lighting if enabled 30 | if (Config.CLIENT.smoothLighting.get() == SodiumGameOptions.LightingQuality.HIGH) { 31 | cir.setReturnValue(EntityLighter.getBlendedLight(this, entity, tickDelta)); 32 | } 33 | } 34 | 35 | @Inject(method = "shouldRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/culling/ClippingHelper;isBoundingBoxInFrustum(Lnet/minecraft/util/math/AxisAlignedBB;)Z", shift = At.Shift.AFTER), cancellable = true) 36 | private void preShouldRender(T entity, ClippingHelper frustum, double x, double y, double z, CallbackInfoReturnable cir) { 37 | // If the entity isn't culled already by other means, try to perform a second pass 38 | if (cir.getReturnValue() && !SodiumWorldRenderer.getInstance().isEntityVisible(entity)) { 39 | cir.setReturnValue(false); 40 | } 41 | } 42 | 43 | @Override 44 | public int bridge$getBlockLight(T entity, BlockPos pos) { 45 | return this.getBlockLight(entity, pos); 46 | } 47 | 48 | @Override 49 | public int bridge$getSkyLight(T entity, BlockPos pos) { 50 | return this.func_239381_b_(entity, pos); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/model/quad/ModelQuadView.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.model.quad; 2 | 3 | import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | 6 | import java.nio.ByteBuffer; 7 | 8 | /** 9 | * Provides a read-only view of a model quad. For mutable access to a model quad, see {@link ModelQuadViewMutable}. 10 | */ 11 | public interface ModelQuadView { 12 | /** 13 | * @return The x-position of the vertex at index {@param idx} 14 | */ 15 | float getX(int idx); 16 | 17 | /** 18 | * @return The y-position of the vertex at index {@param idx} 19 | */ 20 | float getY(int idx); 21 | 22 | /** 23 | * @return The z-position of the vertex at index {@param idx} 24 | */ 25 | float getZ(int idx); 26 | 27 | /** 28 | * @return The integer-encoded color of the vertex at index {@param idx} 29 | */ 30 | int getColor(int idx); 31 | 32 | /** 33 | * @return The texture x-coordinate for the vertex at index {@param idx} 34 | */ 35 | float getTexU(int idx); 36 | 37 | /** 38 | * @return The texture y-coordinate for the vertex at index {@param idx} 39 | */ 40 | float getTexV(int idx); 41 | 42 | /** 43 | * @return The integer bit flags containing the {@link ModelQuadFlags} for this quad 44 | */ 45 | int getFlags(); 46 | 47 | /** 48 | * @return The lightmap texture coordinates for the vertex at index {@param idx} 49 | */ 50 | int getLight(int idx); 51 | 52 | /** 53 | * @return The integer-encoded normal vector for the vertex at index {@param idx} 54 | */ 55 | int getNormal(int idx); 56 | 57 | /** 58 | * @return The color index of this quad. 59 | */ 60 | int getColorIndex(); 61 | 62 | /** 63 | * Copies this quad's data into the specified buffer starting at the given position. 64 | * @param buf The buffer to write this quad's data to 65 | * @param position The starting byte index to write to 66 | */ 67 | default void copyInto(ByteBuffer buf, int position) { 68 | for (int i = 0; i < 4; i++) { 69 | buf.putFloat(position, this.getX(i)); 70 | buf.putFloat(position + 4, this.getY(i)); 71 | buf.putFloat(position + 8, this.getZ(i)); 72 | buf.putInt(position + 12, this.getColor(i)); 73 | buf.putFloat(position + 16, this.getTexU(i)); 74 | buf.putFloat(position + 20, this.getTexV(i)); 75 | buf.putInt(position + 24, this.getLight(i)); 76 | 77 | position += 28; 78 | } 79 | } 80 | 81 | /** 82 | * @return The sprite texture used by this quad, or null if none is attached 83 | */ 84 | TextureAtlasSprite getSprite(); 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/me/jellysquid/mods/sodium/client/render/pipeline/context/ChunkRenderContext.java: -------------------------------------------------------------------------------- 1 | package me.jellysquid.mods.sodium.client.render.pipeline.context; 2 | 3 | import me.jellysquid.mods.sodium.client.model.light.LightPipelineProvider; 4 | import me.jellysquid.mods.sodium.client.model.light.cache.ArrayLightDataCache; 5 | import me.jellysquid.mods.sodium.client.model.quad.blender.BiomeColorBlender; 6 | import me.jellysquid.mods.sodium.client.model.quad.sink.ModelQuadSinkDelegate; 7 | import me.jellysquid.mods.sodium.client.render.pipeline.BlockRenderer; 8 | import me.jellysquid.mods.sodium.client.render.pipeline.FluidRenderer; 9 | import me.jellysquid.mods.sodium.client.render.pipeline.RenderContextCommon; 10 | import me.jellysquid.mods.sodium.client.world.WorldSlice; 11 | import net.minecraft.block.BlockState; 12 | import net.minecraft.client.Minecraft; 13 | import net.minecraft.client.renderer.BlockModelShapes; 14 | import net.minecraft.client.renderer.model.IBakedModel; 15 | import net.minecraft.fluid.FluidState; 16 | import net.minecraft.util.math.BlockPos; 17 | import net.minecraft.world.IBlockDisplayReader; 18 | import net.minecraftforge.client.model.data.IModelData; 19 | 20 | public class ChunkRenderContext { 21 | private final ArrayLightDataCache lightDataCache; 22 | 23 | private final BlockRenderer blockRenderer; 24 | private final FluidRenderer fluidRenderer; 25 | 26 | private final BlockModelShapes models; 27 | 28 | public ChunkRenderContext(Minecraft client) { 29 | this.lightDataCache = new ArrayLightDataCache(WorldSlice.BLOCK_LENGTH); 30 | 31 | LightPipelineProvider lightPipelineProvider = new LightPipelineProvider(this.lightDataCache); 32 | BiomeColorBlender biomeColorBlender = RenderContextCommon.createBiomeColorBlender(); 33 | 34 | this.blockRenderer = new BlockRenderer(client, lightPipelineProvider, biomeColorBlender); 35 | this.fluidRenderer = new FluidRenderer(client, lightPipelineProvider, biomeColorBlender); 36 | 37 | this.models = client.getModelManager().getBlockModelShapes(); 38 | } 39 | 40 | public boolean renderBlock(IBlockDisplayReader world, BlockState state, BlockPos pos, ModelQuadSinkDelegate consumer, boolean cull, IModelData modelData) { 41 | IBakedModel model = this.models.getModel(state); 42 | long seed = state.getPositionRandom(pos); 43 | 44 | return this.blockRenderer.renderModel(world, state, pos, model, consumer, cull, seed, modelData); 45 | } 46 | 47 | public boolean renderFluid(IBlockDisplayReader world, FluidState fluidState, BlockPos.Mutable pos, ModelQuadSinkDelegate consumer) { 48 | return this.fluidRenderer.render(world, fluidState, pos, consumer); 49 | } 50 | 51 | public void init(IBlockDisplayReader world, int x, int y, int z) { 52 | this.lightDataCache.init(world, x, y, z); 53 | } 54 | } 55 | --------------------------------------------------------------------------------