diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5262594 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# +# LambdAurora's ignore file +# +# v0.13 + +# JetBrains +.idea/ +*.iml +*.ipr +*.iws +## Intellij IDEA +out/ +## CLion +cmake-build-debug*/ +cmake-build-release*/ +## Eclipse +eclipse +*.launch +.settings +.metadata +.classpath +.project +## Visual Studio +.vs/ +CMakeSettings.json + +# Build system +## Cargo +Cargo.lock +## CMake +CMakeCache.txt +CMakeFiles/ +## Gradle +.gradle/ +## Node.JS +node_modules/ + +# Editors +## VSCode +.vscode/ + +# Logging +logs/ + +# Languages +## Java +classes/ +## Python +__pycache__/ +## Rust +**/*.rs.bk + +# OS +## Windows +desktop.ini + +# File types +*.dll +*.so +*.dylib +*.lib +lib*.a +*.png~ + +# Common +bin/ +build/ +dist/ +run/ +target/ diff --git a/HOW_DOES_IT_WORK.md b/HOW_DOES_IT_WORK.md new file mode 100644 index 0000000..dd69e9d --- /dev/null +++ b/HOW_DOES_IT_WORK.md @@ -0,0 +1,76 @@ +# How does it work? + +This is a little file explaining how the mod works and hopefully be as detailed as it can +to allow people to maintain the code over newer versions and remove the monopole OptiFine has. + +## [UpcraftLP method](https://gist.github.com/UpcraftLP/93db478535cb3954cc9f3dc98bac91cf) & [AtomicStryker method](https://github.com/AtomicStryker/atomicstrykers-minecraft-mods/tree/1.14.3/DynamicLights) + +Not used by this mod. + +UpcraftLP method can be found here: https://gist.github.com/UpcraftLP/93db478535cb3954cc9f3dc98bac91cf + +AtomicStryker method can be found here: https://github.com/AtomicStryker/atomicstrykers-minecraft-mods/tree/1.14.3/DynamicLights + +Both methods suffer from a "laggy" dynamic lighting, the way the light moves is too much tied to +the block positions as it only injects at luminance getters in `WorldChunk` or a lighting provider. +It will only provide the dynamic light value of the light source if the block position is the position +of the light source. + +It's better in a way as the F3 menu will actually report a light value instead of the lightmap coordinates +method, but will be significantly be less smooth in its transitions. + +## Lightmap coordinates method + +This method is used by this mod. + +### Dynamic luminance injection + +As [@Martmists](https://github.com/martmists) suggested, `WorldRenderer#getLightmapCoordinates` is a great entrypoint. + +This method gives lightmap coordinates in the format `(skyLevel << 20 | blockLevel << 4)` +and to get the blockLevel from the lightmap use `LightmapTextureManager#getBlockLightCoordinates`. + +The goal is to inject at TAIL into `getLightmapCoordinates` and get the vanilla value, then +get the dynamic value at the specified block position (which is calculated from all the dynamic +light sources, their distances and the luminance), if the dynamic value is higher than the block value +then we replace it. + +This also means that we can't just do like the previous method and only give the source luminance but +we also have to calculate the surrounding luminance created by the dynamic light source in a specified +range (which is 7.75 to limit chunk rebuilding to 8 chunks (which is still a lot)). + +When getting the dynamic light value at the specified position, it has to be a `double` and not +an integer as the light value calculated with the range has to be precise. +To modify the lightmap with the dynamic light value, it has to be multiplied by 16.0 instead of +using a bitshift to preserve as much as possible the precision. + +Dynamic light value at a specified position is calculated in a for-loop with all the dynamic light +sources, only the highest light value is kept. The light value is calculated as follow: + +```java +// dist being the distance between the light source origin and the position where the +// lightmap coordinates are requested. +double multiplier = 1.0 - dist / 7.75; // 7.75 because of the range +// luminace being the luminance of the dynamic light source. +double lightLevel = multiplier * (double) luminance; +``` + +### Chunk rebuilding + +To apply the dynamic lighting we have to request the affected chunks a rebuild to rebuild the lightmap, +which is the most critic part performance-wise. Rebuilding a chunk cost performances, +that's why there's multiple mode: FASTEST, FAST and FANCY. The fast modes will limit the update. + +To manage chunk rebuilding, we inject at `WorldRenderer#setupTerrain` (`SodiumWorldRender#setupTerrain` if Sodium is present), +and if fast mode then we check when the last update was done. +If we can update, then we get the current dynamic light source position and get its chunk. +After that we get the surrounding affect chunks and build a new Set of chunk coordinates which +need to be updated. + +## Shader based method + +This would be more ideal performance-wise as it would give the smoothness of the second method +and avoid too many chunk rebuilding. + +This has still to be researched, if a method is found using shaders this mod is likely to switch +to this method. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f87002f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright © 2020 LambdAurora + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..79a5bb7 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# LambdaDynamicLights + +![Java 8](https://img.shields.io/badge/language-Java%208-9B599A.svg?style=flat-square) +[![GitHub license](https://img.shields.io/github/license/LambdAurora/LambdaDynamicLights?style=flat-square)](https://raw.githubusercontent.com/LambdAurora/LambdaDynamicLights/master/LICENSE) +![Environment: Client](https://img.shields.io/badge/environment-client-1976d2?style=flat-square) +![Mod loader: Fabric](https://img.shields.io/badge/modloader-Fabric-1976d2?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTEyLTE2VDE2OjU0OjE3LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHN0RXZ0OndoZW49IjIwMTgtMTItMTZUMTY6NTQ6MTctMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4/HiGMAAAAtUlEQVRYw+XXrQqAMBQF4D2P2eBL+QIG8RnEJFaNBjEum+0+zMQLtwwv+wV3ZzhhMDgfJ0wUSinxZUQWgKos1JP/AbD4OneIDyQPwCFniA+EJ4CaXm4TxAXCC0BNHgLhAdAnx9hC8PwGSRtAFVMQjF7cNTWED8B1cgwW20yfJgAvrssAsZ1cB3g/xckAxr6FmCDU5N6f488BrpCQ4rQBJkiMYh4ACmLzwOQF0CExinkCsvw7vgGikl+OotaKRwAAAABJRU5ErkJggg==) +![Version](https://img.shields.io/github/v/tag/LambdAurora/LambdaDynamicLights?label=version&style=flat-square) + +A dynamic lights mod for Fabric. + +## What's this mod? + +This mod adds dynamic lights to Minecraft. Dynamic lights are lights created by an entity holding an +item which makes light as a block, or create by an entity on fire, etc. + +Dynamic lights are present as an option in OptiFine or as a Forge mod (Dynamic Lights mod). + +## Build + +Just do `./gradlew build` and everything should build just fine! + +## How does it work internally? + +Check [this documentation](https://github.com/LambdAurora/LambdaDynamicLights/blob/mc1.16/HOW_DOES_IT_WORK.md).