From b2274a25b0d7d3e41be2bc81a85e17888da5c081 Mon Sep 17 00:00:00 2001 From: LAX1DUDE Date: Fri, 7 Apr 2023 16:48:33 -0700 Subject: [PATCH] Update #18 - Final release, added PBR shaders --- CREDITS | 6 +- client_version | 2 +- .../net/minecraft/block/Block.edit.java | 7 + .../net/minecraft/block/BlockGlass.edit.java | 9 +- .../net/minecraft/block/BlockLiquid.edit.java | 11 +- .../net/minecraft/block/BlockPane.edit.java | 9 +- .../client/LoadingScreenRenderer.edit.java | 10 +- .../net/minecraft/client/Minecraft.edit.java | 142 +- .../minecraft/client/gui/GuiButton.edit.java | 22 + .../minecraft/client/gui/GuiIngame.edit.java | 4 +- .../client/gui/GuiLanguage.edit.java | 5 +- .../client/gui/GuiMainMenu.edit.java | 50 +- .../minecraft/client/gui/GuiOptions.edit.java | 26 +- .../minecraft/client/gui/GuiScreen.edit.java | 8 +- .../client/gui/GuiVideoSettings.edit.java | 2 +- .../client/model/ModelDragon.edit.java | 17 +- .../client/particle/EffectRenderer.edit.java | 61 +- .../client/particle/EntityDiggingFX.edit.java | 9 +- .../particle/EntityLargeExplodeFX.edit.java | 22 +- .../renderer/BlockFluidRenderer.edit.java | 122 +- .../renderer/BlockModelRenderer.edit.java | 326 +- .../renderer/ChunkRenderContainer.edit.java | 24 +- .../client/renderer/EntityRenderer.edit.java | 1193 ++++- .../RegionRenderCacheBuilder.edit.java | 5 + .../client/renderer/RenderGlobal.edit.java | 410 +- .../client/renderer/RenderHelper.edit.java | 35 +- .../client/renderer/RenderList.edit.java | 3 +- .../renderer/block/model/BakedQuad.edit.java | 33 + .../block/model/BreakingFour.edit.java | 17 +- .../renderer/block/model/FaceBakery.edit.java | 121 +- .../chunk/ChunkCompileTaskGenerator.edit.java | 13 +- .../chunk/ChunkRenderWorker.edit.java | 17 +- .../renderer/chunk/CompiledChunk.edit.java | 15 + .../renderer/chunk/RenderChunk.edit.java | 76 +- .../client/renderer/entity/Render.edit.java | 37 +- .../renderer/entity/RenderBlaze.edit.java | 22 +- .../renderer/entity/RenderCreeper.edit.java | 23 +- .../renderer/entity/RenderDragon.edit.java | 30 +- .../renderer/entity/RenderEnderman.edit.java | 3 +- .../entity/RenderEntityItem.edit.java | 21 +- .../entity/RenderFallingBlock.edit.java | 9 +- .../renderer/entity/RenderItem.edit.java | 118 +- .../entity/RenderLightningBolt.edit.java | 36 +- .../renderer/entity/RenderManager.edit.java | 49 +- .../renderer/entity/RenderPlayer.edit.java | 4 + .../renderer/entity/RenderSlime.edit.java | 4 + .../renderer/entity/RenderTNTPrimed.edit.java | 28 +- .../entity/RendererLivingEntity.edit.java | 109 +- .../entity/layers/LayerArmorBase.edit.java | 96 +- .../layers/LayerCreeperCharge.edit.java | 79 +- .../layers/LayerEnderDragonDeath.edit.java | 60 +- .../layers/LayerEnderDragonEyes.edit.java | 17 +- .../entity/layers/LayerEndermanEyes.edit.java | 60 +- .../entity/layers/LayerHeldBlock.edit.java | 50 +- .../layers/LayerMooshroomMushroom.edit.java | 14 +- .../entity/layers/LayerSlimeGel.edit.java | 58 +- .../entity/layers/LayerSpiderEyes.edit.java | 57 +- .../entity/layers/LayerWitherAura.edit.java | 66 +- .../texture/AbstractTexture.edit.java | 25 +- .../renderer/texture/TextureClock.edit.java | 11 +- .../renderer/texture/TextureCompass.edit.java | 23 +- .../renderer/texture/TextureManager.edit.java | 30 +- .../renderer/texture/TextureMap.edit.java | 334 +- .../renderer/texture/TextureUtil.edit.java | 7 +- .../tileentity/RenderItemFrame.edit.java | 33 +- .../TileEntityBeaconRenderer.edit.java | 161 +- .../TileEntityChestRenderer.edit.java | 6 +- .../TileEntityEndPortalRenderer.edit.java | 55 +- .../TileEntityPistonRenderer.edit.java | 14 +- .../TileEntitySignRenderer.edit.java | 25 +- .../resources/model/ModelBakery.edit.java | 46 +- .../client/settings/GameSettings.edit.java | 190 +- .../net/minecraft/entity/Entity.edit.java | 37 +- .../entity/EntityLivingBase.edit.java | 18 +- .../entity/item/EntityItem.edit.java | 18 +- .../entity/item/EntityItemFrame.edit.java | 18 +- .../entity/item/EntityTNTPrimed.edit.java | 20 +- .../entity/item/EntityXPOrb.edit.java | 20 +- .../entity/monster/EntityBlaze.edit.java | 14 +- .../entity/monster/EntityCreeper.edit.java | 24 +- .../entity/monster/EntityEnderman.edit.java | 9 +- .../net/minecraft/util/BlockPos.edit.java | 91 +- .../util/EnumWorldBlockLayer.edit.java | 13 + .../net/minecraft/util/Timer.edit.java | 10 + .../net/minecraft/world/ChunkCache.edit.java | 4 + .../net/minecraft/world/World.edit.java | 50 +- .../net/minecraft/world/chunk/Chunk.edit.java | 30 +- .../assets/minecraft/lang/en_US.edit.lang | 113 +- .../v1_8/internal/PlatformApplication.java | 3 +- .../v1_8/internal/PlatformAudio.java | 13 + .../internal/PlatformBufferFunctions.java | 13 + .../v1_8/internal/PlatformOpenGL.java | 74 +- .../v1_8/internal/PlatformRuntime.java | 1 + .../v1_8/internal/WebSocketPlayClient.java | 9 +- .../v1_8/internal/WebSocketServerQuery.java | 7 +- .../v1_8/internal/lwjgl/LWJGLEntryPoint.java | 7 + .../eaglercraft/v1_8/EaglerInputStream.java | 3 + .../v1_8/EaglercraftSoundManager.java | 22 +- .../eaglercraft/v1_8/EaglercraftVersion.java | 15 +- .../minecraft/AcceleratedEffectRenderer.java | 2 + .../v1_8/minecraft/ChunkUpdateManager.java | 16 +- .../minecraft/EaglerTextureAtlasSprite.java | 57 +- .../minecraft/IAcceleratedParticleEngine.java | 4 + .../v1_8/minecraft/TextureAnimationCache.java | 110 +- .../eaglercraft/v1_8/opengl/DrawUtils.java | 99 + .../v1_8/opengl/EaglercraftGPU.java | 190 +- .../v1_8/opengl/EffectPipelineFXAA.java | 7 +- .../v1_8/opengl/FixedFunctionPipeline.java | 645 +-- .../v1_8/opengl/FixedFunctionShader.java | 138 +- .../v1_8/opengl/GlStateManager.java | 288 +- .../v1_8/opengl/IExtPipelineCompiler.java | 37 + .../v1_8/opengl/InstancedFontRenderer.java | 3 +- .../v1_8/opengl/SpriteLevelMixer.java | 56 +- .../eaglercraft/v1_8/opengl/StreamBuffer.java | 148 + .../v1_8/opengl/TextureCopyUtil.java | 352 ++ .../eaglercraft/v1_8/opengl/VertexFormat.java | 16 +- .../v1_8/opengl/WorldRenderer.java | 79 +- .../AbstractAcceleratedEffectRenderer.java | 49 + .../opengl/ext/deferred/ArrayListSerial.java | 52 + .../opengl/ext/deferred/BetterFrustum.java | 1169 +++++ .../opengl/ext/deferred/BlockVertexIDs.java | 74 + .../ext/deferred/CloudRenderWorker.java | 607 +++ .../ext/deferred/DebugFramebufferView.java | 528 +++ .../ext/deferred/DeferredStateManager.java | 496 ++ .../ext/deferred/DynamicLightInstance.java | 54 + .../ext/deferred/DynamicLightManager.java | 74 + .../ext/deferred/EaglerDeferredConfig.java | 161 + .../ext/deferred/EaglerDeferredPipeline.java | 4010 +++++++++++++++++ .../v1_8/opengl/ext/deferred/ExtGLEnums.java | 40 + .../ForwardAcceleratedEffectRenderer.java | 218 + .../ForwardRenderCallbackHandler.java | 52 + .../GBufferAcceleratedEffectRenderer.java | 216 + .../ext/deferred/GBufferPipelineCompiler.java | 389 ++ .../GBufferPipelineProgramInstance.java | 30 + .../ext/deferred/LensFlareMeshRenderer.java | 375 ++ .../opengl/ext/deferred/LightSourceMesh.java | 135 + .../v1_8/opengl/ext/deferred/ListSerial.java | 28 + .../opengl/ext/deferred/NameTagRenderer.java | 52 + .../opengl/ext/deferred/ShaderPackInfo.java | 77 + .../ShaderPackInfoReloadListener.java | 46 + .../ext/deferred/ShadersRenderPassFuture.java | 66 + .../opengl/ext/deferred/SkyboxRenderer.java | 199 + .../ext/deferred/VertexMarkerState.java | 23 + .../ext/deferred/gui/GuiShaderConfig.java | 133 + .../ext/deferred/gui/GuiShaderConfigList.java | 657 +++ .../deferred/gui/GuiShadersNotSupported.java | 48 + .../program/GBufferExtPipelineShader.java | 130 + .../deferred/program/IProgramUniforms.java | 22 + .../PipelineShaderAccelParticleForward.java | 110 + .../PipelineShaderAccelParticleGBuffer.java | 72 + .../program/PipelineShaderBloomBlurPass.java | 59 + .../PipelineShaderBloomBrightPass.java | 60 + .../program/PipelineShaderCloudsNoise3D.java | 63 + .../program/PipelineShaderCloudsSample.java | 70 + .../program/PipelineShaderCloudsShapes.java | 69 + .../PipelineShaderCloudsSunOcclusion.java | 56 + .../deferred/program/PipelineShaderFXAA.java | 57 + .../program/PipelineShaderGBufferCombine.java | 96 + .../PipelineShaderGBufferDebugView.java | 64 + .../program/PipelineShaderGBufferFog.java | 84 + .../program/PipelineShaderHandDepthMask.java | 53 + .../program/PipelineShaderLensDistortion.java | 53 + .../program/PipelineShaderLensFlares.java | 89 + .../PipelineShaderLensSunOcclusion.java | 55 + .../PipelineShaderLightShaftsSample.java | 80 + .../program/PipelineShaderLightingPoint.java | 82 + .../program/PipelineShaderLightingSun.java | 81 + .../program/PipelineShaderMoonRender.java | 72 + .../PipelineShaderPostExposureAvg.java | 64 + .../PipelineShaderPostExposureFinal.java | 59 + .../PipelineShaderRealisticWaterControl.java | 82 + .../PipelineShaderRealisticWaterNoise.java | 54 + ...PipelineShaderRealisticWaterNormalMap.java | 54 + .../program/PipelineShaderReprojControl.java | 88 + .../program/PipelineShaderReprojSSR.java | 67 + .../program/PipelineShaderSSAOGenerate.java | 60 + .../program/PipelineShaderShadowsSun.java | 95 + .../PipelineShaderSkyboxAtmosphere.java | 57 + .../PipelineShaderSkyboxIrradiance.java | 55 + .../program/PipelineShaderSkyboxRender.java | 88 + .../PipelineShaderSkyboxRenderEnd.java | 67 + .../program/PipelineShaderTonemap.java | 58 + .../program/ShaderCompileException.java | 27 + .../ext/deferred/program/ShaderCompiler.java | 123 + .../ext/deferred/program/ShaderException.java | 25 + .../deferred/program/ShaderLinkException.java | 22 + .../ext/deferred/program/ShaderProgram.java | 45 + .../ext/deferred/program/ShaderSource.java | 186 + .../program/SharedPipelineShaders.java | 42 + .../texture/EaglerBitwisePackedTexture.java | 76 + .../texture/EaglerTextureAtlasSpritePBR.java | 312 ++ .../ext/deferred/texture/EmissiveItems.java | 86 + .../opengl/ext/deferred/texture/IEEE754.java | 32 + .../ext/deferred/texture/MetalsLUT.java | 149 + .../texture/PBRMaterialConstants.java | 84 + .../deferred/texture/PBRTextureMapUtils.java | 168 + .../ext/deferred/texture/TemperaturesLUT.java | 68 + .../deferred/texture/TextureClockPBRImpl.java | 74 + .../texture/TextureCompassPBRImpl.java | 90 + .../v1_8/socket/ConnectionHandshake.java | 10 +- .../eaglercraft/v1_8/vector/Matrix4f.java | 25 + .../commons/lang3/text/CompositeFormat.java | 4 +- .../lang3/text/ExtendedMessageFormat.java | 4 +- .../commons/lang3/text/FormatFactory.java | 4 +- .../commons/lang3/text/FormattableUtils.java | 4 +- .../apache/commons/lang3/text/StrBuilder.java | 4 +- .../apache/commons/lang3/text/StrLookup.java | 4 +- .../apache/commons/lang3/text/StrMatcher.java | 4 +- .../commons/lang3/text/StrSubstitutor.java | 4 +- .../commons/lang3/text/StrTokenizer.java | 4 +- .../apache/commons/lang3/text/WordUtils.java | 4 +- sources/resources/assets/eagler/CREDITS.txt | 6 +- .../assets/eagler/glsl/accel_font.fsh | 4 +- .../assets/eagler/glsl/accel_font.vsh | 4 +- .../assets/eagler/glsl/accel_particle.fsh | 4 +- .../assets/eagler/glsl/accel_particle.vsh | 4 +- sources/resources/assets/eagler/glsl/core.fsh | 13 +- sources/resources/assets/eagler/glsl/core.vsh | 40 +- .../eagler/glsl/deferred/accel_particle.vsh | 72 + .../glsl/deferred/accel_particle_forward.fsh | 233 + .../glsl/deferred/accel_particle_gbuffer.fsh | 42 + .../glsl/deferred/assets_pbr/readme.txt | 1 + .../textures/blocks/bed_feet_end_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/bed_feet_side_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/bed_feet_top_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/bed_head_end_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/bed_head_side_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/bed_head_top_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/bedrock_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/bookshelf_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/brewing_stand_base_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/brewing_stand_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/brick_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/cake_inner_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/cake_side_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/blocks/cake_top_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/blocks/coal_ore_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/coarse_dirt_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/cobblestone_mossy_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/cobblestone_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/comparator_off_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/comparator_on_s.ebp | Bin 0 -> 173 bytes .../blocks/crafting_table_front_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/crafting_table_side_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/crafting_table_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/diamond_block_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/diamond_ore_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/dirt_podzol_side_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/dirt_podzol_top_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/dirt_s.ebp | Bin 0 -> 129 bytes .../blocks/dispenser_front_horizontal_s.ebp | Bin 0 -> 129 bytes .../blocks/dispenser_front_vertical_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/door_acacia_lower_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_acacia_upper_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_birch_lower_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_birch_upper_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_dark_oak_lower_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/door_dark_oak_upper_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/door_jungle_lower_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_jungle_upper_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_spruce_lower_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_spruce_upper_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_wood_lower_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/door_wood_upper_s.ebp | Bin 0 -> 88 bytes .../blocks/dropper_front_horizontal_s.ebp | Bin 0 -> 132 bytes .../blocks/dropper_front_vertical_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/emerald_block_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/emerald_ore_s.ebp | Bin 0 -> 132 bytes .../blocks/enchanting_table_bottom_s.ebp | Bin 0 -> 129 bytes .../blocks/enchanting_table_side_s.ebp | Bin 0 -> 185 bytes .../blocks/enchanting_table_top_s.ebp | Bin 0 -> 176 bytes .../textures/blocks/end_stone_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/endframe_side_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/endframe_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/farmland_dry_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/farmland_wet_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/furnace_front_off_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/furnace_front_on_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/furnace_side_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/furnace_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/gold_block_s.ebp | Bin 0 -> 126 bytes .../assets_pbr/textures/blocks/gold_ore_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/grass_side_overlay_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/grass_side_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/grass_side_snowed_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/grass_top_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/gravel_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/iron_block_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/iron_ore_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/lapis_block_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/lapis_ore_s.ebp | Bin 0 -> 132 bytes .../textures/blocks/log_acacia_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_acacia_top_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/log_big_oak_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_big_oak_top_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/log_birch_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_birch_top_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/log_jungle_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_jungle_top_s.ebp | Bin 0 -> 135 bytes .../assets_pbr/textures/blocks/log_oak_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_oak_top_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/log_spruce_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/log_spruce_top_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/netherrack_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/obsidian_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/piston_bottom_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/piston_inner_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/piston_side_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/piston_top_normal_s.ebp | Bin 0 -> 182 bytes .../textures/blocks/piston_top_sticky_s.ebp | Bin 0 -> 357 bytes .../textures/blocks/planks_acacia_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/planks_big_oak_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/planks_birch_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/planks_jungle_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/planks_oak_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/planks_spruce_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/prismarine_bricks_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/prismarine_dark_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/prismarine_rough_s.ebp | Bin 0 -> 423 bytes .../textures/blocks/pumpkin_face_off_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/pumpkin_face_on_s.ebp | Bin 0 -> 170 bytes .../textures/blocks/quartz_block_bottom_s.ebp | Bin 0 -> 129 bytes .../blocks/quartz_block_chiseled_s.ebp | Bin 0 -> 129 bytes .../blocks/quartz_block_chiseled_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/quartz_block_lines_s.ebp | Bin 0 -> 129 bytes .../blocks/quartz_block_lines_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/quartz_block_side_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/quartz_block_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/quartz_ore_s.ebp | Bin 0 -> 135 bytes .../blocks/rail_activator_powered_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/rail_activator_s.ebp | Bin 0 -> 126 bytes .../blocks/rail_detector_powered_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/rail_detector_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/rail_golden_powered_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/rail_golden_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/rail_normal_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/rail_normal_turned_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/redstone_lamp_off_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/redstone_lamp_on_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/redstone_ore_s.ebp | Bin 0 -> 170 bytes .../textures/blocks/redstone_torch_off_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/redstone_torch_on_s.ebp | Bin 0 -> 91 bytes .../textures/blocks/repeater_off_s.ebp | Bin 0 -> 88 bytes .../textures/blocks/repeater_on_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/blocks/sand_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/sandstone_bottom_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/sandstone_carved_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/sandstone_normal_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/sandstone_smooth_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/sandstone_top_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/soul_sand_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/stone_andesite_s.ebp | Bin 0 -> 129 bytes .../blocks/stone_andesite_smooth_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/stone_diorite_s.ebp | Bin 0 -> 129 bytes .../blocks/stone_diorite_smooth_s.ebp | Bin 0 -> 170 bytes .../textures/blocks/stone_granite_s.ebp | Bin 0 -> 129 bytes .../blocks/stone_granite_smooth_s.ebp | Bin 0 -> 135 bytes .../assets_pbr/textures/blocks/stone_s.ebp | Bin 0 -> 126 bytes .../textures/blocks/stone_slab_side_s.ebp | Bin 0 -> 135 bytes .../textures/blocks/stone_slab_top_s.ebp | Bin 0 -> 170 bytes .../textures/blocks/stonebrick_carved_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/stonebrick_cracked_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/stonebrick_mossy_s.ebp | Bin 0 -> 170 bytes .../textures/blocks/stonebrick_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/tnt_bottom_s.ebp | Bin 0 -> 126 bytes .../assets_pbr/textures/blocks/tnt_side_s.ebp | Bin 0 -> 129 bytes .../assets_pbr/textures/blocks/tnt_top_s.ebp | Bin 0 -> 126 bytes .../assets_pbr/textures/blocks/torch_on_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/blocks/trapdoor_s.ebp | Bin 0 -> 129 bytes .../textures/blocks/trip_wire_source_s.ebp | Bin 0 -> 232 bytes .../textures/items/bow_pulling_0_s.ebp | Bin 0 -> 126 bytes .../textures/items/bow_pulling_1_s.ebp | Bin 0 -> 126 bytes .../textures/items/bow_pulling_2_s.ebp | Bin 0 -> 126 bytes .../textures/items/bow_standby_s.ebp | Bin 0 -> 91 bytes .../textures/items/brewing_stand_s.ebp | Bin 0 -> 126 bytes .../textures/items/bucket_lava_s.ebp | Bin 0 -> 88 bytes .../textures/items/bucket_milk_s.ebp | Bin 0 -> 88 bytes .../textures/items/bucket_water_s.ebp | Bin 0 -> 88 bytes .../textures/items/carrot_on_a_stick_s.ebp | Bin 0 -> 126 bytes .../assets_pbr/textures/items/clock_s.ebp | Bin 0 -> 4123 bytes .../assets_pbr/textures/items/compass_s.ebp | Bin 0 -> 3102 bytes .../textures/items/diamond_axe_s.ebp | Bin 0 -> 88 bytes .../textures/items/diamond_hoe_s.ebp | Bin 0 -> 88 bytes .../textures/items/diamond_pickaxe_s.ebp | Bin 0 -> 88 bytes .../textures/items/diamond_shovel_s.ebp | Bin 0 -> 88 bytes .../textures/items/diamond_sword_s.ebp | Bin 0 -> 88 bytes .../textures/items/fishing_rod_cast_s.ebp | Bin 0 -> 91 bytes .../textures/items/fishing_rod_uncast_s.ebp | Bin 0 -> 126 bytes .../textures/items/flint_and_steel_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/gold_axe_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/gold_hoe_s.ebp | Bin 0 -> 88 bytes .../textures/items/gold_pickaxe_s.ebp | Bin 0 -> 88 bytes .../textures/items/gold_shovel_s.ebp | Bin 0 -> 88 bytes .../textures/items/gold_sword_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/iron_axe_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/iron_hoe_s.ebp | Bin 0 -> 88 bytes .../textures/items/iron_pickaxe_s.ebp | Bin 0 -> 88 bytes .../textures/items/iron_shovel_s.ebp | Bin 0 -> 88 bytes .../textures/items/iron_sword_s.ebp | Bin 0 -> 88 bytes .../textures/items/minecart_chest_s.ebp | Bin 0 -> 88 bytes .../items/minecart_command_block_s.ebp | Bin 0 -> 88 bytes .../textures/items/minecart_furnace_s.ebp | Bin 0 -> 88 bytes .../textures/items/minecart_tnt_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/shears_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/stone_axe_s.ebp | Bin 0 -> 88 bytes .../assets_pbr/textures/items/stone_hoe_s.ebp | Bin 0 -> 88 bytes .../textures/items/stone_pickaxe_s.ebp | Bin 0 -> 88 bytes .../textures/items/stone_shovel_s.ebp | Bin 0 -> 88 bytes .../textures/items/stone_sword_s.ebp | Bin 0 -> 88 bytes .../assets/eagler/glsl/deferred/brdf_lut.bmp | Bin 0 -> 8192 bytes .../eagler/glsl/deferred/clouds_noise3d.fsh | 55 + .../eagler/glsl/deferred/clouds_sample.fsh | 92 + .../eagler/glsl/deferred/clouds_shapes.bmp | Bin 0 -> 12288 bytes .../eagler/glsl/deferred/clouds_shapes.fsh | 33 + .../eagler/glsl/deferred/clouds_shapes.vsh | 30 + .../glsl/deferred/clouds_sun_occlusion.fsh | 48 + .../eagler/glsl/deferred/deferred_combine.fsh | 172 + .../eagler/glsl/deferred/deferred_core.vsh | 114 + .../glsl/deferred/deferred_core_gbuffer.fsh | 166 + .../eagler/glsl/deferred/deferred_fog.fsh | 101 + .../eagler/glsl/deferred/deferred_local.vsh | 28 + .../eagler/glsl/deferred/deferred_shadow.fsh | 59 + .../eagler/glsl/deferred/deferred_shadow.vsh | 101 + .../assets/eagler/glsl/deferred/dither16.bmp | Bin 0 -> 256 bytes .../eagler/glsl/deferred/eagler_moon.bmp | Bin 0 -> 349570 bytes .../eagler/glsl/deferred/emissive_items.csv | 9 + .../eagler/glsl/deferred/forward_core.fsh | 471 ++ .../eagler/glsl/deferred/forward_core.vsh | 101 + .../deferred/forward_glass_highlights.fsh | 306 ++ .../deferred/forward_glass_highlights.vsh | 52 + .../glsl/deferred/gbuffer_debug_view.fsh | 109 + .../eagler/glsl/deferred/hand_depth_mask.fsh | 27 + .../eagler/glsl/deferred/lens_ghosts.bmp | Bin 0 -> 21880 bytes .../eagler/glsl/deferred/lens_streaks.bmp | Bin 0 -> 10951 bytes .../glsl/deferred/lens_sun_occlusion.fsh | 68 + .../eagler/glsl/deferred/lib/pbr_env_map.glsl | 120 + .../glsl/deferred/lib/pbr_lighting.glsl | 86 + .../glsl/deferred/lib/waving_blocks.glsl | 218 + .../eagler/glsl/deferred/light_point_mesh.dat | Bin 0 -> 522 bytes .../glsl/deferred/light_shafts_sample.fsh | 158 + .../eagler/glsl/deferred/lighting_mesh.vsh | 27 + .../eagler/glsl/deferred/lighting_point.fsh | 86 + .../eagler/glsl/deferred/lighting_sun.fsh | 100 + .../deferred/material_block_constants.csv | 583 +++ .../assets/eagler/glsl/deferred/metals.csv | 9 + .../eagler/glsl/deferred/moon_render.fsh | 50 + .../eagler/glsl/deferred/moon_render.vsh | 35 + .../eagler/glsl/deferred/particles_s.png | Bin 0 -> 528 bytes .../eagler/glsl/deferred/post_bloom_blur.fsh | 48 + .../glsl/deferred/post_bloom_bright.fsh | 48 + .../glsl/deferred/post_exposure_avg.fsh | 44 + .../glsl/deferred/post_exposure_final.fsh | 40 + .../assets/eagler/glsl/deferred/post_fxaa.fsh | 273 ++ .../glsl/deferred/post_lens_distort.fsh | 38 + .../eagler/glsl/deferred/post_lens_ghosts.fsh | 34 + .../eagler/glsl/deferred/post_lens_ghosts.vsh | 65 + .../glsl/deferred/post_lens_streaks.fsh | 34 + .../glsl/deferred/post_lens_streaks.vsh | 40 + .../eagler/glsl/deferred/post_tonemap.fsh | 55 + .../assets/eagler/glsl/deferred/rain.png | Bin 0 -> 2046 bytes .../glsl/deferred/realistic_water_control.fsh | 194 + .../glsl/deferred/realistic_water_mask.fsh | 40 + .../glsl/deferred/realistic_water_mask.vsh | 44 + .../glsl/deferred/realistic_water_noise.bmp | 1 + .../glsl/deferred/realistic_water_noise.fsh | 39 + .../glsl/deferred/realistic_water_normals.fsh | 33 + .../glsl/deferred/realistic_water_render.fsh | 433 ++ .../glsl/deferred/realistic_water_render.vsh | 80 + .../glsl/deferred/reproject_control.fsh | 236 + .../eagler/glsl/deferred/reproject_ssr.fsh | 110 + .../eagler/glsl/deferred/shader_pack_icon.png | Bin 0 -> 4307 bytes .../glsl/deferred/shader_pack_info.json | 24 + .../eagler/glsl/deferred/shadows_sun.fsh | 168 + .../assets/eagler/glsl/deferred/skybox.dat | Bin 0 -> 9204 bytes .../glsl/deferred/skybox_atmosphere.fsh | 126 + .../glsl/deferred/skybox_irradiance.fsh | 231 + .../eagler/glsl/deferred/skybox_render.fsh | 60 + .../eagler/glsl/deferred/skybox_render.vsh | 49 + .../glsl/deferred/skybox_render_end.fsh | 45 + .../glsl/deferred/skybox_render_end.vsh | 33 + .../eagler/glsl/deferred/ssao_generate.fsh | 96 + .../eagler/glsl/deferred/ssao_noise.bmp | Bin 0 -> 16384 bytes .../eagler/glsl/deferred/temperatures.lut | Bin 0 -> 1173 bytes .../eagler/glsl/deferred/vertex_ids.csv | 120 + .../resources/assets/eagler/glsl/local.vsh | 6 +- .../assets/eagler/glsl/post_fxaa.fsh | 81 +- .../assets/eagler/glsl/texture_blit.fsh | 45 + .../assets/eagler/glsl/texture_blit.vsh | 32 + .../assets/eagler/glsl/texture_mix.fsh | 4 +- .../v1_8/internal/PlatformApplication.java | 3 +- .../v1_8/internal/PlatformAudio.java | 35 + .../v1_8/internal/PlatformOpenGL.java | 146 +- .../buffer/EaglerArrayBufferAllocator.java | 14 + .../buffer/EaglerArrayByteBuffer.java | 5 +- .../v1_8/internal/teavm/EarlyLoadScreen.java | 7 +- .../v1_8/internal/teavm/MainClass.java | 12 +- .../teavm/WebGL2RenderingContext.java | 36 +- 497 files changed, 28342 insertions(+), 1014 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/renderer/block/model/BakedQuad.edit.java create mode 100644 patches/minecraft/net/minecraft/util/EnumWorldBlockLayer.edit.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/DrawUtils.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/IExtPipelineCompiler.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/StreamBuffer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/TextureCopyUtil.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/AbstractAcceleratedEffectRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ArrayListSerial.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BetterFrustum.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/CloudRenderWorker.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DebugFramebufferView.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DeferredStateManager.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightInstance.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightManager.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredConfig.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ExtGLEnums.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardAcceleratedEffectRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardRenderCallbackHandler.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferAcceleratedEffectRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineCompiler.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineProgramInstance.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LensFlareMeshRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LightSourceMesh.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ListSerial.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/NameTagRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfo.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfoReloadListener.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShadersRenderPassFuture.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/SkyboxRenderer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/VertexMarkerState.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfig.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfigList.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShadersNotSupported.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/GBufferExtPipelineShader.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/IProgramUniforms.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleForward.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleGBuffer.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBlurPass.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBrightPass.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsNoise3D.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSample.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsShapes.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSunOcclusion.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderFXAA.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferCombine.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferDebugView.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferFog.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderHandDepthMask.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensDistortion.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensFlares.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensSunOcclusion.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightShaftsSample.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingPoint.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingSun.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderMoonRender.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureAvg.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureFinal.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterControl.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNoise.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNormalMap.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojControl.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojSSR.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSSAOGenerate.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderShadowsSun.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxAtmosphere.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxIrradiance.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRender.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRenderEnd.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderTonemap.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompileException.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompiler.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderException.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderLinkException.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderProgram.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderSource.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/SharedPipelineShaders.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerBitwisePackedTexture.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerTextureAtlasSpritePBR.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EmissiveItems.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/IEEE754.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/MetalsLUT.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRMaterialConstants.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRTextureMapUtils.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TemperaturesLUT.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureClockPBRImpl.java create mode 100644 sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureCompassPBRImpl.java create mode 100644 sources/resources/assets/eagler/glsl/deferred/accel_particle.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/accel_particle_forward.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/accel_particle_gbuffer.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/readme.txt create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_feet_end_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_feet_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_feet_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_end_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bedrock_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bookshelf_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/brewing_stand_base_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/brewing_stand_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/brick_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_inner_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/coal_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/coarse_dirt_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cobblestone_mossy_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cobblestone_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/comparator_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/comparator_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_front_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/diamond_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/diamond_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dispenser_front_horizontal_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dispenser_front_vertical_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_jungle_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_jungle_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_lower_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_upper_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dropper_front_horizontal_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dropper_front_vertical_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_bottom_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/end_stone_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/farmland_dry_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/farmland_wet_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/gold_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/gold_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_overlay_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_snowed_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/gravel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/lapis_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/lapis_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_jungle_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_jungle_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/netherrack_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/obsidian_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_bottom_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_inner_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_top_normal_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_top_sticky_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_acacia_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_big_oak_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_birch_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_jungle_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_oak_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_spruce_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_bricks_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_dark_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_rough_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/pumpkin_face_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/pumpkin_face_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_bottom_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_chiseled_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_chiseled_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_lines_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_lines_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_activator_powered_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_activator_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_powered_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_powered_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_turned_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_ore_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_torch_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_torch_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/repeater_off_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/repeater_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sand_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_bottom_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_carved_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_normal_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_smooth_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/soul_sand_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_andesite_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_andesite_smooth_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_diorite_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_diorite_smooth_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_granite_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_granite_smooth_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_slab_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_slab_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_carved_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_cracked_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_mossy_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/tnt_bottom_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/tnt_side_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/tnt_top_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/torch_on_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/trapdoor_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/trip_wire_source_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_pulling_0_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_pulling_1_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_pulling_2_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_standby_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/brewing_stand_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bucket_lava_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bucket_milk_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bucket_water_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/carrot_on_a_stick_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/clock_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/compass_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_axe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_hoe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_pickaxe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_shovel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_sword_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_cast_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_uncast_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/flint_and_steel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_axe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_hoe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_pickaxe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_shovel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_sword_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_axe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_hoe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_pickaxe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_shovel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_sword_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_chest_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_command_block_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_furnace_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_tnt_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/shears_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_axe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_hoe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_pickaxe_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_shovel_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_sword_s.ebp create mode 100644 sources/resources/assets/eagler/glsl/deferred/brdf_lut.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_noise3d.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_sample.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_shapes.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_shapes.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_shapes.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/clouds_sun_occlusion.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_combine.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_core.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_core_gbuffer.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_fog.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_local.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_shadow.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/dither16.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/eagler_moon.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/emissive_items.csv create mode 100644 sources/resources/assets/eagler/glsl/deferred/forward_core.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/forward_core.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/gbuffer_debug_view.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/hand_depth_mask.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/lens_ghosts.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/lens_streaks.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/lens_sun_occlusion.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/lib/pbr_env_map.glsl create mode 100644 sources/resources/assets/eagler/glsl/deferred/lib/pbr_lighting.glsl create mode 100644 sources/resources/assets/eagler/glsl/deferred/lib/waving_blocks.glsl create mode 100644 sources/resources/assets/eagler/glsl/deferred/light_point_mesh.dat create mode 100644 sources/resources/assets/eagler/glsl/deferred/light_shafts_sample.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/lighting_mesh.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/lighting_point.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/lighting_sun.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/material_block_constants.csv create mode 100644 sources/resources/assets/eagler/glsl/deferred/metals.csv create mode 100644 sources/resources/assets/eagler/glsl/deferred/moon_render.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/moon_render.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/particles_s.png create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_bloom_blur.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_bloom_bright.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_exposure_avg.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_exposure_final.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_fxaa.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_lens_distort.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/post_tonemap.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/rain.png create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_control.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_normals.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_render.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/realistic_water_render.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/reproject_control.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/reproject_ssr.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/shader_pack_icon.png create mode 100644 sources/resources/assets/eagler/glsl/deferred/shader_pack_info.json create mode 100644 sources/resources/assets/eagler/glsl/deferred/shadows_sun.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox.dat create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_atmosphere.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_irradiance.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_render.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_render.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_render_end.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/skybox_render_end.vsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/ssao_generate.fsh create mode 100644 sources/resources/assets/eagler/glsl/deferred/ssao_noise.bmp create mode 100644 sources/resources/assets/eagler/glsl/deferred/temperatures.lut create mode 100644 sources/resources/assets/eagler/glsl/deferred/vertex_ids.csv create mode 100644 sources/resources/assets/eagler/glsl/texture_blit.fsh create mode 100644 sources/resources/assets/eagler/glsl/texture_blit.vsh diff --git a/CREDITS b/CREDITS index 66b90c2..a6ed136 100644 --- a/CREDITS +++ b/CREDITS @@ -5,9 +5,11 @@ lax1dude: - Creator of Eaglercraft - - Wrote HW accelerated OpenGL 1.3 emulator - - Wrote all desktop emulation code - Ported the Minecraft 1.8 client src to TeaVM + - Wrote HW accelerated OpenGL 1.3 emulator + - Wrote the default shader pack + - Made the integrated PBR resource pack + - Wrote all desktop emulation code - Wrote EaglercraftXBungee - Wrote the patch and build system diff --git a/client_version b/client_version index c386376..ae88067 100644 --- a/client_version +++ b/client_version @@ -1 +1 @@ -u17 \ No newline at end of file +u18 \ No newline at end of file diff --git a/patches/minecraft/net/minecraft/block/Block.edit.java b/patches/minecraft/net/minecraft/block/Block.edit.java index 7fb0477..ce23631 100644 --- a/patches/minecraft/net/minecraft/block/Block.edit.java +++ b/patches/minecraft/net/minecraft/block/Block.edit.java @@ -93,4 +93,11 @@ + } + +> INSERT 43 : 47 @ 43 + ++ ++ public boolean eaglerShadersShouldRenderGlassHighlights() { ++ return false; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/block/BlockGlass.edit.java b/patches/minecraft/net/minecraft/block/BlockGlass.edit.java index 4e588a9..0ce27ab 100644 --- a/patches/minecraft/net/minecraft/block/BlockGlass.edit.java +++ b/patches/minecraft/net/minecraft/block/BlockGlass.edit.java @@ -8,10 +8,17 @@ > CHANGE 2 : 4 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -~ +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > CHANGE 10 : 11 @ 10 : 11 ~ public int quantityDropped(EaglercraftRandom var1) { +> INSERT 14 : 18 @ 14 + ++ ++ public boolean eaglerShadersShouldRenderGlassHighlights() { ++ return DeferredStateManager.isRenderingGlassHighlights(); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/block/BlockLiquid.edit.java b/patches/minecraft/net/minecraft/block/BlockLiquid.edit.java index 7af6f70..c082142 100644 --- a/patches/minecraft/net/minecraft/block/BlockLiquid.edit.java +++ b/patches/minecraft/net/minecraft/block/BlockLiquid.edit.java @@ -8,7 +8,7 @@ > CHANGE 2 : 4 @ 2 : 6 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -~ +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > CHANGE 104 : 105 @ 104 : 105 @@ -18,7 +18,14 @@ ~ public int quantityDropped(EaglercraftRandom var1) { -> CHANGE 64 : 65 @ 64 : 65 +> CHANGE 61 : 65 @ 61 : 62 + +~ return this.blockMaterial == Material.water +~ ? (DeferredStateManager.isRenderingRealisticWater() ? EnumWorldBlockLayer.REALISTIC_WATER +~ : EnumWorldBlockLayer.TRANSLUCENT) +~ : EnumWorldBlockLayer.SOLID; + +> CHANGE 2 : 3 @ 2 : 3 ~ public void randomDisplayTick(World world, BlockPos blockpos, IBlockState iblockstate, EaglercraftRandom random) { diff --git a/patches/minecraft/net/minecraft/block/BlockPane.edit.java b/patches/minecraft/net/minecraft/block/BlockPane.edit.java index 417c470..1dceb55 100644 --- a/patches/minecraft/net/minecraft/block/BlockPane.edit.java +++ b/patches/minecraft/net/minecraft/block/BlockPane.edit.java @@ -8,10 +8,17 @@ > CHANGE 3 : 5 @ 3 : 5 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -~ +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > CHANGE 47 : 48 @ 47 : 48 ~ public Item getItemDropped(IBlockState iblockstate, EaglercraftRandom random, int i) { +> INSERT 101 : 105 @ 101 + ++ public boolean eaglerShadersShouldRenderGlassHighlights() { ++ return this == Blocks.glass_pane && DeferredStateManager.isRenderingGlassHighlights(); ++ } ++ + > EOF diff --git a/patches/minecraft/net/minecraft/client/LoadingScreenRenderer.edit.java b/patches/minecraft/net/minecraft/client/LoadingScreenRenderer.edit.java index 7f8428d..7491629 100644 --- a/patches/minecraft/net/minecraft/client/LoadingScreenRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/LoadingScreenRenderer.edit.java @@ -14,7 +14,9 @@ > DELETE 1 @ 1 : 2 -> DELETE 1 @ 1 : 2 +> CHANGE 1 : 2 @ 1 : 2 + +~ import net.minecraft.client.resources.I18n; > DELETE 10 @ 10 : 11 @@ -26,7 +28,7 @@ ~ GlStateManager.ortho(0.0D, scaledresolution.getScaledWidth_double(), ~ scaledresolution.getScaledHeight_double(), 0.0D, 100.0D, 300.0D); -> INSERT 19 : 33 @ 19 +> INSERT 19 : 37 @ 19 + public void eaglerShow(String line1, String line2) { + if (!this.mc.running) { @@ -42,6 +44,10 @@ + } + } + ++ public void eaglerShowRefreshResources() { ++ eaglerShow(I18n.format("resourcePack.load.refreshing"), I18n.format("resourcePack.load.pleaseWait")); ++ } ++ > CHANGE 13 : 14 @ 13 : 20 diff --git a/patches/minecraft/net/minecraft/client/Minecraft.edit.java b/patches/minecraft/net/minecraft/client/Minecraft.edit.java index af45196..5d3909a 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.edit.java +++ b/patches/minecraft/net/minecraft/client/Minecraft.edit.java @@ -5,7 +5,10 @@ # Version: 1.0 # Author: lax1dude -> DELETE 2 @ 2 : 17 +> CHANGE 2 : 4 @ 2 : 17 + +~ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL._wglBindFramebuffer; +~ > DELETE 2 @ 2 : 6 @@ -17,7 +20,7 @@ > DELETE 1 @ 1 : 4 -> CHANGE 1 : 32 @ 1 : 4 +> CHANGE 1 : 41 @ 1 : 4 ~ ~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput; @@ -44,6 +47,15 @@ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.BlockVertexIDs; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DebugFramebufferView; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShaderPackInfoReloadListener; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.EmissiveItems; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.MetalsLUT; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.PBRTextureMapUtils; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.TemperaturesLUT; ~ import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; ~ import net.lax1dude.eaglercraft.v1_8.profile.GuiScreenEditProfile; ~ import net.lax1dude.eaglercraft.v1_8.profile.SkinPreviewRenderer; @@ -85,7 +97,9 @@ > DELETE 1 @ 1 : 3 -> DELETE 5 @ 5 : 6 +> INSERT 6 : 7 @ 6 + ++ import net.minecraft.util.EnumChatFormatting; > INSERT 11 : 12 @ 11 @@ -119,10 +133,12 @@ ~ private final List> scheduledTasks = new LinkedList(); -> INSERT 14 : 16 @ 14 +> INSERT 14 : 18 @ 14 + public int joinWorldTickCounter = 0; + private int dontPauseTimer = 0; ++ public int bungeeOutdatedMsgTimer = 0; ++ public String bungeeOutdatedMsgVer = null; > CHANGE 3 : 4 @ 3 : 6 @@ -199,7 +215,16 @@ ~ this.standardGalacticFontRenderer = new EaglerFontRenderer(this.gameSettings, -> CHANGE 8 : 9 @ 8 : 9 +> INSERT 5 : 11 @ 5 + ++ this.mcResourceManager.registerReloadListener(new ShaderPackInfoReloadListener()); ++ this.mcResourceManager.registerReloadListener(PBRTextureMapUtils.blockMaterialConstants); ++ this.mcResourceManager.registerReloadListener(new TemperaturesLUT()); ++ this.mcResourceManager.registerReloadListener(new MetalsLUT()); ++ this.mcResourceManager.registerReloadListener(new EmissiveItems()); ++ this.mcResourceManager.registerReloadListener(new BlockVertexIDs()); + +> CHANGE 3 : 4 @ 3 : 4 ~ return HString.format(parString1, new Object[] { GameSettings @@ -207,7 +232,11 @@ ~ GlStateManager.clearDepth(1.0f); -> INSERT 30 : 31 @ 30 +> INSERT 10 : 11 @ 10 + ++ this.textureMapBlocks.setEnablePBREagler(gameSettings.shaders); + +> INSERT 20 : 21 @ 20 + SkinPreviewRenderer.initialize(); @@ -276,7 +305,12 @@ ~ logger.info("Caught error stitching, removing all assigned resourcepacks"); ~ logger.info(runtimeexception); -> CHANGE 16 : 19 @ 16 : 28 +> INSERT 9 : 11 @ 9 + ++ ShaderSource.clearCache(); ++ + +> CHANGE 7 : 10 @ 7 : 19 ~ private void updateDisplayMode() { ~ this.displayWidth = Display.getWidth(); @@ -333,9 +367,16 @@ > DELETE 18 @ 18 : 26 -> CHANGE 1 : 11 @ 1 : 5 +> CHANGE 1 : 4 @ 1 : 5 ~ if (!Display.contextLost()) { +~ this.mcProfiler.startSection("EaglercraftGPU_optimize"); +~ EaglercraftGPU.optimize(); + +> CHANGE 1 : 11 @ 1 : 2 + +~ _wglBindFramebuffer(0x8D40, null); +~ GlStateManager.viewport(0, 0, this.displayWidth, this.displayHeight); ~ GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f); ~ GlStateManager.pushMatrix(); ~ GlStateManager.clear(16640); @@ -344,17 +385,16 @@ ~ if (this.thePlayer != null && this.thePlayer.isEntityInsideOpaqueBlock()) { ~ this.gameSettings.thirdPersonView = 0; ~ } -~ -> CHANGE 1 : 6 @ 1 : 2 +> CHANGE 1 : 6 @ 1 : 5 +~ this.mcProfiler.endSection(); ~ if (!this.skipRenderWorld) { ~ this.mcProfiler.endStartSection("gameRenderer"); ~ this.entityRenderer.func_181560_a(this.timer.renderPartialTicks, i); ~ this.mcProfiler.endSection(); -~ } -> CHANGE 1 : 13 @ 1 : 5 +> CHANGE 2 : 18 @ 2 : 7 ~ this.mcProfiler.endSection(); ~ if (this.gameSettings.showDebugInfo && this.gameSettings.showDebugProfilerChart @@ -368,9 +408,8 @@ ~ } else { ~ this.mcProfiler.profilingEnabled = false; ~ this.prevFrameTime = System.nanoTime(); - -> CHANGE 2 : 4 @ 2 : 7 - +~ } +~ ~ this.guiAchievement.updateAchievementWindow(); ~ GlStateManager.popMatrix(); @@ -434,7 +473,11 @@ + RateLimitTracker.tick(); + -> INSERT 23 : 29 @ 23 +> INSERT 15 : 16 @ 15 + ++ GlStateManager.viewport(0, 0, displayWidth, displayHeight); // to be safe + +> INSERT 8 : 14 @ 8 + if (this.currentScreen == null && this.dontPauseTimer <= 0) { + if (!Mouse.isMouseGrabbed()) { @@ -470,18 +513,64 @@ + KeyBinding.setKeyBindState(gameSettings.keyBindSprint.getKeyCode(), Keyboard.getEventKeyState()); + } -> CHANGE 26 : 27 @ 26 : 27 +> CHANGE 19 : 27 @ 19 : 21 + +~ if (EaglerDeferredPipeline.instance != null) { +~ if (k == 62) { +~ DebugFramebufferView.toggleDebugView(); +~ } else if (k == 0xCB || k == 0xC8) { +~ DebugFramebufferView.switchView(-1); +~ } else if (k == 0xCD || k == 0xD0) { +~ DebugFramebufferView.switchView(1); +~ } + +> CHANGE 5 : 6 @ 5 : 6 ~ if (k == 1 || (k > -1 && k == this.gameSettings.keyBindClose.getKeyCode())) { -> INSERT 41 : 42 @ 41 +> INSERT 11 : 18 @ 11 + ++ if (k == 19 && Keyboard.isKeyDown(61)) { // F3+R ++ if (gameSettings.shaders) { ++ ShaderSource.clearCache(); ++ this.renderGlobal.loadRenderers(); ++ } ++ } ++ + +> INSERT 30 : 31 @ 30 + GlStateManager.recompileShaders(); -> INSERT 206 : 212 @ 206 +> INSERT 206 : 237 @ 206 + if (this.theWorld != null) { + ++joinWorldTickCounter; ++ if (bungeeOutdatedMsgTimer > 0) { ++ if (--bungeeOutdatedMsgTimer == 0) { ++ String pfx = EnumChatFormatting.GOLD + "[EagX]" + EnumChatFormatting.AQUA; ++ ingameGUI.getChatGUI() ++ .printChatMessage(new ChatComponentText(pfx + " ---------------------------------------")); ++ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText( ++ pfx + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD + " MESSAGE FROM LAX:")); ++ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx)); ++ ingameGUI.getChatGUI() ++ .printChatMessage(new ChatComponentText( ++ pfx + " This server appears to be using version " + EnumChatFormatting.YELLOW ++ + bungeeOutdatedMsgVer + EnumChatFormatting.AQUA + " of")); ++ ingameGUI.getChatGUI().printChatMessage( ++ new ChatComponentText(pfx + " the EaglerXBungee plugin which has memory leaks")); ++ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx)); ++ ingameGUI.getChatGUI() ++ .printChatMessage(new ChatComponentText(pfx + " If you are the admin update to " ++ + EnumChatFormatting.YELLOW + "1.0.6" + EnumChatFormatting.AQUA + " or newer")); ++ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx)); ++ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx + EnumChatFormatting.GREEN ++ + " https://ftp.deev.is/EaglerXBungee-1.0.6-MemleakFix.jar")); ++ ingameGUI.getChatGUI() ++ .printChatMessage(new ChatComponentText(pfx + " ---------------------------------------")); ++ } ++ } + } else { + joinWorldTickCounter = 0; + } @@ -503,7 +592,14 @@ ~ this.thePlayer = this.playerController.func_178892_a(this.theWorld, new StatFileWriter()); -> CHANGE 165 : 166 @ 165 : 166 +> CHANGE 34 : 38 @ 34 : 35 + +~ if (theMinecraft == null) +~ return false; +~ GameSettings g = theMinecraft.gameSettings; +~ return g.ambientOcclusion != 0 && !g.shadersAODisable; + +> CHANGE 130 : 131 @ 130 : 131 ~ return EagRuntime.getVersion(); @@ -579,7 +675,7 @@ > DELETE 24 @ 24 : 32 -> INSERT 7 : 15 @ 7 +> INSERT 7 : 19 @ 7 + + public static int getGLMaximumTextureSize() { @@ -589,5 +685,9 @@ + public boolean areKeysLocked() { + return PlatformInput.lockKeys; + } ++ ++ public ModelManager getModelManager() { ++ return modelManager; ++ } > EOF diff --git a/patches/minecraft/net/minecraft/client/gui/GuiButton.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiButton.edit.java index 100e7ff..f0f9c2a 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiButton.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiButton.edit.java @@ -11,4 +11,26 @@ > DELETE 3 @ 3 : 6 +> INSERT 13 : 14 @ 13 + ++ public float fontScale = 1.0f; + +> CHANGE 51 : 66 @ 51 : 53 + +~ if (fontScale == 1.0f) { +~ this.drawCenteredString(fontrenderer, this.displayString, this.xPosition + this.width / 2, +~ this.yPosition + (this.height - 8) / 2, j); +~ } else { +~ float xScale = fontScale; +~ float yScale = 1.0f + (fontScale - 1.0f) * 0.7f; +~ float strWidth = fontrenderer.getStringWidth(displayString) / xScale; +~ GlStateManager.pushMatrix(); +~ GlStateManager.translate(this.xPosition + this.width / 2, +~ this.yPosition + (this.height - 8 * yScale) / 2, 1.0f); +~ GlStateManager.scale(xScale, yScale, 1.0f); +~ GlStateManager.translate(-strWidth * 0.5f * xScale, 0.0f, 0.0f); +~ fontrenderer.drawStringWithShadow(displayString, 0, 0, j); +~ GlStateManager.popMatrix(); +~ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/gui/GuiIngame.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiIngame.edit.java index afdf520..5d696a1 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiIngame.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiIngame.edit.java @@ -37,9 +37,11 @@ > DELETE 27 @ 27 : 28 -> CHANGE 16 : 17 @ 16 : 21 +> CHANGE 16 : 19 @ 16 : 21 ~ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); +~ GlStateManager.enableDepth(); +~ GlStateManager.disableLighting(); > DELETE 21 @ 21 : 22 diff --git a/patches/minecraft/net/minecraft/client/gui/GuiLanguage.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiLanguage.edit.java index 31fe1e0..2eafa10 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiLanguage.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiLanguage.edit.java @@ -20,10 +20,9 @@ ~ protected void actionPerformed(GuiButton parGuiButton) { -> INSERT 56 : 58 @ 56 +> INSERT 56 : 57 @ 56 -+ this.mc.loadingScreen.eaglerShow(I18n.format("resourcePack.load.refreshing"), -+ I18n.format("resourcePack.load.pleaseWait")); ++ this.mc.loadingScreen.eaglerShowRefreshResources(); > INSERT 9 : 10 @ 9 diff --git a/patches/minecraft/net/minecraft/client/gui/GuiMainMenu.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiMainMenu.edit.java index 8a89ac7..f546a36 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiMainMenu.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiMainMenu.edit.java @@ -254,19 +254,51 @@ + s1 = EaglercraftVersion.mainMenuStringD; + this.drawString(this.fontRendererObj, s1, this.width - this.fontRendererObj.getStringWidth(s1) - 2, -> CHANGE 1 : 9 @ 1 : 7 +> CHANGE 1 : 10 @ 1 : 7 ~ -~ String lbl = "CREDITS.txt"; -~ int w = fontRendererObj.getStringWidth(lbl) * 3 / 4; -~ -~ if (i >= (this.width - w - 4) && i <= this.width && j >= 0 && j <= 9) { -~ drawRect((this.width - w - 4), 0, this.width, 10, 0x55000099); -~ } else { -~ drawRect((this.width - w - 4), 0, this.width, 10, 0x55200000); +~ GlStateManager.pushMatrix(); +~ GlStateManager.scale(0.75f, 0.75f, 0.75f); +~ int www = 0; +~ int hhh = 0; +~ s1 = EaglercraftVersion.mainMenuStringG; +~ if (s1 != null) { +~ www = this.fontRendererObj.getStringWidth(s1); +~ hhh += 10; -> INSERT 2 : 8 @ 2 +> INSERT 1 : 20 @ 1 ++ s1 = EaglercraftVersion.mainMenuStringH; ++ if (s1 != null) { ++ www = Math.max(www, this.fontRendererObj.getStringWidth(s1)); ++ hhh += 10; ++ } ++ if (www > 0) { ++ drawRect(0, 0, www + 6, hhh + 4, 0x55200000); ++ s1 = EaglercraftVersion.mainMenuStringG; ++ if (s1 != null) { ++ www = this.fontRendererObj.getStringWidth(s1); ++ this.drawString(this.fontRendererObj, s1, 3, 3, 0xFFFFFF99); ++ } ++ s1 = EaglercraftVersion.mainMenuStringH; ++ if (s1 != null) { ++ www = Math.max(www, this.fontRendererObj.getStringWidth(s1)); ++ this.drawString(this.fontRendererObj, s1, 3, 13, 0xFFFFFF99); ++ } ++ } ++ GlStateManager.popMatrix(); + +> INSERT 1 : 16 @ 1 + ++ String lbl = "CREDITS.txt"; ++ int w = fontRendererObj.getStringWidth(lbl) * 3 / 4; ++ ++ if (i >= (this.width - w - 4) && i <= this.width && j >= 0 && j <= 9) { ++ drawRect((this.width - w - 4), 0, this.width, 10, 0x55000099); ++ } else { ++ drawRect((this.width - w - 4), 0, this.width, 10, 0x55200000); ++ } ++ + GlStateManager.pushMatrix(); + GlStateManager.translate((this.width - w - 2), 2.0f, 0.0f); + GlStateManager.scale(0.75f, 0.75f, 0.75f); diff --git a/patches/minecraft/net/minecraft/client/gui/GuiOptions.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiOptions.edit.java index 332f427..d89f9d4 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiOptions.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiOptions.edit.java @@ -5,26 +5,25 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 4 @ 2 : 3 +> CHANGE 2 : 7 @ 2 : 24 ~ import net.lax1dude.eaglercraft.v1_8.EagRuntime; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui.GuiShaderConfig; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui.GuiShadersNotSupported; ~ import net.lax1dude.eaglercraft.v1_8.vfs.SYS; -> DELETE 4 @ 4 : 21 - > DELETE 2 @ 2 : 3 -> INSERT 12 : 14 @ 12 +> INSERT 12 : 13 @ 12 -+ private GuiButton notSoSuperSecret; + private GuiButton broadcastSettings; -> CHANGE 46 : 48 @ 46 : 48 +> CHANGE 47 : 48 @ 47 : 59 -~ this.buttonList.add(notSoSuperSecret = new GuiButton(8675309, this.width / 2 + 5, this.height / 6 + 48 - 6, 150, -~ 20, "Super Secret Settings...") { +~ I18n.format("shaders.gui.optionsButton"))); -> CHANGE 13 : 16 @ 13 : 15 +> CHANGE 2 : 5 @ 2 : 4 ~ this.buttonList.add(broadcastSettings = new GuiButton(107, this.width / 2 + 5, this.height / 6 + 72 - 6, 150, ~ 20, I18n.format(EagRuntime.getRecText(), new Object[0]))); @@ -53,9 +52,14 @@ ~ protected void actionPerformed(GuiButton parGuiButton) { -> CHANGE 32 : 33 @ 32 : 33 +> CHANGE 32 : 38 @ 32 : 33 -~ notSoSuperSecret.displayString = "Nope!"; +~ if (EaglerDeferredPipeline.isSupported()) { +~ this.mc.displayGuiScreen(new GuiShaderConfig(this)); +~ } else { +~ this.mc.displayGuiScreen(new GuiShadersNotSupported(this, +~ I18n.format(EaglerDeferredPipeline.getReasonUnsupported()))); +~ } > DELETE 22 @ 22 : 27 diff --git a/patches/minecraft/net/minecraft/client/gui/GuiScreen.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiScreen.edit.java index 5bdaf8a..541c3a4 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiScreen.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiScreen.edit.java @@ -107,7 +107,13 @@ ~ EagRuntime.setClipboard(copyText); -> INSERT 176 : 177 @ 176 +> CHANGE 68 : 71 @ 68 : 69 + +~ if (s1.length() > 0) { +~ this.fontRendererObj.drawStringWithShadow(s1, (float) j2, (float) k2, -1); +~ } + +> INSERT 107 : 108 @ 107 + String uri = clickevent.getValue(); diff --git a/patches/minecraft/net/minecraft/client/gui/GuiVideoSettings.edit.java b/patches/minecraft/net/minecraft/client/gui/GuiVideoSettings.edit.java index 66b65e2..a15a2d1 100644 --- a/patches/minecraft/net/minecraft/client/gui/GuiVideoSettings.edit.java +++ b/patches/minecraft/net/minecraft/client/gui/GuiVideoSettings.edit.java @@ -15,7 +15,7 @@ ~ GameSettings.Options.BLOCK_ALTERNATIVES, GameSettings.Options.ENTITY_SHADOWS, GameSettings.Options.FOG, ~ GameSettings.Options.FULLSCREEN, GameSettings.Options.HUD_FPS, GameSettings.Options.HUD_COORDS, ~ GameSettings.Options.HUD_PLAYER, GameSettings.Options.HUD_STATS, GameSettings.Options.HUD_WORLD, -~ GameSettings.Options.HUD_24H, GameSettings.Options.CHUNK_FIX }; +~ GameSettings.Options.HUD_24H, GameSettings.Options.CHUNK_FIX, GameSettings.Options.FAST_MATH }; > CHANGE 11 : 13 @ 11 : 14 diff --git a/patches/minecraft/net/minecraft/client/model/ModelDragon.edit.java b/patches/minecraft/net/minecraft/client/model/ModelDragon.edit.java index adb3014..6014e0c 100644 --- a/patches/minecraft/net/minecraft/client/model/ModelDragon.edit.java +++ b/patches/minecraft/net/minecraft/client/model/ModelDragon.edit.java @@ -5,8 +5,23 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 3 @ 2 : 5 +> CHANGE 2 : 6 @ 2 : 5 +~ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; + +> INSERT 154 : 155 @ 154 + ++ boolean flag = DeferredStateManager.isEnableShadowRender(); + +> CHANGE 18 : 19 @ 18 : 19 + +~ GlStateManager.cullFace(flag ? GL_BACK : GL_FRONT); + +> CHANGE 4 : 5 @ 4 : 5 + +~ GlStateManager.cullFace(flag ? GL_FRONT : GL_BACK); > EOF diff --git a/patches/minecraft/net/minecraft/client/particle/EffectRenderer.edit.java b/patches/minecraft/net/minecraft/client/particle/EffectRenderer.edit.java index ff774b6..2a32d0d 100644 --- a/patches/minecraft/net/minecraft/client/particle/EffectRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/particle/EffectRenderer.edit.java @@ -7,13 +7,14 @@ > DELETE 2 @ 2 : 4 -> CHANGE 3 : 6 @ 3 : 4 +> CHANGE 3 : 7 @ 3 : 4 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.AcceleratedEffectRenderer; +~ import net.lax1dude.eaglercraft.v1_8.minecraft.IAcceleratedParticleEngine; ~ -> INSERT 1 : 7 @ 1 +> INSERT 1 : 9 @ 1 + + import com.google.common.collect.Lists; @@ -21,6 +22,8 @@ + + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.GBufferAcceleratedEffectRenderer; > DELETE 3 @ 3 : 36 @@ -28,19 +31,48 @@ > DELETE 1 @ 1 : 2 -> CHANGE 20 : 21 @ 20 : 21 +> INSERT 16 : 18 @ 16 + ++ private static final ResourceLocation particleMaterialsTextures = new ResourceLocation( ++ "eagler:glsl/deferred/particles_s.png"); + +> CHANGE 4 : 5 @ 4 : 5 ~ private EaglercraftRandom rand = new EaglercraftRandom(); -> INSERT 2 : 4 @ 2 +> INSERT 2 : 5 @ 2 -+ private AcceleratedEffectRenderer acceleratedParticleRenderer = new AcceleratedEffectRenderer(); ++ public static final AcceleratedEffectRenderer vanillaAcceleratedParticleRenderer = new AcceleratedEffectRenderer(); ++ public IAcceleratedParticleEngine acceleratedParticleRenderer = vanillaAcceleratedParticleRenderer; + -> CHANGE 170 : 172 @ 170 : 172 +> CHANGE 157 : 167 @ 157 : 158 + +~ public boolean hasParticlesInAlphaLayer() { +~ for (int i = 0; i < 3; ++i) { +~ if (!this.fxLayers[i][0].isEmpty()) { +~ return true; +~ } +~ } +~ return false; +~ } +~ +~ public void renderParticles(Entity entityIn, float partialTicks, int pass) { + +> CHANGE 8 : 12 @ 8 : 10 + +~ if (!DeferredStateManager.isDeferredRenderer()) { +~ GlStateManager.enableBlend(); +~ GlStateManager.blendFunc(770, 771); +~ } + +> CHANGE 2 : 7 @ 2 : 4 ~ for (int i = 0; i < 3; ++i) { ~ for (int j = 1; j >= 0; --j) { +~ if (pass != 2 && j != pass) { +~ continue; +~ } > CHANGE 1 : 8 @ 1 : 8 @@ -57,11 +89,24 @@ + float texCoordWidth = 0.001f; + float texCoordHeight = 0.001f; -> INSERT 4 : 5 @ 4 +> INSERT 3 : 4 @ 3 ++ GBufferAcceleratedEffectRenderer.isMaterialNormalTexture = false; + +> INSERT 1 : 7 @ 1 + ++ if (DeferredStateManager.isDeferredRenderer()) { ++ GlStateManager.setActiveTexture(33986); ++ this.renderer.bindTexture(particleMaterialsTextures); ++ GlStateManager.setActiveTexture(33984); ++ } + texCoordWidth = texCoordHeight = 1.0f / 256.0f; -> INSERT 3 : 6 @ 3 +> INSERT 2 : 3 @ 2 + ++ GBufferAcceleratedEffectRenderer.isMaterialNormalTexture = true; + +> INSERT 1 : 4 @ 1 + TextureMap blockMap = (TextureMap) this.renderer.getTexture(TextureMap.locationBlocksTexture); + texCoordWidth = 1.0f / blockMap.getWidth(); diff --git a/patches/minecraft/net/minecraft/client/particle/EntityDiggingFX.edit.java b/patches/minecraft/net/minecraft/client/particle/EntityDiggingFX.edit.java index 3698bc8..8b28189 100644 --- a/patches/minecraft/net/minecraft/client/particle/EntityDiggingFX.edit.java +++ b/patches/minecraft/net/minecraft/client/particle/EntityDiggingFX.edit.java @@ -12,11 +12,16 @@ > DELETE 3 @ 3 : 6 -> INSERT 3 : 4 @ 3 +> INSERT 3 : 5 @ 3 ++ import net.minecraft.util.EnumWorldBlockLayer; + import net.minecraft.util.MathHelper; -> INSERT 90 : 103 @ 90 +> INSERT 15 : 16 @ 15 + ++ this.particleAlpha = state.getBlock().getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT ? 0.999f : 1.0f; + +> INSERT 75 : 88 @ 75 + public boolean renderAccelerated(IAcceleratedParticleEngine accelerator, Entity var2, float f, float f1, float f2, + float f3, float f4, float f5) { diff --git a/patches/minecraft/net/minecraft/client/particle/EntityLargeExplodeFX.edit.java b/patches/minecraft/net/minecraft/client/particle/EntityLargeExplodeFX.edit.java index 2aec0d8..5626248 100644 --- a/patches/minecraft/net/minecraft/client/particle/EntityLargeExplodeFX.edit.java +++ b/patches/minecraft/net/minecraft/client/particle/EntityLargeExplodeFX.edit.java @@ -5,10 +5,11 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 5 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 1 @ 1 : 4 @@ -18,8 +19,25 @@ > DELETE 6 @ 6 : 10 -> CHANGE 30 : 31 @ 30 : 31 +> CHANGE 30 : 32 @ 30 : 31 +~ int l = DeferredStateManager.isInDeferredPass() ? ((var2.getBrightnessForRender(f) >> 16) & 0xFF) : 0; ~ worldrenderer.begin(7, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); +> CHANGE 4 : 5 @ 4 : 5 + +~ .lightmap(l, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); + +> CHANGE 4 : 5 @ 4 : 5 + +~ .lightmap(l, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); + +> CHANGE 4 : 5 @ 4 : 5 + +~ .lightmap(l, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); + +> CHANGE 4 : 5 @ 4 : 5 + +~ .lightmap(l, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/BlockFluidRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/BlockFluidRenderer.edit.java index a5850c0..d7dd9f5 100644 --- a/patches/minecraft/net/minecraft/client/renderer/BlockFluidRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/BlockFluidRenderer.edit.java @@ -5,29 +5,137 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 7 @ 2 + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.BlockVertexIDs; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.minecraft.block.Block; > DELETE 4 @ 4 : 6 -> CHANGE 7 : 9 @ 7 : 9 +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.init.Blocks; + +> CHANGE 6 : 8 @ 6 : 8 ~ private EaglerTextureAtlasSprite[] atlasSpritesLava = new EaglerTextureAtlasSprite[2]; ~ private EaglerTextureAtlasSprite[] atlasSpritesWater = new EaglerTextureAtlasSprite[2]; -> CHANGE 17 : 19 @ 17 : 18 +> INSERT 15 : 17 @ 15 -~ EaglerTextureAtlasSprite[] atextureatlassprite = blockliquid.getMaterial() == Material.lava -~ ? this.atlasSpritesLava ++ BlockPos tmp = new BlockPos(0, 0, 0); ++ boolean deferred = DeferredStateManager.isDeferredRenderer(); -> CHANGE 31 : 32 @ 31 : 32 +> INSERT 1 : 3 @ 1 + ++ boolean lava = blockliquid.getMaterial() == Material.lava; ++ boolean realistic = !lava && DeferredStateManager.isRenderingRealisticWater(); + +> CHANGE 1 : 2 @ 1 : 3 + +~ EaglerTextureAtlasSprite[] atextureatlassprite = lava ? this.atlasSpritesLava : this.atlasSpritesWater; + +> CHANGE 4 : 10 @ 4 : 6 + +~ boolean flag = blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.up(tmp), EnumFacing.UP); +~ if (realistic && blockStateIn.getValue(BlockLiquid.LEVEL).intValue() == 0) { +~ Block blockUp = blockAccess.getBlockState(blockPosIn.up(tmp)).getBlock(); +~ flag &= !blockUp.isFullCube() || !blockUp.isBlockSolid(blockAccess, blockPosIn.up(tmp), EnumFacing.DOWN); +~ } +~ boolean flag1 = blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.down(tmp), EnumFacing.DOWN); + +> CHANGE 1 : 5 @ 1 : 5 + +~ blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.north(tmp), EnumFacing.NORTH), +~ blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.south(tmp), EnumFacing.SOUTH), +~ blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.west(tmp), EnumFacing.WEST), +~ blockliquid.shouldSideBeRendered(blockAccess, blockPosIn.east(tmp), EnumFacing.EAST) }; + +> CHANGE 10 : 16 @ 10 : 16 + +~ float f8 = this.getFluidHeight(blockAccess, blockPosIn.south(tmp), material); +~ float f9 = this.getFluidHeight(blockAccess, blockPosIn.east(tmp).south(tmp), material); +~ float f10 = this.getFluidHeight(blockAccess, blockPosIn.east(tmp), material); +~ double d0 = (double) blockPosIn.x; +~ double d1 = (double) blockPosIn.y; +~ double d2 = (double) blockPosIn.z; + +> CHANGE 3 : 4 @ 3 : 4 ~ EaglerTextureAtlasSprite textureatlassprite = atextureatlassprite[0]; -> CHANGE 105 : 106 @ 105 : 106 +> CHANGE 17 : 22 @ 17 : 20 + +~ if (realistic || f12 < -999.0F) { +~ f13 = realistic ? (f12 < -999.0F ? 0.0f : MathHelper.sin(f12)) +~ : textureatlassprite.getInterpolatedU(0.0D); +~ f17 = realistic ? (f12 < -999.0F ? 0.0f : -MathHelper.cos(f12)) +~ : textureatlassprite.getInterpolatedV(0.0D); + +> CHANGE 1 : 3 @ 1 : 3 + +~ f18 = realistic ? f17 : textureatlassprite.getInterpolatedV(16.0D); +~ f15 = realistic ? f13 : textureatlassprite.getInterpolatedU(16.0D); + +> CHANGE 31 : 36 @ 31 : 32 + +~ if (deferred) +~ worldRendererIn.genNormals(true, f12 <= -999.0F ? BlockVertexIDs.builtin_water_still_vertex_id +~ : BlockVertexIDs.builtin_water_flow_vertex_id); +~ +~ if (blockliquid.func_176364_g(blockAccess, blockPosIn.up(tmp))) { + +> INSERT 8 : 11 @ 8 + ++ if (deferred) ++ worldRendererIn.genNormals(true, f12 <= -999.0F ? BlockVertexIDs.builtin_water_still_vertex_id ++ : BlockVertexIDs.builtin_water_flow_vertex_id); + +> CHANGE 4 : 9 @ 4 : 9 + +~ float f35 = realistic ? 0.0f : atextureatlassprite[0].getMinU(); +~ float f36 = realistic ? 0.0f : atextureatlassprite[0].getMaxU(); +~ float f37 = realistic ? 0.0f : atextureatlassprite[0].getMinV(); +~ float f38 = realistic ? 0.0f : atextureatlassprite[0].getMaxV(); +~ int l1 = blockliquid.getMixedBrightnessForBlock(blockAccess, blockPosIn.down(tmp)); + +> INSERT 10 : 12 @ 10 + ++ if (deferred) ++ worldRendererIn.putNormal(0.0f, -1.0f, 0.0f, BlockVertexIDs.builtin_water_still_vertex_id); + +> CHANGE 23 : 24 @ 23 : 24 ~ EaglerTextureAtlasSprite textureatlassprite1 = atextureatlassprite[1]; +> CHANGE 38 : 45 @ 38 : 43 + +~ float f41 = realistic ? 1.0f : textureatlassprite1.getInterpolatedU(0.0D); +~ float f27 = realistic ? 1.0f : textureatlassprite1.getInterpolatedU(8.0D); +~ float f28 = realistic ? 0.0f +~ : textureatlassprite1.getInterpolatedV((double) ((1.0F - f39) * 16.0F * 0.5F)); +~ float f29 = realistic ? 0.0f +~ : textureatlassprite1.getInterpolatedV((double) ((1.0F - f40) * 16.0F * 0.5F)); +~ float f30 = realistic ? 0.0f : textureatlassprite1.getInterpolatedV(8.0D); + +> CHANGE 15 : 29 @ 15 : 23 + +~ if (deferred) +~ worldRendererIn.putNormal(j1, 0.0f, k1, BlockVertexIDs.builtin_water_flow_vertex_id); +~ if (!realistic) { +~ worldRendererIn.pos(d3, d1 + 0.0D, d4).color(f32, f33, f34, 1.0F) +~ .tex((double) f41, (double) f30).lightmap(k, l).endVertex(); +~ worldRendererIn.pos(d5, d1 + 0.0D, d6).color(f32, f33, f34, 1.0F) +~ .tex((double) f27, (double) f30).lightmap(k, l).endVertex(); +~ worldRendererIn.pos(d5, d1 + (double) f40, d6).color(f32, f33, f34, 1.0F) +~ .tex((double) f27, (double) f29).lightmap(k, l).endVertex(); +~ worldRendererIn.pos(d3, d1 + (double) f39, d4).color(f32, f33, f34, 1.0F) +~ .tex((double) f41, (double) f28).lightmap(k, l).endVertex(); +~ if (deferred) +~ worldRendererIn.putNormal(-j1, 0.0f, -k1, BlockVertexIDs.builtin_water_flow_vertex_id); +~ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/BlockModelRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/BlockModelRenderer.edit.java index 7dec8c3..b7b6477 100644 --- a/patches/minecraft/net/minecraft/client/renderer/BlockModelRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/BlockModelRenderer.edit.java @@ -5,15 +5,25 @@ # Version: 1.0 # Author: lax1dude -> INSERT 4 : 7 @ 4 +> INSERT 4 : 9 @ 4 + + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.VertexMarkerState; > DELETE 3 @ 3 : 7 -> INSERT 75 : 76 @ 75 +> INSERT 72 : 73 @ 72 + ++ boolean isDeferred = DeferredStateManager.isDeferredRenderer(); + +> INSERT 1 : 2 @ 1 + ++ float[] afloat = isDeferred ? new float[EnumFacing.values().length * 2] : null; + +> INSERT 2 : 3 @ 2 + BlockPos.MutableBlockPos pointer = new BlockPos.MutableBlockPos(); @@ -21,4 +31,316 @@ ~ BlockPos blockpos = blockPosIn.offsetEvenFaster(enumfacing, pointer); +> CHANGE 3 : 4 @ 3 : 4 + +~ worldRendererIn, list, bitset, afloat); + +> CHANGE 8 : 9 @ 8 : 9 + +~ worldRendererIn, list1, bitset, afloat); + +> INSERT 9 : 10 @ 9 + ++ boolean isDeferred = DeferredStateManager.isDeferredRenderer(); + +> CHANGE 8 : 9 @ 8 : 9 + +~ if (!isDeferred && block$enumoffsettype == Block.EnumOffsetType.XYZ) { + +> CHANGE 5 : 7 @ 5 : 6 + +~ int[] vertData = isDeferred ? bakedquad.getVertexDataWithNormals() : bakedquad.getVertexData(); +~ this.fillQuadBounds(blockIn, vertData, bakedquad.getFace(), quadBounds, boundsFlags, isDeferred ? 8 : 7); + +> CHANGE 2 : 3 @ 2 : 3 + +~ worldRendererIn.addVertexData(vertData); + +> CHANGE 36 : 37 @ 36 : 37 + +~ BitSet boundsFlags, int deferredStrideOverride) { + +> CHANGE 8 : 12 @ 8 : 11 + +~ int j = i * deferredStrideOverride; +~ float f6 = Float.intBitsToFloat(vertexData[j]); +~ float f7 = Float.intBitsToFloat(vertexData[j + 1]); +~ float f8 = Float.intBitsToFloat(vertexData[j + 2]); + +> INSERT 53 : 60 @ 53 + ++ private final BlockPos blockpos0 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos1 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos2 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos3 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos4 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos5 = new BlockPos(0, 0, 0); ++ + +> CHANGE 2 : 4 @ 2 : 3 + +~ List listQuadsIn, BitSet boundsFlags, float[] quadBounds) { +~ boolean isDeferred = DeferredStateManager.isDeferredRenderer(); + +> CHANGE 11 : 12 @ 11 : 12 + +~ if (!isDeferred && block$enumoffsettype == Block.EnumOffsetType.XYZ) { + +> INSERT 5 : 10 @ 5 + ++ EnumFacing facingIn = bakedquad.getFace(); ++ int[] vertData = isDeferred ? bakedquad.getVertexDataWithNormals() : bakedquad.getVertexData(); ++ blockPosIn.offsetEvenFaster(facingIn, blockpos0); ++ this.fillQuadBounds(blockIn, vertData, facingIn, quadBounds, boundsFlags, isDeferred ? 8 : 7); ++ boolean boundsFlags0 = boundsFlags.get(0); + +> CHANGE 1 : 2 @ 1 : 5 + +~ brightnessIn = boundsFlags0 ? blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos0) + +> CHANGE 3 : 100 @ 3 : 5 + +~ worldRendererIn.addVertexData(vertData); +~ +~ if (isDeferred) { +~ BlockModelRenderer.EnumNeighborInfo blockmodelrenderer$enumneighborinfo = BlockModelRenderer.EnumNeighborInfo +~ .getNeighbourInfo(facingIn); +~ BlockPos blockPosIn2 = boundsFlags0 ? blockpos0 : blockPosIn; +~ blockPosIn2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[0], blockpos1); +~ int i = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos1); +~ blockPosIn2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[1], blockpos2); +~ int j = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos2); +~ blockPosIn2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos3); +~ int k = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos3); +~ blockPosIn2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos4); +~ int l = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos4); +~ +~ blockpos1.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos5); +~ int i1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); +~ +~ blockpos1.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos5); +~ int j1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); +~ +~ blockpos2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos5); +~ int k1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); +~ +~ blockpos2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos5); +~ int l1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); +~ +~ int[] b = new int[4]; +~ +~ boolean upIsOpaque = !blockAccessIn.getBlockState(blockpos0).getBlock().isOpaqueCube(); +~ int i3; +~ if (boundsFlags0 || upIsOpaque) { +~ i3 = (ownBrightness && boundsFlags0) ? brightnessIn +~ : blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos0); +~ } else { +~ i3 = (ownBrightness && !boundsFlags0) ? brightnessIn +~ : blockIn.getMixedBrightnessForBlock(blockAccessIn, blockPosIn); +~ } +~ +~ BlockModelRenderer.VertexTranslations blockmodelrenderer$vertextranslations = BlockModelRenderer.VertexTranslations +~ .getVertexTranslations(facingIn); +~ if (boundsFlags.get(1) && blockmodelrenderer$enumneighborinfo.field_178289_i) { +~ float f13 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[0].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[1].field_178229_m]; +~ float f14 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[2].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[3].field_178229_m]; +~ float f15 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[4].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[5].field_178229_m]; +~ float f16 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[6].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178286_j[7].field_178229_m]; +~ float f17 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[0].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[1].field_178229_m]; +~ float f18 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[2].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[3].field_178229_m]; +~ float f19 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[4].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[5].field_178229_m]; +~ float f20 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[6].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178287_k[7].field_178229_m]; +~ float f21 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[0].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[1].field_178229_m]; +~ float f22 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[2].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[3].field_178229_m]; +~ float f23 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[4].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[5].field_178229_m]; +~ float f24 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[6].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178284_l[7].field_178229_m]; +~ float f25 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[0].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[1].field_178229_m]; +~ float f26 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[2].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[3].field_178229_m]; +~ float f27 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[4].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[5].field_178229_m]; +~ float f28 = quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[6].field_178229_m] +~ * quadBounds[blockmodelrenderer$enumneighborinfo.field_178285_m[7].field_178229_m]; +~ int i2 = getAoBrightness(l, i, j1, i3); +~ int j2 = getAoBrightness(k, i, i1, i3); +~ int k2 = getAoBrightness(k, j, k1, i3); +~ int l2 = getAoBrightness(l, j, l1, i3); +~ b[blockmodelrenderer$vertextranslations.field_178191_g] = getVertexBrightness(i2, j2, k2, l2, f13, +~ f14, f15, f16); +~ b[blockmodelrenderer$vertextranslations.field_178200_h] = getVertexBrightness(i2, j2, k2, l2, f17, +~ f18, f19, f20); +~ b[blockmodelrenderer$vertextranslations.field_178201_i] = getVertexBrightness(i2, j2, k2, l2, f21, +~ f22, f23, f24); +~ b[blockmodelrenderer$vertextranslations.field_178198_j] = getVertexBrightness(i2, j2, k2, l2, f25, +~ f26, f27, f28); +~ } else { +~ b[blockmodelrenderer$vertextranslations.field_178191_g] = getAoBrightness(l, i, j1, i3); +~ b[blockmodelrenderer$vertextranslations.field_178200_h] = getAoBrightness(k, i, i1, i3); +~ b[blockmodelrenderer$vertextranslations.field_178201_i] = getAoBrightness(k, j, k1, i3); +~ b[blockmodelrenderer$vertextranslations.field_178198_j] = getAoBrightness(l, j, l1, i3); +~ } +~ worldRendererIn.putBrightness4(b[0], b[1], b[2], b[3]); +~ } else { +~ worldRendererIn.putBrightness4(brightnessIn, brightnessIn, brightnessIn, brightnessIn); +~ } +~ + +> INSERT 20 : 36 @ 20 + ++ private static int getAoBrightness(int parInt1, int parInt2, int parInt3, int parInt4) { ++ if (parInt1 == 0) { ++ parInt1 = parInt4; ++ } ++ ++ if (parInt2 == 0) { ++ parInt2 = parInt4; ++ } ++ ++ if (parInt3 == 0) { ++ parInt3 = parInt4; ++ } ++ ++ return parInt1 + parInt2 + parInt3 + parInt4 >> 2 & 16711935; ++ } ++ + +> CHANGE 45 : 47 @ 45 : 46 + +~ worldrenderer.putNormal((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ(), +~ VertexMarkerState.markId); + +> INSERT 9 : 16 @ 9 + ++ private final BlockPos blockpos0 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos1 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos2 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos3 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos4 = new BlockPos(0, 0, 0); ++ private final BlockPos blockpos5 = new BlockPos(0, 0, 0); ++ + +> CHANGE 2 : 3 @ 2 : 3 + +~ BlockPos blockpos = boundsFlags.get(0) ? blockPosIn.offsetEvenFaster(facingIn, blockpos0) : blockPosIn; + +> CHANGE 2 : 3 @ 2 : 6 + +~ blockpos.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[0], blockpos1); + +> DELETE 1 @ 1 : 4 + +> INSERT 1 : 6 @ 1 + ++ blockpos1.offsetEvenFaster(facingIn, blockpos5); ++ boolean flag = blockAccessIn.getBlockState(blockpos5).getBlock().isTranslucent(); ++ ++ blockpos.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[1], blockpos2); ++ int j = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos2); + +> INSERT 1 : 6 @ 1 + ++ blockpos2.offsetEvenFaster(facingIn, blockpos5); ++ boolean flag1 = blockAccessIn.getBlockState(blockpos5).getBlock().isTranslucent(); ++ ++ blockpos.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos3); ++ int k = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos3); + +> INSERT 1 : 6 @ 1 + ++ blockpos3.offsetEvenFaster(facingIn, blockpos5); ++ boolean flag2 = blockAccessIn.getBlockState(blockpos5).getBlock().isTranslucent(); ++ ++ blockpos.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos4); ++ int l = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos4); + +> CHANGE 1 : 4 @ 1 : 5 + +~ blockpos4.offsetEvenFaster(facingIn, blockpos5); +~ boolean flag3 = blockAccessIn.getBlockState(blockpos5).getBlock().isTranslucent(); +~ + +> CHANGE 6 : 7 @ 6 : 7 + +~ blockpos1.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos5); + +> CHANGE 10 : 13 @ 10 : 13 + +~ blockpos1.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos5); +~ f5 = blockAccessIn.getBlockState(blockpos5).getBlock().getAmbientOcclusionLightValue(); +~ j1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); + +> CHANGE 8 : 11 @ 8 : 11 + +~ blockpos2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[2], blockpos5); +~ f6 = blockAccessIn.getBlockState(blockpos5).getBlock().getAmbientOcclusionLightValue(); +~ k1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); + +> CHANGE 8 : 11 @ 8 : 11 + +~ blockpos2.offsetEvenFaster(blockmodelrenderer$enumneighborinfo.field_178276_g[3], blockpos5); +~ f7 = blockAccessIn.getBlockState(blockpos5).getBlock().getAmbientOcclusionLightValue(); +~ l1 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); + +> INSERT 2 : 3 @ 2 + ++ blockPosIn.offsetEvenFaster(facingIn, blockpos5); + +> CHANGE 1 : 3 @ 1 : 4 + +~ if (boundsFlags.get(0) || !blockAccessIn.getBlockState(blockpos5).getBlock().isOpaqueCube()) { +~ i3 = blockIn.getMixedBrightnessForBlock(blockAccessIn, blockpos5); + +> CHANGE 52 : 64 @ 52 : 64 + +~ int i2 = getAoBrightness(l, i, j1, i3); +~ int j2 = getAoBrightness(k, i, i1, i3); +~ int k2 = getAoBrightness(k, j, k1, i3); +~ int l2 = getAoBrightness(l, j, l1, i3); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178191_g] = getVertexBrightness(i2, +~ j2, k2, l2, f13, f14, f15, f16); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178200_h] = getVertexBrightness(i2, +~ j2, k2, l2, f17, f18, f19, f20); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178201_i] = getVertexBrightness(i2, +~ j2, k2, l2, f21, f22, f23, f24); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178198_j] = getVertexBrightness(i2, +~ j2, k2, l2, f25, f26, f27, f28); + +> CHANGE 5 : 13 @ 5 : 13 + +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178191_g] = getAoBrightness(l, i, j1, +~ i3); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178200_h] = getAoBrightness(k, i, i1, +~ i3); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178201_i] = getAoBrightness(k, j, k1, +~ i3); +~ this.vertexBrightness[blockmodelrenderer$vertextranslations.field_178198_j] = getAoBrightness(l, j, l1, +~ i3); + +> INSERT 7 : 8 @ 7 + ++ } + +> CHANGE 1 : 8 @ 1 : 25 + +~ private static int getVertexBrightness(int parInt1, int parInt2, int parInt3, int parInt4, float parFloat1, +~ float parFloat2, float parFloat3, float parFloat4) { +~ int i = (int) ((float) (parInt1 >> 16 & 255) * parFloat1 + (float) (parInt2 >> 16 & 255) * parFloat2 +~ + (float) (parInt3 >> 16 & 255) * parFloat3 + (float) (parInt4 >> 16 & 255) * parFloat4) & 255; +~ int j = (int) ((float) (parInt1 & 255) * parFloat1 + (float) (parInt2 & 255) * parFloat2 +~ + (float) (parInt3 & 255) * parFloat3 + (float) (parInt4 & 255) * parFloat4) & 255; +~ return i << 16 | j; + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/ChunkRenderContainer.edit.java b/patches/minecraft/net/minecraft/client/renderer/ChunkRenderContainer.edit.java index d814976..25deccd 100644 --- a/patches/minecraft/net/minecraft/client/renderer/ChunkRenderContainer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/ChunkRenderContainer.edit.java @@ -7,11 +7,33 @@ > DELETE 2 @ 2 : 3 -> CHANGE 1 : 5 @ 1 : 2 +> CHANGE 1 : 6 @ 1 : 2 ~ ~ import com.google.common.collect.Lists; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; + +> INSERT 3 : 4 @ 3 + ++ import net.minecraft.util.MathHelper; + +> CHANGE 16 : 17 @ 16 : 17 + +~ public void preRenderChunk(RenderChunk renderChunkIn, EnumWorldBlockLayer enumworldblocklayer) { + +> CHANGE 1 : 11 @ 1 : 4 + +~ float posX = (float) ((double) blockpos.getX() - this.viewEntityX); +~ float posY = (float) ((double) blockpos.getY() - this.viewEntityY); +~ float posZ = (float) ((double) blockpos.getZ() - this.viewEntityZ); +~ GlStateManager.translate(posX, posY, posZ); +~ if (DeferredStateManager.isInForwardPass()) { +~ posX = (float) (blockpos.getX() - (MathHelper.floor_double(this.viewEntityX / 16.0) << 4)); // TODO +~ posY = (float) (blockpos.getY() - (MathHelper.floor_double(this.viewEntityY / 16.0) << 4)); +~ posZ = (float) (blockpos.getZ() - (MathHelper.floor_double(this.viewEntityZ / 16.0) << 4)); +~ DeferredStateManager.reportForwardRenderObjectPosition((int) posX, (int) posY, (int) posZ); +~ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/EntityRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/EntityRenderer.edit.java index b1191ba..6863e7d 100644 --- a/patches/minecraft/net/minecraft/client/renderer/EntityRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/EntityRenderer.edit.java @@ -5,16 +5,18 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 3 @ 2 : 7 +> CHANGE 2 : 5 @ 2 : 7 ~ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +~ +~ import java.util.Arrays; > CHANGE 1 : 3 @ 1 : 2 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ import net.lax1dude.eaglercraft.v1_8.HString; -> INSERT 1 : 15 @ 1 +> INSERT 1 : 27 @ 1 + + import com.google.common.base.Predicate; @@ -30,28 +32,61 @@ + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.BetterFrustum; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DebugFramebufferView; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredConfig; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui.GuiShaderConfig; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.EmissiveItems; ++ import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; -> DELETE 10 @ 10 : 19 +> CHANGE 10 : 13 @ 10 : 20 -> DELETE 7 @ 7 : 9 +~ import net.minecraft.client.particle.EntityFX; +~ import net.minecraft.client.renderer.RenderGlobal.ChunkCullAdapter; +~ import net.minecraft.client.renderer.chunk.RenderChunk; -> DELETE 7 @ 7 : 10 +> INSERT 1 : 2 @ 1 -> DELETE 20 @ 20 : 27 ++ import net.minecraft.client.renderer.entity.Render; + +> INSERT 2 : 3 @ 2 + ++ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; + +> DELETE 3 @ 3 : 5 + +> INSERT 6 : 7 @ 6 + ++ import net.minecraft.entity.item.EntityItem; + +> DELETE 1 @ 1 : 4 + +> INSERT 18 : 19 @ 18 + ++ import net.minecraft.util.Vec3i; + +> DELETE 2 @ 2 : 9 > CHANGE 9 : 10 @ 9 : 10 ~ private EaglercraftRandom random = new EaglercraftRandom(); -> DELETE 43 @ 43 : 61 +> DELETE 43 @ 43 : 59 -> INSERT 1 : 2 @ 1 +> INSERT 3 : 5 @ 3 + private GameOverlayFramebuffer overlayFramebuffer; ++ private float eagPartialTicks = 0.0f; -> DELETE 2 @ 2 : 4 +> DELETE 2 @ 2 : 3 -> CHANGE 8 : 9 @ 8 : 9 +> CHANGE 9 : 10 @ 9 : 10 ~ this.overlayFramebuffer = new GameOverlayFramebuffer(); @@ -73,33 +108,42 @@ > DELETE 3 @ 3 : 9 -> DELETE 3 @ 3 : 4 +> DELETE 7 @ 7 : 22 > DELETE 3 @ 3 : 18 -> DELETE 3 @ 3 : 18 +> CHANGE 3 : 4 @ 3 : 18 -> DELETE 3 @ 3 : 18 +~ this.useShader = false; > DELETE 3 @ 3 : 14 > DELETE 3 @ 3 : 7 -> DELETE 44 @ 44 : 48 +> CHANGE 23 : 26 @ 23 : 24 + +~ float f3 = this.mc.theWorld.getLightBrightness( +~ DeferredStateManager.isDeferredRenderer() ? new BlockPos(this.mc.getRenderViewEntity()).up() +~ : new BlockPos(this.mc.getRenderViewEntity())); + +> DELETE 20 @ 20 : 24 > DELETE 1 @ 1 : 8 -> CHANGE 118 : 119 @ 118 : 119 +> CHANGE 111 : 112 @ 111 : 112 + +~ public float getFOVModifier(float partialTicks, boolean parFlag) { + +> CHANGE 6 : 7 @ 6 : 7 ~ f = this.mc.gameSettings.keyBindZoomCamera.isKeyDown() ? 17.0f : this.mc.gameSettings.fovSetting; -> CHANGE 169 : 170 @ 169 : 170 +> CHANGE 169 : 173 @ 169 : 172 +~ float farPlane = this.farPlaneDistance * 2.0f * MathHelper.SQRT_2; ~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), - -> CHANGE 1 : 2 @ 1 : 2 - -~ this.farPlaneDistance * 2.0f * MathHelper.SQRT_2); +~ (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, farPlane); +~ DeferredStateManager.setGBufferNearFarPlanes(0.05f, farPlane); > CHANGE 57 : 58 @ 57 : 58 @@ -107,7 +151,22 @@ > DELETE 43 @ 43 : 55 -> CHANGE 121 : 122 @ 121 : 122 +> INSERT 4 : 16 @ 4 + ++ public static void disableLightmapStatic() { ++ GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); ++ GlStateManager.disableTexture2D(); ++ GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); ++ } ++ ++ public static void enableLightmapStatic() { ++ GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); ++ GlStateManager.enableTexture2D(); ++ GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); ++ } ++ + +> CHANGE 117 : 118 @ 117 : 118 ~ this.lightmapColors[i] = short1 << 24 | j | k << 8 | l << 16; @@ -138,7 +197,7 @@ > DELETE 39 @ 39 : 52 -> CHANGE 4 : 43 @ 4 : 5 +> CHANGE 4 : 44 @ 4 : 5 ~ long framebufferAge = this.overlayFramebuffer.getAge(); ~ if (framebufferAge == -1l || framebufferAge > (Minecraft.getDebugFPS() < 25 ? 125l : 75l)) { @@ -152,6 +211,7 @@ ~ this.overlayFramebuffer.endRender(); ~ } ~ this.setupOverlayRendering(); +~ GlStateManager.disableLighting(); ~ GlStateManager.enableBlend(); ~ if (Minecraft.isFancyGraphicsEnabled()) { ~ this.mc.ingameGUI.renderVignette(parFloat1, l, i1); @@ -198,24 +258,50 @@ ~ EaglercraftGPU.glLineWidth(1.0F); -> INSERT 25 : 32 @ 25 +> INSERT 25 : 33 @ 25 + -+ boolean fxaa = (this.mc.gameSettings.fxaa == 0 && this.mc.gameSettings.fancyGraphics) -+ || this.mc.gameSettings.fxaa == 1; ++ boolean fxaa = !this.mc.gameSettings.shaders ++ && ((this.mc.gameSettings.fxaa == 0 && this.mc.gameSettings.fancyGraphics) ++ || this.mc.gameSettings.fxaa == 1); + if (fxaa) { + EffectPipelineFXAA.begin(this.mc.displayWidth, this.mc.displayHeight); + } + -> INSERT 16 : 20 @ 16 +> CHANGE 4 : 5 @ 4 : 5 + +~ if (this.mc.gameSettings.anaglyph && !this.mc.gameSettings.shaders) { + +> CHANGE 8 : 24 @ 8 : 9 + +~ if (this.mc.gameSettings.shaders) { +~ try { +~ this.eaglercraftShaders(partialTicks, finishTimeNano); +~ } catch (Throwable t) { +~ logger.error("Exception caught running deferred render!"); +~ logger.error(t); +~ EaglerDeferredPipeline.instance.resetContextStateAfterException(); +~ logger.error("Suspending shaders..."); +~ EaglerDeferredPipeline.isSuspended = true; +~ +~ } +~ mc.effectRenderer.acceleratedParticleRenderer = EffectRenderer.vanillaAcceleratedParticleRenderer; +~ } else { +~ mc.effectRenderer.acceleratedParticleRenderer = EffectRenderer.vanillaAcceleratedParticleRenderer; +~ this.renderWorldPass(2, partialTicks, finishTimeNano); +~ } + +> INSERT 2 : 6 @ 2 + if (fxaa) { + EffectPipelineFXAA.end(); + } + -> CHANGE 29 : 31 @ 29 : 31 +> DELETE 15 @ 15 : 17 + +> CHANGE 12 : 14 @ 12 : 14 ~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), ~ (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * 4.0F); @@ -234,7 +320,11 @@ + GlStateManager.shadeModel(7424); -> CHANGE 91 : 92 @ 91 : 92 +> CHANGE 46 : 47 @ 46 : 47 + +~ effectrenderer.renderParticles(entity, partialTicks, 2); + +> CHANGE 44 : 45 @ 44 : 45 ~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), @@ -242,15 +332,77 @@ ~ GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), -> CHANGE 87 : 88 @ 87 : 88 +> INSERT 8 : 10 @ 8 ++ if (DeferredStateManager.isDeferredRenderer()) ++ return; + +> INSERT 70 : 71 @ 70 + ++ boolean df = DeferredStateManager.isInDeferredPass(); + +> CHANGE 9 : 24 @ 9 : 13 + +~ if (!df) { +~ GlStateManager.enableBlend(); +~ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); +~ GlStateManager.alphaFunc(516, 0.1F); +~ } else { +~ GlStateManager.enableAlpha(); +~ DeferredStateManager.setHDRTranslucentPassBlendFunc(); +~ DeferredStateManager.reportForwardRenderObjectPosition2(0.0f, 0.0f, 0.0f); +~ GlStateManager.alphaFunc(516, 0.01F); +~ GlStateManager.depthMask(false); +~ EaglerDeferredPipeline.instance.setForwardRenderLightFactors(0.65f, +~ 4.75f - MathHelper.clamp_float(DeferredStateManager.getSunHeight() * 8.0f - 3.0f, 0.0f, 4.0f), +~ 1.0f, 0.03f); +~ } ~ EaglercraftGPU.glNormal3f(0.0F, 1.0F, 0.0F); -> CHANGE 47 : 48 @ 47 : 48 +> CHANGE 5 : 8 @ 5 : 6 + +~ if (df) { +~ b0 = 8; +~ } else if (this.mc.gameSettings.fancyGraphics) { + +> CHANGE 38 : 39 @ 38 : 39 ~ if (f2 >= 0.15F) { -> CHANGE 236 : 237 @ 236 : 237 +> CHANGE 6 : 15 @ 6 : 7 + +~ this.mc.getTextureManager() +~ .bindTexture(df ? new ResourceLocation("eagler:glsl/deferred/rain.png") +~ : locationRainPng); +~ if (df) { +~ DeferredStateManager.setRoughnessConstant(0.5f); +~ DeferredStateManager.setMetalnessConstant(0.05f); +~ DeferredStateManager.setEmissionConstant(1.0f); +~ GlStateManager.color(0.8F, 0.8F, 1.0F, 0.25F); +~ } + +> INSERT 34 : 40 @ 34 + ++ if (df) { ++ DeferredStateManager.setRoughnessConstant(0.7f); ++ DeferredStateManager.setMetalnessConstant(0.05f); ++ DeferredStateManager.setEmissionConstant(1.0f); ++ GlStateManager.color(1.3F, 1.3F, 1.3F, 0.5F); ++ } + +> CHANGE 41 : 50 @ 41 : 42 + +~ if (!df) { +~ GlStateManager.disableBlend(); +~ } else { +~ GlStateManager.disableAlpha(); +~ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); +~ DeferredStateManager.setDefaultMaterialConstants(); +~ GlStateManager.depthMask(true); +~ EaglerDeferredPipeline.instance.setForwardRenderLightFactors(1.0f, 1.0f, 1.0f, 1.0f); +~ } + +> CHANGE 153 : 154 @ 153 : 154 ~ GlStateManager.clearColor(this.fogColorRed, this.fogColorGreen, this.fogColorBlue, 1.0F); @@ -280,4 +432,983 @@ > DELETE 9 @ 9 : 10 +> INSERT 12 : 988 @ 12 + ++ ++ private static final Vector4f tmpVec4f_1 = new Vector4f(); ++ private static final Matrix4f tmpMat4f_1 = new Matrix4f(); ++ private int shadowFrameIndex = 0; ++ ++ private double blockWaveOffsetX = 0.0; ++ private double blockWaveOffsetY = 0.0; ++ private double blockWaveOffsetZ = 0.0; ++ ++ private void eaglercraftShaders(float partialTicks, long finishTimeNano) { ++ if ((EaglerDeferredPipeline.isSuspended || EaglerDeferredPipeline.instance == null) ++ || (mc.currentScreen != null && mc.currentScreen instanceof GuiShaderConfig)) { ++ EaglerDeferredPipeline.renderSuspended(); ++ return; ++ } ++ mc.mcProfiler.endStartSection("eaglercraftShaders"); ++ EaglerDeferredPipeline.instance.setPartialTicks(partialTicks); ++ eagPartialTicks = partialTicks; ++ EaglerDeferredConfig conf = mc.gameSettings.deferredShaderConf; ++ boolean flag = isDrawBlockOutline(); ++ GlStateManager.viewport(0, 0, mc.displayWidth, mc.displayHeight); ++ mc.mcProfiler.startSection("camera"); ++ setupCameraTransform(partialTicks, 2); ++ EaglerDeferredPipeline.instance.loadViewMatrix(); ++ ActiveRenderInfo.updateRenderInfo(mc.thePlayer, mc.gameSettings.thirdPersonView == 2); ++ mc.mcProfiler.endStartSection("culling"); ++ Frustum frustum = new Frustum(); ++ Entity entity = mc.getRenderViewEntity(); ++ if (entity == null) { ++ entity = mc.thePlayer; ++ } ++ double d0 = EaglerDeferredPipeline.instance.currentRenderX = entity.lastTickPosX ++ + (entity.posX - entity.lastTickPosX) * (double) partialTicks; ++ double d1 = EaglerDeferredPipeline.instance.currentRenderY = entity.lastTickPosY ++ + (entity.posY - entity.lastTickPosY) * (double) partialTicks; ++ double d2 = EaglerDeferredPipeline.instance.currentRenderZ = entity.lastTickPosZ ++ + (entity.posZ - entity.lastTickPosZ) * (double) partialTicks; ++ EaglerDeferredPipeline.instance.updateReprojectionCoordinates(d0, d1, d2); ++ float eyeHeight = entity.getEyeHeight(); ++ frustum.setPosition(d0, d1, d2); ++ ++ // StringBuilder builder = new StringBuilder(); ++ // long ll = Double.doubleToLongBits(d0); ++ // for(int i = 63; i >= 0; --i) { ++ // builder.append((ll >>> i) & 1); ++ // } ++ // System.out.println(builder.toString()); ++ ++ float waveTimer = (float) ((System.currentTimeMillis() % 600000l) * 0.001); ++ DeferredStateManager.setWaterWindOffset(0.0f, 0.0f, waveTimer, waveTimer); ++ ++ float blockWaveDistX = (float) (d0 - blockWaveOffsetX); ++ float blockWaveDistY = (float) (d1 - blockWaveOffsetY); ++ float blockWaveDistZ = (float) (d2 - blockWaveOffsetZ); ++ if (blockWaveDistX * blockWaveDistX + blockWaveDistY * blockWaveDistY + blockWaveDistZ * blockWaveDistZ > 128.0f ++ * 128.0f) { ++ blockWaveOffsetX = MathHelper.floor_double(d0); ++ blockWaveOffsetY = MathHelper.floor_double(d1); ++ blockWaveOffsetZ = MathHelper.floor_double(d2); ++ blockWaveDistX = (float) (d0 - blockWaveOffsetX); ++ blockWaveDistY = (float) (d1 - blockWaveOffsetY); ++ blockWaveDistZ = (float) (d2 - blockWaveOffsetZ); ++ } ++ ++ boolean wavingBlocks = conf.is_rendering_wavingBlocks; ++ ++ DeferredStateManager.setWavingBlockOffset(blockWaveDistX, blockWaveDistY, blockWaveDistZ); ++ if (wavingBlocks) { ++ DeferredStateManager.setWavingBlockParams(1.0f * waveTimer, ++ 200.0f * waveTimer ++ + MathHelper.sin(waveTimer * 0.125f + MathHelper.sin(waveTimer * 1.5f) * 0.2f) * 125.0f, ++ 0.0f, 0.0f); ++ } ++ ++ // if (mc.gameSettings.renderDistanceChunks >= 4) vanilla shows sky not fog ++ ++ mc.mcProfiler.endStartSection("terrain_setup"); ++ mc.renderGlobal.setupTerrain(entity, (double) partialTicks, frustum, frameCount++, mc.thePlayer.isSpectator()); ++ ++ // clear some state: ++ ++ GlStateManager.enableCull(); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.pushMatrix(); ++ GlStateManager.disableAlpha(); ++ GlStateManager.disableBlend(); ++ ++ // vanilla solid chunks pass: ++ ++ EaglerDeferredPipeline.instance.beginDrawDeferred(); ++ EaglerDeferredPipeline.instance.beginDrawMainGBuffer(); ++ ++ EaglerDeferredPipeline.instance.beginDrawMainGBufferTerrain(); ++ ++ mc.mcProfiler.endStartSection("updatechunks"); ++ mc.renderGlobal.updateChunks(finishTimeNano); ++ ++ mc.mcProfiler.endStartSection("terrain"); ++ ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.SOLID, (double) partialTicks, 2, entity); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.5F); ++ if (wavingBlocks) ++ DeferredStateManager.enableDrawWavingBlocks(); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.CUTOUT_MIPPED, (double) partialTicks, 2, entity); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.CUTOUT, (double) partialTicks, 2, entity); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ GlStateManager.alphaFunc(516, 0.1F); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ if (wavingBlocks) ++ DeferredStateManager.disableDrawWavingBlocks(); ++ ++ // vanilla solid entities: ++ ++ EaglerDeferredPipeline.instance.beginDrawMainGBufferEntities(); ++ if (conf.is_rendering_dynamicLights) { ++ DynamicLightManager.setIsRenderingLights(true); ++ } ++ ++ DeferredStateManager.forwardCallbackHandler = DeferredStateManager.forwardCallbackGBuffer; ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ ++ NameTagRenderer.doRenderNameTags = true; ++ NameTagRenderer.nameTagsCount = 0; ++ GlStateManager.pushMatrix(); ++ mc.mcProfiler.endStartSection("entities"); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.startUsingEnvMap(); ++ mc.renderGlobal.renderEntities(entity, frustum, partialTicks); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ mc.mcProfiler.endStartSection("litParticles"); ++ EntityFX.interpPosX = d0; ++ EntityFX.interpPosY = d1; ++ EntityFX.interpPosZ = d2; ++ enableLightmap(); ++ GlStateManager.pushMatrix(); ++ mc.effectRenderer.renderLitParticles(entity, partialTicks); ++ mc.mcProfiler.endStartSection("gbufferParticles"); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ GlStateManager.pushMatrix(); ++ mc.effectRenderer.acceleratedParticleRenderer = EaglerDeferredPipeline.instance.gbufferEffectRenderer; ++ mc.effectRenderer.renderParticles(entity, partialTicks, 1); ++ mc.effectRenderer.acceleratedParticleRenderer = EffectRenderer.vanillaAcceleratedParticleRenderer; ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ DeferredStateManager.endUsingEnvMap(); ++ disableLightmap(); ++ DynamicLightManager.setIsRenderingLights(false); ++ NameTagRenderer.doRenderNameTags = false; ++ ++ mc.mcProfiler.endStartSection("endDrawMainGBuffer"); ++ EaglerDeferredPipeline.instance.endDrawMainGBuffer(); ++ mc.mcProfiler.endStartSection("shadowSetup"); ++ ++ // calculate sun matrix and angle: ++ ++ GlStateManager.matrixMode(5888); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadIdentity(); ++ GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); ++ float celestialAngle = mc.theWorld.getCelestialAngle(partialTicks) * 360.0F; ++ GlStateManager.rotate(DeferredStateManager.sunAngle, 0.0F, 1.0F, 0.0F); ++ ++ if (mc.theWorld.provider.getDimensionId() == 0) { ++ GlStateManager.pushMatrix(); ++ GlStateManager.rotate(celestialAngle + 90.0f, 1.0F, 0.0F, 0.0F); ++ tmpVec4f_1.set(0.0f, 0.0f, 1.0f); ++ GlStateManager.transform(tmpVec4f_1, tmpVec4f_1); ++ tmpVec4f_1.normalise(); ++ DeferredStateManager.setCurrentSunAngle(tmpVec4f_1); ++ if (tmpVec4f_1.y > 0.1f) { ++ celestialAngle += 180.0f; ++ } ++ GlStateManager.popMatrix(); ++ } else { ++ tmpVec4f_1.set(0.0f, 1.0f, 0.0f); ++ DeferredStateManager.setCurrentSunAngle(tmpVec4f_1); ++ celestialAngle = 270.0f; ++ } ++ ++ if (conf.is_rendering_shadowsSun_clamped > 0) { ++ if (conf.is_rendering_shadowsColored) { ++ DeferredStateManager.forwardCallbackHandler = DeferredStateManager.forwardCallbackSun; ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ } else { ++ DeferredStateManager.forwardCallbackHandler = null; ++ } ++ EaglerDeferredPipeline.instance.beginDrawMainShadowMap(); ++ ++shadowFrameIndex; ++ EaglerDeferredPipeline.instance.beginDrawMainShadowMapLOD(0); ++ GlStateManager.enableCull(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadIdentity(); ++ int shadowMapDist = 16; ++ GlStateManager.ortho(-shadowMapDist, shadowMapDist, -shadowMapDist, shadowMapDist, -64.0f, 64.0f); ++ ++ setupSunCameraTransform(celestialAngle); ++ ++ DeferredStateManager.loadShadowPassViewMatrix(); ++ DeferredStateManager.loadSunShadowMatrixLOD0(); ++ ++ GlStateManager.disableAlpha(); ++ GlStateManager.disableBlend(); ++ ++ GlStateManager.matrixMode(5888); ++ GlStateManager.loadIdentity(); ++ ++ final AxisAlignedBB aabb = matrixToBounds(DeferredStateManager.getSunShadowMatrixLOD0(), d0, d1 + eyeHeight, ++ d2); ++ DeferredStateManager.setShadowMapBounds(aabb); ++ ++ final BetterFrustum shadowLOD0Frustrum = new BetterFrustum(DeferredStateManager.getSunShadowMatrixLOD0()); ++ ++ ChunkCullAdapter shadowCullAdapter = (renderChunk) -> { ++ if (renderChunk.shadowLOD0FrameIndex != shadowFrameIndex) { ++ renderChunk.shadowLOD0FrameIndex = shadowFrameIndex; ++ AxisAlignedBB aabb2 = renderChunk.boundingBox; ++ if (aabb.intersectsWith(aabb2)) { ++ int shadowVisRet = shadowLOD0Frustrum.intersectAab((float) (aabb2.minX - d0), ++ (float) (aabb2.minY - d1 - eyeHeight), (float) (aabb2.minZ - d2), ++ (float) (aabb2.maxX - d0), (float) (aabb2.maxY - d1 - eyeHeight), ++ (float) (aabb2.maxZ - d2)); ++ renderChunk.shadowLOD0InFrustum = shadowVisRet == BetterFrustum.INSIDE ++ ? RenderChunk.ShadowFrustumState.INSIDE ++ : (shadowVisRet == BetterFrustum.INTERSECT ? RenderChunk.ShadowFrustumState.INTERSECT ++ : RenderChunk.ShadowFrustumState.OUTSIDE); ++ } else { ++ renderChunk.shadowLOD0InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE_BB; ++ return true; ++ } ++ } ++ return renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE; ++ }; ++ ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.SOLID, aabb, shadowCullAdapter); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.5F); ++ if (wavingBlocks) { ++ DeferredStateManager.enableDrawWavingBlocks(); ++ enableLightmap(); ++ } ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT_MIPPED, aabb, shadowCullAdapter); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT, aabb, shadowCullAdapter); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ GlStateManager.alphaFunc(516, 0.1F); ++ if (wavingBlocks) { ++ DeferredStateManager.disableDrawWavingBlocks(); ++ disableLightmap(); ++ } ++ ++ mc.renderGlobal.renderShadowLODEntities(entity, partialTicks, (renderChunk) -> { ++ return renderChunk.shadowLOD0FrameIndex == shadowFrameIndex ++ && (renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE ++ || renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE_BB); ++ }, (renderChunk, renderManager, renderEntity) -> { ++ boolean b; ++ if (renderEntity.ignoreFrustumCheck) { ++ return false; ++ } else if (!renderEntity.isInRangeToRender3d(d0, d1, d2)) { ++ return true; ++ } else if (renderChunk.shadowLOD0FrameIndex == shadowFrameIndex ++ && ((b = renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE) ++ || renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.INSIDE)) { ++ return b; ++ } else { ++ AxisAlignedBB aabbEntity = renderEntity.getEntityBoundingBox(); ++ if (aabbEntity.func_181656_b() || aabbEntity.getAverageEdgeLength() == 0.0) { ++ aabbEntity = new AxisAlignedBB(d0 - 2.0, d1 - 2.0, d2 - 2.0, d0 + 2.0, d1 + 2.0, d2 + 2.0); ++ } ++ if (shadowLOD0Frustrum.testAab((float) (aabbEntity.minX - d0), ++ (float) (aabbEntity.minY - d1 - eyeHeight), (float) (aabbEntity.minZ - d2), ++ (float) (aabbEntity.maxX - d0), (float) (aabbEntity.maxY - d1 - eyeHeight), ++ (float) (aabbEntity.maxZ - d2))) { ++ return !renderManager.shouldRender(renderEntity, frustum, d0, d1, d2); ++ } else { ++ return true; ++ } ++ } ++ }); ++ disableLightmap(); ++ ++ if (conf.is_rendering_shadowsColored) { ++ EaglerDeferredPipeline.instance.beginDrawColoredShadows(); ++ List lst = DeferredStateManager.forwardCallbackHandler.renderPassList; ++ for (int i = 0, l = lst.size(); i < l; ++i) { ++ lst.get(i).draw(ShadersRenderPassFuture.PassType.SHADOW); ++ } ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.TRANSLUCENT, aabb, shadowCullAdapter); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ if (conf.is_rendering_realisticWater) { ++ GlStateManager.disableTexture2D(); ++ GlStateManager.color(0.173f, 0.239f, 0.957f, 0.25f); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.REALISTIC_WATER, aabb, ++ shadowCullAdapter); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.enableTexture2D(); ++ } ++ EaglerDeferredPipeline.instance.endDrawColoredShadows(); ++ } ++ disableLightmap(); ++ ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.disableAlpha(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.popMatrix(); ++ ++ if (conf.is_rendering_shadowsSun_clamped > 1) { ++ EaglerDeferredPipeline.instance.beginDrawMainShadowMapLOD(1); ++ if (conf.is_rendering_shadowsColored) { ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ } ++ ++ GlStateManager.enableCull(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadIdentity(); ++ shadowMapDist = 32; ++ GlStateManager.ortho(-shadowMapDist, shadowMapDist, -shadowMapDist, shadowMapDist, -64.0f, 64.0f); ++ ++ setupSunCameraTransform(celestialAngle); ++ ++ DeferredStateManager.loadShadowPassViewMatrix(); ++ DeferredStateManager.loadSunShadowMatrixLOD1(); ++ ++ GlStateManager.disableAlpha(); ++ GlStateManager.disableBlend(); ++ ++ GlStateManager.matrixMode(5888); ++ GlStateManager.loadIdentity(); ++ ++ final AxisAlignedBB aabb2 = matrixToBounds(DeferredStateManager.getSunShadowMatrixLOD1(), d0, ++ d1 + eyeHeight, d2); ++ DeferredStateManager.setShadowMapBounds(aabb2); ++ ++ BetterFrustum shadowLOD1Frustrum = new BetterFrustum(DeferredStateManager.getSunShadowMatrixLOD1()); ++ ++ ChunkCullAdapter shadowCullAdapter2 = (renderChunk) -> { ++ if (renderChunk.shadowLOD1FrameIndex != shadowFrameIndex) { ++ renderChunk.shadowLOD1FrameIndex = shadowFrameIndex; ++ if (renderChunk.shadowLOD0FrameIndex == shadowFrameIndex ++ && renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.INSIDE) { ++ renderChunk.shadowLOD1InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE; ++ return true; ++ } else { ++ AxisAlignedBB aabb3 = renderChunk.boundingBox; ++ if (aabb2.intersectsWith(aabb3)) { ++ int shadowVisRet = shadowLOD1Frustrum.intersectAab((float) (aabb3.minX - d0), ++ (float) (aabb3.minY - d1 - eyeHeight), (float) (aabb3.minZ - d2), ++ (float) (aabb3.maxX - d0), (float) (aabb3.maxY - d1 - eyeHeight), ++ (float) (aabb3.maxZ - d2)); ++ renderChunk.shadowLOD1InFrustum = shadowVisRet == BetterFrustum.INSIDE ++ ? RenderChunk.ShadowFrustumState.INSIDE ++ : (shadowVisRet == BetterFrustum.INTERSECT ++ ? RenderChunk.ShadowFrustumState.INTERSECT ++ : RenderChunk.ShadowFrustumState.OUTSIDE); ++ } else { ++ renderChunk.shadowLOD1InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE_BB; ++ return true; ++ } ++ } ++ } ++ return renderChunk.shadowLOD1InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE; ++ }; ++ ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.SOLID, aabb2, shadowCullAdapter2); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.5F); ++ if (wavingBlocks) { ++ DeferredStateManager.enableDrawWavingBlocks(); ++ enableLightmap(); ++ } ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT_MIPPED, aabb2, shadowCullAdapter2); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT, aabb2, shadowCullAdapter2); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ GlStateManager.alphaFunc(516, 0.1F); ++ if (wavingBlocks) { ++ DeferredStateManager.disableDrawWavingBlocks(); ++ disableLightmap(); ++ } ++ ++ mc.renderGlobal.renderShadowLODEntities(entity, partialTicks, (renderChunk) -> { ++ return renderChunk.shadowLOD1FrameIndex == shadowFrameIndex ++ && (renderChunk.shadowLOD1InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE ++ || renderChunk.shadowLOD1InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE_BB); ++ }, (renderChunk, renderManager, renderEntity) -> { ++ boolean b; ++ if (renderEntity.ignoreFrustumCheck) { ++ return false; ++ } else if (!renderEntity.isInRangeToRender3d(d0, d1, d2)) { ++ return true; ++ } else if (renderChunk.shadowLOD1FrameIndex == shadowFrameIndex ++ && (b = renderChunk.shadowLOD1InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE)) { ++ return b; ++ } else { ++ AxisAlignedBB aabbEntity = renderEntity.getEntityBoundingBox(); ++ if (aabbEntity.func_181656_b() || aabbEntity.getAverageEdgeLength() == 0.0) { ++ aabbEntity = new AxisAlignedBB(d0 - 2.0, d1 - 2.0, d2 - 2.0, d0 + 2.0, d1 + 2.0, d2 + 2.0); ++ } ++ if (shadowLOD1Frustrum.testAab((float) (aabbEntity.minX - d0), ++ (float) (aabbEntity.minY - d1 - eyeHeight), (float) (aabbEntity.minZ - d2), ++ (float) (aabbEntity.maxX - d0), (float) (aabbEntity.maxY - d1 - eyeHeight), ++ (float) (aabbEntity.maxZ - d2))) { ++ return !renderManager.shouldRender(renderEntity, frustum, d0, d1, d2); ++ } else { ++ return true; ++ } ++ } ++ }); ++ disableLightmap(); ++ ++ if (conf.is_rendering_shadowsColored) { ++ EaglerDeferredPipeline.instance.beginDrawColoredShadows(); ++ List lst = DeferredStateManager.forwardCallbackHandler.renderPassList; ++ for (int i = 0, l = lst.size(); i < l; ++i) { ++ lst.get(i).draw(ShadersRenderPassFuture.PassType.SHADOW); ++ } ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.TRANSLUCENT, aabb2, shadowCullAdapter2); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ if (conf.is_rendering_realisticWater) { ++ GlStateManager.disableTexture2D(); ++ GlStateManager.color(0.173f, 0.239f, 0.957f, 0.25f); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.REALISTIC_WATER, aabb2, ++ shadowCullAdapter2); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.enableTexture2D(); ++ } ++ EaglerDeferredPipeline.instance.endDrawColoredShadows(); ++ } ++ disableLightmap(); ++ ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.disableAlpha(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.popMatrix(); ++ ++ if (conf.is_rendering_shadowsSun_clamped > 2) { ++ EaglerDeferredPipeline.instance.beginDrawMainShadowMapLOD(2); ++ ++ GlStateManager.enableCull(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadIdentity(); ++ shadowMapDist = 1 << (conf.is_rendering_shadowsSun_clamped + 3); ++ GlStateManager.ortho(-shadowMapDist, shadowMapDist, -shadowMapDist, shadowMapDist, -64.0f, 64.0f); ++ ++ setupSunCameraTransform(celestialAngle); ++ ++ DeferredStateManager.loadShadowPassViewMatrix(); ++ DeferredStateManager.loadSunShadowMatrixLOD2(); ++ ++ GlStateManager.disableAlpha(); ++ GlStateManager.disableBlend(); ++ ++ GlStateManager.matrixMode(5888); ++ GlStateManager.loadIdentity(); ++ ++ DeferredStateManager.loadPassViewMatrix(); ++ DeferredStateManager.loadPassProjectionMatrix(); ++ ++ AxisAlignedBB aabb3 = matrixToBounds(DeferredStateManager.getSunShadowMatrixLOD2(), d0, ++ d1 + eyeHeight, d2); ++ DeferredStateManager.setShadowMapBounds(aabb3); ++ ++ BetterFrustum shadowLOD2Frustum = new BetterFrustum(DeferredStateManager.getSunShadowMatrixLOD2()); ++ ++ ChunkCullAdapter shadowCullAdapter3 = (renderChunk) -> { ++ if (renderChunk.shadowLOD2FrameIndex != shadowFrameIndex) { ++ renderChunk.shadowLOD2FrameIndex = shadowFrameIndex; ++ if (renderChunk.shadowLOD0FrameIndex == shadowFrameIndex ++ && renderChunk.shadowLOD0InFrustum == RenderChunk.ShadowFrustumState.INSIDE) { ++ renderChunk.shadowLOD2InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE; ++ return true; ++ } else if (renderChunk.shadowLOD1FrameIndex == shadowFrameIndex ++ && renderChunk.shadowLOD1InFrustum == RenderChunk.ShadowFrustumState.INSIDE) { ++ renderChunk.shadowLOD2InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE; ++ return true; ++ } else { ++ AxisAlignedBB aabb4 = renderChunk.boundingBox; ++ if (aabb3.intersectsWith(aabb4)) { ++ int shadowVisRet = shadowLOD2Frustum.intersectAab((float) (aabb4.minX - d0), ++ (float) (aabb4.minY - d1 - eyeHeight), (float) (aabb4.minZ - d2), ++ (float) (aabb4.maxX - d0), (float) (aabb4.maxY - d1 - eyeHeight), ++ (float) (aabb4.maxZ - d2)); ++ renderChunk.shadowLOD2InFrustum = shadowVisRet == BetterFrustum.INSIDE ++ ? RenderChunk.ShadowFrustumState.INSIDE ++ : (shadowVisRet == BetterFrustum.INTERSECT ++ ? RenderChunk.ShadowFrustumState.INTERSECT ++ : RenderChunk.ShadowFrustumState.OUTSIDE); ++ } else { ++ renderChunk.shadowLOD2InFrustum = RenderChunk.ShadowFrustumState.OUTSIDE_BB; ++ return true; ++ } ++ } ++ } ++ return renderChunk.shadowLOD2InFrustum == RenderChunk.ShadowFrustumState.OUTSIDE; ++ }; ++ ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.SOLID, aabb3, shadowCullAdapter3); ++ GlStateManager.enableAlpha(); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT_MIPPED, aabb3, ++ shadowCullAdapter3); ++ mc.renderGlobal.renderBlockLayerShadow(EnumWorldBlockLayer.CUTOUT, aabb3, shadowCullAdapter3); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ disableLightmap(); ++ ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.disableAlpha(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.popMatrix(); ++ } ++ } ++ ++ EaglerDeferredPipeline.instance.endDrawMainShadowMap(); ++ if (conf.is_rendering_shadowsColored) { ++ DeferredStateManager.forwardCallbackHandler.reset(); ++ } ++ } ++ ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ ++ if (conf.is_rendering_dynamicLights && entity != null && mc.gameSettings.thirdPersonView == 0) { ++ if (entity instanceof EntityLivingBase) { ++ DynamicLightManager.setIsRenderingLights(true); ++ ItemStack itemStack = ((EntityLivingBase) entity).getHeldItem(); ++ if (itemStack != null) { ++ float[] emission = EmissiveItems.getItemEmission(itemStack); ++ if (emission != null) { ++ float yaw = entity.prevRotationYaw ++ + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks; ++ yaw *= 0.017453293f; ++ float s = 0.2f; ++ double d02 = d0 + MathHelper.sin(yaw) * s; ++ double d22 = d2 + MathHelper.cos(yaw) * s; ++ float mag = 0.7f; ++ DynamicLightManager.renderDynamicLight("render_view_entity_holding", d02, ++ d1 + entity.getEyeHeight(), d22, emission[0] * mag, emission[1] * mag, ++ emission[2] * mag, false); ++ } ++ } ++ DynamicLightManager.setIsRenderingLights(false); ++ } ++ } ++ ++ mc.mcProfiler.endStartSection("combineGBuffersAndIlluminate"); ++ EaglerDeferredPipeline.instance.combineGBuffersAndIlluminate(); ++ ++ if (conf.is_rendering_useEnvMap) { ++ mc.mcProfiler.endStartSection("envMap"); ++ DeferredStateManager.forwardCallbackHandler = null; ++ EaglerDeferredPipeline.instance.beginDrawEnvMap(); ++ GlStateManager.enableCull(); ++ ++ EaglerDeferredPipeline.instance.beginDrawEnvMapTop(entity.getEyeHeight()); ++ EaglerDeferredPipeline.instance.beginDrawEnvMapSolid(); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.SOLID, (double) partialTicks, 1, entity); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.5F); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.CUTOUT, (double) partialTicks, 1, entity); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.CUTOUT_MIPPED, (double) partialTicks, 1, ++ entity); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ mc.renderGlobal.renderParaboloidTileEntities(entity, partialTicks, 1); ++ GlStateManager.alphaFunc(516, 0.1F); ++ EaglerDeferredPipeline.instance.beginDrawEnvMapTranslucent(); ++ if (conf.is_rendering_realisticWater) { ++ GlStateManager.disableTexture2D(); ++ DeferredStateManager.disableMaterialTexture(); ++ DeferredStateManager.setRoughnessConstant(0.117f); ++ DeferredStateManager.setMetalnessConstant(0.067f); ++ DeferredStateManager.setEmissionConstant(0.0f); ++ GlStateManager.color(0.173f, 0.239f, 0.957f, 0.65f); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.REALISTIC_WATER, (double) partialTicks, ++ 1, entity); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.enableTexture2D(); ++ DeferredStateManager.enableMaterialTexture(); ++ } ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.TRANSLUCENT, (double) partialTicks, 1, ++ entity); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ GlStateManager.disableAlpha(); ++ ++ EaglerDeferredPipeline.instance.beginDrawEnvMapBottom(entity.getEyeHeight()); ++ EaglerDeferredPipeline.instance.beginDrawEnvMapSolid(); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.SOLID, (double) partialTicks, -1, entity); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.5F); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.CUTOUT, (double) partialTicks, -1, entity); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.CUTOUT_MIPPED, (double) partialTicks, -1, ++ entity); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ mc.renderGlobal.renderParaboloidTileEntities(entity, partialTicks, -1); ++ GlStateManager.alphaFunc(516, 0.1F); ++ EaglerDeferredPipeline.instance.beginDrawEnvMapTranslucent(); ++ if (conf.is_rendering_realisticWater) { ++ GlStateManager.disableTexture2D(); ++ DeferredStateManager.disableMaterialTexture(); ++ DeferredStateManager.setRoughnessConstant(0.117f); ++ DeferredStateManager.setMetalnessConstant(0.067f); ++ DeferredStateManager.setEmissionConstant(0.0f); ++ GlStateManager.color(0.173f, 0.239f, 0.957f, 0.65f); ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.REALISTIC_WATER, (double) partialTicks, ++ -1, entity); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.enableTexture2D(); ++ DeferredStateManager.enableMaterialTexture(); ++ } ++ mc.renderGlobal.renderParaboloidBlockLayer(EnumWorldBlockLayer.TRANSLUCENT, (double) partialTicks, -1, ++ entity); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ GlStateManager.disableAlpha(); ++ ++ EaglerDeferredPipeline.instance.endDrawEnvMap(); ++ } ++ ++ if (conf.is_rendering_realisticWater) { ++ mc.mcProfiler.endStartSection("realisticWaterMask"); ++ EaglerDeferredPipeline.instance.beginDrawRealisticWaterMask(); ++ enableLightmap(); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.REALISTIC_WATER, (double) partialTicks, 2, entity); ++ disableLightmap(); ++ EaglerDeferredPipeline.instance.endDrawRealisticWaterMask(); ++ } ++ ++ mc.mcProfiler.endStartSection("setupShaderFog"); ++ ++ int dim = mc.theWorld.provider.getDimensionId(); ++ float ff; ++ if (dim == 0) { ++ ff = (this.fogColor2 + (this.fogColor1 - this.fogColor2) * partialTicks) * 4.8f - 2.8f; ++ if (ff < 0.0f) ++ ff = 0.0f; ++ if (ff > 1.0f) ++ ff = 1.0f; ++ } else { ++ ff = 1.0f; ++ } ++ ++ Block block = ActiveRenderInfo.getBlockAtEntityViewpoint(this.mc.theWorld, entity, partialTicks); ++ if (entity instanceof EntityLivingBase && ((EntityLivingBase) entity).isPotionActive(Potion.blindness)) { ++ float f1 = 5.0F; ++ int i = ((EntityLivingBase) entity).getActivePotionEffect(Potion.blindness).getDuration(); ++ if (i < 20) { ++ f1 = 5.0F + (this.farPlaneDistance - 5.0F) * (1.0F - (float) i / 20.0F); ++ } ++ if (partialTicks == -1) { ++ DeferredStateManager.enableFogLinear(0.0f, f1 * 0.8F, false, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, ++ 1.0f); ++ } else { ++ DeferredStateManager.enableFogLinear(f1 * 0.25F, f1, false, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, ++ 1.0f); ++ } ++ } else if (block.getMaterial() == Material.water) { ++ updateFogColor(partialTicks); // gen vanilla fog color ++ ff *= 0.2f; ++ ff += 0.8f; ++ fogColorRed *= 0.5f; ++ fogColorGreen *= 0.5f; ++ fogColorBlue *= 0.5f; ++ if (entity instanceof EntityLivingBase ++ && ((EntityLivingBase) entity).isPotionActive(Potion.waterBreathing)) { ++ DeferredStateManager.enableFogExp(0.01F, false, fogColorRed, fogColorGreen, fogColorBlue, 1.0f, ++ fogColorRed * ff, fogColorGreen * ff, fogColorBlue * ff, 1.0f); ++ } else { ++ DeferredStateManager.enableFogExp(0.1F - (float) EnchantmentHelper.getRespiration(entity) * 0.03F, ++ false, fogColorRed, fogColorGreen, fogColorBlue, 1.0f, fogColorRed * ff, fogColorGreen * ff, ++ fogColorBlue * ff, 1.0f); ++ } ++ } else if (block.getMaterial() == Material.lava) { ++ updateFogColor(partialTicks); // gen vanilla fog color ++ DeferredStateManager.enableFogExp(2.0F, false, fogColorRed, fogColorGreen, fogColorBlue, 1.0f, fogColorRed, ++ fogColorGreen, fogColorBlue, 1.0f); ++ } else { ++ float ds = 0.0005f; ++ if (mc.gameSettings.renderDistanceChunks < 6) { ++ ds *= 3.0f - mc.gameSettings.renderDistanceChunks * 0.33f; ++ } ++ ds *= 1.5f + mc.theWorld.getRainStrength(partialTicks) * 10.0f ++ + mc.theWorld.getThunderStrength(partialTicks) * 5.0f; ++ ds *= MathHelper.clamp_float(6.0f - DeferredStateManager.getSunHeight() * 17.0f, 1.0f, 2.0f); ++ DeferredStateManager.enableFogExp(ds, true, 1.0f, 1.0f, 1.0f, 1.0f, ff, ff, ff, 1.0f); ++ } ++ ++ EaglerDeferredPipeline.instance.beginDrawHDRTranslucent(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ ++ if (conf.is_rendering_realisticWater) { ++ mc.mcProfiler.endStartSection("realisticWaterSurface"); ++ EaglerDeferredPipeline.instance.beginDrawRealisticWaterSurface(); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.REALISTIC_WATER, (double) partialTicks, 2, entity); ++ EaglerDeferredPipeline.instance.endDrawRealisticWaterSurface(); ++ } ++ ++ mc.mcProfiler.endStartSection("gbufferFog"); ++ EaglerDeferredPipeline.instance.applyGBufferFog(); ++ ++ mc.mcProfiler.endStartSection("translucentEntities"); ++ EaglerDeferredPipeline.instance.beginDrawTranslucentEntities(); ++ ++ TileEntityRendererDispatcher.staticPlayerX = d0; ++ TileEntityRendererDispatcher.staticPlayerY = d1; ++ TileEntityRendererDispatcher.staticPlayerZ = d2; ++ mc.getRenderManager().setRenderPosition(d0, d1, d2); ++ ++ for (int i = 0; i < mc.theWorld.weatherEffects.size(); ++i) { ++ Entity entity1 = (Entity) mc.theWorld.weatherEffects.get(i); ++ if (entity1.isInRangeToRender3d(d0, d1, d2)) { ++ mc.getRenderManager().renderEntitySimple(entity1, partialTicks); ++ } ++ } ++ disableLightmap(); ++ ++ DeferredStateManager.forwardCallbackGBuffer.sort(0.0f, 0.0f, 0.0f); ++ List lst = DeferredStateManager.forwardCallbackGBuffer.renderPassList; ++ for (int i = 0, l = lst.size(); i < l; ++i) { ++ lst.get(i).draw(ShadersRenderPassFuture.PassType.MAIN); ++ } ++ DeferredStateManager.forwardCallbackGBuffer.reset(); ++ ++ EaglerDeferredPipeline.instance.beginDrawTranslucentBlocks(); ++ mc.mcProfiler.endStartSection("translucentBlocks"); ++ mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.TRANSLUCENT, (double) partialTicks, 2, entity); ++ ++ EaglerDeferredPipeline.instance.beginDrawMainGBufferDestroyProgress(); ++ ++ mc.mcProfiler.endStartSection("destroyProgress"); ++ ++ GlStateManager.enableBlend(); ++ GlStateManager.tryBlendFuncSeparate(0, 770, 0, 0); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 0.5f); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); ++ mc.renderGlobal.drawBlockDamageTexture(Tessellator.getInstance(), Tessellator.getInstance().getWorldRenderer(), ++ entity, partialTicks); ++ mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); ++ ++ EaglerDeferredPipeline.instance.endDrawMainGBufferDestroyProgress(); ++ ++ if (mc.effectRenderer.hasParticlesInAlphaLayer()) { ++ mc.mcProfiler.endStartSection("transparentParticles"); ++ GlStateManager.pushMatrix(); ++ mc.effectRenderer.acceleratedParticleRenderer = EaglerDeferredPipeline.instance.forwardEffectRenderer; ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ DeferredStateManager.reportForwardRenderObjectPosition2(0.0f, 0.0f, 0.0f); ++ GlStateManager.enableBlend(); ++ GlStateManager.depthMask(false); ++ mc.effectRenderer.renderParticles(entity, partialTicks, 0); ++ mc.effectRenderer.acceleratedParticleRenderer = EffectRenderer.vanillaAcceleratedParticleRenderer; ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ GlStateManager.enableBlend(); ++ GlStateManager.depthMask(true); ++ } ++ ++ if (conf.is_rendering_useEnvMap) { ++ mc.mcProfiler.endStartSection("glassHighlights"); ++ EaglerDeferredPipeline.instance.beginDrawGlassHighlights(); ++ mc.renderGlobal.renderBlockLayer(EnumWorldBlockLayer.GLASS_HIGHLIGHTS, (double) partialTicks, 2, entity); ++ EaglerDeferredPipeline.instance.endDrawGlassHighlights(); ++ } ++ ++ mc.mcProfiler.endStartSection("saveReprojData"); ++ EaglerDeferredPipeline.instance.saveReprojData(); ++ ++ mc.mcProfiler.endStartSection("rainSnow"); ++ renderRainSnow(partialTicks); ++ ++ GlStateManager.disableBlend(); ++ ++ if (renderHand) { ++ mc.mcProfiler.endStartSection("renderHandOverlay"); ++ EaglerDeferredPipeline.instance.beginDrawHandOverlay(); ++ DeferredStateManager.reportForwardRenderObjectPosition2(0.0f, 0.0f, 0.0f); ++ DeferredStateManager.forwardCallbackHandler = DeferredStateManager.forwardCallbackGBuffer; ++ GlStateManager.matrixMode(5888); ++ GlStateManager.pushMatrix(); ++ GlStateManager.matrixMode(5889); ++ GlStateManager.pushMatrix(); ++ GlStateManager.enableAlpha(); ++ renderHand(partialTicks, 2); ++ DeferredStateManager.forwardCallbackHandler = null; ++ GlStateManager.enableBlend(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ lst = DeferredStateManager.forwardCallbackGBuffer.renderPassList; ++ for (int i = 0, l = lst.size(); i < l; ++i) { ++ lst.get(i).draw(ShadersRenderPassFuture.PassType.MAIN); ++ } ++ GlStateManager.matrixMode(5889); ++ GlStateManager.popMatrix(); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ EaglerDeferredPipeline.instance.endDrawHandOverlay(); ++ GlStateManager.disableBlend(); ++ GlStateManager.disableAlpha(); ++ } ++ ++ mc.mcProfiler.endStartSection("endDrawDeferred"); ++ EaglerDeferredPipeline.instance.endDrawHDRTranslucent(); ++ ++ EaglerDeferredPipeline.instance.endDrawDeferred(); ++ ++ GlStateManager.setActiveTexture(33985); ++ this.mc.getTextureManager().bindTexture(this.locationLightMap); ++ ++ GlStateManager.setActiveTexture(33984); ++ GlStateManager.matrixMode(5890); ++ GlStateManager.loadIdentity(); ++ GlStateManager.matrixMode(5888); ++ ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ GlStateManager.enableDepth(); ++ GlStateManager.depthMask(true); ++ ++ if (!DebugFramebufferView.debugViewShown) { ++ GlStateManager.disableAlpha(); ++ if (isDrawBlockOutline()) { ++ this.mc.mcProfiler.endStartSection("outline"); ++ mc.renderGlobal.drawSelectionBox(mc.thePlayer, this.mc.objectMouseOver, 0, partialTicks); ++ } ++ GlStateManager.enableAlpha(); ++ this.mc.mcProfiler.endStartSection("nameTags"); ++ if (NameTagRenderer.nameTagsCount > 0) { ++ enableLightmap(); ++ Arrays.sort(NameTagRenderer.nameTagsThisFrame, 0, NameTagRenderer.nameTagsCount, (n1, n2) -> { ++ return n1.dst2 < n2.dst2 ? 1 : (n1.dst2 > n2.dst2 ? -1 : 0); ++ }); ++ for (int i = 0; i < NameTagRenderer.nameTagsCount; ++i) { ++ NameTagRenderer n = NameTagRenderer.nameTagsThisFrame[i]; ++ int ii = n.entityIn.getBrightnessForRender(partialTicks); ++ int j = ii % 65536; ++ int k = ii / 65536; ++ OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) j / 1.0F, ++ (float) k / 1.0F); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ if (n.maxDistance == -69) { ++ // calls renderName instead of renderLivingLabel: ++ Render.renderNameAdapter(mc.getRenderManager().getEntityRenderObject(n.entityIn), n.entityIn, ++ n.x, n.y, n.z); ++ } else { ++ mc.getRenderManager().getEntityRenderObject(n.entityIn).renderLivingLabel(n.entityIn, n.str, ++ n.x, n.y, n.z, n.maxDistance); ++ } ++ } ++ NameTagRenderer.nameTagsCount = 0; ++ } ++ disableLightmap(); ++ GlStateManager.disableLighting(); ++ this.mc.mcProfiler.endStartSection("worldBorder"); ++ mc.renderGlobal.renderWorldBorder(entity, partialTicks); ++ } ++ ++ mc.mcProfiler.endSection(); ++ } ++ ++ public boolean renderHeldItemLight(EntityLivingBase entityLiving, float mag) { ++ if (DynamicLightManager.isRenderingLights()) { ++ ItemStack itemStack = entityLiving.getHeldItem(); ++ if (itemStack != null) { ++ float[] emission = EmissiveItems.getItemEmission(itemStack); ++ if (emission != null) { ++ double d0 = entityLiving.prevPosX + (entityLiving.posX - entityLiving.prevPosX) * eagPartialTicks; ++ double d1 = entityLiving.prevPosY + (entityLiving.posY - entityLiving.prevPosY) * eagPartialTicks; ++ double d2 = entityLiving.prevPosZ + (entityLiving.posZ - entityLiving.prevPosZ) * eagPartialTicks; ++ float yaw = entityLiving.prevRotationYaw ++ + (entityLiving.rotationYaw - entityLiving.prevRotationYaw) * eagPartialTicks; ++ yaw *= 0.017453293f; ++ float s = 0.5f; ++ d0 -= MathHelper.sin(yaw) * s; ++ d2 += MathHelper.cos(yaw) * s; ++ mag *= 0.5f; ++ DynamicLightManager.renderDynamicLight("entity_" + entityLiving.getEntityId() + "_holding", d0, ++ d1 + entityLiving.getEyeHeight() * 0.63f, d2, emission[0] * mag, emission[1] * mag, ++ emission[2] * mag, false); ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ public boolean renderItemEntityLight(Entity entity, float mag) { ++ if (DynamicLightManager.isRenderingLights()) { ++ ItemStack itemStack = null; ++ float offsetX = 0.0f; ++ float offsetY = 0.0f; ++ float offsetZ = 0.0f; ++ if (entity instanceof EntityItem) { ++ EntityItem ei = (EntityItem) entity; ++ itemStack = ei.getEntityItem(); ++ offsetY = MathHelper.sin(((float) ei.getAge() + eagPartialTicks) / 10.0F + ei.hoverStart) * 0.1F + 0.3F; ++ } else if (entity instanceof EntityItemFrame) { ++ itemStack = ((EntityItemFrame) entity).getDisplayedItem(); ++ Vec3i facingVec = ((EntityItemFrame) entity).facingDirection.getDirectionVec(); ++ offsetX = facingVec.x * 0.1f; ++ offsetZ = facingVec.z * 0.1f; ++ } ++ if (itemStack != null) { ++ float[] emission = EmissiveItems.getItemEmission(itemStack); ++ if (emission != null) { ++ double d0 = entity.prevPosX + (entity.posX - entity.prevPosX) * eagPartialTicks; ++ double d1 = entity.prevPosY + (entity.posY - entity.prevPosY) * eagPartialTicks; ++ double d2 = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * eagPartialTicks; ++ DynamicLightManager.renderDynamicLight("entity_" + entity.getEntityId() + "_item", d0 + offsetX, ++ d1 + offsetY, d2 + offsetZ, emission[0] * mag, emission[1] * mag, emission[2] * mag, false); ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ private static final Matrix4f matrixToBounds_tmpMat4f_1 = new Matrix4f(); ++ private static final Vector4f matrixToBounds_tmpVec4f_1 = new Vector4f(); ++ private static final Vector4f[] matrixToBounds_tmpVec4f_array = new Vector4f[] { new Vector4f(-1, -1, -1, 1), ++ new Vector4f(-1, -1, 1, 1), new Vector4f(-1, 1, -1, 1), new Vector4f(-1, 1, 1, 1), ++ new Vector4f(1, -1, -1, 1), new Vector4f(1, -1, 1, 1), new Vector4f(1, 1, -1, 1), ++ new Vector4f(1, 1, 1, 1) }; ++ ++ private static AxisAlignedBB matrixToBounds(Matrix4f matrixIn, double x, double y, double z) { ++ Matrix4f.invert(matrixIn, matrixToBounds_tmpMat4f_1); ++ ++ float minX = Integer.MAX_VALUE; ++ float minY = Integer.MAX_VALUE; ++ float minZ = Integer.MAX_VALUE; ++ float maxX = Integer.MIN_VALUE; ++ float maxY = Integer.MIN_VALUE; ++ float maxZ = Integer.MIN_VALUE; ++ Vector4f tmpVec = matrixToBounds_tmpVec4f_1; ++ float vx, vy, vz; ++ for (int i = 0; i < 8; ++i) { ++ Matrix4f.transform(matrixToBounds_tmpMat4f_1, matrixToBounds_tmpVec4f_array[i], tmpVec); ++ vx = tmpVec.x; ++ vy = tmpVec.y; ++ vz = tmpVec.z; ++ if (vx < minX) ++ minX = vx; ++ if (vy < minY) ++ minY = vy; ++ if (vz < minZ) ++ minZ = vz; ++ if (vx > maxX) ++ maxX = vx; ++ if (vy > maxY) ++ maxY = vy; ++ if (vz > maxZ) ++ maxZ = vz; ++ } ++ ++ return new AxisAlignedBB(minX + x, minY + y, minZ + z, maxX + x, maxY + y, maxZ + z); ++ } ++ ++ public static void setupSunCameraTransform(float celestialAngle) { ++ GlStateManager.rotate(celestialAngle + 90.0f, 1.0F, 0.0F, 0.0F); ++ GlStateManager.rotate(-DeferredStateManager.sunAngle, 0.0F, 1.0F, 0.0F); ++ GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/RegionRenderCacheBuilder.edit.java b/patches/minecraft/net/minecraft/client/renderer/RegionRenderCacheBuilder.edit.java index 7f55336..3b74a31 100644 --- a/patches/minecraft/net/minecraft/client/renderer/RegionRenderCacheBuilder.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/RegionRenderCacheBuilder.edit.java @@ -9,4 +9,9 @@ ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +> INSERT 10 : 12 @ 10 + ++ this.worldRenderers[EnumWorldBlockLayer.REALISTIC_WATER.ordinal()] = new WorldRenderer(262145); ++ this.worldRenderers[EnumWorldBlockLayer.GLASS_HIGHLIGHTS.ordinal()] = new WorldRenderer(131072); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/RenderGlobal.edit.java b/patches/minecraft/net/minecraft/client/renderer/RenderGlobal.edit.java index eb8825f..7375e6e 100644 --- a/patches/minecraft/net/minecraft/client/renderer/RenderGlobal.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/RenderGlobal.edit.java @@ -7,12 +7,14 @@ > DELETE 2 @ 2 : 7 -> CHANGE 6 : 8 @ 6 : 7 +> CHANGE 6 : 10 @ 6 : 7 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ import net.lax1dude.eaglercraft.v1_8.HString; +~ import net.lax1dude.eaglercraft.v1_8.Keyboard; +~ -> INSERT 2 : 16 @ 2 +> INSERT 2 : 22 @ 2 + + import com.google.common.collect.Lists; @@ -25,7 +27,13 @@ + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; + import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredConfig; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.SharedPipelineShaders; + import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; + import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; @@ -39,7 +47,15 @@ > DELETE 2 @ 2 : 5 -> DELETE 29 @ 29 : 34 +> INSERT 15 : 16 @ 15 + ++ import net.minecraft.util.ChatComponentText; + +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.util.EnumChatFormatting; + +> DELETE 13 @ 13 : 18 > DELETE 20 @ 20 : 24 @@ -108,21 +124,277 @@ ~ EaglercraftRandom random = new EaglercraftRandom(10842L); -> DELETE 70 @ 70 : 79 +> DELETE 67 @ 67 : 79 -> DELETE 1 @ 1 : 7 +> CHANGE 1 : 5 @ 1 : 5 -> DELETE 28 @ 28 : 32 +~ if (mc.gameSettings.shaders) { +~ if (!EaglerDeferredPipeline.isSupported()) { +~ mc.gameSettings.shaders = false; +~ } + +> INSERT 2 : 6 @ 2 + ++ Blocks.leaves.setGraphicsLevel(mc.gameSettings.shaders || mc.gameSettings.fancyGraphics); ++ Blocks.leaves2.setGraphicsLevel(mc.gameSettings.shaders || mc.gameSettings.fancyGraphics); ++ this.renderDistanceChunks = this.mc.gameSettings.renderDistanceChunks; ++ + +> INSERT 19 : 76 @ 19 + ++ ++ if (mc.gameSettings.shaders) { ++ EaglerDeferredConfig dfc = mc.gameSettings.deferredShaderConf; ++ dfc.updateConfig(); ++ if (theWorld.provider.getHasNoSky()) { ++ dfc.is_rendering_shadowsSun_clamped = 0; ++ dfc.is_rendering_lightShafts = false; ++ } else { ++ int maxDist = renderDistanceChunks << 4; ++ int ss = dfc.is_rendering_shadowsSun; ++ while (ss > 1 && (1 << (ss + 3)) > maxDist) { ++ --ss; ++ } ++ dfc.is_rendering_shadowsSun_clamped = ss; ++ dfc.is_rendering_lightShafts = dfc.lightShafts; ++ } ++ boolean flag = false; ++ if (EaglerDeferredPipeline.instance == null) { ++ EaglerDeferredPipeline.instance = new EaglerDeferredPipeline(mc); ++ flag = true; ++ } ++ try { ++ SharedPipelineShaders.init(); ++ EaglerDeferredPipeline.instance.rebuild(dfc); ++ EaglerDeferredPipeline.isSuspended = false; ++ } catch (Throwable ex) { ++ logger.error("Could not enable shaders!"); ++ logger.error(ex); ++ EaglerDeferredPipeline.isSuspended = true; ++ } ++ if (flag && !EaglerDeferredPipeline.isSuspended) { ++ ChatComponentText shaderF4Msg = new ChatComponentText("[EaglercraftX]"); ++ shaderF4Msg.getChatStyle().setColor(EnumChatFormatting.GOLD); ++ ChatComponentText shaderF4Msg2 = new ChatComponentText( ++ " Press " + Keyboard.getKeyName(mc.gameSettings.keyBindFunction.getKeyCode()) ++ + "+4 to access the shader debug menu"); ++ shaderF4Msg2.getChatStyle().setColor(EnumChatFormatting.AQUA); ++ shaderF4Msg.appendSibling(shaderF4Msg2); ++ mc.ingameGUI.getChatGUI().printChatMessage(shaderF4Msg); ++ } ++ } ++ ++ mc.gameSettings.shadersAODisable = mc.gameSettings.shaders ++ && mc.gameSettings.deferredShaderConf.is_rendering_ssao; ++ ++ if (!mc.gameSettings.shaders || EaglerDeferredPipeline.isSuspended) { ++ try { ++ if (EaglerDeferredPipeline.instance != null) { ++ EaglerDeferredPipeline.instance.destroy(); ++ EaglerDeferredPipeline.instance = null; ++ } ++ } catch (Throwable ex) { ++ logger.error("Could not safely disable shaders!"); ++ logger.error(ex); ++ } ++ SharedPipelineShaders.free(); ++ } + +> DELETE 9 @ 9 : 13 > DELETE 1 @ 1 : 2 -> DELETE 41 @ 41 : 78 +> INSERT 6 : 7 @ 6 -> CHANGE 53 : 54 @ 53 : 54 ++ boolean light = DynamicLightManager.isRenderingLights(); + +> CHANGE 27 : 36 @ 27 : 54 + +~ if (!DeferredStateManager.isDeferredRenderer()) { +~ for (int i = 0; i < this.theWorld.weatherEffects.size(); ++i) { +~ Entity entity1 = (Entity) this.theWorld.weatherEffects.get(i); +~ ++this.countEntitiesRendered; +~ if (entity1.isInRangeToRender3d(d0, d1, d2)) { +~ if (light) { +~ entity1.renderDynamicLightsEagler(partialTicks, true); +~ } +~ this.renderManager.renderEntitySimple(entity1, partialTicks); + +> DELETE 2 @ 2 : 16 + +> INSERT 24 : 27 @ 24 + ++ if (light) { ++ entity2.renderDynamicLightsEagler(partialTicks, flag2); ++ } + +> CHANGE 31 : 32 @ 31 : 32 ~ for (TileEntity tileentity2 : (List) list1) { -> CHANGE 52 : 53 @ 52 : 53 +> INSERT 41 : 200 @ 41 + ++ public static interface EntityChunkCullAdapter { ++ boolean shouldCull(RenderChunk renderChunk); ++ } ++ ++ public static interface EntityObjectCullAdapter { ++ boolean shouldCull(RenderChunk renderChunk, RenderManager renderManager, Entity entity); ++ } ++ ++ public void renderShadowLODEntities(Entity renderViewEntity, float partialTicks, ++ EntityChunkCullAdapter entityChunkCull, EntityObjectCullAdapter entityObjectCull) { // TODO ++ if (renderEntitiesStartupCounter <= 0) { ++ theWorld.theProfiler.startSection("shadow_entity_prepare"); ++ ++ TileEntityRendererDispatcher.instance.cacheActiveRenderInfo(theWorld, mc.getTextureManager(), ++ mc.fontRendererObj, renderViewEntity, partialTicks); ++ renderManager.cacheActiveRenderInfo(theWorld, mc.fontRendererObj, renderViewEntity, mc.pointedEntity, ++ mc.gameSettings, partialTicks); ++ ++ double d3 = renderViewEntity.lastTickPosX ++ + (renderViewEntity.posX - renderViewEntity.lastTickPosX) * (double) partialTicks; ++ double d4 = renderViewEntity.lastTickPosY ++ + (renderViewEntity.posY - renderViewEntity.lastTickPosY) * (double) partialTicks; ++ double d5 = renderViewEntity.lastTickPosZ ++ + (renderViewEntity.posZ - renderViewEntity.lastTickPosZ) * (double) partialTicks; ++ TileEntityRendererDispatcher.staticPlayerX = d3; ++ TileEntityRendererDispatcher.staticPlayerY = d4; ++ TileEntityRendererDispatcher.staticPlayerZ = d5; ++ renderManager.setRenderPosition(d3, d4, d5); ++ ++ this.theWorld.theProfiler.endStartSection("shadow_entities"); ++ for (RenderGlobal.ContainerLocalRenderInformation containerlocalrenderinformation : this.renderInfos) { ++ RenderChunk currentRenderChunk = containerlocalrenderinformation.renderChunk; ++ ++ if (!entityChunkCull.shouldCull(currentRenderChunk)) { ++ Chunk chunk = this.theWorld ++ .getChunkFromBlockCoords(containerlocalrenderinformation.renderChunk.getPosition()); ++ ClassInheritanceMultiMap classinheritancemultimap = chunk ++ .getEntityLists()[containerlocalrenderinformation.renderChunk.getPosition().getY() / 16]; ++ if (!classinheritancemultimap.isEmpty()) { ++ Iterator iterator = classinheritancemultimap.iterator(); ++ while (iterator.hasNext()) { ++ Entity entity2 = iterator.next(); ++ if (!entityObjectCull.shouldCull(currentRenderChunk, renderManager, entity2) ++ || entity2.riddenByEntity == this.mc.thePlayer) { ++ if (entity2.posY < 0.0D || entity2.posY >= 256.0D ++ || this.theWorld.isBlockLoaded(new BlockPos(entity2))) { ++ ++this.countEntitiesRendered; ++ this.renderManager.renderEntitySimple(entity2, partialTicks); ++ mc.entityRenderer.disableLightmap(); ++ GlStateManager.disableShaderBlendAdd(); ++ GlStateManager.disableBlend(); ++ GlStateManager.depthMask(true); ++ } ++ } ++ ++ } ++ ++ // TODO: why? ++ // if (!flag2 && entity2 instanceof EntityWitherSkull) { ++ // this.mc.getRenderManager().renderWitherSkull(entity2, partialTicks); ++ // } ++ } ++ ++ List tileEntities = currentRenderChunk.compiledChunk.getTileEntities(); ++ for (int i = 0, l = tileEntities.size(); i < l; ++i) { ++ TileEntityRendererDispatcher.instance.renderTileEntity(tileEntities.get(i), partialTicks, -1); ++ mc.entityRenderer.disableLightmap(); ++ GlStateManager.disableShaderBlendAdd(); ++ GlStateManager.disableBlend(); ++ GlStateManager.depthMask(true); ++ } ++ } ++ } ++ ++ synchronized (this.field_181024_n) { ++ for (TileEntity tileentity : this.field_181024_n) { ++ TileEntityRendererDispatcher.instance.renderTileEntity(tileentity, partialTicks, -1); ++ mc.entityRenderer.disableLightmap(); ++ GlStateManager.disableShaderBlendAdd(); ++ GlStateManager.disableBlend(); ++ GlStateManager.depthMask(true); ++ } ++ } ++ theWorld.theProfiler.endSection(); ++ } ++ } ++ ++ public void renderParaboloidTileEntities(Entity renderViewEntity, float partialTicks, int up) { ++ if (renderEntitiesStartupCounter <= 0) { ++ theWorld.theProfiler.startSection("paraboloid_entity_prepare"); ++ ++ TileEntityRendererDispatcher.instance.cacheActiveRenderInfo(theWorld, mc.getTextureManager(), ++ mc.fontRendererObj, renderViewEntity, partialTicks); ++ renderManager.cacheActiveRenderInfo(theWorld, mc.fontRendererObj, renderViewEntity, mc.pointedEntity, ++ mc.gameSettings, partialTicks); ++ ++ double d3 = renderViewEntity.lastTickPosX ++ + (renderViewEntity.posX - renderViewEntity.lastTickPosX) * (double) partialTicks; ++ double d4 = renderViewEntity.lastTickPosY ++ + (renderViewEntity.posY - renderViewEntity.lastTickPosY) * (double) partialTicks; ++ double d5 = renderViewEntity.lastTickPosZ ++ + (renderViewEntity.posZ - renderViewEntity.lastTickPosZ) * (double) partialTicks; ++ TileEntityRendererDispatcher.staticPlayerX = d3; ++ TileEntityRendererDispatcher.staticPlayerY = d4; ++ TileEntityRendererDispatcher.staticPlayerZ = d5; ++ renderManager.setRenderPosition(d3, d4, d5); ++ ++ double rad = 8.0; ++ ++ int minX = (int) (d3 - rad); ++ int minY = (int) d4; ++ if (up == -1) { ++ minY -= rad; ++ } ++ int minZ = (int) (d5 - rad); ++ ++ int maxX = (int) (d3 + rad); ++ int maxY = (int) d4; ++ if (up == 1) { ++ maxY += rad; ++ } ++ int maxZ = (int) (d5 + rad); ++ ++ BlockPos tmp = new BlockPos(0, 0, 0); ++ minX = MathHelper.floor_double(minX / 16.0) * 16; ++ minY = MathHelper.floor_double(minY / 16.0) * 16; ++ minZ = MathHelper.floor_double(minZ / 16.0) * 16; ++ maxX = MathHelper.floor_double(maxX / 16.0) * 16; ++ maxY = MathHelper.floor_double(maxY / 16.0) * 16; ++ maxZ = MathHelper.floor_double(maxZ / 16.0) * 16; ++ ++ this.theWorld.theProfiler.endStartSection("paraboloid_entities"); ++ for (int cx = minX; cx <= maxX; cx += 16) { ++ for (int cz = minZ; cz <= maxZ; cz += 16) { ++ for (int cy = minY; cy <= maxY; cy += 16) { ++ tmp.x = cx; ++ tmp.y = cy; ++ tmp.z = cz; ++ RenderChunk ch = viewFrustum.getRenderChunk(tmp); ++ CompiledChunk cch; ++ if (ch != null && (cch = ch.compiledChunk) != null) { ++ List tileEntities = cch.getTileEntities(); ++ for (int i = 0, l = tileEntities.size(); i < l; ++i) { ++ mc.entityRenderer.enableLightmap(); ++ TileEntityRendererDispatcher.instance.renderTileEntity(tileEntities.get(i), ++ partialTicks, -1); ++ GlStateManager.disableShaderBlendAdd(); ++ GlStateManager.disableBlend(); ++ GlStateManager.depthMask(true); ++ } ++ } ++ } ++ } ++ } ++ theWorld.theProfiler.endSection(); ++ mc.entityRenderer.disableLightmap(); ++ } ++ } ++ + +> CHANGE 11 : 12 @ 11 : 12 ~ return HString.format("C: %d/%d %sD: %d, %s", @@ -156,11 +428,111 @@ + ((ClippingHelperImpl) this.debugFixedClippingHelper).destroy(); -> DELETE 94 @ 94 : 104 +> INSERT 92 : 129 @ 92 -> DELETE 1 @ 1 : 21 ++ public static interface ChunkCullAdapter { ++ boolean shouldCull(RenderChunk chunk); ++ } ++ ++ public int renderBlockLayerShadow(EnumWorldBlockLayer blockLayerIn, AxisAlignedBB boundingBox, ++ ChunkCullAdapter cullAdapter) { ++ int i = 0; ++ BlockPos tmp = new BlockPos(0, 0, 0); ++ int minXChunk = MathHelper.floor_double(boundingBox.minX / 16.0) * 16; ++ int minYChunk = MathHelper.floor_double(boundingBox.minY / 16.0) * 16; ++ int minZChunk = MathHelper.floor_double(boundingBox.minZ / 16.0) * 16; ++ int maxXChunk = MathHelper.floor_double(boundingBox.maxX / 16.0) * 16; ++ int maxYChunk = MathHelper.floor_double(boundingBox.maxY / 16.0) * 16; ++ int maxZChunk = MathHelper.floor_double(boundingBox.maxZ / 16.0) * 16; ++ for (int cx = minXChunk; cx <= maxXChunk; cx += 16) { ++ for (int cz = minZChunk; cz <= maxZChunk; cz += 16) { ++ for (int cy = minYChunk; cy <= maxYChunk; cy += 16) { ++ tmp.x = cx; ++ tmp.y = cy; ++ tmp.z = cz; ++ RenderChunk ch = viewFrustum.getRenderChunk(tmp); ++ CompiledChunk cch; ++ if (ch != null && (cch = ch.getCompiledChunk()) != null && !cch.isLayerEmpty(blockLayerIn) ++ && !cullAdapter.shouldCull(ch)) { ++ this.renderContainer.addRenderChunk(ch, blockLayerIn); ++ ++i; ++ } ++ } ++ } ++ } ++ if (i > 0) { ++ this.mc.mcProfiler.endStartSection("render_shadow_" + blockLayerIn); ++ this.renderContainer.renderChunkLayer(blockLayerIn); ++ } ++ return i; ++ } ++ -> CHANGE 93 : 94 @ 93 : 103 +> CHANGE 2 : 16 @ 2 : 10 + +~ this.renderContainer.renderChunkLayer(blockLayerIn); +~ this.mc.entityRenderer.disableLightmap(); +~ } +~ +~ public int renderParaboloidBlockLayer(EnumWorldBlockLayer blockLayerIn, double partialTicks, int up, +~ Entity entityIn) { +~ double rad = 8.0; +~ +~ int minX = (int) (entityIn.posX - rad); +~ int minY = (int) entityIn.posY; +~ if (up == -1) { +~ minY -= rad * 0.75; +~ } else { +~ minY += 1.0; + +> INSERT 1 : 2 @ 1 + ++ int minZ = (int) (entityIn.posZ - rad); + +> CHANGE 1 : 31 @ 1 : 18 + +~ int maxX = (int) (entityIn.posX + rad); +~ int maxY = (int) entityIn.posY; +~ if (up == 1) { +~ maxY += rad; +~ } else { +~ maxY += 2.0; +~ } +~ int maxZ = (int) (entityIn.posZ + rad); +~ +~ BlockPos tmp = new BlockPos(0, 0, 0); +~ minX = MathHelper.floor_double(minX / 16.0) * 16; +~ minY = MathHelper.floor_double(minY / 16.0) * 16; +~ minZ = MathHelper.floor_double(minZ / 16.0) * 16; +~ maxX = MathHelper.floor_double(maxX / 16.0) * 16; +~ maxY = MathHelper.floor_double(maxY / 16.0) * 16; +~ maxZ = MathHelper.floor_double(maxZ / 16.0) * 16; +~ +~ int i = 0; +~ for (int cx = minX; cx <= maxX; cx += 16) { +~ for (int cz = minZ; cz <= maxZ; cz += 16) { +~ for (int cy = minY; cy <= maxY; cy += 16) { +~ tmp.x = cx; +~ tmp.y = cy; +~ tmp.z = cz; +~ RenderChunk ch = viewFrustum.getRenderChunk(tmp); +~ CompiledChunk cch; +~ if (ch != null && (cch = ch.getCompiledChunk()) != null && !cch.isLayerEmpty(blockLayerIn)) { +~ this.renderContainer.addRenderChunk(ch, blockLayerIn); +~ ++i; +~ } + +> CHANGE 3 : 10 @ 3 : 5 + +~ if (i > 0) { +~ this.mc.mcProfiler.endStartSection("render_paraboloid_" + up + "_" + blockLayerIn); +~ this.mc.entityRenderer.enableLightmap(); +~ this.renderContainer.renderChunkLayer(blockLayerIn); +~ this.mc.entityRenderer.disableLightmap(); +~ } +~ return i; + +> CHANGE 92 : 93 @ 92 : 102 ~ GlStateManager.callList(this.glSkyList); @@ -182,11 +554,21 @@ > DELETE 17 @ 17 : 18 -> CHANGE 175 : 176 @ 175 : 176 +> CHANGE 155 : 157 @ 155 : 156 + +~ worldRendererIn.begin(7, DeferredStateManager.isDeferredRenderer() ? VertexFormat.BLOCK_SHADERS +~ : DefaultVertexFormats.BLOCK); + +> CHANGE 19 : 20 @ 19 : 20 ~ EaglerTextureAtlasSprite textureatlassprite = this.destroyBlockIcons[i]; -> CHANGE 21 : 22 @ 21 : 22 +> CHANGE 17 : 19 @ 17 : 18 + +~ if (partialTicks == 0 && movingObjectPositionIn != null +~ && movingObjectPositionIn.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) { + +> CHANGE 3 : 4 @ 3 : 4 ~ EaglercraftGPU.glLineWidth(2.0F); diff --git a/patches/minecraft/net/minecraft/client/renderer/RenderHelper.edit.java b/patches/minecraft/net/minecraft/client/renderer/RenderHelper.edit.java index 19df23f..bd76dda 100644 --- a/patches/minecraft/net/minecraft/client/renderer/RenderHelper.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/RenderHelper.edit.java @@ -5,25 +5,42 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 5 @ 2 : 5 +> CHANGE 2 : 6 @ 2 : 5 ~ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 1 @ 1 : 2 -> CHANGE 8 : 10 @ 8 : 10 +> CHANGE 7 : 13 @ 7 : 11 -~ GlStateManager.disableMCLight(0); -~ GlStateManager.disableMCLight(1); +~ if (!DeferredStateManager.isInDeferredPass()) { +~ GlStateManager.disableLighting(); +~ GlStateManager.disableMCLight(0); +~ GlStateManager.disableMCLight(1); +~ GlStateManager.disableColorMaterial(); +~ } -> CHANGE 5 : 8 @ 5 : 7 +> CHANGE 3 : 10 @ 3 : 21 -~ GlStateManager.enableMCLight(0, 0.6f, LIGHT0_POS.xCoord, LIGHT0_POS.yCoord, LIGHT0_POS.zCoord, 0.0D); -~ GlStateManager.enableMCLight(1, 0.6f, LIGHT1_POS.xCoord, LIGHT1_POS.yCoord, LIGHT1_POS.zCoord, 0.0D); -~ GlStateManager.setMCLightAmbient(0.4f, 0.4f, 0.4f); +~ if (!DeferredStateManager.isInDeferredPass()) { +~ GlStateManager.enableLighting(); +~ GlStateManager.enableMCLight(0, 0.6f, LIGHT0_POS.xCoord, LIGHT0_POS.yCoord, LIGHT0_POS.zCoord, 0.0D); +~ GlStateManager.enableMCLight(1, 0.6f, LIGHT1_POS.xCoord, LIGHT1_POS.yCoord, LIGHT1_POS.zCoord, 0.0D); +~ GlStateManager.setMCLightAmbient(0.4f, 0.4f, 0.4f); +~ GlStateManager.enableColorMaterial(); +~ } -> DELETE 1 @ 1 : 15 +> CHANGE 15 : 22 @ 15 : 20 + +~ if (!DeferredStateManager.isInDeferredPass()) { +~ GlStateManager.pushMatrix(); +~ GlStateManager.rotate(-30.0F, 0.0F, 1.0F, 0.0F); +~ GlStateManager.rotate(165.0F, 1.0F, 0.0F, 0.0F); +~ enableStandardItemLighting(); +~ GlStateManager.popMatrix(); +~ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/RenderList.edit.java b/patches/minecraft/net/minecraft/client/renderer/RenderList.edit.java index 5e72b91..15575bb 100644 --- a/patches/minecraft/net/minecraft/client/renderer/RenderList.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/RenderList.edit.java @@ -12,8 +12,9 @@ > DELETE 3 @ 3 : 4 -> CHANGE 8 : 9 @ 8 : 9 +> CHANGE 7 : 9 @ 7 : 9 +~ this.preRenderChunk(renderchunk, enumworldblocklayer); ~ EaglercraftGPU.glCallList( > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/block/model/BakedQuad.edit.java b/patches/minecraft/net/minecraft/client/renderer/block/model/BakedQuad.edit.java new file mode 100644 index 0000000..5571495 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/renderer/block/model/BakedQuad.edit.java @@ -0,0 +1,33 @@ + +# Eagler Context Redacted Diff +# Copyright (c) 2023 lax1dude. All rights reserved. + +# Version: 1.0 +# Author: lax1dude + +> INSERT 6 : 7 @ 6 + ++ protected final int[] vertexDataWithNormals; + +> INSERT 5 : 6 @ 5 + ++ this.vertexDataWithNormals = null; + +> INSERT 4 : 11 @ 4 + ++ public BakedQuad(int[] vertexDataIn, int[] vertexDataWithNormalsIn, int tintIndexIn, EnumFacing faceIn) { ++ this.vertexData = vertexDataIn; ++ this.vertexDataWithNormals = vertexDataWithNormalsIn; ++ this.tintIndex = tintIndexIn; ++ this.face = faceIn; ++ } ++ + +> INSERT 4 : 8 @ 4 + ++ public int[] getVertexDataWithNormals() { ++ return this.vertexDataWithNormals; ++ } ++ + +> EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/block/model/BreakingFour.edit.java b/patches/minecraft/net/minecraft/client/renderer/block/model/BreakingFour.edit.java index 82b9385..521b0a9 100644 --- a/patches/minecraft/net/minecraft/client/renderer/block/model/BreakingFour.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/block/model/BreakingFour.edit.java @@ -7,17 +7,30 @@ > DELETE 3 @ 3 : 6 -> INSERT 1 : 3 @ 1 +> INSERT 1 : 4 @ 1 + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; + > CHANGE 1 : 2 @ 1 : 2 ~ private final EaglerTextureAtlasSprite texture; -> CHANGE 1 : 2 @ 1 : 2 +> CHANGE 1 : 5 @ 1 : 4 ~ public BreakingFour(BakedQuad parBakedQuad, EaglerTextureAtlasSprite textureIn) { +~ super(Arrays.copyOf(parBakedQuad.getVertexData(), parBakedQuad.getVertexData().length), +~ Arrays.copyOf(parBakedQuad.getVertexDataWithNormals(), parBakedQuad.getVertexDataWithNormals().length), +~ parBakedQuad.tintIndex, parBakedQuad.face); + +> INSERT 46 : 52 @ 46 + ++ if (this.vertexDataWithNormals != null) { ++ int i2 = 8 * parInt1; ++ this.vertexDataWithNormals[i2 + 4] = this.vertexData[i + 4]; ++ this.vertexDataWithNormals[i2 + 4 + 1] = this.vertexData[i + 4 + 1]; ++ ++ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/block/model/FaceBakery.edit.java b/patches/minecraft/net/minecraft/client/renderer/block/model/FaceBakery.edit.java index 250c0aa..efc3d08 100644 --- a/patches/minecraft/net/minecraft/client/renderer/block/model/FaceBakery.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/block/model/FaceBakery.edit.java @@ -5,9 +5,10 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 6 @ 2 +> INSERT 2 : 7 @ 2 + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.VertexMarkerState; + import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; + import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; + import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; @@ -16,31 +17,133 @@ > DELETE 4 @ 4 : 7 -> CHANGE 5 : 8 @ 5 : 8 +> CHANGE 5 : 11 @ 5 : 8 +~ private int stride = 7; +~ ~ public BakedQuad makeBakedQuad(Vector3f posFrom, Vector3f posTo, BlockPartFace face, ~ EaglerTextureAtlasSprite sprite, EnumFacing facing, ModelRotation modelRotationIn, ~ BlockPartRotation partRotation, boolean uvLocked, boolean shade) { +~ stride = 7; -> CHANGE 14 : 15 @ 14 : 15 +> CHANGE 1 : 4 @ 1 : 3 + +~ modelRotationIn, partRotation, uvLocked, shade, null); +~ Vector3f calcNormal = getNormalFromVertexData(aint); +~ EnumFacing enumfacing = getFacingFromVertexData(calcNormal); + +> CHANGE 8 : 21 @ 8 : 9 + +~ stride = 8; +~ int[] aint2 = this.makeQuadVertexData(face, sprite, facing, this.getPositionsDiv16(posFrom, posTo), +~ modelRotationIn, partRotation, uvLocked, shade, calcNormal); +~ if (uvLocked) { +~ this.func_178409_a(aint2, enumfacing, face.blockFaceUV, sprite); +~ } +~ +~ if (partRotation == null) { +~ this.func_178408_a(aint2, enumfacing); +~ } +~ stride = 7; +~ +~ return new BakedQuad(aint, aint2, face.tintIndex, enumfacing); + +> CHANGE 2 : 3 @ 2 : 3 ~ private int[] makeQuadVertexData(BlockPartFace partFace, EaglerTextureAtlasSprite sprite, EnumFacing facing, -> CHANGE 47 : 49 @ 47 : 49 +> CHANGE 1 : 3 @ 1 : 3 + +~ boolean parFlag2, Vector3f calcNormal) { +~ int[] aint = new int[stride * 4]; + +> CHANGE 3 : 4 @ 3 : 4 + +~ parFlag2, calcNormal); + +> CHANGE 40 : 42 @ 40 : 42 ~ float[] sprite, EaglerTextureAtlasSprite modelRotationIn, ModelRotation partRotation, -~ BlockPartRotation uvLocked, boolean shade, boolean parFlag2) { +~ BlockPartRotation uvLocked, boolean shade, boolean parFlag2, Vector3f calcNormal) { -> CHANGE 13 : 14 @ 13 : 14 +> CHANGE 1 : 2 @ 1 : 2 -~ EaglerTextureAtlasSprite sprite, BlockFaceUV faceUV) { +~ int i = (parFlag2 && stride != 8) ? this.getFaceShadeColor(enumfacing) : -1; -> CHANGE 113 : 114 @ 113 : 114 +> CHANGE 7 : 9 @ 7 : 8 + +~ this.storeVertexData(faceData, j, vertexIndex, vector3f, i, modelRotationIn, partFace.blockFaceUV, enumfacing, +~ calcNormal); + +> CHANGE 3 : 5 @ 3 : 8 + +~ EaglerTextureAtlasSprite sprite, BlockFaceUV faceUV, EnumFacing facing, Vector3f calcNormal) { +~ int i = storeIndex * stride; + +> INSERT 4 : 27 @ 4 + ++ if (stride == 8) { ++ faceData[i] = Float.floatToRawIntBits(position.x * VertexMarkerState.localCoordDeriveHackX); ++ faceData[i + 1] = Float.floatToRawIntBits(position.y * VertexMarkerState.localCoordDeriveHackY); ++ faceData[i + 2] = Float.floatToRawIntBits(position.z * VertexMarkerState.localCoordDeriveHackZ); ++ if (calcNormal != null) { ++ int x = (byte) ((int) (calcNormal.x * 127.0F)) & 255; ++ int y = (byte) ((int) (calcNormal.y * 127.0F)) & 255; ++ int z = (byte) ((int) (calcNormal.z * 127.0F)) & 255; ++ int l = x | y << 8 | z << 16 | ((byte) VertexMarkerState.markId) << 24; ++ faceData[i + 6] = l; ++ } else { ++ Vec3i vec = facing.getDirectionVec(); ++ int x = (byte) ((int) (vec.x * 127.0F)) & 255; ++ int y = (byte) ((int) (vec.y * 127.0F)) & 255; ++ int z = (byte) ((int) (vec.z * 127.0F)) & 255; ++ int l = x | y << 8 | z << 16 | ((byte) VertexMarkerState.markId) << 24; ++ faceData[i + 6] = l; ++ } ++ } else { ++ faceData[i] = Float.floatToRawIntBits(position.x); ++ faceData[i + 1] = Float.floatToRawIntBits(position.y); ++ faceData[i + 2] = Float.floatToRawIntBits(position.z); ++ } + +> CHANGE 66 : 67 @ 66 : 67 + +~ public static Vector3f getNormalFromVertexData(int[] faceData) { + +> INSERT 17 : 21 @ 17 + ++ return vector3f5; ++ } ++ ++ public static EnumFacing getFacingFromVertexData(Vector3f normal) { + +> CHANGE 6 : 7 @ 6 : 7 + +~ float f2 = Vector3f.dot(normal, vector3f6); + +> CHANGE 14 : 15 @ 14 : 15 ~ EaglerTextureAtlasSprite parTextureAtlasSprite) { -> CHANGE 76 : 77 @ 76 : 77 +> CHANGE 18 : 19 @ 18 : 19 + +~ int j = stride * i; + +> CHANGE 31 : 32 @ 31 : 32 + +~ int j1 = stride * i1; + +> CHANGE 10 : 11 @ 10 : 11 + +~ int l = stride * k; + +> CHANGE 14 : 16 @ 14 : 16 ~ EaglerTextureAtlasSprite parTextureAtlasSprite) { +~ int i = stride * facing; + +> CHANGE 43 : 44 @ 43 : 44 + +~ int j = parBlockFaceUV.func_178345_c(facing) * stride; > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkCompileTaskGenerator.edit.java b/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkCompileTaskGenerator.edit.java index 09a38eb..4245b71 100644 --- a/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkCompileTaskGenerator.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkCompileTaskGenerator.edit.java @@ -7,11 +7,12 @@ > DELETE 2 @ 2 : 3 -> CHANGE 1 : 4 @ 1 : 2 +> CHANGE 1 : 5 @ 1 : 2 ~ ~ import com.google.common.collect.Lists; ~ +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > CHANGE 1 : 2 @ 1 : 3 @@ -57,11 +58,17 @@ > DELETE 2 @ 2 : 6 -> INSERT 8 : 16 @ 8 +> INSERT 8 : 22 @ 8 + public boolean canExecuteYet() { + if (this.type == ChunkCompileTaskGenerator.Type.RESORT_TRANSPARENCY) { -+ return !this.renderChunk.getCompiledChunk().isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT); ++ CompiledChunk ch = this.renderChunk.getCompiledChunk(); ++ if (DeferredStateManager.isRenderingRealisticWater()) { ++ return !ch.isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT) ++ || !ch.isLayerEmpty(EnumWorldBlockLayer.REALISTIC_WATER); ++ } else { ++ return !ch.isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT); ++ } + } else { + return true; + } diff --git a/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkRenderWorker.edit.java b/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkRenderWorker.edit.java index cb26267..a5c7f4e 100644 --- a/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkRenderWorker.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/chunk/ChunkRenderWorker.edit.java @@ -5,11 +5,12 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 5 @ 2 : 9 +> CHANGE 2 : 6 @ 2 : 9 ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; ~ import net.lax1dude.eaglercraft.v1_8.minecraft.ChunkUpdateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 2 @ 2 : 6 @@ -66,11 +67,7 @@ + generator.setStatus(ChunkCompileTaskGenerator.Status.UPLOADING); + -> CHANGE 1 : 4 @ 1 : 2 - -~ if (compiledchunk == null) { -~ System.out.println(chunkcompiletaskgenerator$type); -~ } +> DELETE 1 @ 1 : 2 > CHANGE 2 : 4 @ 2 : 4 @@ -87,9 +84,15 @@ ~ this.chunkRenderDispatcher.uploadChunk( -> CHANGE 2 : 5 @ 2 : 3 +> CHANGE 2 : 11 @ 2 : 3 ~ generator.getRenderChunk(), compiledchunk); +~ if (DeferredStateManager.isRenderingRealisticWater()) { +~ this.chunkRenderDispatcher.uploadChunk( +~ EnumWorldBlockLayer.REALISTIC_WATER, generator.getRegionRenderCacheBuilder() +~ .getWorldRendererByLayer(EnumWorldBlockLayer.REALISTIC_WATER), +~ generator.getRenderChunk(), compiledchunk); +~ } ~ generator.getRenderChunk().setCompiledChunk(compiledchunk); ~ generator.setStatus(ChunkCompileTaskGenerator.Status.DONE); diff --git a/patches/minecraft/net/minecraft/client/renderer/chunk/CompiledChunk.edit.java b/patches/minecraft/net/minecraft/client/renderer/chunk/CompiledChunk.edit.java index 45b4b46..b9c6084 100644 --- a/patches/minecraft/net/minecraft/client/renderer/chunk/CompiledChunk.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/chunk/CompiledChunk.edit.java @@ -18,4 +18,19 @@ ~ return true; +> INSERT 8 : 9 @ 8 + ++ private WorldRenderer.State stateWater; + +> INSERT 45 : 53 @ 45 + ++ ++ public WorldRenderer.State getStateRealisticWater() { ++ return this.stateWater; ++ } ++ ++ public void setStateRealisticWater(WorldRenderer.State stateIn) { ++ this.stateWater = stateIn; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/chunk/RenderChunk.edit.java b/patches/minecraft/net/minecraft/client/renderer/chunk/RenderChunk.edit.java index 190dc30..4427ce7 100644 --- a/patches/minecraft/net/minecraft/client/renderer/chunk/RenderChunk.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/chunk/RenderChunk.edit.java @@ -9,14 +9,16 @@ ~ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; -> CHANGE 3 : 9 @ 3 : 4 +> CHANGE 3 : 11 @ 3 : 4 ~ ~ import com.google.common.collect.Maps; ~ import com.google.common.collect.Sets; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 4 @ 4 : 7 @@ -24,17 +26,45 @@ > DELETE 3 @ 3 : 4 -> DELETE 13 @ 13 : 15 +> INSERT 8 : 12 @ 8 + ++ public static enum ShadowFrustumState { ++ OUTSIDE, OUTSIDE_BB, INTERSECT, INSIDE ++ } ++ + +> DELETE 5 @ 5 : 7 > CHANGE 3 : 4 @ 3 : 5 ~ private final float[] modelviewMatrix = new float[16]; -> DELETE 13 @ 13 : 19 +> INSERT 3 : 9 @ 3 + ++ public int shadowLOD0FrameIndex = -1; ++ public int shadowLOD1FrameIndex = -1; ++ public int shadowLOD2FrameIndex = -1; ++ public ShadowFrustumState shadowLOD0InFrustum = ShadowFrustumState.OUTSIDE; ++ public ShadowFrustumState shadowLOD1InFrustum = ShadowFrustumState.OUTSIDE; ++ public ShadowFrustumState shadowLOD2InFrustum = ShadowFrustumState.OUTSIDE; + +> DELETE 10 @ 10 : 16 > DELETE 11 @ 11 : 15 -> DELETE 31 @ 31 : 32 +> INSERT 24 : 33 @ 24 + ++ if (DeferredStateManager.isRenderingRealisticWater() && compiledchunk.getStateRealisticWater() != null ++ && !compiledchunk.isLayerEmpty(EnumWorldBlockLayer.REALISTIC_WATER)) { ++ this.preRenderBlocks(generator.getRegionRenderCacheBuilder() ++ .getWorldRendererByLayer(EnumWorldBlockLayer.REALISTIC_WATER), this.position); ++ generator.getRegionRenderCacheBuilder().getWorldRendererByLayer(EnumWorldBlockLayer.REALISTIC_WATER) ++ .setVertexState(compiledchunk.getStateRealisticWater()); ++ this.postRenderBlocks(EnumWorldBlockLayer.REALISTIC_WATER, x, y, z, generator.getRegionRenderCacheBuilder() ++ .getWorldRendererByLayer(EnumWorldBlockLayer.REALISTIC_WATER), compiledchunk); ++ } + +> DELETE 7 @ 7 : 8 > CHANGE 2 : 4 @ 2 : 11 @@ -56,7 +86,23 @@ ~ TileEntity tileentity = regionrendercache.getTileEntity(blockpos$mutableblockpos); -> DELETE 38 @ 38 : 39 +> INSERT 21 : 34 @ 21 + ++ ++ if (block.eaglerShadersShouldRenderGlassHighlights()) { ++ enumworldblocklayer1 = EnumWorldBlockLayer.GLASS_HIGHLIGHTS; ++ worldrenderer = generator.getRegionRenderCacheBuilder() ++ .getWorldRendererByLayerId(enumworldblocklayer1.ordinal()); ++ if (!compiledchunk.isLayerStarted(enumworldblocklayer1)) { ++ compiledchunk.setLayerStarted(enumworldblocklayer1); ++ this.preRenderBlocks(worldrenderer, blockpos); ++ } ++ ++ aboolean[enumworldblocklayer1.ordinal()] |= blockrendererdispatcher.renderBlock(iblockstate, ++ blockpos$mutableblockpos, regionrendercache, worldrenderer); ++ } + +> DELETE 17 @ 17 : 18 > CHANGE 1 : 8 @ 1 : 12 @@ -92,7 +138,25 @@ ~ this.compileTask.setCompiledChunk(this.compiledChunk); ~ return this.compileTask; -> CHANGE 37 : 38 @ 37 : 45 +> CHANGE 3 : 5 @ 3 : 4 + +~ worldRendererIn.begin(7, +~ DeferredStateManager.isDeferredRenderer() ? VertexFormat.BLOCK_SHADERS : DefaultVertexFormats.BLOCK); + +> CHANGE 5 : 7 @ 5 : 6 + +~ if ((layer == EnumWorldBlockLayer.TRANSLUCENT || layer == EnumWorldBlockLayer.REALISTIC_WATER) +~ && !compiledChunkIn.isLayerEmpty(layer)) { + +> CHANGE 1 : 6 @ 1 : 2 + +~ if (layer == EnumWorldBlockLayer.REALISTIC_WATER) { +~ compiledChunkIn.setStateRealisticWater(worldRendererIn.func_181672_a()); +~ } else { +~ compiledChunkIn.setState(worldRendererIn.func_181672_a()); +~ } + +> CHANGE 25 : 26 @ 25 : 33 ~ this.compiledChunk = compiledChunkIn; diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/Render.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/Render.edit.java index 5de8ca3..0238503 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/Render.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/Render.edit.java @@ -5,12 +5,14 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 6 @ 2 +> INSERT 2 : 8 @ 2 + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; + import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer; > DELETE 3 @ 3 : 4 @@ -20,7 +22,20 @@ > DELETE 10 @ 10 : 11 -> CHANGE 61 : 63 @ 61 : 63 +> INSERT 12 : 15 @ 12 + ++ if (DeferredStateManager.isEnableShadowRender()) { ++ return true; ++ } + +> INSERT 21 : 25 @ 21 + ++ public static void renderNameAdapter(Render r, Entity e, double x, double y, double z) { ++ r.renderName(e, x, y, z); ++ } ++ + +> CHANGE 28 : 30 @ 28 : 30 ~ EaglerTextureAtlasSprite textureatlassprite = texturemap.getAtlasSprite("minecraft:blocks/fire_layer_0"); ~ EaglerTextureAtlasSprite textureatlassprite1 = texturemap.getAtlasSprite("minecraft:blocks/fire_layer_1"); @@ -29,7 +44,23 @@ ~ EaglerTextureAtlasSprite textureatlassprite2 = i % 2 == 0 ? textureatlassprite : textureatlassprite1; -> CHANGE 179 : 180 @ 179 : 180 +> CHANGE 150 : 152 @ 150 : 152 + +~ if (!DeferredStateManager.isInDeferredPass() && this.renderManager.options.field_181151_V +~ && this.shadowSize > 0.0F && !entityIn.isInvisible() && this.renderManager.isRenderShadow()) { + +> CHANGE 19 : 20 @ 19 : 20 + +~ public void renderLivingLabel(T entityIn, String str, double x, double y, double z, int maxDistance) { + +> INSERT 2 : 6 @ 2 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ NameTagRenderer.renderNameTag(entityIn, str, x, y, z, maxDistance); ++ return; ++ } + +> CHANGE 5 : 6 @ 5 : 6 ~ EaglercraftGPU.glNormal3f(0.0F, 1.0F, 0.0F); diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderBlaze.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderBlaze.edit.java index bfaa719..bfed53c 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderBlaze.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderBlaze.edit.java @@ -5,6 +5,26 @@ # Version: 1.0 # Author: lax1dude -> DELETE 3 @ 3 : 5 +> INSERT 2 : 3 @ 2 + ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; + +> DELETE 1 @ 1 : 3 + +> INSERT 13 : 26 @ 13 + ++ ++ public void doRender(EntityBlaze entityliving, double d0, double d1, double d2, float f, float f1) { ++ if (DeferredStateManager.isInDeferredPass()) { ++ DeferredStateManager.setEmissionConstant(1.0f); ++ try { ++ super.doRender(entityliving, d0, d1, d2, f, f1); ++ } finally { ++ DeferredStateManager.setEmissionConstant(0.0f); ++ } ++ } else { ++ super.doRender(entityliving, d0, d1, d2, f, f1); ++ } ++ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderCreeper.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderCreeper.edit.java index d74d1ab..8d76cba 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderCreeper.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderCreeper.edit.java @@ -5,10 +5,31 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 5 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; > DELETE 1 @ 1 : 4 +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; + +> INSERT 34 : 46 @ 34 + ++ public void doRender(EntityCreeper entitycreeper, double d0, double d1, double d2, float f, float f1) { ++ float ff = entitycreeper.getCreeperFlashIntensity(f); ++ if ((int) (ff * 10.0F) % 2 != 0) { ++ DeferredStateManager.setEmissionConstant(1.0f); ++ } ++ try { ++ super.doRender(entitycreeper, d0, d1, d2, f, f1); ++ } finally { ++ DeferredStateManager.setEmissionConstant(0.0f); ++ } ++ } ++ + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderDragon.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderDragon.edit.java index f5dcfcd..9090c10 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderDragon.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderDragon.edit.java @@ -5,13 +5,41 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 5 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 1 @ 1 : 2 > DELETE 2 @ 2 : 5 +> INSERT 43 : 67 @ 43 + ++ if (DeferredStateManager.isDeferredRenderer()) { ++ if (entitydragon.deathTicks > 0) { ++ float f6 = (float) entitydragon.deathTicks / 200.0F; ++ GlStateManager.depthFunc(515); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, f6); ++ this.bindTexture(enderDragonExplodingTextures); ++ this.mainModel.render(entitydragon, f, f1, f2, f3, f4, f5); ++ GlStateManager.alphaFunc(516, 0.1F); ++ GlStateManager.depthFunc(514); ++ } ++ if (entitydragon.hurtTime > 0) { ++ GlStateManager.enableShaderBlendAdd(); ++ GlStateManager.setShaderBlendSrc(0.5f, 0.5f, 0.5f, 1.0f); ++ GlStateManager.setShaderBlendAdd(1.0f, 0.0f, 0.0f, 0.0f); ++ } ++ this.bindEntityTexture(entitydragon); ++ this.mainModel.render(entitydragon, f, f1, f2, f3, f4, f5); ++ GlStateManager.depthFunc(515); ++ if (entitydragon.hurtTime > 0) { ++ GlStateManager.disableShaderBlendAdd(); ++ } ++ return; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderEnderman.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderEnderman.edit.java index ac1f754..639f204 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderEnderman.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderEnderman.edit.java @@ -5,10 +5,9 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 4 @ 2 : 3 +> CHANGE 2 : 3 @ 2 : 3 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -~ > DELETE 2 @ 2 : 4 diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderEntityItem.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderEntityItem.edit.java index 506847e..f476d97 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderEntityItem.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderEntityItem.edit.java @@ -5,11 +5,13 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 5 @ 2 : 4 +> CHANGE 2 : 7 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.minecraft.client.Minecraft; > DELETE 1 @ 1 : 4 @@ -22,4 +24,21 @@ ~ float f6 = 0.0F * (float) (i - 1) * 0.5F; ~ float f4 = 0.0F * (float) (i - 1) * 0.5F; +> INSERT 25 : 27 @ 25 + ++ boolean emissive = entityitem.eaglerEmissiveFlag; ++ entityitem.eaglerEmissiveFlag = false; + +> INSERT 8 : 11 @ 8 + ++ if (emissive) { ++ DeferredStateManager.setEmissionConstant(1.0f); ++ } + +> INSERT 43 : 46 @ 43 + ++ if (emissive) { ++ DeferredStateManager.setEmissionConstant(0.0f); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderFallingBlock.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderFallingBlock.edit.java index 26922b4..4f31eca 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderFallingBlock.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderFallingBlock.edit.java @@ -5,13 +5,20 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 6 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 4 @ 4 : 5 > DELETE 1 @ 1 : 4 +> CHANGE 28 : 30 @ 28 : 29 + +~ worldrenderer.begin(7, DeferredStateManager.isDeferredRenderer() ? VertexFormat.BLOCK_SHADERS +~ : DefaultVertexFormats.BLOCK); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderItem.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderItem.edit.java index 91195fa..82af36d 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderItem.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderItem.edit.java @@ -5,14 +5,130 @@ # Version: 1.0 # Author: lax1dude -> INSERT 4 : 7 @ 4 +> INSERT 4 : 12 @ 4 + + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture.PassType; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; > DELETE 21 @ 21 : 22 > DELETE 3 @ 3 : 4 +> INSERT 21 : 22 @ 21 + ++ import net.minecraft.item.ItemBlock; + +> INSERT 5 : 6 @ 5 + ++ import net.minecraft.util.EnumWorldBlockLayer; + +> INSERT 63 : 67 @ 63 + ++ public static float renderPosX = 0.0f; ++ public static float renderPosY = 0.0f; ++ public static float renderPosZ = 0.0f; ++ + +> CHANGE 12 : 82 @ 12 : 15 + +~ if (DeferredStateManager.isInDeferredPass() && isTransparentItem(stack)) { +~ if (DeferredStateManager.forwardCallbackHandler != null) { +~ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); +~ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); +~ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(renderPosX, +~ renderPosY, renderPosZ, EaglerDeferredPipeline.instance.getPartialTicks()) { +~ @Override +~ public void draw(PassType pass) { +~ if (pass == PassType.MAIN) { +~ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); +~ } +~ EntityRenderer.enableLightmapStatic(); +~ GlStateManager.pushMatrix(); +~ GlStateManager.loadMatrix(mat); +~ GlStateManager.texCoords2DDirect(1, lx, ly); +~ Minecraft.getMinecraft().getTextureManager() +~ .bindTexture(TextureMap.locationBlocksTexture); +~ RenderItem.this.renderModel(model, stack); +~ if (pass != PassType.SHADOW && stack.hasEffect()) { +~ GlStateManager.color(1.5F, 0.5F, 1.5F, 1.0F); +~ DeferredStateManager.setDefaultMaterialConstants(); +~ DeferredStateManager.setRoughnessConstant(0.05f); +~ DeferredStateManager.setMetalnessConstant(0.01f); +~ GlStateManager.blendFunc(768, 1); +~ renderEffect(model); +~ DeferredStateManager.setHDRTranslucentPassBlendFunc(); +~ } +~ GlStateManager.popMatrix(); +~ EntityRenderer.disableLightmapStatic(); +~ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); +~ } +~ }); +~ } +~ } else { +~ this.renderModel(model, stack); +~ if (stack.hasEffect()) { +~ if (DeferredStateManager.isInDeferredPass()) { +~ if (DeferredStateManager.forwardCallbackHandler != null +~ && !DeferredStateManager.isEnableShadowRender()) { +~ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); +~ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); +~ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(renderPosX, +~ renderPosY, renderPosZ, EaglerDeferredPipeline.instance.getPartialTicks()) { +~ @Override +~ public void draw(PassType pass) { +~ if (pass == PassType.MAIN) { +~ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); +~ } +~ EntityRenderer.enableLightmapStatic(); +~ GlStateManager.color(1.5F, 0.5F, 1.5F, 1.0F); +~ DeferredStateManager.setDefaultMaterialConstants(); +~ DeferredStateManager.setRoughnessConstant(0.05f); +~ DeferredStateManager.setMetalnessConstant(0.01f); +~ GlStateManager.pushMatrix(); +~ GlStateManager.loadMatrix(mat); +~ GlStateManager.texCoords2DDirect(1, lx, ly); +~ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE); +~ renderEffect(model); +~ DeferredStateManager.setHDRTranslucentPassBlendFunc(); +~ GlStateManager.popMatrix(); +~ EntityRenderer.disableLightmapStatic(); +~ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); +~ } +~ }); +~ } +~ } else { +~ GlStateManager.blendFunc(768, 1); +~ this.renderEffect(model); +~ } +~ } + +> INSERT 7 : 13 @ 7 + ++ private static boolean isTransparentItem(ItemStack stack) { ++ Item itm = stack.getItem(); ++ return itm instanceof ItemBlock ++ && ((ItemBlock) itm).getBlock().getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT; ++ } ++ + +> DELETE 4 @ 4 : 5 + +> INSERT 123 : 124 @ 123 + ++ boolean flag = DeferredStateManager.isEnableShadowRender(); + +> CHANGE 1 : 2 @ 1 : 2 + +~ GlStateManager.cullFace(flag ? GL_BACK : GL_FRONT); + +> CHANGE 3 : 4 @ 3 : 4 + +~ GlStateManager.cullFace(flag ? GL_FRONT : GL_BACK); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderLightningBolt.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderLightningBolt.edit.java index d728bf5..899b054 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderLightningBolt.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderLightningBolt.edit.java @@ -5,16 +5,46 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 6 @ 2 : 4 +> CHANGE 2 : 9 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 4 -> CHANGE 21 : 22 @ 21 : 22 +> INSERT 11 : 33 @ 11 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ GlStateManager.disableExtensionPipeline(); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.tryBlendFuncSeparate(768, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.disableCull(); ++ float bright = 0.04f; ++ GlStateManager.color(6.0f * bright, 6.25f * bright, 7.0f * bright, 1.0f); ++ doRender0(entitylightningbolt, d0, d1, d2, var8, var9); ++ GlStateManager.enableCull(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ GlStateManager.enableExtensionPipeline(); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ return; ++ } ++ GlStateManager.enableBlend(); ++ GlStateManager.blendFunc(770, 1); ++ doRender0(entitylightningbolt, d0, d1, d2, var8, var9); ++ GlStateManager.disableBlend(); ++ } ++ ++ private void doRender0(EntityLightningBolt entitylightningbolt, double d0, double d1, double d2, float var8, ++ float var9) { + +> DELETE 4 @ 4 : 6 + +> CHANGE 4 : 5 @ 4 : 5 ~ EaglercraftRandom random = new EaglercraftRandom(entitylightningbolt.boltVertex); @@ -22,4 +52,6 @@ ~ EaglercraftRandom random1 = new EaglercraftRandom(entitylightningbolt.boltVertex); +> DELETE 73 @ 73 : 74 + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderManager.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderManager.edit.java index 8405db1..24b4e4e 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderManager.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderManager.edit.java @@ -7,7 +7,7 @@ > DELETE 2 @ 2 : 3 -> INSERT 1 : 7 @ 1 +> INSERT 1 : 8 @ 1 + + import com.google.common.collect.Maps; @@ -15,6 +15,7 @@ + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 16 @ 16 : 18 @@ -35,4 +36,50 @@ ~ public Render getEntityRenderObject(Entity entityIn) { +> INSERT 85 : 86 @ 85 + ++ DeferredStateManager.setEmissionConstant(1.0f); + +> CHANGE 7 : 13 @ 7 : 9 + +~ try { +~ return this.doRenderEntity(entity, d0 - this.renderPosX, d1 - this.renderPosY, d2 - this.renderPosZ, f, +~ partialTicks, parFlag); +~ } finally { +~ DeferredStateManager.setEmissionConstant(0.0f); +~ } + +> INSERT 2 : 13 @ 2 + ++ public static void setupLightmapCoords(Entity entity, float partialTicks) { ++ int i = entity.getBrightnessForRender(partialTicks); ++ if (entity.isBurning()) { ++ DeferredStateManager.setEmissionConstant(1.0f); ++ i = 15728880; ++ } ++ int j = i % 65536; ++ int k = i / 65536; ++ OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) j / 1.0F, (float) k / 1.0F); ++ } ++ + +> CHANGE 18 : 23 @ 18 : 19 + +~ try { +~ return this.doRenderEntity(entityIn, x, y, z, entityYaw, partialTicks, false); +~ } finally { +~ DeferredStateManager.setEmissionConstant(0.0f); +~ } + +> INSERT 14 : 17 @ 14 + ++ RenderItem.renderPosX = (float) x; ++ RenderItem.renderPosY = (float) y + entity.height * 0.5f; ++ RenderItem.renderPosZ = (float) z; + +> CHANGE 14 : 16 @ 14 : 15 + +~ if (this.debugBoundingBox && !entity.isInvisible() && !parFlag +~ && !DeferredStateManager.isDeferredRenderer()) { + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderPlayer.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderPlayer.edit.java index e9e6ee6..a9e1d97 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderPlayer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderPlayer.edit.java @@ -80,4 +80,8 @@ ~ ((ModelPlayer) modelplayer).renderLeftArm(); ~ } +> CHANGE 2 : 3 @ 2 : 3 + +~ public void renderLivingAt(AbstractClientPlayer abstractclientplayer, double d0, double d1, double d2) { + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderSlime.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderSlime.edit.java index d74d1ab..2e1a53f 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderSlime.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderSlime.edit.java @@ -11,4 +11,8 @@ > DELETE 1 @ 1 : 4 +> CHANGE 5 : 6 @ 5 : 6 + +~ public static final ResourceLocation slimeTextures = new ResourceLocation("textures/entity/slime/slime.png"); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RenderTNTPrimed.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RenderTNTPrimed.edit.java index a58b534..742b3a6 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RenderTNTPrimed.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RenderTNTPrimed.edit.java @@ -5,10 +5,36 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 4 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 2 @ 2 : 5 +> INSERT 28 : 37 @ 28 + ++ boolean light = entitytntprimed.fuse / 5 % 2 == 0; ++ boolean deferred = DeferredStateManager.isInDeferredPass(); ++ if (light && deferred) { ++ DeferredStateManager.setEmissionConstant(1.0f); ++ DeferredStateManager.disableMaterialTexture(); ++ GlStateManager.enableShaderBlendAdd(); ++ GlStateManager.setShaderBlendSrc(0.0f, 0.0f, 0.0f, 0.0f); ++ GlStateManager.setShaderBlendAdd(1.0f, 1.0f, 1.0f, 1.0f); ++ } + +> CHANGE 2 : 3 @ 2 : 3 + +~ if (light && !deferred) { + +> INSERT 18 : 24 @ 18 + ++ if (light && deferred) { ++ DeferredStateManager.setEmissionConstant(0.0f); ++ DeferredStateManager.enableMaterialTexture(); ++ GlStateManager.disableShaderBlendAdd(); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/RendererLivingEntity.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/RendererLivingEntity.edit.java index b8d1518..330b778 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/RendererLivingEntity.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/RendererLivingEntity.edit.java @@ -9,7 +9,7 @@ ~ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; -> INSERT 1 : 10 @ 1 +> INSERT 1 : 15 @ 1 + + import com.google.common.collect.Lists; @@ -20,8 +20,18 @@ + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; -> DELETE 5 @ 5 : 7 +> INSERT 4 : 6 @ 4 + ++ import net.minecraft.client.model.ModelBiped; ++ import net.minecraft.client.renderer.EntityRenderer; + +> DELETE 1 @ 1 : 3 > DELETE 1 @ 1 : 4 @@ -31,7 +41,84 @@ ~ return this.layerRenderers.add((LayerRenderer) layer); -> CHANGE 194 : 201 @ 194 : 250 +> DELETE 115 @ 115 : 116 + +> CHANGE 36 : 42 @ 36 : 37 + +~ protected void renderModel(T entitylivingbase, float f, float f1, float f2, float f3, float f4, float f5) { // f8, +~ // f7, +~ // f10, +~ // f4, +~ // f9, +~ // 0.0625 + +> INSERT 6 : 65 @ 6 + ++ if (flag1 && DeferredStateManager.isDeferredRenderer()) { ++ if (!DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entitylivingbase, ++ EaglerDeferredPipeline.instance.getPartialTicks()) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ EntityRenderer.enableLightmapStatic(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.05f); ++ DeferredStateManager.setMetalnessConstant(0.2f); ++ DeferredStateManager.setEmissionConstant(0.5f); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.texCoords2DDirect(1, lx, ly); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ GlStateManager.enableAlpha(); ++ GlStateManager.alphaFunc(516, 0.003921569F); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 0.15F); ++ RendererLivingEntity.this.bindEntityTexture(entitylivingbase); ++ RendererLivingEntity.this.mainModel.swingProgress = RendererLivingEntity.this ++ .getSwingProgress(entitylivingbase, f1); ++ RendererLivingEntity.this.mainModel.isRiding = entitylivingbase.isRiding(); ++ RendererLivingEntity.this.mainModel.isChild = entitylivingbase.isChild(); ++ if (RendererLivingEntity.this.mainModel instanceof ModelBiped) { ++ if ((entitylivingbase instanceof EntityPlayer) ++ && ((EntityPlayer) entitylivingbase).isSpectator()) { ++ ((ModelBiped) RendererLivingEntity.this.mainModel).setInvisible(false); ++ ((ModelBiped) RendererLivingEntity.this.mainModel).bipedHead.showModel = true; ++ ((ModelBiped) RendererLivingEntity.this.mainModel).bipedHeadwear.showModel = true; ++ } else { ++ ((ModelBiped) RendererLivingEntity.this.mainModel).setInvisible(true); ++ } ++ } ++ RendererLivingEntity.this.mainModel.setLivingAnimations(entitylivingbase, f, f1, f1); ++ RendererLivingEntity.this.mainModel.setRotationAngles(f, f1, f2, f3, f4, f5, ++ entitylivingbase); ++ RendererLivingEntity.this.mainModel.render(entitylivingbase, f, f1, f2, f3, f4, f5); ++ if (RendererLivingEntity.this.mainModel instanceof ModelBiped) { ++ if ((entitylivingbase instanceof EntityPlayer) ++ && ((EntityPlayer) entitylivingbase).isSpectator()) { ++ ((ModelBiped) RendererLivingEntity.this.mainModel).setInvisible(true); ++ } ++ } ++ GlStateManager.alphaFunc(516, 0.1F); ++ GlStateManager.popMatrix(); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.disableAlpha(); ++ } ++ }); ++ } ++ return; ++ } + +> CHANGE 25 : 26 @ 25 : 26 + +~ public boolean setBrightness(T entitylivingbaseIn, float partialTicks, boolean combineTextures) { + +> CHANGE 9 : 16 @ 9 : 65 ~ GlStateManager.enableShaderBlendAdd(); ~ float f1 = 1.0F - (float) (i >> 24 & 255) / 255.0F; @@ -41,11 +128,23 @@ ~ GlStateManager.setShaderBlendSrc(f1, f1, f1, 1.0F); ~ GlStateManager.setShaderBlendAdd(f2 * f1 + 0.4F, f3 * f1, f4 * f1, 0.0f); -> CHANGE 5 : 6 @ 5 : 42 +> CHANGE 4 : 6 @ 4 : 42 +~ public void unsetBrightness() { ~ GlStateManager.disableShaderBlendAdd(); -> CHANGE 73 : 74 @ 73 : 74 +> CHANGE 2 : 3 @ 2 : 3 + +~ public void renderLivingAt(T entityLivingBaseIn, double x, double y, double z) { + +> INSERT 66 : 70 @ 66 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ NameTagRenderer.renderNameTag(entitylivingbase, null, d0, d1, d2, -69); ++ return; ++ } + +> CHANGE 4 : 5 @ 4 : 5 ~ EaglercraftGPU.glNormal3f(0.0F, 1.0F, 0.0F); diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerArmorBase.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerArmorBase.edit.java index 21608a4..beca21a 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerArmorBase.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerArmorBase.edit.java @@ -7,15 +7,21 @@ > DELETE 2 @ 2 : 3 -> INSERT 1 : 6 @ 1 +> INSERT 1 : 10 @ 1 + + import com.google.common.collect.Maps; + + import net.lax1dude.eaglercraft.v1_8.HString; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; -> DELETE 1 @ 1 : 2 +> CHANGE 1 : 2 @ 1 : 2 + +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 2 @@ -23,11 +29,93 @@ ~ this.func_177179_a((T) modelbase, parInt1); -> CHANGE 19 : 20 @ 19 : 20 +> INSERT 2 : 3 @ 2 ++ DeferredStateManager.setDefaultMaterialConstants(); + +> INSERT 1 : 18 @ 1 + ++ case CHAIN: ++ case IRON: ++ DeferredStateManager.setRoughnessConstant(0.123f); ++ DeferredStateManager.setMetalnessConstant(0.902f); ++ break; ++ case GOLD: ++ DeferredStateManager.setRoughnessConstant(0.108f); ++ DeferredStateManager.setMetalnessConstant(0.907f); ++ break; ++ case DIAMOND: ++ DeferredStateManager.setRoughnessConstant(0.078f); ++ DeferredStateManager.setMetalnessConstant(0.588f); ++ break; ++ default: ++ break; ++ } ++ switch (itemarmor.getArmorMaterial()) { + +> INSERT 14 : 15 @ 14 + ++ DeferredStateManager.setDefaultMaterialConstants(); + +> CHANGE 2 : 41 @ 2 : 3 + +~ if (DeferredStateManager.isInDeferredPass()) { +~ if (!DeferredStateManager.isEnableShadowRender() +~ && DeferredStateManager.forwardCallbackHandler != null) { +~ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); +~ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); +~ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture( +~ entitylivingbaseIn, EaglerDeferredPipeline.instance.getPartialTicks()) { +~ @Override +~ public void draw(PassType pass) { +~ if (pass == PassType.MAIN) { +~ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); +~ } +~ EntityRenderer.enableLightmapStatic(); +~ float f = 0.55f; +~ GlStateManager.color(1.5F * f, 0.5F * f, 1.5F * f, 1.0F); +~ DeferredStateManager.setDefaultMaterialConstants(); +~ DeferredStateManager.setRoughnessConstant(0.05f); +~ DeferredStateManager.setMetalnessConstant(0.01f); +~ GlStateManager.pushMatrix(); +~ GlStateManager.loadMatrix(mat); +~ GlStateManager.texCoords2DDirect(1, lx, ly); +~ GlStateManager.enableBlend(); +~ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE); +~ modelbase.setModelAttributes(LayerArmorBase.this.renderer.getMainModel()); +~ modelbase.setLivingAnimations(entitylivingbaseIn, armorSlot, parFloat2, parFloat3); +~ LayerArmorBase.this.func_177179_a((T) modelbase, parInt1); +~ LayerArmorBase.this.func_177183_a(entitylivingbaseIn, (T) modelbase, armorSlot, +~ parFloat2, parFloat3, parFloat4, parFloat5, parFloat6, parFloat7); +~ DeferredStateManager.setHDRTranslucentPassBlendFunc(); +~ GlStateManager.enableBlend(); +~ GlStateManager.popMatrix(); +~ EntityRenderer.disableLightmapStatic(); +~ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); +~ } +~ }); +~ } +~ break; +~ } ~ this.func_177183_a(entitylivingbaseIn, (T) modelbase, armorSlot, parFloat2, parFloat3, parFloat4, -> CHANGE 58 : 59 @ 58 : 59 +> CHANGE 27 : 31 @ 27 : 28 + +~ boolean d = !DeferredStateManager.isInDeferredPass(); +~ if (d) { +~ GlStateManager.color(f1, f1, f1, 1.0F); +~ } + +> DELETE 3 @ 3 : 4 + +> CHANGE 1 : 5 @ 1 : 2 + +~ if (d) { +~ GlStateManager.blendFunc(768, 1); +~ GlStateManager.color(0.5F * f2, 0.25F * f2, 0.8F * f2, 1.0F); +~ } + +> CHANGE 24 : 25 @ 24 : 25 ~ String s = HString.format("textures/models/armor/%s_layer_%d%s.png", diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerCreeperCharge.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerCreeperCharge.edit.java index ce20507..970ee9f 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerCreeperCharge.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerCreeperCharge.edit.java @@ -5,12 +5,85 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 6 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; -> DELETE 1 @ 1 : 2 +> CHANGE 1 : 2 @ 1 : 2 -> DELETE 1 @ 1 : 2 +~ import net.minecraft.client.renderer.EntityRenderer; + +> CHANGE 1 : 2 @ 1 : 2 + +~ import net.minecraft.client.renderer.entity.RendererLivingEntity; + +> INSERT 16 : 67 @ 16 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (DeferredStateManager.forwardCallbackHandler != null ++ && !DeferredStateManager.isEnableShadowRender()) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entitycreeper) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ boolean flag = entitycreeper.isInvisible(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.1f); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.color(0.5F, 0.5F, 0.5F, 1.0F); ++ if (flag) { ++ GlStateManager.depthMask(false); ++ } ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.disableCull(); ++ GlStateManager.matrixMode(5890); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadIdentity(); ++ float f7 = (float) entitycreeper.ticksExisted + f2; ++ GlStateManager.translate(f7 * 0.01F, f7 * 0.01F, 0.0F); ++ GlStateManager.matrixMode(5888); ++ LayerCreeperCharge.this.creeperRenderer.bindTexture(LIGHTNING_TEXTURE); ++ LayerCreeperCharge.this.creeperModel ++ .setModelAttributes(LayerCreeperCharge.this.creeperRenderer.getMainModel()); ++ LayerCreeperCharge.this.creeperModel.setLivingAnimations(entitycreeper, f, f1, f1); ++ LayerCreeperCharge.this.creeperModel.render(entitycreeper, f, f1, f3, f4, f5, f6); ++ GlStateManager.matrixMode(5890); ++ GlStateManager.popMatrix(); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ if (flag) { ++ GlStateManager.depthMask(true); ++ } ++ GlStateManager.enableCull(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ } ++ }); ++ } ++ return; ++ } + +> CHANGE 1 : 4 @ 1 : 2 + +~ if (flag) { +~ GlStateManager.depthMask(false); +~ } + +> CHANGE 18 : 21 @ 18 : 19 + +~ if (flag) { +~ GlStateManager.depthMask(true); +~ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonDeath.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonDeath.edit.java index 260c50d..c6b8f23 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonDeath.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonDeath.edit.java @@ -5,17 +5,73 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 6 @ 2 : 4 +> CHANGE 2 : 11 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; +~ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 2 @ 2 : 4 -> CHANGE 16 : 17 @ 16 : 17 +> INSERT 6 : 48 @ 6 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (entitydragon.deathTicks > 0 && !DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ final float ly = GlStateManager.getTexCoordY(1); ++ DeferredStateManager.forwardCallbackHandler.push( ++ new ShadersRenderPassFuture(entitydragon, EaglerDeferredPipeline.instance.getPartialTicks()) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ float bright = 0.01f + ly * 0.001f; ++ GlStateManager.color(bright, bright, bright, 1.0F); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.tryBlendFuncSeparate(770, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.enableCull(); ++ GlStateManager.enableBlend(); ++ GlStateManager.disableExtensionPipeline(); ++ EntityRenderer.disableLightmapStatic(); ++ doRenderLayer0(entitydragon, var2, var3, f, var5, var6, var7, var8); ++ GlStateManager.enableExtensionPipeline(); ++ GlStateManager.popMatrix(); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.disableAlpha(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ } ++ }); ++ } ++ } else { ++ GlStateManager.enableBlend(); ++ GlStateManager.enableCull(); ++ GlStateManager.blendFunc(770, 1); ++ doRenderLayer0(entitydragon, var2, var3, f, var5, var6, var7, var8); ++ GlStateManager.disableBlend(); ++ GlStateManager.disableCull(); ++ } ++ } ++ ++ public void doRenderLayer0(EntityDragon entitydragon, float var2, float var3, float f, float var5, float var6, ++ float var7, float var8) { + +> CHANGE 10 : 11 @ 10 : 11 ~ EaglercraftRandom random = new EaglercraftRandom(432L); +> DELETE 2 @ 2 : 4 + +> DELETE 1 @ 1 : 2 + +> DELETE 27 @ 27 : 29 + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonEyes.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonEyes.edit.java index ffa550d..fcb250f 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonEyes.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEnderDragonEyes.edit.java @@ -5,11 +5,26 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 4 @ 2 : 4 +> CHANGE 2 : 5 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 1 @ 1 : 2 +> INSERT 14 : 25 @ 14 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ DeferredStateManager.setEmissionConstant(0.5f); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ GlStateManager.enablePolygonOffset(); ++ GlStateManager.doPolygonOffset(-0.025f, 1.0f); ++ this.dragonRenderer.getMainModel().render(entitydragon, f, f1, f3, f4, f5, f6); ++ this.dragonRenderer.func_177105_a(entitydragon, f2); ++ GlStateManager.disablePolygonOffset(); ++ DeferredStateManager.setEmissionConstant(0.0f); ++ return; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEndermanEyes.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEndermanEyes.edit.java index ffa550d..6688675 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEndermanEyes.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerEndermanEyes.edit.java @@ -5,11 +5,69 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 4 @ 2 : 4 +> CHANGE 2 : 9 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; +~ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +~ import net.minecraft.client.model.ModelEnderman; +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 2 +> INSERT 14 : 64 @ 14 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (entityenderman.isInvisible()) { ++ if (!DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entityenderman) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ LayerEndermanEyes.this.endermanRenderer.bindTexture(field_177203_a); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.1f); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.color(0.5F, 0.5F, 0.5F, 1.0F); ++ GlStateManager.depthMask(false); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.disableCull(); ++ ModelEnderman eee = (ModelEnderman) LayerEndermanEyes.this.endermanRenderer.getMainModel(); ++ eee.isAttacking = entityenderman.isScreaming(); ++ eee.setLivingAnimations(entityenderman, f, f1, f1); ++ eee.render(entityenderman, f, f1, f3, f4, f5, f6); ++ GlStateManager.popMatrix(); ++ GlStateManager.depthMask(true); ++ GlStateManager.enableCull(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ } ++ }); ++ } ++ return; ++ } ++ this.endermanRenderer.bindTexture(field_177203_a); ++ EntityRenderer.disableLightmapStatic(); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ GlStateManager.enablePolygonOffset(); ++ GlStateManager.doPolygonOffset(-0.025f, 1.0f); ++ this.endermanRenderer.getMainModel().render(entityenderman, f, f1, f3, f4, f5, f6); ++ GlStateManager.disablePolygonOffset(); ++ DeferredStateManager.setEmissionConstant(0.0f); ++ EntityRenderer.enableLightmapStatic(); ++ return; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerHeldBlock.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerHeldBlock.edit.java index 17e6546..e1d574b 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerHeldBlock.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerHeldBlock.edit.java @@ -5,13 +5,59 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 7 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; -> DELETE 4 @ 4 : 6 +> CHANGE 4 : 5 @ 4 : 6 + +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 2 +> INSERT 2 : 3 @ 2 + ++ import net.minecraft.util.EnumWorldBlockLayer; + +> INSERT 25 : 55 @ 25 + ++ ++ if (DeferredStateManager.isInDeferredPass() ++ && iblockstate.getBlock().getBlockLayer() == EnumWorldBlockLayer.TRANSLUCENT) { ++ if (DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entityenderman) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ EntityRenderer.enableLightmapStatic(); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.texCoords2DDirect(1, lx, ly); ++ LayerHeldBlock.this.endermanRenderer.bindTexture(TextureMap.locationBlocksTexture); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ blockrendererdispatcher.renderBlockBrightness(iblockstate, 1.0F); ++ GlStateManager.popMatrix(); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ } ++ }); ++ } ++ GlStateManager.popMatrix(); ++ GlStateManager.disableRescaleNormal(); ++ return; ++ } ++ + +> INSERT 3 : 4 @ 3 + ++ + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerMooshroomMushroom.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerMooshroomMushroom.edit.java index 7e77e1a..a3c3944 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerMooshroomMushroom.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerMooshroomMushroom.edit.java @@ -5,12 +5,24 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 6 @ 2 ++ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; ++ + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 3 @ 3 : 4 > DELETE 1 @ 1 : 2 +> CHANGE 17 : 19 @ 17 : 18 + +~ boolean flag = DeferredStateManager.isEnableShadowRender(); +~ GlStateManager.cullFace(flag ? GL_BACK : GL_FRONT); + +> CHANGE 23 : 24 @ 23 : 24 + +~ GlStateManager.cullFace(flag ? GL_FRONT : GL_BACK); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSlimeGel.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSlimeGel.edit.java index d6d61f4..0f11452 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSlimeGel.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSlimeGel.edit.java @@ -5,16 +5,64 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 6 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; + +> CHANGE 2 : 4 @ 2 : 3 + +~ import net.minecraft.client.renderer.EntityRenderer; +~ import net.minecraft.client.renderer.entity.RenderManager; + +> CHANGE 1 : 2 @ 1 : 2 + +~ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; + +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.util.MathHelper; + +> INSERT 11 : 44 @ 11 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entityslime) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.1f); ++ boolean flag = LayerSlimeGel.this.slimeRenderer.setBrightness(entityslime, partialTicks, ++ LayerSlimeGel.this.shouldCombineTextures()); ++ EntityRenderer.enableLightmapStatic(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ RenderManager.setupLightmapCoords(entityslime, partialTicks); ++ LayerSlimeGel.this.slimeModel ++ .setModelAttributes(LayerSlimeGel.this.slimeRenderer.getMainModel()); ++ LayerSlimeGel.this.slimeRenderer.bindTexture(RenderSlime.slimeTextures); ++ LayerSlimeGel.this.slimeModel.render(entityslime, f, f1, f2, f3, f4, f5); ++ GlStateManager.popMatrix(); ++ EntityRenderer.disableLightmapStatic(); ++ if (flag) { ++ LayerSlimeGel.this.slimeRenderer.unsetBrightness(); ++ } ++ } ++ }); ++ } ++ return; ++ } > DELETE 2 @ 2 : 3 -> DELETE 1 @ 1 : 2 - -> DELETE 14 @ 14 : 15 - > DELETE 5 @ 5 : 6 > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSpiderEyes.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSpiderEyes.edit.java index ffa550d..96b6113 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSpiderEyes.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerSpiderEyes.edit.java @@ -5,11 +5,66 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 4 @ 2 : 4 +> CHANGE 2 : 9 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; +~ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +~ import net.minecraft.client.model.ModelSpider; +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 2 +> INSERT 13 : 60 @ 13 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (entityspider.isInvisible()) { ++ if (!DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entityspider) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ LayerSpiderEyes.this.spiderRenderer.bindTexture(SPIDER_EYES); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.1f); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.color(0.5F, 0.5F, 0.5F, 1.0F); ++ GlStateManager.depthMask(false); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.disableCull(); ++ ModelSpider eee = (ModelSpider) LayerSpiderEyes.this.spiderRenderer.getMainModel(); ++ eee.setLivingAnimations(entityspider, f, f1, f1); ++ eee.render(entityspider, f, f1, f3, f4, f5, f6); ++ GlStateManager.popMatrix(); ++ GlStateManager.depthMask(true); ++ GlStateManager.enableCull(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ } ++ }); ++ } ++ return; ++ } ++ this.spiderRenderer.bindTexture(SPIDER_EYES); ++ DeferredStateManager.setEmissionConstant(0.5f); ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ GlStateManager.enablePolygonOffset(); ++ GlStateManager.doPolygonOffset(-0.025f, 1.0f); ++ this.spiderRenderer.getMainModel().render(entityspider, f, f1, f3, f4, f5, f6); ++ GlStateManager.disablePolygonOffset(); ++ DeferredStateManager.setEmissionConstant(0.0f); ++ return; ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerWitherAura.edit.java b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerWitherAura.edit.java index ce20507..1b79a6e 100644 --- a/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerWitherAura.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/entity/layers/LayerWitherAura.edit.java @@ -5,12 +5,74 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 6 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; ++ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; + +> CHANGE 1 : 2 @ 1 : 2 + +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 2 -> DELETE 1 @ 1 : 2 +> INSERT 17 : 67 @ 17 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (!DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ DeferredStateManager.forwardCallbackHandler.push(new ShadersRenderPassFuture(entitywither) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ boolean flag = entitywither.isInvisible(); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.5f); ++ DeferredStateManager.setMetalnessConstant(0.2f); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); ++ GlStateManager.color(0.5F, 0.5F, 0.5F, 1.0F); ++ if (flag) { ++ GlStateManager.depthMask(false); ++ } ++ LayerWitherAura.this.witherRenderer.bindTexture(WITHER_ARMOR); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.matrixMode(5890); ++ GlStateManager.loadIdentity(); ++ float f7 = (float) entitywither.ticksExisted + f2; ++ float f8 = MathHelper.cos(f7 * 0.02F) * 3.0F; ++ float f9 = f7 * 0.01F; ++ GlStateManager.translate(f8, f9, 0.0F); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.disableCull(); ++ LayerWitherAura.this.witherModel.setLivingAnimations(entitywither, f, f1, f2); ++ LayerWitherAura.this.witherModel.setRotationAngles(f, f1, f2, f3, f4, f5, entitywither); ++ LayerWitherAura.this.witherModel ++ .setModelAttributes(LayerWitherAura.this.witherRenderer.getMainModel()); ++ LayerWitherAura.this.witherModel.render(entitywither, f, f1, f3, f4, f5, f6); ++ GlStateManager.matrixMode(5890); ++ GlStateManager.loadIdentity(); ++ GlStateManager.matrixMode(5888); ++ GlStateManager.popMatrix(); ++ if (flag) { ++ GlStateManager.depthMask(true); ++ } ++ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); ++ } ++ }); ++ } ++ return; ++ } + +> INSERT 22 : 23 @ 22 + ++ GlStateManager.depthMask(true); > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/AbstractTexture.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/AbstractTexture.edit.java index d66b768..831be9a 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/AbstractTexture.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/AbstractTexture.edit.java @@ -14,25 +14,20 @@ + import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + -> CHANGE 8 : 20 @ 8 : 19 +> CHANGE 8 : 16 @ 8 : 10 ~ if (blur != parFlag || mipmap != parFlag2) { ~ this.blur = parFlag; ~ this.mipmap = parFlag2; -~ int i = -1; -~ short short1 = -1; -~ if (parFlag) { -~ i = parFlag2 ? 9987 : 9729; -~ short1 = 9729; -~ } else { -~ i = parFlag2 ? 9986 : 9728; -~ short1 = 9728; -~ } - -> CHANGE 1 : 4 @ 1 : 3 - -~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, i); -~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, short1); +~ setBlurMipmapDirect0(parFlag, parFlag2); ~ } +~ } +~ +~ protected void setBlurMipmapDirect0(boolean parFlag, boolean parFlag2) { + +> CHANGE 10 : 12 @ 10 : 12 + +~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, i); +~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, short1); > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureClock.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/TextureClock.edit.java index a3c0959..219e0b7 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureClock.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureClock.edit.java @@ -5,8 +5,9 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 4 @ 2 ++ import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; > DELETE 1 @ 1 : 3 @@ -15,10 +16,14 @@ ~ public class TextureClock extends EaglerTextureAtlasSprite { -> CHANGE 41 : 43 @ 41 : 43 +> CHANGE 7 : 8 @ 7 : 8 + +~ public void updateAnimation(IFramebufferGL[] copyColorFramebuffer) { + +> CHANGE 33 : 35 @ 33 : 35 ~ animationCache.copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, this.width, -~ this.height); +~ this.height, copyColorFramebuffer); > INSERT 4 : 5 @ 4 diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureCompass.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/TextureCompass.edit.java index 7b977ad..76a78b6 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureCompass.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureCompass.edit.java @@ -5,8 +5,9 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 3 @ 2 +> INSERT 2 : 4 @ 2 ++ import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; > DELETE 1 @ 1 : 3 @@ -15,10 +16,26 @@ ~ public class TextureCompass extends EaglerTextureAtlasSprite { -> CHANGE 62 : 64 @ 62 : 64 +> CHANGE 9 : 10 @ 9 : 10 + +~ public void updateAnimation(IFramebufferGL[] copyColorFramebuffer) { + +> CHANGE 3 : 4 @ 3 : 4 + +~ (double) minecraft.thePlayer.rotationYaw, false, false, copyColorFramebuffer); + +> CHANGE 1 : 2 @ 1 : 2 + +~ this.updateCompass((World) null, 0.0D, 0.0D, 0.0D, true, false, copyColorFramebuffer); + +> CHANGE 5 : 6 @ 5 : 6 + +~ boolean parFlag2, IFramebufferGL[] copyColorFramebuffer) { + +> CHANGE 40 : 42 @ 40 : 42 ~ animationCache.copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, this.width, -~ this.height); +~ this.height, copyColorFramebuffer); > INSERT 4 : 5 @ 4 diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureManager.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/TextureManager.edit.java index fb0e6b1..46a8b2e 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureManager.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureManager.edit.java @@ -5,9 +5,12 @@ # Version: 1.0 # Author: lax1dude -> DELETE 2 @ 2 : 4 +> CHANGE 2 : 4 @ 2 : 4 -> CHANGE 5 : 12 @ 5 : 11 +~ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +~ + +> CHANGE 5 : 15 @ 5 : 11 ~ ~ import com.google.common.collect.Lists; @@ -16,13 +19,17 @@ ~ import net.lax1dude.eaglercraft.v1_8.HString; ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.minecraft.client.Minecraft; > DELETE 6 @ 6 : 8 -> CHANGE 13 : 21 @ 13 : 18 +> CHANGE 13 : 22 @ 13 : 18 +~ int glTex; ~ if (resource.cachedPointer != null) { -~ TextureUtil.bindTexture(((ITextureObject) resource.cachedPointer).getGlTextureId()); // unsafe, lol +~ TextureUtil.bindTexture(glTex = ((ITextureObject) resource.cachedPointer).getGlTextureId()); // unsafe, lol ~ } else { ~ Object object = (ITextureObject) this.mapTextureObjects.get(resource); ~ if (object == null) { @@ -30,10 +37,21 @@ ~ this.loadTexture(resource, (ITextureObject) object); ~ } -> CHANGE 1 : 4 @ 1 : 2 +> CHANGE 1 : 15 @ 1 : 2 ~ resource.cachedPointer = object; -~ TextureUtil.bindTexture(((ITextureObject) object).getGlTextureId()); +~ TextureUtil.bindTexture(glTex = ((ITextureObject) object).getGlTextureId()); +~ } +~ if (DeferredStateManager.isInDeferredPass()) { +~ TextureMap blocksTex = Minecraft.getMinecraft().getTextureMapBlocks(); +~ if (blocksTex != null) { +~ if (blocksTex.getGlTextureId() == glTex) { +~ DeferredStateManager.enableMaterialTexture(); +~ GlStateManager.quickBindTexture(GL_TEXTURE2, blocksTex.eaglerPBRMaterialTexture); +~ } else { +~ DeferredStateManager.disableMaterialTexture(); +~ } +~ } ~ } > CHANGE 11 : 12 @ 11 : 12 diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.edit.java index 27103eb..eacd8e0 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureMap.edit.java @@ -11,49 +11,260 @@ + import java.util.Collection; -> INSERT 6 : 15 @ 6 +> INSERT 6 : 20 @ 6 + + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + + import net.lax1dude.eaglercraft.v1_8.HString; ++ import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; + import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; + import net.lax1dude.eaglercraft.v1_8.log4j.Logger; + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; ++ import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; ++ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.EaglerTextureAtlasSpritePBR; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.PBRTextureMapUtils; > DELETE 2 @ 2 : 8 > DELETE 9 @ 9 : 11 -> CHANGE 5 : 8 @ 5 : 8 +> INSERT 1 : 3 @ 1 + ++ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; ++ + +> CHANGE 4 : 7 @ 4 : 7 ~ private final List listAnimatedSprites; ~ private final Map mapRegisteredSprites; ~ private final Map mapUploadedSprites; -> CHANGE 3 : 6 @ 3 : 4 +> CHANGE 3 : 9 @ 3 : 4 ~ private final EaglerTextureAtlasSprite missingImage; +~ private final EaglerTextureAtlasSpritePBR missingImagePBR; ~ private int width; ~ private int height; +~ private boolean isEaglerPBRMode = false; +~ public int eaglerPBRMaterialTexture = -1; -> CHANGE 9 : 10 @ 9 : 10 +> INSERT 1 : 7 @ 1 + ++ public static final int _GL_FRAMEBUFFER = 0x8D40; ++ public static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0; ++ ++ private IFramebufferGL[] copyColorFramebuffer = null; ++ private IFramebufferGL[] copyMaterialFramebuffer = null; ++ + +> CHANGE 8 : 10 @ 8 : 9 ~ this.missingImage = new EaglerTextureAtlasSprite("missingno"); +~ this.missingImagePBR = new EaglerTextureAtlasSpritePBR("missingno"); -> DELETE 17 @ 17 : 18 +> INSERT 11 : 27 @ 11 + ++ this.missingImagePBR.setIconWidth(16); ++ this.missingImagePBR.setIconHeight(16); ++ int[][][] aint2 = new int[3][this.mipmapLevels + 1][]; ++ aint2[0][0] = aint; ++ int[] missingNormals = new int[256]; ++ for (int i = 0; i < missingNormals.length; ++i) { ++ missingNormals[i] = 0xFF7F7F; ++ } ++ aint2[1][0] = missingNormals; ++ int[] missingMaterial = new int[256]; ++ for (int i = 0; i < missingMaterial.length; ++i) { ++ missingMaterial[i] = 0x00000077; ++ } ++ aint2[2][0] = missingMaterial; ++ this.missingImagePBR.setFramesTextureDataPBR(new List[] { Lists.newArrayList(new int[][][] { aint2[0] }), ++ Lists.newArrayList(new int[][][] { aint2[1] }), Lists.newArrayList(new int[][][] { aint2[2] }) }); + +> DELETE 6 @ 6 : 7 > INSERT 3 : 4 @ 3 + destroyAnimationCaches(); -> CHANGE 16 : 17 @ 16 : 17 +> INSERT 7 : 27 @ 7 + ++ public void deleteGlTexture() { ++ super.deleteGlTexture(); ++ if (eaglerPBRMaterialTexture != -1) { ++ GlStateManager.deleteTexture(eaglerPBRMaterialTexture); ++ eaglerPBRMaterialTexture = -1; ++ } ++ if (copyColorFramebuffer != null) { ++ for (int i = 0; i < copyColorFramebuffer.length; ++i) { ++ _wglDeleteFramebuffer(copyColorFramebuffer[i]); ++ } ++ copyColorFramebuffer = null; ++ } ++ if (copyMaterialFramebuffer != null) { ++ for (int i = 0; i < copyMaterialFramebuffer.length; ++i) { ++ _wglDeleteFramebuffer(copyMaterialFramebuffer[i]); ++ } ++ copyMaterialFramebuffer = null; ++ } ++ } ++ + +> INSERT 8 : 43 @ 8 + ++ if (copyColorFramebuffer != null) { ++ for (int l = 0; l < copyColorFramebuffer.length; ++l) { ++ _wglDeleteFramebuffer(copyColorFramebuffer[l]); ++ } ++ copyColorFramebuffer = null; ++ } ++ ++ if (isEaglerPBRMode) { ++ if (eaglerPBRMaterialTexture == -1) { ++ eaglerPBRMaterialTexture = GlStateManager.generateTexture(); ++ } ++ if (copyMaterialFramebuffer == null) { ++ GlStateManager.bindTexture(eaglerPBRMaterialTexture); ++ copyMaterialFramebuffer = new IFramebufferGL[this.mipmapLevels + 1]; ++ for (int l = 0; l < copyMaterialFramebuffer.length; ++l) { ++ copyMaterialFramebuffer[l] = _wglCreateFramebuffer(); ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, copyMaterialFramebuffer[l]); ++ _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ++ EaglercraftGPU.getNativeTexture(eaglerPBRMaterialTexture), l); ++ } ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, null); ++ } ++ } else { ++ if (eaglerPBRMaterialTexture != -1) { ++ GlStateManager.deleteTexture(eaglerPBRMaterialTexture); ++ eaglerPBRMaterialTexture = -1; ++ } ++ if (copyMaterialFramebuffer != null) { ++ for (int l = 0; l < copyMaterialFramebuffer.length; ++l) { ++ _wglDeleteFramebuffer(copyMaterialFramebuffer[l]); ++ } ++ copyMaterialFramebuffer = null; ++ } ++ } ++ + +> CHANGE 1 : 2 @ 1 : 2 ~ EaglerTextureAtlasSprite textureatlassprite = (EaglerTextureAtlasSprite) entry.getValue(); -> CHANGE 5 : 6 @ 5 : 6 +> INSERT 3 : 108 @ 3 + ++ if (isEaglerPBRMode) { ++ try { ++ IResource iresource = resourceManager.getResource(resourcelocation1); ++ ImageData[] abufferedimageColor = new ImageData[1 + this.mipmapLevels]; ++ ImageData[] abufferedimageNormal = new ImageData[1 + this.mipmapLevels]; ++ ImageData[] abufferedimageMaterial = new ImageData[1 + this.mipmapLevels]; ++ abufferedimageColor[0] = TextureUtil.readBufferedImage(iresource.getInputStream()); ++ abufferedimageNormal[0] = PBRTextureMapUtils.locateCompanionTexture(resourceManager, iresource, ++ "_n"); ++ abufferedimageMaterial[0] = PBRTextureMapUtils.locateCompanionTexture(resourceManager, iresource, ++ "_s"); ++ boolean dontAnimateNormals = false; ++ boolean dontAnimateMaterial = false; ++ if (abufferedimageNormal[0] == null) { ++ abufferedimageNormal[0] = PBRTextureMapUtils.defaultNormalsTexture; ++ dontAnimateNormals = true; ++ } ++ if (abufferedimageMaterial[0] == null) { ++ abufferedimageMaterial[0] = PBRTextureMapUtils.generateMaterialTextureFor( ++ ((EaglerTextureAtlasSprite) (entry.getValue())).getIconName()); ++ dontAnimateMaterial = true; ++ } ++ PBRTextureMapUtils.unifySizes(0, abufferedimageColor, abufferedimageNormal, abufferedimageMaterial); ++ ++ TextureMetadataSection texturemetadatasection = (TextureMetadataSection) iresource ++ .getMetadata("texture"); ++ if (texturemetadatasection != null) { ++ List list = texturemetadatasection.getListMipmaps(); ++ if (!list.isEmpty()) { ++ int l = abufferedimageColor[0].width; ++ int i1 = abufferedimageColor[0].height; ++ if (MathHelper.roundUpToPowerOfTwo(l) != l || MathHelper.roundUpToPowerOfTwo(i1) != i1) { ++ throw new RuntimeException( ++ "Unable to load extra miplevels, source-texture is not power of two"); ++ } ++ } ++ ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ int i2 = ((Integer) iterator.next()).intValue(); ++ if (i2 > 0 && i2 < abufferedimageColor.length - 1 && abufferedimageColor[i2] == null) { ++ ResourceLocation resourcelocation2 = this.completeResourceLocation(resourcelocation, ++ i2); ++ ++ try { ++ IResource mipLevelResource = resourceManager.getResource(resourcelocation2); ++ abufferedimageColor[i2] = TextureUtil ++ .readBufferedImage(mipLevelResource.getInputStream()); ++ abufferedimageNormal[i2] = PBRTextureMapUtils ++ .locateCompanionTexture(resourceManager, mipLevelResource, "_n"); ++ abufferedimageMaterial[i2] = PBRTextureMapUtils ++ .locateCompanionTexture(resourceManager, mipLevelResource, "_s"); ++ if (abufferedimageNormal[i2] == null) { ++ abufferedimageNormal[i2] = PBRTextureMapUtils.defaultNormalsTexture; ++ } ++ if (abufferedimageMaterial[i2] == null) { ++ abufferedimageMaterial[i2] = PBRTextureMapUtils.generateMaterialTextureFor( ++ ((EaglerTextureAtlasSprite) (entry.getValue())).getIconName()); ++ } ++ PBRTextureMapUtils.unifySizes(i2, abufferedimageColor, abufferedimageNormal, ++ abufferedimageMaterial); ++ if ((abufferedimageColor[0].width >> i2) != abufferedimageColor[i2].width) { ++ throw new IOException("Mipmap level " + i2 + " is the wrong size, should be " ++ + (abufferedimageColor[0].width >> i2) + " pixels"); ++ } ++ } catch (Throwable exc) { ++ logger.error("Unable to load miplevel {} from: {}", i2, resourcelocation2); ++ logger.error(exc); ++ } ++ } ++ } ++ } ++ ++ AnimationMetadataSection animationmetadatasection = (AnimationMetadataSection) iresource ++ .getMetadata("animation"); ++ textureatlassprite.loadSpritePBR( ++ new ImageData[][] { abufferedimageColor, abufferedimageNormal, abufferedimageMaterial }, ++ animationmetadatasection, dontAnimateNormals, dontAnimateMaterial); ++ } catch (RuntimeException runtimeexception) { ++ logger.error("Unable to parse metadata from " + resourcelocation1); ++ logger.error(runtimeexception); ++ continue; ++ } catch (IOException ioexception1) { ++ logger.error("Using missing texture, unable to load " + resourcelocation1); ++ logger.error(ioexception1); ++ continue; ++ } ++ ++ j = Math.min(j, Math.min(textureatlassprite.getIconWidth(), textureatlassprite.getIconHeight())); ++ int l1 = Math.min(Integer.lowestOneBit(textureatlassprite.getIconWidth()), ++ Integer.lowestOneBit(textureatlassprite.getIconHeight())); ++ if (l1 < k) { ++ logger.warn("Texture {} with size {}x{} limits mip level from {} to {}", ++ new Object[] { resourcelocation1, Integer.valueOf(textureatlassprite.getIconWidth()), ++ Integer.valueOf(textureatlassprite.getIconHeight()), ++ Integer.valueOf(MathHelper.calculateLogBaseTwo(k)), ++ Integer.valueOf(MathHelper.calculateLogBaseTwo(l1)) }); ++ k = l1; ++ } ++ ++ stitcher.addSprite(textureatlassprite); ++ continue; ++ } ++ + +> CHANGE 2 : 3 @ 2 : 3 ~ ImageData[] abufferedimage = new ImageData[1 + this.mipmapLevels]; @@ -81,18 +292,70 @@ ~ for (final EaglerTextureAtlasSprite textureatlassprite1 : this.mapRegisteredSprites.values()) { -> CHANGE 40 : 44 @ 40 : 41 +> CHANGE 25 : 32 @ 25 : 27 + +~ if (isEaglerPBRMode) { +~ this.missingImagePBR.generateMipmaps(this.mipmapLevels); +~ stitcher.addSprite(this.missingImagePBR); +~ } else { +~ this.missingImage.generateMipmaps(this.mipmapLevels); +~ stitcher.addSprite(this.missingImage); +~ } + +> INSERT 11 : 28 @ 11 + ++ if (isEaglerPBRMode) { ++ TextureUtil.allocateTextureImpl(eaglerPBRMaterialTexture, this.mipmapLevels, stitcher.getCurrentWidth(), ++ stitcher.getCurrentHeight() * 2); ++ } ++ ++ TextureUtil.bindTexture(this.glTextureId); ++ ++ copyColorFramebuffer = new IFramebufferGL[this.mipmapLevels + 1]; ++ for (int l = 0; l < copyColorFramebuffer.length; ++l) { ++ copyColorFramebuffer[l] = _wglCreateFramebuffer(); ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, copyColorFramebuffer[l]); ++ _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ++ EaglercraftGPU.getNativeTexture(this.glTextureId), l); ++ } ++ ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, null); ++ + +> CHANGE 2 : 7 @ 2 : 3 ~ width = stitcher.getCurrentWidth(); ~ height = stitcher.getCurrentHeight(); ~ -~ for (EaglerTextureAtlasSprite textureatlassprite2 : stitcher.getStichSlots()) { +~ List spriteList = stitcher.getStichSlots(); +~ for (EaglerTextureAtlasSprite textureatlassprite2 : spriteList) { -> CHANGE 21 : 22 @ 21 : 22 +> INSERT 5 : 6 @ 5 + ++ TextureUtil.bindTexture(this.glTextureId); + +> INSERT 3 : 13 @ 3 + ++ if (isEaglerPBRMode) { ++ TextureUtil.bindTexture(eaglerPBRMaterialTexture); ++ int[][][] pixels = ((EaglerTextureAtlasSpritePBR) textureatlassprite2).getFramePBRTextureData(0); ++ TextureUtil.uploadTextureMipmap(pixels[1], textureatlassprite2.getIconWidth(), ++ textureatlassprite2.getIconHeight(), textureatlassprite2.getOriginX(), ++ textureatlassprite2.getOriginY(), false, false); ++ TextureUtil.uploadTextureMipmap(pixels[2], textureatlassprite2.getIconWidth(), ++ textureatlassprite2.getIconHeight(), textureatlassprite2.getOriginX(), ++ textureatlassprite2.getOriginY() + height, false, false); ++ } + +> CHANGE 13 : 14 @ 13 : 14 ~ for (EaglerTextureAtlasSprite textureatlassprite3 : (Collection) hashmap.values()) { -> CHANGE 8 : 10 @ 8 : 10 +> INSERT 3 : 4 @ 3 + ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + +> CHANGE 5 : 7 @ 5 : 7 ~ HString.format("%s/%s%s", new Object[] { this.basePath, location.getResourcePath(), ".png" })) ~ : new ResourceLocation(location.getResourceDomain(), HString.format("%s/mipmaps/%s.%d%s", @@ -102,11 +365,30 @@ ~ public EaglerTextureAtlasSprite getAtlasSprite(String iconName) { ~ EaglerTextureAtlasSprite textureatlassprite = (EaglerTextureAtlasSprite) this.mapUploadedSprites.get(iconName); -> CHANGE 10 : 11 @ 10 : 11 +> CHANGE 1 : 2 @ 1 : 2 + +~ textureatlassprite = isEaglerPBRMode ? missingImagePBR : missingImage; + +> CHANGE 6 : 13 @ 6 : 7 + +~ if (isEaglerPBRMode) { +~ for (EaglerTextureAtlasSprite textureatlassprite : this.listAnimatedSprites) { +~ textureatlassprite.updateAnimationPBR(copyColorFramebuffer, copyMaterialFramebuffer, height); +~ } +~ _wglBindFramebuffer(_GL_FRAMEBUFFER, null); +~ return; +~ } + +> CHANGE 1 : 3 @ 1 : 3 ~ for (EaglerTextureAtlasSprite textureatlassprite : this.listAnimatedSprites) { +~ textureatlassprite.updateAnimation(copyColorFramebuffer); -> CHANGE 5 : 12 @ 5 : 6 +> INSERT 2 : 3 @ 2 + ++ _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + +> CHANGE 2 : 9 @ 2 : 3 ~ private void destroyAnimationCaches() { ~ for (EaglerTextureAtlasSprite textureatlassprite : this.listAnimatedSprites) { @@ -121,15 +403,20 @@ ~ EaglerTextureAtlasSprite textureatlassprite = (EaglerTextureAtlasSprite) this.mapRegisteredSprites ~ .get(location); -> CHANGE 1 : 2 @ 1 : 2 +> CHANGE 1 : 6 @ 1 : 2 -~ textureatlassprite = EaglerTextureAtlasSprite.makeAtlasSprite(location); +~ if (isEaglerPBRMode) { +~ textureatlassprite = EaglerTextureAtlasSpritePBR.makeAtlasSprite(location); +~ } else { +~ textureatlassprite = EaglerTextureAtlasSprite.makeAtlasSprite(location); +~ } -> CHANGE 15 : 16 @ 15 : 16 +> CHANGE 15 : 17 @ 15 : 17 ~ public EaglerTextureAtlasSprite getMissingSprite() { +~ return isEaglerPBRMode ? missingImagePBR : missingImage; -> INSERT 2 : 11 @ 2 +> INSERT 1 : 23 @ 1 + + public int getWidth() { @@ -140,5 +427,18 @@ + return height; + } + ++ public void setEnablePBREagler(boolean enable) { ++ isEaglerPBRMode = enable; ++ } ++ ++ public void setBlurMipmapDirect0(boolean parFlag, boolean parFlag2) { ++ super.setBlurMipmapDirect0(parFlag, parFlag2); ++ if (isEaglerPBRMode && eaglerPBRMaterialTexture != -1) { ++ GlStateManager.setActiveTexture(33986); ++ GlStateManager.bindTexture(eaglerPBRMaterialTexture); ++ super.setBlurMipmapDirect0(parFlag, parFlag2); ++ GlStateManager.setActiveTexture(33984); ++ } ++ } > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/texture/TextureUtil.edit.java b/patches/minecraft/net/minecraft/client/renderer/texture/TextureUtil.edit.java index 150e915..96c47c9 100644 --- a/patches/minecraft/net/minecraft/client/renderer/texture/TextureUtil.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/texture/TextureUtil.edit.java @@ -53,12 +53,11 @@ ~ EaglercraftGPU.glTexParameterf(GL_TEXTURE_2D, '\u813b', (float) parInt2); ~ // EaglercraftGPU.glTexParameterf(GL_TEXTURE_2D, '\u8501', 0.0F); -> CHANGE 3 : 5 @ 3 : 4 +> CHANGE 1 : 2 @ 1 : 6 -~ EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, parInt3 >> i, parInt4 >> i, 0, GL_RGBA, -~ GL_UNSIGNED_BYTE, (IntBuffer) null); +~ EaglercraftGPU.glTexStorage2D(GL_TEXTURE_2D, parInt2 + 1, GL_RGBA8, parInt3, parInt4); -> CHANGE 4 : 5 @ 4 : 5 +> CHANGE 2 : 3 @ 2 : 3 ~ public static int uploadTextureImageSub(int textureId, ImageData parBufferedImage, int parInt2, int parInt3, diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/RenderItemFrame.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/RenderItemFrame.edit.java index 1dbfeab..009189b 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/RenderItemFrame.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/RenderItemFrame.edit.java @@ -5,20 +5,23 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 6 @ 2 +> INSERT 2 : 7 @ 2 -+ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; + import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer; > DELETE 3 @ 3 : 4 > DELETE 2 @ 2 : 3 -> DELETE 4 @ 4 : 5 +> DELETE 4 @ 4 : 6 -> DELETE 16 @ 16 : 17 +> DELETE 12 @ 12 : 13 + +> DELETE 2 @ 2 : 3 > INSERT 36 : 38 @ 36 @@ -30,17 +33,33 @@ + GlStateManager.enableLighting(); + GlStateManager.enableColorMaterial(); -> DELETE 33 @ 33 : 54 +> CHANGE 33 : 37 @ 33 : 52 + +~ boolean emissive = itemFrame.eaglerEmissiveFlag; +~ itemFrame.eaglerEmissiveFlag = false; +~ if (emissive) { +~ DeferredStateManager.setEmissionConstant(1.0f); + +> DELETE 1 @ 1 : 2 > CHANGE 5 : 6 @ 5 : 6 ~ GlStateManager.pushLightCoords(); -> CHANGE 3 : 4 @ 3 : 7 +> CHANGE 3 : 6 @ 3 : 6 ~ GlStateManager.popLightCoords(); +~ if (emissive) { +~ DeferredStateManager.setEmissionConstant(0.0f); -> CHANGE 21 : 22 @ 21 : 22 +> INSERT 19 : 23 @ 19 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ NameTagRenderer.renderNameTag(entityitemframe, null, d0, d1, d2, -69); ++ return; ++ } + +> CHANGE 3 : 4 @ 3 : 4 ~ EaglercraftGPU.glNormal3f(0.0F, 1.0F, 0.0F); diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer.edit.java index 0432889..1d59024 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityBeaconRenderer.edit.java @@ -5,20 +5,173 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 3 : 7 @ 3 : 4 +> CHANGE 3 : 11 @ 3 : 4 ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; +~ import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +~ import net.minecraft.client.renderer.EntityRenderer; > DELETE 1 @ 1 : 3 > DELETE 4 @ 4 : 5 -> CHANGE 19 : 21 @ 19 : 21 +> INSERT 6 : 8 @ 6 -~ EaglercraftGPU.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 10497.0F); -~ EaglercraftGPU.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 10497.0F); ++ if (DeferredStateManager.isEnableShadowRender()) ++ return; + +> INSERT 3 : 4 @ 3 + ++ boolean deferred = DeferredStateManager.isInDeferredPass(); + +> CHANGE 10 : 18 @ 10 : 12 + +~ if (deferred) { +~ DeferredStateManager.setDefaultMaterialConstants(); +~ DeferredStateManager.setRoughnessConstant(0.3f); +~ DeferredStateManager.setMetalnessConstant(0.3f); +~ DeferredStateManager.setEmissionConstant(0.9f); +~ } +~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 10497); +~ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 10497); + +> CHANGE 24 : 26 @ 24 : 25 + +~ worldrenderer.begin(7, deferred ? DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL +~ : DefaultVertexFormats.POSITION_TEX_COLOR); + +> INSERT 6 : 8 @ 6 + ++ if (deferred) ++ worldrenderer.genNormals(true, 0); + +> INSERT 8 : 10 @ 8 + ++ if (deferred) ++ worldrenderer.genNormals(true, 0); + +> INSERT 8 : 10 @ 8 + ++ if (deferred) ++ worldrenderer.genNormals(true, 0); + +> INSERT 6 : 8 @ 6 + ++ if (deferred) ++ worldrenderer.genNormals(true, 0); + +> INSERT 1 : 10 @ 1 + ++ ++ if (deferred) { ++ DeferredStateManager.setDefaultMaterialConstants(); ++ GlStateManager.enableLighting(); ++ GlStateManager.depthMask(true); ++ i = k; ++ continue; ++ } ++ + +> INSERT 55 : 149 @ 55 + ++ if (deferred && list.size() > 0) { ++ if (DeferredStateManager.forwardCallbackHandler != null) { ++ final Matrix4f mat = new Matrix4f(GlStateManager.getModelViewReference()); ++ final float lx = GlStateManager.getTexCoordX(1), ly = GlStateManager.getTexCoordY(1); ++ DeferredStateManager.forwardCallbackHandler ++ .push(new ShadersRenderPassFuture((float) d0, (float) d1, (float) d2, f) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ TileEntityBeaconRenderer.this.bindTexture(beaconBeam); ++ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 10497); ++ EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 10497); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.2f); ++ DeferredStateManager.setEmissionConstant(0.6f); ++ GlStateManager.depthMask(false); ++ GlStateManager.pushMatrix(); ++ GlStateManager.loadMatrix(mat); ++ GlStateManager.texCoords2DDirect(1, lx, ly); ++ EntityRenderer.enableLightmapStatic(); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ List list = tileentitybeacon.getBeamSegments(); ++ int i = 0; ++ ++ for (int j = 0; j < list.size(); ++j) { ++ TileEntityBeacon.BeamSegment tileentitybeacon$beamsegment = (TileEntityBeacon.BeamSegment) list ++ .get(j); ++ int k = i + tileentitybeacon$beamsegment.getHeight(); ++ ++ double d3 = (double) tileentitybeacon.getWorld().getTotalWorldTime() ++ + (double) f; ++ double d4 = MathHelper.func_181162_h( ++ -d3 * 0.2D - (double) MathHelper.floor_double(-d3 * 0.1D)); ++ float f2 = tileentitybeacon$beamsegment.getColors()[0]; ++ float f3 = tileentitybeacon$beamsegment.getColors()[1]; ++ float f4 = tileentitybeacon$beamsegment.getColors()[2]; ++ ++ double d15 = 0.0D; ++ double d16 = 1.0D; ++ double d17 = -1.0D + d4; ++ ++ d15 = -1.0D + d4; ++ d16 = (double) ((float) tileentitybeacon$beamsegment.getHeight() * f1) + d15; ++ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) k, d2 + 0.2D).tex(1.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) i, d2 + 0.2D).tex(1.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) i, d2 + 0.2D).tex(0.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) k, d2 + 0.2D).tex(0.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.genNormals(true, 0); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) k, d2 + 0.8D).tex(1.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) i, d2 + 0.8D).tex(1.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) i, d2 + 0.8D).tex(0.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) k, d2 + 0.8D).tex(0.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.genNormals(true, 0); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) k, d2 + 0.2D).tex(1.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) i, d2 + 0.2D).tex(1.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) i, d2 + 0.8D).tex(0.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.8D, d1 + (double) k, d2 + 0.8D).tex(0.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.genNormals(true, 0); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) k, d2 + 0.8D).tex(1.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) i, d2 + 0.8D).tex(1.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) i, d2 + 0.2D).tex(0.0D, d15) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.pos(d0 + 0.2D, d1 + (double) k, d2 + 0.2D).tex(0.0D, d16) ++ .color(f2, f3, f4, 0.125F).endVertex(); ++ worldrenderer.genNormals(true, 0); ++ tessellator.draw(); ++ i = k; ++ } ++ GlStateManager.popMatrix(); ++ EntityRenderer.disableLightmapStatic(); ++ GlStateManager.depthMask(true); ++ } ++ }); ++ } ++ } ++ > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityChestRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityChestRenderer.edit.java index 725bac4..356c826 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityChestRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityChestRenderer.edit.java @@ -12,11 +12,7 @@ > DELETE 4 @ 4 : 6 -> INSERT 49 : 50 @ 49 - -+ - -> DELETE 7 @ 7 : 9 +> DELETE 56 @ 56 : 58 > INSERT 2 : 4 @ 2 diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityEndPortalRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityEndPortalRenderer.edit.java index 985376b..e468e6d 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityEndPortalRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityEndPortalRenderer.edit.java @@ -5,13 +5,15 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 2 : 7 @ 2 : 4 +> CHANGE 2 : 9 @ 2 : 4 ~ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ ~ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture; > DELETE 3 @ 3 : 4 @@ -21,7 +23,54 @@ ~ private static final EaglercraftRandom field_147527_e = new EaglercraftRandom(31100L); -> CHANGE 34 : 35 @ 34 : 35 +> INSERT 3 : 31 @ 3 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ if (!DeferredStateManager.isInParaboloidPass() && !DeferredStateManager.isEnableShadowRender() ++ && DeferredStateManager.forwardCallbackHandler != null) { ++ DeferredStateManager.forwardCallbackHandler ++ .push(new ShadersRenderPassFuture((float) d0, (float) d1, (float) d2, var8) { ++ @Override ++ public void draw(PassType pass) { ++ if (pass == PassType.MAIN) { ++ DeferredStateManager.reportForwardRenderObjectPosition2(x, y, z); ++ } ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setRoughnessConstant(0.3f); ++ DeferredStateManager.setMetalnessConstant(0.3f); ++ DeferredStateManager.setEmissionConstant(0.9f); ++ renderTileEntityAt0(var1, d0, d1, d2, var8, var9); ++ DeferredStateManager.setDefaultMaterialConstants(); ++ DeferredStateManager.setHDRTranslucentPassBlendFunc(); ++ } ++ }); ++ } ++ return; ++ } ++ GlStateManager.enableBlend(); ++ renderTileEntityAt0(var1, d0, d1, d2, var8, var9); ++ GlStateManager.disableBlend(); ++ } ++ ++ private void renderTileEntityAt0(TileEntityEndPortal var1, double d0, double d1, double d2, float var8, int var9) { + +> CHANGE 17 : 22 @ 17 : 19 + +~ if (DeferredStateManager.isInDeferredPass()) { +~ DeferredStateManager.setHDRTranslucentPassBlendFunc(); +~ } else { +~ GlStateManager.blendFunc(770, 771); +~ } + +> CHANGE 7 : 12 @ 7 : 9 + +~ if (DeferredStateManager.isInDeferredPass()) { +~ GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); +~ } else { +~ GlStateManager.blendFunc(1, 1); +~ } + +> CHANGE 3 : 4 @ 3 : 4 ~ float f7 = (float) (-(d1 + (double) f3 - 1.25)); @@ -29,7 +78,7 @@ ~ GlStateManager.enableTexGen(); -> CHANGE 34 : 35 @ 34 : 38 +> CHANGE 33 : 34 @ 33 : 38 ~ GlStateManager.disableTexGen(); diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityPistonRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityPistonRenderer.edit.java index 0d7662b..4fe4e2d 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityPistonRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntityPistonRenderer.edit.java @@ -5,10 +5,12 @@ # Version: 1.0 # Author: lax1dude -> INSERT 2 : 4 @ 2 +> INSERT 2 : 6 @ 2 + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat; + import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 7 @ 7 : 8 @@ -16,4 +18,14 @@ > DELETE 1 @ 1 : 2 +> CHANGE 28 : 30 @ 28 : 29 + +~ worldrenderer.begin(7, DeferredStateManager.isDeferredRenderer() ? VertexFormat.BLOCK_SHADERS +~ : DefaultVertexFormats.BLOCK); + +> INSERT 38 : 40 @ 38 + ++ GlStateManager.enableCull(); ++ GlStateManager.disableBlend(); + > EOF diff --git a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntitySignRenderer.edit.java b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntitySignRenderer.edit.java index ef9265c..365f1eb 100644 --- a/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntitySignRenderer.edit.java +++ b/patches/minecraft/net/minecraft/client/renderer/tileentity/TileEntitySignRenderer.edit.java @@ -5,11 +5,19 @@ # Version: 1.0 # Author: lax1dude -> INSERT 3 : 6 @ 3 +> INSERT 2 : 5 @ 2 + ++ import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; ++ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; ++ + +> INSERT 1 : 6 @ 1 + + import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredPipeline; > DELETE 4 @ 4 : 6 @@ -19,4 +27,19 @@ ~ EaglercraftGPU.glNormal3f(0.0F, 0.0F, -1.0F * f3); +> INSERT 3 : 8 @ 3 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); ++ GlStateManager.colorMask(true, true, true, false); ++ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); ++ } + +> INSERT 15 : 19 @ 15 + ++ if (DeferredStateManager.isInDeferredPass()) { ++ _wglDrawBuffers(EaglerDeferredPipeline.instance.gBufferDrawBuffers); ++ GlStateManager.colorMask(true, true, true, true); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/client/resources/model/ModelBakery.edit.java b/patches/minecraft/net/minecraft/client/resources/model/ModelBakery.edit.java index 8e2ea8e..6b2d423 100644 --- a/patches/minecraft/net/minecraft/client/resources/model/ModelBakery.edit.java +++ b/patches/minecraft/net/minecraft/client/resources/model/ModelBakery.edit.java @@ -7,13 +7,13 @@ > DELETE 2 @ 2 : 8 -> INSERT 6 : 7 @ 6 +> CHANGE 4 : 5 @ 4 : 7 -+ import java.nio.charset.StandardCharsets; +~ import java.nio.charset.StandardCharsets; -> DELETE 8 @ 8 : 9 +> DELETE 7 @ 7 : 8 -> INSERT 1 : 13 @ 1 +> INSERT 1 : 17 @ 1 + import java.util.Set; + @@ -27,6 +27,10 @@ + import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; + import net.lax1dude.eaglercraft.v1_8.log4j.Logger; + import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.BlockVertexIDs; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.VertexMarkerState; ++ import net.minecraft.client.Minecraft; > DELETE 9 @ 9 : 10 @@ -87,7 +91,39 @@ ~ + Item.itemRegistry.getNameForObject(item) + "\'"); ~ LOGGER.warn(exception); -> CHANGE 188 : 189 @ 188 : 189 +> INSERT 132 : 133 @ 132 + ++ boolean deferred = Minecraft.getMinecraft().gameSettings.shaders; + +> INSERT 9 : 34 @ 9 + ++ if (deferred) { ++ ModelBlock currentBlockModel = modelblock; ++ ResourceLocation currentResourceLocation = modelblockdefinition$variant.getModelLocation(); ++ Integer blockId = null; ++ do { ++ blockId = BlockVertexIDs.modelToID.get(currentResourceLocation.toString()); ++ if (blockId != null) { ++ break; ++ } ++ currentResourceLocation = currentBlockModel.getParentLocation(); ++ currentBlockModel = models.get(currentResourceLocation); ++ } while (currentBlockModel != null); ++ if (blockId != null) { ++ VertexMarkerState.markId = blockId.intValue(); ++ try { ++ weightedbakedmodel$builder.add( ++ this.bakeModel(modelblock, modelblockdefinition$variant.getRotation(), ++ modelblockdefinition$variant.isUvLocked()), ++ modelblockdefinition$variant.getWeight()); ++ } finally { ++ VertexMarkerState.markId = 0; ++ } ++ continue; ++ } ++ } + +> CHANGE 47 : 48 @ 47 : 48 ~ for (ModelResourceLocation modelresourcelocation : (List) arraylist) { diff --git a/patches/minecraft/net/minecraft/client/settings/GameSettings.edit.java b/patches/minecraft/net/minecraft/client/settings/GameSettings.edit.java index f400289..1b2264e 100644 --- a/patches/minecraft/net/minecraft/client/settings/GameSettings.edit.java +++ b/patches/minecraft/net/minecraft/client/settings/GameSettings.edit.java @@ -15,7 +15,7 @@ > DELETE 1 @ 1 : 3 -> INSERT 3 : 21 @ 3 +> INSERT 3 : 22 @ 3 + + import org.json.JSONArray; @@ -35,6 +35,7 @@ + import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants; + import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; + import net.lax1dude.eaglercraft.v1_8.log4j.Logger; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredConfig; > DELETE 5 @ 5 : 7 @@ -44,8 +45,9 @@ > DELETE 1 @ 1 : 9 -> CHANGE 23 : 26 @ 23 : 26 +> CHANGE 22 : 26 @ 22 : 26 +~ public int limitFramerate = 260; ~ public int clouds = 1; ~ public boolean fancyGraphics = false; ~ public int ambientOcclusion = 0; @@ -54,7 +56,9 @@ > DELETE 1 @ 1 : 2 -> CHANGE 36 : 37 @ 36 : 37 +> DELETE 17 @ 17 : 28 + +> CHANGE 8 : 9 @ 8 : 9 ~ public KeyBinding keyBindSprint = new KeyBinding("key.sprint", KeyboardConstants.KEY_R, "key.categories.movement"); @@ -73,7 +77,7 @@ ~ public int guiScale = 3; -> INSERT 3 : 12 @ 3 +> INSERT 3 : 16 @ 3 + public boolean hudFps = true; + public boolean hudCoords = true; @@ -84,6 +88,10 @@ + public boolean chunkFix = true; + public boolean fog = true; + public int fxaa = 0; ++ public boolean shaders = false; ++ public boolean shadersAODisable = false; ++ public EaglerDeferredConfig deferredShaderConf = new EaglerDeferredConfig(); ++ public int fastMath = 1; > CHANGE 1 : 2 @ 1 : 2 @@ -113,18 +121,18 @@ ~ : HString.format("%c", new Object[] { Character.valueOf((char) (parInt1 - 256)) }) -> DELETE 83 @ 83 : 84 +> DELETE 76 @ 76 : 99 -> DELETE 4 @ 4 : 5 - -> INSERT 45 : 47 @ 45 +> INSERT 35 : 37 @ 35 + this.mc.loadingScreen.eaglerShow(I18n.format("resourcePack.load.refreshing"), + I18n.format("resourcePack.load.pleaseWait")); -> DELETE 58 @ 58 : 75 +> DELETE 18 @ 18 : 38 -> INSERT 13 : 53 @ 13 +> DELETE 20 @ 20 : 37 + +> INSERT 13 : 57 @ 13 + if (parOptions == GameSettings.Options.HUD_FPS) { + this.hudFps = !this.hudFps; @@ -166,10 +174,20 @@ + this.mc.toggleFullscreen(); + } + ++ if (parOptions == GameSettings.Options.FAST_MATH) { ++ this.fastMath = (this.fastMath + parInt1) % 3; ++ } ++ -> DELETE 54 @ 54 : 60 +> CHANGE 23 : 24 @ 23 : 34 -> INSERT 12 : 30 @ 12 +~ : 0.0F))))))))))); + +> DELETE 20 @ 20 : 26 + +> DELETE 2 @ 2 : 4 + +> INSERT 8 : 26 @ 8 + case HUD_COORDS: + return this.hudCoords; @@ -226,7 +244,9 @@ ~ + "%") ~ : "yee")))))))))))); -> INSERT 28 : 36 @ 28 +> DELETE 11 @ 11 : 19 + +> INSERT 9 : 19 @ 9 + } else if (parOptions == GameSettings.Options.FXAA) { + if (this.fxaa == 0) { @@ -236,6 +256,8 @@ + } else { + return s + I18n.format("options.off"); + } ++ } else if (parOptions == GameSettings.Options.FAST_MATH) { ++ return s + I18n.format("options.fastMath." + this.fastMath); > CHANGE 7 : 9 @ 7 : 8 @@ -269,52 +291,99 @@ > DELETE 4 @ 4 : 8 -> INSERT 116 : 153 @ 116 +> CHANGE 52 : 54 @ 52 : 54 -+ if (astring[0].equals("hudFps")) { -+ this.hudFps = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("hudWorld")) { -+ this.hudWorld = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("hudCoords")) { -+ this.hudCoords = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("hudPlayer")) { -+ this.hudPlayer = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("hudStats")) { -+ this.hudStats = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("hud24h")) { -+ this.hud24h = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("chunkFix")) { -+ this.chunkFix = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("fog")) { -+ this.fog = astring[1].equals("true"); -+ } -+ -+ if (astring[0].equals("fxaa")) { -+ this.fxaa = (astring[1].equals("true") || astring[1].equals("false")) ? 0 -+ : Integer.parseInt(astring[1]); -+ } -+ +~ if (astring[0].equals("forceUnicodeFont")) { +~ this.forceUnicodeFont = astring[1].equals("true"); -> INSERT 6 : 8 @ 6 +> CHANGE 2 : 4 @ 2 : 4 +~ if (astring[0].equals("allowBlockAlternatives")) { +~ this.allowBlockAlternatives = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("reducedDebugInfo")) { +~ this.reducedDebugInfo = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("useNativeTransport")) { +~ this.field_181150_U = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("entityShadows")) { +~ this.field_181151_V = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hudFps")) { +~ this.hudFps = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hudWorld")) { +~ this.hudWorld = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hudCoords")) { +~ this.hudCoords = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hudPlayer")) { +~ this.hudPlayer = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hudStats")) { +~ this.hudStats = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("hud24h")) { +~ this.hud24h = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("chunkFix")) { +~ this.chunkFix = astring[1].equals("true"); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("fog")) { +~ this.fog = astring[1].equals("true"); + +> CHANGE 2 : 5 @ 2 : 4 + +~ if (astring[0].equals("fxaa")) { +~ this.fxaa = (astring[1].equals("true") || astring[1].equals("false")) ? 0 +~ : Integer.parseInt(astring[1]); + +> CHANGE 2 : 4 @ 2 : 4 + +~ if (astring[0].equals("fastMath")) { +~ this.fastMath = Integer.parseInt(astring[1]); + +> DELETE 2 @ 2 : 6 + +> INSERT 6 : 12 @ 6 + ++ if (astring[0].equals("shaders")) { ++ this.shaders = astring[1].equals("true"); ++ } ++ + Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + -> DELETE 17 @ 17 : 18 +> INSERT 11 : 13 @ 11 + ++ ++ deferredShaderConf.readOption(astring[0], astring[1]); + +> DELETE 6 @ 6 : 7 > CHANGE 12 : 14 @ 12 : 13 @@ -330,7 +399,9 @@ > DELETE 1 @ 1 : 2 -> INSERT 29 : 38 @ 29 +> DELETE 13 @ 13 : 24 + +> INSERT 5 : 16 @ 5 + printwriter.println("hudFps:" + this.hudFps); + printwriter.println("hudWorld:" + this.hudWorld); @@ -341,13 +412,20 @@ + printwriter.println("chunkFix:" + this.chunkFix); + printwriter.println("fog:" + this.fog); + printwriter.println("fxaa:" + this.fxaa); ++ printwriter.println("fastMath:" + this.fastMath); ++ printwriter.println("shaders:" + this.shaders); > INSERT 5 : 7 @ 5 + Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + -> INSERT 11 : 13 @ 11 +> INSERT 10 : 12 @ 10 + ++ deferredShaderConf.writeOptions(printwriter); ++ + +> INSERT 1 : 3 @ 1 + + EagRuntime.setStorage("g", bao.toByteArray()); @@ -383,6 +461,6 @@ ~ HUD_WORLD("options.hud.world", false, true), HUD_PLAYER("options.hud.player", false, true), ~ HUD_24H("options.hud.24h", false, true), CHUNK_FIX("options.chunkFix", false, true), ~ FOG("options.fog", false, true), FXAA("options.fxaa", false, false), -~ FULLSCREEN("options.fullscreen", false, true); +~ FULLSCREEN("options.fullscreen", false, true), FAST_MATH("options.fastMath", false, false); > EOF diff --git a/patches/minecraft/net/minecraft/entity/Entity.edit.java b/patches/minecraft/net/minecraft/entity/Entity.edit.java index b898c7b..6de3ce4 100644 --- a/patches/minecraft/net/minecraft/entity/Entity.edit.java +++ b/patches/minecraft/net/minecraft/entity/Entity.edit.java @@ -5,17 +5,21 @@ # Version: 1.0 # Author: lax1dude -> CHANGE 3 : 6 @ 3 : 5 +> CHANGE 3 : 8 @ 3 : 5 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; ~ import net.lax1dude.eaglercraft.v1_8.HString; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; +~ > INSERT 1 : 2 @ 1 + -> DELETE 7 @ 7 : 10 +> CHANGE 7 : 8 @ 7 : 10 + +~ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; > DELETE 4 @ 4 : 7 @@ -146,4 +150,33 @@ > DELETE 51 @ 51 : 63 +> INSERT 22 : 48 @ 22 + ++ ++ public void renderDynamicLightsEagler(float partialTicks, boolean isInFrustum) { ++ double entityX = prevPosX + (posX - prevPosX) * (double) partialTicks; ++ double entityY = prevPosY + (posY - prevPosY) * (double) partialTicks; ++ double entityZ = prevPosZ + (posZ - prevPosZ) * (double) partialTicks; ++ double entityX2 = entityX - TileEntityRendererDispatcher.staticPlayerX; ++ double entityY2 = entityY - TileEntityRendererDispatcher.staticPlayerY; ++ double entityZ2 = entityZ - TileEntityRendererDispatcher.staticPlayerZ; ++ if (Math.sqrt(entityX2 * entityX2 + entityY2 * entityY2 + entityZ2 * entityZ2) < 48.0 * 48.0) { ++ renderDynamicLightsEaglerAt(entityX, entityY, entityZ, entityX2, entityY2, entityZ2, partialTicks, ++ isInFrustum); ++ } ++ } ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ if (this.isBurning()) { ++ float size = Math.max(width, height); ++ if (size < 1.0f && !isInFrustum) { ++ return; ++ } ++ float mag = 5.0f * size; ++ DynamicLightManager.renderDynamicLight("entity_" + entityId + "_fire", entityX, entityY + height * 0.75, ++ entityZ, mag, 0.487f * mag, 0.1411f * mag, false); ++ } ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/entity/EntityLivingBase.edit.java b/patches/minecraft/net/minecraft/entity/EntityLivingBase.edit.java index 6f50130..5044b1f 100644 --- a/patches/minecraft/net/minecraft/entity/EntityLivingBase.edit.java +++ b/patches/minecraft/net/minecraft/entity/EntityLivingBase.edit.java @@ -17,7 +17,9 @@ ~ import com.google.common.collect.Maps; ~ -> DELETE 2 @ 2 : 3 +> CHANGE 2 : 3 @ 2 : 3 + +~ import net.minecraft.client.Minecraft; > DELETE 1 @ 1 : 5 @@ -108,4 +110,18 @@ ~ return false; +> INSERT 60 : 71 @ 60 + ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ Minecraft mc = Minecraft.getMinecraft(); ++ if (mc.gameSettings.thirdPersonView != 0 || !(mc.getRenderViewEntity() == this)) { ++ Minecraft.getMinecraft().entityRenderer.renderHeldItemLight(this, 1.0f); ++ } ++ } ++ + > EOF diff --git a/patches/minecraft/net/minecraft/entity/item/EntityItem.edit.java b/patches/minecraft/net/minecraft/entity/item/EntityItem.edit.java index c93b677..435748e 100644 --- a/patches/minecraft/net/minecraft/entity/item/EntityItem.edit.java +++ b/patches/minecraft/net/minecraft/entity/item/EntityItem.edit.java @@ -10,7 +10,11 @@ + import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; + import net.lax1dude.eaglercraft.v1_8.log4j.Logger; -> DELETE 5 @ 5 : 6 +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.client.Minecraft; + +> DELETE 4 @ 4 : 5 > DELETE 2 @ 2 : 3 @@ -26,4 +30,16 @@ > DELETE 11 @ 11 : 19 +> INSERT 66 : 75 @ 66 + ++ ++ public boolean eaglerEmissiveFlag = false; ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ eaglerEmissiveFlag = Minecraft.getMinecraft().entityRenderer.renderItemEntityLight(this, 0.1f); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/entity/item/EntityItemFrame.edit.java b/patches/minecraft/net/minecraft/entity/item/EntityItemFrame.edit.java index b06f3bc..c8f3e4d 100644 --- a/patches/minecraft/net/minecraft/entity/item/EntityItemFrame.edit.java +++ b/patches/minecraft/net/minecraft/entity/item/EntityItemFrame.edit.java @@ -5,8 +5,24 @@ # Version: 1.0 # Author: lax1dude -> DELETE 41 @ 41 : 46 +> INSERT 2 : 3 @ 2 + ++ import net.minecraft.client.Minecraft; + +> DELETE 39 @ 39 : 44 > DELETE 126 @ 126 : 139 +> INSERT 6 : 15 @ 6 + ++ ++ public boolean eaglerEmissiveFlag = false; ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ eaglerEmissiveFlag = Minecraft.getMinecraft().entityRenderer.renderItemEntityLight(this, 0.1f); ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/entity/item/EntityTNTPrimed.edit.java b/patches/minecraft/net/minecraft/entity/item/EntityTNTPrimed.edit.java index 9b567eb..9761db8 100644 --- a/patches/minecraft/net/minecraft/entity/item/EntityTNTPrimed.edit.java +++ b/patches/minecraft/net/minecraft/entity/item/EntityTNTPrimed.edit.java @@ -5,8 +5,26 @@ # Version: 1.0 # Author: lax1dude -> DELETE 61 @ 61 : 64 +> INSERT 2 : 3 @ 2 + ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; + +> DELETE 59 @ 59 : 62 > DELETE 8 @ 8 : 13 +> INSERT 15 : 26 @ 15 + ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ if (fuse / 5 % 2 == 0) { ++ float dynamicLightMag = 10.0f; ++ DynamicLightManager.renderDynamicLight("entity_" + getEntityId() + "_tnt_flash", entityX, entityY + 0.5, ++ entityZ, dynamicLightMag, dynamicLightMag * 0.7792f, dynamicLightMag * 0.618f, false); ++ } ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/entity/item/EntityXPOrb.edit.java b/patches/minecraft/net/minecraft/entity/item/EntityXPOrb.edit.java index 614c619..e98ff35 100644 --- a/patches/minecraft/net/minecraft/entity/item/EntityXPOrb.edit.java +++ b/patches/minecraft/net/minecraft/entity/item/EntityXPOrb.edit.java @@ -5,6 +5,24 @@ # Version: 1.0 # Author: lax1dude -> DELETE 160 @ 160 : 174 +> INSERT 2 : 3 @ 2 + ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; + +> DELETE 158 @ 158 : 172 + +> INSERT 33 : 44 @ 33 + ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ if (isInFrustum && renderX * renderX + renderY * renderY + renderZ * renderZ < 150.0) { ++ float mag = 0.025f; ++ DynamicLightManager.renderDynamicLight("entity_" + getEntityId() + "_xp", entityX, entityY + 0.2, entityZ, ++ mag * 0.3f, mag, mag * 0.2f, false); ++ } ++ } > EOF diff --git a/patches/minecraft/net/minecraft/entity/monster/EntityBlaze.edit.java b/patches/minecraft/net/minecraft/entity/monster/EntityBlaze.edit.java index 5049870..7b4bbb2 100644 --- a/patches/minecraft/net/minecraft/entity/monster/EntityBlaze.edit.java +++ b/patches/minecraft/net/minecraft/entity/monster/EntityBlaze.edit.java @@ -5,7 +5,11 @@ # Version: 1.0 # Author: lax1dude -> DELETE 4 @ 4 : 14 +> INSERT 2 : 3 @ 2 + ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; + +> DELETE 2 @ 2 : 12 > DELETE 2 @ 2 : 3 @@ -28,6 +32,12 @@ ~ this.posY + this.rand.nextDouble() * (double) this.height, ~ this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.width, 0.0D, 0.0D, 0.0D, new int[0]); -> DELETE 67 @ 67 : 145 +> CHANGE 67 : 72 @ 67 : 144 + +~ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, +~ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { +~ float mag = 5.0f; +~ DynamicLightManager.renderDynamicLight("entity_" + getEntityId() + "_blaze", entityX, entityY + 0.75, entityZ, +~ mag, 0.487f * mag, 0.1411f * mag, false); > EOF diff --git a/patches/minecraft/net/minecraft/entity/monster/EntityCreeper.edit.java b/patches/minecraft/net/minecraft/entity/monster/EntityCreeper.edit.java index 6149222..972237a 100644 --- a/patches/minecraft/net/minecraft/entity/monster/EntityCreeper.edit.java +++ b/patches/minecraft/net/minecraft/entity/monster/EntityCreeper.edit.java @@ -5,7 +5,13 @@ # Version: 1.0 # Author: lax1dude -> DELETE 4 @ 4 : 13 +> INSERT 2 : 5 @ 2 + ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; ++ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; ++ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; + +> DELETE 2 @ 2 : 11 > DELETE 1 @ 1 : 4 @@ -17,4 +23,20 @@ > DELETE 5 @ 5 : 16 +> INSERT 15 : 28 @ 15 + ++ ++ protected void renderDynamicLightsEaglerAt(double entityX, double entityY, double entityZ, double renderX, ++ double renderY, double renderZ, float partialTicks, boolean isInFrustum) { ++ super.renderDynamicLightsEaglerAt(entityX, entityY, entityZ, renderX, renderY, renderZ, partialTicks, ++ isInFrustum); ++ float ff = getCreeperFlashIntensity(partialTicks); ++ if ((int) (ff * 10.0F) % 2 != 0) { ++ float dynamicLightMag = 7.0f; ++ DynamicLightManager.renderDynamicLight("entity_" + getEntityId() + "_creeper_flash", entityX, entityY + 1.0, ++ entityZ, dynamicLightMag, dynamicLightMag * 0.7792f, dynamicLightMag * 0.618f, false); ++ DeferredStateManager.setEmissionConstant(1.0f); ++ } ++ } + > EOF diff --git a/patches/minecraft/net/minecraft/entity/monster/EntityEnderman.edit.java b/patches/minecraft/net/minecraft/entity/monster/EntityEnderman.edit.java index 6f87ce9..97297f0 100644 --- a/patches/minecraft/net/minecraft/entity/monster/EntityEnderman.edit.java +++ b/patches/minecraft/net/minecraft/entity/monster/EntityEnderman.edit.java @@ -7,16 +7,21 @@ > DELETE 2 @ 2 : 7 -> CHANGE 1 : 5 @ 1 : 2 +> CHANGE 1 : 6 @ 1 : 2 ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DynamicLightManager; ~ ~ import com.google.common.collect.Sets; ~ > DELETE 1 @ 1 : 2 -> DELETE 4 @ 4 : 12 +> INSERT 1 : 2 @ 1 + ++ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; + +> DELETE 3 @ 3 : 11 > DELETE 1 @ 1 : 4 diff --git a/patches/minecraft/net/minecraft/util/BlockPos.edit.java b/patches/minecraft/net/minecraft/util/BlockPos.edit.java index 9a34da5..87b6220 100644 --- a/patches/minecraft/net/minecraft/util/BlockPos.edit.java +++ b/patches/minecraft/net/minecraft/util/BlockPos.edit.java @@ -15,9 +15,87 @@ > DELETE 1 @ 1 : 5 -> INSERT 103 : 120 @ 103 +> INSERT 55 : 65 @ 55 -+ public BlockPos offsetFaster(EnumFacing facing, MutableBlockPos ret) { ++ /** ++ * eagler ++ */ ++ public BlockPos up(BlockPos dst) { ++ dst.x = x; ++ dst.y = y + 1; ++ dst.z = z; ++ return dst; ++ } ++ + +> INSERT 8 : 18 @ 8 + ++ /** ++ * eagler ++ */ ++ public BlockPos down(BlockPos dst) { ++ dst.x = x; ++ dst.y = y - 1; ++ dst.z = z; ++ return dst; ++ } ++ + +> INSERT 8 : 18 @ 8 + ++ /** ++ * eagler ++ */ ++ public BlockPos north(BlockPos dst) { ++ dst.x = x; ++ dst.y = y; ++ dst.z = z - 1; ++ return dst; ++ } ++ + +> INSERT 8 : 18 @ 8 + ++ /** ++ * eagler ++ */ ++ public BlockPos south(BlockPos dst) { ++ dst.x = x; ++ dst.y = y; ++ dst.z = z + 1; ++ return dst; ++ } ++ + +> INSERT 12 : 22 @ 12 + ++ /** ++ * eagler ++ */ ++ public BlockPos west(BlockPos dst) { ++ dst.x = x - 1; ++ dst.y = y; ++ dst.z = z; ++ return dst; ++ } ++ + +> INSERT 8 : 18 @ 8 + ++ /** ++ * eagler ++ */ ++ public BlockPos east(BlockPos dst) { ++ dst.x = x + 1; ++ dst.y = y; ++ dst.z = z; ++ return dst; ++ } ++ + +> INSERT 4 : 21 @ 4 + ++ public BlockPos offsetFaster(EnumFacing facing, BlockPos ret) { + ret.x = this.getX() + facing.getFrontOffsetX(); + ret.y = this.getY() + facing.getFrontOffsetY(); + ret.z = this.getZ() + facing.getFrontOffsetZ(); @@ -27,7 +105,7 @@ + /** + * only use with a regular "net.minecraft.util.BlockPos"! + */ -+ public BlockPos offsetEvenFaster(EnumFacing facing, MutableBlockPos ret) { ++ public BlockPos offsetEvenFaster(EnumFacing facing, BlockPos ret) { + ret.x = this.x + facing.getFrontOffsetX(); + ret.y = this.y + facing.getFrontOffsetY(); + ret.z = this.z + facing.getFrontOffsetZ(); @@ -35,7 +113,12 @@ + } + -> DELETE 108 @ 108 : 111 +> CHANGE 2 : 4 @ 2 : 4 + +~ : new BlockPos(this.x + facing.getFrontOffsetX() * n, this.y + facing.getFrontOffsetY() * n, +~ this.z + facing.getFrontOffsetZ() * n); + +> DELETE 104 @ 104 : 107 > CHANGE 6 : 7 @ 6 : 10 diff --git a/patches/minecraft/net/minecraft/util/EnumWorldBlockLayer.edit.java b/patches/minecraft/net/minecraft/util/EnumWorldBlockLayer.edit.java new file mode 100644 index 0000000..2c2b6f8 --- /dev/null +++ b/patches/minecraft/net/minecraft/util/EnumWorldBlockLayer.edit.java @@ -0,0 +1,13 @@ + +# Eagler Context Redacted Diff +# Copyright (c) 2023 lax1dude. All rights reserved. + +# Version: 1.0 +# Author: lax1dude + +> CHANGE 3 : 5 @ 3 : 4 + +~ SOLID("Solid"), CUTOUT_MIPPED("Mipped Cutout"), CUTOUT("Cutout"), TRANSLUCENT("Translucent"), +~ REALISTIC_WATER("EaglerShaderWater"), GLASS_HIGHLIGHTS("EaglerShaderGlassHighlights"); + +> EOF diff --git a/patches/minecraft/net/minecraft/util/Timer.edit.java b/patches/minecraft/net/minecraft/util/Timer.edit.java index 9e5d86d..8700198 100644 --- a/patches/minecraft/net/minecraft/util/Timer.edit.java +++ b/patches/minecraft/net/minecraft/util/Timer.edit.java @@ -7,4 +7,14 @@ > DELETE 3 @ 3 : 4 +> CHANGE 53 : 60 @ 53 : 54 + +~ int fastMathSetting = Minecraft.getMinecraft().gameSettings.fastMath; +~ if (fastMathSetting > 0) { +~ float f = fastMathSetting == 2 ? 16.0f : 64.0f; +~ this.renderPartialTicks = ((int) (this.elapsedPartialTicks * f) / f); +~ } else { +~ this.renderPartialTicks = this.elapsedPartialTicks; +~ } + > EOF diff --git a/patches/minecraft/net/minecraft/world/ChunkCache.edit.java b/patches/minecraft/net/minecraft/world/ChunkCache.edit.java index 6625041..7573eda 100644 --- a/patches/minecraft/net/minecraft/world/ChunkCache.edit.java +++ b/patches/minecraft/net/minecraft/world/ChunkCache.edit.java @@ -7,4 +7,8 @@ > DELETE 8 @ 8 : 12 +> CHANGE 77 : 78 @ 77 : 78 + +~ return Chunk.getNoSkyLightValue(); + > EOF diff --git a/patches/minecraft/net/minecraft/world/World.edit.java b/patches/minecraft/net/minecraft/world/World.edit.java index 8146b68..aa78f32 100644 --- a/patches/minecraft/net/minecraft/world/World.edit.java +++ b/patches/minecraft/net/minecraft/world/World.edit.java @@ -23,7 +23,15 @@ + import com.google.common.collect.Sets; + -> DELETE 18 @ 18 : 19 +> INSERT 8 : 9 @ 8 + ++ import net.minecraft.client.Minecraft; + +> INSERT 4 : 5 @ 4 + ++ import net.minecraft.entity.EntityLivingBase; + +> DELETE 6 @ 6 : 7 > DELETE 12 @ 12 : 27 @@ -79,7 +87,45 @@ > DELETE 1 @ 1 : 21 -> DELETE 1404 @ 1404 : 1462 +> CHANGE 117 : 118 @ 117 : 118 + +~ return Chunk.getNoSkyLightValue(); + +> INSERT 896 : 927 @ 896 + ++ int fastMathSetting = Minecraft.getMinecraft().gameSettings.fastMath; ++ if (fastMathSetting > 0) { ++ double posPrec = fastMathSetting == 2 ? 256.0 : 1024.0; ++ float rotPrec = fastMathSetting == 2 ? 64.0f : 128.0f; ++ double velPrec = fastMathSetting == 2 ? 2048.0 : 4096.0; ++ entityIn.lastTickPosX = (long) (entityIn.lastTickPosX * posPrec) / posPrec; ++ entityIn.lastTickPosY = (long) (entityIn.lastTickPosY * posPrec) / posPrec; ++ entityIn.lastTickPosZ = (long) (entityIn.lastTickPosZ * posPrec) / posPrec; ++ entityIn.prevPosX = (int) (entityIn.prevPosX * posPrec) / posPrec; ++ entityIn.prevPosY = (int) (entityIn.prevPosY * posPrec) / posPrec; ++ entityIn.prevPosZ = (int) (entityIn.prevPosZ * posPrec) / posPrec; ++ entityIn.posX = (int) (entityIn.posX * posPrec) / posPrec; ++ entityIn.posY = (int) (entityIn.posY * posPrec) / posPrec; ++ entityIn.posZ = (int) (entityIn.posZ * posPrec) / posPrec; ++ entityIn.prevRotationPitch = (int) (entityIn.prevRotationPitch * rotPrec) / rotPrec; ++ entityIn.prevRotationYaw = (int) (entityIn.prevRotationYaw * rotPrec) / rotPrec; ++ entityIn.rotationPitch = (int) (entityIn.rotationPitch * rotPrec) / rotPrec; ++ entityIn.rotationYaw = (int) (entityIn.rotationYaw * rotPrec) / rotPrec; ++ if (entityIn instanceof EntityLivingBase) { ++ EntityLivingBase l = (EntityLivingBase) entityIn; ++ l.prevRotationYawHead = (int) (l.prevRotationYawHead * rotPrec) / rotPrec; ++ l.rotationYawHead = (int) (l.rotationYawHead * rotPrec) / rotPrec; ++ l.prevRenderYawOffset = (int) (l.prevRenderYawOffset * rotPrec) / rotPrec; ++ l.renderYawOffset = (int) (l.renderYawOffset * rotPrec) / rotPrec; ++ l.prevRotationPitch = (int) (l.prevRotationPitch * rotPrec) / rotPrec; ++ l.rotationPitch = (int) (l.rotationPitch * rotPrec) / rotPrec; ++ } ++ entityIn.motionX = (int) (entityIn.motionX * velPrec) / velPrec; ++ entityIn.motionY = (int) (entityIn.motionY * velPrec) / velPrec; ++ entityIn.motionZ = (int) (entityIn.motionZ * velPrec) / velPrec; ++ } + +> DELETE 390 @ 390 : 448 > DELETE 40 @ 40 : 64 diff --git a/patches/minecraft/net/minecraft/world/chunk/Chunk.edit.java b/patches/minecraft/net/minecraft/world/chunk/Chunk.edit.java index 139c0bc..99c8b06 100644 --- a/patches/minecraft/net/minecraft/world/chunk/Chunk.edit.java +++ b/patches/minecraft/net/minecraft/world/chunk/Chunk.edit.java @@ -13,7 +13,7 @@ ~ import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -> CHANGE 1 : 7 @ 1 : 2 +> CHANGE 1 : 8 @ 1 : 2 ~ ~ import com.google.common.base.Predicate; @@ -21,6 +21,7 @@ ~ ~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; ~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; > DELETE 18 @ 18 : 19 @@ -101,7 +102,32 @@ > DELETE 33 @ 33 : 37 -> CHANGE 251 : 253 @ 251 : 253 +> CHANGE 24 : 26 @ 24 : 25 + +~ return extendedblockstorage == null +~ ? (this.canSeeSky(blockpos) ? enumskyblock.defaultLightValue : getNoSkyLightValue()) + +> CHANGE 1 : 2 @ 1 : 2 + +~ ? (this.worldObj.provider.getHasNoSky() ? getNoSkyLightValue() + +> CHANGE 35 : 36 @ 35 : 36 + +~ : getNoSkyLightValue(); + +> CHANGE 1 : 3 @ 1 : 2 + +~ int i1 = this.worldObj.provider.getHasNoSky() ? getNoSkyLightValue() +~ : extendedblockstorage.getExtSkylightValue(j, k & 15, l); + +> INSERT 10 : 14 @ 10 + ++ public static int getNoSkyLightValue() { ++ return DeferredStateManager.isDeferredRenderer() ? 5 : 0; ++ } ++ + +> CHANGE 176 : 178 @ 176 : 178 ~ && (predicate == null || predicate.apply((T) entity))) { ~ list.add((T) entity); diff --git a/patches/resources/assets/minecraft/lang/en_US.edit.lang b/patches/resources/assets/minecraft/lang/en_US.edit.lang index d5ab201..ec10036 100644 --- a/patches/resources/assets/minecraft/lang/en_US.edit.lang +++ b/patches/resources/assets/minecraft/lang/en_US.edit.lang @@ -12,7 +12,7 @@ ~ eaglercraft.recording.start=Record Screen... ~ eaglercraft.soundCategory.voice=Voice -> INSERT 1 : 68 @ 1 +> INSERT 1 : 179 @ 1 + eaglercraft.resourcePack.prompt.title=What do you want to do with '%s'? + eaglercraft.resourcePack.prompt.text=Tip: Hold Shift to skip this screen when selecting a resource pack! @@ -71,6 +71,10 @@ + eaglercraft.options.fog=Fog + eaglercraft.options.fxaa=FXAA Antialiasing + eaglercraft.options.fxaa.auto=Auto ++ eaglercraft.options.fastMath=Fast Math ++ eaglercraft.options.fastMath.0=OFF ++ eaglercraft.options.fastMath.1=Low ++ eaglercraft.options.fastMath.2=High + + eaglercraft.key.function=Function + eaglercraft.key.zoomCamera=Zoom Camera @@ -81,6 +85,113 @@ + eaglercraft.auth.required=Authentication Required + eaglercraft.auth.continue=Join Server + ++ eaglercraft.shaders.gui.optionsButton=Shaders ++ eaglercraft.shaders.gui.title=Shaders ++ eaglercraft.shaders.gui.enable=Enable Shaders ++ eaglercraft.shaders.gui.headerTier1=Simple Effects (fast) ++ eaglercraft.shaders.gui.headerTier2=Intermediate Effects (not as fast) ++ ++ ++ eaglercraft.shaders.gui.option.WAVING_BLOCKS.label=Waving Grass ++ ++ eaglercraft.shaders.gui.option.WAVING_BLOCKS.desc.0=The classic vanilla shader that make grass and leaf blocks move with the wind ++ eaglercraft.shaders.gui.option.WAVING_BLOCKS.desc.2=ON: slower, complex control flow ++ eaglercraft.shaders.gui.option.WAVING_BLOCKS.desc.3=OFF: faster, simple control flow ++ ++ eaglercraft.shaders.gui.option.DYNAMIC_LIGHTS.label=Dynamic Lights ++ ++ eaglercraft.shaders.gui.option.DYNAMIC_LIGHTS.desc.0=Items like torches, glowstone, jack o'lanterns, etc. light up the area around them when they are held or dropped ++ eaglercraft.shaders.gui.option.DYNAMIC_LIGHTS.desc.2=This feature usually does not affect FPS unless there is a large number of dynamic light sources close to the player ++ eaglercraft.shaders.gui.option.DYNAMIC_LIGHTS.desc.4=ON: enable dynamic lights ++ eaglercraft.shaders.gui.option.DYNAMIC_LIGHTS.desc.5=OFF: disable dynamic lights ++ ++ eaglercraft.shaders.gui.option.GLOBAL_AMBIENT_OCCLUSION.label=Global SSAO ++ ++ eaglercraft.shaders.gui.option.GLOBAL_AMBIENT_OCCLUSION.desc.0=Applies realistic screenspace ambient occlusion (SSAO) to areas of the screen that vanilla Minecraft's default "Smooth Lighting" feature cannot ++ eaglercraft.shaders.gui.option.GLOBAL_AMBIENT_OCCLUSION.desc.2=This effect can greatly reduce lag spikes caused by chunk updates in exchange for a decreased maximum FPS when standing still ++ eaglercraft.shaders.gui.option.GLOBAL_AMBIENT_OCCLUSION.desc.4=ON: use SSAO ++ eaglercraft.shaders.gui.option.GLOBAL_AMBIENT_OCCLUSION.desc.5=OFF: use vanilla ++ ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.label=Sun Shadow Dist ++ ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.0=Makes the sun and moon cast shadows on the world, you almost definitely want to enable this ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.2=0: off ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.3=1: 16 blocks ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.4=2: 32 blocks ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.5=3: 64 blocks ++ eaglercraft.shaders.gui.option.SHADOWS_SUN.desc.6=4: 128 blocks ++ ++ eaglercraft.shaders.gui.option.SHADOWS_COLORED.label=Color Shadow ++ ++ eaglercraft.shaders.gui.option.SHADOWS_COLORED.desc.0=Makes blocks like stained glass cast colored shadows ++ eaglercraft.shaders.gui.option.SHADOWS_COLORED.desc.2=ON: colored shadows (slower) ++ eaglercraft.shaders.gui.option.SHADOWS_COLORED.desc.3=OFF: grayscale shadows (faster) ++ ++ eaglercraft.shaders.gui.option.SHADOWS_SMOOTHED.label=Smooth Shadow ++ ++ eaglercraft.shaders.gui.option.SHADOWS_SMOOTHED.desc.0=Smooths out the edges of sun and dynamic light shadows to get rid of aliasing ++ eaglercraft.shaders.gui.option.SHADOWS_SMOOTHED.desc.2=ON: smooth shadows (slower) ++ eaglercraft.shaders.gui.option.SHADOWS_SMOOTHED.desc.3=OFF: aliased shadows (faster) ++ ++ eaglercraft.shaders.gui.option.REFLECTIONS_PARABOLOID.label=Env. Mapping ++ ++ eaglercraft.shaders.gui.option.REFLECTIONS_PARABOLOID.desc.0=Renders an environment map, allows transparent blocks and moving entities to reflect their surroundings ++ eaglercraft.shaders.gui.option.REFLECTIONS_PARABOLOID.desc.2=Uses dual paraboloid mapping, only 2 render passes are required to render all reflections, instead of a full 6 render passes like a conventional cube map ++ eaglercraft.shaders.gui.option.REFLECTIONS_PARABOLOID.desc.4=ON: render env. map (slower) ++ eaglercraft.shaders.gui.option.REFLECTIONS_PARABOLOID.desc.5=OFF: disable env. map (faster) ++ ++ eaglercraft.shaders.gui.option.REALISTIC_WATER.label=Realistic Water ++ ++ eaglercraft.shaders.gui.option.REALISTIC_WATER.desc.0=Makes water realistic, adds reflection and refraction effects, uses raytracing ++ eaglercraft.shaders.gui.option.REALISTIC_WATER.desc.2=ON: render realistic water (slower) ++ eaglercraft.shaders.gui.option.REALISTIC_WATER.desc.3=OFF: render vanilla water (faster) ++ ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.label=God Rays ++ ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.0=Render god rays (light shafts) for sunlight and moonlight shadows ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.2=ON: render god rays (slower) ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.3=OFF: disable god rays (faster) ++ ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.label=Raytracing ++ ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.0=Renders raytraced reflections off of blocks ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.2=Thanks to some advanced optimizations, this feature only has a small impact on FPS and is compatible with old hardware ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.4=Both raymarching and raytracing are employed, raymarching is initially used to locate and track groups of pixels on the screen to reflect, then raytracing is used to reproject that data between multiple frames so the raymarching process only has to be repeated once or twice every few seconds ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.6=ON: enable raytracing (slower) ++ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.7=OFF: disable raytracing (faster) ++ ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.0=Render god rays (light shafts) for sunlight and moonlight shadows ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.2=ON: render god rays (slower) ++ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.3=OFF: disable god rays (faster) ++ ++ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.label=Lens Distort ++ ++ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.desc.0=Renders chromatic abberation and lens distorion ++ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.desc.2=ON: render lens distortion (slower) ++ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.desc.3=OFF: disable lens distortion (faster) ++ ++ eaglercraft.shaders.gui.option.POST_LENS_FLARES.label=Lens Flares ++ ++ eaglercraft.shaders.gui.option.POST_LENS_FLARES.desc.0=Renders filmic lens flares for the sun ++ eaglercraft.shaders.gui.option.POST_LENS_FLARES.desc.2=ON: render lens flares (slower) ++ eaglercraft.shaders.gui.option.POST_LENS_FLARES.desc.3=OFF: disable lens flares (faster) ++ ++ eaglercraft.shaders.gui.option.POST_BLOOM.label=Bloom ++ ++ eaglercraft.shaders.gui.option.POST_BLOOM.desc.0=Renders bloom for emissive textures and sunlight ++ eaglercraft.shaders.gui.option.POST_BLOOM.desc.2=ON: render bloom (slower) ++ eaglercraft.shaders.gui.option.POST_BLOOM.desc.3=OFF: disable bloom (faster) ++ ++ eaglercraft.shaders.gui.option.POST_FXAA.label=FXAA ++ ++ eaglercraft.shaders.gui.option.POST_FXAA.desc.0=Applies FXAA antialiasing in post processing ++ eaglercraft.shaders.gui.option.POST_FXAA.desc.2=This is the preferred antialiasing method for minecraft, as classical MSAA cannot antialias the pixels of upscaled textures ++ eaglercraft.shaders.gui.option.POST_FXAA.desc.4=ON: enable fxaa (slower) ++ eaglercraft.shaders.gui.option.POST_FXAA.desc.5=OFF: disable fxaa (faster) ++ ++ eaglercraft.shaders.gui.unsupported.title=Shaders are unavailable on this device! ++ eaglercraft.shaders.gui.unsupported.reason.hdrFramebuffer=Reason: No HDR render target support ++ > CHANGE 468 : 469 @ 468 : 469 diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index 5650ce6..5e3e84c 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -54,7 +54,8 @@ public class PlatformApplication { } public static String getClipboard() { - return glfwGetClipboardString(win); + String str = glfwGetClipboardString(win); + return str == null ? "" : str; } public static void setLocalStorage(String name, byte[] data) { diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java index 53e563c..78f678c 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java @@ -2,6 +2,7 @@ package net.lax1dude.eaglercraft.v1_8.internal; import java.net.URL; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformAudio.IAudioCacheLoader; import net.lax1dude.eaglercraft.v1_8.internal.paulscode.lwjgl3.LibraryLWJGLOpenAL; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; @@ -106,6 +107,18 @@ public class PlatformAudio { public static void clearAudioCache() { // browser only } + + public static void flushAudioCache() { + + } + + public static interface IAudioCacheLoader { + byte[] loadFile(String filename); + } + + public static IAudioResource loadAudioDataNew(String filename, boolean holdInCache, IAudioCacheLoader loader) { + throw new UnsupportedOperationException("Browser only!"); + } private static final Logger logger = LogManager.getLogger("EaglercraftPlatformAudio"); private static SoundSystem sndSystem = null; diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java index 8fdc01b..9c55008 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java @@ -3,6 +3,19 @@ package net.lax1dude.eaglercraft.v1_8.internal; import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; +/** + * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ public class PlatformBufferFunctions { public static void put(ByteBuffer newBuffer, ByteBuffer flip) { diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java index 7e7ad6e..cf9f227 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java @@ -70,6 +70,10 @@ public class PlatformOpenGL { glBlendEquation(glEnum); } + public static final void _wglBlendColor(float r, float g, float b, float a) { + glBlendColor(r, g, b, a); + } + public static final void _wglColorMask(boolean r, boolean g, boolean b, boolean a) { glColorMask(r, g, b, a); } @@ -233,6 +237,12 @@ public class PlatformOpenGL { glTexParameteri(target, param, value); } + public static final void _wglTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, + int border, int format, int type, ByteBuffer data) { + nglTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, + data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); + } + public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) { nglTexImage2D(target, level, internalFormat, width, height, border, format, type, @@ -251,15 +261,21 @@ public class PlatformOpenGL { data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); } + public static final void _wglTexImage2Du16(int target, int level, int internalFormat, int width, int height, + int border, int format, int type, ByteBuffer data) { + nglTexImage2D(target, level, internalFormat, width, height, border, format, type, + data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); + } + public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer data) { - glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, + nglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); } public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer data) { - glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, + nglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); } @@ -269,11 +285,21 @@ public class PlatformOpenGL { data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); } + public static final void _wglTexSubImage2Du16(int target, int level, int xoffset, int yoffset, int width, int height, + int format, int type, ByteBuffer data) { + nglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, + data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); + } + public static final void _wglCopyTexSubImage2D(int target, int level, int xoffset, int yoffset, int x, int y, int width, int height) { glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } + public static final void _wglTexStorage2D(int target, int levels, int internalFormat, int w, int h) { + glTexStorage2D(target, levels, internalFormat, w, h); + } + public static final void _wglPixelStorei(int pname, int value) { glPixelStorei(pname, value); } @@ -351,6 +377,18 @@ public class PlatformOpenGL { return loc < 0 ? null : new OpenGLObjects.UniformGL(loc); } + public static final int _wglGetUniformBlockIndex(IProgramGL obj, String name) { + return glGetUniformBlockIndex(((OpenGLObjects.ProgramGL) obj).ptr, name); + } + + public static final void _wglBindBufferRange(int target, int index, IBufferGL buffer, int offset, int size) { + glBindBufferRange(target, index, ((OpenGLObjects.BufferGL) buffer).ptr, offset, size); + } + + public static final void _wglUniformBlockBinding(IProgramGL obj, int blockIndex, int bufferIndex) { + glUniformBlockBinding(((OpenGLObjects.ProgramGL) obj).ptr, blockIndex, bufferIndex); + } + public static final void _wglUniform1f(IUniformGL obj, float x) { if (obj != null) glUniform1f(((OpenGLObjects.UniformGL) obj).ptr, x); @@ -403,14 +441,36 @@ public class PlatformOpenGL { EaglerLWJGLAllocator.getAddress(mat)); } + public static final void _wglUniformMatrix3x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if (obj != null) + nglUniformMatrix3x2fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() / 6, transpose, + EaglerLWJGLAllocator.getAddress(mat)); + } + public static final void _wglUniformMatrix4fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if (obj != null) nglUniformMatrix4fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() >> 4, transpose, EaglerLWJGLAllocator.getAddress(mat)); } + public static final void _wglUniformMatrix4x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if (obj != null) + nglUniformMatrix4x2fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() >> 3, transpose, + EaglerLWJGLAllocator.getAddress(mat)); + } + + public static final void _wglUniformMatrix4x3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if (obj != null) + nglUniformMatrix4x3fv(((OpenGLObjects.UniformGL) obj).ptr, mat.remaining() / 12, transpose, + EaglerLWJGLAllocator.getAddress(mat)); + } + public static final void _wglBindFramebuffer(int target, IFramebufferGL framebuffer) { - glBindFramebuffer(target, framebuffer == null ? 0 : ((OpenGLObjects.FramebufferGL) framebuffer).ptr); + if(framebuffer == null) { + glBindFramebuffer(target, 0); + }else { + glBindFramebuffer(target, ((OpenGLObjects.FramebufferGL) framebuffer).ptr); + } } public static final int _wglCheckFramebufferStatus(int target) { @@ -422,6 +482,10 @@ public class PlatformOpenGL { glFramebufferTexture2D(target, attachment, texTarget, ((OpenGLObjects.TextureGL) texture).ptr, level); } + public static final void _wglFramebufferTextureLayer(int target, int attachment, ITextureGL texture, int level, int layer) { + glFramebufferTextureLayer(target, attachment, ((OpenGLObjects.TextureGL) texture).ptr, level, layer); + } + public static final void _wglBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int bits, int filter) { glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, bits, filter); @@ -453,4 +517,8 @@ public class PlatformOpenGL { return glGetError(); } + public static final boolean checkHDRFramebufferSupport(int bits) { + return true; + } + } diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java index cd8e5f5..6bf684a 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java @@ -232,6 +232,7 @@ public class PlatformRuntime { logger.info("Initializing Hooks..."); PlatformInput.initHooks(windowHandle); + PlatformApplication.initHooks(windowHandle); } public static void destroy() { diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketPlayClient.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketPlayClient.java index 5659b56..9edd9c3 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketPlayClient.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketPlayClient.java @@ -2,9 +2,11 @@ package net.lax1dude.eaglercraft.v1_8.internal; import java.net.URI; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import org.java_websocket.client.WebSocketClient; +import org.java_websocket.drafts.Draft; +import org.java_websocket.drafts.Draft_6455; +import org.java_websocket.extensions.permessage_deflate.PerMessageDeflateExtension; import org.java_websocket.handshake.ServerHandshake; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; @@ -24,12 +26,15 @@ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; * */ class WebSocketPlayClient extends WebSocketClient { + + private static final Draft perMessageDeflateDraft = new Draft_6455(new PerMessageDeflateExtension()); public static final Logger logger = LogManager.getLogger("WebSocket"); WebSocketPlayClient(URI serverUri) { - super(serverUri); + super(serverUri, perMessageDeflateDraft); this.setConnectionLostTimeout(15); + this.setTcpNoDelay(true); } @Override diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketServerQuery.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketServerQuery.java index 3d952e3..38365f7 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketServerQuery.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketServerQuery.java @@ -6,6 +6,9 @@ import java.util.LinkedList; import java.util.List; import org.java_websocket.client.WebSocketClient; +import org.java_websocket.drafts.Draft; +import org.java_websocket.drafts.Draft_6455; +import org.java_websocket.extensions.permessage_deflate.PerMessageDeflateExtension; import org.java_websocket.handshake.ServerHandshake; import org.json.JSONObject; @@ -27,6 +30,8 @@ import net.lax1dude.eaglercraft.v1_8.log4j.Logger; */ class WebSocketServerQuery extends WebSocketClient implements IServerQuery { + private static final Draft perMessageDeflateDraft = new Draft_6455(new PerMessageDeflateExtension()); + public static final Logger logger = LogManager.getLogger("WebSocketQuery"); private final List queryResponses = new LinkedList(); @@ -39,7 +44,7 @@ class WebSocketServerQuery extends WebSocketClient implements IServerQuery { private EnumServerRateLimit rateLimit = EnumServerRateLimit.OK; WebSocketServerQuery(String type, URI serverUri) { - super(serverUri); + super(serverUri, perMessageDeflateDraft); this.type = type; this.setConnectionLostTimeout(5); this.setTcpNoDelay(true); diff --git a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java index fa0a225..f5e0102 100644 --- a/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java +++ b/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java @@ -7,6 +7,7 @@ import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformANGLE; import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource; import net.minecraft.client.main.Main; /** @@ -45,6 +46,12 @@ public class LWJGLEntryPoint { getANGLEPlatformFromArgs(args); + for(int i = 0; i < args.length; ++i) { + if(args[i].equalsIgnoreCase("highp")) { + ShaderSource.setHighP(true); + } + } + EagRuntime.create(); Main.appMain(new String[0]); diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglerInputStream.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglerInputStream.java index 1115121..dd5fe96 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglerInputStream.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglerInputStream.java @@ -29,6 +29,9 @@ public class EaglerInputStream extends ByteArrayInputStream { } public static byte[] inputStreamToBytesQuiet(InputStream is) { + if(is == null) { + return null; + } try { return inputStreamToBytes(is); }catch(IOException ex) { diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftSoundManager.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftSoundManager.java index b3d6a24..93a434a 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftSoundManager.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftSoundManager.java @@ -4,11 +4,13 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType; import net.lax1dude.eaglercraft.v1_8.internal.IAudioHandle; import net.lax1dude.eaglercraft.v1_8.internal.IAudioResource; import net.lax1dude.eaglercraft.v1_8.internal.PlatformAudio; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.ISound.AttenuationType; import net.minecraft.client.audio.ITickableSound; @@ -137,7 +139,7 @@ public class EaglercraftSoundManager { } public void reloadSoundSystem() { - // irrelevant + PlatformAudio.flushAudioCache(); } public void setSoundCategoryVolume(SoundCategory category, float volume) { @@ -282,6 +284,15 @@ public class EaglercraftSoundManager { } } + private final PlatformAudio.IAudioCacheLoader browserResourcePackLoader = filename -> { + try { + return EaglerInputStream.inputStreamToBytesQuiet(Minecraft.getMinecraft().getResourceManager() + .getResource(new ResourceLocation(filename)).getInputStream()); + }catch(Throwable t) { + return null; + } + }; + public void playSound(ISound sound) { if(!PlatformAudio.available()) { return; @@ -296,8 +307,13 @@ public class EaglercraftSoundManager { logger.warn("Unable to play empty soundEvent(2): {}", etr.getSoundPoolEntryLocation().toString()); }else { ResourceLocation lc = etr.getSoundPoolEntryLocation(); - IAudioResource trk = PlatformAudio.loadAudioData( - "/assets/" + lc.getResourceDomain() + "/" + lc.getResourcePath(), !etr.isStreamingSound()); + IAudioResource trk; + if(EagRuntime.getPlatformType() != EnumPlatformType.DESKTOP) { + trk = PlatformAudio.loadAudioDataNew(lc.toString(), !etr.isStreamingSound(), browserResourcePackLoader); + }else { + trk = PlatformAudio.loadAudioData( + "/assets/" + lc.getResourceDomain() + "/" + lc.getResourcePath(), !etr.isStreamingSound()); + } if(trk == null) { logger.warn("Unable to play unknown soundEvent(3): {}", sound.getSoundLocation().toString()); }else { diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java index 3a0dd4a..8b920dc 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java @@ -8,7 +8,7 @@ public class EaglercraftVersion { /// Customize these to fit your fork: public static final String projectForkName = "EaglercraftX"; - public static final String projectForkVersion = "u17"; + public static final String projectForkVersion = "u18"; public static final String projectForkVendor = "lax1dude"; public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; @@ -23,7 +23,7 @@ public class EaglercraftVersion { public static final String projectOriginName = "EaglercraftX"; public static final String projectOriginAuthor = "lax1dude"; public static final String projectOriginRevision = "1.8"; - public static final String projectOriginVersion = "u17"; + public static final String projectOriginVersion = "u18"; public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; @@ -32,15 +32,16 @@ public class EaglercraftVersion { public static final String mainMenuStringA = "Minecraft 1.8.8"; public static final String mainMenuStringB = projectOriginName + " " + - projectOriginRevision + "-" + projectOriginVersion; - public static final String mainMenuStringC = null; + projectOriginRevision + "-" + projectOriginVersion + " ultimate"; + public static final String mainMenuStringC = ""; public static final String mainMenuStringD = "Resources Copyright Mojang AB"; public static final String mainMenuStringE = projectForkName + " " + projectForkVersion; public static final String mainMenuStringF = "Made by " + projectForkVendor; - public static final boolean mainMenuEnableGithubButton = true; - - + public static final String mainMenuStringG = "Collector's Edition"; + public static final String mainMenuStringH = "PBR Shaders"; + + public static final boolean mainMenuEnableGithubButton = false; } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java index cc4cd0c..fe2911e 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java @@ -29,6 +29,7 @@ public class AcceleratedEffectRenderer implements IAcceleratedParticleEngine { private float f4; private float f5; + @Override public void begin(float partialTicks) { this.partialTicks = partialTicks; InstancedParticleRenderer.begin(); @@ -42,6 +43,7 @@ public class AcceleratedEffectRenderer implements IAcceleratedParticleEngine { } } + @Override public void draw(float texCoordWidth, float texCoordHeight) { InstancedParticleRenderer.render(texCoordWidth, texCoordHeight, 0.0625f, f1, f5, f2, f3, f4); } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/ChunkUpdateManager.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/ChunkUpdateManager.java index dace59a..b80bf04 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/ChunkUpdateManager.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/ChunkUpdateManager.java @@ -58,7 +58,8 @@ public class ChunkUpdateManager { RenderChunk r = generator.getRenderChunk(); try { r.resortTransparency(f, f1, f2, generator); - if(generator.getCompiledChunk().isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT)) { + CompiledChunk ch = generator.getCompiledChunk(); + if(ch.isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT) && ch.isLayerEmpty(EnumWorldBlockLayer.REALISTIC_WATER)) { throw new EmptyBlockLayerException(); } }catch(EmptyBlockLayerException ex) { @@ -82,9 +83,16 @@ public class ChunkUpdateManager { } generator.getRenderChunk().setCompiledChunk(compiledchunk); } else if (chunkcompiletaskgenerator$type == ChunkCompileTaskGenerator.Type.RESORT_TRANSPARENCY) { - this.uploadChunk(EnumWorldBlockLayer.TRANSLUCENT, generator.getRegionRenderCacheBuilder() - .getWorldRendererByLayer(EnumWorldBlockLayer.TRANSLUCENT), - generator.getRenderChunk(), compiledchunk); + if(!compiledchunk.isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT)) { + this.uploadChunk(EnumWorldBlockLayer.TRANSLUCENT, generator.getRegionRenderCacheBuilder() + .getWorldRendererByLayer(EnumWorldBlockLayer.TRANSLUCENT), + generator.getRenderChunk(), compiledchunk); + } + if(!compiledchunk.isLayerEmpty(EnumWorldBlockLayer.REALISTIC_WATER)) { + this.uploadChunk(EnumWorldBlockLayer.REALISTIC_WATER, generator.getRegionRenderCacheBuilder() + .getWorldRendererByLayer(EnumWorldBlockLayer.REALISTIC_WATER), + generator.getRenderChunk(), compiledchunk); + } generator.getRenderChunk().setCompiledChunk(compiledchunk); generator.setStatus(ChunkCompileTaskGenerator.Status.DONE); } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerTextureAtlasSprite.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerTextureAtlasSprite.java index c04263e..eb1e038 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerTextureAtlasSprite.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerTextureAtlasSprite.java @@ -9,6 +9,9 @@ import java.util.concurrent.Callable; import com.google.common.collect.Lists; import net.lax1dude.eaglercraft.v1_8.HString; +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; import net.minecraft.client.renderer.texture.TextureClock; import net.minecraft.client.renderer.texture.TextureCompass; @@ -34,24 +37,26 @@ import net.minecraft.util.ResourceLocation; * */ public class EaglerTextureAtlasSprite { - private final String iconName; + + private static final Logger logger = LogManager.getLogger("EaglerTextureAtlasSprite"); + + protected final String iconName; protected List framesTextureData = Lists.newArrayList(); protected int[][] interpolatedFrameData; - private AnimationMetadataSection animationMetadata; - private int cacheInterpolateSteps; + protected AnimationMetadataSection animationMetadata; protected boolean rotated; protected int originX; protected int originY; protected int width; protected int height; - private float minU; - private float maxU; - private float minV; - private float maxV; + protected float minU; + protected float maxU; + protected float minV; + protected float maxV; protected int frameCounter; protected int tickCounter; - private static String locationNameClock = "builtin/clock"; - private static String locationNameCompass = "builtin/compass"; + protected static String locationNameClock = "builtin/clock"; + protected static String locationNameCompass = "builtin/compass"; protected TextureAnimationCache animationCache = null; @@ -143,7 +148,7 @@ public class EaglerTextureAtlasSprite { return this.iconName; } - public void updateAnimation() { + public void updateAnimation(IFramebufferGL[] copyColorFramebuffer) { if(animationCache == null) { throw new IllegalStateException("Animation cache for '" + this.iconName + "' was never baked!"); } @@ -156,7 +161,7 @@ public class EaglerTextureAtlasSprite { this.tickCounter = 0; int k = this.animationMetadata.getFrameIndex(this.frameCounter); if (i != k && k >= 0 && k < this.framesTextureData.size()) { - animationCache.copyFrameLevelsToTex2D(k, this.originX, this.originY, this.width, this.height); + animationCache.copyFrameLevelsToTex2D(k, this.originX, this.originY, this.width, this.height, copyColorFramebuffer); } } else if (this.animationMetadata.isInterpolate()) { float f = 1.0f - (float) this.tickCounter / (float) this.animationMetadata.getFrameTimeSingle(this.frameCounter); @@ -165,7 +170,7 @@ public class EaglerTextureAtlasSprite { : this.animationMetadata.getFrameCount(); int k = this.animationMetadata.getFrameIndex((this.frameCounter + 1) % j); if (i != k && k >= 0 && k < this.framesTextureData.size()) { - animationCache.copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY, this.width, this.height); + animationCache.copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY, this.width, this.height, copyColorFramebuffer); } } } @@ -292,20 +297,19 @@ public class EaglerTextureAtlasSprite { if(animationCache == null) { animationCache = new TextureAnimationCache(width, height, mipLevels); } - animationCache.initialize(framesTextureData, animationMetadata.isInterpolate()); + animationCache.initialize(framesTextureData); } } - private void allocateFrameTextureData(int index) { + protected void allocateFrameTextureData(int index) { if (this.framesTextureData.size() <= index) { for (int i = this.framesTextureData.size(); i <= index; ++i) { this.framesTextureData.add((int[][]) null); } - } } - private static int[][] getFrameTextureData(int[][] data, int rows, int columns, int parInt3) { + protected static int[][] getFrameTextureData(int[][] data, int rows, int columns, int parInt3) { int[][] aint = new int[data.length][]; for (int i = 0; i < data.length; ++i) { @@ -335,7 +339,7 @@ public class EaglerTextureAtlasSprite { this.framesTextureData = newFramesTextureData; } - private void resetSprite() { + protected void resetSprite() { this.animationMetadata = null; this.setFramesTextureData(Lists.newArrayList()); this.frameCounter = 0; @@ -352,4 +356,23 @@ public class EaglerTextureAtlasSprite { + this.height + ", width=" + this.width + ", u0=" + this.minU + ", u1=" + this.maxU + ", v0=" + this.minV + ", v1=" + this.maxV + '}'; } + + public void loadSpritePBR(ImageData[][] imageDatas, AnimationMetadataSection animationmetadatasection, + boolean dontAnimateNormals, boolean dontAnimateMaterial) { + Throwable t = new UnsupportedOperationException("PBR is not enabled"); + try { + throw t; + }catch(Throwable tt) { + logger.error(t); + } + } + + public void updateAnimationPBR(IFramebufferGL[] copyColorFramebuffer, IFramebufferGL[] copyMaterialFramebuffer, int materialTexOffset) { + Throwable t = new UnsupportedOperationException("PBR is not enabled"); + try { + throw t; + }catch(Throwable tt) { + logger.error(t); + } + } } \ No newline at end of file diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/IAcceleratedParticleEngine.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/IAcceleratedParticleEngine.java index 5298eab..b54d5b1 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/IAcceleratedParticleEngine.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/IAcceleratedParticleEngine.java @@ -17,6 +17,10 @@ import net.minecraft.entity.Entity; */ public interface IAcceleratedParticleEngine { + void begin(float partialTicks); + + void draw(float texCoordWidth, float texCoordHeight); + void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY, int lightMapData, int texSize, float particleSize, float r, float g, float b, float a); diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/TextureAnimationCache.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/TextureAnimationCache.java index 6525314..7448a0e 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/TextureAnimationCache.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/TextureAnimationCache.java @@ -1,18 +1,17 @@ package net.lax1dude.eaglercraft.v1_8.minecraft; -import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import java.util.List; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; -import net.lax1dude.eaglercraft.v1_8.internal.IRenderbufferGL; -import net.lax1dude.eaglercraft.v1_8.internal.ITextureGL; import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.SpriteLevelMixer; +import net.lax1dude.eaglercraft.v1_8.opengl.TextureCopyUtil; import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f; import net.minecraft.client.renderer.GLAllocation; @@ -31,10 +30,6 @@ import net.minecraft.client.renderer.GLAllocation; */ public class TextureAnimationCache { - public static final int _GL_FRAMEBUFFER = 0x8D40; // enum not defined in RealOpenGLEnums - public static final int _GL_RENDERBUFFER = 0x8D41; - public static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0; - public final int width; public final int height; public final int mipLevels; @@ -42,10 +37,8 @@ public class TextureAnimationCache { private int frameCount = 1; private int[] cacheTextures = null; - private IFramebufferGL[] cacheFramebuffers = null; - private IFramebufferGL interpolateFramebuffer = null; - private IRenderbufferGL interpolateRenderbuffer = null; + public static final int _GL_FRAMEBUFFER = 0x8D40; public TextureAnimationCache(int width, int height, int mipLevels) { this.width = width; @@ -53,9 +46,8 @@ public class TextureAnimationCache { this.mipLevels = mipLevels; } - public void initialize(List frames, boolean enableInterpolation) { - boolean init = cacheTextures == null; - if(init) { + public void initialize(List frames) { + if(cacheTextures == null) { cacheTextures = new int[mipLevels]; for(int i = 0; i < cacheTextures.length; ++i) { cacheTextures[i] = GlStateManager.generateTexture(); @@ -65,17 +57,6 @@ public class TextureAnimationCache { EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } - - if(enableInterpolation) { - interpolateFramebuffer = _wglCreateFramebuffer(); - _wglBindFramebuffer(_GL_FRAMEBUFFER, interpolateFramebuffer); - interpolateRenderbuffer = _wglCreateRenderbuffer(); - _wglBindRenderbuffer(_GL_RENDERBUFFER, interpolateRenderbuffer); - _wglRenderbufferStorage(_GL_RENDERBUFFER, GL_RGBA8, width, height); - _wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, - _GL_RENDERBUFFER, interpolateRenderbuffer); - _wglBindFramebuffer(_GL_FRAMEBUFFER, null); - } } frameCount = frames.size(); @@ -111,37 +92,10 @@ public class TextureAnimationCache { }finally { EagRuntime.freeIntBuffer(pixels); } - - if(init) { - cacheFramebuffers = new IFramebufferGL[mipLevels]; - for(int i = 0; i < mipLevels; ++i) { - GlStateManager.bindTexture(cacheTextures[i]); - IFramebufferGL fbo = _wglCreateFramebuffer(); - _wglBindFramebuffer(_GL_FRAMEBUFFER, fbo); - _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - EaglercraftGPU.getNativeTexture(cacheTextures[i]), 0); - cacheFramebuffers[i] = fbo; - } - _wglBindFramebuffer(_GL_FRAMEBUFFER, null); - } } public void free() { if(cacheTextures != null) { - if(interpolateFramebuffer != null) { - _wglDeleteFramebuffer(interpolateFramebuffer); - interpolateFramebuffer = null; - } - if(interpolateRenderbuffer != null) { - _wglDeleteRenderbuffer(interpolateRenderbuffer); - interpolateRenderbuffer = null; - } - if(cacheFramebuffers != null) { - for(int i = 0; i < mipLevels; ++i) { - _wglDeleteFramebuffer(cacheFramebuffers[i]); - } - cacheFramebuffers = null; - } for(int i = 0; i < cacheTextures.length; ++i) { GlStateManager.deleteTexture(cacheTextures[i]); } @@ -149,12 +103,16 @@ public class TextureAnimationCache { } } - public void copyFrameLevelsToTex2D(int animationFrame, int dx, int dy, int w, int h) { - copyFrameLevelsToTex2D(animationFrame, mipLevels, dx, dy, w, h); + public void copyFrameLevelsToTex2D(int animationFrame, int dx, int dy, int w, int h, IFramebufferGL[] dstFramebuffers) { + copyFrameLevelsToTex2D(animationFrame, mipLevels, dx, dy, w, h, dstFramebuffers); } - public void copyFrameLevelsToTex2D(int animationFrame, int levels, int dx, int dy, int w, int h) { + /** + * WARNING: call _wglBindFramebuffer(_GL_FRAMEBUFFER, null); when complete + */ + public void copyFrameLevelsToTex2D(int animationFrame, int levels, int dx, int dy, int w, int h, IFramebufferGL[] dstFramebuffers) { for(int i = 0; i < levels; ++i) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, dstFramebuffers[i]); copyFrameToTex2D(animationFrame, i, dx >> i, dy >> i, w >> i, h >> i); } } @@ -163,20 +121,23 @@ public class TextureAnimationCache { if(cacheTextures == null) { throw new IllegalStateException("Cannot copy from uninitialized TextureAnimationCache"); } - _wglBindFramebuffer(_GL_FRAMEBUFFER, cacheFramebuffers[level]); - _wglReadBuffer(_GL_COLOR_ATTACHMENT0); - _wglCopyTexSubImage2D(GL_TEXTURE_2D, level, dx, dy, 0, h * animationFrame, w, h); - _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.bindTexture(cacheTextures[level]); + TextureCopyUtil.srcSize(width >> level, (height >> level) * frameCount); + TextureCopyUtil.blitTextureUsingViewports(0, h * animationFrame, dx, dy, w, h); } public void copyInterpolatedFrameLevelsToTex2D(int animationFrameFrom, int animationFrameTo, float factor, int dx, - int dy, int w, int h) { - copyInterpolatedFrameLevelsToTex2D(animationFrameFrom, animationFrameTo, factor, mipLevels, dx, dy, w, h); + int dy, int w, int h, IFramebufferGL[] dstFramebuffers) { + copyInterpolatedFrameLevelsToTex2D(animationFrameFrom, animationFrameTo, factor, mipLevels, dx, dy, w, h, dstFramebuffers); } + /** + * WARNING: call _wglBindFramebuffer(_GL_FRAMEBUFFER, null); when complete + */ public void copyInterpolatedFrameLevelsToTex2D(int animationFrameFrom, int animationFrameTo, float factor, - int levels, int dx, int dy, int w, int h) { + int levels, int dx, int dy, int w, int h, IFramebufferGL[] dstFramebuffers) { for(int i = 0; i < levels; ++i) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, dstFramebuffers[i]); copyInterpolatedFrameToTex2D(animationFrameFrom, animationFrameTo, factor, i, dx >> i, dy >> i, w >> i, h >> i); } } @@ -187,19 +148,9 @@ public class TextureAnimationCache { throw new IllegalStateException("Cannot copy from uninitialized TextureAnimationCache"); } - int storeTexture = GlStateManager.getTextureBound(); - - _wglBindFramebuffer(_GL_FRAMEBUFFER, interpolateFramebuffer); + GlStateManager.viewport(dx, dy, w, h); GlStateManager.bindTexture(cacheTextures[level]); - - int[] storeViewport = new int[4]; - EaglercraftGPU.glGetInteger(GL_VIEWPORT, storeViewport); - GlStateManager.viewport(0, 0, w, h); - GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); - GlStateManager.clear(GL_COLOR_BUFFER_BIT); - - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL_ONE, GL_ONE); + GlStateManager.disableBlend(); Matrix3f matrix = new Matrix3f(); matrix.m11 = 1.0f / frameCount; @@ -216,18 +167,13 @@ public class TextureAnimationCache { float fac1 = 1.0f - factor; SpriteLevelMixer.setBlendColor(fac1, fac1, fac1, fac1); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + SpriteLevelMixer.drawSprite(0); - GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GlStateManager.disableBlend(); - - GlStateManager.bindTexture(storeTexture); - GlStateManager.viewport(storeViewport[0], storeViewport[1], storeViewport[2], storeViewport[3]); - GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f); - - _wglReadBuffer(_GL_COLOR_ATTACHMENT0); - _wglCopyTexSubImage2D(GL_TEXTURE_2D, level, dx, dy, 0, 0, w, h); - _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } public int getFrameCount() { diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/DrawUtils.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/DrawUtils.java new file mode 100644 index 0000000..131d997 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/DrawUtils.java @@ -0,0 +1,99 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class DrawUtils { + + public static final String vertexShaderPath = "/assets/eagler/glsl/local.vsh"; + + public static IBufferArrayGL standardQuad2DVAO = null; + public static IBufferArrayGL standardQuad3DVAO = null; + public static IBufferGL standardQuadVBO = null; + + public static IShaderGL vshLocal = null; + + static void init() { + if(standardQuad2DVAO == null) { + standardQuad2DVAO = _wglGenVertexArrays(); + standardQuad3DVAO = _wglGenVertexArrays(); + standardQuadVBO = _wglGenBuffers(); + + FloatBuffer verts = EagRuntime.allocateFloatBuffer(18); + verts.put(new float[] { + -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f + }); + verts.flip(); + + EaglercraftGPU.bindGLArrayBuffer(standardQuadVBO); + _wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW); + EagRuntime.freeFloatBuffer(verts); + + EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0); + + EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0); + } + + if(vshLocal == null) { + String vertexSource = EagRuntime.getResourceString(vertexShaderPath); + if(vertexSource == null) { + throw new RuntimeException("vertex shader \"" + vertexShaderPath + "\" is missing!"); + } + + vshLocal = _wglCreateShader(GL_VERTEX_SHADER); + + _wglShaderSource(vshLocal, FixedFunctionConstants.VERSION + "\n" + vertexSource); + _wglCompileShader(vshLocal); + + if(_wglGetShaderi(vshLocal, GL_COMPILE_STATUS) != GL_TRUE) { + EaglercraftGPU.logger.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\"!"); + String log = _wglGetShaderInfoLog(vshLocal); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + EaglercraftGPU.logger.error("[VERT] {}", lines[i]); + } + } + throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!"); + } + } + } + + public static void drawStandardQuad2D() { + EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO); + _wglDrawArrays(GL_TRIANGLES, 0, 6); + } + + public static void drawStandardQuad3D() { + EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO); + _wglDrawArrays(GL_TRIANGLES, 0, 6); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java index 6af406c..ce22b0f 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java @@ -3,6 +3,9 @@ package net.lax1dude.eaglercraft.v1_8.opengl; import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; + import java.util.HashMap; import java.util.Map; @@ -37,7 +40,9 @@ public class EaglercraftGPU { static final GLObjectMap mapTexturesGL = new GLObjectMap(32767); static final GLObjectMap mapQueriesGL = new GLObjectMap(32767); static final GLObjectMap mapDisplayListsGL = new GLObjectMap(32767); - + + static final Logger logger = LogManager.getLogger("EaglercraftGPU"); + public static final String gluErrorString(int i) { switch(i) { case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; @@ -123,6 +128,7 @@ public class EaglercraftGPU { _wglDeleteBuffers(dp.vertexBuffer); dp.vertexBuffer = null; } + currentList = null; return; } @@ -239,6 +245,10 @@ public class EaglercraftGPU { int type, IntBuffer pixels) { _wglTexSubImage2D(target, level, x, y, w, h, format, type, pixels); } + + public static final void glTexStorage2D(int target, int levels, int internalFormat, int w, int h) { + _wglTexStorage2D(target, levels, internalFormat, w, h); + } public static final void glLineWidth(float f) { _wglLineWidth(f); @@ -293,31 +303,54 @@ public class EaglercraftGPU { private static IBufferArrayGL currentBufferArray = null; - static final void bindGLBufferArray(IBufferArrayGL buffer) { + public static final void bindGLBufferArray(IBufferArrayGL buffer) { if(currentBufferArray != buffer) { - PlatformOpenGL._wglBindVertexArray(buffer); + _wglBindVertexArray(buffer); currentBufferArray = buffer; } } private static IBufferGL currentArrayBuffer = null; - static final void bindGLArrayBuffer(IBufferGL buffer) { + public static final void bindGLArrayBuffer(IBufferGL buffer) { if(currentArrayBuffer != buffer) { - PlatformOpenGL._wglBindBuffer(GL_ARRAY_BUFFER, buffer); + _wglBindBuffer(GL_ARRAY_BUFFER, buffer); currentArrayBuffer = buffer; } } + private static IBufferGL currentUniformBuffer = null; + + public static final void bindGLUniformBuffer(IBufferGL buffer) { + if(currentUniformBuffer != buffer) { + _wglBindBuffer(0x8A11, buffer); + currentUniformBuffer = buffer; + } + } + private static IProgramGL currentShaderProgram = null; - static final void bindGLShaderProgram(IProgramGL prog) { + public static final void bindGLShaderProgram(IProgramGL prog) { if(currentShaderProgram != prog) { - PlatformOpenGL._wglUseProgram(prog); + _wglUseProgram(prog); currentShaderProgram = prog; } } + private static final IBufferGL[] currentUniformBlockBindings = new IBufferGL[16]; + private static final int[] currentUniformBlockBindingOffset = new int[16]; + private static final int[] currentUniformBlockBindingSize = new int[16]; + + public static final void bindUniformBufferRange(int index, IBufferGL buffer, int offset, int size) { + if(currentUniformBlockBindings[index] != buffer || currentUniformBlockBindingOffset[index] != offset + || currentUniformBlockBindingSize[index] != size) { + _wglBindBufferRange(0x8A11, index, buffer, offset, size); + currentUniformBlockBindings[index] = buffer; + currentUniformBlockBindingOffset[index] = offset; + currentUniformBlockBindingSize[index] = size; + } + } + public static final int ATTRIB_TEXTURE = 1; public static final int ATTRIB_COLOR = 2; public static final int ATTRIB_NORMAL = 4; @@ -349,6 +382,10 @@ public class EaglercraftGPU { } } + public static final void optimize() { + FixedFunctionPipeline.optimize(); + } + private static FixedFunctionPipeline lastRender = null; private static int lastMode = 0; private static int lastCount = 0; @@ -367,7 +404,7 @@ public class EaglercraftGPU { private static IBufferGL quad32EmulationBuffer = null; private static int quad32EmulationBufferSize = 0; - static final void attachQuad16EmulationBuffer(int vertexCount, boolean bind) { + public static final void attachQuad16EmulationBuffer(int vertexCount, boolean bind) { IBufferGL buf = quad16EmulationBuffer; if(buf == null) { quad16EmulationBuffer = buf = _wglGenBuffers(); @@ -392,7 +429,7 @@ public class EaglercraftGPU { } } - static final void attachQuad32EmulationBuffer(int vertexCount, boolean bind) { + public static final void attachQuad32EmulationBuffer(int vertexCount, boolean bind) { IBufferGL buf = quad32EmulationBuffer; if(buf == null) { quad32EmulationBuffer = buf = _wglGenBuffers(); @@ -445,19 +482,132 @@ public class EaglercraftGPU { EagRuntime.freeIntBuffer(buf); } - public static final void warmUpCache() { - EaglercraftGPU.glGetString(7936); - EaglercraftGPU.glGetString(7937); - EaglercraftGPU.glGetString(7938); - SpriteLevelMixer.initialize(); - InstancedFontRenderer.initialize(); - InstancedParticleRenderer.initialize(); - EffectPipelineFXAA.initialize(); - SpriteLevelMixer.vshLocal.free(); - } - public static final ITextureGL getNativeTexture(int tex) { return mapTexturesGL.get(tex); } + static boolean hasFramebufferHDR16FSupport = false; + static boolean hasFramebufferHDR32FSupport = false; + + public static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) { + createFramebufferHDR16FTexture(target, level, w, h, format, allow32bitFallback, null); + } + + public static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) { + createFramebufferHDR16FTexture(target, level, w, h, format, false, pixelData); + } + + private static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback, ByteBuffer pixelData) { + if(hasFramebufferHDR16FSupport) { + int internalFormat; + switch(format) { + case GL_RED: + internalFormat = 0x822D; // GL_R16F + break; + case 0x8227: // GL_RG + internalFormat = 0x822F; // GL_RG16F + case GL_RGB: + throw new UnsupportedOperationException("GL_RGB16F isn't supported specifically in WebGL 2.0 for some goddamn reason"); + case GL_RGBA: + internalFormat = 0x881A; // GL_RGBA16F + break; + default: + throw new UnsupportedOperationException("Unknown format: " + format); + } + _wglTexImage2Du16(target, level, internalFormat, w, h, 0, format, 0x140B, pixelData); + }else { + if(allow32bitFallback) { + if(hasFramebufferHDR32FSupport) { + createFramebufferHDR32FTexture(target, level, w, h, format, false, null); + }else { + throw new UnsupportedOperationException("No fallback 32-bit HDR (floating point) texture support is available on this device"); + } + }else { + throw new UnsupportedOperationException("16-bit HDR (floating point) textures are not supported on this device"); + } + } + } + + public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback) { + createFramebufferHDR32FTexture(target, level, w, h, format, allow16bitFallback, null); + } + + public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) { + createFramebufferHDR32FTexture(target, level, w, h, format, false, pixelData); + } + + private static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback, ByteBuffer pixelData) { + if(hasFramebufferHDR32FSupport) { + int internalFormat; + switch(format) { + case GL_RED: + internalFormat = 0x822E; // GL_R32F + break; + case 0x8227: // GL_RG + internalFormat = 0x822F; // GL_RG32F + case GL_RGB: + throw new UnsupportedOperationException("GL_RGB32F isn't supported specifically in WebGL 2.0 for some goddamn reason"); + case GL_RGBA: + internalFormat = 0x8814; //GL_RGBA32F + break; + default: + throw new UnsupportedOperationException("Unknown format: " + format); + } + _wglTexImage2D(target, level, internalFormat, w, h, 0, format, GL_FLOAT, pixelData); + }else { + if(allow16bitFallback) { + if(hasFramebufferHDR16FSupport) { + createFramebufferHDR16FTexture(target, level, w, h, format, false); + }else { + throw new UnsupportedOperationException("No fallback 16-bit HDR (floating point) texture support is available on this device"); + } + }else { + throw new UnsupportedOperationException("32-bit HDR (floating point) textures are not supported on this device"); + } + } + } + + public static final void warmUpCache() { + EaglercraftGPU.glGetString(7936); + EaglercraftGPU.glGetString(7937); + EaglercraftGPU.glGetString(7938); + hasFramebufferHDR16FSupport = PlatformOpenGL.checkHDRFramebufferSupport(16); + if(hasFramebufferHDR16FSupport) { + logger.info("16-bit HDR render target support: true"); + }else { + logger.error("16-bit HDR render target support: false"); + } + hasFramebufferHDR32FSupport = PlatformOpenGL.checkHDRFramebufferSupport(32); + if(hasFramebufferHDR32FSupport) { + logger.info("32-bit HDR render target support: true"); + }else { + logger.error("32-bit HDR render target support: false"); + } + if(!checkHasHDRFramebufferSupport()) { + logger.error("No HDR render target support was detected! Shaders will be disabled."); + } + DrawUtils.init(); + SpriteLevelMixer.initialize(); + InstancedFontRenderer.initialize(); + InstancedParticleRenderer.initialize(); + EffectPipelineFXAA.initialize(); + TextureCopyUtil.initialize(); + DrawUtils.vshLocal.free(); + DrawUtils.vshLocal = null; + } + + public static final boolean checkHDRFramebufferSupport(int bits) { + switch(bits) { + case 16: + return hasFramebufferHDR16FSupport; + case 32: + return hasFramebufferHDR32FSupport; + default: + return false; + } + } + + public static final boolean checkHasHDRFramebufferSupport() { + return hasFramebufferHDR16FSupport || hasFramebufferHDR32FSupport; + } } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EffectPipelineFXAA.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EffectPipelineFXAA.java index d466365..9427335 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EffectPipelineFXAA.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EffectPipelineFXAA.java @@ -75,12 +75,12 @@ public class EffectPipelineFXAA { shaderProgram = _wglCreateProgram(); - _wglAttachShader(shaderProgram, SpriteLevelMixer.vshLocal); + _wglAttachShader(shaderProgram, DrawUtils.vshLocal); _wglAttachShader(shaderProgram, frag); _wglLinkProgram(shaderProgram); - _wglDetachShader(shaderProgram, SpriteLevelMixer.vshLocal); + _wglDetachShader(shaderProgram, DrawUtils.vshLocal); _wglDetachShader(shaderProgram, frag); _wglDeleteShader(frag); @@ -144,14 +144,13 @@ public class EffectPipelineFXAA { public static void end() { _wglBindFramebuffer(_GL_FRAMEBUFFER, null); - EaglercraftGPU.bindGLBufferArray(SpriteLevelMixer.vertexArray); EaglercraftGPU.bindGLShaderProgram(shaderProgram); GlStateManager.bindTexture(framebufferColor); _wglUniform2f(u_screenSize2f, 1.0f / currentWidth, 1.0f / currentHeight); - _wglDrawArrays(GL_TRIANGLES, 0, 6); + DrawUtils.drawStandardQuad2D(); } } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionPipeline.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionPipeline.java index b6e730c..f80b509 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionPipeline.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionPipeline.java @@ -3,6 +3,9 @@ package net.lax1dude.eaglercraft.v1_8.opengl; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import java.util.ArrayList; +import java.util.List; + import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; @@ -16,11 +19,14 @@ import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL; import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; -import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants; +import net.lax1dude.eaglercraft.v1_8.opengl.StreamBuffer.StreamBufferInstance; import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; import net.minecraft.util.MathHelper; +import static net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionState.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants.*; + /** * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. * @@ -34,23 +40,10 @@ import net.minecraft.util.MathHelper; * (please read the 'LICENSE' file this repo's root directory for more info) * */ -class FixedFunctionPipeline { +public class FixedFunctionPipeline { private static final Logger LOGGER = LogManager.getLogger("FixedFunctionPipeline"); - static final int STATE_HAS_ATTRIB_TEXTURE = 1; - static final int STATE_HAS_ATTRIB_COLOR = 2; - static final int STATE_HAS_ATTRIB_NORMAL = 4; - static final int STATE_HAS_ATTRIB_LIGHTMAP = 8; - static final int STATE_ENABLE_TEXTURE2D = 16; - static final int STATE_ENABLE_LIGHTMAP = 32; - static final int STATE_ENABLE_ALPHA_TEST = 64; - static final int STATE_ENABLE_MC_LIGHTING = 128; - static final int STATE_ENABLE_END_PORTAL = 256; - static final int STATE_ENABLE_ANISOTROPIC_FIX = 512; - static final int STATE_ENABLE_FOG = 1024; - static final int STATE_ENABLE_BLEND_ADD = 2048; - static final int getFragmentState() { return (GlStateManager.stateTexture[0] ? STATE_ENABLE_TEXTURE2D : 0) | (GlStateManager.stateTexture[1] ? STATE_ENABLE_LIGHTMAP : 0) | @@ -66,25 +59,41 @@ class FixedFunctionPipeline { } static FixedFunctionPipeline setupDirect(ByteBuffer buffer, int attrib) { - FixedFunctionPipeline self = getPipelineInstance(attrib | getFragmentState()); - - EaglercraftGPU.bindGLBufferArray(self.vertexArray); - EaglercraftGPU.bindGLArrayBuffer(self.vertexBuffer); - - int wantSize = buffer.remaining(); - if(self.vertexBufferSize < wantSize) { - int newSize = (wantSize & 0xFFFFF000) + 0x2000; - _wglBufferData(GL_ARRAY_BUFFER, newSize, GL_DYNAMIC_DRAW); - self.vertexBufferSize = newSize; + FixedFunctionPipeline self; + int baseState = attrib | getFragmentState(); + if(GlStateManager.stateUseExtensionPipeline) { + if(extensionProvider != null) { + self = getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState)); + }else { + throw new IllegalStateException("No extension pipeline is available!"); + } + }else { + self = getPipelineInstanceCore(baseState); } + StreamBufferInstance sb = self.streamBuffer.getBuffer(buffer.remaining()); + self.currentVertexArray = sb; + + EaglercraftGPU.bindGLBufferArray(sb.vertexArray); + EaglercraftGPU.bindGLArrayBuffer(sb.vertexBuffer); + _wglBufferSubData(GL_ARRAY_BUFFER, 0, buffer); return self; } static void setupDisplayList(DisplayList list) { - FixedFunctionPipeline self = getPipelineInstance(list.attribs | getFragmentState()); + FixedFunctionPipeline self; + int baseState = list.attribs | getFragmentState(); + if(GlStateManager.stateUseExtensionPipeline) { + if(extensionProvider != null) { + self = getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState)); + }else { + throw new IllegalStateException("No extension pipeline is available!"); + } + }else { + self = getPipelineInstanceCore(baseState); + } EaglercraftGPU.bindGLBufferArray(list.vertexArray); EaglercraftGPU.bindGLArrayBuffer(list.vertexBuffer); @@ -120,7 +129,16 @@ class FixedFunctionPipeline { } static FixedFunctionPipeline setupRenderDisplayList(int attribs) { - return getPipelineInstance(attribs | getFragmentState()); + int baseState = attribs | getFragmentState(); + if(GlStateManager.stateUseExtensionPipeline) { + if(extensionProvider != null) { + return getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState)); + }else { + throw new IllegalStateException("No extension pipeline is available!"); + } + }else { + return getPipelineInstanceCore(baseState); + } } void drawArrays(int mode, int offset, int count) { @@ -131,10 +149,11 @@ class FixedFunctionPipeline { void drawDirectArrays(int mode, int offset, int count) { EaglercraftGPU.bindGLShaderProgram(shaderProgram); if(mode == GL_QUADS) { + StreamBufferInstance sb = currentVertexArray; if(count > 0xFFFF) { - if(!bindQuad32) { - bindQuad16 = false; - bindQuad32 = true; + if(!sb.bindQuad32) { + sb.bindQuad16 = false; + sb.bindQuad32 = true; EaglercraftGPU.attachQuad32EmulationBuffer(count, true); }else { EaglercraftGPU.attachQuad32EmulationBuffer(count, false); @@ -142,9 +161,9 @@ class FixedFunctionPipeline { PlatformOpenGL._wglDrawElements(GL_TRIANGLES, count + (count >> 1), GL_UNSIGNED_INT, 0); }else { - if(!bindQuad16) { - bindQuad16 = true; - bindQuad32 = false; + if(!sb.bindQuad16) { + sb.bindQuad16 = true; + sb.bindQuad32 = false; EaglercraftGPU.attachQuad16EmulationBuffer(count, true); }else { EaglercraftGPU.attachQuad16EmulationBuffer(count, false); @@ -162,142 +181,203 @@ class FixedFunctionPipeline { PlatformOpenGL._wglDrawElements(mode, count, type, offset); } - private static final FixedFunctionPipeline[] pipelineStateCache = new FixedFunctionPipeline[4096]; + private static IExtPipelineCompiler extensionProvider; + + public static void loadExtensionPipeline(IExtPipelineCompiler provider) { + flushCache(); + extensionProvider = provider; + } + + private static final FixedFunctionPipeline[] pipelineStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1]; + private static final FixedFunctionPipeline[][] pipelineExtStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1][]; + private static final List pipelineListTracker = new ArrayList(1024); private static String shaderSourceCacheVSH = null; private static String shaderSourceCacheFSH = null; - private static FixedFunctionPipeline getPipelineInstance(int bits) { + private static FixedFunctionPipeline getPipelineInstanceCore(int bits) { FixedFunctionPipeline pp = pipelineStateCache[bits]; if(pp == null) { - if(shaderSourceCacheVSH == null) { - shaderSourceCacheVSH = EagRuntime.getResourceString(FixedFunctionConstants.FILENAME_VSH); - if(shaderSourceCacheVSH == null) { - throw new RuntimeException("Could not load: " + FixedFunctionConstants.FILENAME_VSH); - } - } - if(shaderSourceCacheFSH == null) { - shaderSourceCacheFSH = EagRuntime.getResourceString(FixedFunctionConstants.FILENAME_FSH); - if(shaderSourceCacheFSH == null) { - throw new RuntimeException("Could not load: " + FixedFunctionConstants.FILENAME_FSH); - } - } - - String macros = FixedFunctionConstants.VERSION + "\n"; - if((bits & STATE_HAS_ATTRIB_TEXTURE) == STATE_HAS_ATTRIB_TEXTURE) { - macros += ("#define " + FixedFunctionConstants.MACRO_ATTRIB_TEXTURE + "\n"); - } - if((bits & STATE_HAS_ATTRIB_COLOR) == STATE_HAS_ATTRIB_COLOR) { - macros += ("#define " + FixedFunctionConstants.MACRO_ATTRIB_COLOR + "\n"); - } - if((bits & STATE_HAS_ATTRIB_NORMAL) == STATE_HAS_ATTRIB_NORMAL) { - macros += ("#define " + FixedFunctionConstants.MACRO_ATTRIB_NORMAL + "\n"); - } - if((bits & STATE_HAS_ATTRIB_LIGHTMAP) == STATE_HAS_ATTRIB_LIGHTMAP) { - macros += ("#define " + FixedFunctionConstants.MACRO_ATTRIB_LIGHTMAP + "\n"); - } - if((bits & STATE_ENABLE_TEXTURE2D) == STATE_ENABLE_TEXTURE2D) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_TEXTURE2D + "\n"); - } - if((bits & STATE_ENABLE_LIGHTMAP) == STATE_ENABLE_LIGHTMAP) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_LIGHTMAP + "\n"); - } - if((bits & STATE_ENABLE_ALPHA_TEST) == STATE_ENABLE_ALPHA_TEST) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_ALPHA_TEST + "\n"); - } - if((bits & STATE_ENABLE_MC_LIGHTING) == STATE_ENABLE_MC_LIGHTING) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_MC_LIGHTING + "\n"); - } - if((bits & STATE_ENABLE_END_PORTAL) == STATE_ENABLE_END_PORTAL) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_END_PORTAL + "\n"); - } - if((bits & STATE_ENABLE_ANISOTROPIC_FIX) == STATE_ENABLE_ANISOTROPIC_FIX) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_ANISOTROPIC_FIX + "\n"); - } - if((bits & STATE_ENABLE_FOG) == STATE_ENABLE_FOG) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_FOG + "\n"); - } - if((bits & STATE_ENABLE_BLEND_ADD) == STATE_ENABLE_BLEND_ADD) { - macros += ("#define " + FixedFunctionConstants.MACRO_ENABLE_BLEND_ADD + "\n"); - } - - macros += ("precision " + FixedFunctionConstants.PRECISION_INT + " int;\n"); - macros += ("precision " + FixedFunctionConstants.PRECISION_FLOAT + " float;\n"); - macros += ("precision " + FixedFunctionConstants.PRECISION_SAMPLER + " sampler2D;\n\n"); - - IShaderGL vsh = _wglCreateShader(GL_VERTEX_SHADER); - - _wglShaderSource(vsh, macros + shaderSourceCacheVSH); - _wglCompileShader(vsh); - - if(_wglGetShaderi(vsh, GL_COMPILE_STATUS) != GL_TRUE) { - LOGGER.error("Failed to compile GL_VERTEX_SHADER for state {} !", getStateBits(bits, 11)); - String log = _wglGetShaderInfoLog(vsh); - if(log != null) { - String[] lines = log.split("(\\r\\n|\\r|\\n)"); - for(int i = 0; i < lines.length; ++i) { - LOGGER.error("[VERT] {}", lines[i]); - } - } - _wglDeleteShader(vsh); - throw new IllegalStateException("Vertex shader could not be compiled!"); - } - - IShaderGL fsh = _wglCreateShader(GL_FRAGMENT_SHADER); - - _wglShaderSource(fsh, macros + shaderSourceCacheFSH); - _wglCompileShader(fsh); - - if(_wglGetShaderi(fsh, GL_COMPILE_STATUS) != GL_TRUE) { - LOGGER.error("Failed to compile GL_FRAGMENT_SHADER for state {} !", getStateBits(bits, 11)); - String log = _wglGetShaderInfoLog(fsh); - if(log != null) { - String[] lines = log.split("(\\r\\n|\\r|\\n)"); - for(int i = 0; i < lines.length; ++i) { - LOGGER.error("[FRAG] {}", lines[i]); - } - } - _wglDeleteShader(fsh); - _wglDeleteShader(vsh); - throw new IllegalStateException("Fragment shader could not be compiled!"); - } - - IProgramGL prog = _wglCreateProgram(); - - _wglAttachShader(prog, vsh); - _wglAttachShader(prog, fsh); - - IllegalStateException err = null; - try { - pp = new FixedFunctionPipeline(bits, prog); - }catch(IllegalStateException t) { - err = t; - } - - _wglDetachShader(prog, vsh); - _wglDetachShader(prog, fsh); - _wglDeleteShader(fsh); - _wglDeleteShader(vsh); - - if(err != null) { - _wglDeleteProgram(prog); - throw err; - }else { - pipelineStateCache[bits] = pp; - } + pipelineStateCache[bits] = pp = makeNewPipeline(bits, 0, false); } return pp; } - private static String getStateBits(int input, int bits) { - String out = ""; - for(int i = bits - 1; i >= 0; --i) { - out += (input >> bits) & 1; + private static FixedFunctionPipeline getPipelineInstanceExt(int coreBits, int extBits) { + coreBits &= (15 | extensionProvider.getCoreStateMask(extBits)); + FixedFunctionPipeline[] pp = pipelineExtStateCache[coreBits]; + if(pp == null) { + pipelineExtStateCache[coreBits] = pp = new FixedFunctionPipeline[1 << extensionProvider.getExtensionStatesCount()]; + return pp[extBits] = makeNewPipeline(coreBits, extBits, true); + }else { + FixedFunctionPipeline ppp = pp[extBits]; + if(ppp == null) { + pp[extBits] = ppp = makeNewPipeline(coreBits, extBits, true); + } + return ppp; } - return out; + } + + private static FixedFunctionPipeline makeNewPipeline(int coreBits, int extBits, boolean enableExt) { + String vshSource; + String fshSource; + + Object[] extProviderUserPointer = null; + if(enableExt) { + extProviderUserPointer = new Object[1]; + String[] extSource = extensionProvider.getShaderSource(coreBits, extBits, extProviderUserPointer); + vshSource = extSource[0]; + fshSource = extSource[1]; + }else { + if(shaderSourceCacheVSH == null) { + shaderSourceCacheVSH = EagRuntime.getResourceString(FILENAME_VSH); + if(shaderSourceCacheVSH == null) { + throw new RuntimeException("Could not load: " + FILENAME_VSH); + } + } + vshSource = shaderSourceCacheVSH; + if(shaderSourceCacheFSH == null) { + shaderSourceCacheFSH = EagRuntime.getResourceString(FILENAME_FSH); + if(shaderSourceCacheFSH == null) { + throw new RuntimeException("Could not load: " + FILENAME_FSH); + } + } + fshSource = shaderSourceCacheFSH; + } + + StringBuilder macros = new StringBuilder(VERSION + "\n"); + if((coreBits & STATE_HAS_ATTRIB_TEXTURE) != 0) { + macros.append("#define " + MACRO_ATTRIB_TEXTURE + "\n"); + } + if((coreBits & STATE_HAS_ATTRIB_COLOR) != 0) { + macros.append("#define " + MACRO_ATTRIB_COLOR + "\n"); + } + if((coreBits & STATE_HAS_ATTRIB_NORMAL) != 0) { + macros.append("#define " + MACRO_ATTRIB_NORMAL + "\n"); + } + if((coreBits & STATE_HAS_ATTRIB_LIGHTMAP) != 0) { + macros.append("#define " + MACRO_ATTRIB_LIGHTMAP + "\n"); + } + if((coreBits & STATE_ENABLE_TEXTURE2D) != 0) { + macros.append("#define " + MACRO_ENABLE_TEXTURE2D + "\n"); + } + if((coreBits & STATE_ENABLE_LIGHTMAP) != 0) { + macros.append("#define " + MACRO_ENABLE_LIGHTMAP + "\n"); + } + if((coreBits & STATE_ENABLE_ALPHA_TEST) != 0) { + macros.append("#define " + MACRO_ENABLE_ALPHA_TEST + "\n"); + } + if((coreBits & STATE_ENABLE_MC_LIGHTING) != 0) { + macros.append("#define " + MACRO_ENABLE_MC_LIGHTING + "\n"); + } + if((coreBits & STATE_ENABLE_END_PORTAL) != 0) { + macros.append("#define " + MACRO_ENABLE_END_PORTAL + "\n"); + } + if((coreBits & STATE_ENABLE_ANISOTROPIC_FIX) != 0) { + macros.append("#define " + MACRO_ENABLE_ANISOTROPIC_FIX + "\n"); + } + if((coreBits & STATE_ENABLE_FOG) != 0) { + macros.append("#define " + MACRO_ENABLE_FOG + "\n"); + } + if((coreBits & STATE_ENABLE_BLEND_ADD) != 0) { + macros.append("#define " + MACRO_ENABLE_BLEND_ADD + "\n"); + } + + macros.append("precision " + PRECISION_INT + " int;\n"); + macros.append("precision " + PRECISION_FLOAT + " float;\n"); + macros.append("precision " + PRECISION_SAMPLER + " sampler2D;\n\n"); + + IShaderGL vsh = _wglCreateShader(GL_VERTEX_SHADER); + + _wglShaderSource(vsh, macros.toString() + vshSource); + _wglCompileShader(vsh); + + if(_wglGetShaderi(vsh, GL_COMPILE_STATUS) != GL_TRUE) { + LOGGER.error("Failed to compile GL_VERTEX_SHADER for state {} !", (visualizeBits(coreBits) + (enableExt && extBits != 0 ? " ext " + visualizeBits(extBits) : ""))); + String log = _wglGetShaderInfoLog(vsh); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + LOGGER.error("[VERT] {}", lines[i]); + } + } + _wglDeleteShader(vsh); + throw new IllegalStateException("Vertex shader could not be compiled!"); + } + + IShaderGL fsh = _wglCreateShader(GL_FRAGMENT_SHADER); + + _wglShaderSource(fsh, macros.toString() + fshSource); + _wglCompileShader(fsh); + + if(_wglGetShaderi(fsh, GL_COMPILE_STATUS) != GL_TRUE) { + LOGGER.error("Failed to compile GL_FRAGMENT_SHADER for state {} !", (visualizeBits(coreBits) + (enableExt && extBits != 0 ? " ext " + visualizeBits(extBits) : ""))); + String log = _wglGetShaderInfoLog(fsh); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + LOGGER.error("[FRAG] {}", lines[i]); + } + } + _wglDeleteShader(fsh); + _wglDeleteShader(vsh); + throw new IllegalStateException("Fragment shader could not be compiled!"); + } + + IProgramGL prog = _wglCreateProgram(); + + _wglAttachShader(prog, vsh); + _wglAttachShader(prog, fsh); + + FixedFunctionPipeline pp = null; + IllegalStateException err = null; + try { + pp = new FixedFunctionPipeline(coreBits, extBits, prog); + }catch(IllegalStateException t) { + err = t; + } + + _wglDetachShader(prog, vsh); + _wglDetachShader(prog, fsh); + _wglDeleteShader(fsh); + _wglDeleteShader(vsh); + + if(err != null) { + _wglDeleteProgram(prog); + throw err; + }else { + if(extProviderUserPointer != null) { + pp.extensionPointer = extProviderUserPointer; + extensionProvider.initializeNewShader(prog, pp.stateCoreBits, pp.stateExtBits, extProviderUserPointer); + } + pipelineListTracker.add(pp); + return pp; + } + } + + public static String visualizeBits(int i) { + if(i == 0) { + return "0"; + } + StringBuilder sb = new StringBuilder(); + int j = 0, k = 0, l = 0; + do { + k = i & (1 << j); + if(k > 0) { + if(l++ > 0) { + sb.append(' '); + } + sb.append(k); + } + ++j; + }while(i >= (1 << j)); + return sb.toString(); } private final int stateBits; + private final int stateCoreBits; + private final int stateExtBits; + private Object[] extensionPointer; private final boolean stateHasAttribTexture; private final boolean stateHasAttribColor; private final boolean stateHasAttribNormal; @@ -401,6 +481,8 @@ class FixedFunctionPipeline { private final IUniformGL stateProjectionMatrixUniformMat4f; private int stateProjectionMatrixSerial = -1; + private final IUniformGL stateModelProjectionMatrixUniformMat4f; + // implement only 2 textures private final IUniformGL stateTextureMatrix01UniformMat4f; private final IUniformGL stateTextureMatrix02UniformMat4f; @@ -418,34 +500,33 @@ class FixedFunctionPipeline { private float stateAnisotropicFixH = -999.0f; private float stateAnisotropicFixSerial = 0; - private final IBufferArrayGL vertexArray; - private final IBufferGL vertexBuffer; - private int vertexBufferSize = -1; - - private boolean bindQuad16 = false; - private boolean bindQuad32 = false; - + private final StreamBuffer streamBuffer; + private StreamBufferInstance currentVertexArray = null; + private static FloatBuffer matrixCopyBuffer = null; - - private FixedFunctionPipeline(int bits, IProgramGL compiledProg) { + + private FixedFunctionPipeline(int bits, int extBits, IProgramGL compiledProg) { shaderProgram = compiledProg; stateBits = bits; - stateHasAttribTexture = (bits & STATE_HAS_ATTRIB_TEXTURE) == STATE_HAS_ATTRIB_TEXTURE; - stateHasAttribColor = (bits & STATE_HAS_ATTRIB_COLOR) == STATE_HAS_ATTRIB_COLOR; - stateHasAttribNormal = (bits & STATE_HAS_ATTRIB_NORMAL) == STATE_HAS_ATTRIB_NORMAL; - stateHasAttribLightmap = (bits & STATE_HAS_ATTRIB_LIGHTMAP) == STATE_HAS_ATTRIB_LIGHTMAP; + stateHasAttribTexture = (bits & STATE_HAS_ATTRIB_TEXTURE) != 0; + stateHasAttribColor = (bits & STATE_HAS_ATTRIB_COLOR) != 0; + stateHasAttribNormal = (bits & STATE_HAS_ATTRIB_NORMAL) != 0; + stateHasAttribLightmap = (bits & STATE_HAS_ATTRIB_LIGHTMAP) != 0; + + stateCoreBits = bits; + stateExtBits = extBits; int index = 0; int stride = 0; - _wglBindAttribLocation(compiledProg, index, FixedFunctionConstants.ATTRIB_POSITION); + _wglBindAttribLocation(compiledProg, index, ATTRIB_POSITION); stride += VertexFormat.COMPONENT_POSITION_STRIDE; // vec3f if(stateHasAttribColor) { attribColorIndex = ++index; attribColorOffset = stride; - _wglBindAttribLocation(compiledProg, index, FixedFunctionConstants.ATTRIB_COLOR); + _wglBindAttribLocation(compiledProg, index, ATTRIB_COLOR); stride += VertexFormat.COMPONENT_COLOR_STRIDE; // vec4b }else { attribColorIndex = -1; @@ -454,7 +535,7 @@ class FixedFunctionPipeline { if(stateHasAttribTexture) { attribTextureIndex = ++index; attribTextureOffset = stride; - _wglBindAttribLocation(compiledProg, index, FixedFunctionConstants.ATTRIB_TEXTURE); + _wglBindAttribLocation(compiledProg, index, ATTRIB_TEXTURE); stride += VertexFormat.COMPONENT_TEX_STRIDE; // vec2f }else { attribTextureIndex = -1; @@ -463,7 +544,7 @@ class FixedFunctionPipeline { if(stateHasAttribNormal) { attribNormalIndex = ++index; attribNormalOffset = stride; - _wglBindAttribLocation(compiledProg, index, FixedFunctionConstants.ATTRIB_NORMAL); + _wglBindAttribLocation(compiledProg, index, ATTRIB_NORMAL); stride += VertexFormat.COMPONENT_NORMAL_STRIDE; // vec4b }else { attribNormalIndex = -1; @@ -472,7 +553,7 @@ class FixedFunctionPipeline { if(stateHasAttribLightmap) { attribLightmapIndex = ++index; attribLightmapOffset = stride; - _wglBindAttribLocation(compiledProg, index, FixedFunctionConstants.ATTRIB_LIGHTMAP); + _wglBindAttribLocation(compiledProg, index, ATTRIB_LIGHTMAP); stride += VertexFormat.COMPONENT_LIGHTMAP_STRIDE; // vec2s }else { attribLightmapIndex = -1; @@ -484,7 +565,7 @@ class FixedFunctionPipeline { _wglLinkProgram(compiledProg); if(_wglGetProgrami(compiledProg, GL_LINK_STATUS) != GL_TRUE) { - LOGGER.error("Program could not be linked for state {} !", getStateBits(bits, 11)); + LOGGER.error("Program could not be linked for state {} !", (visualizeBits(bits) + (extensionProvider != null && extBits != 0 ? " ext " + visualizeBits(extBits) : ""))); String log = _wglGetProgramInfoLog(compiledProg); if(log != null) { String[] lines = log.split("(\\r\\n|\\r|\\n)"); @@ -495,40 +576,40 @@ class FixedFunctionPipeline { throw new IllegalStateException("Program could not be linked!"); } - vertexArray = PlatformOpenGL._wglGenVertexArrays(); - vertexBuffer = PlatformOpenGL._wglGenBuffers(); + streamBuffer = new StreamBuffer(FixedFunctionShader.initialSize, FixedFunctionShader.initialCount, + FixedFunctionShader.maxCount, (vertexArray, vertexBuffer) -> { + EaglercraftGPU.bindGLBufferArray(vertexArray); + EaglercraftGPU.bindGLArrayBuffer(vertexBuffer); - EaglercraftGPU.bindGLBufferArray(vertexArray); - EaglercraftGPU.bindGLArrayBuffer(vertexBuffer); - - _wglEnableVertexAttribArray(0); - _wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE, - VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0); + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE, + VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0); + + if(attribTextureIndex != -1) { + _wglEnableVertexAttribArray(attribTextureIndex); + _wglVertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE, + VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset); + } + + if(attribColorIndex != -1) { + _wglEnableVertexAttribArray(attribColorIndex); + _wglVertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE, + VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset); + } + + if(attribNormalIndex != -1) { + _wglEnableVertexAttribArray(attribNormalIndex); + _wglVertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE, + VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset); + } + + if(attribLightmapIndex != -1) { + _wglEnableVertexAttribArray(attribLightmapIndex); + _wglVertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE, + VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset); + } + }); - if(attribTextureIndex != -1) { - _wglEnableVertexAttribArray(attribTextureIndex); - _wglVertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE, - VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset); - } - - if(attribColorIndex != -1) { - _wglEnableVertexAttribArray(attribColorIndex); - _wglVertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE, - VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset); - } - - if(attribNormalIndex != -1) { - _wglEnableVertexAttribArray(attribNormalIndex); - _wglVertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE, - VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset); - } - - if(attribLightmapIndex != -1) { - _wglEnableVertexAttribArray(attribLightmapIndex); - _wglVertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE, - VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset); - } - stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) == STATE_ENABLE_TEXTURE2D; stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) == STATE_ENABLE_LIGHTMAP; stateEnableAlphaTest = (bits & STATE_ENABLE_ALPHA_TEST) == STATE_ENABLE_ALPHA_TEST; @@ -547,85 +628,87 @@ class FixedFunctionPipeline { } stateColorUniform4f = _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_COLOR_NAME); + UNIFORM_COLOR_NAME); stateAlphaTestUniform1f = stateEnableAlphaTest ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_ALPHA_TEST_NAME) : null; + UNIFORM_ALPHA_TEST_NAME) : null; stateLightsEnabledUniform1i = stateEnableMCLighting ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_LIGHTS_ENABLED_NAME) : null; + UNIFORM_LIGHTS_ENABLED_NAME) : null; if(stateEnableMCLighting) { for(int i = 0; i < stateLightsVectorsArrayUniform4f.length; ++i) { stateLightsVectorsArrayUniform4f[i] =_wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_LIGHTS_VECTORS_NAME + "[" + i + "]"); + UNIFORM_LIGHTS_VECTORS_NAME + "[" + i + "]"); } } stateLightingAmbientUniform3f = stateEnableMCLighting ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_LIGHTS_AMBIENT_NAME) : null; + UNIFORM_LIGHTS_AMBIENT_NAME) : null; stateNormalUniform3f = (!stateHasAttribNormal && stateEnableMCLighting) ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_CONSTANT_NORMAL_NAME) : null; + UNIFORM_CONSTANT_NORMAL_NAME) : null; stateFogParamUniform4f = stateEnableFog ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_FOG_PARAM_NAME) : null; + UNIFORM_FOG_PARAM_NAME) : null; stateFogColorUniform4f = stateEnableFog ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_FOG_COLOR_NAME) : null; + UNIFORM_FOG_COLOR_NAME) : null; stateTexGenPlaneUniform4i = stateEnableEndPortal ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEX_GEN_PLANE_NAME) : null; + UNIFORM_TEX_GEN_PLANE_NAME) : null; stateTexGenSVectorUniform4f = stateEnableEndPortal ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEX_GEN_S_NAME) : null; + UNIFORM_TEX_GEN_S_NAME) : null; stateTexGenTVectorUniform4f = stateEnableEndPortal ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEX_GEN_T_NAME) : null; + UNIFORM_TEX_GEN_T_NAME) : null; stateTexGenRVectorUniform4f = stateEnableEndPortal ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEX_GEN_R_NAME) : null; + UNIFORM_TEX_GEN_R_NAME) : null; stateTexGenQVectorUniform4f = stateEnableEndPortal ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEX_GEN_Q_NAME) : null; + UNIFORM_TEX_GEN_Q_NAME) : null; stateModelMatrixUniformMat4f = _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_MODEL_MATRIX_NAME); + UNIFORM_MODEL_MATRIX_NAME); stateProjectionMatrixUniformMat4f = _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_PROJECTION_MATRIX_NAME); + UNIFORM_PROJECTION_MATRIX_NAME); + + stateModelProjectionMatrixUniformMat4f = _wglGetUniformLocation(compiledProg, + UNIFORM_MODEL_PROJECTION_MATRIX_NAME); stateTextureMatrix01UniformMat4f = (stateEnableEndPortal || stateHasAttribTexture) ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEXTURE_MATRIX_01_NAME) : null; + UNIFORM_TEXTURE_MATRIX_01_NAME) : null; stateTextureMatrix02UniformMat4f = stateHasAttribLightmap ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEXTURE_MATRIX_02_NAME) : null; + UNIFORM_TEXTURE_MATRIX_02_NAME) : null; stateTextureCoords01Uniform2f = (!stateHasAttribTexture && stateEnableTexture2D) ? _wglGetUniformLocation( - compiledProg, FixedFunctionConstants.UNIFORM_TEXTURE_COORDS_01_NAME) : null; + compiledProg, UNIFORM_TEXTURE_COORDS_01_NAME) : null; stateTextureCoords02Uniform2f = (!stateHasAttribLightmap && stateEnableLightmap) ? _wglGetUniformLocation( - compiledProg, FixedFunctionConstants.UNIFORM_TEXTURE_COORDS_02_NAME) : null; + compiledProg, UNIFORM_TEXTURE_COORDS_02_NAME) : null; stateAnisotropicFix2f = stateEnableAnisotropicFix ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_TEXTURE_ANISOTROPIC_FIX) : null; + UNIFORM_TEXTURE_ANISOTROPIC_FIX) : null; stateShaderBlendSrcColorUniform4f = stateEnableBlendAdd ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_BLEND_SRC_COLOR_NAME) : null; + UNIFORM_BLEND_SRC_COLOR_NAME) : null; stateShaderBlendAddColorUniform4f = stateEnableBlendAdd ? _wglGetUniformLocation(compiledProg, - FixedFunctionConstants.UNIFORM_BLEND_ADD_COLOR_NAME) : null; + UNIFORM_BLEND_ADD_COLOR_NAME) : null; if(stateEnableTexture2D) { EaglercraftGPU.bindGLShaderProgram(compiledProg); - _wglUniform1i(_wglGetUniformLocation(compiledProg, FixedFunctionConstants.UNIFORM_TEXTURE_UNIT_01_NAME), 0); + _wglUniform1i(_wglGetUniformLocation(compiledProg, UNIFORM_TEXTURE_UNIT_01_NAME), 0); } if(stateEnableLightmap) { EaglercraftGPU.bindGLShaderProgram(compiledProg); - _wglUniform1i(_wglGetUniformLocation(compiledProg, FixedFunctionConstants.UNIFORM_TEXTURE_UNIT_02_NAME), 1); + _wglUniform1i(_wglGetUniformLocation(compiledProg, UNIFORM_TEXTURE_UNIT_02_NAME), 1); } - } public FixedFunctionPipeline update() { @@ -653,24 +736,48 @@ class FixedFunctionPipeline { matrixCopyBuffer = PlatformRuntime.allocateFloatBuffer(16); } - int ptr = GlStateManager.modelMatrixStackPointer; - serial = GlStateManager.modelMatrixStackAccessSerial[ptr]; - if(stateModelMatrixSerial != serial) { - stateModelMatrixSerial = serial; - matrixCopyBuffer.clear(); - GlStateManager.modelMatrixStack[ptr].store(matrixCopyBuffer); - matrixCopyBuffer.flip(); - _wglUniformMatrix4fv(stateModelMatrixUniformMat4f, false, matrixCopyBuffer); - } - - ptr = GlStateManager.projectionMatrixStackPointer; - serial = GlStateManager.projectionMatrixStackAccessSerial[ptr]; - if(stateProjectionMatrixSerial != serial) { - stateProjectionMatrixSerial = serial; - matrixCopyBuffer.clear(); - GlStateManager.projectionMatrixStack[ptr].store(matrixCopyBuffer); - matrixCopyBuffer.flip(); - _wglUniformMatrix4fv(stateProjectionMatrixUniformMat4f, false, matrixCopyBuffer); + int ptr; + if(stateModelProjectionMatrixUniformMat4f == null) { + ptr = GlStateManager.modelMatrixStackPointer; + serial = GlStateManager.modelMatrixStackAccessSerial[ptr]; + if(stateModelMatrixSerial != serial) { + stateModelMatrixSerial = serial; + matrixCopyBuffer.clear(); + GlStateManager.modelMatrixStack[ptr].store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(stateModelMatrixUniformMat4f, false, matrixCopyBuffer); + } + + ptr = GlStateManager.projectionMatrixStackPointer; + serial = GlStateManager.projectionMatrixStackAccessSerial[ptr]; + if(stateProjectionMatrixSerial != serial) { + stateProjectionMatrixSerial = serial; + matrixCopyBuffer.clear(); + GlStateManager.projectionMatrixStack[ptr].store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(stateProjectionMatrixUniformMat4f, false, matrixCopyBuffer); + } + }else { + ptr = GlStateManager.modelMatrixStackPointer; + serial = GlStateManager.modelMatrixStackAccessSerial[ptr]; + int ptr2 = GlStateManager.projectionMatrixStackPointer; + int serial2 = GlStateManager.projectionMatrixStackAccessSerial[ptr2]; + boolean b = stateModelMatrixSerial != serial; + if(b || stateProjectionMatrixSerial != serial2) { + stateModelMatrixSerial = serial; + stateProjectionMatrixSerial = serial2; + if(b && stateModelMatrixUniformMat4f != null) { + matrixCopyBuffer.clear(); + GlStateManager.modelMatrixStack[ptr].store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(stateModelMatrixUniformMat4f, false, matrixCopyBuffer); + } + Matrix4f.mul(GlStateManager.projectionMatrixStack[ptr2], GlStateManager.modelMatrixStack[ptr], tmpMatrixForInv); + matrixCopyBuffer.clear(); + tmpMatrixForInv.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(stateModelProjectionMatrixUniformMat4f, false, matrixCopyBuffer); + } } if(stateEnableAlphaTest) { @@ -949,27 +1056,55 @@ class FixedFunctionPipeline { } } + if(extensionProvider != null && extensionPointer != null) { + extensionProvider.updatePipeline(shaderProgram, stateCoreBits, stateExtBits, extensionPointer); + } + return this; } - + + static void optimize() { + FixedFunctionPipeline pp; + for(int i = 0, l = pipelineListTracker.size(); i < l; ++i) { + pipelineListTracker.get(i).streamBuffer.optimize(); + } + } + public static void flushCache() { shaderSourceCacheVSH = null; shaderSourceCacheFSH = null; + FixedFunctionPipeline pp; for(int i = 0; i < pipelineStateCache.length; ++i) { - if(pipelineStateCache[i] != null) { - pipelineStateCache[i].destroy(); + pp = pipelineStateCache[i]; + if(pp != null) { + pp.destroy(); pipelineStateCache[i] = null; } } + for(int i = 0; i < pipelineExtStateCache.length; ++i) { + FixedFunctionPipeline[] ppp = pipelineExtStateCache[i]; + if(ppp != null) { + for(int j = 0; j < ppp.length; ++j) { + FixedFunctionPipeline pppp = ppp[j]; + if(pppp != null) { + pppp.destroy(); + if(extensionProvider != null && pppp.extensionPointer != null) { + extensionProvider.destroyPipeline(pppp.shaderProgram, pppp.stateCoreBits, pppp.stateExtBits, pppp.extensionPointer); + } + } + } + pipelineExtStateCache[i] = null; + } + } + pipelineListTracker.clear(); } public void destroy() { PlatformOpenGL._wglDeleteProgram(shaderProgram); - PlatformOpenGL._wglDeleteVertexArrays(vertexArray); - PlatformOpenGL._wglDeleteBuffers(vertexBuffer); + streamBuffer.destroy(); } public IBufferArrayGL getDirectModeBufferArray() { - return vertexArray; + return currentVertexArray.vertexArray; } } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionShader.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionShader.java index c990efe..9fd4ddb 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionShader.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/FixedFunctionShader.java @@ -13,66 +13,92 @@ package net.lax1dude.eaglercraft.v1_8.opengl; * (please read the 'LICENSE' file this repo's root directory for more info) * */ -class FixedFunctionShader { +public class FixedFunctionShader { - class FixedFunctionConstants { + public static final int initialSize = 0x8000; + public static final int initialCount = 3; + public static final int maxCount = 8; - static final String VERSION = "#version 300 es"; - static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh"; - static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh"; + public class FixedFunctionState { - static final String PRECISION_INT = "lowp"; - static final String PRECISION_FLOAT = "mediump"; - static final String PRECISION_SAMPLER = "lowp"; - - static final String MACRO_ATTRIB_TEXTURE = "COMPILE_TEXTURE_ATTRIB"; - static final String MACRO_ATTRIB_COLOR = "COMPILE_COLOR_ATTRIB"; - static final String MACRO_ATTRIB_NORMAL = "COMPILE_NORMAL_ATTRIB"; - static final String MACRO_ATTRIB_LIGHTMAP = "COMPILE_LIGHTMAP_ATTRIB"; - - static final String MACRO_ENABLE_TEXTURE2D = "COMPILE_ENABLE_TEXTURE2D"; - static final String MACRO_ENABLE_LIGHTMAP = "COMPILE_ENABLE_LIGHTMAP"; - static final String MACRO_ENABLE_ALPHA_TEST = "COMPILE_ENABLE_ALPHA_TEST"; - static final String MACRO_ENABLE_MC_LIGHTING = "COMPILE_ENABLE_MC_LIGHTING"; - static final String MACRO_ENABLE_END_PORTAL = "COMPILE_ENABLE_TEX_GEN"; - static final String MACRO_ENABLE_ANISOTROPIC_FIX = "COMPILE_ENABLE_ANISOTROPIC_FIX"; - static final String MACRO_ENABLE_FOG = "COMPILE_ENABLE_FOG"; - static final String MACRO_ENABLE_BLEND_ADD = "COMPILE_BLEND_ADD"; + public static final int fixedFunctionStatesCount = 12; + public static final int fixedFunctionStatesBits = (1 << 12) - 1; + public static final int extentionStateBits = fixedFunctionStatesBits ^ 0xFFFFFFFF; - static final String ATTRIB_POSITION = "a_position3f"; - static final String ATTRIB_TEXTURE = "a_texture2f"; - static final String ATTRIB_COLOR = "a_color4f"; - static final String ATTRIB_NORMAL = "a_normal4f"; - static final String ATTRIB_LIGHTMAP = "a_lightmap2f"; + public static final int STATE_HAS_ATTRIB_TEXTURE = 1; + public static final int STATE_HAS_ATTRIB_COLOR = 2; + public static final int STATE_HAS_ATTRIB_NORMAL = 4; + public static final int STATE_HAS_ATTRIB_LIGHTMAP = 8; + public static final int STATE_ENABLE_TEXTURE2D = 16; + public static final int STATE_ENABLE_LIGHTMAP = 32; + public static final int STATE_ENABLE_ALPHA_TEST = 64; + public static final int STATE_ENABLE_MC_LIGHTING = 128; + public static final int STATE_ENABLE_END_PORTAL = 256; + public static final int STATE_ENABLE_ANISOTROPIC_FIX = 512; + public static final int STATE_ENABLE_FOG = 1024; + public static final int STATE_ENABLE_BLEND_ADD = 2048; - static final String UNIFORM_COLOR_NAME = "u_color4f"; - static final String UNIFORM_BLEND_SRC_COLOR_NAME = "u_colorBlendSrc4f"; - static final String UNIFORM_BLEND_ADD_COLOR_NAME = "u_colorBlendAdd4f"; - static final String UNIFORM_ALPHA_TEST_NAME = "u_alphaTestRef1f"; - static final String UNIFORM_LIGHTS_ENABLED_NAME = "u_lightsEnabled1i"; - static final String UNIFORM_LIGHTS_VECTORS_NAME = "u_lightsDirections4fv"; - static final String UNIFORM_LIGHTS_AMBIENT_NAME = "u_lightsAmbient3f"; - static final String UNIFORM_CONSTANT_NORMAL_NAME = "u_uniformNormal3f"; - static final String UNIFORM_FOG_PARAM_NAME = "u_fogParameters4f"; - static final String UNIFORM_FOG_COLOR_NAME = "u_fogColor4f"; - static final String UNIFORM_TEX_GEN_S_NAME = "u_texGenS4f"; - static final String UNIFORM_TEX_GEN_T_NAME = "u_texGenT4f"; - static final String UNIFORM_TEX_GEN_R_NAME = "u_texGenR4f"; - static final String UNIFORM_TEX_GEN_Q_NAME = "u_texGenQ4f"; - static final String UNIFORM_MODEL_MATRIX_NAME = "u_modelviewMat4f"; - static final String UNIFORM_TEX_GEN_PLANE_NAME = "u_texGenPlane4i"; - static final String UNIFORM_PROJECTION_MATRIX_NAME = "u_projectionMat4f"; - static final String UNIFORM_TEXTURE_COORDS_01_NAME = "u_textureCoords01"; - static final String UNIFORM_TEXTURE_MATRIX_01_NAME = "u_textureMat4f01"; - static final String UNIFORM_TEXTURE_COORDS_02_NAME = "u_textureCoords02"; - static final String UNIFORM_TEXTURE_MATRIX_02_NAME = "u_textureMat4f02"; - static final String UNIFORM_TEXTURE_ANISOTROPIC_FIX = "u_textureAnisotropicFix"; - - static final String UNIFORM_TEXTURE_UNIT_01_NAME = "u_samplerTexture"; - static final String UNIFORM_TEXTURE_UNIT_02_NAME = "u_samplerLightmap"; - - static final String OUTPUT_COLOR = "output4f"; - } - + + public class FixedFunctionConstants { + + public static final String VERSION = "#version 300 es"; + public static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh"; + public static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh"; + + public static final String PRECISION_INT = "lowp"; + public static final String PRECISION_FLOAT = "highp"; + public static final String PRECISION_SAMPLER = "mediump"; + + public static final String MACRO_ATTRIB_TEXTURE = "COMPILE_TEXTURE_ATTRIB"; + public static final String MACRO_ATTRIB_COLOR = "COMPILE_COLOR_ATTRIB"; + public static final String MACRO_ATTRIB_NORMAL = "COMPILE_NORMAL_ATTRIB"; + public static final String MACRO_ATTRIB_LIGHTMAP = "COMPILE_LIGHTMAP_ATTRIB"; + + public static final String MACRO_ENABLE_TEXTURE2D = "COMPILE_ENABLE_TEXTURE2D"; + public static final String MACRO_ENABLE_LIGHTMAP = "COMPILE_ENABLE_LIGHTMAP"; + public static final String MACRO_ENABLE_ALPHA_TEST = "COMPILE_ENABLE_ALPHA_TEST"; + public static final String MACRO_ENABLE_MC_LIGHTING = "COMPILE_ENABLE_MC_LIGHTING"; + public static final String MACRO_ENABLE_END_PORTAL = "COMPILE_ENABLE_TEX_GEN"; + public static final String MACRO_ENABLE_ANISOTROPIC_FIX = "COMPILE_ENABLE_ANISOTROPIC_FIX"; + public static final String MACRO_ENABLE_FOG = "COMPILE_ENABLE_FOG"; + public static final String MACRO_ENABLE_BLEND_ADD = "COMPILE_BLEND_ADD"; + + public static final String ATTRIB_POSITION = "a_position3f"; + public static final String ATTRIB_TEXTURE = "a_texture2f"; + public static final String ATTRIB_COLOR = "a_color4f"; + public static final String ATTRIB_NORMAL = "a_normal4f"; + public static final String ATTRIB_LIGHTMAP = "a_lightmap2f"; + + public static final String UNIFORM_COLOR_NAME = "u_color4f"; + public static final String UNIFORM_BLEND_SRC_COLOR_NAME = "u_colorBlendSrc4f"; + public static final String UNIFORM_BLEND_ADD_COLOR_NAME = "u_colorBlendAdd4f"; + public static final String UNIFORM_ALPHA_TEST_NAME = "u_alphaTestRef1f"; + public static final String UNIFORM_LIGHTS_ENABLED_NAME = "u_lightsEnabled1i"; + public static final String UNIFORM_LIGHTS_VECTORS_NAME = "u_lightsDirections4fv"; + public static final String UNIFORM_LIGHTS_AMBIENT_NAME = "u_lightsAmbient3f"; + public static final String UNIFORM_CONSTANT_NORMAL_NAME = "u_uniformNormal3f"; + public static final String UNIFORM_FOG_PARAM_NAME = "u_fogParameters4f"; + public static final String UNIFORM_FOG_COLOR_NAME = "u_fogColor4f"; + public static final String UNIFORM_TEX_GEN_S_NAME = "u_texGenS4f"; + public static final String UNIFORM_TEX_GEN_T_NAME = "u_texGenT4f"; + public static final String UNIFORM_TEX_GEN_R_NAME = "u_texGenR4f"; + public static final String UNIFORM_TEX_GEN_Q_NAME = "u_texGenQ4f"; + public static final String UNIFORM_MODEL_MATRIX_NAME = "u_modelviewMat4f"; + public static final String UNIFORM_TEX_GEN_PLANE_NAME = "u_texGenPlane4i"; + public static final String UNIFORM_PROJECTION_MATRIX_NAME = "u_projectionMat4f"; + public static final String UNIFORM_MODEL_PROJECTION_MATRIX_NAME = "u_modelviewProjMat4f"; + public static final String UNIFORM_TEXTURE_COORDS_01_NAME = "u_textureCoords01"; + public static final String UNIFORM_TEXTURE_MATRIX_01_NAME = "u_textureMat4f01"; + public static final String UNIFORM_TEXTURE_COORDS_02_NAME = "u_textureCoords02"; + public static final String UNIFORM_TEXTURE_MATRIX_02_NAME = "u_textureMat4f02"; + public static final String UNIFORM_TEXTURE_ANISOTROPIC_FIX = "u_textureAnisotropicFix"; + + public static final String UNIFORM_TEXTURE_UNIT_01_NAME = "u_samplerTexture"; + public static final String UNIFORM_TEXTURE_UNIT_02_NAME = "u_samplerLightmap"; + + public static final String OUTPUT_COLOR = "output4f"; + + } + } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java index 2c2ff44..3626f9f 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java @@ -54,13 +54,14 @@ public class GlStateManager { static float stateShaderBlendAddColorA = 0.0f; static int stateShaderBlendColorSerial = 0; static boolean stateEnableShaderBlendColor = false; - + static boolean stateBlend = false; + static boolean stateGlobalBlend = true; static int stateBlendEquation = -1; static int stateBlendSRC = -1; static int stateBlendDST = -1; static boolean stateEnableOverlayFramebufferBlending = false; - + static boolean stateAlphaTest = false; static float stateAlphaTestRef = 0.1f; @@ -127,7 +128,12 @@ public class GlStateManager { Vector4f vector = new Vector4f(); } - + + static float blendConstantR = -999.0f; + static float blendConstantG = -999.0f; + static float blendConstantB = -999.0f; + static float blendConstantA = -999.0f; + static int stateTexGenSerial = 0; static int stateMatrixMode = GL_MODELVIEW; @@ -151,6 +157,8 @@ public class GlStateManager { static int[] textureMatrixAccessSerial = new int[8]; static int[] textureMatrixStackPointer = new int[8]; + static boolean stateUseExtensionPipeline = false; + private static final Matrix4f tmpInvertedMatrix = new Matrix4f(); static { @@ -237,7 +245,19 @@ public class GlStateManager { public static final void disableLighting() { stateLighting = false; } - + + public static final void enableExtensionPipeline() { + stateUseExtensionPipeline = true; + } + + public static final void disableExtensionPipeline() { + stateUseExtensionPipeline = false; + } + + public static final boolean isExtensionPipeline() { + return stateUseExtensionPipeline; + } + private static final Vector4f paramVector4 = new Vector4f(); public static final void enableMCLight(int light, float diffuse, double dirX, double dirY, double dirZ, double dirW) { @@ -324,18 +344,32 @@ public class GlStateManager { public static final void disableBlend() { if(stateBlend) { - _wglDisable(GL_BLEND); + if(stateGlobalBlend) _wglDisable(GL_BLEND); stateBlend = false; } } public static final void enableBlend() { if(!stateBlend) { - _wglEnable(GL_BLEND); + if(stateGlobalBlend) _wglEnable(GL_BLEND); stateBlend = true; } } + public static final void globalDisableBlend() { + if(stateBlend) { + _wglDisable(GL_BLEND); + } + stateGlobalBlend = false; + } + + public static final void globalEnableBlend() { + if(stateBlend) { + _wglEnable(GL_BLEND); + } + stateGlobalBlend = true; + } + public static final void blendFunc(int srcFactor, int dstFactor) { if(stateEnableOverlayFramebufferBlending) { tryBlendFuncSeparate(srcFactor, dstFactor, 0, 1); @@ -396,6 +430,16 @@ public class GlStateManager { stateEnableShaderBlendColor = false; } + public static final void setBlendConstants(float r, float g, float b, float a) { + if(r != blendConstantR || g != blendConstantG || b != blendConstantB || a != blendConstantA) { + _wglBlendColor(r, g, b, a); + blendConstantR = r; + blendConstantG = g; + blendConstantB = b; + blendConstantA = a; + } + } + public static final void enableFog() { stateFog = true; } @@ -468,7 +512,7 @@ public class GlStateManager { } public static final void enableColorLogic() { - System.err.println("TODO: rewrite text field cursor to use blending"); + throw new UnsupportedOperationException("Color logic op is not supported in OpenGL ES!"); } public static final void disableColorLogic() { @@ -523,6 +567,20 @@ public class GlStateManager { textureCoordsY[activeTexture] = y; ++textureCoordsAccessSerial[activeTexture]; } + + public static final void texCoords2DDirect(int tex, float x, float y) { + textureCoordsX[tex] = x; + textureCoordsY[tex] = y; + ++textureCoordsAccessSerial[tex]; + } + + public static final float getTexCoordX(int tex) { + return textureCoordsX[tex]; + } + + public static final float getTexCoordY(int tex) { + return textureCoordsY[tex]; + } public static final int generateTexture() { return EaglercraftGPU.mapTexturesGL.register(_wglGenTextures()); @@ -530,6 +588,19 @@ public class GlStateManager { public static final void deleteTexture(int texture) { _wglDeleteTextures(EaglercraftGPU.mapTexturesGL.free(texture)); + boolean f = false; + for(int i = 0; i < boundTexture.length; ++i) { + if(boundTexture[i] == texture) { + _wglActiveTexture(GL_TEXTURE0 + i); + _wglBindTexture(GL_TEXTURE_2D, null); + _wglBindTexture(GL_TEXTURE_3D, null); + boundTexture[i] = -1; + f = true; + } + } + if(f) { + _wglActiveTexture(GL_TEXTURE0 + activeTexture); + } } public static final void bindTexture(int texture) { @@ -539,8 +610,25 @@ public class GlStateManager { } } - public static final int getTextureBound() { - return boundTexture[activeTexture]; + public static final void bindTexture3D(int texture) { + if(texture != boundTexture[activeTexture]) { + _wglBindTexture(GL_TEXTURE_3D, EaglercraftGPU.mapTexturesGL.get(texture)); + boundTexture[activeTexture] = texture; + } + } + + public static final void quickBindTexture(int unit, int texture) { + int unitBase = unit - GL_TEXTURE0; + if(texture != boundTexture[unitBase]) { + if(unitBase != activeTexture) { + _wglActiveTexture(unit); + } + _wglBindTexture(GL_TEXTURE_2D, EaglercraftGPU.mapTexturesGL.get(texture)); + boundTexture[unitBase] = texture; + if(unitBase != activeTexture) { + _wglActiveTexture(GL_TEXTURE0 + activeTexture); + } + } } public static final void shadeModel(int mode) { @@ -730,22 +818,23 @@ public class GlStateManager { ++textureMatrixAccessSerial[activeTexture]; break; } - matrix.m00 = 2.0f / (float)(right - left); - matrix.m01 = 0.0f; - matrix.m02 = 0.0f; - matrix.m03 = 0.0f; - matrix.m10 = 0.0f; - matrix.m11 = 2.0f / (float)(top - bottom); - matrix.m12 = 0.0f; - matrix.m13 = 0.0f; - matrix.m20 = 0.0f; - matrix.m21 = 0.0f; - matrix.m22 = 2.0f / (float)(zFar - zNear); - matrix.m23 = 0.0f; - matrix.m30 = (float)(-(right + left) / (right - left)); - matrix.m31 = (float)(-(top + bottom) / (top - bottom)); - matrix.m32 = (float)((zFar + zNear) / (zFar - zNear)); - matrix.m33 = 1.0f; + paramMatrix.m00 = 2.0f / (float)(right - left); + paramMatrix.m01 = 0.0f; + paramMatrix.m02 = 0.0f; + paramMatrix.m03 = 0.0f; + paramMatrix.m10 = 0.0f; + paramMatrix.m11 = 2.0f / (float)(top - bottom); + paramMatrix.m12 = 0.0f; + paramMatrix.m13 = 0.0f; + paramMatrix.m20 = 0.0f; + paramMatrix.m21 = 0.0f; + paramMatrix.m22 = 2.0f / (float)(zFar - zNear); + paramMatrix.m23 = 0.0f; + paramMatrix.m30 = (float)(-(right + left) / (right - left)); + paramMatrix.m31 = (float)(-(top + bottom) / (top - bottom)); + paramMatrix.m32 = (float)((zFar + zNear) / (zFar - zNear)); + paramMatrix.m33 = 1.0f; + Matrix4f.mul(matrix, paramMatrix, matrix); } private static final Vector3f paramVector = new Vector3f(); @@ -940,22 +1029,98 @@ public class GlStateManager { break; } float cotangent = (float) Math.cos(fovy * toRad * 0.5f) / (float) Math.sin(fovy * toRad * 0.5f); - matrix.m00 = cotangent / aspect; - matrix.m01 = 0.0f; - matrix.m02 = 0.0f; - matrix.m03 = 0.0f; - matrix.m10 = 0.0f; - matrix.m11 = cotangent; - matrix.m12 = 0.0f; - matrix.m13 = 0.0f; - matrix.m20 = 0.0f; - matrix.m21 = 0.0f; - matrix.m22 = (zFar + zNear) / (zFar - zNear); - matrix.m23 = -1.0f; - matrix.m30 = 0.0f; - matrix.m31 = 0.0f; - matrix.m32 = 2.0f * zFar * zNear / (zFar - zNear); - matrix.m33 = 0.0f; + paramMatrix.m00 = cotangent / aspect; + paramMatrix.m01 = 0.0f; + paramMatrix.m02 = 0.0f; + paramMatrix.m03 = 0.0f; + paramMatrix.m10 = 0.0f; + paramMatrix.m11 = cotangent; + paramMatrix.m12 = 0.0f; + paramMatrix.m13 = 0.0f; + paramMatrix.m20 = 0.0f; + paramMatrix.m21 = 0.0f; + paramMatrix.m22 = (zFar + zNear) / (zFar - zNear); + paramMatrix.m23 = -1.0f; + paramMatrix.m30 = 0.0f; + paramMatrix.m31 = 0.0f; + paramMatrix.m32 = 2.0f * zFar * zNear / (zFar - zNear); + paramMatrix.m33 = 0.0f; + Matrix4f.mul(matrix, paramMatrix, matrix); + } + + public static final void gluLookAt(Vector3f eye, Vector3f center, Vector3f up) { + Matrix4f matrix; + switch(stateMatrixMode) { + case GL_MODELVIEW: + matrix = modelMatrixStack[modelMatrixStackPointer]; + modelMatrixStackAccessSerial[modelMatrixStackPointer] = ++modelMatrixAccessSerial; + break; + case GL_PROJECTION: + default: + matrix = projectionMatrixStack[projectionMatrixStackPointer]; + projectionMatrixStackAccessSerial[projectionMatrixStackPointer] = ++projectionMatrixAccessSerial; + break; + case GL_TEXTURE: + int ptr = textureMatrixStackPointer[activeTexture]; + matrix = textureMatrixStack[activeTexture][ptr]; + textureMatrixStackAccessSerial[activeTexture][textureMatrixStackPointer[activeTexture]] = + ++textureMatrixAccessSerial[activeTexture]; + break; + } + float x = center.x - eye.x; + float y = center.y - eye.y; + float z = center.z - eye.z; + float xyzLen = (float) Math.sqrt(x * x + y * y + z * z); + x /= xyzLen; + y /= xyzLen; + z /= xyzLen; + float ux = up.x; + float uy = up.y; + float uz = up.z; + xyzLen = (float) Math.sqrt(ux * ux + uy * uy + uz * uz); + ux /= xyzLen; + uy /= xyzLen; + uz /= xyzLen; + float lxx = y * uz - z * uy; + float lxy = ux * z - uz * x; + float lxz = x * uy - y * ux; + float lyx = lxy * z - lxz * y; + float lyy = x * lxz - z * lxx; + float lyz = lxx * y - lxy * x; + paramMatrix.m00 = lxx; + paramMatrix.m01 = lyx; + paramMatrix.m02 = -x; + paramMatrix.m03 = 0.0f; + paramMatrix.m10 = lxy; + paramMatrix.m11 = lyy; + paramMatrix.m12 = -y; + paramMatrix.m13 = 0.0f; + paramMatrix.m20 = lxz; + paramMatrix.m21 = lyz; + paramMatrix.m22 = -z; + paramMatrix.m23 = 0.0f; + paramMatrix.m30 = -eye.x; + paramMatrix.m31 = -eye.y; + paramMatrix.m32 = -eye.z; + paramMatrix.m33 = 1.0f; + Matrix4f.mul(matrix, paramMatrix, matrix); + } + + public static final void transform(Vector4f vecIn, Vector4f vecOut) { + Matrix4f matrix; + switch(stateMatrixMode) { + case GL_MODELVIEW: + matrix = modelMatrixStack[modelMatrixStackPointer]; + break; + case GL_PROJECTION: + default: + matrix = projectionMatrixStack[projectionMatrixStackPointer]; + break; + case GL_TEXTURE: + matrix = textureMatrixStack[activeTexture][textureMatrixStackPointer[activeTexture]]; + break; + } + Matrix4f.transform(matrix, vecIn, vecOut); } private static final Matrix4f unprojA = new Matrix4f(); @@ -975,6 +1140,47 @@ public class GlStateManager { objectcoords[2] = unprojC.z / unprojC.w; } + public static final void getMatrix(Matrix4f mat) { + switch(stateMatrixMode) { + case GL_MODELVIEW: + mat.load(modelMatrixStack[modelMatrixStackPointer]); + break; + case GL_PROJECTION: + default: + mat.load(projectionMatrixStack[projectionMatrixStackPointer]); + break; + case GL_TEXTURE: + mat.load(textureMatrixStack[activeTexture][textureMatrixStackPointer[activeTexture]]); + break; + } + } + + public static final void loadMatrix(Matrix4f mat) { + switch(stateMatrixMode) { + case GL_MODELVIEW: + modelMatrixStack[modelMatrixStackPointer].load(mat); + modelMatrixStackAccessSerial[modelMatrixStackPointer] = ++modelMatrixAccessSerial; + break; + case GL_PROJECTION: + default: + projectionMatrixStack[projectionMatrixStackPointer].load(mat); + projectionMatrixStackAccessSerial[projectionMatrixStackPointer] = ++projectionMatrixAccessSerial; + break; + case GL_TEXTURE: + textureMatrixStack[activeTexture][textureMatrixStackPointer[activeTexture]].load(mat); + textureMatrixStackAccessSerial[activeTexture][textureMatrixStackPointer[activeTexture]] = ++textureMatrixAccessSerial[activeTexture]; + break; + } + } + + public static final int getModelViewSerial() { + return modelMatrixStackAccessSerial[modelMatrixStackPointer]; + } + + public static final Matrix4f getModelViewReference() { + return modelMatrixStack[modelMatrixStackPointer]; + } + public static void recompileShaders() { FixedFunctionPipeline.flushCache(); } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/IExtPipelineCompiler.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/IExtPipelineCompiler.java new file mode 100644 index 0000000..14f2764 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/IExtPipelineCompiler.java @@ -0,0 +1,37 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public interface IExtPipelineCompiler { + + /** + * @return new String[] { vshSource, fshSource } + */ + String[] getShaderSource(int stateCoreBits, int stateExtBits, Object[] userPointer); + + int getExtensionStatesCount(); + + int getCurrentExtensionStateBits(int stateCoreBits); + + int getCoreStateMask(int stateExtBits); + + void initializeNewShader(IProgramGL compiledProg, int stateCoreBits, int stateExtBits, Object[] userPointer); + + void updatePipeline(IProgramGL compiledProg, int stateCoreBits, int stateExtBits, Object[] userPointer); + + void destroyPipeline(IProgramGL shaderProgram, int stateCoreBits, int stateExtBits, Object[] userPointer); + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java index 2effd2d..5f145bd 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java @@ -14,6 +14,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; @@ -276,7 +277,7 @@ public class InstancedFontRenderer { _wglUniformMatrix4fv(u_matrixTransform, false, matrixCopyBuffer); } - if(!fogEnabled) { + if(!fogEnabled || DeferredStateManager.isInDeferredPass()) { int serial = GlStateManager.stateColorSerial; if(stateColorSerial != serial) { stateColorSerial = serial; diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/SpriteLevelMixer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/SpriteLevelMixer.java index ca98228..b9de019 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/SpriteLevelMixer.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/SpriteLevelMixer.java @@ -32,13 +32,8 @@ public class SpriteLevelMixer { private static final Logger LOGGER = LogManager.getLogger("SpriteLevelMixer"); - public static final String vertexShaderPath = "/assets/eagler/glsl/local.vsh"; public static final String fragmentShaderPath = "/assets/eagler/glsl/texture_mix.fsh"; - public static IShaderGL vshLocal = null; - - private static IBufferGL vertexBuffer = null; - public static IBufferArrayGL vertexArray = null; private static IProgramGL shaderProgram = null; private static IUniformGL u_textureLod1f = null; @@ -67,34 +62,13 @@ public class SpriteLevelMixer { static void initialize() { - String vertexSource = EagRuntime.getResourceString(vertexShaderPath); - if(vertexSource == null) { - throw new RuntimeException("SpriteLevelMixer shader \"" + vertexShaderPath + "\" is missing!"); - } - String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath); if(fragmentSource == null) { throw new RuntimeException("SpriteLevelMixer shader \"" + fragmentShaderPath + "\" is missing!"); } - vshLocal = _wglCreateShader(GL_VERTEX_SHADER); IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER); - _wglShaderSource(vshLocal, FixedFunctionConstants.VERSION + "\n" + vertexSource); - _wglCompileShader(vshLocal); - - if(_wglGetShaderi(vshLocal, GL_COMPILE_STATUS) != GL_TRUE) { - LOGGER.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\" for SpriteLevelMixer!"); - String log = _wglGetShaderInfoLog(vshLocal); - if(log != null) { - String[] lines = log.split("(\\r\\n|\\r|\\n)"); - for(int i = 0; i < lines.length; ++i) { - LOGGER.error("[VERT] {}", lines[i]); - } - } - throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!"); - } - _wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource); _wglCompileShader(frag); @@ -112,12 +86,12 @@ public class SpriteLevelMixer { shaderProgram = _wglCreateProgram(); - _wglAttachShader(shaderProgram, vshLocal); + _wglAttachShader(shaderProgram, DrawUtils.vshLocal); _wglAttachShader(shaderProgram, frag); _wglLinkProgram(shaderProgram); - _wglDetachShader(shaderProgram, vshLocal); + _wglDetachShader(shaderProgram, DrawUtils.vshLocal); _wglDetachShader(shaderProgram, frag); _wglDeleteShader(frag); @@ -145,26 +119,6 @@ public class SpriteLevelMixer { _wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_inputTexture"), 0); - vertexArray = _wglGenVertexArrays(); - vertexBuffer = _wglGenBuffers(); - - FloatBuffer verts = EagRuntime.allocateFloatBuffer(12); - verts.put(new float[] { - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f - }); - verts.flip(); - - EaglercraftGPU.bindGLBufferArray(vertexArray); - - EaglercraftGPU.bindGLArrayBuffer(vertexBuffer); - _wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW); - - EagRuntime.freeFloatBuffer(verts); - - _wglEnableVertexAttribArray(0); - _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0); - } public static void setBlendColor(float r, float g, float b, float a) { @@ -206,7 +160,7 @@ public class SpriteLevelMixer { if(blendColorChanged) { _wglUniform4f(u_blendFactor4f, blendColorR, blendColorG, blendColorB, blendColorA); blendColorChanged = false; - } + } if(biasColorChanged) { _wglUniform4f(u_blendBias4f, biasColorR, biasColorG, biasColorB, biasColorA); @@ -221,9 +175,7 @@ public class SpriteLevelMixer { matrixChanged = false; } - EaglercraftGPU.bindGLBufferArray(vertexArray); - - _wglDrawArrays(GL_TRIANGLES, 0, 6); + DrawUtils.drawStandardQuad2D(); } } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/StreamBuffer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/StreamBuffer.java new file mode 100644 index 0000000..e7f7b2c --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/StreamBuffer.java @@ -0,0 +1,148 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class StreamBuffer { + + public final int initialSize; + public final int initialCount; + public final int maxCount; + + protected StreamBufferInstance[] buffers; + + protected int currentBufferId = 0; + protected int overflowCounter = 0; + + protected final IStreamBufferInitializer initializer; + + public static class StreamBufferInstance { + + protected IBufferArrayGL vertexArray = null; + protected IBufferGL vertexBuffer = null; + protected int vertexBufferSize = 0; + + public boolean bindQuad16 = false; + public boolean bindQuad32 = false; + + public IBufferArrayGL getVertexArray() { + return vertexArray; + } + + public IBufferGL getVertexBuffer() { + return vertexBuffer; + } + + } + + public static interface IStreamBufferInitializer { + void initialize(IBufferArrayGL vertexArray, IBufferGL vertexBuffer); + } + + public StreamBuffer(int initialSize, int initialCount, int maxCount, IStreamBufferInitializer initializer) { + this.buffers = new StreamBufferInstance[initialCount]; + for(int i = 0; i < this.buffers.length; ++i) { + this.buffers[i] = new StreamBufferInstance(); + } + this.initialSize = initialSize; + this.initialCount = initialCount; + this.maxCount = maxCount; + this.initializer = initializer; + } + + public StreamBufferInstance getBuffer(int requiredMemory) { + StreamBufferInstance next = buffers[(currentBufferId++) % buffers.length]; + if(next.vertexBuffer == null) { + next.vertexBuffer = _wglGenBuffers(); + } + if(next.vertexArray == null) { + next.vertexArray = _wglGenVertexArrays(); + initializer.initialize(next.vertexArray, next.vertexBuffer); + } + if(next.vertexBufferSize < requiredMemory) { + int newSize = (requiredMemory & 0xFFFFF000) + 0x2000; + EaglercraftGPU.bindGLArrayBuffer(next.vertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW); + next.vertexBufferSize = newSize; + } + return next; + } + + public void optimize() { + overflowCounter += currentBufferId - buffers.length; + if(overflowCounter < -25) { + int newCount = buffers.length - 1 + ((overflowCounter + 25) / 5); + if(newCount < initialCount) { + newCount = initialCount; + } + if(newCount < buffers.length) { + StreamBufferInstance[] newArray = new StreamBufferInstance[newCount]; + for(int i = 0; i < buffers.length; ++i) { + if(i < newArray.length) { + newArray[i] = buffers[i]; + }else { + if(buffers[i].vertexArray != null) { + _wglDeleteVertexArrays(buffers[i].vertexArray); + } + if(buffers[i].vertexBuffer != null) { + _wglDeleteBuffers(buffers[i].vertexBuffer); + } + } + } + buffers = newArray; + } + overflowCounter = 0; + }else if(overflowCounter > 15) { + int newCount = buffers.length + 1 + ((overflowCounter - 15) / 5); + if(newCount > maxCount) { + newCount = maxCount; + } + if(newCount > buffers.length) { + StreamBufferInstance[] newArray = new StreamBufferInstance[newCount]; + for(int i = 0; i < newArray.length; ++i) { + if(i < buffers.length) { + newArray[i] = buffers[i]; + }else { + newArray[i] = new StreamBufferInstance(); + } + } + buffers = newArray; + } + overflowCounter = 0; + } + currentBufferId = 0; + } + + public void destroy() { + for(int i = 0; i < buffers.length; ++i) { + StreamBufferInstance next = buffers[i]; + if(next.vertexArray != null) { + _wglDeleteVertexArrays(next.vertexArray); + } + if(next.vertexBuffer != null) { + _wglDeleteBuffers(next.vertexBuffer); + } + } + buffers = new StreamBufferInstance[initialCount]; + for(int i = 0; i < buffers.length; ++i) { + buffers[i] = new StreamBufferInstance(); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/TextureCopyUtil.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/TextureCopyUtil.java new file mode 100644 index 0000000..3645808 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/TextureCopyUtil.java @@ -0,0 +1,352 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class TextureCopyUtil { + + private static final Logger LOGGER = LogManager.getLogger("TextureCopyUtil"); + + public static final String vertexShaderPath = "/assets/eagler/glsl/texture_blit.vsh"; + public static final String fragmentShaderPath = "/assets/eagler/glsl/texture_blit.fsh"; + + private static String vshSource = null; + private static String fshSource = null; + + private static IShaderGL vshShader = null; + + private static class TextureCopyShader { + private IProgramGL shaderProgram = null; + private IUniformGL u_srcCoords4f = null; + private IUniformGL u_dstCoords4f = null; + private IUniformGL u_textureLod1f = null; + private IUniformGL u_pixelAlignmentSizes4f = null; + private IUniformGL u_pixelAlignmentOffset2f = null; + private TextureCopyShader(IProgramGL shaderProgram) { + this.shaderProgram = shaderProgram; + EaglercraftGPU.bindGLShaderProgram(shaderProgram); + this.u_srcCoords4f = _wglGetUniformLocation(shaderProgram, "u_srcCoords4f"); + this.u_dstCoords4f = _wglGetUniformLocation(shaderProgram, "u_dstCoords4f"); + this.u_textureLod1f = _wglGetUniformLocation(shaderProgram, "u_textureLod1f"); + this.u_pixelAlignmentSizes4f = _wglGetUniformLocation(shaderProgram, "u_pixelAlignmentSizes4f"); + this.u_pixelAlignmentOffset2f = _wglGetUniformLocation(shaderProgram, "u_pixelAlignmentOffset2f"); + } + } + + private static TextureCopyShader textureBlit = null; + private static TextureCopyShader textureBlitAligned = null; + private static TextureCopyShader textureBlitDepth = null; + private static TextureCopyShader textureBlitDepthAligned = null; + + private static float srcViewW = 100.0f; + private static float srcViewH = 100.0f; + + private static float dstViewW = 50.0f; + private static float dstViewH = 50.0f; + + private static boolean isAligned = false; + private static int alignW = 0; + private static int alignH = 0; + private static float alignOffsetX = 0.0f; + private static float alignOffsetY = 0.0f; + + static void initialize() { + vshSource = EagRuntime.getResourceString(vertexShaderPath); + if(vshSource == null) { + throw new RuntimeException("TextureCopyUtil shader \"" + vertexShaderPath + "\" is missing!"); + } + + fshSource = EagRuntime.getResourceString(fragmentShaderPath); + if(fshSource == null) { + throw new RuntimeException("TextureCopyUtil shader \"" + fragmentShaderPath + "\" is missing!"); + } + + vshShader = _wglCreateShader(GL_VERTEX_SHADER); + + _wglShaderSource(vshShader, FixedFunctionConstants.VERSION + "\n" + vshSource); + _wglCompileShader(vshShader); + + if(_wglGetShaderi(vshShader, GL_COMPILE_STATUS) != GL_TRUE) { + LOGGER.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\" for TextureCopyUtil!"); + String log = _wglGetShaderInfoLog(vshShader); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + LOGGER.error("[VERT] {}", lines[i]); + } + } + throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!"); + } + } + + private static TextureCopyShader compileShader(boolean align, boolean depth) { + IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER); + + _wglShaderSource(frag, + FixedFunctionConstants.VERSION + "\n" + (align ? "#define COMPILE_PIXEL_ALIGNMENT\n" : "") + + (depth ? "#define COMPILE_BLIT_DEPTH\n" : "") + fshSource); + _wglCompileShader(frag); + + if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) { + LOGGER.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for TextureCopyUtil!"); + String log = _wglGetShaderInfoLog(frag); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + LOGGER.error("[FRAG] {}", lines[i]); + } + } + throw new IllegalStateException("Fragment shader \"" + fragmentShaderPath + "\" could not be compiled!"); + } + + IProgramGL shaderProgram = _wglCreateProgram(); + + _wglAttachShader(shaderProgram, vshShader); + _wglAttachShader(shaderProgram, frag); + + _wglLinkProgram(shaderProgram); + + _wglDetachShader(shaderProgram, vshShader); + _wglDetachShader(shaderProgram, frag); + + _wglDeleteShader(frag); + + if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) { + LOGGER.error("Failed to link shader program for TextureCopyUtil!"); + String log = _wglGetProgramInfoLog(shaderProgram); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + LOGGER.error("[LINK] {}", lines[i]); + } + } + throw new IllegalStateException("Shader program for TextureCopyUtil could not be linked!"); + } + + return new TextureCopyShader(shaderProgram); + } + + private static TextureCopyShader getShaderObj(boolean align, boolean depth) { + if(align) { + if(depth) { + if(textureBlitDepthAligned == null) textureBlitDepthAligned = compileShader(true, true); + return textureBlitDepthAligned; + }else { + if(textureBlitAligned == null) textureBlitAligned = compileShader(true, false); + return textureBlitAligned; + } + }else { + if(depth) { + if(textureBlitDepth == null) textureBlitDepth = compileShader(false, true); + return textureBlitDepth; + }else { + if(textureBlit == null) textureBlit = compileShader(false, false); + return textureBlit; + } + } + } + + public static void srcSize(int w, int h) { + srcViewW = w; + srcViewH = h; + } + + public static void dstSize(int w, int h) { + dstViewW = w * 0.5f; + dstViewH = h * 0.5f; + } + + public static void srcDstSize(int w, int h) { + srcViewW = w; + srcViewH = h; + dstViewW = w * 0.5f; + dstViewH = h * 0.5f; + } + + /** + * this is reset after every blit + */ + public static void alignPixels(int dstW, int dstH, float alignX, float alignY) { + isAligned = true; + alignW = dstW; + alignH = dstH; + alignOffsetX = alignX; + alignOffsetY = alignY; + } + + /** + * this is reset after every blit + */ + public static void alignPixelsTopLeft(int srcW, int srcH, int dstW, int dstH) { + alignPixels(dstW, dstH, (0.5f * dstW) / srcW, (0.5f * dstH) / srcH); + } + + public static void disableAlign() { + isAligned = false; + } + + public static void blitTexture(int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTexture(0, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTexture(int lvl, int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTexture(lvl, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTexture(int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + blitTexture(0, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH); + } + + public static void blitTexture(int lvl, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + TextureCopyShader shaderObj = getShaderObj(isAligned, false); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + _wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH); + _wglUniform4f(shaderObj.u_dstCoords4f, (float) dstX / dstViewW - 1.0f, (float) dstY / dstViewH - 1.0f, + (float) dstW / dstViewW, (float) dstH / dstViewH); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } + + public static void blitTexture() { + blitTexture(0); + } + + public static void blitTexture(int lvl) { + TextureCopyShader shaderObj = getShaderObj(isAligned, false); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + _wglUniform4f(shaderObj.u_srcCoords4f, 0.0f, 0.0f, 1.0f, 1.0f); + _wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } + + public static void blitTextureUsingViewports(int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureUsingViewports(0, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureUsingViewports(int lvl, int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureUsingViewports(lvl, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureUsingViewports(int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + blitTextureUsingViewports(0, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH); + } + + public static void blitTextureUsingViewports(int lvl, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + TextureCopyShader shaderObj = getShaderObj(isAligned, false); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + GlStateManager.viewport(dstX, dstY, dstW, dstH); + _wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH); + _wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } + + public static void blitTextureDepth(int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureDepth(0, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureDepth(int lvl, int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureDepth(lvl, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureDepth(int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + blitTextureDepth(0, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH); + } + + public static void blitTextureDepth(int lvl, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + TextureCopyShader shaderObj = getShaderObj(isAligned, true); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + _wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH); + _wglUniform4f(shaderObj.u_dstCoords4f, (float) dstX / dstViewW - 1.0f, (float) dstY / dstViewH - 1.0f, + (float) dstW / dstViewW, (float) dstH / dstViewH); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } + + public static void blitTextureDepth() { + blitTextureDepth(0); + } + + public static void blitTextureDepth(int lvl) { + TextureCopyShader shaderObj = getShaderObj(isAligned, true); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + _wglUniform4f(shaderObj.u_srcCoords4f, 0.0f, 0.0f, 1.0f, 1.0f); + _wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } + + public static void blitTextureDepthUsingViewports(int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureDepthUsingViewports(0, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureDepthUsingViewports(int lvl, int srcX, int srcY, int dstX, int dstY, int w, int h) { + blitTextureDepthUsingViewports(lvl, srcX, srcY, w, h, dstX, dstY, w, h); + } + + public static void blitTextureDepthUsingViewports(int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + blitTextureDepthUsingViewports(0, srcX, srcY, srcW, srcH, dstX, dstY, dstW, dstH); + } + + public static void blitTextureDepthUsingViewports(int lvl, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY, int dstW, int dstH) { + TextureCopyShader shaderObj = getShaderObj(isAligned, true); + EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram); + GlStateManager.viewport(dstX, dstY, dstW, dstH); + _wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH); + _wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f); + _wglUniform1f(shaderObj.u_textureLod1f, lvl); + if(isAligned) { + _wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH); + _wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY); + isAligned = false; + } + DrawUtils.drawStandardQuad2D(); + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/VertexFormat.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/VertexFormat.java index 5806acd..09ef232 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/VertexFormat.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/VertexFormat.java @@ -18,6 +18,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; public enum VertexFormat { BLOCK(true, true, false, true), + BLOCK_SHADERS(true, true, true, true), ITEM(true, true, true, false), OLDMODEL_POSITION_TEX_NORMAL(true, false, true, false), PARTICLE_POSITION_TEX_COLOR_LMAP(true, true, true, true), @@ -107,7 +108,6 @@ public enum VertexFormat { attribPositionFormat = COMPONENT_POSITION_FORMAT; attribPositionNormalized = false; attribPositionSize = COMPONENT_POSITION_SIZE; - attribPositionStride = COMPONENT_POSITION_STRIDE; bytes += COMPONENT_POSITION_STRIDE; if(color) { @@ -117,7 +117,6 @@ public enum VertexFormat { attribColorFormat = COMPONENT_COLOR_FORMAT; attribColorNormalized = true; attribColorSize = COMPONENT_COLOR_SIZE; - attribColorStride = COMPONENT_COLOR_STRIDE; bytes += COMPONENT_COLOR_STRIDE; bitfield |= EaglercraftGPU.ATTRIB_COLOR; }else { @@ -127,7 +126,6 @@ public enum VertexFormat { attribColorFormat = -1; attribColorNormalized = false; attribColorSize = -1; - attribColorStride = -1; } if(texture) { @@ -137,7 +135,6 @@ public enum VertexFormat { attribTextureFormat = COMPONENT_TEX_FORMAT; attribTextureNormalized = false; attribTextureSize = COMPONENT_TEX_SIZE; - attribTextureStride = COMPONENT_TEX_STRIDE; bytes += COMPONENT_TEX_STRIDE; bitfield |= EaglercraftGPU.ATTRIB_TEXTURE; }else { @@ -147,7 +144,6 @@ public enum VertexFormat { attribTextureFormat = -1; attribTextureNormalized = false; attribTextureSize = -1; - attribTextureStride = -1; } if(normal) { @@ -157,7 +153,6 @@ public enum VertexFormat { attribNormalFormat = COMPONENT_NORMAL_FORMAT; attribNormalNormalized = true; attribNormalSize = COMPONENT_NORMAL_SIZE; - attribNormalStride = COMPONENT_NORMAL_STRIDE; bytes += COMPONENT_NORMAL_STRIDE; bitfield |= EaglercraftGPU.ATTRIB_NORMAL; }else { @@ -167,7 +162,6 @@ public enum VertexFormat { attribNormalFormat = -1; attribNormalNormalized = false; attribNormalSize = -1; - attribNormalStride = -1; } if(lightmap) { @@ -177,7 +171,6 @@ public enum VertexFormat { attribLightmapFormat = COMPONENT_LIGHTMAP_FORMAT; attribLightmapNormalized = false; attribLightmapSize = COMPONENT_LIGHTMAP_SIZE; - attribLightmapStride = COMPONENT_LIGHTMAP_STRIDE; bytes += COMPONENT_LIGHTMAP_STRIDE; bitfield |= EaglercraftGPU.ATTRIB_LIGHTMAP; }else { @@ -187,11 +180,14 @@ public enum VertexFormat { attribLightmapFormat = -1; attribLightmapNormalized = false; attribLightmapSize = -1; - attribLightmapStride = -1; } attribCount = index; - attribStride = bytes; + attribStride = attribPositionStride = bytes; + attribColorStride = color ? bytes : -1; + attribTextureStride = texture ? bytes : -1; + attribNormalStride = normal ? bytes : -1; + attribLightmapStride = lightmap ? bytes : -1; eaglercraftAttribBits = bitfield; } diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java index 0243cc4..5b800d8 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java @@ -10,6 +10,7 @@ import java.util.Comparator; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.internal.PlatformBufferFunctions; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; import net.minecraft.client.renderer.GLAllocation; import net.minecraft.util.MathHelper; @@ -150,9 +151,6 @@ public class WorldRenderer { return new WorldRenderer.State(aint, fmt); } - /** - * MOST LIKELY A SLOW AND RETARDED WAY TO GET THE DISTANCE TO A QUAD - */ private static float func_181665_a(FloatBuffer parFloatBuffer, float parFloat1, float parFloat2, float parFloat3, int parInt1, int parInt2) { float f = parFloatBuffer.get(parInt2 + parInt1 * 0 + 0); @@ -379,6 +377,20 @@ public class WorldRenderer { this.byteBuffer.putInt(j1 + i1 * 3, l); } + public void putNormal(float x, float y, float z, int id) { + int i = (byte) ((int) (x * 127.0F)) & 255; + int j = (byte) ((int) (y * 127.0F)) & 255; + int k = (byte) ((int) (z * 127.0F)) & 255; + int l = i | j << 8 | k << 16 | ((byte)id) << 24; + VertexFormat fmt = this.vertexFormat; + int i1 = fmt.attribStride; + int j1 = (this.vertexCount - 4) * i1 + fmt.attribNormalOffset; + this.byteBuffer.putInt(j1, l); + this.byteBuffer.putInt(j1 + i1, l); + this.byteBuffer.putInt(j1 + i1 * 2, l); + this.byteBuffer.putInt(j1 + i1 * 3, l); + } + /** * set normal of current vertex */ @@ -391,6 +403,67 @@ public class WorldRenderer { return this; } + private final Vector3f tmpVec1 = new Vector3f(); + private final Vector3f tmpVec2 = new Vector3f(); + private final Vector3f tmpVec3 = new Vector3f(); + private final Vector3f tmpVec4 = new Vector3f(); + private final Vector3f tmpVec5 = new Vector3f(); + private final Vector3f tmpVec6 = new Vector3f(); + + public void genNormals(boolean b, int vertId) { + VertexFormat fmt = this.vertexFormat; + int i1 = fmt.attribStride; + int j1 = (this.vertexCount - 4) * i1; + tmpVec1.x = this.byteBuffer.getFloat(j1); + tmpVec1.y = this.byteBuffer.getFloat(j1 + 4); + tmpVec1.z = this.byteBuffer.getFloat(j1 + 8); + j1 += i1; + tmpVec2.x = this.byteBuffer.getFloat(j1); + tmpVec2.y = this.byteBuffer.getFloat(j1 + 4); + tmpVec2.z = this.byteBuffer.getFloat(j1 + 8); + j1 += i1 * 2; + tmpVec3.x = this.byteBuffer.getFloat(j1); + tmpVec3.y = this.byteBuffer.getFloat(j1 + 4); + tmpVec3.z = this.byteBuffer.getFloat(j1 + 8); + Vector3f.sub(tmpVec1, tmpVec2, tmpVec4); + Vector3f.sub(tmpVec3, tmpVec2, tmpVec5); + Vector3f.cross(tmpVec5, tmpVec4, tmpVec6); + float f = (float) Math + .sqrt((double) (tmpVec6.x * tmpVec6.x + tmpVec6.y * tmpVec6.y + tmpVec6.z * tmpVec6.z)); + tmpVec6.x /= f; + tmpVec6.y /= f; + tmpVec6.z /= f; + int i = (byte) ((int) (tmpVec6.x * 127.0F)) & 255; + int j = (byte) ((int) (tmpVec6.y * 127.0F)) & 255; + int k = (byte) ((int) (tmpVec6.z * 127.0F)) & 255; + int l = i | j << 8 | k << 16 | vertId << 24; + int jj1 = (this.vertexCount - 4) * i1 + fmt.attribNormalOffset; + this.byteBuffer.putInt(jj1, l); + this.byteBuffer.putInt(jj1 + i1, l); + if(!b) { + this.byteBuffer.putInt(jj1 + i1 * 2, l); + } + this.byteBuffer.putInt(jj1 + i1 * 3, l); + if(b) { + j1 = (this.vertexCount - 2) * i1; + tmpVec1.x = this.byteBuffer.getFloat(j1); + tmpVec1.y = this.byteBuffer.getFloat(j1 + 4); + tmpVec1.z = this.byteBuffer.getFloat(j1 + 8); + Vector3f.sub(tmpVec2, tmpVec1, tmpVec4); + Vector3f.sub(tmpVec3, tmpVec1, tmpVec5); + Vector3f.cross(tmpVec5, tmpVec4, tmpVec6); + f = (float) Math.sqrt((double) (tmpVec6.x * tmpVec6.x + tmpVec6.y * tmpVec6.y + tmpVec6.z * tmpVec6.z)); + tmpVec6.x /= f; + tmpVec6.y /= f; + tmpVec6.z /= f; + i = (byte) ((int) (tmpVec6.x * 127.0F)) & 255; + j = (byte) ((int) (tmpVec6.y * 127.0F)) & 255; + k = (byte) ((int) (tmpVec6.z * 127.0F)) & 255; + l = i | j << 8 | k << 16 | vertId << 24; + this.byteBuffer.putInt(jj1 + i1 * 2, l); + } + } + /** * sets translation applied to all positions set by functions */ diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/AbstractAcceleratedEffectRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/AbstractAcceleratedEffectRenderer.java new file mode 100644 index 0000000..519103c --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/AbstractAcceleratedEffectRenderer.java @@ -0,0 +1,49 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.lax1dude.eaglercraft.v1_8.minecraft.IAcceleratedParticleEngine; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.entity.Entity; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public abstract class AbstractAcceleratedEffectRenderer implements IAcceleratedParticleEngine { + + public float partialTicks; + + @Override + public void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY, int lightMapData, + int texSize, float particleSize, float r, float g, float b, float a) { + float xx = (float) (entityIn.prevPosX + (entityIn.posX - entityIn.prevPosX) * (double) partialTicks - EntityFX.interpPosX); + float yy = (float) (entityIn.prevPosY + (entityIn.posY - entityIn.prevPosY) * (double) partialTicks - EntityFX.interpPosY); + float zz = (float) (entityIn.prevPosZ + (entityIn.posZ - entityIn.prevPosZ) * (double) partialTicks - EntityFX.interpPosZ); + drawParticle(xx, yy, zz, particleIndexX, particleIndexY, lightMapData, texSize, particleSize, r, g, b, a); + } + + @Override + public void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY, int lightMapData, + int texSize, float particleSize, int rgba) { + float xx = (float) (entityIn.prevPosX + (entityIn.posX - entityIn.prevPosX) * (double) partialTicks - EntityFX.interpPosX); + float yy = (float) (entityIn.prevPosY + (entityIn.posY - entityIn.prevPosY) * (double) partialTicks - EntityFX.interpPosY); + float zz = (float) (entityIn.prevPosZ + (entityIn.posZ - entityIn.prevPosZ) * (double) partialTicks - EntityFX.interpPosZ); + drawParticle(xx, yy, zz, particleIndexX, particleIndexY, lightMapData, texSize, particleSize, rgba); + } + + @Override + public void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY, + int lightMapData, int texSize, float particleSize, float r, float g, float b, float a) { + int color = ((int)(a * 255.0f) << 24) | ((int)(r * 255.0f) << 16) | ((int)(g * 255.0f) << 8) | (int)(b * 255.0f); + drawParticle(posX, posY, posZ, particleIndexX, particleIndexY, lightMapData, texSize, particleSize, color); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ArrayListSerial.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ArrayListSerial.java new file mode 100644 index 0000000..c1dbe1f --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ArrayListSerial.java @@ -0,0 +1,52 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.ArrayList; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ArrayListSerial extends ArrayList implements ListSerial { + + protected int modCountEagler = 0; + protected int mark = 0; + + public ArrayListSerial() { + super(); + } + + public ArrayListSerial(int initialSize) { + super(initialSize); + } + + public E set(int index, E element) { + ++modCountEagler; + return super.set(index, element); + } + + public int getEaglerSerial() { + return (modCount << 8) + modCountEagler; + } + + public void eaglerIncrSerial() { + ++modCountEagler; + } + + public void eaglerResetCheck() { + mark = getEaglerSerial(); + } + + public boolean eaglerCheck() { + return mark != getEaglerSerial(); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BetterFrustum.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BetterFrustum.java new file mode 100644 index 0000000..94a0836 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BetterFrustum.java @@ -0,0 +1,1169 @@ +/* + * The MIT License + * + * Copyright (c) 2015-2022 Kai Burjack + * + * 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. + */ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector2f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; + +/** + * Efficiently performs frustum intersection tests by caching the frustum planes + * of an arbitrary transformation {@link Matrix4fc matrix}. + *

+ * This class is preferred over the frustum intersection methods in + * {@link Matrix4fc} when many objects need to be culled by the same static + * frustum. + * + * @author Kai Burjack + */ +public class BetterFrustum { + + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation x=-1 when using the identity frustum. + */ + public static final int PLANE_NX = 0; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation x=1 when using the identity frustum. + */ + public static final int PLANE_PX = 1; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation y=-1 when using the identity frustum. + */ + public static final int PLANE_NY = 2; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation y=1 when using the identity frustum. + */ + public static final int PLANE_PY = 3; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation z=-1 when using the identity frustum. + */ + public static final int PLANE_NZ = 4; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads identifying the plane with + * equation z=1 when using the identity frustum. + */ + public static final int PLANE_PZ = 5; + + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads indicating that the axis-aligned + * box intersects the frustum. + */ + public static final int INTERSECT = -1; + /** + * Return value of + * {@link #intersectAab(float, float, float, float, float, float) + * intersectAab()} and its different overloads indicating that the axis-aligned + * box is fully inside of the frustum. + */ + public static final int INSIDE = -2; + /** + * Return value of {@link #intersectSphere(Vector3fc, float)} or + * {@link #intersectSphere(float, float, float, float)} indicating that the + * sphere is completely outside of the frustum. + */ + public static final int OUTSIDE = -3; + + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation x=-1 + * when using the identity frustum. + */ + public static final int PLANE_MASK_NX = 1 << PLANE_NX; + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation x=1 when + * using the identity frustum. + */ + public static final int PLANE_MASK_PX = 1 << PLANE_PX; + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation y=-1 + * when using the identity frustum. + */ + public static final int PLANE_MASK_NY = 1 << PLANE_NY; + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation y=1 when + * using the identity frustum. + */ + public static final int PLANE_MASK_PY = 1 << PLANE_PY; + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation z=-1 + * when using the identity frustum. + */ + public static final int PLANE_MASK_NZ = 1 << PLANE_NZ; + /** + * The value in a bitmask for + * {@link #intersectAab(float, float, float, float, float, float, int) + * intersectAab()} that identifies the plane with equation z=1 when + * using the identity frustum. + */ + public static final int PLANE_MASK_PZ = 1 << PLANE_PZ; + + private float nxX, nxY, nxZ, nxW; + private float pxX, pxY, pxZ, pxW; + private float nyX, nyY, nyZ, nyW; + private float pyX, pyY, pyZ, pyW; + private float nzX, nzY, nzZ, nzW; + private float pzX, pzY, pzZ, pzW; + + private final Vector4f[] planes = new Vector4f[6]; + { + for (int i = 0; i < 6; i++) { + planes[i] = new Vector4f(); + } + } + + /** + * Create a new {@link FrustumIntersection} with undefined frustum planes. + *

+ * Before using any of the frustum culling methods, make sure to define the + * frustum planes using {@link #set(Matrix4fc)}. + */ + public BetterFrustum() { + } + + /** + * Create a new {@link FrustumIntersection} from the given {@link Matrix4fc + * matrix} by extracing the matrix's frustum planes. + *

+ * In order to update the compute frustum planes later on, call + * {@link #set(Matrix4fc)}. + * + * @see #set(Matrix4fc) + * + * @param m the {@link Matrix4fc} to create the frustum culler from + */ + public BetterFrustum(Matrix4f m) { + set(m, true); + } + + /** + * Create a new {@link FrustumIntersection} from the given {@link Matrix4fc + * matrix} by extracing the matrix's frustum planes. + *

+ * In order to update the compute frustum planes later on, call + * {@link #set(Matrix4fc)}. + * + * @see #set(Matrix4fc) + * + * @param m the {@link Matrix4fc} to create the frustum culler + * from + * @param allowTestSpheres whether the methods + * {@link #testSphere(Vector3fc, float)}, + * {@link #testSphere(float, float, float, float)}, + * {@link #intersectSphere(Vector3fc, float)} or + * {@link #intersectSphere(float, float, float, float)} + * will used. If no spheres need to be tested, then + * false should be used + */ + public BetterFrustum(Matrix4f m, boolean allowTestSpheres) { + set(m, allowTestSpheres); + } + + /** + * Update the stored frustum planes of this + * {@link FrustumIntersection} with the given {@link Matrix4fc matrix}. + *

+ * Reference: + * Fast Extraction of Viewing Frustum Planes from the World-View-Projection + * Matrix + * + * @param m the {@link Matrix4fc matrix} to update this frustum + * culler's frustum planes from + * @return this + */ + public BetterFrustum set(Matrix4f m) { + return set(m, true); + } + + /** + * Update the stored frustum planes of this + * {@link FrustumIntersection} with the given {@link Matrix4fc matrix} and allow + * to optimize the frustum plane extraction in the case when no intersection + * test is needed for spheres. + *

+ * Reference: + * Fast Extraction of Viewing Frustum Planes from the World-View-Projection + * Matrix + * + * @param m the {@link Matrix4fc matrix} to update + * this frustum culler's frustum planes + * from + * @param allowTestSpheres whether the methods + * {@link #testSphere(Vector3fc, float)}, + * {@link #testSphere(float, float, float, float)}, + * {@link #intersectSphere(Vector3fc, float)} or + * {@link #intersectSphere(float, float, float, float)} + * will be used. If no spheres need to be tested, then + * false should be used + * @return this + */ + public BetterFrustum set(Matrix4f m, boolean allowTestSpheres) { + float invl; + nxX = m.m03 + m.m00; + nxY = m.m13 + m.m10; + nxZ = m.m23 + m.m20; + nxW = m.m33 + m.m30; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(nxX * nxX + nxY * nxY + nxZ * nxZ); + nxX *= invl; + nxY *= invl; + nxZ *= invl; + nxW *= invl; + } + planes[0].set(nxX, nxY, nxZ, nxW); + pxX = m.m03 - m.m00; + pxY = m.m13 - m.m10; + pxZ = m.m23 - m.m20; + pxW = m.m33 - m.m30; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(pxX * pxX + pxY * pxY + pxZ * pxZ); + pxX *= invl; + pxY *= invl; + pxZ *= invl; + pxW *= invl; + } + planes[1].set(pxX, pxY, pxZ, pxW); + nyX = m.m03 + m.m01; + nyY = m.m13 + m.m11; + nyZ = m.m23 + m.m21; + nyW = m.m33 + m.m31; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(nyX * nyX + nyY * nyY + nyZ * nyZ); + nyX *= invl; + nyY *= invl; + nyZ *= invl; + nyW *= invl; + } + planes[2].set(nyX, nyY, nyZ, nyW); + pyX = m.m03 - m.m01; + pyY = m.m13 - m.m11; + pyZ = m.m23 - m.m21; + pyW = m.m33 - m.m31; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(pyX * pyX + pyY * pyY + pyZ * pyZ); + pyX *= invl; + pyY *= invl; + pyZ *= invl; + pyW *= invl; + } + planes[3].set(pyX, pyY, pyZ, pyW); + nzX = m.m03 + m.m02; + nzY = m.m13 + m.m12; + nzZ = m.m23 + m.m22; + nzW = m.m33 + m.m32; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(nzX * nzX + nzY * nzY + nzZ * nzZ); + nzX *= invl; + nzY *= invl; + nzZ *= invl; + nzW *= invl; + } + planes[4].set(nzX, nzY, nzZ, nzW); + pzX = m.m03 - m.m02; + pzY = m.m13 - m.m12; + pzZ = m.m23 - m.m22; + pzW = m.m33 - m.m32; + if (allowTestSpheres) { + invl = 1.0f / (float)Math.sqrt(pzX * pzX + pzY * pzY + pzZ * pzZ); + pzX *= invl; + pzY *= invl; + pzZ *= invl; + pzW *= invl; + } + planes[5].set(pzX, pzY, pzZ, pzW); + return this; + } + + /** + * Test whether the given point is within the frustum defined by + * this frustum culler. + * + * @param point the point to test + * @return true if the given point is inside the frustum; + * false otherwise + */ + public boolean testPoint(Vector3f point) { + return testPoint(point.x, point.y, point.z); + } + + /** + * Test whether the given point (x, y, z) is within the frustum + * defined by this frustum culler. + * + * @param x the x-coordinate of the point + * @param y the y-coordinate of the point + * @param z the z-coordinate of the point + * @return true if the given point is inside the frustum; + * false otherwise + */ + public boolean testPoint(float x, float y, float z) { + return nxX * x + nxY * y + nxZ * z + nxW >= 0 && pxX * x + pxY * y + pxZ * z + pxW >= 0 + && nyX * x + nyY * y + nyZ * z + nyW >= 0 && pyX * x + pyY * y + pyZ * z + pyW >= 0 + && nzX * x + nzY * y + nzZ * z + nzW >= 0 && pzX * x + pzY * y + pzZ * z + pzW >= 0; + } + + /** + * Test whether the given sphere is partly or completely within or outside of + * the frustum defined by this frustum culler. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for spheres that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param center the sphere's center + * @param radius the sphere's radius + * @return true if the given sphere is partly or completely inside + * the frustum; false otherwise + */ + public boolean testSphere(Vector3f center, float radius) { + return testSphere(center.x, center.y, center.z, radius); + } + + /** + * Test whether the given sphere is partly or completely within or outside of + * the frustum defined by this frustum culler. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for spheres that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param x the x-coordinate of the sphere's center + * @param y the y-coordinate of the sphere's center + * @param z the z-coordinate of the sphere's center + * @param r the sphere's radius + * @return true if the given sphere is partly or completely inside + * the frustum; false otherwise + */ + public boolean testSphere(float x, float y, float z, float r) { + return nxX * x + nxY * y + nxZ * z + nxW >= -r && pxX * x + pxY * y + pxZ * z + pxW >= -r + && nyX * x + nyY * y + nyZ * z + nyW >= -r && pyX * x + pyY * y + pyZ * z + pyW >= -r + && nzX * x + nzY * y + nzZ * z + nzW >= -r && pzX * x + pzY * y + pzZ * z + pzW >= -r; + } + + /** + * Determine whether the given sphere is partly or completely within or outside + * of the frustum defined by this frustum culler. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for spheres that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param center the sphere's center + * @param radius the sphere's radius + * @return {@link #INSIDE} if the given sphere is completely inside the frustum, + * or {@link #INTERSECT} if the sphere intersects the frustum, or + * {@link #OUTSIDE} if the sphere is outside of the frustum + */ + public int intersectSphere(Vector3f center, float radius) { + return intersectSphere(center.x, center.y, center.z, radius); + } + + /** + * Determine whether the given sphere is partly or completely within or outside + * of the frustum defined by this frustum culler. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for spheres that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param x the x-coordinate of the sphere's center + * @param y the y-coordinate of the sphere's center + * @param z the z-coordinate of the sphere's center + * @param r the sphere's radius + * @return {@link #INSIDE} if the given sphere is completely inside the frustum, + * or {@link #INTERSECT} if the sphere intersects the frustum, or + * {@link #OUTSIDE} if the sphere is outside of the frustum + */ + public int intersectSphere(float x, float y, float z, float r) { + boolean inside = true; + float dist; + dist = nxX * x + nxY * y + nxZ * z + nxW; + if (dist >= -r) { + inside &= dist >= r; + dist = pxX * x + pxY * y + pxZ * z + pxW; + if (dist >= -r) { + inside &= dist >= r; + dist = nyX * x + nyY * y + nyZ * z + nyW; + if (dist >= -r) { + inside &= dist >= r; + dist = pyX * x + pyY * y + pyZ * z + pyW; + if (dist >= -r) { + inside &= dist >= r; + dist = nzX * x + nzY * y + nzZ * z + nzW; + if (dist >= -r) { + inside &= dist >= r; + dist = pzX * x + pzY * y + pzZ * z + pzW; + if (dist >= -r) { + inside &= dist >= r; + return inside ? INSIDE : INTERSECT; + } + } + } + } + } + } + return OUTSIDE; + } + + /** + * Test whether the given axis-aligned box is partly or completely within or + * outside of the frustum defined by this frustum culler. The box + * is specified via its min and max corner + * coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param min the minimum corner coordinates of the axis-aligned box + * @param max the maximum corner coordinates of the axis-aligned box + * @return true if the axis-aligned box is completely or partly + * inside of the frustum; false otherwise + */ + public boolean testAab(Vector3f min, Vector3f max) { + return testAab(min.x, min.y, min.z, max.x, max.y, max.z); + } + + /** + * Test whether the given axis-aligned box is partly or completely within or + * outside of the frustum defined by this frustum culler. The box + * is specified via its min and max corner coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @return true if the axis-aligned box is completely or partly + * inside of the frustum; false otherwise + */ + public boolean testAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + /* + * This is an implementation of the "2.4 Basic intersection test" of the + * mentioned site. It does not distinguish between partially inside and fully + * inside, though, so the test with the 'p' vertex is omitted. + */ + return nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW + && pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW + && nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW + && pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW + && nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW + && pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW; + } + + /** + * Test whether the given XY-plane (at Z = 0) is partly or + * completely within or outside of the frustum defined by this + * frustum culler. The plane is specified via its min and + * max corner coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for planes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param min the minimum corner coordinates of the XY-plane + * @param max the maximum corner coordinates of the XY-plane + * @return true if the XY-plane is completely or partly inside of + * the frustum; false otherwise + */ + public boolean testPlaneXY(Vector2f min, Vector2f max) { + return testPlaneXY(min.x, min.y, max.x, max.y); + } + + /** + * Test whether the given XY-plane (at Z = 0) is partly or + * completely within or outside of the frustum defined by this + * frustum culler. The plane is specified via its min and max corner + * coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for planes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @return true if the XY-plane is completely or partly inside of + * the frustum; false otherwise + */ + public boolean testPlaneXY(float minX, float minY, float maxX, float maxY) { + /* + * This is an implementation of the "2.4 Basic intersection test" of the + * mentioned site. It does not distinguish between partially inside and fully + * inside, though, so the test with the 'p' vertex is omitted. + */ + return nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) >= -nxW + && pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) >= -pxW + && nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) >= -nyW + && pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) >= -pyW + && nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) >= -nzW + && pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) >= -pzW; + } + + /** + * Test whether the given XZ-plane (at Y = 0) is partly or + * completely within or outside of the frustum defined by this + * frustum culler. The plane is specified via its min and max corner + * coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns true for planes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @return true if the XZ-plane is completely or partly inside of + * the frustum; false otherwise + */ + public boolean testPlaneXZ(float minX, float minZ, float maxX, float maxZ) { + /* + * This is an implementation of the "2.4 Basic intersection test" of the + * mentioned site. It does not distinguish between partially inside and fully + * inside, though, so the test with the 'p' vertex is omitted. + */ + return nxX * (nxX < 0 ? minX : maxX) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW + && pxX * (pxX < 0 ? minX : maxX) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW + && nyX * (nyX < 0 ? minX : maxX) + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW + && pyX * (pyX < 0 ? minX : maxX) + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW + && nzX * (nzX < 0 ? minX : maxX) + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW + && pzX * (pzX < 0 ? minX : maxX) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW; + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner + * coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param min the minimum corner coordinates of the axis-aligned box + * @param max the maximum corner coordinates of the axis-aligned box + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum; or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(Vector3f min, Vector3f max) { + return intersectAab(min.x, min.y, min.z, max.x, max.y, max.z); + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner coordinates. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum, or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + /* + * This is an implementation of the "2.4 Basic intersection test" of the + * mentioned site. + * + * In addition to the algorithm in the paper, this method also returns the index + * of the first plane that culled the box. + */ + int plane = PLANE_NX; + boolean inside = true; + if (nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) { + plane = PLANE_PX; + inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW; + if (pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) { + plane = PLANE_NY; + inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW; + if (nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) { + plane = PLANE_PY; + inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW; + if (pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) { + plane = PLANE_NZ; + inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW; + if (nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) { + plane = PLANE_PZ; + inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW; + if (pzX * (pzX < 0 ? minX : maxX) + pzY * (pzY < 0 ? minY : maxY) + + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) { + inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW; + return inside ? INSIDE : INTERSECT; + } + } + } + } + } + } + return plane; + } + + /** + * Compute the signed distance from the given axis-aligned box to the + * plane. + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @param plane one of {@link #PLANE_NX}, {@link #PLANE_PX}, {@link #PLANE_NY}, + * {@link #PLANE_PY}, {@link #PLANE_NZ} and {@link #PLANE_PZ} + * @return the signed distance of the axis-aligned box to the plane + */ + public float distanceToPlane(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int plane) { + return planes[plane].x * (planes[plane].x < 0 ? maxX : minX) + + planes[plane].y * (planes[plane].y < 0 ? maxY : minY) + + planes[plane].z * (planes[plane].z < 0 ? maxZ : minZ) + planes[plane].w; + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner + * coordinates. + *

+ * This method differs from {@link #intersectAab(Vector3fc, Vector3fc)} in that + * it allows to mask-off planes that should not be calculated. For example, in + * order to only test a box against the left frustum plane, use a mask of + * {@link #PLANE_MASK_NX}. Or in order to test all planes except the left + * plane, use a mask of (~0 ^ PLANE_MASK_NX). + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param min the minimum corner coordinates of the axis-aligned box + * @param max the maximum corner coordinates of the axis-aligned box + * @param mask contains as bitset all the planes that should be tested. This + * value can be any combination of {@link #PLANE_MASK_NX}, + * {@link #PLANE_MASK_PX}, {@link #PLANE_MASK_NY}, + * {@link #PLANE_MASK_PY}, {@link #PLANE_MASK_NZ} and + * {@link #PLANE_MASK_PZ} + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum, or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(Vector3f min, Vector3f max, int mask) { + return intersectAab(min.x, min.y, min.z, max.x, max.y, max.z, mask); + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner coordinates. + *

+ * This method differs from + * {@link #intersectAab(float, float, float, float, float, float)} in that it + * allows to mask-off planes that should not be calculated. For example, in + * order to only test a box against the left frustum plane, use a mask of + * {@link #PLANE_MASK_NX}. Or in order to test all planes except the left + * plane, use a mask of (~0 ^ PLANE_MASK_NX). + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @param mask contains as bitset all the planes that should be tested. This + * value can be any combination of {@link #PLANE_MASK_NX}, + * {@link #PLANE_MASK_PX}, {@link #PLANE_MASK_NY}, + * {@link #PLANE_MASK_PY}, {@link #PLANE_MASK_NZ} and + * {@link #PLANE_MASK_PZ} + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum, or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int mask) { + /* + * This is an implementation of the first algorithm in + * "2.5 Plane masking and coherency" of the mentioned site. + * + * In addition to the algorithm in the paper, this method also returns the index + * of the first plane that culled the box. + */ + int plane = PLANE_NX; + boolean inside = true; + if ((mask & PLANE_MASK_NX) == 0 || nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) { + plane = PLANE_PX; + inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW; + if ((mask & PLANE_MASK_PX) == 0 || pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) { + plane = PLANE_NY; + inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW; + if ((mask & PLANE_MASK_NY) == 0 || nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) { + plane = PLANE_PY; + inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW; + if ((mask & PLANE_MASK_PY) == 0 || pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) { + plane = PLANE_NZ; + inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW; + if ((mask & PLANE_MASK_NZ) == 0 || nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) { + plane = PLANE_PZ; + inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW; + if ((mask & PLANE_MASK_PZ) == 0 || pzX * (pzX < 0 ? minX : maxX) + + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) { + inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW; + return inside ? INSIDE : INTERSECT; + } + } + } + } + } + } + return plane; + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner + * coordinates. + *

+ * This method differs from {@link #intersectAab(Vector3fc, Vector3fc)} in that + * it allows to mask-off planes that should not be calculated. For example, in + * order to only test a box against the left frustum plane, use a mask of + * {@link #PLANE_MASK_NX}. Or in order to test all planes except the left + * plane, use a mask of (~0 ^ PLANE_MASK_NX). + *

+ * In addition, the startPlane denotes the first frustum plane to + * test the box against. To use this effectively means to store the plane that + * previously culled an axis-aligned box (as returned by + * intersectAab()) and in the next frame use the return value as + * the argument to the startPlane parameter of this method. The + * assumption is that the plane that culled the object previously will also cull + * it now (temporal coherency) and the culling computation is likely reduced in + * that case. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + * + * @param min the minimum corner coordinates of the axis-aligned box + * @param max the maximum corner coordinates of the axis-aligned box + * @param mask contains as bitset all the planes that should be tested. + * This value can be any combination of + * {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX}, + * {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY}, + * {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ} + * @param startPlane the first frustum plane to test the axis-aligned box + * against. It is one of {@link #PLANE_NX}, {@link #PLANE_PX}, + * {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and + * {@link #PLANE_PZ} + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum, or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(Vector3f min, Vector3f max, int mask, int startPlane) { + return intersectAab(min.x, min.y, min.z, max.x, max.y, max.z, mask, startPlane); + } + + /** + * Determine whether the given axis-aligned box is partly or completely within + * or outside of the frustum defined by this frustum culler and, if + * the box is not inside this frustum, return the index of the plane that culled + * it. The box is specified via its min and max corner coordinates. + *

+ * This method differs from + * {@link #intersectAab(float, float, float, float, float, float)} in that it + * allows to mask-off planes that should not be calculated. For example, in + * order to only test a box against the left frustum plane, use a mask of + * {@link #PLANE_MASK_NX}. Or in order to test all planes except the left + * plane, use a mask of (~0 ^ PLANE_MASK_NX). + *

+ * In addition, the startPlane denotes the first frustum plane to + * test the box against. To use this effectively means to store the plane that + * previously culled an axis-aligned box (as returned by + * intersectAab()) and in the next frame use the return value as + * the argument to the startPlane parameter of this method. The + * assumption is that the plane that culled the object previously will also cull + * it now (temporal coherency) and the culling computation is likely reduced in + * that case. + *

+ * The algorithm implemented by this method is conservative. This means that in + * certain circumstances a false positive can occur, when the method + * returns {@link #INTERSECT} for boxes that do not intersect the frustum. See + * iquilezles.org + * for an examination of this problem. + *

+ * Reference: + * Efficient View + * Frustum Culling + * + * @param minX the x-coordinate of the minimum corner + * @param minY the y-coordinate of the minimum corner + * @param minZ the z-coordinate of the minimum corner + * @param maxX the x-coordinate of the maximum corner + * @param maxY the y-coordinate of the maximum corner + * @param maxZ the z-coordinate of the maximum corner + * @param mask contains as bitset all the planes that should be tested. + * This value can be any combination of + * {@link #PLANE_MASK_NX}, {@link #PLANE_MASK_PX}, + * {@link #PLANE_MASK_NY}, {@link #PLANE_MASK_PY}, + * {@link #PLANE_MASK_NZ} and {@link #PLANE_MASK_PZ} + * @param startPlane the first frustum plane to test the axis-aligned box + * against. It is one of {@link #PLANE_NX}, {@link #PLANE_PX}, + * {@link #PLANE_NY}, {@link #PLANE_PY}, {@link #PLANE_NZ} and + * {@link #PLANE_PZ} + * @return the index of the first plane that culled the box, if the box does not + * intersect the frustum, or {@link #INTERSECT} if the box intersects + * the frustum, or {@link #INSIDE} if the box is fully inside of the + * frustum. The plane index is one of {@link #PLANE_NX}, + * {@link #PLANE_PX}, {@link #PLANE_NY}, {@link #PLANE_PY}, + * {@link #PLANE_NZ} and {@link #PLANE_PZ} + */ + public int intersectAab(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, int mask, + int startPlane) { + /* + * This is an implementation of the second algorithm in + * "2.5 Plane masking and coherency" of the mentioned site. + * + * In addition to the algorithm in the paper, this method also returns the index + * of the first plane that culled the box. + */ + int plane = startPlane; + boolean inside = true; + Vector4f p = planes[startPlane]; + if ((mask & 1 << startPlane) != 0 && p.x * (p.x < 0 ? minX : maxX) + p.y * (p.y < 0 ? minY : maxY) + + p.z * (p.z < 0 ? minZ : maxZ) < -p.w) { + return plane; + } + if ((mask & PLANE_MASK_NX) == 0 || nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) + + nxZ * (nxZ < 0 ? minZ : maxZ) >= -nxW) { + plane = PLANE_PX; + inside &= nxX * (nxX < 0 ? maxX : minX) + nxY * (nxY < 0 ? maxY : minY) + + nxZ * (nxZ < 0 ? maxZ : minZ) >= -nxW; + if ((mask & PLANE_MASK_PX) == 0 || pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) + + pxZ * (pxZ < 0 ? minZ : maxZ) >= -pxW) { + plane = PLANE_NY; + inside &= pxX * (pxX < 0 ? maxX : minX) + pxY * (pxY < 0 ? maxY : minY) + + pxZ * (pxZ < 0 ? maxZ : minZ) >= -pxW; + if ((mask & PLANE_MASK_NY) == 0 || nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) + + nyZ * (nyZ < 0 ? minZ : maxZ) >= -nyW) { + plane = PLANE_PY; + inside &= nyX * (nyX < 0 ? maxX : minX) + nyY * (nyY < 0 ? maxY : minY) + + nyZ * (nyZ < 0 ? maxZ : minZ) >= -nyW; + if ((mask & PLANE_MASK_PY) == 0 || pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) + + pyZ * (pyZ < 0 ? minZ : maxZ) >= -pyW) { + plane = PLANE_NZ; + inside &= pyX * (pyX < 0 ? maxX : minX) + pyY * (pyY < 0 ? maxY : minY) + + pyZ * (pyZ < 0 ? maxZ : minZ) >= -pyW; + if ((mask & PLANE_MASK_NZ) == 0 || nzX * (nzX < 0 ? minX : maxX) + nzY * (nzY < 0 ? minY : maxY) + + nzZ * (nzZ < 0 ? minZ : maxZ) >= -nzW) { + plane = PLANE_PZ; + inside &= nzX * (nzX < 0 ? maxX : minX) + nzY * (nzY < 0 ? maxY : minY) + + nzZ * (nzZ < 0 ? maxZ : minZ) >= -nzW; + if ((mask & PLANE_MASK_PZ) == 0 || pzX * (pzX < 0 ? minX : maxX) + + pzY * (pzY < 0 ? minY : maxY) + pzZ * (pzZ < 0 ? minZ : maxZ) >= -pzW) { + inside &= pzX * (pzX < 0 ? maxX : minX) + pzY * (pzY < 0 ? maxY : minY) + + pzZ * (pzZ < 0 ? maxZ : minZ) >= -pzW; + return inside ? INSIDE : INTERSECT; + } + } + } + } + } + } + return plane; + } + + /** + * Test whether the given line segment, defined by the end points a + * and b, is partly or completely within the frustum defined by + * this frustum culler. + * + * @param a the line segment's first end point + * @param b the line segment's second end point + * @return true if the given line segment is partly or completely + * inside the frustum; false otherwise + */ + public boolean testLineSegment(Vector3f a, Vector3f b) { + return testLineSegment(a.x, a.y, a.z, b.x, b.y, b.z); + } + + private float fma(float f1, float f2, float f3) { + return (f1 * f2) + f3; + } + + /** + * Test whether the given line segment, defined by the end points + * (aX, aY, aZ) and (bX, bY, bZ), is partly or + * completely within the frustum defined by this frustum culler. + * + * @param aX the x coordinate of the line segment's first end point + * @param aY the y coordinate of the line segment's first end point + * @param aZ the z coordinate of the line segment's first end point + * @param bX the x coordinate of the line segment's second end point + * @param bY the y coordinate of the line segment's second end point + * @param bZ the z coordinate of the line segment's second end point + * @return true if the given line segment is partly or completely + * inside the frustum; false otherwise + */ + public boolean testLineSegment(float aX, float aY, float aZ, float bX, float bY, float bZ) { + float da, db; + da = fma(nxX, aX, fma(nxY, aY, fma(nxZ, aZ, nxW))); + db = fma(nxX, bX, fma(nxY, bY, fma(nxZ, bZ, nxW))); + if (da < 0.0f && db < 0.0f) + return false; + if (da * db < 0.0f) { + float p = Math.abs(da) / Math.abs(db - da); + float dx = fma(bX - aX, p, aX), dy = fma(bY - aY, p, aY), dz = fma(bZ - aZ, p, aZ); + if (da < 0.0f) { + aX = dx; + aY = dy; + aZ = dz; + } else { + bX = dx; + bY = dy; + bZ = dz; + } + } + da = fma(pxX, aX, fma(pxY, aY, fma(pxZ, aZ, pxW))); + db = fma(pxX, bX, fma(pxY, bY, fma(pxZ, bZ, pxW))); + if (da < 0.0f && db < 0.0f) + return false; + if (da * db < 0.0f) { + float p = Math.abs(da) / Math.abs(db - da); + float dx = fma(bX - aX, p, aX), dy = fma(bY - aY, p, aY), dz = fma(bZ - aZ, p, aZ); + if (da < 0.0f) { + aX = dx; + aY = dy; + aZ = dz; + } else { + bX = dx; + bY = dy; + bZ = dz; + } + } + da = fma(nyX, aX, fma(nyY, aY, fma(nyZ, aZ, nyW))); + db = fma(nyX, bX, fma(nyY, bY, fma(nyZ, bZ, nyW))); + if (da < 0.0f && db < 0.0f) + return false; + if (da * db < 0.0f) { + float p = Math.abs(da) / Math.abs(db - da); + float dx = fma(bX - aX, p, aX), dy = fma(bY - aY, p, aY), dz = fma(bZ - aZ, p, aZ); + if (da < 0.0f) { + aX = dx; + aY = dy; + aZ = dz; + } else { + bX = dx; + bY = dy; + bZ = dz; + } + } + da = fma(pyX, aX, fma(pyY, aY, fma(pyZ, aZ, pyW))); + db = fma(pyX, bX, fma(pyY, bY, fma(pyZ, bZ, pyW))); + if (da < 0.0f && db < 0.0f) + return false; + if (da * db < 0.0f) { + float p = Math.abs(da) / Math.abs(db - da); + float dx = fma(bX - aX, p, aX), dy = fma(bY - aY, p, aY), dz = fma(bZ - aZ, p, aZ); + if (da < 0.0f) { + aX = dx; + aY = dy; + aZ = dz; + } else { + bX = dx; + bY = dy; + bZ = dz; + } + } + da = fma(nzX, aX, fma(nzY, aY, fma(nzZ, aZ, nzW))); + db = fma(nzX, bX, fma(nzY, bY, fma(nzZ, bZ, nzW))); + if (da < 0.0f && db < 0.0f) + return false; + if (da * db < 0.0f) { + float p = Math.abs(da) / Math.abs(db - da); + float dx = fma(bX - aX, p, aX), dy = fma(bY - aY, p, aY), dz = fma(bZ - aZ, p, aZ); + if (da < 0.0f) { + aX = dx; + aY = dy; + aZ = dz; + } else { + bX = dx; + bY = dy; + bZ = dz; + } + } + da = fma(pzX, aX, fma(pzY, aY, fma(pzZ, aZ, pzW))); + db = fma(pzX, bX, fma(pzY, bY, fma(pzZ, bZ, pzW))); + return da >= 0.0f || db >= 0.0f; + } + +} \ No newline at end of file diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java new file mode 100644 index 0000000..fd41992 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/BlockVertexIDs.java @@ -0,0 +1,74 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; + +public class BlockVertexIDs implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV"); + + public static final Map modelToID = new HashMap(); + + public static int builtin_water_still_vertex_id = 0; + public static int builtin_water_flow_vertex_id = 0; + + @Override + public void onResourceManagerReload(IResourceManager var1) { + try { + IResource itemsCsv = var1.getResource(new ResourceLocation("eagler:glsl/deferred/vertex_ids.csv")); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(itemsCsv.getInputStream(), StandardCharsets.UTF_8))) { + modelToID.clear(); + String line; + boolean firstLine = true; + while((line = reader.readLine()) != null) { + if((line = line.trim()).length() > 0) { + if(firstLine) { + firstLine = false; + continue; + } + String[] split = line.split(","); + if(split.length == 2) { + try { + int i = Integer.parseInt(split[1]); + if(i <= 0 || i > 254) { + logger.error("Error: {}: Only IDs 1 to 254 are configurable!", split[0]); + throw new NumberFormatException(); + } + i -= 127; + modelToID.put(split[0], i); + switch(split[0]) { + case "eagler:builtin/water_still_vertex_id": + builtin_water_still_vertex_id = i; + break; + case "eagler:builtin/water_flow_vertex_id": + builtin_water_flow_vertex_id = i; + break; + default: + break; + } + continue; + }catch(NumberFormatException ex) { + } + } + logger.error("Skipping bad vertex id entry: {}", line); + } + } + } + }catch(Throwable t) { + logger.error("Could not load list of vertex ids!"); + logger.error(t); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/CloudRenderWorker.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/CloudRenderWorker.java new file mode 100644 index 0000000..3c0b784 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/CloudRenderWorker.java @@ -0,0 +1,607 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.TextureCopyUtil; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderCloudsNoise3D; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderCloudsSample; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderCloudsShapes; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderCloudsSunOcclusion; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.util.MathHelper; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class CloudRenderWorker { + + static PipelineShaderCloudsNoise3D shader_clouds_noise3d = null; + static PipelineShaderCloudsShapes shader_clouds_shapes = null; + static PipelineShaderCloudsSample shader_clouds_sample = null; + static PipelineShaderCloudsSunOcclusion shader_clouds_sun_occlusion = null; + + static int cloudNoiseTexture = -1; + + static int cloud3DSamplesTextureSizeX = 256; + static int cloud3DSamplesTextureSizeY = 256; + static int cloud3DSamplesTextureSizeZ = 64; + + static int cloudParaboloidTextureSize = 512; + + static int cloud3DSamplesTexture = -1; + static IFramebufferGL[] cloud3DSamplesSlices = null; + + static IFramebufferGL[] cloudNoiseSampleParaboloidFramebuffer = new IFramebufferGL[4]; + static int[] cloudNoiseSampleParaboloidTexture = new int[] { -1, -1, -1, -1 }; + + static IFramebufferGL cloudOcclusionFramebuffer = null; + static int cloudOcclusionTexture = -1; + + static int cloudSpecialShapeTexture = -1; + + static float renderViewX = 0.0f; + static float renderViewY = 0.0f; + static float renderViewZ = 0.0f; + + private static final Matrix4f tmpMatrix1 = new Matrix4f(); + private static final Matrix3f tmpMatrix2 = new Matrix3f(); + private static final Matrix3f tmpMatrix3 = new Matrix3f(); + private static final Vector3f tmpVector1 = new Vector3f(); + private static final Vector3f tmpVector2 = new Vector3f(); + private static final Vector3f tmpVector3 = new Vector3f(); + + private static long cloudStartTimer = 0l; + static int cloudRenderProgress = 0; + static int cloudRenderPeriod = 500; + static int cloudRenderPhase = 0; + + static float cloudColorR = 0.0f; + static float cloudColorG = 0.0f; + static float cloudColorB = 0.0f; + + static boolean isDrawingCloudShapes = false; + + static int shapePosX = 100; + static int shapeSizeX = 32; + static int shapePosY = 80; + static int shapeSizeY = 16; + static int shapePosZ = 20; + static int shapeSizeZ = 24; + static float shapeRotate = 45.0f; + + static long shapeUpdateTimer = 0l; + static long nextShapeAppearance = 0l; + + static EaglercraftRandom rand = new EaglercraftRandom(); + + static void initialize() { + destroy(); + + cloudStartTimer = System.currentTimeMillis(); + cloudRenderProgress = 0; + cloudRenderPeriod = 500; + cloudRenderPhase = 0; + cloudColorR = 0.0f; + cloudColorG = 0.0f; + cloudColorB = 0.0f; + + shapeUpdateTimer = cloudStartTimer; + nextShapeAppearance = cloudStartTimer + rand.nextInt(1800000); + + cloudNoiseTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(cloudNoiseTexture); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + int cloudNoiseW = 64, cloudNoiseH = 64, cloudNoiseLen = 4096; + byte[] cloudNoiseDat = new byte[cloudNoiseLen]; + (new EaglercraftRandom(696969l)).nextBytes(cloudNoiseDat); + ByteBuffer cloudNoiseDatBuffer = EagRuntime.allocateByteBuffer(cloudNoiseDat.length); + cloudNoiseDatBuffer.put(cloudNoiseDat); + cloudNoiseDatBuffer.flip(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, cloudNoiseW, cloudNoiseH, 0, GL_RED, GL_UNSIGNED_BYTE, cloudNoiseDatBuffer); + EagRuntime.freeByteBuffer(cloudNoiseDatBuffer); + + cloud3DSamplesTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture3D(cloud3DSamplesTexture); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + _wglTexImage3D(GL_TEXTURE_3D, 0, _GL_R8, cloud3DSamplesTextureSizeX, cloud3DSamplesTextureSizeY, + cloud3DSamplesTextureSizeZ, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer) null); + + cloud3DSamplesSlices = new IFramebufferGL[cloud3DSamplesTextureSizeZ]; + for(int i = 0; i < cloud3DSamplesTextureSizeZ; ++i) { + cloud3DSamplesSlices[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloud3DSamplesSlices[i]); + _wglFramebufferTextureLayer(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, EaglercraftGPU.getNativeTexture(cloud3DSamplesTexture), 0, i); + } + + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f); + for(int i = 0; i < 4; ++i) { + cloudNoiseSampleParaboloidFramebuffer[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloudNoiseSampleParaboloidFramebuffer[i]); + cloudNoiseSampleParaboloidTexture[i] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(cloudNoiseSampleParaboloidTexture[i]); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, i == 3 ? GL_LINEAR : GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, i == 3 ? GL_LINEAR : GL_NEAREST); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, cloudParaboloidTextureSize, cloudParaboloidTextureSize, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(cloudNoiseSampleParaboloidTexture[i]), 0); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + } + + cloudSpecialShapeTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture3D(cloudSpecialShapeTexture); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + byte[] cloudShapeTexture = EagRuntime.getResourceBytes("/assets/eagler/glsl/deferred/clouds_shapes.bmp"); + cloudNoiseDatBuffer = EagRuntime.allocateByteBuffer(cloudShapeTexture.length); + cloudNoiseDatBuffer.put(cloudShapeTexture); + cloudNoiseDatBuffer.flip(); + _wglTexImage3D(GL_TEXTURE_3D, 0, _GL_R8, 32, 16, 24, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer) cloudNoiseDatBuffer); + EagRuntime.freeByteBuffer(cloudNoiseDatBuffer); + + shader_clouds_noise3d = PipelineShaderCloudsNoise3D.compile(); + shader_clouds_noise3d.loadUniforms(); + shader_clouds_shapes = PipelineShaderCloudsShapes.compile(); + shader_clouds_shapes.loadUniforms(); + shader_clouds_sample = PipelineShaderCloudsSample.compile(); + shader_clouds_sample.loadUniforms(); + shader_clouds_sun_occlusion = PipelineShaderCloudsSunOcclusion.compile(); + shader_clouds_sun_occlusion.loadUniforms(); + + cloudOcclusionFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloudOcclusionFramebuffer); + cloudOcclusionTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(cloudOcclusionTexture); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer)null); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(cloudOcclusionTexture), 0); + } + + static void setPosition(float x, float y, float z) { + renderViewX = x; + renderViewY = y; + renderViewZ = z; + } + + static void bindParaboloid() { + GlStateManager.bindTexture(cloudNoiseSampleParaboloidTexture[3]); + } + + static void update() { + long millis = System.currentTimeMillis(); + int cloudProgress = (int)(millis - cloudStartTimer); + int totalCloudSteps = 32 + 32 - 1; + int currentCloudStep = cloudProgress * totalCloudSteps / cloudRenderPeriod; + boolean b = false; + if(currentCloudStep > totalCloudSteps) { + currentCloudStep = totalCloudSteps; + b = true; + } + + float playerCoordsNoiseMapScale = 0.02f; + FloatBuffer matrixCopyBuffer = EaglerDeferredPipeline.matrixCopyBuffer; + + WorldClient wc = Minecraft.getMinecraft().theWorld; + float rain = wc.getRainStrength(0.0f); + if(cloudRenderProgress == 0) { + shader_clouds_noise3d.useProgram(); + _wglUniform2f(shader_clouds_noise3d.uniforms.u_textureSize2f, 1.0f / cloud3DSamplesTextureSizeX, 1.0f / cloud3DSamplesTextureSizeY); + float m = (float)((millis % 1200000l) * 0.00002); + _wglUniform3f(shader_clouds_noise3d.uniforms.u_cloudMovement3f, m, 0.0f, m);//2.213f, 0.0f, 2.213f); + + tmpMatrix1.setIdentity(); + tmpVector1.set(renderViewX * playerCoordsNoiseMapScale, 0.0f, renderViewZ * playerCoordsNoiseMapScale); + Matrix4f.translate(tmpVector1, tmpMatrix1, tmpMatrix1); + float s = 1500.0f; + tmpVector1.set(s, s * 0.0015f, s); + Matrix4f.scale(tmpVector1, tmpMatrix1, tmpMatrix1); + matrixCopyBuffer.clear(); + matrixCopyBuffer.put(tmpMatrix1.m00); + matrixCopyBuffer.put(tmpMatrix1.m01); + matrixCopyBuffer.put(tmpMatrix1.m02); + matrixCopyBuffer.put(tmpMatrix1.m10); + matrixCopyBuffer.put(tmpMatrix1.m11); + matrixCopyBuffer.put(tmpMatrix1.m12); + matrixCopyBuffer.put(tmpMatrix1.m20); + matrixCopyBuffer.put(tmpMatrix1.m21); + matrixCopyBuffer.put(tmpMatrix1.m22); + matrixCopyBuffer.put(tmpMatrix1.m30); + matrixCopyBuffer.put(tmpMatrix1.m31); + matrixCopyBuffer.put(tmpMatrix1.m32); + matrixCopyBuffer.flip(); + _wglUniformMatrix4x3fv(shader_clouds_noise3d.uniforms.u_sampleOffsetMatrix4f, false, matrixCopyBuffer); + + shader_clouds_sample.useProgram(); + _wglUniform1f(shader_clouds_sample.uniforms.u_rainStrength1f, 0.0f); + _wglUniform1f(shader_clouds_sample.uniforms.u_cloudTimer1f, 0.0f); + _wglUniform3f(shader_clouds_sample.uniforms.u_cloudOffset3f, renderViewX, renderViewY, renderViewZ); + Vector3f currentSunAngle = DeferredStateManager.currentSunLightAngle; + _wglUniform3f(shader_clouds_sample.uniforms.u_sunDirection3f, -currentSunAngle.x, -currentSunAngle.y, -currentSunAngle.z); + currentSunAngle = tmpVector1; + currentSunAngle.set(DeferredStateManager.currentSunLightColor); + float luma = currentSunAngle.x * 0.299f + currentSunAngle.y * 0.587f + currentSunAngle.z * 0.114f; + float sat = 0.65f; // desaturate sun a bit + currentSunAngle.x = (currentSunAngle.x - luma) * sat + luma; + currentSunAngle.y = (currentSunAngle.y - luma) * sat + luma; + currentSunAngle.z = (currentSunAngle.z - luma) * sat + luma; + cloudColorR += (currentSunAngle.x - cloudColorR) * 0.1f; + cloudColorG += (currentSunAngle.y - cloudColorG) * 0.1f; + cloudColorB += (currentSunAngle.z - cloudColorB) * 0.1f; + _wglUniform3f(shader_clouds_sample.uniforms.u_sunColor3f, cloudColorR, cloudColorG, cloudColorB); + + float cloudDensityTimer = (float)((System.currentTimeMillis() % 10000000l) * 0.001); + cloudDensityTimer += MathHelper.sin(cloudDensityTimer * 1.5f) * 1.5f; + float x = cloudDensityTimer * 0.004f; + float f1 = MathHelper.sin(x + 0.322f) * 0.544f + MathHelper.sin(x * 4.5f + 1.843f) * 0.69f + MathHelper.sin(x * 3.4f + 0.8f) * 0.6f + MathHelper.sin(x * 6.1f + 1.72f) * 0.7f; + x = cloudDensityTimer * 0.002f; + float f2 = MathHelper.cos(x + 2.7f) + MathHelper.cos(x * 1.28f + 1.3f) * 0.4f + MathHelper.cos(x * 4.0f + 2.5f) * 0.3f + MathHelper.cos(x * 2.3f + 1.07f); + float rain2 = rain + wc.getThunderStrength(0.0f); + _wglUniform4f(shader_clouds_sample.uniforms.u_densityModifier4f, 0.015f + f1 * 0.0021f * (1.0f - rain2 * 0.35f) + rain2 * 0.00023f, 0.0325f, -0.0172f + f2 * 0.00168f * (1.0f - rain2 * 0.35f) + rain * 0.0015f, 0.0f); + } + + if(cloudRenderProgress < 32 && currentCloudStep > cloudRenderProgress) { + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(cloudNoiseTexture); + + GlStateManager.viewport(0, 0, cloud3DSamplesTextureSizeX, cloud3DSamplesTextureSizeY); + + updateShape(); + boolean shapeAllow = isDrawingCloudShapes; + boolean shapeInit = false; + + for(int i = cloudRenderProgress, j = currentCloudStep < 32 ? currentCloudStep : 32; i < j; ++i) { + int ccl = i * 2; + + boolean drawShape = false; + if(isDrawingCloudShapes && shapeAllow) { + if(ccl >= shapePosZ && ccl < shapePosZ + shapeSizeZ) { + drawShape = true; + if(!shapeInit) { + shapeInit = true; + Matrix3f mat = tmpMatrix2; + mat.setIdentity(); + mat.m00 = MathHelper.cos(shapeRotate * 0.0174532f); + mat.m01 = MathHelper.sin(shapeRotate * 0.0174532f); + mat.m10 = -mat.m01; + mat.m11 = mat.m00; + mat = tmpMatrix3; + mat.setIdentity(); + mat.m00 = (float)shapeSizeX * 0.5f; + mat.m11 = (float)shapeSizeY * 0.5f; + Matrix3f.mul(tmpMatrix2, mat, tmpMatrix2); + tmpMatrix2.m20 = shapePosX - renderViewX * playerCoordsNoiseMapScale * 128.0f; + tmpMatrix2.m21 = shapePosY - renderViewZ * playerCoordsNoiseMapScale * 128.0f; + mat.setIdentity(); + mat.m00 = 2.0f / cloud3DSamplesTextureSizeX; + mat.m11 = 2.0f / cloud3DSamplesTextureSizeY; + Matrix3f.mul(mat, tmpMatrix2, tmpMatrix2); + mat = tmpMatrix2; + mat.m20 -= 1.0f; + mat.m21 -= 1.0f; + if(!checkFrustum(mat)) { + drawShape = false; + shapeAllow = false; + }else { + matrixCopyBuffer.clear(); + matrixCopyBuffer.put(mat.m00); + matrixCopyBuffer.put(mat.m01); + matrixCopyBuffer.put(mat.m10); + matrixCopyBuffer.put(mat.m11); + matrixCopyBuffer.put(mat.m20); + matrixCopyBuffer.put(mat.m21); + matrixCopyBuffer.flip(); + shader_clouds_shapes.useProgram(); + _wglUniformMatrix3x2fv(shader_clouds_shapes.uniforms.u_transformMatrix3x2f, false, matrixCopyBuffer); + _wglUniform1f(shader_clouds_shapes.uniforms.u_textureLod1f, 0.0f); + _wglUniform2f(shader_clouds_shapes.uniforms.u_sampleWeights2f, 0.35f, 0.55f); + } + } + } + } + + shader_clouds_noise3d.useProgram(); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloud3DSamplesSlices[ccl]); + _wglUniform1f(shader_clouds_noise3d.uniforms.u_textureSlice1f, (float)(ccl / (float)cloud3DSamplesTextureSizeZ)); + + DrawUtils.drawStandardQuad2D(); + + if(drawShape) { + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_SRC_ALPHA); + shader_clouds_shapes.useProgram(); + _wglUniform1f(shader_clouds_shapes.uniforms.u_textureLevel1f, (float)(ccl - shapePosZ + 0.5f) / (float)shapeSizeZ); + GlStateManager.bindTexture3D(cloudSpecialShapeTexture); + DrawUtils.drawStandardQuad2D(); + GlStateManager.disableBlend(); + shader_clouds_noise3d.useProgram(); + GlStateManager.bindTexture(cloudNoiseTexture); + } + + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloud3DSamplesSlices[ccl + 1]); + _wglUniform1f(shader_clouds_noise3d.uniforms.u_textureSlice1f, (float)((ccl + 1) / (float)cloud3DSamplesTextureSizeZ)); + + DrawUtils.drawStandardQuad2D(); + + if(drawShape && ccl + 1 < shapePosZ + shapeSizeZ) { + GlStateManager.enableBlend(); + shader_clouds_shapes.useProgram(); + _wglUniform1f(shader_clouds_shapes.uniforms.u_textureLevel1f, (float)((ccl + 1) - shapePosZ + 0.5f) / (float)shapeSizeZ); + GlStateManager.bindTexture3D(cloudSpecialShapeTexture); + DrawUtils.drawStandardQuad2D(); + GlStateManager.disableBlend(); + } + } + } + + if(currentCloudStep >= 32 && currentCloudStep > cloudRenderProgress) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloudNoiseSampleParaboloidFramebuffer[cloudRenderPhase]); + GlStateManager.viewport(0, 0, cloudParaboloidTextureSize, cloudParaboloidTextureSize); + + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(EaglerDeferredPipeline.instance.atmosphereIrradianceTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture3D(cloud3DSamplesTexture); + shader_clouds_sample.useProgram(); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_DST_ALPHA, GL_ZERO); + + for(int i = cloudRenderProgress > 32 ? cloudRenderProgress - 32 : 0, j = currentCloudStep - 31; i < j; ++i) { + if(i == 0) { + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + } + + _wglUniform1f(shader_clouds_sample.uniforms.u_sampleStep1f, i * 2); + DrawUtils.drawStandardQuad2D(); + + _wglUniform1f(shader_clouds_sample.uniforms.u_sampleStep1f, i * 2 + 1); + DrawUtils.drawStandardQuad2D(); + } + + GlStateManager.disableBlend(); + } + + if(b) { + cloudRenderProgress = 0; + cloudStartTimer = System.currentTimeMillis(); + cloudProgress = 0; + cloudRenderPhase = (cloudRenderPhase + 1) % 3; + }else { + cloudRenderProgress = currentCloudStep; + } + + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloudNoiseSampleParaboloidFramebuffer[3]); + GlStateManager.viewport(0, 0, cloudParaboloidTextureSize, cloudParaboloidTextureSize); + + float fadeFactor = cloudProgress / (float)cloudRenderPeriod; + if(fadeFactor > 1.0f) fadeFactor = 1.0f; + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(cloudNoiseSampleParaboloidTexture[(cloudRenderPhase + 1) % 3]); + TextureCopyUtil.blitTexture(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + GlStateManager.setBlendConstants(0.0f, 0.0f, 0.0f, fadeFactor); + GlStateManager.bindTexture(cloudNoiseSampleParaboloidTexture[(cloudRenderPhase + 2) % 3]); + TextureCopyUtil.blitTexture(); + GlStateManager.disableBlend(); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, cloudOcclusionFramebuffer); + GlStateManager.viewport(0, 0, 1, 1); + if(rain >= 1.0f) { + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + }else if(DeferredStateManager.currentSunLightAngle.y < 0.0f) { + shader_clouds_sun_occlusion.useProgram(); + GlStateManager.bindTexture(cloudNoiseSampleParaboloidTexture[3]); + matrixCopyBuffer.clear(); + + tmpVector1.set(0.0f, 1.0f, 0.0f); + Vector3f vec33 = tmpVector3; + vec33.set(DeferredStateManager.currentSunLightAngle); + vec33.x = -vec33.x; + vec33.y = -vec33.y; + vec33.z = -vec33.z; + Vector3f.cross(tmpVector1, vec33, tmpVector1); + Vector3f.cross(vec33, tmpVector1, tmpVector2); + + float rad = 0.1f; + + matrixCopyBuffer.put(tmpVector1.x * rad); + matrixCopyBuffer.put(tmpVector2.x * rad); + matrixCopyBuffer.put(vec33.x * rad); + + matrixCopyBuffer.put(tmpVector1.y * rad); + matrixCopyBuffer.put(tmpVector2.y * rad); + matrixCopyBuffer.put(vec33.y * rad); + + matrixCopyBuffer.put(tmpVector1.z * rad); + matrixCopyBuffer.put(tmpVector2.z * rad); + matrixCopyBuffer.put(vec33.z * rad); + + rad = 1.0f - rad; + matrixCopyBuffer.put(vec33.x * rad); + matrixCopyBuffer.put(vec33.y * rad); + matrixCopyBuffer.put(vec33.z * rad); + + matrixCopyBuffer.flip(); + _wglUniformMatrix4x3fv(shader_clouds_sun_occlusion.uniforms.u_sampleMatrix4x3f, false, matrixCopyBuffer); + + if(rain > 0.0f) { + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_CONSTANT_ALPHA, GL_ZERO); + GlStateManager.setBlendConstants(0.0f, 0.0f, 0.0f, 1.0f - rain); + DrawUtils.drawStandardQuad2D(); + GlStateManager.disableBlend(); + }else { + DrawUtils.drawStandardQuad2D(); + } + }else { + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + } + } + + static void destroy() { + if(cloudNoiseTexture != -1) { + GlStateManager.deleteTexture(cloudNoiseTexture); + cloudNoiseTexture = -1; + } + for(int i = 0; i < 4; ++i) { + if(cloudNoiseSampleParaboloidFramebuffer[i] != null) { + _wglDeleteFramebuffer(cloudNoiseSampleParaboloidFramebuffer[i]); + cloudNoiseSampleParaboloidFramebuffer[i] = null; + } + if(cloudNoiseSampleParaboloidTexture[i] != -1) { + GlStateManager.deleteTexture(cloudNoiseSampleParaboloidTexture[i]); + cloudNoiseSampleParaboloidTexture[i] = -1; + } + } + if(cloud3DSamplesTexture != -1) { + GlStateManager.deleteTexture(cloud3DSamplesTexture); + cloud3DSamplesTexture = -1; + } + if(cloud3DSamplesSlices != null) { + for(int i = 0; i < cloud3DSamplesSlices.length; ++i) { + _wglDeleteFramebuffer(cloud3DSamplesSlices[i]); + } + cloud3DSamplesSlices = null; + } + if(cloudSpecialShapeTexture != -1) { + GlStateManager.deleteTexture(cloudSpecialShapeTexture); + cloudSpecialShapeTexture = -1; + } + if(cloudOcclusionFramebuffer != null) { + _wglDeleteFramebuffer(cloudOcclusionFramebuffer); + cloudOcclusionFramebuffer = null; + } + if(cloudOcclusionTexture != -1) { + GlStateManager.deleteTexture(cloudOcclusionTexture); + cloudOcclusionTexture = -1; + } + if(shader_clouds_noise3d != null) { + shader_clouds_noise3d.destroy(); + shader_clouds_noise3d = null; + } + if(shader_clouds_shapes != null) { + shader_clouds_shapes.destroy(); + shader_clouds_shapes = null; + } + if(shader_clouds_sample != null) { + shader_clouds_sample.destroy(); + shader_clouds_sample = null; + } + if(shader_clouds_sun_occlusion != null) { + shader_clouds_sun_occlusion.destroy(); + shader_clouds_sun_occlusion = null; + } + } + + private static void updateShape() { + long millis = System.currentTimeMillis(); + float dt = (float)((millis - shapeUpdateTimer) * 0.001); + shapeUpdateTimer = millis; + if(millis > nextShapeAppearance) { + float playerCoordsNoiseMapScale = 0.02f * 128.0f; + if(!isDrawingCloudShapes) { + float shapeScaleBase = rand.nextFloat() * 3.0f + 2.0f; + shapeSizeX = (int)(32 * shapeScaleBase * (0.9f + rand.nextFloat() * 0.2f)); + shapeSizeY = (int)(16 * shapeScaleBase * (0.95f + rand.nextFloat() * 0.1f)); + shapeSizeZ = (int)(24 * shapeScaleBase * (0.48f + rand.nextFloat() * 0.04f)); + do { + shapePosX = (int)(cloud3DSamplesTextureSizeX * (rand.nextFloat() * 1.5f - 0.75f)); + shapePosY = (int)(cloud3DSamplesTextureSizeY * (rand.nextFloat() * 1.5f - 0.75f)); + }while(shapePosX > -192 && shapePosY > -192 && shapePosX < 192 && shapePosY < 192); + float l = -MathHelper.sqrt_float(shapePosX * shapePosX + shapePosY * shapePosY); + shapeRotate = (float)Math.atan2(shapePosY / l, shapePosX / l) / 0.0174532f; + shapeRotate += (rand.nextFloat() - 0.5f) * 90.0f; + shapePosX += renderViewX * playerCoordsNoiseMapScale + cloud3DSamplesTextureSizeX * 0.5f; + shapePosY += renderViewZ * playerCoordsNoiseMapScale + cloud3DSamplesTextureSizeY * 0.5f; + shapePosZ = (int)((cloud3DSamplesTextureSizeZ - shapeSizeZ) * (rand.nextFloat() * 0.5f + 0.25f)); + isDrawingCloudShapes = true; + }else { + float dx = MathHelper.cos(-shapeRotate * 0.0174532f); + float dy = MathHelper.sin(-shapeRotate * 0.0174532f); + shapePosX += (int)(dx * 10.0f * dt); + shapePosY -= (int)(dy * 10.0f * dt); + if(MathHelper.abs(shapePosX - renderViewX * playerCoordsNoiseMapScale - cloud3DSamplesTextureSizeX * 0.5f) > 300.0f || + MathHelper.abs(shapePosY - renderViewZ * playerCoordsNoiseMapScale - cloud3DSamplesTextureSizeY * 0.5f) > 300.0f) { + nextShapeAppearance = millis + 300000l + rand.nextInt(1500000); + isDrawingCloudShapes = false; + } + } + }else { + isDrawingCloudShapes = false; + } + } + + static boolean checkFrustum(Matrix3f mat) { + Vector3f tmp = tmpVector1; + tmp.x = -1.0f; + tmp.y = -1.0f; + tmp.z = 1.0f; + Matrix3f.transform(mat, tmp, tmp); + if(tmp.x >= -1.0f && tmp.x <= 1.0f && tmp.y >= -1.0f && tmp.y <= 1.0f) { + return true; + } + tmp.x = 1.0f; + tmp.y = -1.0f; + Matrix3f.transform(mat, tmp, tmp); + if(tmp.x >= -1.0f && tmp.x <= 1.0f && tmp.y >= -1.0f && tmp.y <= 1.0f) { + return true; + } + tmp.x = 1.0f; + tmp.y = 1.0f; + Matrix3f.transform(mat, tmp, tmp); + if(tmp.x >= -1.0f && tmp.x <= 1.0f && tmp.y >= -1.0f && tmp.y <= 1.0f) { + return true; + } + tmp.x = -1.0f; + tmp.y = 1.0f; + Matrix3f.transform(mat, tmp, tmp); + if(tmp.x >= -1.0f && tmp.x <= 1.0f && tmp.y >= -1.0f && tmp.y <= 1.0f) { + return true; + } + return false; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DebugFramebufferView.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DebugFramebufferView.java new file mode 100644 index 0000000..0633c45 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DebugFramebufferView.java @@ -0,0 +1,528 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderGBufferDebugView; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class DebugFramebufferView { + + public static boolean debugViewShown = false; + private static long debugViewNameTimer = 0l; + private static int currentDebugView = 0; + + public static final List views = Arrays.asList( + (new DebugFramebufferView("GBuffer: Diffuse Color", (pipeline) -> { + pipeline.useDebugViewShader(0); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferDiffuseTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("GBuffer: Normal Vectors", (pipeline) -> { + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(1); + EaglerDeferredPipeline.uniformMatrixHelper(dbv.uniforms.u_inverseViewMatrix, DeferredStateManager.inverseViewMatrix); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferNormalsTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("GBuffer: Block/Sky Light Values", (pipeline) -> { + pipeline.useDebugViewShader(2); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(pipeline.gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferDiffuseTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("GBuffer: Material Params (1)", (pipeline) -> { + pipeline.useDebugViewShader(0); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferMaterialTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("GBuffer: Material Params (2)", (pipeline) -> { + pipeline.useDebugViewShader(3); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferMaterialTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("GBuffer: Depth Buffer", (pipeline) -> { + float depthStart = 0.001f; + float depthScale = 25.0f; + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(4); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, depthStart, depthScale); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.gBufferDepthTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Sun Shadow Depth: LOD 1", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 1) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(5); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, 1.0f / pipeline.config.is_rendering_shadowsSun_clamped, 0.0f); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, GL_NONE); + DrawUtils.drawStandardQuad2D(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + })), + (new DebugFramebufferView("Sun Shadow Color: LOD 1", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 1 || !pipeline.config.is_rendering_shadowsColored) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(10); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, 1.0f / pipeline.config.is_rendering_shadowsSun_clamped, 0.0f); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(pipeline.sunShadowColorBuffer); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, GL_NONE); + DrawUtils.drawStandardQuad2D(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + })), + (new DebugFramebufferView("Sun Shadow Depth: LOD 2", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 2) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(5); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, 1.0f / pipeline.config.is_rendering_shadowsSun_clamped, 1.0f); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, GL_NONE); + DrawUtils.drawStandardQuad2D(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + })), + (new DebugFramebufferView("Sun Shadow Color: LOD 2", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 2 || !pipeline.config.is_rendering_shadowsColored) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(10); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, 1.0f / pipeline.config.is_rendering_shadowsSun_clamped, 1.0f); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(pipeline.sunShadowColorBuffer); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, GL_NONE); + DrawUtils.drawStandardQuad2D(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + })), + (new DebugFramebufferView("Sun Shadow Depth: LOD 3", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 3) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(5); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, 1.0f / pipeline.config.is_rendering_shadowsSun_clamped, 2.0f); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, GL_NONE); + DrawUtils.drawStandardQuad2D(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + })), + (new DebugFramebufferView("GBuffer Shadow Values", (pipeline) -> { + if(pipeline.config.is_rendering_shadowsSun_clamped < 1) throw new NoDataException(); + if(pipeline.config.is_rendering_shadowsColored) { + pipeline.useDebugViewShader(0); + }else { + pipeline.useDebugViewShader(6); + } + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunLightingShadowTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Light Shafts Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_lightShafts) throw new NoDataException(); + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lightShaftsTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Forward Render Mask", (pipeline) -> { + pipeline.useDebugViewShader(7); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lightingHDRFramebufferColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Final HDR Color Buffer", (pipeline) -> { + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lightingHDRFramebufferColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Final Depth Buffer", (pipeline) -> { + float depthStart = 0.001f; + float depthScale = 25.0f; + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(4); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, depthStart, depthScale); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lightingHDRFramebufferDepthTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Last Frame Color Buffer", (pipeline) -> { + if(!pipeline.reprojectionEngineEnable && !pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lastFrameColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Last Frame Depth Buffer", (pipeline) -> { + if(!pipeline.reprojectionEngineEnable && !pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + float depthStart = 0.001f; + float depthScale = 25.0f; + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(4); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, depthStart, depthScale); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lastFrameDepthTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSAO: Raw GBuffer Samples", (pipeline) -> { + if(!pipeline.config.is_rendering_ssao) throw new NoDataException(); + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.ssaoGenerateTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSAO: Reprojected Samples", (pipeline) -> { + if(!pipeline.config.is_rendering_ssao) throw new NoDataException(); + pipeline.useDebugViewShader(9); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionControlSSAOTexture[pipeline.reprojectionPhase]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSAO: History Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_ssao) throw new NoDataException(); + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionControlSSAOTexture[pipeline.reprojectionPhase]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSR: Reflection Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_raytracing) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionSSRTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSR: Reflection Traces", (pipeline) -> { + if(!pipeline.config.is_rendering_raytracing) throw new NoDataException(); + pipeline.useDebugViewShader(11); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionSSRTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSR: Reflection Hit Vectors", (pipeline) -> { + if(!pipeline.config.is_rendering_raytracing) throw new NoDataException(); + pipeline.useDebugViewShader(12); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionSSRHitVector[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSR: Reflection Hit Mask", (pipeline) -> { + if(!pipeline.config.is_rendering_raytracing) throw new NoDataException(); + pipeline.useDebugViewShader(13); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionSSRHitVector[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("SSR: History Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_raytracing) throw new NoDataException(); + pipeline.useDebugViewShader(11); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.reprojectionSSRHitVector[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Clouds 3D Noise Map", (pipeline) -> { + PipelineShaderGBufferDebugView dbg = pipeline.useDebugViewShader(18); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture3D(CloudRenderWorker.cloud3DSamplesTexture); + _wglUniform1f(_wglGetUniformLocation(dbg.program, "u_fuckU1f"), (float)((System.currentTimeMillis() % 5000l) / 5000.0)); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Clouds Back Buffer", (pipeline) -> { + pipeline.useDebugViewShader(0); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(CloudRenderWorker.cloudNoiseSampleParaboloidTexture[CloudRenderWorker.cloudRenderPhase]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Clouds Front Buffer", (pipeline) -> { + pipeline.useDebugViewShader(0); + GlStateManager.setActiveTexture(GL_TEXTURE0); + CloudRenderWorker.bindParaboloid(); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Cached Atmosphere Colors", (pipeline) -> { + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.atmosphereHDRFramebufferColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Dual Paraboloid Map: Atmosphere", (pipeline) -> { + pipeline.useDebugViewShader(14); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.envMapAtmosphereTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Dual Paraboloid Map: Skybox", (pipeline) -> { + pipeline.useDebugViewShader(14); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.envMapSkyTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Dual Paraboloid Map: Terrain", (pipeline) -> { + if(!pipeline.config.is_rendering_useEnvMap) throw new NoDataException(); + pipeline.useDebugViewShader(14); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.envMapColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Dual Paraboloid Map: Mask", (pipeline) -> { + if(!pipeline.config.is_rendering_useEnvMap) throw new NoDataException(); + pipeline.useDebugViewShader(15); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.envMapColorTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Skybox Irradiance Map", (pipeline) -> { + pipeline.useDebugViewShader(14); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.skyIrradianceTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Atmosphere Irradiance Map", (pipeline) -> { + pipeline.useDebugViewShader(14); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.atmosphereIrradianceTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: Surface Normals", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(1); + EaglerDeferredPipeline.uniformMatrixHelper(dbv.uniforms.u_inverseViewMatrix, DeferredStateManager.inverseViewMatrix); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterMaskTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: Surface Depth", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + float depthStart = 0.001f; + float depthScale = 25.0f; + PipelineShaderGBufferDebugView dbv = pipeline.useDebugViewShader(4); + _wglUniform2f(dbv.uniforms.u_depthSliceStartEnd2f, depthStart, depthScale); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterDepthBuffer); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: Distortion Map", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(16); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterNormalMapTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: Refraction Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterRefractionTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: SSR Reflect Buffer", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterControlReflectionTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: SSR Reflect Traces", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(11); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterControlReflectionTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: SSR Reflect Hit Vectors", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(12); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterControlHitVectorTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: SSR Reflect Hit Mask", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(13); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterControlHitVectorTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Water: SSR Reflect History", (pipeline) -> { + if(!pipeline.config.is_rendering_realisticWater) throw new NoDataException(); + pipeline.useDebugViewShader(11); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.realisticWaterControlHitVectorTexture[1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Exposure Average -2", (pipeline) -> { + pipeline.useDebugViewShader(17); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lumaAvgDownscaleTexture[pipeline.lumaAvgDownscaleFramebuffers.length - 2]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Exposure Average -1", (pipeline) -> { + pipeline.useDebugViewShader(17); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.lumaAvgDownscaleTexture[pipeline.lumaAvgDownscaleFramebuffers.length - 1]); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Dynamic Exposure Value", (pipeline) -> { + pipeline.useDebugViewShader(17); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.exposureBlendTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Bloom Bright Pass", (pipeline) -> { + if(!pipeline.config.is_rendering_bloom) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.bloomBrightPassTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Bloom Horz. Blur", (pipeline) -> { + if(!pipeline.config.is_rendering_bloom) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.bloomHBlurTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Bloom Vert. Blur", (pipeline) -> { + if(!pipeline.config.is_rendering_bloom) throw new NoDataException(); + pipeline.useDebugViewShader(8); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.bloomVBlurTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Sun Occlusion: World", (pipeline) -> { + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(CloudRenderWorker.cloudOcclusionTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("Sun Occlusion: Screen", (pipeline) -> { + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.sunOcclusionValueTexture); + DrawUtils.drawStandardQuad2D(); + })), + (new DebugFramebufferView("FXAA Luma Values", (pipeline) -> { + if(!pipeline.config.is_rendering_fxaa) throw new NoDataException(); + pipeline.useDebugViewShader(6); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(pipeline.tonemapOutputTexture); + DrawUtils.drawStandardQuad2D(); + })) + ); + + private static class NoDataException extends RuntimeException { + } + + public static void renderDebugView() { + Minecraft mc = Minecraft.getMinecraft(); + boolean noData = false; + DebugFramebufferView view = views.get(currentDebugView); + try { + view.renderHandler.accept(EaglerDeferredPipeline.instance); + }catch(NoDataException ex) { + GlStateManager.clearColor(0.0f, 0.0f, 0.1f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + noData = true; + } + long millis = System.currentTimeMillis(); + long elapsed = millis - debugViewNameTimer; + if(elapsed < 2000l || noData) { + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.pushMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.pushMatrix(); + ScaledResolution scaledresolution = new ScaledResolution(mc); + int w = scaledresolution.getScaledWidth(); + mc.entityRenderer.setupOverlayRendering(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + int h = scaledresolution.getScaledHeight() / 2; + + if(noData) { + String noDataTxt = "No Data"; + mc.entityRenderer.setupOverlayRendering(); + int viewNameWidth = mc.fontRendererObj.getStringWidth(noDataTxt) * 2; + GlStateManager.pushMatrix(); + GlStateManager.translate((w - viewNameWidth) * 0.5f, h - 70.0f, 0.0f); + GlStateManager.scale(2.0f, 2.0f, 2.0f); + mc.fontRendererObj.drawStringWithShadow(noDataTxt, 0, 0, 0xFFFFFFFF); + GlStateManager.popMatrix(); + } + + if(elapsed < 2000l) { + for(int i = 0; i < 9; ++i) { + int i2 = currentDebugView - 4 + i; + if(i2 >= 0 && i2 < views.size()) { + String str = views.get(i2).name; + int j = mc.fontRendererObj.getStringWidth(str); + float alphaF = ((i == 0 || i == 8) ? 0.25f : ((i == 1 || i == 7) ? 0.65f : 1.0f)); + int x = 5; + if(elapsed > 1800l) { + x -= (int)(elapsed - 1800l); + alphaF *= (1.0f - (float)(elapsed - 1800l) / 190.0f); + } + int y = h + (i - 5) * 11; + Gui.drawRect(x, y, x + j + 2, y + 10, (int)(alphaF * 127.0f) << 24); + mc.fontRendererObj.drawStringWithShadow(str, x + 1, y + 1, (i == 4 ? 0xFFFF00 : 0xFFFFFF) | ((int)(alphaF * 255.0f) << 24)); + } + } + + mc.fontRendererObj.drawStringWithShadow("Use arrow keys to select framebuffers", 5, 23, 0xFFFFFF); + mc.fontRendererObj.drawStringWithShadow("Press F+4 to exit", 5, 33, 0xFFFFFF); + } + + GlStateManager.disableBlend(); + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.popMatrix(); + } + } + + public static void toggleDebugView() { + debugViewShown = !debugViewShown; + if(debugViewShown) { + debugViewNameTimer = System.currentTimeMillis(); + } + } + + public static void switchView(int dir) { + if(!debugViewShown) return; + debugViewNameTimer = System.currentTimeMillis(); + currentDebugView += dir; + if(currentDebugView < 0) currentDebugView = views.size() - 1; + if(currentDebugView >= views.size()) currentDebugView = 0; + } + + protected final String name; + protected final Consumer renderHandler; + + protected DebugFramebufferView(String name, Consumer renderHandler) { + this.name = name; + this.renderHandler = renderHandler; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DeferredStateManager.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DeferredStateManager.java new file mode 100644 index 0000000..5905b33 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DeferredStateManager.java @@ -0,0 +1,496 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class DeferredStateManager { + + public static float sunAngle = 45.0f; // realistic: 23.5f + + static boolean enableMaterialMapTexture = false; + static boolean enableForwardRender = false; + static boolean enableParaboloidRender = false; + static boolean enableShadowRender = false; + static boolean enableClipPlane = false; + static boolean enableDrawWavingBlocks = false; + static boolean enableDrawRealisticWaterMask = false; + static boolean enableDrawRealisticWaterRender = false; + static boolean enableDrawGlassHighlightsRender = false; + + static int materialConstantsSerial = 0; + static float materialConstantsRoughness = 0.5f; + static float materialConstantsMetalness = 0.02f; + static float materialConstantsEmission = 0.0f; + static boolean materialConstantsUseEnvMap = false; + + static int wavingBlockOffsetSerial = 0; + static float wavingBlockOffsetX = 0.0f; + static float wavingBlockOffsetY = 0.0f; + static float wavingBlockOffsetZ = 0.0f; + + static int wavingBlockParamSerial = 0; + static float wavingBlockParamX = 0.0f; + static float wavingBlockParamY = 0.0f; + static float wavingBlockParamZ = 0.0f; + static float wavingBlockParamW = 0.0f; + + static int constantBlock = 0; + + static float clipPlaneY = 0.0f; + + static AxisAlignedBB shadowMapBounds = new AxisAlignedBB(-1, -1, -1, 1, 1, 1); + + static float gbufferNearPlane = 0.01f; + static float gbufferFarPlane = 128.0f; + + static final Vector3f currentSunAngle = new Vector3f(); + static final Vector3f currentSunLightAngle = new Vector3f(); + static final Vector3f currentSunLightColor = new Vector3f(); + + static int waterWindOffsetSerial = 0; + static final Vector4f u_waterWindOffset4f = new Vector4f(); + + private static final float[] matrixCopyBuffer = new float[16]; + static int viewMatrixSerial = -1; + static int projMatrixSerial = -1; + static int passViewMatrixSerial = -1; + static int passProjMatrixSerial = -1; + static boolean isShadowPassMatrixLoaded = false; + static final Matrix4f viewMatrix = new Matrix4f(); + static final Matrix4f projMatrix = new Matrix4f(); + static final Matrix4f inverseViewMatrix = new Matrix4f(); + static final Matrix4f inverseProjMatrix = new Matrix4f(); + static final Matrix4f passViewMatrix = new Matrix4f(); + static final Matrix4f passProjMatrix = new Matrix4f(); + static final Matrix4f passInverseViewMatrix = new Matrix4f(); + static final Matrix4f passInverseProjMatrix = new Matrix4f(); + static final Matrix4f sunShadowMatrix0 = new Matrix4f(); + static final Matrix4f sunShadowMatrix1 = new Matrix4f(); + static final Matrix4f sunShadowMatrix2 = new Matrix4f(); + static final BetterFrustum currentGBufferFrustum = new BetterFrustum(); + static final Matrix4f paraboloidTopViewMatrix = new Matrix4f().rotate(-1.57f, new Vector3f(1.0f, 0.0f, 0.0f)); + static final Matrix4f paraboloidBottomViewMatrix = new Matrix4f().rotate(1.57f, new Vector3f(1.0f, 0.0f, 0.0f)); + + public static ForwardRenderCallbackHandler forwardCallbackHandler = null; + + public static final ForwardRenderCallbackHandler forwardCallbackGBuffer = new ForwardRenderCallbackHandler(); + public static final ForwardRenderCallbackHandler forwardCallbackSun = new ForwardRenderCallbackHandler(); + + public static boolean doCheckErrors = false; + + public static final boolean isDeferredRenderer() { + return EaglerDeferredPipeline.instance != null; + } + + public static final boolean isInDeferredPass() { + return GlStateManager.isExtensionPipeline(); + } + + public static final boolean isInForwardPass() { + return enableForwardRender && !enableShadowRender; + } + + public static final boolean isInParaboloidPass() { + return enableParaboloidRender; + } + + public static final boolean isRenderingRealisticWater() { + return EaglerDeferredPipeline.instance != null && EaglerDeferredPipeline.instance.config.is_rendering_realisticWater; + } + + public static final boolean isRenderingGlassHighlights() { + return EaglerDeferredPipeline.instance != null && EaglerDeferredPipeline.instance.config.is_rendering_useEnvMap; + } + + public static final void setDefaultMaterialConstants() { + materialConstantsRoughness = 0.5f; + materialConstantsMetalness = 0.02f; + materialConstantsEmission = 0.0f; + ++materialConstantsSerial; + } + + public static final void startUsingEnvMap() { + materialConstantsUseEnvMap = true; + } + + public static final void endUsingEnvMap() { + materialConstantsUseEnvMap = false; + } + + public static final void reportForwardRenderObjectPosition(int centerX, int centerY, int centerZ) { + EaglerDeferredPipeline instance = EaglerDeferredPipeline.instance; + if(instance != null && enableForwardRender) { + EaglerDeferredConfig cfg = instance.config; + if(!cfg.is_rendering_dynamicLights || !cfg.shaderPackInfo.DYNAMIC_LIGHTS) { + return; + } + instance.loadLightSourceBucket(centerX, centerY, centerZ); + } + } + + public static final void reportForwardRenderObjectPosition2(float x, float y, float z) { + float posX = (float)((x + TileEntityRendererDispatcher.staticPlayerX) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerX / 16.0) << 4)); + float posY = (float)((y + TileEntityRendererDispatcher.staticPlayerY) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerY / 16.0) << 4)); + float posZ = (float)((z + TileEntityRendererDispatcher.staticPlayerZ) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerZ / 16.0) << 4)); + reportForwardRenderObjectPosition((int)posX, (int)posY, (int)posZ); + } + + public static final void setHDRTranslucentPassBlendFunc() { + GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ZERO); + } + + public static final void enableMaterialTexture() { + enableMaterialMapTexture = true; + } + + public static final void disableMaterialTexture() { + enableMaterialMapTexture = false; + } + + public static final void enableForwardRender() { + enableForwardRender = true; + } + + public static final void disableForwardRender() { + enableForwardRender = false; + } + + public static final void enableParaboloidRender() { + enableParaboloidRender = true; + } + + public static final void disableParaboloidRender() { + enableParaboloidRender = false; + } + + public static final void enableShadowRender() { + enableShadowRender = true; + } + + public static final void disableShadowRender() { + enableShadowRender = false; + } + + public static final boolean isEnableShadowRender() { + return enableShadowRender; + } + + public static final void enableClipPlane() { + enableClipPlane = true; + } + + public static final void disableClipPlane() { + enableClipPlane = false; + } + + public static final void setClipPlaneY(float yValue) { + clipPlaneY = yValue; + } + + public static final void enableDrawWavingBlocks() { + enableDrawWavingBlocks = true; + } + + public static final void disableDrawWavingBlocks() { + enableDrawWavingBlocks = false; + } + + public static final boolean isEnableDrawWavingBlocks() { + return enableDrawWavingBlocks; + } + + public static final void enableDrawRealisticWaterMask() { + enableDrawRealisticWaterMask = true; + } + + public static final void disableDrawRealisticWaterMask() { + enableDrawRealisticWaterMask = false; + } + + public static final boolean isDrawRealisticWaterMask() { + return enableDrawRealisticWaterMask; + } + + public static final void enableDrawRealisticWaterRender() { + enableDrawRealisticWaterRender = true; + } + + public static final void disableDrawRealisticWaterRender() { + enableDrawRealisticWaterRender = false; + } + + public static final boolean isDrawRealisticWaterRender() { + return enableDrawRealisticWaterRender; + } + + public static final void enableDrawGlassHighlightsRender() { + enableDrawGlassHighlightsRender = true; + } + + public static final void disableDrawGlassHighlightsRender() { + enableDrawGlassHighlightsRender = false; + } + + public static final boolean isDrawGlassHighlightsRender() { + return enableDrawGlassHighlightsRender; + } + + public static final void setWavingBlockOffset(float x, float y, float z) { + wavingBlockOffsetX = x; + wavingBlockOffsetY = y; + wavingBlockOffsetZ = z; + ++wavingBlockOffsetSerial; + } + + public static final void setWavingBlockParams(float x, float y, float z, float w) { + wavingBlockParamX = x; + wavingBlockParamY = y; + wavingBlockParamZ = z; + wavingBlockParamW = w; + ++wavingBlockParamSerial; + } + + public static final void setRoughnessConstant(float roughness) { + materialConstantsRoughness = roughness; + ++materialConstantsSerial; + } + + public static final void setMetalnessConstant(float metalness) { + materialConstantsMetalness = metalness; + ++materialConstantsSerial; + } + + public static final void setEmissionConstant(float emission) { + materialConstantsEmission = emission; + ++materialConstantsSerial; + } + + public static final void setBlockConstant(int blockId) { + constantBlock = blockId; + } + + public static final AxisAlignedBB getShadowMapBounds() { + return shadowMapBounds; + } + + public static final void setShadowMapBounds(AxisAlignedBB newShadowMapBounds) { + shadowMapBounds = newShadowMapBounds; + } + + public static final void loadGBufferViewMatrix() { + loadPassViewMatrix(); + viewMatrix.load(passViewMatrix); + inverseViewMatrix.load(passInverseViewMatrix); + viewMatrixSerial = passViewMatrixSerial; + } + + public static void loadGBufferProjectionMatrix() { + loadPassProjectionMatrix(); + projMatrix.load(passProjMatrix); + inverseProjMatrix.load(passInverseProjMatrix); + projMatrixSerial = passProjMatrixSerial; + } + + public static final void loadPassViewMatrix() { + GlStateManager.getFloat(GL_MODELVIEW_MATRIX, matrixCopyBuffer); + passViewMatrix.load(matrixCopyBuffer); + Matrix4f.invert(passViewMatrix, passInverseViewMatrix); + ++passViewMatrixSerial; + isShadowPassMatrixLoaded = false; + } + + public static void loadPassProjectionMatrix() { + GlStateManager.getFloat(GL_PROJECTION_MATRIX, matrixCopyBuffer); + passProjMatrix.load(matrixCopyBuffer); + Matrix4f.invert(passProjMatrix, passInverseProjMatrix); + ++passProjMatrixSerial; + } + + public static final void loadShadowPassViewMatrix() { + GlStateManager.getFloat(GL_PROJECTION_MATRIX, matrixCopyBuffer); + passViewMatrix.load(matrixCopyBuffer); + Matrix4f.invert(passViewMatrix, passInverseViewMatrix); + passProjMatrix.setIdentity(); + ++passViewMatrixSerial; + isShadowPassMatrixLoaded = true; + } + + public static final void setPassMatrixToGBuffer() { + passViewMatrix.load(viewMatrix); + passInverseViewMatrix.load(inverseViewMatrix); + passProjMatrix.load(projMatrix); + passInverseProjMatrix.load(inverseProjMatrix); + ++passViewMatrixSerial; + ++passProjMatrixSerial; + } + + public static void setCurrentSunAngle(Vector3f vec) { + currentSunAngle.set(vec); + if(vec.y > 0.05f) { + currentSunLightAngle.x = -vec.x; + currentSunLightAngle.y = -vec.y; + currentSunLightAngle.z = -vec.z; + }else { + currentSunLightAngle.set(vec); + } + } + + public static void setCurrentSunAngle(Vector4f vec) { + currentSunAngle.set(vec); + if(vec.y > 0.05f) { + currentSunLightAngle.x = -vec.x; + currentSunLightAngle.y = -vec.y; + currentSunLightAngle.z = -vec.z; + }else { + currentSunLightAngle.set(vec); + } + } + + public static final void loadSunShadowMatrixLOD0() { + GlStateManager.getFloat(GL_PROJECTION_MATRIX, matrixCopyBuffer); + sunShadowMatrix0.load(matrixCopyBuffer); + } + + public static final void loadSunShadowMatrixLOD1() { + GlStateManager.getFloat(GL_PROJECTION_MATRIX, matrixCopyBuffer); + sunShadowMatrix1.load(matrixCopyBuffer); + } + + public static final void loadSunShadowMatrixLOD2() { + GlStateManager.getFloat(GL_PROJECTION_MATRIX, matrixCopyBuffer); + sunShadowMatrix2.load(matrixCopyBuffer); + } + + public static final Matrix4f getSunShadowMatrixLOD0() { + return sunShadowMatrix0; + } + + public static final Matrix4f getSunShadowMatrixLOD1() { + return sunShadowMatrix1; + } + + public static final Matrix4f getSunShadowMatrixLOD2() { + return sunShadowMatrix2; + } + + public static final void setGBufferNearFarPlanes(float zNear, float zFar) { + gbufferNearPlane = zNear; + gbufferFarPlane = zFar; + } + + public static final void setWaterWindOffset(float sx, float sy, float fx, float fy) { + ++waterWindOffsetSerial; + u_waterWindOffset4f.x = sx; + u_waterWindOffset4f.y = sy; + u_waterWindOffset4f.z = fx; + u_waterWindOffset4f.w = fy; + } + + static int fogLinearExp = 0; + + static float fogNear = 0.0f; + static float fogFar = 100.0f; + + static float fogDensity = 0.0f; + + static float fogColorLightR = 1.0f; + static float fogColorLightG = 1.0f; + static float fogColorLightB = 1.0f; + static float fogColorLightA = 1.0f; + + static float fogColorDarkR = 1.0f; + static float fogColorDarkG = 1.0f; + static float fogColorDarkB = 1.0f; + static float fogColorDarkA = 1.0f; + + public static final void enableFogLinear(float near, float far, boolean atmosphere, float colorLightR, + float colorLightG, float colorLightB, float colorLightA, float colorDarkR, float colorDarkG, + float colorDarkB, float colorDarkA) { + fogLinearExp = atmosphere ? 5 : 1; + fogNear = near; + fogFar = far; + fogColorLightR = colorLightR; + fogColorLightG = colorLightG; + fogColorLightB = colorLightB; + fogColorLightA = colorLightA; + fogColorDarkR = colorDarkR; + fogColorDarkG = colorDarkG; + fogColorDarkB = colorDarkB; + fogColorDarkA = colorDarkA; + } + + public static final void enableFogExp(float density, boolean atmosphere, float colorLightR, float colorLightG, + float colorLightB, float colorLightA, float colorDarkR, float colorDarkG, float colorDarkB, + float colorDarkA) { + fogLinearExp = atmosphere ? 6 : 2; + fogDensity = density; + fogColorLightR = colorLightR; + fogColorLightG = colorLightG; + fogColorLightB = colorLightB; + fogColorLightA = colorLightA; + fogColorDarkR = colorDarkR; + fogColorDarkG = colorDarkG; + fogColorDarkB = colorDarkB; + fogColorDarkA = colorDarkA; + } + + public static final void disableFog() { + fogLinearExp = 0; + } + + public static final void disableAll() { + enableMaterialMapTexture = false; + materialConstantsUseEnvMap = false; + enableForwardRender = false; + enableParaboloidRender = false; + enableShadowRender = false; + enableClipPlane = false; + enableDrawWavingBlocks = false; + fogLinearExp = 0; + fogNear = 0.0f; + fogFar = 100.0f; + forwardCallbackHandler = null; + } + + public static float getSunHeight() { + return -currentSunAngle.y; + } + + public static void checkGLError(String section) { + if(!doCheckErrors) { + return; + } + int i = EaglercraftGPU.glGetError(); + if(i != 0) { + EaglerDeferredPipeline.logger.error("########## GL ERROR ##########"); + EaglerDeferredPipeline.logger.error("@ {}", section); + do { + EaglerDeferredPipeline.logger.error("#{} - {}", i, EaglercraftGPU.gluErrorString(i)); + }while((i = EaglercraftGPU.glGetError()) != 0); + EaglerDeferredPipeline.logger.error("##############################"); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightInstance.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightInstance.java new file mode 100644 index 0000000..b2057e2 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightInstance.java @@ -0,0 +1,54 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +class DynamicLightInstance { + + public final String lightName; + public final boolean shadow; + long lastCacheHit = 0l; + + double posX; + double posY; + double posZ; + float red; + float green; + float blue; + float radius; + + public DynamicLightInstance(String lightName, boolean shadow) { + this.lightName = lightName; + this.shadow = shadow; + } + + public void updateLight(double posX, double posY, double posZ, float red, float green, float blue) { + this.lastCacheHit = System.currentTimeMillis(); + this.posX = posX; + this.posY = posY; + this.posZ = posZ; + this.red = red; + this.green = green; + this.blue = blue; + this.radius = (float)(Math.sqrt(red + green + blue) * 3.0 + 0.5); + } + + public void destroy() { + + } + + public float getRadiusInWorld() { + return radius; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightManager.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightManager.java new file mode 100644 index 0000000..8847817 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/DynamicLightManager.java @@ -0,0 +1,74 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class DynamicLightManager { + + static final Map lightRenderers = new HashMap(); + static final List lightRenderList = new LinkedList(); + static long renderTimeout = 5000l; + static boolean isRenderLightsPass = false; + + private static long lastTick = 0l; + + public static void renderDynamicLight(String lightName, double posX, double posY, double posZ, float red, + float green, float blue, boolean shadows) { + if(isRenderLightsPass) { + DynamicLightInstance dl = lightRenderers.get(lightName); + if(dl == null) { + lightRenderers.put(lightName, dl = new DynamicLightInstance(lightName, shadows)); + } + dl.updateLight(posX, posY, posZ, red, green, blue); + lightRenderList.add(dl); + } + } + + public static boolean isRenderingLights() { + return isRenderLightsPass; + } + + public static void setIsRenderingLights(boolean b) { + isRenderLightsPass = b; + } + + static void updateTimers() { + long millis = System.currentTimeMillis(); + if(millis - lastTick > 1000l) { + lastTick = millis; + Iterator itr = lightRenderers.values().iterator(); + while(itr.hasNext()) { + DynamicLightInstance dl = itr.next(); + if(millis - dl.lastCacheHit > renderTimeout) { + dl.destroy(); + itr.remove(); + } + } + } + } + + static void destroyAll() { + Iterator itr = lightRenderers.values().iterator(); + while(itr.hasNext()) { + itr.next().destroy(); + } + lightRenderers.clear(); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredConfig.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredConfig.java new file mode 100644 index 0000000..7d14b40 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredConfig.java @@ -0,0 +1,161 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; + +import org.json.JSONException; +import org.json.JSONObject; + +import net.lax1dude.eaglercraft.v1_8.EaglerInputStream; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class EaglerDeferredConfig { + + public static final ResourceLocation shaderPackInfoFile = new ResourceLocation("eagler:glsl/deferred/shader_pack_info.json"); + + public ShaderPackInfo shaderPackInfo = null; + + public boolean wavingBlocks = true; + public boolean dynamicLights = true; + public boolean ssao = true; + public int shadowsSun = 3; + public boolean shadowsColored = false; + public boolean shadowsSmoothed = true; + public boolean useEnvMap = true; + public boolean realisticWater = true; + public boolean lightShafts = false; + public boolean raytracing = true; + public boolean lensDistortion = false; + public boolean lensFlares = true; + public boolean bloom = false; + public boolean fxaa = true; + + public boolean is_rendering_wavingBlocks = true; + public boolean is_rendering_dynamicLights = true; + public boolean is_rendering_ssao = true; + public int is_rendering_shadowsSun = 3; + public int is_rendering_shadowsSun_clamped = 3; + public boolean is_rendering_shadowsColored = false; + public boolean is_rendering_shadowsSmoothed = true; + public boolean is_rendering_useEnvMap = true; + public boolean is_rendering_realisticWater = true; + public boolean is_rendering_lightShafts = false; + public boolean is_rendering_raytracing = true; + public boolean is_rendering_lensDistortion = false; + public boolean is_rendering_lensFlares = true; + public boolean is_rendering_bloom = false; + public boolean is_rendering_fxaa = true; + + public void readOption(String key, String value) { + switch(key) { + case "shaders_deferred_wavingBlocks": + wavingBlocks = value.equals("true"); + break; + case "shaders_deferred_dynamicLights": + dynamicLights = value.equals("true"); + break; + case "shaders_deferred_ssao": + ssao = value.equals("true"); + break; + case "shaders_deferred_shadowsSun": + shadowsSun = Integer.parseInt(value); + break; + case "shaders_deferred_shadowsColored": + shadowsColored = value.equals("true"); + break; + case "shaders_deferred_shadowsSmoothed": + shadowsSmoothed = value.equals("true"); + break; + case "shaders_deferred_useEnvMap": + useEnvMap = value.equals("true"); + break; + case "shaders_deferred_realisticWater": + realisticWater = value.equals("true"); + break; + case "shaders_deferred_lightShafts": + lightShafts = value.equals("true"); + break; + case "shaders_deferred_raytracing": + raytracing = value.equals("true"); + break; + case "shaders_deferred_lensDistortion": + lensDistortion = value.equals("true"); + break; + case "shaders_deferred_lensFlares": + lensFlares = value.equals("true"); + break; + case "shaders_deferred_bloom": + bloom = value.equals("true"); + break; + case "shaders_deferred_fxaa": + fxaa = value.equals("true"); + break; + default: + break; + } + } + + public void writeOptions(PrintWriter output) { + output.println("shaders_deferred_wavingBlocks:" + wavingBlocks); + output.println("shaders_deferred_dynamicLights:" + dynamicLights); + output.println("shaders_deferred_ssao:" + ssao); + output.println("shaders_deferred_shadowsSun:" + shadowsSun); + output.println("shaders_deferred_shadowsColored:" + shadowsColored); + output.println("shaders_deferred_shadowsSmoothed:" + shadowsSmoothed); + output.println("shaders_deferred_useEnvMap:" + useEnvMap); + output.println("shaders_deferred_realisticWater:" + realisticWater); + output.println("shaders_deferred_lightShafts:" + lightShafts); + output.println("shaders_deferred_raytracing:" + raytracing); + output.println("shaders_deferred_lensDistortion:" + lensDistortion); + output.println("shaders_deferred_lensFlares:" + lensFlares); + output.println("shaders_deferred_bloom:" + bloom); + output.println("shaders_deferred_fxaa:" + fxaa); + } + + public void reloadShaderPackInfo(IResourceManager mgr) throws IOException { + IResource res = mgr.getResource(shaderPackInfoFile); + try(InputStream is = res.getInputStream()) { + try { + JSONObject shaderInfoJSON = new JSONObject(new String(EaglerInputStream.inputStreamToBytes(is), StandardCharsets.UTF_8)); + shaderPackInfo = new ShaderPackInfo(shaderInfoJSON); + }catch(JSONException ex) { + throw new IOException("Invalid shader pack info json!", ex); + } + } + } + + public void updateConfig() { + is_rendering_wavingBlocks = wavingBlocks && shaderPackInfo.WAVING_BLOCKS; + is_rendering_dynamicLights = dynamicLights && shaderPackInfo.DYNAMIC_LIGHTS; + is_rendering_ssao = ssao && shaderPackInfo.GLOBAL_AMBIENT_OCCLUSION; + is_rendering_shadowsSun = is_rendering_shadowsSun_clamped = shaderPackInfo.SHADOWS_SUN ? shadowsSun : 0; + is_rendering_shadowsColored = shadowsColored && shaderPackInfo.SHADOWS_COLORED; + is_rendering_shadowsSmoothed = shadowsSmoothed && shaderPackInfo.SHADOWS_SMOOTHED; + is_rendering_useEnvMap = useEnvMap && shaderPackInfo.REFLECTIONS_PARABOLOID; + is_rendering_realisticWater = realisticWater && shaderPackInfo.REALISTIC_WATER; + is_rendering_lightShafts = is_rendering_shadowsSun_clamped > 0 && lightShafts && shaderPackInfo.LIGHT_SHAFTS; + is_rendering_raytracing = shaderPackInfo.SCREEN_SPACE_REFLECTIONS && raytracing; + is_rendering_lensDistortion = lensDistortion && shaderPackInfo.POST_LENS_DISTORION; + is_rendering_lensFlares = lensFlares && shaderPackInfo.POST_LENS_FLARES; + is_rendering_bloom = bloom && shaderPackInfo.POST_BLOOM; + is_rendering_fxaa = fxaa && shaderPackInfo.POST_FXAA; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java new file mode 100644 index 0000000..1345353 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java @@ -0,0 +1,4010 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EagUtils; +import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionPipeline; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.TextureCopyUtil; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderBloomBlurPass; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderBloomBrightPass; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderFXAA; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderGBufferCombine; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderGBufferDebugView; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderGBufferFog; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderHandDepthMask; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLensDistortion; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLensSunOcclusion; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLightShaftsSample; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLightingPoint; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLightingSun; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderMoonRender; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderPostExposureAvg; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderPostExposureFinal; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterControl; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterNoise; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderRealisticWaterNormalMap; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderReprojControl; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderReprojSSR; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSSAOGenerate; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderShadowsSun; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxAtmosphere; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxIrradiance; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxRender; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderSkyboxRenderEnd; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderTonemap; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.MetalsLUT; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.TemperaturesLUT; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class EaglerDeferredPipeline { + + public static final Logger logger = LogManager.getLogger("EaglerDeferredPipeline"); + + public static final byte[] ditherPattern = new byte[] { (byte) 12, (byte) 139, (byte) 44, (byte) 171, (byte) 4, + (byte) 131, (byte) 36, (byte) 163, (byte) 239, (byte) 112, (byte) 207, (byte) 80, (byte) 247, (byte) 120, + (byte) 215, (byte) 88, (byte) 48, (byte) 175, (byte) 16, (byte) 143, (byte) 56, (byte) 183, (byte) 24, + (byte) 151, (byte) 191, (byte) 64, (byte) 223, (byte) 96, (byte) 199, (byte) 72, (byte) 231, (byte) 104, + (byte) 0, (byte) 127, (byte) 32, (byte) 159, (byte) 8, (byte) 135, (byte) 40, (byte) 167, (byte) 251, + (byte) 124, (byte) 219, (byte) 92, (byte) 243, (byte) 116, (byte) 211, (byte) 84, (byte) 60, (byte) 187, + (byte) 28, (byte) 155, (byte) 52, (byte) 179, (byte) 20, (byte) 147, (byte) 203, (byte) 76, (byte) 235, + (byte) 108, (byte) 195, (byte) 68, (byte) 227, (byte) 100 }; + + public static EaglerDeferredPipeline instance = null; + public static boolean isSuspended = false; + + public EaglerDeferredConfig config = null; + public GBufferPipelineCompiler deferredExtPipeline = new GBufferPipelineCompiler(); + + public final Minecraft mc; + + public int currentWidth = -1; + public int currentHeight = -1; + + public double currentRenderX = 0.0; + public double currentRenderY = 0.0; + public double currentRenderZ = 0.0; + + public IFramebufferGL gBufferFramebuffer = null; + + public int gBufferDiffuseTexture = -1; + public int gBufferNormalsTexture = -1; + public int gBufferMaterialTexture = -1; + + public IFramebufferGL gBufferQuarterFramebuffer = null; + public int gBufferQuarterDepthTexture = -1; + + public int[] gBufferDrawBuffers = null; + + public int gBufferDepthTexture = -1; + + public IFramebufferGL lastFrameGBufferFramebuffer = null; + public int lastFrameGBufferDepthTexture = -1; + + public IFramebufferGL lastFrameFramebuffer = null; + public int lastFrameColorTexture = -1; + public int lastFrameDepthTexture = -1; + + public IFramebufferGL fogDepthCopyBuffer = null; + public int fogDepthCopyTexture = -1; + + public IFramebufferGL sunShadowFramebuffer = null; + public IFramebufferGL sunShadowColorFramebuffer = null; + + public int sunShadowDepthBuffer = -1; + public int sunShadowDepthBufferRes = -1; + public int sunShadowColorBuffer = -1; + + public IFramebufferGL sunLightingShadowFramebuffer = null; + public int sunLightingShadowTexture = -1; + + public IFramebufferGL ssaoGenerateFramebuffer = null; + public int ssaoGenerateTexture = -1; + + private int reprojectionStartup = 0; + + public int ssaoNoiseTexture = -1; + + public IFramebufferGL lightingHDRFramebuffer = null; + public int lightingHDRFramebufferColorTexture = -1; + public int lightingHDRFramebufferDepthTexture = -1; + + public IFramebufferGL handRenderFramebuffer = null; + public int handRenderFramebufferDepthTexture = -1; + + public IFramebufferGL[] reprojectionControlFramebuffer = new IFramebufferGL[] { null, null }; + public int[] reprojectionControlDrawBuffers = new int[0]; + public int[] reprojectionControlSSAOTexture = new int[] { -1, -1 }; + + public int reprojectionPhase = 0; + + public IFramebufferGL[] reprojectionSSRFramebuffer = new IFramebufferGL[] { null, null }; + public int[] reprojectionSSRTexture = new int[] { -1, -1 }; + public int[] reprojectionSSRHitVector = new int[] { -1, -1 }; + public boolean reprojectionEngineEnable = false; + + private static final int[] SSRColorAttachments = new int[] { _GL_COLOR_ATTACHMENT0, _GL_COLOR_ATTACHMENT1 }; + + public IFramebufferGL lightShaftsFramebuffer = null; + public int lightShaftsTexture = -1; + + public IFramebufferGL atmosphereHDRFramebuffer = null; + public int atmosphereHDRFramebufferColorTexture = -1; + + public IFramebufferGL envMapAtmosphereFramebuffer = null; + public int envMapAtmosphereTexture = -1; + + public IFramebufferGL envMapSkyFramebuffer = null; + public int envMapSkyTexture = -1; + public IFramebufferGL envMapFramebuffer = null; + public int envMapColorTexture = -1; + public int envMapDepthTexture = -1; + + public int moonTextures = -1; + + public int irradiancePhase = 0; + + public IFramebufferGL atmosphereIrradianceFramebuffer = null; + public int atmosphereIrradianceTexture = -1; + + public IFramebufferGL skyIrradianceFramebuffer = null; + public int skyIrradianceTexture = -1; + + public IFramebufferGL realisticWaterMaskFramebuffer = null; + public int realisticWaterMaskTexture = -1; + public int realisticWaterDepthBuffer = -1; + + public IFramebufferGL realisticWaterCombinedNormalsFramebuffer = null; + public int realisticWaterCombinedNormalsTexture = -1; + + public IFramebufferGL realisticWaterDisplacementMapFramebuffer = null; + public int realisticWaterDisplacementMapTexture = -1; + public int realisticWaterNoiseMap = -1; + + public IFramebufferGL realisticWaterNormalMapFramebuffer = null; + public int realisticWaterNormalMapTexture = -1; + + public IFramebufferGL realisticWaterControlFramebuffer = null; + public IFramebufferGL[] realisticWaterSSRFramebuffer = new IFramebufferGL[2]; + public int[] realisticWaterControlReflectionTexture = new int[] { -1, -1 }; + public int[] realisticWaterControlHitVectorTexture = new int[] { -1, -1 }; + public int realisticWaterRefractionTexture = -1; + + public IFramebufferGL[] lumaAvgDownscaleFramebuffers = null; + public int[] lumaAvgDownscaleTexture = null; + + public IFramebufferGL exposureBlendFramebuffer = null; + public int exposureBlendTexture = -1; + + public IFramebufferGL sunOcclusionValueFramebuffer = null; + public int sunOcclusionValueTexture = -1; + + public int dither8x8Texture = -1; + + public IFramebufferGL bloomBrightPassFramebuffer = null; + public int bloomBrightPassTextureW = -1; + public int bloomBrightPassTextureH = -1; + public int bloomBrightPassTexture = -1; + + public IFramebufferGL bloomDownscaleAFramebuffer = null; + public int bloomDownscaleATextureW = -1; + public int bloomDownscaleATextureH = -1; + public int bloomDownscaleATexture = -1; + + public IFramebufferGL bloomDownscaleBFramebuffer = null; + public int bloomDownscaleBTextureW = -1; + public int bloomDownscaleBTextureH = -1; + public int bloomDownscaleBTexture = -1; + + public IFramebufferGL bloomHBlurFramebuffer = null; + public int bloomBlurTextureW = -1; + public int bloomBlurTextureH = -1; + public int bloomHBlurTexture = -1; + + public IFramebufferGL bloomVBlurFramebuffer = null; + public int bloomVBlurTexture = -1; + + public IFramebufferGL lensDistortFramebuffer = null; + public int lensDistortTexture = -1; + + public IFramebufferGL tonemapOutputFramebuffer = null; + public int tonemapOutputTexture = -1; + + public PipelineShaderSSAOGenerate shader_ssao_generate = null; + private int reprojectionTexWidth = -1; + private int reprojectionTexHeight = -1; + public PipelineShaderGBufferCombine shader_deferred_combine = null; + public int brdfTexture = -1; + public PipelineShaderLightingSun shader_lighting_sun = null; + public PipelineShaderShadowsSun shader_shadows_sun = null; + public PipelineShaderLightShaftsSample shader_light_shafts_sample = null; + public PipelineShaderTonemap shader_post_tonemap = null; + public PipelineShaderLensDistortion shader_post_lens_distort = null; + public PipelineShaderPostExposureAvg shader_post_exposure_avg = null; + public PipelineShaderPostExposureAvg shader_post_exposure_avg_luma = null; + public PipelineShaderPostExposureFinal shader_post_exposure_final = null; + public PipelineShaderBloomBrightPass shader_post_bloom_bright = null; + public PipelineShaderBloomBlurPass shader_post_bloom_blur = null; + public PipelineShaderLensSunOcclusion shader_lens_sun_occlusion = null; + public PipelineShaderSkyboxAtmosphere shader_skybox_atmosphere = null; + public PipelineShaderSkyboxIrradiance[] shader_skybox_irradiance = new PipelineShaderSkyboxIrradiance[3]; + public PipelineShaderSkyboxRender shader_skybox_render = null; + public PipelineShaderSkyboxRender shader_skybox_render_paraboloid = null; + public PipelineShaderSkyboxRender shader_skybox_render_paraboloid_noclouds = null; + public PipelineShaderSkyboxRenderEnd shader_skybox_render_end = null; + public PipelineShaderGBufferFog shader_colored_fog_linear = null; + public PipelineShaderGBufferFog shader_colored_fog_exp = null; + public PipelineShaderGBufferFog shader_atmosphere_fog = null; + public PipelineShaderMoonRender shader_moon_render = null; + public PipelineShaderLightingPoint shader_lighting_point = null; + public PipelineShaderReprojControl shader_reproject_control = null; + public PipelineShaderReprojSSR shader_reproject_ssr = null; + public PipelineShaderRealisticWaterControl shader_realistic_water_control = null; + public PipelineShaderRealisticWaterNoise shader_realistic_water_noise = null; + public PipelineShaderRealisticWaterNormalMap shader_realistic_water_normals = null; + public PipelineShaderHandDepthMask shader_hand_depth_mask = null; + public PipelineShaderFXAA shader_post_fxaa = null; + public SkyboxRenderer skybox = null; + public LightSourceMesh pointLightMesh = null; + public final GBufferAcceleratedEffectRenderer gbufferEffectRenderer = new GBufferAcceleratedEffectRenderer(); + public final ForwardAcceleratedEffectRenderer forwardEffectRenderer = new ForwardAcceleratedEffectRenderer(); + + public final PipelineShaderGBufferDebugView[] shader_gbuffer_debug_view = new PipelineShaderGBufferDebugView[19]; + + public final EaglercraftRandom random = new EaglercraftRandom(); + + public static FloatBuffer matrixCopyBuffer = null; + + public IBufferGL buffer_worldLightingData; + private ByteBuffer worldLightingDataCopyBuffer; + + public IBufferGL buffer_chunkLightingData; + private ByteBuffer chunkLightingDataCopyBuffer; + private boolean isChunkLightingEnabled = false; + public ListSerial currentBoundLightSourceBucket; + + public static final Matrix4f tmpMatrixViewProj = new Matrix4f(); + public static final Matrix4f tmpMatrixViewReproject = new Matrix4f(); + public static final Matrix4f tmpMatrixViewProjReproject = new Matrix4f(); + public static final Matrix4f tmpMatrixLastFrameViewReproject = new Matrix4f(); + public static final Matrix4f tmpMatrixLastFrameProj = new Matrix4f(); + public static final Matrix4f tmpMatrixLastFrameViewProjReproject = new Matrix4f(); + public static final Matrix4f tmpMatrixInverseViewProj = new Matrix4f(); + public static final Matrix4f tmpMatrixInverseViewProjReproject = new Matrix4f(); + public static final Matrix4f tmpShadowLOD0MatrixTexSpace = new Matrix4f(); + public static final Matrix4f tmpShadowLOD1MatrixTexSpace = new Matrix4f(); + public static final Matrix4f tmpShadowLOD2MatrixTexSpace = new Matrix4f(); + public static final Vector3f vec3_05 = new Vector3f(0.5f, 0.5f, 0.5f); + public static final Vector3f vec3_2 = new Vector3f(2.0f, 2.0f, 2.0f); + public static final Vector3f vec3_n1 = new Vector3f(-1.0f, -1.0f, -1.0f); + public static final Matrix4f tmpClipToTexSpaceMatLeft = new Matrix4f().translate(vec3_05).scale(vec3_05); + public static final Matrix4f tmpTexToClipSpaceMatRight = new Matrix4f().translate(vec3_n1).scale(vec3_2); + public static final Matrix4f tmpMatrix1 = new Matrix4f(); + public static final Matrix4f tmpMatrix2 = new Matrix4f(); + public static final Matrix3f tmpMatrix3 = new Matrix3f(); + public static final Vector3f tmpVector1 = new Vector3f(); + public static final Vector4f tmpVector2 = new Vector4f(); + public static final Vector3f tmpVector3 = new Vector3f(); + public static final Vector3f tmpVector4 = new Vector3f(); + + public final ListSerial[] lightSourceBuckets; + public ListSerial currentLightSourceBucket; + + public static final int MAX_LIGHTS_PER_CHUNK = 12; + + private final int lightSourceBucketsWidth; + private final int lightSourceBucketsHeight; + + private double reprojectionOriginCoordinateX = 0.0; + private double reprojectionOriginCoordinateY = 0.0; + private double reprojectionOriginCoordinateZ = 0.0; + + private float reprojectionViewerOffsetX = 0.0f; + private float reprojectionViewerOffsetY = 0.0f; + private float reprojectionViewerOffsetZ = 0.0f; + + private double cloudRenderOriginCoordinateX = 0.0; + private double cloudRenderOriginCoordinateZ = 0.0; + + private float cloudRenderViewerOffsetX = 0.0f; + private float cloudRenderViewerOffsetZ = 0.0f; + + private long recalcAtmosphereTimer = 0l; + + private long lastExposureUpdate = 0l; + + private float partialTicks = 0.0f; + + public EaglerDeferredPipeline(Minecraft mc) { + this.mc = mc; + if(matrixCopyBuffer == null) { + matrixCopyBuffer = GLAllocation.createDirectFloatBuffer(16); + } + this.lightSourceBucketsWidth = 5; + this.lightSourceBucketsHeight = 3; + int cnt = 5 * 3 * 5; + this.lightSourceBuckets = new ListSerial[cnt]; + for(int i = 0; i < cnt; ++i) { + this.lightSourceBuckets[i] = new ArrayListSerial(16); + } + } + + public void rebuild(EaglerDeferredConfig config) { + destroy(); + DeferredStateManager.checkGLError("Pre: rebuild pipeline"); + this.config = config; + this.currentWidth = -1; + this.currentHeight = -1; + logger.info("Rebuilding pipeline..."); + + gBufferFramebuffer = _wglCreateFramebuffer(); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, gBufferFramebuffer); + + gBufferDiffuseTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(gBufferDiffuseTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(gBufferDiffuseTexture), 0); + gBufferNormalsTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(gBufferNormalsTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(gBufferNormalsTexture), 0); + gBufferMaterialTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(gBufferMaterialTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(gBufferMaterialTexture), 0); + gBufferDrawBuffers = new int[] { _GL_COLOR_ATTACHMENT0, _GL_COLOR_ATTACHMENT1, _GL_COLOR_ATTACHMENT2 }; + _wglDrawBuffers(gBufferDrawBuffers); + + gBufferDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(gBufferDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(gBufferDepthTexture), 0); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: gbuffers"); + + boolean shadowsSun = config.is_rendering_shadowsSun_clamped > 0; + if(shadowsSun) { + sunShadowFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowFramebuffer); + sunShadowDepthBuffer = GlStateManager.generateTexture(); + GlStateManager.bindTexture(sunShadowDepthBuffer); + setNearest(); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_FUNC, GL_GREATER); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + int lods = config.is_rendering_shadowsSun_clamped; + if(lods > 3) { + lods = 3; + } + sunShadowDepthBufferRes = 2048; + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT24, sunShadowDepthBufferRes, sunShadowDepthBufferRes * lods, 0, _GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (ByteBuffer)null); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(sunShadowDepthBuffer), 0); + sunLightingShadowFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunLightingShadowFramebuffer); + sunLightingShadowTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(sunLightingShadowTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(sunLightingShadowTexture), 0); + if(config.is_rendering_shadowsColored) { + sunShadowColorFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowColorFramebuffer); + GlStateManager.bindTexture(sunShadowDepthBuffer); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(sunShadowDepthBuffer), 0); + sunShadowColorBuffer = GlStateManager.generateTexture(); + GlStateManager.bindTexture(sunShadowColorBuffer); + setNearest(); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sunShadowDepthBufferRes, sunShadowDepthBufferRes * lods, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(sunShadowColorBuffer), 0); + } + + DeferredStateManager.checkGLError("Post: rebuild pipeline: shadowsSun"); + } + + reprojectionEngineEnable = config.is_rendering_ssao || config.is_rendering_raytracing; + if(reprojectionEngineEnable || config.is_rendering_realisticWater) { + lastFrameFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lastFrameFramebuffer); + lastFrameColorTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lastFrameColorTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lastFrameColorTexture), 0); + lastFrameDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lastFrameDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lastFrameDepthTexture), 0); + lastFrameGBufferFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lastFrameGBufferFramebuffer); + lastFrameGBufferDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lastFrameGBufferDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lastFrameGBufferDepthTexture), 0); + DeferredStateManager.checkGLError("Post: rebuild pipeline: lastFrame"); + } + + if(reprojectionEngineEnable) { + gBufferQuarterFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, gBufferQuarterFramebuffer); + gBufferQuarterDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(gBufferQuarterDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(gBufferQuarterDepthTexture), 0); + reprojectionStartup = 0; + for(int i = 0; i < 2; ++i) { + reprojectionControlFramebuffer[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionControlFramebuffer[i]); + if(config.is_rendering_ssao) { + reprojectionControlSSAOTexture[i] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(reprojectionControlSSAOTexture[i]); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(reprojectionControlSSAOTexture[i]), 0); + } + if(config.is_rendering_raytracing) { + reprojectionSSRTexture[i] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(reprojectionSSRTexture[0]); // yes this should be 0 + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, + config.is_rendering_ssao ? _GL_COLOR_ATTACHMENT1 : _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + EaglercraftGPU.getNativeTexture(reprojectionSSRTexture[0]), 0); + reprojectionSSRHitVector[i] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(reprojectionSSRHitVector[0]); // yes this should be 0 + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, + config.is_rendering_ssao ? _GL_COLOR_ATTACHMENT2 : _GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, + EaglercraftGPU.getNativeTexture(reprojectionSSRHitVector[0]), 0); + reprojectionSSRFramebuffer[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[i]); + _wglDrawBuffers(SSRColorAttachments); + GlStateManager.bindTexture(reprojectionSSRTexture[i]); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(reprojectionSSRTexture[i]), 0); + GlStateManager.bindTexture(reprojectionSSRHitVector[i]); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(reprojectionSSRHitVector[i]), 0); + } + } + shader_reproject_control = PipelineShaderReprojControl.compile(config.is_rendering_ssao, config.is_rendering_raytracing); + shader_reproject_control.loadUniforms(); + if(config.is_rendering_raytracing) { + shader_reproject_ssr = PipelineShaderReprojSSR.compile(); + shader_reproject_ssr.loadUniforms(); + } + reprojectionControlDrawBuffers = new int[(config.is_rendering_ssao ? 1 : 0) + (config.is_rendering_raytracing ? 2 : 0)]; + int i = 0; + if(config.is_rendering_ssao) { + reprojectionControlDrawBuffers[i] = _GL_COLOR_ATTACHMENT0; + ++i; + } + if(config.is_rendering_raytracing) { + reprojectionControlDrawBuffers[i] = _GL_COLOR_ATTACHMENT0 + i; + ++i; + reprojectionControlDrawBuffers[i] = _GL_COLOR_ATTACHMENT0 + i; + } + for(int j = 0; j < 2; ++j) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionControlFramebuffer[j]); + _wglDrawBuffers(reprojectionControlDrawBuffers); + } + DeferredStateManager.checkGLError("Post: rebuild pipeline: reprojectionEngineEnable"); + } + + if(config.is_rendering_ssao) { + ssaoGenerateFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, ssaoGenerateFramebuffer); + ssaoGenerateTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(ssaoGenerateTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(ssaoGenerateTexture), 0); + ssaoNoiseTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(ssaoNoiseTexture); + setNearest(); + int noiseTexSize = 64, noiseTexLen = 16384; + byte[] noiseTexDat = EagRuntime.getResourceBytes("assets/eagler/glsl/deferred/ssao_noise.bmp"); + if(noiseTexDat == null || noiseTexDat.length != noiseTexLen) { + noiseTexDat = new byte[noiseTexLen]; + for(int i = 0; i < 4096; ++i) { + noiseTexDat[(i << 2) + 2] = (byte)255; // dumb fallback + } + } + ByteBuffer noiseTextureBytes = EagRuntime.allocateByteBuffer(noiseTexLen); + noiseTextureBytes.put(noiseTexDat); + noiseTextureBytes.flip(); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, noiseTexSize, noiseTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, noiseTextureBytes); + EagRuntime.freeByteBuffer(noiseTextureBytes); + shader_ssao_generate = PipelineShaderSSAOGenerate.compile(); + shader_ssao_generate.loadUniforms(); + DeferredStateManager.checkGLError("Post: rebuild pipeline: SSAO"); + } + + lightingHDRFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + lightingHDRFramebufferColorTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lightingHDRFramebufferColorTexture), 0); + lightingHDRFramebufferDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lightingHDRFramebufferDepthTexture), 0); + + handRenderFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, handRenderFramebuffer); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lightingHDRFramebufferColorTexture), 0); + handRenderFramebufferDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(handRenderFramebufferDepthTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(handRenderFramebufferDepthTexture), 0); + + shader_hand_depth_mask = PipelineShaderHandDepthMask.compile(); + shader_hand_depth_mask.loadUniforms(); + shader_deferred_combine = PipelineShaderGBufferCombine.compile(config.is_rendering_ssao, config.is_rendering_useEnvMap, config.is_rendering_raytracing); + shader_deferred_combine.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: lightingHDRFramebuffer"); + + brdfTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(brdfTexture); + setLinear(); + int brdfLutW = 64, brdfLutH = 64, brdfLutLen = 8192; + byte[] brdfLutDat = EagRuntime.getResourceBytes("assets/eagler/glsl/deferred/brdf_lut.bmp"); + if(brdfLutDat == null || brdfLutDat.length != brdfLutLen) { + brdfLutDat = new byte[brdfLutLen]; + for(int i = 0; i < 4096; ++i) { + brdfLutDat[i << 1] = (byte)192; // dumb fallback + } + } + ByteBuffer brdfLutDatBuffer = EagRuntime.allocateByteBuffer(brdfLutDat.length); + brdfLutDatBuffer.put(brdfLutDat); + brdfLutDatBuffer.flip(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_RG8, brdfLutW, brdfLutH, 0, _GL_RG, GL_UNSIGNED_BYTE, brdfLutDatBuffer); + EagRuntime.freeByteBuffer(brdfLutDatBuffer); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: brdfLut"); + + dither8x8Texture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(dither8x8Texture); + setNearest(); + ByteBuffer dither8x8DatBuffer = EagRuntime.allocateByteBuffer(ditherPattern.length); + dither8x8DatBuffer.put(ditherPattern); + dither8x8DatBuffer.flip(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, dither8x8DatBuffer); + EagRuntime.freeByteBuffer(dither8x8DatBuffer); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: dither8x8Texture"); + + shader_lighting_sun = PipelineShaderLightingSun.compile(shadowsSun ? config.is_rendering_shadowsSun_clamped : 0, + config.is_rendering_shadowsColored); + shader_lighting_sun.loadUniforms(); + if(shadowsSun) { + shader_shadows_sun = PipelineShaderShadowsSun.compile(config.is_rendering_shadowsSun_clamped, + config.is_rendering_shadowsSmoothed, config.is_rendering_shadowsColored); + shader_shadows_sun.loadUniforms(); + } + shader_post_tonemap = PipelineShaderTonemap.compile(); + shader_post_tonemap.loadUniforms(); + shader_post_fxaa = PipelineShaderFXAA.compile(); + shader_post_fxaa.loadUniforms(); + shader_post_exposure_avg = PipelineShaderPostExposureAvg.compile(false); + shader_post_exposure_avg.loadUniforms(); + shader_post_exposure_avg_luma = PipelineShaderPostExposureAvg.compile(true); + shader_post_exposure_avg_luma.loadUniforms(); + shader_post_exposure_final = PipelineShaderPostExposureFinal.compile(); + shader_post_exposure_final.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: compile shaders 1"); + + if(config.is_rendering_lensFlares) { + sunOcclusionValueFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunOcclusionValueFramebuffer); + sunOcclusionValueTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(sunOcclusionValueTexture); + setNearest(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer)null); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(sunOcclusionValueTexture), 0); + shader_lens_sun_occlusion = PipelineShaderLensSunOcclusion.compile(); + shader_lens_sun_occlusion.loadUniforms(); + DeferredStateManager.checkGLError("Post: rebuild pipeline: sunOcclusionValueFramebuffer"); + } + + if(config.is_rendering_lensDistortion) { + lensDistortFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lensDistortFramebuffer); + lensDistortTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lensDistortTexture); + setLinear(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lensDistortTexture), 0); + shader_post_lens_distort = PipelineShaderLensDistortion.compile(); + shader_post_lens_distort.loadUniforms(); + DeferredStateManager.checkGLError("Post: rebuild pipeline: lens distortion"); + } + + lastExposureUpdate = 0l; + + exposureBlendFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, exposureBlendFramebuffer); + exposureBlendTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(exposureBlendTexture); + setNearest(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 1, 1, GL_RED, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(exposureBlendTexture), 0); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: exposureBlendFramebuffer"); + + skybox = new SkyboxRenderer(new ResourceLocation("eagler:glsl/deferred/skybox.dat")); + try { + skybox.load(); + } catch (IOException e) { + throw new RuntimeException("Failed to load skybox!", e); + } + + pointLightMesh = new LightSourceMesh(new ResourceLocation("eagler:glsl/deferred/light_point_mesh.dat"), "light_point_mesh"); + try { + pointLightMesh.load(); + } catch (IOException e) { + throw new RuntimeException("Failed to load point light mesh!", e); + } + + DeferredStateManager.checkGLError("Post: rebuild pipeline: meshes"); + + atmosphereHDRFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, atmosphereHDRFramebuffer); + atmosphereHDRFramebufferColorTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(atmosphereHDRFramebufferColorTexture); + setNearest(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, skybox.getAtmosLUTWidth(), skybox.getAtmosLUTHeight(), GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(atmosphereHDRFramebufferColorTexture), 0); + + envMapAtmosphereFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapAtmosphereFramebuffer); + envMapAtmosphereTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(envMapAtmosphereTexture); + setLinear(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 128, 256, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(envMapAtmosphereTexture), 0); + + envMapSkyFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapSkyFramebuffer); + envMapSkyTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(envMapSkyTexture); + setLinear(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 128, 256, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(envMapSkyTexture), 0); + + irradiancePhase = 0; + + atmosphereIrradianceFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, atmosphereIrradianceFramebuffer); + atmosphereIrradianceTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(atmosphereIrradianceTexture); + setLinear(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 32, 64, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(atmosphereIrradianceTexture), 0); + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + + skyIrradianceFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, skyIrradianceFramebuffer); + skyIrradianceTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(skyIrradianceTexture); + setLinear(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 32, 64, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(skyIrradianceTexture), 0); + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: atmosphere"); + + moonTextures = GlStateManager.generateTexture(); + GlStateManager.bindTexture(moonTextures); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ByteBuffer copyBuffer = EagRuntime.allocateByteBuffer(262144); + int mip = 0; + try(DataInputStream dis = new DataInputStream(EagRuntime.getResourceStream("/assets/eagler/glsl/deferred/eagler_moon.bmp"))) { + while(dis.read() == 'E') { + int w = dis.readShort(); + int h = dis.readShort(); + copyBuffer.clear(); + for(int i = 0, l = w * h * 4; i < l; ++i) { + copyBuffer.put((byte)dis.read()); + } + copyBuffer.flip(); + _wglTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, copyBuffer); + } + }catch(IOException ex) { + throw new RuntimeException("Could not load \"eagler_moon.bmp\"!", ex); + }finally { + EagRuntime.freeByteBuffer(copyBuffer); + } + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mip - 1); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: moon"); + + CloudRenderWorker.initialize(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: clouds"); + + fogDepthCopyBuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, fogDepthCopyBuffer); + fogDepthCopyTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(fogDepthCopyTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(fogDepthCopyTexture), 0); + + shader_atmosphere_fog = PipelineShaderGBufferFog.compile(false, true, config.is_rendering_lightShafts); + shader_atmosphere_fog.loadUniforms(); + shader_colored_fog_linear = PipelineShaderGBufferFog.compile(true, false, false); + shader_colored_fog_linear.loadUniforms(); + shader_colored_fog_exp = PipelineShaderGBufferFog.compile(false, false, false); + shader_colored_fog_exp.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: fog"); + + if(config.is_rendering_useEnvMap) { + envMapFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapFramebuffer); + envMapColorTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(envMapColorTexture); + setLinear(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 128, 256, GL_RGBA, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(envMapColorTexture), 0); + envMapDepthTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(envMapDepthTexture); + setNearest(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT24, 128, 256, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, (ByteBuffer)null); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(envMapDepthTexture), 0); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: env map"); + } + + if(config.is_rendering_realisticWater) { + realisticWaterMaskFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterMaskFramebuffer); + realisticWaterMaskTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterMaskTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterMaskTexture), 0); + realisticWaterDepthBuffer = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterDepthBuffer); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterDepthBuffer), 0); + realisticWaterCombinedNormalsFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterCombinedNormalsFramebuffer); + realisticWaterCombinedNormalsTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterCombinedNormalsTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterCombinedNormalsTexture), 0); + realisticWaterRefractionTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterRefractionTexture); + setNearest(); + realisticWaterControlFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterControlFramebuffer); + realisticWaterControlReflectionTexture[0] = GlStateManager.generateTexture(); + realisticWaterControlReflectionTexture[1] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterControlReflectionTexture[0]), 0); + realisticWaterControlHitVectorTexture[0] = GlStateManager.generateTexture(); + realisticWaterControlHitVectorTexture[1] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterControlHitVectorTexture[0]), 0); + GlStateManager.bindTexture(realisticWaterRefractionTexture); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterRefractionTexture), 0); + _wglDrawBuffers(new int[] { _GL_COLOR_ATTACHMENT0, _GL_COLOR_ATTACHMENT1, _GL_COLOR_ATTACHMENT2 }); + for(int i = 0; i < 2; ++i) { + realisticWaterSSRFramebuffer[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[i]); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[i]); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterControlReflectionTexture[i]), 0); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[i]); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterControlHitVectorTexture[i]), 0); + _wglDrawBuffers(new int[] { _GL_COLOR_ATTACHMENT0, _GL_COLOR_ATTACHMENT1 }); + } + realisticWaterDisplacementMapFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterDisplacementMapFramebuffer); + realisticWaterDisplacementMapTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterDisplacementMapTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterDisplacementMapTexture), 0); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 256, 256, GL_RED, true); + realisticWaterNormalMapFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterNormalMapFramebuffer); + realisticWaterNormalMapTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterNormalMapTexture); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(realisticWaterNormalMapTexture), 0); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_RG8, 256, 256, 0, _GL_RG, GL_UNSIGNED_BYTE, (ByteBuffer)null); + realisticWaterNoiseMap = GlStateManager.generateTexture(); + GlStateManager.bindTexture(realisticWaterNoiseMap); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + String realistic_water_noise_filename = "assets/eagler/glsl/deferred/realistic_water_noise.bmp"; + byte[] bitmapBytes = EagRuntime.getResourceBytes(realistic_water_noise_filename); + try { + if(bitmapBytes.length != 32768) { + throw new IOException("File is length " + bitmapBytes.length + ", expected " + 32768); + } + }catch(Throwable t) { + throw new RuntimeException("File \"" + realistic_water_noise_filename + "\" could not be loaded!", t); + } + ByteBuffer buf = EagRuntime.allocateByteBuffer(32768); + buf.put(bitmapBytes); + buf.flip(); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_RG8, 128, 128, 0, _GL_RG, GL_UNSIGNED_BYTE, buf); + EagRuntime.freeByteBuffer(buf); + shader_realistic_water_control = PipelineShaderRealisticWaterControl.compile(); + shader_realistic_water_control.loadUniforms(); + shader_realistic_water_noise = PipelineShaderRealisticWaterNoise.compile(); + shader_realistic_water_noise.loadUniforms(); + shader_realistic_water_normals = PipelineShaderRealisticWaterNormalMap.compile(); + shader_realistic_water_normals.loadUniforms(); + _wglUniform2f(shader_realistic_water_normals.uniforms.u_sampleOffset2f, 0.00390625f, 0.00390625f); + if(!config.is_rendering_raytracing) { + shader_reproject_ssr = PipelineShaderReprojSSR.compile(); + shader_reproject_ssr.loadUniforms(); + } + + DeferredStateManager.checkGLError("Post: rebuild pipeline: realistic water"); + } + + if(config.is_rendering_fxaa) { + tonemapOutputFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, tonemapOutputFramebuffer); + tonemapOutputTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(tonemapOutputTexture); + setNearest(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(tonemapOutputTexture), 0); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: fxaa"); + } + + if(config.is_rendering_lensFlares) { + LensFlareMeshRenderer.initialize(); + DeferredStateManager.checkGLError("Post: rebuild pipeline: lensFlares"); + } + + recalcAtmosphereTimer = 0l; + + shader_skybox_atmosphere = PipelineShaderSkyboxAtmosphere.compile(); + shader_skybox_atmosphere.loadUniforms(); + + shader_skybox_render = PipelineShaderSkyboxRender.compile(false, true); + shader_skybox_render.loadUniforms(); + + shader_skybox_render_paraboloid = PipelineShaderSkyboxRender.compile(true, true); + shader_skybox_render_paraboloid.loadUniforms(); + + shader_skybox_render_paraboloid_noclouds = PipelineShaderSkyboxRender.compile(true, false); + shader_skybox_render_paraboloid_noclouds.loadUniforms(); + + shader_skybox_irradiance[0] = PipelineShaderSkyboxIrradiance.compile(0); + shader_skybox_irradiance[0].loadUniforms(); + + shader_skybox_irradiance[1] = PipelineShaderSkyboxIrradiance.compile(1); + shader_skybox_irradiance[1].loadUniforms(); + + shader_skybox_irradiance[2] = PipelineShaderSkyboxIrradiance.compile(2); + shader_skybox_irradiance[2].loadUniforms(); + + shader_moon_render = PipelineShaderMoonRender.compile(); + shader_moon_render.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: skybox shaders"); + + if(config.is_rendering_lightShafts) { + lightShaftsFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightShaftsFramebuffer); + lightShaftsTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lightShaftsTexture); + setLinear(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(lightShaftsTexture), 0); + shader_light_shafts_sample = PipelineShaderLightShaftsSample.compile(config.is_rendering_shadowsSun_clamped); + shader_light_shafts_sample.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: light shafts"); + } + + if(config.is_rendering_bloom) { + bloomBrightPassFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomBrightPassFramebuffer); + bloomBrightPassTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(bloomBrightPassTexture); + setNearest(); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(bloomBrightPassTexture), 0); + bloomDownscaleAFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomDownscaleAFramebuffer); + bloomDownscaleATexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(bloomDownscaleATexture); + setLinear(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(bloomDownscaleATexture), 0); + bloomDownscaleBFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomDownscaleBFramebuffer); + bloomDownscaleBTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(bloomDownscaleBTexture); + setLinear(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(bloomDownscaleBTexture), 0); + bloomHBlurFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomHBlurFramebuffer); + bloomHBlurTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(bloomHBlurTexture); + setNearest(); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(bloomHBlurTexture), 0); + bloomVBlurFramebuffer = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomVBlurFramebuffer); + bloomVBlurTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(bloomVBlurTexture); + setLinear(); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(bloomVBlurTexture), 0); + shader_post_bloom_bright = PipelineShaderBloomBrightPass.compile(); + shader_post_bloom_bright.loadUniforms(); + shader_post_bloom_blur = PipelineShaderBloomBlurPass.compile(); + shader_post_bloom_blur.loadUniforms(); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: bloom"); + } + + gbufferEffectRenderer.initialize(); + forwardEffectRenderer.initialize(config.is_rendering_dynamicLights, config.is_rendering_shadowsSun_clamped); + + if(config.is_rendering_dynamicLights) { + shader_lighting_point = PipelineShaderLightingPoint.compile(false); + shader_lighting_point.loadUniforms(); + + buffer_chunkLightingData = _wglGenBuffers(); + EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData); + int lightingDataLength = 8 * MAX_LIGHTS_PER_CHUNK + 4; + chunkLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(lightingDataLength << 2); + for(int i = 0; i < lightingDataLength; ++i) { + chunkLightingDataCopyBuffer.putInt(0); + } + chunkLightingDataCopyBuffer.flip(); + _wglBufferData(_GL_UNIFORM_BUFFER, chunkLightingDataCopyBuffer, GL_DYNAMIC_DRAW); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: dynamic lights"); + } + + buffer_worldLightingData = _wglGenBuffers(); + EaglercraftGPU.bindGLUniformBuffer(buffer_worldLightingData); + worldLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(304); + for(int i = 0; i < 76; ++i) { + worldLightingDataCopyBuffer.putInt(0); + } + worldLightingDataCopyBuffer.flip(); + _wglBufferData(_GL_UNIFORM_BUFFER, worldLightingDataCopyBuffer, GL_DYNAMIC_DRAW); + + DeferredStateManager.checkGLError("Post: rebuild pipeline: world lighting data"); + + FixedFunctionPipeline.loadExtensionPipeline(deferredExtPipeline); + + if(!EaglercraftGPU.checkHDRFramebufferSupport(16)) { + logger.warn("16-bit HDR (floating point) framebuffers are not supported on this device, 32-bit framebuffers will be used instead which may slow the game down"); + } + + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + DeferredStateManager.checkGLError("Post: rebuild pipeline"); + } + + public void updateReprojectionCoordinates(double worldX, double worldY, double worldZ) { + double distX = worldX - reprojectionOriginCoordinateX; + double distY = worldY - reprojectionOriginCoordinateY; + double distZ = worldZ - reprojectionOriginCoordinateZ; + if(distX * distX + distY * distY + distZ * distZ > 48.0 * 48.0) { + reprojectionOriginCoordinateX = worldX; + reprojectionOriginCoordinateY = worldY; + reprojectionOriginCoordinateZ = worldZ; + reprojectionViewerOffsetX = 0.0f; + reprojectionViewerOffsetY = 0.0f; + reprojectionViewerOffsetZ = 0.0f; + reprojectionStartup = 0; + }else { + reprojectionViewerOffsetX = (float) distX; + reprojectionViewerOffsetY = (float) distY; + reprojectionViewerOffsetZ = (float) distZ; + } + distX = worldX - cloudRenderOriginCoordinateX; + distZ = worldZ - cloudRenderOriginCoordinateZ; + if(distX * distX + distZ * distZ > 256.0 * 256.0) { + cloudRenderOriginCoordinateX = worldX; + cloudRenderOriginCoordinateZ = worldZ; + cloudRenderViewerOffsetX = 0.0f; + cloudRenderViewerOffsetZ = 0.0f; + }else { + cloudRenderViewerOffsetX = (float) distX; + cloudRenderViewerOffsetZ = (float) distZ; + } + } + + public void setPartialTicks(float partialTicks_) { + partialTicks = partialTicks_; + } + + public float getPartialTicks() { + return partialTicks; + } + + public void resize(int w, int h) { + if(w == currentWidth && h == currentHeight) { + return; + } + + DeferredStateManager.checkGLError("Pre: resize pipeline to " + w + " x " + h); + + GlStateManager.bindTexture(gBufferDiffuseTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + GlStateManager.bindTexture(gBufferNormalsTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + GlStateManager.bindTexture(gBufferMaterialTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + + GlStateManager.bindTexture(gBufferDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + + DeferredStateManager.checkGLError("Post: resize pipeline: gbuffer"); + + if(config.is_rendering_shadowsSun_clamped > 0) { + GlStateManager.bindTexture(sunLightingShadowTexture); + if(config.is_rendering_shadowsColored) { + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + }else { + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer)null); + } + DeferredStateManager.checkGLError("Post: resize pipeline: sunLightingShadowTexture"); + } + + reprojectionStartup = 0; + reprojectionTexWidth = w >> 1; + reprojectionTexHeight = h >> 1; + + shader_deferred_combine.useProgram(); + _wglUniform2f(shader_deferred_combine.uniforms.u_halfResolutionPixelAlignment2f, (float)w / (reprojectionTexWidth << 1), (float)h / (reprojectionTexHeight << 1)); + + if(config.is_rendering_ssao) { + GlStateManager.bindTexture(ssaoGenerateTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, reprojectionTexWidth, reprojectionTexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer)null); + DeferredStateManager.checkGLError("Post: resize pipeline: ssao"); + } + + if(reprojectionEngineEnable || config.is_rendering_realisticWater) { + GlStateManager.bindTexture(lastFrameColorTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + GlStateManager.bindTexture(lastFrameDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, reprojectionTexWidth, reprojectionTexHeight, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + GlStateManager.bindTexture(lastFrameGBufferDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + DeferredStateManager.checkGLError("Post: resize pipeline: lastFrame"); + } + + if(config.is_rendering_raytracing || config.is_rendering_realisticWater) { + shader_reproject_ssr.useProgram(); + _wglUniform4f(shader_reproject_ssr.uniforms.u_pixelAlignment4f, reprojectionTexWidth, reprojectionTexHeight, w, h); + } + + if(reprojectionEngineEnable) { + GlStateManager.bindTexture(gBufferQuarterDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, reprojectionTexWidth, reprojectionTexHeight, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + + for(int i = 0; i < 2; ++i) { + if(config.is_rendering_ssao) { + GlStateManager.bindTexture(reprojectionControlSSAOTexture[i]); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, reprojectionTexWidth, reprojectionTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + } + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(reprojectionSSRTexture[i]); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + GlStateManager.bindTexture(reprojectionSSRHitVector[i]); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + } + } + + shader_reproject_control.useProgram(); + _wglUniform4f(shader_reproject_control.uniforms.u_pixelAlignment4f, reprojectionTexWidth, reprojectionTexHeight, w, h); + DeferredStateManager.checkGLError("Post: resize pipeline: reprojectionEngineEnable"); + } + + if(config.is_rendering_realisticWater) { + GlStateManager.bindTexture(realisticWaterMaskTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + GlStateManager.bindTexture(realisticWaterDepthBuffer); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + GlStateManager.bindTexture(realisticWaterCombinedNormalsTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + GlStateManager.bindTexture(realisticWaterRefractionTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + for(int i = 0; i < 2; ++i) { + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[i]); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[i]); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, reprojectionTexWidth, reprojectionTexHeight, GL_RGBA, true); + } + + shader_realistic_water_control.useProgram(); + _wglUniform4f(shader_realistic_water_control.uniforms.u_pixelAlignment4f, reprojectionTexWidth, reprojectionTexHeight, w, h); + DeferredStateManager.checkGLError("Post: resize pipeline: realisticWater"); + } + + if(config.is_rendering_lightShafts) { + GlStateManager.bindTexture(lightShaftsTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_R8, reprojectionTexWidth, reprojectionTexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, (ByteBuffer)null); + DeferredStateManager.checkGLError("Post: resize pipeline: lightShafts"); + } + + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, w, h, GL_RGBA, true); // USE RGBA! WebGL won't render to RGB16F + + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + + GlStateManager.bindTexture(handRenderFramebufferDepthTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + + DeferredStateManager.checkGLError("Post: resize pipeline: lightingHDRFramebuffer"); + + GlStateManager.bindTexture(fogDepthCopyTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, _GL_DEPTH_COMPONENT32F, w, h, 0, _GL_DEPTH_COMPONENT, GL_FLOAT, (ByteBuffer)null); + + DeferredStateManager.checkGLError("Post: resize pipeline: fogDepthCopyTexture"); + + if(config.is_rendering_lensDistortion) { + GlStateManager.bindTexture(lensDistortTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + DeferredStateManager.checkGLError("Post: resize pipeline: lensDistortion"); + } + + if(config.is_rendering_fxaa) { + GlStateManager.bindTexture(tonemapOutputTexture); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null); + DeferredStateManager.checkGLError("Post: resize pipeline: fxaa"); + } + + if(config.is_rendering_bloom) { + int bloomStageW = w; + int bloomStageH = h; + GlStateManager.bindTexture(bloomBrightPassTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, bloomStageW, bloomStageH, GL_RGBA, true); + bloomBrightPassTextureW = bloomStageW; + bloomBrightPassTextureH = bloomStageH; + bloomDownscaleATextureW = bloomDownscaleATextureH = 0; + bloomDownscaleBTextureW = bloomDownscaleBTextureH = 0; + if(bloomStageW > 150 && bloomStageH > 85) { + setLinear(); + bloomStageW >>= 1; + bloomStageH >>= 1; + if(bloomStageW > 150 && bloomStageH > 85) { + GlStateManager.bindTexture(bloomDownscaleATexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, bloomStageW, bloomStageH, GL_RGBA, true); + bloomDownscaleATextureW = bloomStageW; + bloomDownscaleATextureH = bloomStageH; + bloomStageW >>= 1; + bloomStageH >>= 1; + if(bloomStageW > 150 && bloomStageH > 85) { + GlStateManager.bindTexture(bloomDownscaleBTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, bloomStageW, bloomStageH, GL_RGBA, true); + bloomDownscaleBTextureW = bloomStageW; + bloomDownscaleBTextureH = bloomStageH; + bloomStageW >>= 1; + bloomStageH >>= 1; + } + } + }else { + setNearest(); + } + GlStateManager.bindTexture(bloomHBlurTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, bloomStageW, bloomStageH, GL_RGBA, true); + GlStateManager.bindTexture(bloomVBlurTexture); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, bloomStageW, bloomStageH, GL_RGBA, true); + bloomBlurTextureW = bloomStageW; + bloomBlurTextureH = bloomStageH; + DeferredStateManager.checkGLError("Post: resize pipeline: bloom"); + } + + if(lumaAvgDownscaleFramebuffers != null) { + for(int i = 0; i < lumaAvgDownscaleFramebuffers.length; ++i) { + _wglDeleteFramebuffer(lumaAvgDownscaleFramebuffers[i]); + } + } + + if(lumaAvgDownscaleTexture != null) { + for(int i = 0; i < lumaAvgDownscaleTexture.length; ++i) { + GlStateManager.deleteTexture(lumaAvgDownscaleTexture[i]); + } + } + + int j = 0; + int k = h > w ? w : h; + while(k > 8) { + ++j; + k >>= 2; + } + + lumaAvgDownscaleFramebuffers = new IFramebufferGL[j]; + lumaAvgDownscaleTexture = new int[j]; + + int kw = w; + int kh = h; + int kw2, kh2; + for(int i = 0; i < j; ++i) { + kw2 = kw >> 2; + kh2 = kh >> 2; + lumaAvgDownscaleFramebuffers[i] = _wglCreateFramebuffer(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lumaAvgDownscaleFramebuffers[i]); + lumaAvgDownscaleTexture[i] = GlStateManager.generateTexture(); + GlStateManager.bindTexture(lumaAvgDownscaleTexture[i]); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, i == j - 1 ? GL_NEAREST : GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, i == j - 1 ? GL_NEAREST : GL_LINEAR); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, ((kw & 3) != 0) ? (kw2 + 1) : kw2, + ((kh & 3) != 0) ? (kh2 + 1) : kh2, GL_RED, true); + _wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + EaglercraftGPU.getNativeTexture(lumaAvgDownscaleTexture[i]), 0); + kw = kw2; + kh = kh2; + } + + currentWidth = w; + currentHeight = h; + + DeferredStateManager.checkGLError("Post: resize pipeline: lumaAvg"); + } + + public void loadViewMatrix() { + DeferredStateManager.loadGBufferViewMatrix(); + DeferredStateManager.loadGBufferProjectionMatrix(); + } + + public void beginDrawDeferred() { + DeferredStateManager.checkGLError("Pre: beginDrawDeferred()"); + DynamicLightManager.lightRenderList.clear(); + } + + public void beginDrawMainGBuffer() { + DeferredStateManager.checkGLError("Pre: beginDrawMainGBuffer()"); + resize(mc.displayWidth, mc.displayHeight); + _wglBindFramebuffer(_GL_FRAMEBUFFER, gBufferFramebuffer); + _wglDrawBuffers(gBufferDrawBuffers); + _wglClearColor(0.0f, 0.0f, 0.0f, 0.0f); + _wglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.colorMask(true, true, true, true); + GlStateManager.enableExtensionPipeline(); + GlStateManager.globalDisableBlend(); + DeferredStateManager.checkGLError("Post: beginDrawMainGBuffer()"); + } + + public void beginDrawMainGBufferTerrain() { + DeferredStateManager.checkGLError("Pre: beginDrawMainGBufferTerrain()"); + TextureManager mgr = mc.getTextureManager(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.enableTexture2D(); + mgr.bindTexture(TextureMap.locationBlocksTexture); + DeferredStateManager.checkGLError("Post: beginDrawMainGBufferTerrain()"); + } + + public void beginDrawMainGBufferEntities() { + DeferredStateManager.checkGLError("Pre: beginDrawMainGBufferEntities()"); + } + + public void beginDrawMainGBufferDestroyProgress() { + DeferredStateManager.checkGLError("Pre: beginDrawMainGBufferDestroyProgress()"); + GlStateManager.disableExtensionPipeline(); + } + + public void endDrawMainGBufferDestroyProgress() { + DeferredStateManager.checkGLError("Pre: endDrawMainGBufferDestroyProgress()"); + GlStateManager.enableExtensionPipeline(); + } + + public void endDrawMainGBuffer() { + DeferredStateManager.checkGLError("Pre: endDrawMainGBuffer()"); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + DeferredStateManager.checkGLError("Post: endDrawMainGBuffer()"); + } + + public void beginDrawMainShadowMap() { + DeferredStateManager.checkGLError("Pre: beginDrawMainShadowMap()"); + if(config.is_rendering_shadowsColored) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowColorFramebuffer); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.clearDepth(1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowFramebuffer); + }else { + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowFramebuffer); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + GlStateManager.clearDepth(1.0f); + GlStateManager.clear(GL_DEPTH_BUFFER_BIT); + } + GlStateManager.enableCull(); + GlStateManager.cullFace(GL_FRONT); + DeferredStateManager.enableShadowRender(); + GlStateManager.colorMask(false, false, false, false); + DeferredStateManager.checkGLError("Post: beginDrawMainShadowMap()"); + } + + public void endDrawMainShadowMap() { + DeferredStateManager.checkGLError("Pre: endDrawMainShadowMap()"); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.cullFace(GL_BACK); + DeferredStateManager.disableShadowRender(); + GlStateManager.colorMask(true, true, true, true); + DeferredStateManager.checkGLError("Post: endDrawMainShadowMap()"); + } + + public void beginDrawMainShadowMapLOD(int lod) { + DeferredStateManager.checkGLError("Pre: beginDrawMainShadowMapLOD(" + lod + ")"); + GlStateManager.viewport(0, sunShadowDepthBufferRes * lod, sunShadowDepthBufferRes, sunShadowDepthBufferRes); + } + + public void beginDrawColoredShadows() { + DeferredStateManager.checkGLError("Pre: beginDrawColoredShadows()"); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowColorFramebuffer); + DeferredStateManager.enableForwardRender(); + GlStateManager.globalEnableBlend(); + GlStateManager.enableBlend(); + GlStateManager.depthMask(false); + GlStateManager.tryBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ZERO); + GlStateManager.enablePolygonOffset(); + GlStateManager.doPolygonOffset(0.25f, 1.0f); + GlStateManager.colorMask(true, true, true, true); + DeferredStateManager.checkGLError("Post: beginDrawColoredShadows()"); + } + + public void endDrawColoredShadows() { + DeferredStateManager.checkGLError("Pre: endDrawColoredShadows()"); + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunShadowFramebuffer); + DeferredStateManager.disableForwardRender(); + GlStateManager.disableBlend(); + GlStateManager.globalDisableBlend(); + GlStateManager.depthMask(true); + GlStateManager.disablePolygonOffset(); + GlStateManager.colorMask(false, false, false, false); + DeferredStateManager.checkGLError("Post: endDrawColoredShadows()"); + } + + private static final ResourceLocation locationEndSkyPng = new ResourceLocation("textures/environment/end_sky.png"); + + public void combineGBuffersAndIlluminate() { + DeferredStateManager.checkGLError("Pre: combineGBuffersAndIlluminate()"); + DynamicLightManager.updateTimers(); + + // ========================= CLEAR STATE ========================== // + + GlStateManager.disableExtensionPipeline(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.disableLighting(); + GlStateManager.globalEnableBlend(); + GlStateManager.disableBlend(); + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + GlStateManager.colorMask(true, true, true, true); + GlStateManager.matrixMode(GL_MODELVIEW); + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): CLEAR STATE"); + + // ==================== CACHE SOME MATRICIES ===================== // + + DeferredStateManager.passViewMatrix.load(DeferredStateManager.viewMatrix); + DeferredStateManager.passProjMatrix.load(DeferredStateManager.projMatrix); + DeferredStateManager.passInverseViewMatrix.load(DeferredStateManager.inverseViewMatrix); + DeferredStateManager.passInverseProjMatrix.load(DeferredStateManager.inverseProjMatrix); + Matrix4f.mul(DeferredStateManager.projMatrix, DeferredStateManager.viewMatrix, tmpMatrixViewProj); + DeferredStateManager.currentGBufferFrustum.set(tmpMatrixViewProj); + Matrix4f.invert(tmpMatrixViewProj, tmpMatrixInverseViewProj); + + Entity renderViewEntity = mc.getRenderViewEntity(); + if(renderViewEntity == null) { + renderViewEntity = mc.thePlayer; + } + + double entityPosX = renderViewEntity.prevPosX + (renderViewEntity.posX - renderViewEntity.prevPosX) * partialTicks; + double entityPosY = renderViewEntity.prevPosY + (renderViewEntity.posY - renderViewEntity.prevPosY) * partialTicks; + double entityPosZ = renderViewEntity.prevPosZ + (renderViewEntity.posZ - renderViewEntity.prevPosZ) * partialTicks; + int entityChunkOriginX = MathHelper.floor_double(entityPosX / 16.0) << 4; + int entityChunkOriginY = MathHelper.floor_double(entityPosY / 16.0) << 4; + int entityChunkOriginZ = MathHelper.floor_double(entityPosZ / 16.0) << 4; + + Vector3f currentSunAngle = DeferredStateManager.currentSunAngle; + float sunKelvin = 1500.0f + (2500.0f * Math.max(-currentSunAngle.y, 0.0f)); + float fff = mc.theWorld.getRainStrength(partialTicks); + float ff2 = mc.theWorld.getThunderStrength(partialTicks); + long millis = System.currentTimeMillis(); + int dim = Minecraft.getMinecraft().theWorld.provider.getDimensionId(); + + // ==================== UPDATE CLOUD RENDERER ===================== // + + if(dim == 0) { + CloudRenderWorker.setPosition(cloudRenderViewerOffsetX, (float)entityPosY, cloudRenderViewerOffsetZ); + CloudRenderWorker.update(); + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): UPDATE CLOUD RENDERER"); + } + + if(millis - recalcAtmosphereTimer > 100l) { + + if(dim == 0) { + + // =============== CALCULATE ATMOSPHERE COLORS ================ // + + recalcAtmosphereTimer = millis; + _wglBindFramebuffer(_GL_FRAMEBUFFER, atmosphereHDRFramebuffer); + shader_skybox_atmosphere.useProgram(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(skybox.getNormalsLUT()); + GlStateManager.viewport(0, 0, skybox.getAtmosLUTWidth(), skybox.getAtmosLUTHeight()); + _wglUniform4f(shader_skybox_atmosphere.uniforms.u_sunDirectionIntensity4f, -currentSunAngle.x, -currentSunAngle.y, -currentSunAngle.z, 5.0f); + _wglUniform1f(shader_skybox_atmosphere.uniforms.u_altitude1f, Math.max((float)(entityPosY - 85.0), -20.0f)); + Vector3f sunColorTmp = tmpVector3; + sunColorTmp.set(DeferredStateManager.currentSunLightColor); + float luma = sunColorTmp.x * 0.299f + sunColorTmp.y * 0.587f + sunColorTmp.z * 0.114f; + float sat = 0.3f; // desaturate + sunColorTmp.x = (sunColorTmp.x - luma) * sat + luma; + sunColorTmp.y = (sunColorTmp.y - luma) * sat + luma; + sunColorTmp.z = (sunColorTmp.z - luma) * sat + luma; + sunColorTmp.scale(0.3f - ff2 * 0.175f); + _wglUniform4f(shader_skybox_atmosphere.uniforms.u_blendColor4f, sunColorTmp.x * 0.05f, sunColorTmp.y * 0.05f, sunColorTmp.z * 0.05f, fff); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): CALCULATE ATMOSPHERE COLORS"); + + // =============== GENERATE SKY REFLECTION MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapSkyFramebuffer); + GlStateManager.viewport(0, 0, 128, 128); + GlStateManager.setActiveTexture(GL_TEXTURE1); + CloudRenderWorker.bindParaboloid(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(atmosphereHDRFramebufferColorTexture); + shader_skybox_render_paraboloid.useProgram(); + uniformMatrixHelper(shader_skybox_render_paraboloid.uniforms.u_viewMatrix4f, DeferredStateManager.paraboloidTopViewMatrix); + _wglUniform1f(shader_skybox_render_paraboloid.uniforms.u_farPlane1f, 2.0f); + if (mc.theWorld.getLastLightningBolt() > 0) { + float f = 0.3f + fff; + _wglUniform4f(shader_skybox_render_paraboloid.uniforms.u_lightningColor4f, 0.02f * f, 0.02f * f, 0.02f * f, 1.0f - f * 0.25f); + }else { + _wglUniform4f(shader_skybox_render_paraboloid.uniforms.u_lightningColor4f, 0.0f, 0.0f, 0.0f, 1.0f); + } + skybox.drawTop(); + + GlStateManager.viewport(0, 128, 128, 128); + uniformMatrixHelper(shader_skybox_render_paraboloid.uniforms.u_viewMatrix4f, DeferredStateManager.paraboloidBottomViewMatrix); + skybox.drawBottom(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): GENERATE SKY REFLECTION MAP"); + + + if(irradiancePhase++ % 10 == 0) { + + // =============== GENERATE ATMOSPHERE REFLECTION MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapAtmosphereFramebuffer); + GlStateManager.viewport(0, 0, 128, 128); + shader_skybox_render_paraboloid_noclouds.useProgram(); + uniformMatrixHelper(shader_skybox_render_paraboloid_noclouds.uniforms.u_viewMatrix4f, DeferredStateManager.paraboloidTopViewMatrix); + _wglUniform1f(shader_skybox_render_paraboloid_noclouds.uniforms.u_farPlane1f, 2.0f); + if (mc.theWorld.getLastLightningBolt() > 0) { + float f = 0.3f + fff; + _wglUniform4f(shader_skybox_render_paraboloid_noclouds.uniforms.u_lightningColor4f, 0.02f * f, 0.02f * f, 0.02f * f, 1.0f - f * 0.25f); + }else { + _wglUniform4f(shader_skybox_render_paraboloid_noclouds.uniforms.u_lightningColor4f, 0.0f, 0.0f, 0.0f, 1.0f); + } + skybox.drawTop(); + + GlStateManager.viewport(0, 128, 128, 128); + uniformMatrixHelper(shader_skybox_render_paraboloid_noclouds.uniforms.u_viewMatrix4f, DeferredStateManager.paraboloidBottomViewMatrix); + skybox.drawBottom(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): GENERATE ATMOSPHERE REFLECTION MAP"); + + // =============== GENERATE ATMOSPHERE IRRADIANCE MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, atmosphereIrradianceFramebuffer); + GlStateManager.bindTexture(envMapAtmosphereTexture); + GlStateManager.viewport(0, 0, 32, 64); + + shader_skybox_irradiance[0].useProgram(); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + + shader_skybox_irradiance[1].useProgram(); + DrawUtils.drawStandardQuad2D(); + + shader_skybox_irradiance[2].useProgram(); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.disableBlend(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): GENERATE ATMOSPHERE IRRADIANCE MAP"); + + }else { + + // =============== GENERATE SKY IRRADIANCE MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, skyIrradianceFramebuffer); + GlStateManager.bindTexture(envMapSkyTexture); + GlStateManager.viewport(0, 0, 32, 64); + + shader_skybox_irradiance[0].useProgram(); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + + shader_skybox_irradiance[1].useProgram(); + DrawUtils.drawStandardQuad2D(); + + shader_skybox_irradiance[2].useProgram(); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.disableBlend(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): GENERATE SKY IRRADIANCE MAP"); + } + }else if(dim == -1) { + + // =============== NETHER SKY REFLECTION MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapSkyFramebuffer); + GlStateManager.clearColor(0.55f, 0.25f, 0.05f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): NETHER SKY REFLECTION MAP"); + + // =============== NETHER SKY IRRADIANCE MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, skyIrradianceFramebuffer); + GlStateManager.clearColor(0.22f, 0.08f, 0.01f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): NETHER SKY IRRADIANCE MAP"); + + } + + } + + if(reprojectionEngineEnable) { + + // ============ DOWNSCALE DEPTH BUFFER, FOR PERFORMANCE =========== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, gBufferQuarterFramebuffer); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL_ALWAYS); + GlStateManager.depthMask(true); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferDepthTexture); + _wglDrawBuffers(GL_NONE); + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + TextureCopyUtil.alignPixelsTopLeft(reprojectionTexWidth << 1, reprojectionTexHeight << 1, reprojectionTexWidth, reprojectionTexHeight); + TextureCopyUtil.blitTextureDepth(); + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + GlStateManager.depthFunc(GL_LEQUAL); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): DOWNSCALE DEPTH BUFFER, FOR PERFORMANCE"); + + if(config.is_rendering_ssao) { + + // ====================== RUN SSAO ALGORITHM ====================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, ssaoGenerateFramebuffer); + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(ssaoNoiseTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferQuarterDepthTexture); + shader_ssao_generate.useProgram(); + uniformMatrixHelper(shader_ssao_generate.uniforms.u_projectionMatrix4f, DeferredStateManager.projMatrix); + uniformMatrixHelper(shader_ssao_generate.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + matrixCopyBuffer.clear(); + matrixCopyBuffer.put(((random.nextFloat() * 25.0f - 12.5f) + (random.nextBoolean() ? 1.0f : -1.0f) * (random.nextFloat() * 6.0f + 6.0f)) * 10.0f); + matrixCopyBuffer.put(((random.nextFloat() * 25.0f - 12.5f) + (random.nextBoolean() ? 1.0f : -1.0f) * (random.nextFloat() * 6.0f + 6.0f)) * 10.0f); + matrixCopyBuffer.put(((random.nextFloat() * 25.0f - 12.5f) + (random.nextBoolean() ? 1.0f : -1.0f) * (random.nextFloat() * 6.0f + 6.0f)) * 10.0f); + matrixCopyBuffer.put(((random.nextFloat() * 25.0f - 12.5f) + (random.nextBoolean() ? 1.0f : -1.0f) * (random.nextFloat() * 6.0f + 6.0f)) * 10.0f); + matrixCopyBuffer.flip(); + _wglUniformMatrix2fv(shader_ssao_generate.uniforms.u_randomizerDataMatrix2f, false, matrixCopyBuffer); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RUN SSAO ALGORITHM"); + } + + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + + // ============== RUN REPROJECTION CONTROL SHADER ================ // + + GlStateManager.setActiveTexture(GL_TEXTURE8); + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(gBufferMaterialTexture); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE7); + GlStateManager.bindTexture(lastFrameGBufferDepthTexture); // may be full of garbage data, let's pretend it won't + GlStateManager.setActiveTexture(GL_TEXTURE6); + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(lastFrameColorTexture); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE5); + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(reprojectionSSRHitVector[1]); // may be garbage data + }else { + GlStateManager.bindTexture(-1); + } + + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(reprojectionSSRTexture[1]); // may be garbage data + }else { + GlStateManager.bindTexture(-1); + } + + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE2); + if(config.is_rendering_ssao) { + GlStateManager.bindTexture(reprojectionControlSSAOTexture[1 - reprojectionPhase]); // may be garbage + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE1); + if(config.is_rendering_ssao) { + GlStateManager.bindTexture(ssaoGenerateTexture); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferDepthTexture); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionControlFramebuffer[reprojectionPhase]); + shader_reproject_control.useProgram(); + tmpVector1.set(-reprojectionViewerOffsetX, -reprojectionViewerOffsetY, -reprojectionViewerOffsetZ); + tmpMatrix1.setIdentity(); + Matrix4f.translate(tmpVector1, tmpMatrix1, tmpMatrix1); + Matrix4f.mul(DeferredStateManager.viewMatrix, tmpMatrix1, tmpMatrixViewReproject); + Matrix4f.mul(tmpMatrixViewProj, tmpMatrix1, tmpMatrixViewProjReproject); + Matrix4f.invert(tmpMatrixViewProjReproject, tmpMatrixInverseViewProjReproject); + + uniformMatrixHelper(shader_reproject_control.uniforms.u_inverseViewProjMatrix4f, tmpMatrixInverseViewProjReproject); + uniformMatrixHelper(shader_reproject_control.uniforms.u_reprojectionMatrix4f, tmpMatrixLastFrameViewProjReproject); + if(config.is_rendering_raytracing) { + uniformMatrixHelper(shader_reproject_control.uniforms.u_projectionMatrix4f, DeferredStateManager.projMatrix); + uniformMatrixHelper(shader_reproject_control.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + Matrix4f.invert(tmpMatrixLastFrameProj, tmpMatrix1); + uniformMatrixHelper(shader_reproject_control.uniforms.u_lastInverseProjMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrixLastFrameViewReproject, tmpMatrix1); + Matrix4f.mul(tmpMatrixViewReproject, tmpMatrix1, tmpMatrix1); + uniformMatrixHelper(shader_reproject_control.uniforms.u_reprojectionInverseViewMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrix1, tmpMatrix1); + Matrix4f.mul(tmpMatrixLastFrameProj, tmpMatrix1, tmpMatrix1); + uniformMatrixHelper(shader_reproject_control.uniforms.u_viewToPreviousProjMatrix4f, tmpMatrix1); + } + _wglUniform4f(shader_reproject_control.uniforms.u_nearFarPlane4f, DeferredStateManager.gbufferNearPlane, + DeferredStateManager.gbufferFarPlane, DeferredStateManager.gbufferNearPlane * DeferredStateManager.gbufferFarPlane * 2.0f, + DeferredStateManager.gbufferFarPlane - DeferredStateManager.gbufferNearPlane); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RUN REPROJECTION CONTROL SHADER"); + + if(config.is_rendering_raytracing) { + + // =========== RUN SCREENSPACE REFLECTIONS ALGORITHM ============= // + + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(lastFrameDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE4); + GlStateManager.bindTexture(lastFrameColorTexture); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(reprojectionSSRHitVector[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(reprojectionSSRTexture[0]); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferQuarterDepthTexture); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]); + + shader_reproject_ssr.useProgram(); + uniformMatrixHelper(shader_reproject_ssr.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + Matrix4f.mul(tmpMatrixLastFrameViewProjReproject, tmpMatrixInverseViewProjReproject, tmpMatrix1); + Matrix4f.mul(tmpMatrix1, DeferredStateManager.projMatrix, tmpMatrix1); + uniformMatrixHelper(shader_reproject_ssr.uniforms.u_lastProjectionMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrix1, tmpMatrix1); + matrixCopyBuffer.clear(); + matrixCopyBuffer.put(tmpMatrix1.m02); + matrixCopyBuffer.put(tmpMatrix1.m03); + matrixCopyBuffer.put(tmpMatrix1.m12); + matrixCopyBuffer.put(tmpMatrix1.m13); + matrixCopyBuffer.put(tmpMatrix1.m22); + matrixCopyBuffer.put(tmpMatrix1.m23); + matrixCopyBuffer.put(tmpMatrix1.m32); + matrixCopyBuffer.put(tmpMatrix1.m33); + matrixCopyBuffer.flip(); + _wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer); + _wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.125f); + + DrawUtils.drawStandardQuad2D(); // sample 1 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(reprojectionSSRHitVector[1]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(reprojectionSSRTexture[1]); + + DrawUtils.drawStandardQuad2D(); // sample 2 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(reprojectionSSRHitVector[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(reprojectionSSRTexture[0]); + + DrawUtils.drawStandardQuad2D(); // sample 3 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[0]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(reprojectionSSRHitVector[1]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(reprojectionSSRTexture[1]); + + DrawUtils.drawStandardQuad2D(); // sample 4 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, reprojectionSSRFramebuffer[1]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(reprojectionSSRHitVector[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(reprojectionSSRTexture[0]); + + DrawUtils.drawStandardQuad2D(); // sample 5 + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RUN SCREENSPACE REFLECTIONS ALGORITHM"); + } + } + + if(config.is_rendering_shadowsSun_clamped > 0) { + + // ==================== RENDER SUNLIGHT SHADOWS ===================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunLightingShadowFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + + shader_shadows_sun.useProgram(); + uniformMatrixHelper(shader_shadows_sun.uniforms.u_inverseViewMatrix4f, DeferredStateManager.inverseViewMatrix); + uniformMatrixHelper(shader_shadows_sun.uniforms.u_inverseViewProjMatrix4f, tmpMatrixInverseViewProj); + + if(config.is_rendering_shadowsColored) { + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(sunShadowColorBuffer); + } + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(sunShadowDepthBuffer); + if(config.is_rendering_shadowsSmoothed) { + setLinear(); + } + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferNormalsTexture); + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix0, tmpShadowLOD0MatrixTexSpace); + uniformMatrixHelper(shader_shadows_sun.uniforms.u_sunShadowMatrixLOD04f, tmpShadowLOD0MatrixTexSpace); + if(config.is_rendering_shadowsSun_clamped > 1) { + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix1, tmpShadowLOD1MatrixTexSpace); + uniformMatrixHelper(shader_shadows_sun.uniforms.u_sunShadowMatrixLOD14f, tmpShadowLOD1MatrixTexSpace); + if(config.is_rendering_shadowsSun_clamped > 2) { + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix2, tmpShadowLOD2MatrixTexSpace); + uniformMatrixHelper(shader_shadows_sun.uniforms.u_sunShadowMatrixLOD24f, tmpShadowLOD2MatrixTexSpace); + } + } + + Vector3f currentSunShadowAngle = DeferredStateManager.currentSunLightAngle; + _wglUniform3f(shader_shadows_sun.uniforms.u_sunDirection3f, -currentSunShadowAngle.x, -currentSunShadowAngle.y, -currentSunShadowAngle.z); + DrawUtils.drawStandardQuad2D(); + + if(config.is_rendering_shadowsSmoothed) { + GlStateManager.setActiveTexture(GL_TEXTURE2); + setNearest(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + } + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER SUNLIGHT SHADOWS"); + } + + // ================ INITIALIZE HDR FRAMEBUFFER ================== // + + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + _wglBindFramebuffer(_GL_READ_FRAMEBUFFER, gBufferFramebuffer); + _wglBindFramebuffer(_GL_DRAW_FRAMEBUFFER, lightingHDRFramebuffer); + _wglBlitFramebuffer(0, 0, currentWidth, currentHeight, 0, 0, currentWidth, currentHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + + if(dim == -1) { + float f = 0.13f; + GlStateManager.clearColor(0.57f * 0.57f * f, 0.38f * 0.38f * f, 0.20f * 0.20f * f, 0.0f); + }else { + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + } + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): INITIALIZE HDR FRAMEBUFFER"); + + // ================= RENDER AMBIENT LIGHTING ==================== // + + GlStateManager.setActiveTexture(GL_TEXTURE9); + GlStateManager.bindTexture(MetalsLUT.getGLTexture()); + GlStateManager.setActiveTexture(GL_TEXTURE8); + GlStateManager.bindTexture(brdfTexture); + GlStateManager.setActiveTexture(GL_TEXTURE7); + GlStateManager.bindTexture(skyIrradianceTexture); + GlStateManager.setActiveTexture(GL_TEXTURE6); + if(config.is_rendering_useEnvMap) { + GlStateManager.bindTexture(envMapColorTexture); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE5); + if(config.is_rendering_raytracing) { + GlStateManager.bindTexture(reprojectionSSRTexture[1]); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_ssao) { + GlStateManager.bindTexture(reprojectionControlSSAOTexture[reprojectionPhase]); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(gBufferDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(gBufferMaterialTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferDiffuseTexture); + + shader_deferred_combine.useProgram(); + uniformMatrixHelper(shader_deferred_combine.uniforms.u_inverseViewMatrix4f, DeferredStateManager.inverseViewMatrix); + uniformMatrixHelper(shader_deferred_combine.uniforms.u_inverseProjMatrix4f, DeferredStateManager.inverseProjMatrix); + _wglUniform3f(shader_deferred_combine.uniforms.u_sunDirection3f, DeferredStateManager.currentSunAngle.x, DeferredStateManager.currentSunAngle.y, DeferredStateManager.currentSunAngle.z); + float lightningBoost = mc.theWorld.getLastLightningBolt() > 0 ? 1.0f : 0.0f; + lightningBoost *= 0.3f + fff; + _wglUniform1f(shader_deferred_combine.uniforms.u_skyLightFactor1f, getSkyBrightnessTimeParam() + lightningBoost); + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER AMBIENT LIGHTING"); + + // ================ BEGIN HDR LIGHTING PASS ================= // + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + + // ==================== RENDER SUNLIGHT ===================== // + + if(dim == 0) { + shader_lighting_sun.useProgram(); + uniformMatrixHelper(shader_lighting_sun.uniforms.u_inverseViewMatrix4f, DeferredStateManager.inverseViewMatrix); + uniformMatrixHelper(shader_lighting_sun.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(MetalsLUT.getGLTexture()); + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_shadowsSun_clamped > 0) { + GlStateManager.bindTexture(sunLightingShadowTexture); + }else { + GlStateManager.bindTexture(-1); + } + GlStateManager.setActiveTexture(GL_TEXTURE0); + + float ffff = getSkyBrightnessParam(); + float[] sunRGB; + if(currentSunAngle.y < 0.05f) { + sunRGB = TemperaturesLUT.getColorTemperature((int)sunKelvin); + Vector3f currentSunLightColor3f = DeferredStateManager.currentSunLightColor; // reuse variable + currentSunLightColor3f.x = sunRGB[0] * 8.0f * (0.1f + ffff * 0.9f); + currentSunLightColor3f.y = sunRGB[1] * 8.0f * (0.1f + ffff * 0.9f); + currentSunLightColor3f.z = sunRGB[2] * 8.0f * (0.1f + ffff * 0.9f); + _wglUniform3f(shader_lighting_sun.uniforms.u_sunColor3f, sunRGB[0] * 4.0f * ffff, sunRGB[1] * 4.0f * ffff, sunRGB[2] * 4.0f * ffff); + }else { + sunRGB = TemperaturesLUT.getColorTemperature((int)(9000.0f + 2500.0f * currentSunAngle.y)); + Vector3f currentSunLightColor3f = DeferredStateManager.currentSunLightColor; // reuse variable + currentSunLightColor3f.x = sunRGB[0] * 0.3f * (0.2f + ffff * 0.8f); + currentSunLightColor3f.y = sunRGB[1] * 0.3f * (0.2f + ffff * 0.8f); + currentSunLightColor3f.z = sunRGB[2] * 0.3f * (0.2f + ffff * 0.8f); + _wglUniform3f(shader_lighting_sun.uniforms.u_sunColor3f, sunRGB[0] * 0.1f * (0.5f + ffff * 0.5f), sunRGB[1] * 0.1f * (0.5f + ffff * 0.5f), sunRGB[2] * 0.1f * (0.5f + ffff * 0.5f)); + } + + _wglUniform3f(shader_lighting_sun.uniforms.u_sunDirection3f, -DeferredStateManager.currentSunLightAngle.x, -DeferredStateManager.currentSunLightAngle.y, -DeferredStateManager.currentSunLightAngle.z); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER SUNLIGHT"); + }else { + DeferredStateManager.currentSunLightColor.set(0.0f, 0.0f, 0.0f); + } + + // ================== RENDER DYNAMIC LIGHTS =================== // + + if(config.is_rendering_dynamicLights) { + shader_lighting_point.useProgram(); + uniformMatrixHelper(shader_lighting_point.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + uniformMatrixHelper(shader_lighting_point.uniforms.u_inverseViewMatrix4f, DeferredStateManager.inverseViewMatrix); + _wglUniform2f(shader_lighting_point.uniforms.u_viewportSize2f, 1.0f / currentWidth, 1.0f / currentHeight); + Iterator itr = DynamicLightManager.lightRenderList.iterator(); + AxisAlignedBB aabb = renderViewEntity.getEntityBoundingBox(); + double eyeHeight = renderViewEntity.getEyeHeight(); + while(itr.hasNext()) { + DynamicLightInstance dl = itr.next(); + float lightPosX = (float)(dl.posX - entityPosX); + float lightPosY = (float)(dl.posY - entityPosY); + float lightPosZ = (float)(dl.posZ - entityPosZ); + float lightChunkPosX = (float)(dl.posX - entityChunkOriginX); + float lightChunkPosY = (float)(dl.posY - entityChunkOriginY); + float lightChunkPosZ = (float)(dl.posZ - entityChunkOriginZ); + bucketLightSource(lightChunkPosX, lightChunkPosY, lightChunkPosZ, dl); + if(dl.posX > aabb.minX - 0.25 && dl.posY > aabb.minY + eyeHeight - 0.25 && dl.posZ > aabb.minZ - 0.25 && + dl.posX < aabb.maxX + 0.25 && dl.posY < aabb.minY + eyeHeight + 0.25 && dl.posZ < aabb.maxZ + 0.25) { + tmpMatrix1.setIdentity(); + uniformMatrixHelper(shader_lighting_point.uniforms.u_modelViewProjMatrix4f, tmpMatrix1); + _wglUniform3f(shader_lighting_point.uniforms.u_lightColor3f, dl.red, dl.green, dl.blue); + _wglUniform3f(shader_lighting_point.uniforms.u_lightPosition3f, lightPosX, lightPosY, lightPosZ); + DrawUtils.drawStandardQuad3D(); + }else { + float radius = dl.radius; + tmpVector1.set(lightPosX, lightPosY, lightPosZ); + if(DeferredStateManager.currentGBufferFrustum.testSphere(tmpVector1, radius)) { + tmpMatrix1.setIdentity(); + Matrix4f.translate(tmpVector1, tmpMatrix1, tmpMatrix1); + tmpVector1.set(radius, radius, radius); + Matrix4f.scale(tmpVector1, tmpMatrix1, tmpMatrix1); + Matrix4f.mul(tmpMatrixViewProj, tmpMatrix1, tmpMatrix1); + uniformMatrixHelper(shader_lighting_point.uniforms.u_modelViewProjMatrix4f, tmpMatrix1); + _wglUniform3f(shader_lighting_point.uniforms.u_lightColor3f, dl.red, dl.green, dl.blue); + _wglUniform3f(shader_lighting_point.uniforms.u_lightPosition3f, lightPosX, lightPosY, lightPosZ); + pointLightMesh.drawMeshVAO(); + } + } + } + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER DYNAMIC LIGHTS"); + } + + DynamicLightManager.lightRenderList.clear(); + + // ================== END HDR LIGHTING PASS ================== // + + GlStateManager.disableBlend(); + + if(reprojectionEngineEnable || config.realisticWater) { + + // =========== SAVE REPROJECTION DATA FOR NEXT FRAME ============= // + + _wglBindFramebuffer(_GL_READ_FRAMEBUFFER, lightingHDRFramebuffer); + _wglBindFramebuffer(_GL_DRAW_FRAMEBUFFER, lastFrameGBufferFramebuffer); + _wglBlitFramebuffer(0, 0, currentWidth, currentHeight, 0, 0, currentWidth, currentHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): SAVE REPROJECTION DATA FOR NEXT FRAME"); + + } + + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + + // =================== RENDER SKYBOX MESH =================== // + + if(dim == 0) { + GlStateManager.enableDepth(); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(CloudRenderWorker.cloudOcclusionTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + CloudRenderWorker.bindParaboloid(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(atmosphereHDRFramebufferColorTexture); + shader_skybox_render.useProgram(); + uniformMatrixHelper(shader_skybox_render.uniforms.u_viewMatrix4f, DeferredStateManager.viewMatrix); + uniformMatrixHelper(shader_skybox_render.uniforms.u_projMatrix4f, DeferredStateManager.projMatrix); + _wglUniform3f(shader_skybox_render.uniforms.u_sunDirection3f, -currentSunAngle.x, -currentSunAngle.y, -currentSunAngle.z); + float mag = 25.0f; + float[] sunRGB2 = TemperaturesLUT.getColorTemperature((int)sunKelvin - 1000); + _wglUniform3f(shader_skybox_render.uniforms.u_sunColor3f, sunRGB2[0] * mag, sunRGB2[1] * mag, sunRGB2[2] * mag); + if (mc.theWorld.getLastLightningBolt() > 0) { + float f = 0.3f + fff; + _wglUniform4f(shader_skybox_render.uniforms.u_lightningColor4f, 0.02f * f, 0.02f * f, 0.02f * f, 1.0f - f * 0.25f); + }else { + _wglUniform4f(shader_skybox_render.uniforms.u_lightningColor4f, 0.0f, 0.0f, 0.0f, 1.0f); + } + skybox.drawFull(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER SKYBOX MESH"); + }else if(dim == 1) { + GlStateManager.enableDepth(); + + GlStateManager.setActiveTexture(GL_TEXTURE0); + mc.getTextureManager().bindTexture(locationEndSkyPng); + + if(shader_skybox_render_end == null) { + shader_skybox_render_end = PipelineShaderSkyboxRenderEnd.compile(); + shader_skybox_render_end.loadUniforms(); + } + + shader_skybox_render_end.useProgram(); + uniformMatrixHelper(shader_skybox_render_end.uniforms.u_viewMatrix4f, DeferredStateManager.viewMatrix); + uniformMatrixHelper(shader_skybox_render_end.uniforms.u_projMatrix4f, DeferredStateManager.projMatrix); + _wglUniform2f(shader_skybox_render_end.uniforms.u_skyTextureScale2f, 4.0f, 4.0f); + + skybox.drawFull(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER SKYBOX MESH"); + } + + if(dim == 0 && fff < 1.0f) { + + // ===================== RENDER MOON ====================== // + + Matrix4f moonMatrix = tmpMatrix2; + moonMatrix.setIdentity(); + tmpVector3.set(-1.0f, -1.0f, 1.0f); + Matrix4f.scale(tmpVector3, moonMatrix, moonMatrix); + tmpVector3.set(0.0f, 0.0f, 1.0f); + Matrix4f.rotate(2.7f, tmpVector3, moonMatrix, moonMatrix); + tmpVector3.set(-1.0f, 0.0f, 0.0f); + tmpVector4.set(currentSunAngle); + tmpVector4.scale(-1.0f); + Vector3f.cross(tmpVector3, tmpVector4, tmpVector1); + Vector3f.cross(tmpVector4, tmpVector1, tmpVector3); + moonMatrix = tmpMatrix1; + moonMatrix.setIdentity(); + moonMatrix.m00 = tmpVector1.x; + moonMatrix.m01 = tmpVector1.y; + moonMatrix.m02 = tmpVector1.z; + moonMatrix.m10 = tmpVector3.x; + moonMatrix.m11 = tmpVector3.y; + moonMatrix.m12 = tmpVector3.z; + moonMatrix.m20 = tmpVector4.x; + moonMatrix.m21 = tmpVector4.y; + moonMatrix.m22 = tmpVector4.z; + Matrix4f.mul(moonMatrix, tmpMatrix2, moonMatrix); + + GlStateManager.bindTexture(moonTextures); + shader_moon_render.useProgram(); + + uniformMatrixHelper(shader_moon_render.uniforms.u_modelMatrix4f, moonMatrix); + uniformMatrixHelper(shader_moon_render.uniforms.u_viewMatrix4f, DeferredStateManager.viewMatrix); + uniformMatrixHelper(shader_moon_render.uniforms.u_projMatrix4f, DeferredStateManager.projMatrix); + float fffff = 0.1f + MathHelper.clamp_float((-currentSunAngle.y + 0.1f) * 8.0f, 0.0f, 0.5f); + _wglUniform3f(shader_moon_render.uniforms.u_moonColor3f, 1.4f * fffff, 1.2f * fffff, 1.0f * fffff); + + float f = (float)(Minecraft.getMinecraft().theWorld.getWorldTime() - 18000f) / 24000f / 4f * 3.14159f; + _wglUniform3f(shader_moon_render.uniforms.u_lightDir3f, MathHelper.sin(f), 0.0f, MathHelper.cos(f)); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ZERO); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("combineGBuffersAndIlluminate(): RENDER MOON"); + } + + GlStateManager.disableDepth(); + GlStateManager.depthMask(true); + GlStateManager.disableBlend(); + } + + public void loadLightSourceBucket(int relativeBlockX, int relativeBlockY, int relativeBlockZ) { + int hw = lightSourceBucketsWidth / 2; + int hh = lightSourceBucketsHeight / 2; + int bucketX = (relativeBlockX >> 4) + hw; + int bucketY = (relativeBlockY >> 4) + hh; + int bucketZ = (relativeBlockZ >> 4) + hw; + if(bucketX >= 0 && bucketY >= 0 && bucketZ >= 0 && bucketX < lightSourceBucketsWidth + && bucketY < lightSourceBucketsHeight && bucketZ < lightSourceBucketsWidth) { + currentLightSourceBucket = lightSourceBuckets[bucketY * lightSourceBucketsWidth * lightSourceBucketsWidth + + bucketZ * lightSourceBucketsWidth + bucketX]; + }else { + currentLightSourceBucket = null; + } + updateLightSourceUBO(); + } + + public ListSerial getLightSourceBucketRelativeChunkCoords(int cx, int cy, int cz) { + int hw = lightSourceBucketsWidth / 2; + int hh = lightSourceBucketsHeight / 2; + cx += hw; + cy += hh; + cz += hw; + if(cx < 0 || cx >= lightSourceBucketsWidth || cy < 0 || cy >= lightSourceBucketsHeight || cz < 0 + || cz >= lightSourceBucketsWidth) { + return null; + }else { + return lightSourceBuckets[cy * lightSourceBucketsWidth * lightSourceBucketsWidth + + cz * lightSourceBucketsWidth + cx]; + } + } + + public void addLightSourceToBucket(int cx, int cy, int cz, DynamicLightInstance dl) { + ListSerial lst = getLightSourceBucketRelativeChunkCoords(cx, cy, cz); + if(lst != null) { + lst.add(dl); + } + } + + public void bucketLightSource(float x, float y, float z, DynamicLightInstance dl) { + int bucketX = MathHelper.floor_float(x / 16.0f); + int bucketY = MathHelper.floor_float(y / 16.0f); + int bucketZ = MathHelper.floor_float(z / 16.0f); + addLightSourceToBucket(bucketX, bucketY, bucketZ, dl); + int minX = bucketX, maxX = bucketX; + int minY = bucketY, maxY = bucketY; + int minZ = bucketZ, maxZ = bucketZ; + float lightLocalX = x - (bucketX << 4); + float lightLocalY = y - (bucketY << 4); + float lightLocalZ = z - (bucketZ << 4); + float radius = dl.radius; + boolean outOfBounds = false; + if(lightLocalX - radius < 0.0f) { + minX -= 1; + outOfBounds = true; + addLightSourceToBucket(bucketX - 1, bucketY, bucketZ, dl); + } + if(lightLocalY - radius < 0.0f) { + minY -= 1; + outOfBounds = true; + addLightSourceToBucket(bucketX, bucketY - 1, bucketZ, dl); + } + if(lightLocalZ - radius < 0.0f) { + minZ -= 1; + outOfBounds = true; + addLightSourceToBucket(bucketX, bucketY, bucketZ - 1, dl); + } + if(lightLocalX + radius >= 16.0f) { + maxX += 1; + outOfBounds = true; + addLightSourceToBucket(bucketX + 1, bucketY, bucketZ, dl); + } + if(lightLocalY + radius >= 16.0f) { + maxY += 1; + outOfBounds = true; + addLightSourceToBucket(bucketX, bucketY + 1, bucketZ, dl); + } + if(lightLocalZ + radius >= 16.0f) { + maxZ += 1; + outOfBounds = true; + addLightSourceToBucket(bucketX, bucketY, bucketZ + 1, dl); + } + if(!outOfBounds) { + return; + } + radius *= radius; + for(int yy = minY; yy <= maxY; ++yy) { + for(int zz = minZ; zz <= maxZ; ++zz) { + for(int xx = minX; xx <= maxX; ++xx) { + if((xx == bucketX ? 1 : 0) + (yy == bucketY ? 1 : 0) + (zz == bucketZ ? 1 : 0) > 1) { + continue; + } + List lst = getLightSourceBucketRelativeChunkCoords(xx, yy, zz); + if(lst != null) { + int bucketBoundsX = xx << 4; + int bucketBoundsY = yy << 4; + int bucketBoundsZ = zz << 4; + if(testAabSphere(bucketBoundsX, bucketBoundsY, bucketBoundsZ, bucketBoundsX + 16, bucketBoundsY + 16, bucketBoundsZ + 16, x, y, z, radius)) { + lst.add(dl); + } + } + } + } + } + } + + /** + * source: https://github.com/JOML-CI/JOML/blob/main/src/main/java/org/joml/Intersectionf.java + */ + public static boolean testAabSphere(float minX, float minY, float minZ, float maxX, float maxY, float maxZ, + float centerX, float centerY, float centerZ, float radius2) { + if (centerX < minX) { + float d = (centerX - minX); + radius2 -= d * d; + } else if (centerX > maxX) { + float d = (centerX - maxX); + radius2 -= d * d; + } + if (centerY < minY) { + float d = (centerY - minY); + radius2 -= d * d; + } else if (centerY > maxY) { + float d = (centerY - maxY); + radius2 -= d * d; + } + if (centerZ < minZ) { + float d = (centerZ - minZ); + radius2 -= d * d; + } else if (centerZ > maxZ) { + float d = (centerZ - maxZ); + radius2 -= d * d; + } + return radius2 >= 0.0f; + } + + public void updateLightSourceUBO() { + if(currentLightSourceBucket == null) { + currentBoundLightSourceBucket = null; + if(isChunkLightingEnabled) { + isChunkLightingEnabled = false; + EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData); + chunkLightingDataCopyBuffer.clear(); + chunkLightingDataCopyBuffer.putInt(0); + chunkLightingDataCopyBuffer.flip(); + _wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer); + } + }else { + boolean isNew; + if(!isChunkLightingEnabled) { + isChunkLightingEnabled = true; + isNew = true; + }else { + isNew = currentLightSourceBucket != currentBoundLightSourceBucket; + } + currentBoundLightSourceBucket = currentLightSourceBucket; + if(isNew || currentBoundLightSourceBucket.eaglerCheck()) { + populateLightSourceUBOFromBucket(currentBoundLightSourceBucket); + currentBoundLightSourceBucket.eaglerResetCheck(); + } + } + } + + private static final List tmpListLights = new ArrayList(32); + private static final Comparator comparatorLightRadius = (l1, l2) -> { + return l1.radius < l2.radius ? 1 : -1; + }; + + private void populateLightSourceUBOFromBucket(List lights) { + int max = lights.size(); + if(max > MAX_LIGHTS_PER_CHUNK) { + tmpListLights.clear(); + tmpListLights.addAll(lights); + lights = tmpListLights; + lights.sort(comparatorLightRadius); + max = MAX_LIGHTS_PER_CHUNK; + } + chunkLightingDataCopyBuffer.clear(); + chunkLightingDataCopyBuffer.putInt(max); + if(max > 0) { + chunkLightingDataCopyBuffer.putInt(0); //padding + chunkLightingDataCopyBuffer.putInt(0); //padding + chunkLightingDataCopyBuffer.putInt(0); //padding + for(int i = 0; i < max; ++i) { + DynamicLightInstance dl = lights.get(i); + chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX)); + chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY)); + chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ)); + chunkLightingDataCopyBuffer.putInt(0); //padding + chunkLightingDataCopyBuffer.putFloat(dl.red); + chunkLightingDataCopyBuffer.putFloat(dl.green); + chunkLightingDataCopyBuffer.putFloat(dl.blue); + chunkLightingDataCopyBuffer.putInt(0); //padding + } + } + chunkLightingDataCopyBuffer.flip(); + EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData); + _wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer); + } + + public void beginDrawEnvMap() { + DeferredStateManager.checkGLError("Pre: beginDrawEnvMap()"); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + DeferredStateManager.enableForwardRender(); + DeferredStateManager.enableParaboloidRender(); + DeferredStateManager.disableFog(); + GlStateManager.enableExtensionPipeline(); + updateForwardRenderWorldLightingData(); + EaglercraftGPU.bindGLUniformBuffer(buffer_worldLightingData); + EaglercraftGPU.bindUniformBufferRange(0, buffer_worldLightingData, 0, worldLightingDataCopyBuffer.remaining()); + if(config.is_rendering_dynamicLights) { + EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData); + EaglercraftGPU.bindUniformBufferRange(1, buffer_chunkLightingData, 0, chunkLightingDataCopyBuffer.capacity()); + } + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.pushMatrix(); + GlStateManager.loadIdentity(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.pushMatrix(); + GlStateManager.loadIdentity(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, envMapFramebuffer); + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GlStateManager.setActiveTexture(GL_TEXTURE10); + GlStateManager.bindTexture(skyIrradianceTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + DeferredStateManager.checkGLError("Post: beginDrawEnvMap()"); + } + + public void beginDrawEnvMapTop(float eyeHeight) { + DeferredStateManager.checkGLError("Pre: beginDrawEnvMapTop()"); + GlStateManager.loadIdentity(); + tmpMatrix1.setIdentity(); + tmpMatrix1.m32 = eyeHeight; + Matrix4f.mul(tmpMatrix1, DeferredStateManager.paraboloidTopViewMatrix, tmpMatrix1); + GlStateManager.getModelViewReference().load(tmpMatrix1); + DeferredStateManager.passProjMatrix.setIdentity(); + DeferredStateManager.passInverseProjMatrix.setIdentity(); + ++DeferredStateManager.passProjMatrixSerial; + DeferredStateManager.passViewMatrix.load(tmpMatrix1); + Matrix4f.invert(DeferredStateManager.passViewMatrix, DeferredStateManager.passInverseViewMatrix); + ++DeferredStateManager.passViewMatrixSerial; + GlStateManager.viewport(0, 0, 128, 128); + DeferredStateManager.checkGLError("Post: beginDrawEnvMapTop()"); + } + + public void beginDrawEnvMapSolid() { + DeferredStateManager.checkGLError("Pre: beginDrawEnvMapSolid()"); + GlStateManager.disableBlend(); + bindEnvMapBlockTexture(); + DeferredStateManager.checkGLError("Post: beginDrawEnvMapSolid()"); + } + + public void beginDrawEnvMapTranslucent() { + DeferredStateManager.checkGLError("Pre: beginDrawEnvMapTranslucent()"); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE); + bindEnvMapBlockTexture(); + DeferredStateManager.checkGLError("Post: beginDrawEnvMapTranslucent()"); + } + + private void bindEnvMapBlockTexture() { + DeferredStateManager.checkGLError("Pre: bindEnvMapBlockTexture()"); + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_shadowsSun_clamped > 0) { + GlStateManager.bindTexture(sunShadowDepthBuffer); + }else { + GlStateManager.bindTexture(-1); + } + TextureManager mgr = mc.getTextureManager(); + GlStateManager.setActiveTexture(GL_TEXTURE10); + GlStateManager.bindTexture(skyIrradianceTexture); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(MetalsLUT.getGLTexture()); + GlStateManager.setActiveTexture(GL_TEXTURE0); + mgr.bindTexture(TextureMap.locationBlocksTexture); + GlStateManager.enableCull(); + DeferredStateManager.checkGLError("Post: bindEnvMapBlockTexture()"); + } + + public void beginDrawEnvMapBottom(float eyeHeight) { + DeferredStateManager.checkGLError("Pre: beginDrawEnvMapBottom()"); + GlStateManager.loadIdentity(); + tmpMatrix1.setIdentity(); + tmpMatrix1.m32 = -eyeHeight; + Matrix4f.mul(tmpMatrix1, DeferredStateManager.paraboloidBottomViewMatrix, tmpMatrix1); + GlStateManager.getModelViewReference().load(tmpMatrix1); + DeferredStateManager.passViewMatrix.load(tmpMatrix1); + Matrix4f.invert(DeferredStateManager.passViewMatrix, DeferredStateManager.passInverseViewMatrix); + ++DeferredStateManager.passViewMatrixSerial; + GlStateManager.viewport(0, 128, 128, 128); + DeferredStateManager.checkGLError("Post: beginDrawEnvMapBottom()"); + } + + public void endDrawEnvMap() { + DeferredStateManager.checkGLError("Pre: endDrawEnvMap()"); + DeferredStateManager.disableForwardRender(); + DeferredStateManager.disableParaboloidRender(); + GlStateManager.disableFog(); + GlStateManager.disableDepth(); + GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); + GlStateManager.disableExtensionPipeline(); + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.popMatrix(); + DeferredStateManager.checkGLError("Post: endDrawEnvMap()"); + } + + private void updateForwardRenderWorldLightingData() { + worldLightingDataCopyBuffer.clear(); + worldLightingDataCopyBuffer.putFloat(-DeferredStateManager.currentSunLightAngle.x); + worldLightingDataCopyBuffer.putFloat(-DeferredStateManager.currentSunLightAngle.y); + worldLightingDataCopyBuffer.putFloat(-DeferredStateManager.currentSunLightAngle.z); + worldLightingDataCopyBuffer.putFloat(-DeferredStateManager.currentSunAngle.y); + float f = getSkyBrightnessParam(); + if(DeferredStateManager.currentSunAngle.y > 0.05f) { // moon: + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.x * 0.025f * f); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.y * 0.025f * f); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.z * 0.025f * f); + }else { + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.x * f); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.y * f); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.z * f); + } + float lightningBoost = mc.theWorld.getLastLightningBolt() > 0 ? 1.0f : 0.0f; + lightningBoost *= 0.3f + mc.theWorld.getRainStrength(partialTicks); + worldLightingDataCopyBuffer.putFloat(getSkyBrightnessTimeParam() + lightningBoost); + worldLightingDataCopyBuffer.putFloat((float)DeferredStateManager.fogLinearExp); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogDensity); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogNear); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogFar); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorDarkR); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorDarkG); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorDarkB); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorDarkA); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorLightR); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorLightG); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorLightB); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.fogColorLightA); + float mul = 0.05f * MathHelper.clamp_float(-1.0f - DeferredStateManager.getSunHeight() * 20.0f, 0.0f, 1.0f) + 0.01f; + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.x * mul); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.y * mul); + worldLightingDataCopyBuffer.putFloat(DeferredStateManager.currentSunLightColor.z * mul); + worldLightingDataCopyBuffer.putInt(0); + worldLightingDataCopyBuffer.putFloat(1.0f); + worldLightingDataCopyBuffer.putFloat(1.0f); + worldLightingDataCopyBuffer.putFloat(1.0f); + worldLightingDataCopyBuffer.putFloat(1.0f); + if(config.is_rendering_shadowsSun_clamped > 0) { + tmpShadowLOD0MatrixTexSpace.store(worldLightingDataCopyBuffer); + if(config.is_rendering_shadowsSun_clamped > 1) { + tmpShadowLOD1MatrixTexSpace.store(worldLightingDataCopyBuffer); + if(config.is_rendering_shadowsSun_clamped > 2) { + tmpShadowLOD2MatrixTexSpace.store(worldLightingDataCopyBuffer); + } + } + } + worldLightingDataCopyBuffer.flip(); + EaglercraftGPU.bindGLUniformBuffer(buffer_worldLightingData); + _wglBufferSubData(_GL_UNIFORM_BUFFER, 0, worldLightingDataCopyBuffer); + } + + public void setForwardRenderLightFactors(float block, float sky, float sun, float dynamic) { + worldLightingDataCopyBuffer.clear(); + worldLightingDataCopyBuffer.putFloat(block); + worldLightingDataCopyBuffer.putFloat(sky); + worldLightingDataCopyBuffer.putFloat(sun); + worldLightingDataCopyBuffer.putFloat(dynamic); + worldLightingDataCopyBuffer.flip(); + EaglercraftGPU.bindGLUniformBuffer(buffer_worldLightingData); + _wglBufferSubData(_GL_UNIFORM_BUFFER, 96, worldLightingDataCopyBuffer); + } + + private float getSkyBrightnessParam() { + float fff = mc.theWorld.getRainStrength(partialTicks) * 0.9f; + fff += mc.theWorld.getThunderStrength(partialTicks) * 0.05f; + return 1.0f - fff; + } + + private float getSkyBrightnessTimeParam() { + return (2.0f + MathHelper.clamp_float(-DeferredStateManager.currentSunAngle.y * 8.0f, 0.0f, 1.5f)) * getSkyBrightnessParam(); + } + + public void beginDrawRealisticWaterMask() { + DeferredStateManager.checkGLError("Pre: beginDrawRealisticWaterMask()"); + _wglBindFramebuffer(_GL_READ_FRAMEBUFFER, gBufferFramebuffer); + _wglBindFramebuffer(_GL_DRAW_FRAMEBUFFER, realisticWaterMaskFramebuffer); + _wglBlitFramebuffer(0, 0, currentWidth, currentHeight, 0, 0, currentWidth, currentHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterMaskFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + GlStateManager.enableDepth(); + GlStateManager.enableCull(); + GlStateManager.depthMask(true); + DeferredStateManager.enableDrawRealisticWaterMask(); + GlStateManager.enableExtensionPipeline(); + DeferredStateManager.checkGLError("Post: beginDrawRealisticWaterMask()"); + } + + public void endDrawRealisticWaterMask() { + DeferredStateManager.checkGLError("Pre: endDrawRealisticWaterMask()"); + GlStateManager.disableDepth(); + GlStateManager.disableCull(); + DeferredStateManager.disableDrawRealisticWaterMask(); + GlStateManager.disableExtensionPipeline(); + + if(config.is_rendering_lightShafts) { + + // ================== RENDER LIGHT SHAFTS =================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightShaftsFramebuffer); + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(dither8x8Texture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(sunShadowDepthBuffer); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(realisticWaterDepthBuffer); + shader_light_shafts_sample.useProgram(); + _wglUniform2f(shader_light_shafts_sample.uniforms.u_ditherScale2f, reprojectionTexWidth * 0.125f, reprojectionTexHeight * 0.125f); + uniformMatrixHelper(shader_light_shafts_sample.uniforms.u_inverseViewProjMatrix4f, tmpMatrixInverseViewProj); + _wglUniform3f(shader_light_shafts_sample.uniforms.u_eyePosition3f, DeferredStateManager.inverseViewMatrix.m30, + DeferredStateManager.inverseViewMatrix.m31, DeferredStateManager.inverseViewMatrix.m32); + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix0, tmpShadowLOD0MatrixTexSpace); + uniformMatrixHelper(shader_light_shafts_sample.uniforms.u_sunShadowMatrixLOD04f, tmpShadowLOD0MatrixTexSpace); + if(config.is_rendering_shadowsSun_clamped > 1) { + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix1, tmpShadowLOD1MatrixTexSpace); + uniformMatrixHelper(shader_light_shafts_sample.uniforms.u_sunShadowMatrixLOD14f, tmpShadowLOD1MatrixTexSpace); + if(config.is_rendering_shadowsSun_clamped > 2) { + Matrix4f.mul(tmpClipToTexSpaceMatLeft, DeferredStateManager.sunShadowMatrix2, tmpShadowLOD2MatrixTexSpace); + uniformMatrixHelper(shader_light_shafts_sample.uniforms.u_sunShadowMatrixLOD24f, tmpShadowLOD2MatrixTexSpace); + } + } + + GlStateManager.enableBlend(); + GlStateManager.setBlendConstants(0.0f, 0.0f, 0.0f, 0.25f); + + GlStateManager.blendFunc(GL_CONSTANT_ALPHA, GL_ZERO); + _wglUniform1f(shader_light_shafts_sample.uniforms.u_sampleStep1f, 0.0f); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.blendFunc(GL_CONSTANT_ALPHA, GL_ONE); + _wglUniform1f(shader_light_shafts_sample.uniforms.u_sampleStep1f, 1.0f); + DrawUtils.drawStandardQuad2D(); + + _wglUniform1f(shader_light_shafts_sample.uniforms.u_sampleStep1f, 2.0f); + DrawUtils.drawStandardQuad2D(); + + _wglUniform1f(shader_light_shafts_sample.uniforms.u_sampleStep1f, 3.0f); + DrawUtils.drawStandardQuad2D(); + + GlStateManager.disableBlend(); + + DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): RENDER LIGHT SHAFTS"); + } + + // =================== COMBINE NORMALS =================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterCombinedNormalsFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.bindTexture(gBufferNormalsTexture); + TextureCopyUtil.blitTexture(); + + GlStateManager.bindTexture(realisticWaterMaskTexture); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); + TextureCopyUtil.blitTexture(); + GlStateManager.disableBlend(); + + DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): COMBINE NORMALS"); + + // ================ REPROJ CONTROL AND FOG =============== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterControlFramebuffer); + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + + GlStateManager.setActiveTexture(GL_TEXTURE7); + GlStateManager.bindTexture(lastFrameDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE6); + GlStateManager.bindTexture(lastFrameColorTexture); + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]); + GlStateManager.setActiveTexture(GL_TEXTURE4); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterDepthBuffer); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterCombinedNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + shader_realistic_water_control.useProgram(); + + if(!reprojectionEngineEnable) { + tmpVector1.set(-reprojectionViewerOffsetX, -reprojectionViewerOffsetY, -reprojectionViewerOffsetZ); + tmpMatrix1.setIdentity(); + Matrix4f.translate(tmpVector1, tmpMatrix1, tmpMatrix1); + Matrix4f.mul(DeferredStateManager.viewMatrix, tmpMatrix1, tmpMatrixViewReproject); + Matrix4f.mul(tmpMatrixViewProj, tmpMatrix1, tmpMatrixViewProjReproject); + Matrix4f.invert(tmpMatrixViewProjReproject, tmpMatrixInverseViewProjReproject); + } + + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_inverseViewProjMatrix4f, tmpMatrixInverseViewProjReproject); + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_reprojectionMatrix4f, tmpMatrixLastFrameViewProjReproject); + + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_projectionMatrix4f, DeferredStateManager.projMatrix); + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + Matrix4f.invert(tmpMatrixLastFrameProj, tmpMatrix1); + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_lastInverseProjMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrixLastFrameViewReproject, tmpMatrix1); + Matrix4f.mul(tmpMatrixViewReproject, tmpMatrix1, tmpMatrix1); + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_reprojectionInverseViewMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrix1, tmpMatrix1); + Matrix4f.mul(tmpMatrixLastFrameProj, tmpMatrix1, tmpMatrix1); + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_viewToPreviousProjMatrix4f, tmpMatrix1); + + _wglUniform4f(shader_realistic_water_control.uniforms.u_nearFarPlane4f, DeferredStateManager.gbufferNearPlane, + DeferredStateManager.gbufferFarPlane, DeferredStateManager.gbufferNearPlane * 2.0f, + DeferredStateManager.gbufferFarPlane - DeferredStateManager.gbufferNearPlane); + + float fr = 0.03f; + float fg = 0.06f; + float fb = 0.20f; + float ff = 0.1f; + float fac = MathHelper.clamp_float(DeferredStateManager.currentSunAngle.y * -4.0f, 0.1f, 1.0f); + _wglUniform4f(shader_realistic_water_control.uniforms.u_refractFogColor4f, fr * ff, fg * ff, fb * ff, fac); + + uniformMatrixHelper(shader_realistic_water_control.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): REPROJ CONTROL AND FOG"); + + // =========== RUN SCREENSPACE REFLECTIONS ALGORITHM ============= // + + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(lastFrameDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE4); + GlStateManager.bindTexture(lastFrameColorTexture); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(realisticWaterCombinedNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(realisticWaterDepthBuffer); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]); + + shader_reproject_ssr.useProgram(); + uniformMatrixHelper(shader_reproject_ssr.uniforms.u_inverseProjectionMatrix4f, DeferredStateManager.inverseProjMatrix); + Matrix4f.mul(tmpMatrixLastFrameViewProjReproject, tmpMatrixInverseViewProjReproject, tmpMatrix1); + Matrix4f.mul(tmpMatrix1, DeferredStateManager.projMatrix, tmpMatrix1); + uniformMatrixHelper(shader_reproject_ssr.uniforms.u_lastProjectionMatrix4f, tmpMatrix1); + Matrix4f.invert(tmpMatrix1, tmpMatrix1); + matrixCopyBuffer.clear(); + matrixCopyBuffer.put(tmpMatrix1.m02); + matrixCopyBuffer.put(tmpMatrix1.m03); + matrixCopyBuffer.put(tmpMatrix1.m12); + matrixCopyBuffer.put(tmpMatrix1.m13); + matrixCopyBuffer.put(tmpMatrix1.m22); + matrixCopyBuffer.put(tmpMatrix1.m23); + matrixCopyBuffer.put(tmpMatrix1.m32); + matrixCopyBuffer.put(tmpMatrix1.m33); + matrixCopyBuffer.flip(); + _wglUniformMatrix4x2fv(shader_reproject_ssr.uniforms.u_lastInverseProjMatrix4x2f, false, matrixCopyBuffer); + _wglUniform1f(shader_reproject_ssr.uniforms.u_sampleStep1f, 0.5f); + + DrawUtils.drawStandardQuad2D(); // sample 1 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]); + + DrawUtils.drawStandardQuad2D(); // sample 2 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]); + + DrawUtils.drawStandardQuad2D(); // sample 3 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[0]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[1]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]); + + DrawUtils.drawStandardQuad2D(); // sample 4 + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterSSRFramebuffer[1]); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(realisticWaterControlHitVectorTexture[0]); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[0]); + + DrawUtils.drawStandardQuad2D(); // sample 5 + + DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): RUN SCREENSPACE REFLECTIONS ALGORITHM"); + + // ============== GENERATE WAVE NORMAL MAP ================ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterDisplacementMapFramebuffer); + GlStateManager.viewport(0, 0, 256, 256); + + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(realisticWaterNoiseMap); + + shader_realistic_water_noise.useProgram(); + float waveTimer = (float)((System.currentTimeMillis() % 600000l) * 0.001); + _wglUniform4f(shader_realistic_water_noise.uniforms.u_waveTimer4f, waveTimer, 0.0f, 0.0f, 0.0f); + + DrawUtils.drawStandardQuad2D(); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, realisticWaterNormalMapFramebuffer); + + GlStateManager.bindTexture(realisticWaterDisplacementMapTexture); + + shader_realistic_water_normals.useProgram(); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawRealisticWaterMask(): GENERATE WAVE NORMAL MAP"); + } + + public void applyGBufferFog() { + DeferredStateManager.checkGLError("Pre: applyGBufferFog()"); + if(DeferredStateManager.fogLinearExp == 0) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + return; + } + _wglBindFramebuffer(_GL_READ_FRAMEBUFFER, lightingHDRFramebuffer); + _wglBindFramebuffer(_GL_DRAW_FRAMEBUFFER, fogDepthCopyBuffer); + _wglBlitFramebuffer(0, 0, currentWidth, currentHeight, 0, 0, currentWidth, currentHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + if(config.is_rendering_lightShafts) { + GlStateManager.setActiveTexture(GL_TEXTURE4); + GlStateManager.bindTexture(lightShaftsTexture); + } + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(skyIrradianceTexture); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(fogDepthCopyTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(gBufferNormalsTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(gBufferDepthTexture); + tmpMatrix1.load(DeferredStateManager.inverseViewMatrix); + tmpMatrix1.m30 = tmpMatrix1.m31 = tmpMatrix1.m32 = 0.0f; + Matrix4f.mul(tmpMatrix1, DeferredStateManager.inverseProjMatrix, tmpMatrix1); + PipelineShaderGBufferFog fogShader; + switch(DeferredStateManager.fogLinearExp) { + case 1: + fogShader = shader_colored_fog_linear; + fogShader.useProgram(); + _wglUniform2f(fogShader.uniforms.u_linearFogParam2f, DeferredStateManager.fogNear, DeferredStateManager.fogFar); + break; + case 2: + fogShader = shader_colored_fog_exp; + fogShader.useProgram(); + _wglUniform1f(fogShader.uniforms.u_expFogDensity1f, DeferredStateManager.fogDensity); + break; + case 6: + fogShader = shader_atmosphere_fog; + fogShader.useProgram(); + _wglUniform1f(fogShader.uniforms.u_expFogDensity1f, DeferredStateManager.fogDensity); + float mul = 0.05f * MathHelper.clamp_float(-1.0f - DeferredStateManager.getSunHeight() * 20.0f, 0.0f, 1.0f) + 0.01f; + _wglUniform3f(fogShader.uniforms.u_sunColorAdd3f, DeferredStateManager.currentSunLightColor.x * mul, DeferredStateManager.currentSunLightColor.y * mul, DeferredStateManager.currentSunLightColor.z * mul); + break; + default: + throw new RuntimeException("Invalid fog type: " + DeferredStateManager.fogLinearExp); + } + uniformMatrixHelper(fogShader.uniforms.u_inverseViewProjMatrix4f, tmpMatrix1); + _wglUniform4f(fogShader.uniforms.u_fogColorLight4f, DeferredStateManager.fogColorLightR, + DeferredStateManager.fogColorLightG, DeferredStateManager.fogColorLightB, + DeferredStateManager.fogColorLightA); + _wglUniform4f(fogShader.uniforms.u_fogColorDark4f, DeferredStateManager.fogColorDarkR, + DeferredStateManager.fogColorDarkG, DeferredStateManager.fogColorDarkB, + DeferredStateManager.fogColorDarkA); + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + DrawUtils.drawStandardQuad2D(); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + DeferredStateManager.setHDRTranslucentPassBlendFunc(); + DeferredStateManager.checkGLError("Post: applyGBufferFog()"); + } + + public void beginDrawHDRTranslucent() { + DeferredStateManager.checkGLError("Pre: beginDrawHDRTranslucent()"); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL_GREATER, 0.1f); + GlStateManager.enableBlend(); + DeferredStateManager.setHDRTranslucentPassBlendFunc(); + DeferredStateManager.enableForwardRender(); + GlStateManager.enableExtensionPipeline(); + updateForwardRenderWorldLightingData(); + EaglercraftGPU.bindGLUniformBuffer(buffer_worldLightingData); + EaglercraftGPU.bindUniformBufferRange(0, buffer_worldLightingData, 0, worldLightingDataCopyBuffer.remaining()); + if(config.is_rendering_dynamicLights) { + EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData); + EaglercraftGPU.bindUniformBufferRange(1, buffer_chunkLightingData, 0, chunkLightingDataCopyBuffer.capacity()); + } + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + DeferredStateManager.setPassMatrixToGBuffer(); + GlStateManager.setActiveTexture(GL_TEXTURE10); + GlStateManager.bindTexture(skyIrradianceTexture); + if(config.is_rendering_lightShafts) { + GlStateManager.setActiveTexture(GL_TEXTURE11); + GlStateManager.bindTexture(lightShaftsTexture); + } + if(config.is_rendering_useEnvMap) { + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(envMapColorTexture); + } + GlStateManager.setActiveTexture(GL_TEXTURE6); + GlStateManager.bindTexture(brdfTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + DeferredStateManager.checkGLError("Post: beginDrawHDRTranslucent()"); + } + + public void beginDrawRealisticWaterSurface() { + DeferredStateManager.checkGLError("Pre: beginDrawRealisticWaterSurface()"); + DeferredStateManager.enableDrawRealisticWaterRender(); + GlStateManager.setActiveTexture(GL_TEXTURE9); + GlStateManager.bindTexture(realisticWaterNormalMapTexture); + GlStateManager.setActiveTexture(GL_TEXTURE8); + GlStateManager.bindTexture(realisticWaterRefractionTexture); + GlStateManager.setActiveTexture(GL_TEXTURE7); + GlStateManager.bindTexture(realisticWaterControlReflectionTexture[1]); + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(envMapSkyTexture); + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_shadowsSun_clamped > 0) { + GlStateManager.bindTexture(sunShadowDepthBuffer); + if(config.is_rendering_shadowsSmoothed) { + setLinear(); + } + }else { + GlStateManager.bindTexture(-1); + } + TextureManager mgr = mc.getTextureManager(); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(MetalsLUT.getGLTexture()); + GlStateManager.setActiveTexture(GL_TEXTURE0); + mgr.bindTexture(TextureMap.locationBlocksTexture); + GlStateManager.enableCull(); + DeferredStateManager.checkGLError("Post: beginDrawRealisticWaterSurface()"); + } + + public void endDrawRealisticWaterSurface() { + DeferredStateManager.checkGLError("Pre: endDrawRealisticWaterSurface()"); + DeferredStateManager.disableDrawRealisticWaterRender(); + if(config.is_rendering_useEnvMap) { + GlStateManager.setActiveTexture(GL_TEXTURE5); + GlStateManager.bindTexture(envMapColorTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + } + DeferredStateManager.checkGLError("Post: endDrawRealisticWaterSurface()"); + } + + public void beginDrawTranslucentBlocks() { + DeferredStateManager.checkGLError("Pre: beginDrawTranslucentBlocks()"); + } + + public void beginDrawGlassHighlights() { + DeferredStateManager.checkGLError("Pre: beginDrawGlassHighlights()"); + DeferredStateManager.enableDrawGlassHighlightsRender(); + GlStateManager.depthMask(false); + GlStateManager.enablePolygonOffset(); + GlStateManager.doPolygonOffset(0.25f, 1.0f); + GlStateManager.tryBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + DeferredStateManager.checkGLError("Post: beginDrawGlassHighlights()"); + } + + public void endDrawGlassHighlights() { + DeferredStateManager.checkGLError("Pre: endDrawGlassHighlights()"); + DeferredStateManager.disableDrawGlassHighlightsRender(); + GlStateManager.depthMask(true); + GlStateManager.disablePolygonOffset(); + DeferredStateManager.setHDRTranslucentPassBlendFunc(); + DeferredStateManager.checkGLError("Post: endDrawGlassHighlights()"); + } + + public void beginDrawTranslucentEntities() { + DeferredStateManager.checkGLError("Pre: beginDrawTranslucentEntities()"); + GlStateManager.setActiveTexture(GL_TEXTURE4); + if(config.is_rendering_shadowsSun_clamped > 0) { + GlStateManager.bindTexture(sunShadowDepthBuffer); + if(config.is_rendering_shadowsSmoothed) { + setLinear(); + } + }else { + GlStateManager.bindTexture(-1); + } + TextureManager mgr = mc.getTextureManager(); + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(MetalsLUT.getGLTexture()); + GlStateManager.setActiveTexture(GL_TEXTURE0); + mgr.bindTexture(TextureMap.locationBlocksTexture); + GlStateManager.enableCull(); + DeferredStateManager.checkGLError("Post: beginDrawTranslucentEntities()"); + } + + public void saveReprojData() { + DeferredStateManager.checkGLError("Pre: saveReprojData()"); + if(reprojectionEngineEnable || config.is_rendering_realisticWater) { + + // =========== SAVE REPROJECTION DATA FOR NEXT FRAME ============= // + + tmpMatrixLastFrameProj.load(DeferredStateManager.projMatrix); + tmpMatrixLastFrameViewReproject.load(tmpMatrixViewReproject); + tmpMatrixLastFrameViewProjReproject.load(tmpMatrixViewProjReproject); + + GlStateManager.disableBlend(); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lastFrameFramebuffer); + GlStateManager.viewport(0, 0, reprojectionTexWidth, reprojectionTexHeight); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + TextureCopyUtil.alignPixelsTopLeft(reprojectionTexWidth << 1, reprojectionTexHeight << 1, reprojectionTexWidth, reprojectionTexHeight); + TextureCopyUtil.blitTexture(); + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL_ALWAYS); + GlStateManager.depthMask(true); + _wglDrawBuffers(GL_NONE); + TextureCopyUtil.alignPixelsTopLeft(reprojectionTexWidth << 1, reprojectionTexHeight << 1, reprojectionTexWidth, reprojectionTexHeight); + TextureCopyUtil.blitTextureDepth(); + GlStateManager.disableDepth(); + GlStateManager.depthMask(false); + GlStateManager.depthFunc(GL_LEQUAL); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + + reprojectionPhase = (reprojectionPhase + 1) & 1; + ++reprojectionStartup; + + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.enableBlend(); + } + DeferredStateManager.checkGLError("Post: saveReprojData()"); + } + + public void beginDrawHandOverlay() { + DeferredStateManager.checkGLError("Pre: beginDrawHandOverlay()"); + _wglBindFramebuffer(_GL_FRAMEBUFFER, handRenderFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.clearDepth(1.0f); + GlStateManager.depthMask(true); + GlStateManager.clear(GL_DEPTH_BUFFER_BIT); + GlStateManager.enableDepth(); + DeferredStateManager.setDefaultMaterialConstants(); + DeferredStateManager.checkGLError("Post: beginDrawHandOverlay()"); + } + + public void endDrawHandOverlay() { + DeferredStateManager.checkGLError("Pre: endDrawHandOverlay()"); + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + shader_hand_depth_mask.useProgram(); + _wglDrawBuffers(GL_NONE); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(handRenderFramebufferDepthTexture); + DrawUtils.drawStandardQuad2D(); + _wglDrawBuffers(_GL_COLOR_ATTACHMENT0); + DeferredStateManager.checkGLError("Post: endDrawHandOverlay()"); + } + + public void endDrawHDRTranslucent() { + DeferredStateManager.checkGLError("Pre: endDrawHDRTranslucent()"); + DeferredStateManager.disableForwardRender(); + DeferredStateManager.disableFog(); + GlStateManager.disableFog(); + GlStateManager.disableDepth(); + GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); + GlStateManager.disableExtensionPipeline(); + if(config.is_rendering_shadowsSun_clamped > 0 && config.is_rendering_shadowsSmoothed) { + GlStateManager.bindTexture(sunShadowDepthBuffer); + setNearest(); + } + DeferredStateManager.checkGLError("Post: endDrawHDRTranslucent()"); + } + + public void endDrawDeferred() { + DeferredStateManager.checkGLError("Pre: endDrawDeferred()"); + + if(config.is_rendering_lensFlares && mc.theWorld.provider.getDimensionId() == 0 && + DeferredStateManager.currentSunAngle.y < 0.2f && mc.theWorld.getRainStrength(partialTicks) < 1.0f) { + + // =============== CALCULATE SUN COORDINATES ================ // + + tmpVector2.x = DeferredStateManager.currentSunAngle.x * 10.0f; + tmpVector2.y = DeferredStateManager.currentSunAngle.y * 10.0f; + tmpVector2.z = DeferredStateManager.currentSunAngle.z * 10.0f; + tmpVector2.w = 1.0f; + + Matrix4f.transform(tmpMatrixViewProj, tmpVector2, tmpVector2); + + tmpVector2.z /= tmpVector2.w; + float margin = 0.2f; + if (tmpVector2.z <= -1.0f) { + tmpVector2.x = DeferredStateManager.currentSunAngle.x * 10.0f; + tmpVector2.y = DeferredStateManager.currentSunAngle.y * 10.0f; + tmpVector2.z = DeferredStateManager.currentSunAngle.z * 10.0f; + tmpVector2.w = 0.0f; + Matrix4f.transform(tmpMatrixViewProj, tmpVector2, tmpVector2); + tmpVector2.x /= tmpVector2.w; + tmpVector2.y /= tmpVector2.w; + if (tmpVector2.x < 1.0f + margin && tmpVector2.x > -1.0f - margin && tmpVector2.y < 1.0f + margin + && tmpVector2.y > -1.0f - margin) { + + // ============ CALCULATE DEPTH SUN OCCLUSION ============ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, sunOcclusionValueFramebuffer); + GlStateManager.viewport(0, 0, 1, 1); + + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(CloudRenderWorker.cloudOcclusionTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + + float fov = 90.0f / mc.entityRenderer.getFOVModifier(partialTicks, true); + float radius = 0.05f * fov; + float aspectRatio = (float)currentHeight / (float)currentWidth; + + tmpMatrix3.setIdentity(); + tmpMatrix3.m00 = aspectRatio * radius; + tmpMatrix3.m11 = radius; + tmpMatrix3.m20 = tmpVector2.x * 0.5f + 0.5f; + tmpMatrix3.m21 = tmpVector2.y * 0.5f + 0.5f; + + shader_lens_sun_occlusion.useProgram(); + + uniformMatrixHelper(shader_lens_sun_occlusion.uniforms.u_sampleMatrix3f, tmpMatrix3); + + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawDeferred(): CALCULATE DEPTH SUN OCCLUSION"); + + // ============ RENDER SUN LENS FLARES MESHES ============ // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + + LensFlareMeshRenderer.drawLensFlares(tmpVector2.x, tmpVector2.y); + + DeferredStateManager.checkGLError("endDrawDeferred(): RENDER SUN LENS FLARES MESHES"); + } + } + } + + // ================ DOWNSCALE AND AVERAGE LUMA =============== // + + long millis = System.currentTimeMillis(); + if(millis - lastExposureUpdate > 33l) { + if(lumaAvgDownscaleFramebuffers.length == 0) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, exposureBlendFramebuffer); + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT); + }else { + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + setLinear(); + + int iw = currentWidth; + int ih = currentHeight; + int iw2 = 0, ih2 = 0, iw3 = 0, ih3 = 0; + for(int i = 0; i < lumaAvgDownscaleFramebuffers.length; ++i) { + iw2 = iw >> 2; + ih2 = ih >> 2; + // cheap way to round up: + iw3 = ((iw & 3) != 0) ? (iw2 + 1) : iw2; + ih3 = ((ih & 3) != 0) ? (ih2 + 1) : ih2; + _wglBindFramebuffer(_GL_FRAMEBUFFER, lumaAvgDownscaleFramebuffers[i]); + + if(i == 0) { + shader_post_exposure_avg_luma.useProgram(); + _wglUniform4f(shader_post_exposure_avg_luma.uniforms.u_sampleOffset4f, 1.0f / iw3, 1.0f / ih3, 4.0f / iw, 4.0f / ih); + }else { + shader_post_exposure_avg.useProgram(); + GlStateManager.bindTexture(lumaAvgDownscaleTexture[i - 1]); + _wglUniform4f(shader_post_exposure_avg.uniforms.u_sampleOffset4f, 1.0f / iw3, 1.0f / ih3, 4.0f / iw, 4.0f / ih); + } + + GlStateManager.viewport(0, 0, iw3, ih3); + + DrawUtils.drawStandardQuad2D(); + + iw = iw2; + ih = ih2; + } + + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + setNearest(); + + _wglBindFramebuffer(_GL_FRAMEBUFFER, exposureBlendFramebuffer); + GlStateManager.viewport(0, 0, 1, 1); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + + GlStateManager.setBlendConstants(0.0f, 0.0f, 0.0f, Math.min((float)((millis - lastExposureUpdate) * 0.001), 1.0f)); + + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lumaAvgDownscaleTexture[lumaAvgDownscaleTexture.length - 1]); + + shader_post_exposure_final.useProgram(); + _wglUniform2f(shader_post_exposure_final.uniforms.u_inputSize2f, 1.0f / iw3, 1.0f / ih3); + + DrawUtils.drawStandardQuad2D(); + + GlStateManager.disableBlend(); + + lastExposureUpdate = millis; + } + + DeferredStateManager.checkGLError("endDrawDeferred(): DOWNSCALE AND AVERAGE LUMA"); + } + + if(config.is_rendering_bloom) { + + // ==================== BLOOM: BRIGHT PASS ==================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomBrightPassFramebuffer); + GlStateManager.viewport(0, 0, bloomBrightPassTextureW, bloomBrightPassTextureH); + boolean flag = bloomBrightPassTextureW != currentWidth || bloomBrightPassTextureH != currentHeight; + GlStateManager.setActiveTexture(GL_TEXTURE3); + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(gBufferMaterialTexture); + if(flag) { + setLinear(); + } + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(exposureBlendTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + if(flag) { + setLinear(); + } + shader_post_bloom_bright.useProgram(); + _wglUniform4f(shader_post_bloom_bright.uniforms.u_outputSize4f, bloomBrightPassTextureW, bloomBrightPassTextureH, (flag ? 2.0f : 1.0f) / currentWidth, (flag ? 2.0f : 1.0f) / currentHeight); + DrawUtils.drawStandardQuad2D(); + if(flag) { + setNearest(); + GlStateManager.setActiveTexture(GL_TEXTURE2); + setNearest(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + } + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: BRIGHT PASS"); + + // ==================== BLOOM: DOWNSCALE A ==================== // + + int bloomStageW = bloomBrightPassTextureW; + int bloomStageH = bloomBrightPassTextureH; + int texx = bloomBrightPassTexture; + if(bloomStageW > 300 && bloomStageH > 170) { + bloomStageW >>= 1; + bloomStageH >>= 1; + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomDownscaleAFramebuffer); + GlStateManager.viewport(0, 0, bloomStageW, bloomStageH); + GlStateManager.bindTexture(texx); + texx = bloomDownscaleATexture; + TextureCopyUtil.alignPixels(bloomStageW, bloomStageH, 0.5f, 0.5f); + TextureCopyUtil.blitTexture(); + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: DOWNSCALE A"); + + if(bloomStageW > 300 && bloomStageH > 170) { + + // ==================== BLOOM: DOWNSCALE B ==================== // + + bloomStageW >>= 1; + bloomStageH >>= 1; + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomDownscaleBFramebuffer); + GlStateManager.viewport(0, 0, bloomStageW, bloomStageH); + GlStateManager.bindTexture(texx); + texx = bloomDownscaleBTexture; + TextureCopyUtil.alignPixels(bloomStageW, bloomStageH, 0.5f, 0.5f); + TextureCopyUtil.blitTexture(); + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: DOWNSCALE B"); + } + } + + // ===================== BLOOM: HORZ BLUR ===================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomHBlurFramebuffer); + GlStateManager.viewport(0, 0, bloomBlurTextureW, bloomBlurTextureH); + flag = bloomBrightPassTextureW != bloomBlurTextureW || bloomBrightPassTextureH != bloomBlurTextureH; + GlStateManager.bindTexture(texx); + shader_post_bloom_blur.useProgram(); + _wglUniform2f(shader_post_bloom_blur.uniforms.u_sampleOffset2f, (flag ? 2.0f : 1.0f) / bloomStageW, 0.0f); + _wglUniform4f(shader_post_bloom_blur.uniforms.u_outputSize4f, bloomBlurTextureW, bloomBlurTextureH, (flag ? 2.0f : 1.0f) / bloomStageW, (flag ? 2.0f : 1.0f) / bloomStageH); + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: HORZ BLUR"); + + // ===================== BLOOM: VERT BLUR ===================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, bloomVBlurFramebuffer); + GlStateManager.bindTexture(bloomHBlurTexture); + shader_post_bloom_blur.useProgram(); + _wglUniform2f(shader_post_bloom_blur.uniforms.u_sampleOffset2f, 0.0f, 1.0f / bloomBlurTextureH); + _wglUniform4f(shader_post_bloom_blur.uniforms.u_outputSize4f, bloomBlurTextureW, bloomBlurTextureH, 1.0f / bloomBlurTextureW, 1.0f / bloomBlurTextureH); + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: VERT BLUR"); + + // ======================== BLOOM: MIX ======================= // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, lightingHDRFramebuffer); + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + GlStateManager.bindTexture(bloomVBlurTexture); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE, GL_ZERO, GL_ONE); + GlStateManager.setBlendConstants(0.0f, 0.0f, 0.0f, 0.25f); + TextureCopyUtil.blitTexture(); + GlStateManager.disableBlend(); + + DeferredStateManager.checkGLError("endDrawDeferred(): BLOOM: MIX"); + } + + // ==================== APPLY TONEMAPPING ==================== // + + float exposure = 1.0f; + + if(config.is_rendering_fxaa) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, tonemapOutputFramebuffer); + }else { + if(config.is_rendering_lensDistortion) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, lensDistortFramebuffer); + }else { + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + } + } + GlStateManager.viewport(0, 0, currentWidth, currentHeight); + shader_post_tonemap.useProgram(); + GlStateManager.disableBlend(); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(dither8x8Texture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(exposureBlendTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lightingHDRFramebufferColorTexture); + _wglUniform3f(shader_post_tonemap.uniforms.u_exposure3f, exposure, exposure, exposure); + _wglUniform2f(shader_post_tonemap.uniforms.u_ditherScale2f, currentWidth / 8.0f, currentHeight / 8.0f); + DrawUtils.drawStandardQuad2D(); + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(-1); + GlStateManager.setActiveTexture(GL_TEXTURE0); + + DeferredStateManager.checkGLError("endDrawDeferred(): APPLY TONEMAPPING"); + + if(config.is_rendering_fxaa) { + + // ======================= APPLY FXAA ======================== // + + if(config.is_rendering_lensDistortion) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, lensDistortFramebuffer); + }else { + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + } + shader_post_fxaa.useProgram(); + GlStateManager.bindTexture(tonemapOutputTexture); + _wglUniform2f(shader_post_fxaa.uniforms.u_screenSize2f, 1.0f / currentWidth, 1.0f / currentHeight); + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawDeferred(): APPLY FXAA"); + } + + if(config.is_rendering_lensDistortion) { + + // ================= APPLY LENS DISTORTION ================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(lensDistortTexture); + shader_post_lens_distort.useProgram(); + DrawUtils.drawStandardQuad2D(); + + DeferredStateManager.checkGLError("endDrawDeferred(): APPLY LENS DISTORTION"); + } + + // =========== BLIT WORLD DEPTH BUFFER TO OUTPUT ============= // + + if(EagRuntime.getPlatformType() == EnumPlatformType.DESKTOP) { + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL_ALWAYS); + GlStateManager.depthMask(true); + GlStateManager.bindTexture(lightingHDRFramebufferDepthTexture); + TextureCopyUtil.blitTextureDepth(); + GlStateManager.disableDepth(); + GlStateManager.depthFunc(GL_LEQUAL); + GlStateManager.depthMask(false); + }else { + _wglBindFramebuffer(_GL_READ_FRAMEBUFFER, lightingHDRFramebuffer); + _wglBindFramebuffer(_GL_DRAW_FRAMEBUFFER, null); + _wglBlitFramebuffer(0, 0, currentWidth, currentHeight, 0, 0, currentWidth, currentHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } + + DeferredStateManager.checkGLError("endDrawDeferred(): BLIT WORLD DEPTH BUFFER TO OUTPUT"); + + // ================= OPTIONAL DEBUG OUTPUT =================== // + + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + drawDebugViewIfEnabled(); + + for(int i = 0; i < lightSourceBuckets.length; ++i) { + lightSourceBuckets[i].clear(); + } + + DeferredStateManager.checkGLError("endDrawDeferred(): OPTIONAL DEBUG OUTPUT"); + } + + static void uniformMatrixHelper(IUniformGL uniform, Matrix4f matrix) { + matrixCopyBuffer.clear(); + matrix.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(uniform, false, matrixCopyBuffer); + } + + static void uniformMatrixHelper(IUniformGL uniform, Matrix3f matrix) { + matrixCopyBuffer.clear(); + matrix.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix3fv(uniform, false, matrixCopyBuffer); + } + + public static void setNearest() { + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + public static void setLinear() { + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + public PipelineShaderGBufferDebugView useDebugViewShader(int idx) { + PipelineShaderGBufferDebugView dbgShader = shader_gbuffer_debug_view[idx]; + if(dbgShader == null) { + shader_gbuffer_debug_view[idx] = dbgShader = PipelineShaderGBufferDebugView.compile(idx); + dbgShader.loadUniforms(); + } + dbgShader.useProgram(); + return dbgShader; + } + + private void drawDebugViewIfEnabled() { + if(DebugFramebufferView.debugViewShown) { + DebugFramebufferView.renderDebugView(); + } + } + + public void destroy() { + DeferredStateManager.checkGLError("Pre: destroy()"); + if(gBufferFramebuffer != null) { + _wglDeleteFramebuffer(gBufferFramebuffer); + gBufferFramebuffer = null; + } + if(gBufferDiffuseTexture != -1) { + GlStateManager.bindTexture(gBufferDiffuseTexture); + gBufferDiffuseTexture = -1; + } + if(gBufferNormalsTexture != -1) { + GlStateManager.bindTexture(gBufferNormalsTexture); + gBufferNormalsTexture = -1; + } + if(gBufferMaterialTexture != -1) { + GlStateManager.bindTexture(gBufferMaterialTexture); + gBufferMaterialTexture = -1; + } + if(gBufferDepthTexture != -1) { + GlStateManager.bindTexture(gBufferDepthTexture); + gBufferDepthTexture = -1; + } + if(sunShadowFramebuffer != null) { + _wglDeleteFramebuffer(sunShadowFramebuffer); + sunShadowFramebuffer = null; + } + if(sunShadowDepthBuffer != -1) { + GlStateManager.deleteTexture(sunShadowDepthBuffer); + sunShadowDepthBuffer = -1; + } + if(sunLightingShadowFramebuffer != null) { + _wglDeleteFramebuffer(sunLightingShadowFramebuffer); + sunLightingShadowFramebuffer = null; + } + if(sunLightingShadowTexture != -1) { + GlStateManager.deleteTexture(sunLightingShadowTexture); + sunLightingShadowTexture = -1; + } + if(ssaoGenerateFramebuffer != null) { + _wglDeleteFramebuffer(ssaoGenerateFramebuffer); + ssaoGenerateFramebuffer = null; + } + if(ssaoGenerateTexture != -1) { + GlStateManager.deleteTexture(ssaoGenerateTexture); + ssaoGenerateTexture = -1; + reprojectionTexWidth = -1; + reprojectionTexHeight = -1; + } + if(shader_ssao_generate != null) { + shader_ssao_generate.destroy(); + shader_ssao_generate = null; + } + if(ssaoNoiseTexture != -1) { + GlStateManager.deleteTexture(ssaoNoiseTexture); + ssaoNoiseTexture = -1; + } + for(int i = 0; i < 2; ++i) { + if(reprojectionControlFramebuffer[i] != null) { + _wglDeleteFramebuffer(reprojectionControlFramebuffer[i]); + reprojectionControlFramebuffer[i] = null; + } + if(reprojectionControlSSAOTexture[i] != -1) { + GlStateManager.deleteTexture(reprojectionControlSSAOTexture[i]); + reprojectionControlSSAOTexture[i] = -1; + } + if(reprojectionSSRFramebuffer[i] != null) { + _wglDeleteFramebuffer(reprojectionSSRFramebuffer[i]); + reprojectionSSRFramebuffer[i] = null; + } + if(reprojectionSSRTexture[i] != -1) { + GlStateManager.deleteTexture(reprojectionSSRTexture[i]); + reprojectionSSRTexture[i] = -1; + } + if(reprojectionSSRHitVector[i] != -1) { + GlStateManager.deleteTexture(reprojectionSSRHitVector[i]); + reprojectionSSRHitVector[i] = -1; + } + } + if(lastFrameFramebuffer != null) { + _wglDeleteFramebuffer(lastFrameFramebuffer); + lastFrameFramebuffer = null; + } + if(lastFrameColorTexture != -1) { + GlStateManager.deleteTexture(lastFrameColorTexture); + lastFrameColorTexture = -1; + } + if(lastFrameDepthTexture != -1) { + GlStateManager.deleteTexture(lastFrameDepthTexture); + lastFrameDepthTexture = -1; + } + if(gBufferQuarterFramebuffer != null) { + _wglDeleteFramebuffer(gBufferQuarterFramebuffer); + gBufferQuarterFramebuffer = null; + } + if(gBufferQuarterDepthTexture != -1) { + GlStateManager.deleteTexture(gBufferQuarterDepthTexture); + gBufferQuarterDepthTexture = -1; + } + if(lastFrameGBufferFramebuffer != null) { + _wglDeleteFramebuffer(lastFrameGBufferFramebuffer); + lastFrameGBufferFramebuffer = null; + } + if(lastFrameGBufferDepthTexture != -1) { + GlStateManager.deleteTexture(lastFrameGBufferDepthTexture); + lastFrameGBufferDepthTexture = -1; + } + if(lightingHDRFramebuffer != null) { + _wglDeleteFramebuffer(lightingHDRFramebuffer); + lightingHDRFramebuffer = null; + } + if(lightingHDRFramebufferColorTexture != -1) { + GlStateManager.deleteTexture(lightingHDRFramebufferColorTexture); + lightingHDRFramebufferColorTexture = -1; + } + if(lightingHDRFramebufferDepthTexture != -1) { + GlStateManager.deleteTexture(lightingHDRFramebufferDepthTexture); + lightingHDRFramebufferDepthTexture = -1; + } + if(handRenderFramebuffer != null) { + _wglDeleteFramebuffer(handRenderFramebuffer); + handRenderFramebuffer = null; + } + if(handRenderFramebufferDepthTexture != -1) { + GlStateManager.deleteTexture(handRenderFramebufferDepthTexture); + handRenderFramebufferDepthTexture = -1; + } + if(atmosphereHDRFramebuffer != null) { + _wglDeleteFramebuffer(atmosphereHDRFramebuffer); + atmosphereHDRFramebuffer = null; + } + if(atmosphereHDRFramebufferColorTexture != -1) { + GlStateManager.deleteTexture(atmosphereHDRFramebufferColorTexture); + atmosphereHDRFramebufferColorTexture = -1; + } + if(envMapAtmosphereFramebuffer != null) { + _wglDeleteFramebuffer(envMapAtmosphereFramebuffer); + envMapAtmosphereFramebuffer = null; + } + if(envMapAtmosphereTexture != -1) { + GlStateManager.deleteTexture(envMapAtmosphereTexture); + envMapAtmosphereTexture = -1; + } + if(envMapSkyFramebuffer != null) { + _wglDeleteFramebuffer(envMapSkyFramebuffer); + envMapSkyFramebuffer = null; + } + if(envMapSkyTexture != -1) { + GlStateManager.deleteTexture(envMapSkyTexture); + envMapSkyTexture = -1; + } + if(moonTextures != -1) { + GlStateManager.deleteTexture(moonTextures); + moonTextures = -1; + } + if(envMapFramebuffer != null) { + _wglDeleteFramebuffer(envMapFramebuffer); + envMapFramebuffer = null; + } + if(envMapColorTexture != -1) { + GlStateManager.deleteTexture(envMapColorTexture); + envMapColorTexture = -1; + } + if(envMapDepthTexture != -1) { + GlStateManager.deleteTexture(envMapDepthTexture); + envMapDepthTexture = -1; + } + if(atmosphereIrradianceFramebuffer != null) { + _wglDeleteFramebuffer(atmosphereIrradianceFramebuffer); + atmosphereIrradianceFramebuffer = null; + } + if(atmosphereIrradianceTexture != -1) { + GlStateManager.deleteTexture(atmosphereIrradianceTexture); + atmosphereIrradianceTexture = -1; + } + if(skyIrradianceFramebuffer != null) { + _wglDeleteFramebuffer(skyIrradianceFramebuffer); + skyIrradianceFramebuffer = null; + } + if(skyIrradianceTexture != -1) { + GlStateManager.deleteTexture(skyIrradianceTexture); + skyIrradianceTexture = -1; + } + if(tonemapOutputFramebuffer != null) { + _wglDeleteFramebuffer(tonemapOutputFramebuffer); + tonemapOutputFramebuffer = null; + } + if(tonemapOutputTexture != -1) { + GlStateManager.deleteTexture(tonemapOutputTexture); + tonemapOutputTexture = -1; + } + if(lensDistortFramebuffer != null) { + _wglDeleteFramebuffer(lensDistortFramebuffer); + lensDistortFramebuffer = null; + } + if(lensDistortTexture != -1) { + GlStateManager.deleteTexture(lensDistortTexture); + lensDistortTexture = -1; + } + if(lumaAvgDownscaleFramebuffers != null) { + for(int i = 0; i < lumaAvgDownscaleFramebuffers.length; ++i) { + _wglDeleteFramebuffer(lumaAvgDownscaleFramebuffers[i]); + } + lumaAvgDownscaleFramebuffers = null; + } + if(lumaAvgDownscaleTexture != null) { + for(int i = 0; i < lumaAvgDownscaleTexture.length; ++i) { + GlStateManager.deleteTexture(lumaAvgDownscaleTexture[i]); + } + lumaAvgDownscaleTexture = null; + } + if(exposureBlendFramebuffer != null) { + _wglDeleteFramebuffer(exposureBlendFramebuffer); + exposureBlendFramebuffer = null; + } + if(exposureBlendTexture != -1) { + GlStateManager.deleteTexture(exposureBlendTexture); + exposureBlendTexture = -1; + } + if(bloomBrightPassFramebuffer != null) { + _wglDeleteFramebuffer(bloomBrightPassFramebuffer); + bloomBrightPassFramebuffer = null; + } + if(bloomBrightPassTexture != -1) { + GlStateManager.bindTexture(bloomBrightPassTexture); + bloomBrightPassTexture = -1; + } + if(bloomHBlurFramebuffer != null) { + _wglDeleteFramebuffer(bloomHBlurFramebuffer); + bloomHBlurFramebuffer = null; + } + if(bloomHBlurTexture != -1) { + GlStateManager.deleteTexture(bloomHBlurTexture); + bloomHBlurTexture = -1; + } + if(bloomVBlurFramebuffer != null) { + _wglDeleteFramebuffer(bloomVBlurFramebuffer); + bloomVBlurFramebuffer = null; + } + if(bloomVBlurTexture != -1) { + GlStateManager.deleteTexture(bloomVBlurTexture); + bloomVBlurTexture = -1; + } + if(bloomDownscaleAFramebuffer != null) { + _wglDeleteFramebuffer(bloomDownscaleAFramebuffer); + bloomDownscaleAFramebuffer = null; + } + if(bloomDownscaleATexture != -1) { + GlStateManager.deleteTexture(bloomDownscaleATexture); + bloomDownscaleATexture = -1; + } + if(bloomDownscaleBFramebuffer != null) { + _wglDeleteFramebuffer(bloomDownscaleBFramebuffer); + bloomDownscaleBFramebuffer = null; + } + if(bloomDownscaleBTexture != -1) { + GlStateManager.deleteTexture(bloomDownscaleBTexture); + bloomDownscaleBTexture = -1; + } + if(sunOcclusionValueFramebuffer != null) { + _wglDeleteFramebuffer(sunOcclusionValueFramebuffer); + sunOcclusionValueFramebuffer = null; + } + if(sunOcclusionValueTexture != -1) { + GlStateManager.deleteTexture(sunOcclusionValueTexture); + sunOcclusionValueTexture = -1; + } + if(dither8x8Texture != -1) { + GlStateManager.deleteTexture(dither8x8Texture); + dither8x8Texture = -1; + } + if(shader_deferred_combine != null) { + shader_deferred_combine.destroy(); + shader_deferred_combine = null; + } + if(shader_hand_depth_mask != null) { + shader_hand_depth_mask.destroy(); + shader_hand_depth_mask = null; + } + if(brdfTexture != -1) { + GlStateManager.deleteTexture(brdfTexture); + brdfTexture = -1; + } + if(shader_lighting_sun != null) { + shader_lighting_sun.destroy(); + shader_lighting_sun = null; + } + if(shader_shadows_sun != null) { + shader_shadows_sun.destroy(); + shader_shadows_sun = null; + } + if(shader_light_shafts_sample != null) { + shader_light_shafts_sample.destroy(); + shader_light_shafts_sample = null; + } + if(skybox != null) { + skybox.destroy(); + skybox = null; + } + if(pointLightMesh != null) { + pointLightMesh.destroy(); + pointLightMesh = null; + } + if(shader_skybox_atmosphere != null) { + shader_skybox_atmosphere.destroy(); + shader_skybox_atmosphere = null; + } + if(shader_skybox_render != null) { + shader_skybox_render.destroy(); + shader_skybox_render = null; + } + if(shader_lighting_point != null) { + shader_lighting_point.destroy(); + shader_lighting_point = null; + } + if(shader_post_lens_distort != null) { + shader_post_lens_distort.destroy(); + shader_post_lens_distort = null; + } + if(shader_post_tonemap != null) { + shader_post_tonemap.destroy(); + shader_post_tonemap = null; + } + if(shader_post_exposure_avg != null) { + shader_post_exposure_avg.destroy(); + shader_post_exposure_avg = null; + } + if(shader_post_exposure_avg_luma != null) { + shader_post_exposure_avg_luma.destroy(); + shader_post_exposure_avg_luma = null; + } + if(shader_post_exposure_final != null) { + shader_post_exposure_final.destroy(); + shader_post_exposure_final = null; + } + if(shader_post_bloom_bright != null) { + shader_post_bloom_bright.destroy(); + shader_post_bloom_bright = null; + } + if(shader_post_bloom_blur != null) { + shader_post_bloom_blur.destroy(); + shader_post_bloom_blur = null; + } + if(shader_lens_sun_occlusion != null) { + shader_lens_sun_occlusion.destroy(); + shader_lens_sun_occlusion = null; + } + if(shader_realistic_water_control != null) { + shader_realistic_water_control.destroy(); + shader_realistic_water_control = null; + } + if(shader_realistic_water_noise != null) { + shader_realistic_water_noise.destroy(); + shader_realistic_water_noise = null; + } + if(shader_realistic_water_normals != null) { + shader_realistic_water_normals.destroy(); + shader_realistic_water_normals = null; + } + if(shader_post_fxaa != null) { + shader_post_fxaa.destroy(); + shader_post_fxaa = null; + } + if(shader_skybox_render_paraboloid != null) { + shader_skybox_render_paraboloid.destroy(); + shader_skybox_render_paraboloid = null; + } + if(shader_skybox_render_paraboloid_noclouds != null) { + shader_skybox_render_paraboloid_noclouds.destroy(); + shader_skybox_render_paraboloid_noclouds = null; + } + if(shader_skybox_render_end != null) { + shader_skybox_render_end.destroy(); + shader_skybox_render_end = null; + } + for(int i = 0; i < 3; ++i) { + if(shader_skybox_irradiance[i] != null) { + shader_skybox_irradiance[i].destroy(); + shader_skybox_irradiance[i] = null; + } + } + if(shader_colored_fog_linear != null) { + shader_colored_fog_linear.destroy(); + shader_colored_fog_linear = null; + } + if(shader_colored_fog_exp != null) { + shader_colored_fog_exp.destroy(); + shader_colored_fog_exp = null; + } + if(shader_atmosphere_fog != null) { + shader_atmosphere_fog.destroy(); + shader_atmosphere_fog = null; + } + if(shader_moon_render != null) { + shader_moon_render.destroy(); + shader_moon_render = null; + } + if(shader_reproject_control != null) { + shader_reproject_control.destroy(); + shader_reproject_control = null; + } + if(shader_reproject_ssr != null) { + shader_reproject_ssr.destroy(); + shader_reproject_ssr = null; + } + if(realisticWaterMaskFramebuffer != null) { + _wglDeleteFramebuffer(realisticWaterMaskFramebuffer); + realisticWaterMaskFramebuffer = null; + } + if(realisticWaterMaskTexture != -1) { + GlStateManager.deleteTexture(realisticWaterMaskTexture); + realisticWaterMaskTexture = -1; + } + if(realisticWaterDepthBuffer != -1) { + GlStateManager.deleteTexture(realisticWaterDepthBuffer); + realisticWaterDepthBuffer = -1; + } + if(realisticWaterCombinedNormalsFramebuffer != null) { + _wglDeleteFramebuffer(realisticWaterCombinedNormalsFramebuffer); + realisticWaterCombinedNormalsFramebuffer = null; + } + if(realisticWaterCombinedNormalsTexture != -1) { + GlStateManager.deleteTexture(realisticWaterCombinedNormalsTexture); + realisticWaterCombinedNormalsTexture = -1; + } + if(realisticWaterRefractionTexture != -1) { + GlStateManager.deleteTexture(realisticWaterRefractionTexture); + realisticWaterRefractionTexture = -1; + } + if(realisticWaterControlFramebuffer != null) { + _wglDeleteFramebuffer(realisticWaterControlFramebuffer); + realisticWaterControlFramebuffer = null; + } + for(int i = 0; i < 2; ++i) { + if(realisticWaterSSRFramebuffer[i] != null) { + _wglDeleteFramebuffer(realisticWaterSSRFramebuffer[i]); + realisticWaterSSRFramebuffer[i] = null; + } + if(realisticWaterControlReflectionTexture[i] != -1) { + GlStateManager.deleteTexture(realisticWaterControlReflectionTexture[i]); + realisticWaterControlReflectionTexture[i] = -1; + } + if(realisticWaterControlHitVectorTexture[i] != -1) { + GlStateManager.deleteTexture(realisticWaterControlHitVectorTexture[i]); + realisticWaterControlHitVectorTexture[i] = -1; + } + } + if(realisticWaterNormalMapFramebuffer != null) { + _wglDeleteFramebuffer(realisticWaterNormalMapFramebuffer); + realisticWaterNormalMapFramebuffer = null; + } + if(realisticWaterNormalMapTexture != -1) { + GlStateManager.deleteTexture(realisticWaterNormalMapTexture); + realisticWaterNormalMapTexture = -1; + } + if(realisticWaterDisplacementMapFramebuffer != null) { + _wglDeleteFramebuffer(realisticWaterDisplacementMapFramebuffer); + realisticWaterDisplacementMapFramebuffer = null; + } + if(realisticWaterDisplacementMapTexture != -1) { + GlStateManager.deleteTexture(realisticWaterDisplacementMapTexture); + realisticWaterDisplacementMapTexture = -1; + } + if(realisticWaterNoiseMap != -1) { + GlStateManager.deleteTexture(realisticWaterNoiseMap); + realisticWaterNoiseMap = -1; + } + if(buffer_chunkLightingData != null) { + _wglDeleteBuffers(buffer_chunkLightingData); + buffer_chunkLightingData = null; + } + if(buffer_worldLightingData != null) { + _wglDeleteBuffers(buffer_worldLightingData); + buffer_worldLightingData = null; + } + if(worldLightingDataCopyBuffer != null) { + EagRuntime.freeByteBuffer(worldLightingDataCopyBuffer); + worldLightingDataCopyBuffer = null; + } + if(chunkLightingDataCopyBuffer != null) { + EagRuntime.freeByteBuffer(chunkLightingDataCopyBuffer); + chunkLightingDataCopyBuffer = null; + } + for(int i = 0; i < lightSourceBuckets.length; ++i) { + lightSourceBuckets[i].clear(); + } + currentLightSourceBucket = null; + currentBoundLightSourceBucket = null; + isChunkLightingEnabled = false; + for(int i = 0; i < shader_gbuffer_debug_view.length; ++i) { + if(shader_gbuffer_debug_view[i] != null) { + shader_gbuffer_debug_view[i].destroy(); + shader_gbuffer_debug_view[i] = null; + } + } + gbufferEffectRenderer.destroy(); + forwardEffectRenderer.destroy(); + DynamicLightManager.destroyAll(); + LensFlareMeshRenderer.destroy(); + CloudRenderWorker.destroy(); + FixedFunctionPipeline.loadExtensionPipeline(null); + DeferredStateManager.checkGLError("Post: destroy()"); + } + + public void resetContextStateAfterException() { + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + NameTagRenderer.doRenderNameTags = false; + DeferredStateManager.disableAll(); + DeferredStateManager.setDefaultMaterialConstants(); + GlStateManager.disableExtensionPipeline(); + GlStateManager.disableBlend(); + GlStateManager.disableLighting(); + GlStateManager.disableShaderBlendAdd(); + GlStateManager.disableTexGen(); + GlStateManager.globalEnableBlend(); + DynamicLightManager.setIsRenderingLights(false); + GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f); + GlStateManager.shadeModel(GL_SMOOTH); + GlStateManager.clearDepth(1.0f); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL_LEQUAL); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL_GREATER, 0.1F); + GlStateManager.cullFace(GL_BACK); + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.loadIdentity(); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.matrixMode(GL_TEXTURE); + GlStateManager.loadIdentity(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.loadIdentity(); + if(config.is_rendering_shadowsSun_clamped > 0 && config.is_rendering_shadowsSmoothed) { + GlStateManager.bindTexture(sunShadowDepthBuffer); + _wglTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_COMPARE_MODE, _GL_COMPARE_REF_TO_TEXTURE); + setNearest(); + } + } + + public static final boolean isSupported() { + return EaglercraftGPU.checkHasHDRFramebufferSupport(); + } + + public static final String getReasonUnsupported() { + if(!EaglercraftGPU.checkHasHDRFramebufferSupport()) { + return I18n.format("shaders.gui.unsupported.reason.hdrFramebuffer"); + }else { + return null; + } + } + + public static final void renderSuspended() { + _wglBindFramebuffer(_GL_FRAMEBUFFER, null); + GlStateManager.globalEnableBlend(); + Minecraft mc = Minecraft.getMinecraft(); + GlStateManager.viewport(0, 0, mc.displayWidth, mc.displayHeight); + GlStateManager.clearColor(0.5f, 0.0f, 0.0f, 1.0f); + GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.pushMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.pushMatrix(); + ScaledResolution scaledresolution = new ScaledResolution(mc); + int w = scaledresolution.getScaledWidth(); + mc.entityRenderer.setupOverlayRendering(); + GlStateManager.enableAlpha(); + GlStateManager.pushMatrix(); + String str = "Shaders Suspended"; + GlStateManager.translate((w - mc.fontRendererObj.getStringWidth(str) * 2) * 0.5f, 45.0f, 0.0f); + GlStateManager.scale(2.0f, 2.0f, 2.0f); + mc.fontRendererObj.drawStringWithShadow(str, 0, 0, 0xFFFFFF); + GlStateManager.popMatrix(); + GlStateManager.pushMatrix(); + str = "(check console)"; + GlStateManager.translate((w - mc.fontRendererObj.getStringWidth(str) * 1.5) * 0.5f, 80.0f, 0.0f); + GlStateManager.scale(1.5f, 1.5f, 1.5f); + mc.fontRendererObj.drawStringWithShadow(str, 0, 0, 0xFFFFFF); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.popMatrix(); + EagUtils.sleep(10l); + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ExtGLEnums.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ExtGLEnums.java new file mode 100644 index 0000000..da1bdd2 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ExtGLEnums.java @@ -0,0 +1,40 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ExtGLEnums { + + public static final int _GL_FRAMEBUFFER = 0x8D40; + public static final int _GL_READ_FRAMEBUFFER = 0x8CA8; + public static final int _GL_DRAW_FRAMEBUFFER = 0x8CA9; + public static final int _GL_RENDERBUFFER = 0x8D41; + public static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0; + public static final int _GL_COLOR_ATTACHMENT1 = 0x8CE1; + public static final int _GL_COLOR_ATTACHMENT2 = 0x8CE2; + public static final int _GL_COLOR_ATTACHMENT3 = 0x8CE3; + public static final int _GL_DEPTH_ATTACHMENT = 0x8D00; + public static final int _GL_DEPTH_COMPONENT = 0x1902; + public static final int _GL_DEPTH_COMPONENT24 = 0x81A6; + public static final int _GL_DEPTH_COMPONENT32F = 0x8CAC; + public static final int _GL_R8 = 0x8229; + public static final int _GL_RG = 0x8227; + public static final int _GL_RG8 = 0x822B; + public static final int _GL_RGB16F = 0x881B; + public static final int _GL_HALF_FLOAT = 0x140B; + public static final int _GL_UNIFORM_BUFFER = 0x8A11; + public static final int _GL_TEXTURE_COMPARE_MODE = 0x884C; + public static final int _GL_TEXTURE_COMPARE_FUNC = 0x884D; + public static final int _GL_COMPARE_REF_TO_TEXTURE = 0x884E; + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardAcceleratedEffectRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardAcceleratedEffectRenderer.java new file mode 100644 index 0000000..254f072 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardAcceleratedEffectRenderer.java @@ -0,0 +1,218 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderAccelParticleForward; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderAccelParticleGBuffer; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.MathHelper; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ForwardAcceleratedEffectRenderer extends AbstractAcceleratedEffectRenderer { + + private static final Logger logger = LogManager.getLogger("ForwardAcceleratedEffectRenderer"); + + private ByteBuffer particleBuffer = null; + private int particleCount = 0; + private boolean particlesHasOverflowed = false; + + private static final int BYTES_PER_PARTICLE = 24; + private static final int PARTICLE_LIMIT = 5461; + + private PipelineShaderAccelParticleForward shaderProgram = null; + + private IBufferArrayGL vertexArray = null; + private IBufferGL vertexBuffer = null; + + private IBufferGL instancesBuffer = null; + + private static final Matrix4f tmpMatrix = new Matrix4f(); + + private float f1; + private float f2; + private float f3; + private float f4; + private float f5; + + public static boolean isMaterialNormalTexture = false; + + public void initialize(boolean dynamicLights, int sunShadows) { + destroy(); + + shaderProgram = PipelineShaderAccelParticleForward.compile(dynamicLights, sunShadows); + shaderProgram.loadUniforms(); + + particleBuffer = EagRuntime.allocateByteBuffer(PARTICLE_LIMIT * BYTES_PER_PARTICLE); + + vertexArray = _wglGenVertexArrays(); + vertexBuffer = _wglGenBuffers(); + instancesBuffer = _wglGenBuffers(); + + FloatBuffer verts = EagRuntime.allocateFloatBuffer(12); + verts.put(new float[] { + -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f + }); + verts.flip(); + + EaglercraftGPU.bindGLBufferArray(vertexArray); + + EaglercraftGPU.bindGLArrayBuffer(vertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW); + + EagRuntime.freeFloatBuffer(verts); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0); + _wglVertexAttribDivisor(0, 0); + + EaglercraftGPU.bindGLArrayBuffer(instancesBuffer); + _wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STATIC_DRAW); + + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0); + _wglVertexAttribDivisor(1, 1); + + _wglEnableVertexAttribArray(2); + _wglVertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12); + _wglVertexAttribDivisor(2, 1); + + _wglEnableVertexAttribArray(3); + _wglVertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16); + _wglVertexAttribDivisor(3, 1); + + _wglEnableVertexAttribArray(4); + _wglVertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18); + _wglVertexAttribDivisor(4, 1); + + _wglEnableVertexAttribArray(5); + _wglVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20); + _wglVertexAttribDivisor(5, 1); + + } + + @Override + public void draw(float texCoordWidth, float texCoordHeight) { + if(particleCount == 0) { + return; + } + + shaderProgram.useProgram(); + + _wglUniform3f(shaderProgram.uniforms.u_texCoordSize2f_particleSize1f, texCoordWidth, texCoordHeight, 0.0625f); + _wglUniform4f(shaderProgram.uniforms.u_transformParam_1_2_3_4_f, f1, f5, f2, f3); + _wglUniform1f(shaderProgram.uniforms.u_transformParam_5_f, f4); + if(isMaterialNormalTexture) { + _wglUniform2f(shaderProgram.uniforms.u_textureYScale2f, 0.5f, 0.5f); + }else { + _wglUniform2f(shaderProgram.uniforms.u_textureYScale2f, 1.0f, 0.0f); + } + + EaglerDeferredPipeline.uniformMatrixHelper(shaderProgram.uniforms.u_modelViewMatrix4f, DeferredStateManager.passViewMatrix); + EaglerDeferredPipeline.uniformMatrixHelper(shaderProgram.uniforms.u_projectionMatrix4f, DeferredStateManager.passProjMatrix); + EaglerDeferredPipeline.uniformMatrixHelper(shaderProgram.uniforms.u_inverseViewMatrix4f, DeferredStateManager.passInverseViewMatrix); + + EaglercraftGPU.bindGLArrayBuffer(instancesBuffer); + EaglercraftGPU.bindGLBufferArray(vertexArray); + + int p = particleBuffer.position(); + int l = particleBuffer.limit(); + + particleBuffer.flip(); + _wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer); + + particleBuffer.position(p); + particleBuffer.limit(l); + + _wglDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount); + } + + @Override + public void begin(float partialTicks) { + this.partialTicks = partialTicks; + + particleBuffer.clear(); + particleCount = 0; + particlesHasOverflowed = false; + + Entity et = Minecraft.getMinecraft().getRenderViewEntity(); + if(et != null) { + f1 = MathHelper.cos(et.rotationYaw * 0.017453292F); + f2 = MathHelper.sin(et.rotationYaw * 0.017453292F); + f3 = -f2 * MathHelper.sin(et.rotationPitch * 0.017453292F); + f4 = f1 * MathHelper.sin(et.rotationPitch * 0.017453292F); + f5 = MathHelper.cos(et.rotationPitch * 0.017453292F); + } + } + + @Override + public void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY, + int lightMapData, int texSize, float particleSize, int rgba) { + if(particlesHasOverflowed) { + return; + } + if(particleCount >= PARTICLE_LIMIT) { + particlesHasOverflowed = true; + logger.error("Particle buffer has overflowed! Exceeded {} particles, no more particles will be rendered.", PARTICLE_LIMIT); + return; + } + ++particleCount; + ByteBuffer buf = particleBuffer; + buf.putFloat(posX); + buf.putFloat(posY); + buf.putFloat(posZ); + buf.putShort((short)particleIndexX); + buf.putShort((short)particleIndexY); + buf.put((byte)(lightMapData & 0xFF)); + buf.put((byte)((lightMapData >> 16) & 0xFF)); + buf.put((byte)(particleSize * 16.0f)); + buf.put((byte)texSize); + buf.putInt(rgba); + } + + public void destroy() { + if(particleBuffer != null) { + EagRuntime.freeByteBuffer(particleBuffer); + particleBuffer = null; + } + if(shaderProgram != null) { + shaderProgram.destroy(); + shaderProgram = null; + } + if(vertexArray != null) { + _wglDeleteVertexArrays(vertexArray); + vertexArray = null; + } + if(vertexBuffer != null) { + _wglDeleteBuffers(vertexBuffer); + vertexBuffer = null; + } + if(instancesBuffer != null) { + _wglDeleteBuffers(instancesBuffer); + instancesBuffer = null; + } + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardRenderCallbackHandler.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardRenderCallbackHandler.java new file mode 100644 index 0000000..c5c69df --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ForwardRenderCallbackHandler.java @@ -0,0 +1,52 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ForwardRenderCallbackHandler { + + public final List renderPassList = new ArrayList(1024); + + public void push(ShadersRenderPassFuture f) { + renderPassList.add(f); + } + + public void reset() { + renderPassList.clear(); + } + + public void sort(float x, float y, float z) { + if(renderPassList.size() == 0) return; + ShadersRenderPassFuture rp; + float dx, dy, dz; + for(int i = 0, l = renderPassList.size(); i < l; ++i) { + rp = renderPassList.get(i); + dx = rp.getX() - x; + dy = rp.getY() - y; + dz = rp.getZ() - z; + rp.tmpValue()[0] = dx * dx + dy * dy + dz * dz; + } + Collections.sort(renderPassList, new Comparator() { + @Override + public int compare(ShadersRenderPassFuture o1, ShadersRenderPassFuture o2) { + float a = o1.tmpValue()[0], b = o2.tmpValue()[0]; + return a < b ? 1 : (a > b ? -1 : 0); + } + }); + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferAcceleratedEffectRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferAcceleratedEffectRenderer.java new file mode 100644 index 0000000..6bb487d --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferAcceleratedEffectRenderer.java @@ -0,0 +1,216 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderAccelParticleGBuffer; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.MathHelper; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GBufferAcceleratedEffectRenderer extends AbstractAcceleratedEffectRenderer { + + private static final Logger logger = LogManager.getLogger("GBufferAcceleratedEffectRenderer"); + + private ByteBuffer particleBuffer = null; + private int particleCount = 0; + private boolean particlesHasOverflowed = false; + + private static final int BYTES_PER_PARTICLE = 24; + private static final int PARTICLE_LIMIT = 5461; + + private PipelineShaderAccelParticleGBuffer shaderProgram = null; + + private IBufferArrayGL vertexArray = null; + private IBufferGL vertexBuffer = null; + + private IBufferGL instancesBuffer = null; + + private static final Matrix4f tmpMatrix = new Matrix4f(); + + private float f1; + private float f2; + private float f3; + private float f4; + private float f5; + + public static boolean isMaterialNormalTexture = false; + + public void initialize() { + destroy(); + + shaderProgram = PipelineShaderAccelParticleGBuffer.compile(); + shaderProgram.loadUniforms(); + + particleBuffer = EagRuntime.allocateByteBuffer(PARTICLE_LIMIT * BYTES_PER_PARTICLE); + + vertexArray = _wglGenVertexArrays(); + vertexBuffer = _wglGenBuffers(); + instancesBuffer = _wglGenBuffers(); + + FloatBuffer verts = EagRuntime.allocateFloatBuffer(12); + verts.put(new float[] { + -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f + }); + verts.flip(); + + EaglercraftGPU.bindGLBufferArray(vertexArray); + + EaglercraftGPU.bindGLArrayBuffer(vertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW); + + EagRuntime.freeFloatBuffer(verts); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0); + _wglVertexAttribDivisor(0, 0); + + EaglercraftGPU.bindGLArrayBuffer(instancesBuffer); + _wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STATIC_DRAW); + + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0); + _wglVertexAttribDivisor(1, 1); + + _wglEnableVertexAttribArray(2); + _wglVertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12); + _wglVertexAttribDivisor(2, 1); + + _wglEnableVertexAttribArray(3); + _wglVertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16); + _wglVertexAttribDivisor(3, 1); + + _wglEnableVertexAttribArray(4); + _wglVertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18); + _wglVertexAttribDivisor(4, 1); + + _wglEnableVertexAttribArray(5); + _wglVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20); + _wglVertexAttribDivisor(5, 1); + + } + + @Override + public void draw(float texCoordWidth, float texCoordHeight) { + if(particleCount == 0) { + return; + } + + shaderProgram.useProgram(); + + _wglUniform3f(shaderProgram.uniforms.u_texCoordSize2f_particleSize1f, texCoordWidth, texCoordHeight, 0.0625f); + _wglUniform4f(shaderProgram.uniforms.u_transformParam_1_2_3_4_f, f1, f5, f2, f3); + _wglUniform1f(shaderProgram.uniforms.u_transformParam_5_f, f4); + if(isMaterialNormalTexture) { + _wglUniform2f(shaderProgram.uniforms.u_textureYScale2f, 0.5f, 0.5f); + }else { + _wglUniform2f(shaderProgram.uniforms.u_textureYScale2f, 1.0f, 0.0f); + } + + Matrix4f.mul(DeferredStateManager.passProjMatrix, DeferredStateManager.passViewMatrix, tmpMatrix); + EaglerDeferredPipeline.uniformMatrixHelper(shaderProgram.uniforms.u_matrixTransform, tmpMatrix); + + EaglercraftGPU.bindGLArrayBuffer(instancesBuffer); + EaglercraftGPU.bindGLBufferArray(vertexArray); + + int p = particleBuffer.position(); + int l = particleBuffer.limit(); + + particleBuffer.flip(); + _wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer); + + particleBuffer.position(p); + particleBuffer.limit(l); + + _wglDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount); + } + + @Override + public void begin(float partialTicks) { + this.partialTicks = partialTicks; + + particleBuffer.clear(); + particleCount = 0; + particlesHasOverflowed = false; + + Entity et = Minecraft.getMinecraft().getRenderViewEntity(); + if(et != null) { + f1 = MathHelper.cos(et.rotationYaw * 0.017453292F); + f2 = MathHelper.sin(et.rotationYaw * 0.017453292F); + f3 = -f2 * MathHelper.sin(et.rotationPitch * 0.017453292F); + f4 = f1 * MathHelper.sin(et.rotationPitch * 0.017453292F); + f5 = MathHelper.cos(et.rotationPitch * 0.017453292F); + } + } + + @Override + public void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY, + int lightMapData, int texSize, float particleSize, int rgba) { + if(particlesHasOverflowed) { + return; + } + if(particleCount >= PARTICLE_LIMIT) { + particlesHasOverflowed = true; + logger.error("Particle buffer has overflowed! Exceeded {} particles, no more particles will be rendered.", PARTICLE_LIMIT); + return; + } + ++particleCount; + ByteBuffer buf = particleBuffer; + buf.putFloat(posX); + buf.putFloat(posY); + buf.putFloat(posZ); + buf.putShort((short)particleIndexX); + buf.putShort((short)particleIndexY); + buf.put((byte)(lightMapData & 0xFF)); + buf.put((byte)((lightMapData >> 16) & 0xFF)); + buf.put((byte)(particleSize * 16.0f)); + buf.put((byte)texSize); + buf.putInt(rgba); + } + + public void destroy() { + if(particleBuffer != null) { + EagRuntime.freeByteBuffer(particleBuffer); + particleBuffer = null; + } + if(shaderProgram != null) { + shaderProgram.destroy(); + shaderProgram = null; + } + if(vertexArray != null) { + _wglDeleteVertexArrays(vertexArray); + vertexArray = null; + } + if(vertexBuffer != null) { + _wglDeleteBuffers(vertexBuffer); + vertexBuffer = null; + } + if(instancesBuffer != null) { + _wglDeleteBuffers(instancesBuffer); + instancesBuffer = null; + } + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineCompiler.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineCompiler.java new file mode 100644 index 0000000..0f3a476 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineCompiler.java @@ -0,0 +1,389 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionPipeline; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.IExtPipelineCompiler; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.GBufferExtPipelineShader; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GLAllocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GBufferPipelineCompiler implements IExtPipelineCompiler { + + private static final Logger logger = LogManager.getLogger("DeferredGBufferPipelineCompiler"); + + public static final int STATE_MATERIAL_TEXTURE = 1; + public static final int STATE_FORWARD_RENDER = 2; + public static final int STATE_PARABOLOID_RENDER = 4; + public static final int STATE_SHADOW_RENDER = 8; + public static final int STATE_CLIP_PLANE = 16; + public static final int STATE_WAVING_BLOCKS = 32; + public static final int STATE_REALISTIC_WATER_MASK = 64; + public static final int STATE_REALISTIC_WATER_RENDER = 128; + public static final int STATE_GLASS_HIGHLIGHTS = 256; + + private static FloatBuffer matrixCopyBuffer = null; + private static final Matrix4f tmpMatrix = new Matrix4f(); + + @Override + public String[] getShaderSource(int stateCoreBits, int stateExtBits, Object[] userPointer) { + if(matrixCopyBuffer == null) { + matrixCopyBuffer = GLAllocation.createDirectFloatBuffer(16); + } + userPointer[0] = new GBufferPipelineProgramInstance(stateCoreBits, stateExtBits); + EaglerDeferredConfig conf = Minecraft.getMinecraft().gameSettings.deferredShaderConf; + StringBuilder macros = new StringBuilder(); + if((stateExtBits & STATE_SHADOW_RENDER) != 0) { + if((stateExtBits & STATE_CLIP_PLANE) != 0) { + macros.append("#define STATE_CLIP_PLANE\n"); + } + if((stateExtBits & STATE_WAVING_BLOCKS) != 0) { + macros.append("#define COMPILE_STATE_WAVING_BLOCKS\n"); + } + if((stateExtBits & STATE_FORWARD_RENDER) != 0) { + macros.append("#define COMPILE_COLORED_SHADOWS\n"); + } + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.deferred_shadow_vsh); + logger.info(" - {}", ShaderSource.deferred_shadow_fsh); + return new String[] { macros.toString() + ShaderSource.getSourceFor(ShaderSource.deferred_shadow_vsh), + macros.toString() + ShaderSource.getSourceFor(ShaderSource.deferred_shadow_fsh) }; + }else if((stateExtBits & STATE_REALISTIC_WATER_RENDER) != 0) { + if(conf.is_rendering_dynamicLights) { + macros.append("#define COMPILE_DYNAMIC_LIGHTS\n"); + } + if(conf.is_rendering_shadowsSun_clamped > 0) { + int lods = conf.is_rendering_shadowsSun_clamped - 1; + if(lods > 2) { + lods = 2; + } + macros.append("#define COMPILE_SUN_SHADOW_LOD" + lods + "\n"); + if(conf.is_rendering_shadowsSmoothed) { + macros.append("#define COMPILE_SUN_SHADOW_SMOOTH\n"); + } + } + if(conf.is_rendering_lightShafts) { + macros.append("#define COMPILE_FOG_LIGHT_SHAFTS\n"); + } + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.realistic_water_render_vsh); + logger.info(" - {}", ShaderSource.realistic_water_render_fsh); + return new String[] { macros.toString() + ShaderSource.getSourceFor(ShaderSource.realistic_water_render_vsh), + macros.toString() + ShaderSource.getSourceFor(ShaderSource.realistic_water_render_fsh) }; + }else if((stateExtBits & STATE_GLASS_HIGHLIGHTS) != 0) { + if(conf.is_rendering_dynamicLights) { + macros.append("#define COMPILE_DYNAMIC_LIGHTS\n"); + } + if(conf.is_rendering_shadowsSun_clamped > 0) { + int lods = conf.is_rendering_shadowsSun_clamped - 1; + if(lods > 2) { + lods = 2; + } + macros.append("#define COMPILE_SUN_SHADOW_LOD" + lods + "\n"); + if(conf.is_rendering_shadowsSmoothed) { + macros.append("#define COMPILE_SUN_SHADOW_SMOOTH\n"); + } + } + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.forward_glass_highlights_vsh); + logger.info(" - {}", ShaderSource.forward_glass_highlights_fsh); + return new String[] { macros.toString() + ShaderSource.getSourceFor(ShaderSource.forward_glass_highlights_vsh), + macros.toString() + ShaderSource.getSourceFor(ShaderSource.forward_glass_highlights_fsh) }; + }else if((stateExtBits & (STATE_FORWARD_RENDER | STATE_PARABOLOID_RENDER)) != 0) { + if((stateExtBits & STATE_MATERIAL_TEXTURE) != 0) { + macros.append("#define COMPILE_NORMAL_MATERIAL_TEXTURE\n"); + } + if((stateExtBits & STATE_CLIP_PLANE) != 0) { + macros.append("#define STATE_CLIP_PLANE\n"); + } + if((stateExtBits & STATE_PARABOLOID_RENDER) != 0) { + macros.append("#define COMPILE_PARABOLOID\n"); + }else { + if(conf.is_rendering_useEnvMap) { + macros.append("#define COMPILE_PARABOLOID_ENV_MAP\n"); + } + } + if(conf.is_rendering_dynamicLights) { + macros.append("#define COMPILE_DYNAMIC_LIGHTS\n"); + } + if(conf.is_rendering_shadowsSun_clamped > 0) { + int lods = conf.is_rendering_shadowsSun_clamped - 1; + if(lods > 2) { + lods = 2; + } + macros.append("#define COMPILE_SUN_SHADOW_LOD" + lods + "\n"); + if(conf.is_rendering_shadowsSmoothed) { + macros.append("#define COMPILE_SUN_SHADOW_SMOOTH\n"); + } + } + if(conf.is_rendering_lightShafts) { + macros.append("#define COMPILE_FOG_LIGHT_SHAFTS\n"); + } + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.forward_core_vsh); + logger.info(" - {}", ShaderSource.forward_core_fsh); + return new String[] { macros.toString() + ShaderSource.getSourceFor(ShaderSource.forward_core_vsh), + macros.toString() + ShaderSource.getSourceFor(ShaderSource.forward_core_fsh) }; + }else if((stateExtBits & STATE_REALISTIC_WATER_MASK) != 0) { + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.realistic_water_mask_vsh); + logger.info(" - {}", ShaderSource.realistic_water_mask_fsh); + return new String[] { ShaderSource.getSourceFor(ShaderSource.realistic_water_mask_vsh), + ShaderSource.getSourceFor(ShaderSource.realistic_water_mask_fsh) }; + }else { + if((stateExtBits & STATE_MATERIAL_TEXTURE) != 0) { + macros.append("#define COMPILE_NORMAL_MATERIAL_TEXTURE\n"); + } + if((stateExtBits & STATE_CLIP_PLANE) != 0) { + macros.append("#define COMPILE_STATE_CLIP_PLANE\n"); + } + if((stateExtBits & STATE_WAVING_BLOCKS) != 0) { + macros.append("#define COMPILE_STATE_WAVING_BLOCKS\n"); + } + + logger.info("Compiling program for core state: {}, ext state: {}", visualizeBits(stateCoreBits), visualizeBits(stateExtBits)); + logger.info(" - {}", ShaderSource.deferred_core_vsh); + logger.info(" - {}", ShaderSource.deferred_core_gbuffer_fsh); + + return new String[] { macros.toString() + ShaderSource.getSourceFor(ShaderSource.deferred_core_vsh), + macros.toString() + ShaderSource.getSourceFor(ShaderSource.deferred_core_gbuffer_fsh) }; + } + } + + @Override + public int getExtensionStatesCount() { + return 9; + } + + @Override + public int getCoreStateMask(int stateExtBits) { + return DeferredStateManager.enableShadowRender + ? (FixedFunctionShader.FixedFunctionState.STATE_ENABLE_TEXTURE2D + | FixedFunctionShader.FixedFunctionState.STATE_ENABLE_ALPHA_TEST + | (DeferredStateManager.enableDrawWavingBlocks + ? FixedFunctionShader.FixedFunctionState.STATE_ENABLE_LIGHTMAP + : 0)) + : ((DeferredStateManager.enableDrawRealisticWaterMask) ? FixedFunctionShader.FixedFunctionState.STATE_ENABLE_LIGHTMAP + : (DeferredStateManager.enableDrawRealisticWaterRender + ? (FixedFunctionShader.FixedFunctionState.STATE_ENABLE_LIGHTMAP + | FixedFunctionShader.FixedFunctionState.STATE_ENABLE_TEXTURE2D) + : (2943))); + } + + @Override + public int getCurrentExtensionStateBits(int stateCoreBits) { + return ((DeferredStateManager.enableMaterialMapTexture && !DeferredStateManager.enableShadowRender + && !DeferredStateManager.enableDrawRealisticWaterMask + && !DeferredStateManager.enableDrawRealisticWaterRender) ? STATE_MATERIAL_TEXTURE : 0) | + (DeferredStateManager.enableForwardRender ? STATE_FORWARD_RENDER : 0) | + (DeferredStateManager.enableParaboloidRender ? STATE_PARABOLOID_RENDER : 0) | + (DeferredStateManager.enableShadowRender ? STATE_SHADOW_RENDER : 0) | + (DeferredStateManager.enableClipPlane ? STATE_CLIP_PLANE : 0) | + (DeferredStateManager.enableDrawWavingBlocks ? STATE_WAVING_BLOCKS : 0) | + (DeferredStateManager.enableDrawRealisticWaterMask ? STATE_REALISTIC_WATER_MASK : 0) | + (DeferredStateManager.enableDrawRealisticWaterRender ? STATE_REALISTIC_WATER_RENDER : 0) | + (DeferredStateManager.enableDrawGlassHighlightsRender ? STATE_GLASS_HIGHLIGHTS : 0); + } + + @Override + public void initializeNewShader(IProgramGL compiledProg, int stateCoreBits, int stateExtBits, + Object[] userPointer) { + EaglercraftGPU.bindGLShaderProgram(compiledProg); + GBufferExtPipelineShader newShader = new GBufferExtPipelineShader(compiledProg, stateCoreBits, stateExtBits); + ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject = newShader; + newShader.loadUniforms(); + } + + @Override + public void updatePipeline(IProgramGL compiledProg, int stateCoreBits, int stateExtBits, Object[] userPointer) { + int serial; + GBufferExtPipelineShader.Uniforms uniforms = null; + if((stateExtBits & STATE_MATERIAL_TEXTURE) == 0) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + serial = DeferredStateManager.materialConstantsSerial; + if(uniforms.materialConstantsSerial != serial) { + uniforms.materialConstantsSerial = serial; + float roughness = 1.0f - DeferredStateManager.materialConstantsRoughness; + float metalness = DeferredStateManager.materialConstantsMetalness; + float emission = DeferredStateManager.materialConstantsEmission; + if(uniforms.materialConstantsRoughness != roughness || uniforms.materialConstantsMetalness != metalness + || uniforms.materialConstantsEmission != emission) { + uniforms.materialConstantsRoughness = roughness; + uniforms.materialConstantsMetalness = metalness; + uniforms.materialConstantsEmission = emission; + _wglUniform3f(uniforms.u_materialConstants3f, roughness, metalness, emission); + } + } + } + if((stateCoreBits & FixedFunctionShader.FixedFunctionState.STATE_HAS_ATTRIB_NORMAL) == 0) { + if(uniforms == null) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + } + int blockId = DeferredStateManager.constantBlock; + if(uniforms.constantBlock != blockId) { + uniforms.constantBlock = blockId; + _wglUniform1f(uniforms.u_blockConstant1f, (blockId - 127) * 0.007874f); + } + } + if((stateExtBits & STATE_CLIP_PLANE) != 0) { + if(uniforms == null) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + } + float clipPlaneYState = DeferredStateManager.clipPlaneY; + if(uniforms.clipPlaneY != clipPlaneYState) { + uniforms.clipPlaneY = clipPlaneYState; + _wglUniform1f(uniforms.u_clipPlaneY1f, clipPlaneYState); + } + } + if((stateExtBits & STATE_WAVING_BLOCKS) != 0) { + if(uniforms == null) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + } + serial = DeferredStateManager.passViewMatrixSerial; + boolean modelDirty = false; + if(serial != uniforms.viewMatrixSerial) { + uniforms.viewMatrixSerial = serial; + matrixCopyBuffer.clear(); + DeferredStateManager.passViewMatrix.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(uniforms.u_viewMatrix4f, false, matrixCopyBuffer); + modelDirty = true; + } + serial = GlStateManager.getModelViewSerial(); + if(uniforms.modelMatrixSerial != serial || modelDirty) { + uniforms.modelMatrixSerial = serial; + Matrix4f mat = GlStateManager.getModelViewReference(); + matrixCopyBuffer.clear(); + if(!DeferredStateManager.isShadowPassMatrixLoaded) { + Matrix4f.mul(DeferredStateManager.passInverseViewMatrix, mat, tmpMatrix); + tmpMatrix.store(matrixCopyBuffer); + }else { + mat.store(matrixCopyBuffer); + } + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(uniforms.u_modelMatrix4f, false, matrixCopyBuffer); + } + serial = DeferredStateManager.wavingBlockOffsetSerial; + if(serial != uniforms.wavingBlockOffsetSerial) { + uniforms.wavingBlockOffsetSerial = serial; + float x = DeferredStateManager.wavingBlockOffsetX; + float y = DeferredStateManager.wavingBlockOffsetY; + float z = DeferredStateManager.wavingBlockOffsetZ; + if(uniforms.wavingBlockOffsetX != x || uniforms.wavingBlockOffsetY != y || uniforms.wavingBlockOffsetZ != z) { + uniforms.wavingBlockOffsetX = x; + uniforms.wavingBlockOffsetY = y; + uniforms.wavingBlockOffsetZ = z; + _wglUniform3f(uniforms.u_wavingBlockOffset3f, x, y, z); + } + } + serial = DeferredStateManager.wavingBlockParamSerial; + if(serial != uniforms.wavingBlockParamSerial) { + uniforms.wavingBlockParamSerial = serial; + float x = DeferredStateManager.wavingBlockParamX; + float y = DeferredStateManager.wavingBlockParamY; + float z = DeferredStateManager.wavingBlockParamZ; + float w = DeferredStateManager.wavingBlockParamW; + if(uniforms.wavingBlockParamX != x || uniforms.wavingBlockParamY != y || uniforms.wavingBlockParamZ != z || uniforms.wavingBlockParamW != w) { + uniforms.wavingBlockParamX = x; + uniforms.wavingBlockParamY = y; + uniforms.wavingBlockParamZ = z; + uniforms.wavingBlockParamW = w; + _wglUniform4f(uniforms.u_wavingBlockParam4f, x, y, z, w); + } + } + } + if((stateExtBits & STATE_FORWARD_RENDER) != 0) { + if(uniforms == null) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + } + serial = DeferredStateManager.passViewMatrixSerial; + if(serial != uniforms.inverseViewMatrixSerial) { + uniforms.inverseViewMatrixSerial = serial; + matrixCopyBuffer.clear(); + DeferredStateManager.passInverseViewMatrix.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(uniforms.u_inverseViewMatrix4f, false, matrixCopyBuffer); + } + if((stateExtBits & STATE_PARABOLOID_RENDER) != 0) { + float farPlane = DeferredStateManager.gbufferFarPlane * 0.125f; //TODO + if(farPlane != uniforms.farPlane1f) { + uniforms.farPlane1f = farPlane; + _wglUniform1f(uniforms.u_farPlane1f, farPlane); + } + } + if((stateExtBits & STATE_REALISTIC_WATER_RENDER) != 0) { + serial = DeferredStateManager.passViewMatrixSerial * 87917 + DeferredStateManager.passProjMatrixSerial; + if(serial != uniforms.modelViewProjMatrixAltSerial) { + uniforms.modelViewProjMatrixAltSerial = serial; + Matrix4f.mul(DeferredStateManager.passProjMatrix, DeferredStateManager.passViewMatrix, tmpMatrix); + matrixCopyBuffer.clear(); + tmpMatrix.store(matrixCopyBuffer); + matrixCopyBuffer.flip(); + _wglUniformMatrix4fv(uniforms.u_modelViewProjMat4f_, false, matrixCopyBuffer); + } + serial = DeferredStateManager.waterWindOffsetSerial; + if(serial != uniforms.waterWindOffsetSerial) { + uniforms.waterWindOffsetSerial = serial; + Vector4f vec = DeferredStateManager.u_waterWindOffset4f; + _wglUniform4f(uniforms.u_waterWindOffset4f, vec.x, vec.y, vec.z, vec.w); + } + serial = DeferredStateManager.wavingBlockOffsetSerial; + if(serial != uniforms.wavingBlockOffsetSerial) { + uniforms.wavingBlockOffsetSerial = serial; + float x = DeferredStateManager.wavingBlockOffsetX; + float y = DeferredStateManager.wavingBlockOffsetY; + float z = DeferredStateManager.wavingBlockOffsetZ; + if(uniforms.wavingBlockOffsetX != x || uniforms.wavingBlockOffsetY != y || uniforms.wavingBlockOffsetZ != z) { + uniforms.wavingBlockOffsetX = x; + uniforms.wavingBlockOffsetY = y; + uniforms.wavingBlockOffsetZ = z; + _wglUniform3f(uniforms.u_wavingBlockOffset3f, x, y, z); + } + } + } + }else if((stateExtBits & (STATE_SHADOW_RENDER | STATE_REALISTIC_WATER_MASK)) == 0) { + if(uniforms == null) { + uniforms = ((GBufferPipelineProgramInstance)userPointer[0]).shaderObject.uniforms; + } + if(uniforms.u_useEnvMap1f != null) { + float use = DeferredStateManager.materialConstantsUseEnvMap ? 1.0f : 0.0f; + if(uniforms.materialConstantsUseEnvMap != use) { + uniforms.materialConstantsUseEnvMap = use; + _wglUniform1f(uniforms.u_useEnvMap1f, use); + } + } + } + } + + @Override + public void destroyPipeline(IProgramGL shaderProgram, int stateCoreBits, int stateExtBits, Object[] userPointer) { + + } + + private static String visualizeBits(int bits) { + return FixedFunctionPipeline.visualizeBits(bits); + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineProgramInstance.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineProgramInstance.java new file mode 100644 index 0000000..b5d60c0 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/GBufferPipelineProgramInstance.java @@ -0,0 +1,30 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.GBufferExtPipelineShader; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GBufferPipelineProgramInstance { + + public final int coreState; + public final int extState; + + public GBufferExtPipelineShader shaderObject = null; + + public GBufferPipelineProgramInstance(int coreState, int extState) { + this.coreState = coreState; + this.extState = extState; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LensFlareMeshRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LensFlareMeshRenderer.java new file mode 100644 index 0000000..bc6b103 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LensFlareMeshRenderer.java @@ -0,0 +1,375 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderLensFlares; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f; +import net.lax1dude.eaglercraft.v1_8.vector.Vector3f; +import net.minecraft.client.Minecraft; +import net.minecraft.util.MathHelper; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class LensFlareMeshRenderer { + + public static final String streaksTextureLocation ="assets/eagler/glsl/deferred/lens_streaks.bmp"; + public static final String ghostsTextureLocation = "assets/eagler/glsl/deferred/lens_ghosts.bmp"; + public static final int ghostsSpriteCount = 4; + + static IBufferArrayGL streaksVertexArray = null; + static IBufferGL streaksVertexBuffer = null; + + static IBufferArrayGL ghostsVertexArray = null; + static IBufferGL ghostsVertexBuffer = null; + + static PipelineShaderLensFlares streaksProgram = null; + static PipelineShaderLensFlares ghostsProgram = null; + + static int streaksTexture = -1; + static int ghostsTexture = -1; + + static int streaksVertexCount = 0; + static int ghostsInstanceCount = 0; + + static final Matrix3f tmpMat = new Matrix3f(); + static final Matrix3f tmpMat2 = new Matrix3f(); + static final Vector3f tmpVec = new Vector3f(); + + static void initialize() { + destroy(); + + streaksProgram = PipelineShaderLensFlares.compileStreaks(); + streaksProgram.loadUniforms(); + + ghostsProgram = PipelineShaderLensFlares.compileGhosts(); + ghostsProgram.loadUniforms(); + + ByteBuffer copyBuffer = EagRuntime.allocateByteBuffer(16384); + + for(int i = 0; i < 4; ++i) { + pushStreakQuad(copyBuffer, 0.0f, 0.0f, 1.0f, 10.0f, 0.0f, 0.0f, 1.0f, 1.0f, (i * 3.14159f / 4.0f)); + pushStreakQuad(copyBuffer, 0.0f, 0.0f, 1.5f, 5.0f, 0.0f, 0.0f, 1.0f, 1.0f, ((i + 0.25f) * 3.14159f / 4.0f)); + pushStreakQuad(copyBuffer, 0.0f, 0.0f, 0.5f, 7.0f, 0.0f, 0.0f, 1.0f, 1.0f, ((i + 0.5f) * 3.14159f / 4.0f)); + pushStreakQuad(copyBuffer, 0.0f, 0.0f, 1.5f, 5.0f, 0.0f, 0.0f, 1.0f, 1.0f, ((i + 0.75f) * 3.14159f / 4.0f)); + } + + copyBuffer.flip(); + streaksVertexCount = 64; + + streaksVertexBuffer = _wglGenBuffers(); + EaglercraftGPU.bindGLArrayBuffer(streaksVertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, copyBuffer, GL_STATIC_DRAW); + + streaksVertexArray = _wglGenVertexArrays(); + EaglercraftGPU.bindGLBufferArray(streaksVertexArray); + EaglercraftGPU.attachQuad16EmulationBuffer(16, true); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 16, 0); + + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 2, GL_FLOAT, false, 16, 8); + + copyBuffer.clear(); + + ghostsInstanceCount = 0; + + float streakIntensity2 = 10.0f; + float scale = 5.0f; + + pushGhostQuadAbberated(copyBuffer, 0.4f, 0.15f * scale, 2, 0.5f, 0.9f, 0.2f, 0.04f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 0.45f, 0.15f * scale, 2, 0.5f, 0.9f, 0.2f, 0.04f * streakIntensity2); + + pushGhostQuadAbberated(copyBuffer, 0.6f, 0.1f * scale, 0, 0.5f, 0.9f, 0.2f, 0.045f * streakIntensity2); + + pushGhostQuadAbberated(copyBuffer, 0.67f, 0.1f * scale, 0, 0.5f, 0.9f, 0.2f, 0.2f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 0.78f, 0.15f * scale, 1, 0.5f, 0.9f, 0.7f, 0.2f * streakIntensity2); + + pushGhostQuadAbberated(copyBuffer, 1.0f, 0.15f * scale, 1, 0.5f, 0.9f, 0.7f, 0.1f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.04f, 0.15f * scale, 3, 0.5f, 0.5f, 0.7f, 0.1f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.07f, 0.1f * scale, 1, 0.7f, 0.7f, 0.7f, 0.2f * streakIntensity2); + pushGhostQuad(copyBuffer, 1.11f, 0.1f * scale, 2, 0.2f, 0.2f, 0.7f, 0.05f * streakIntensity2); + pushGhostQuad(copyBuffer, 1.11f, 0.3f * scale, 2, 0.2f, 0.7f, 0.2f, 0.05f * streakIntensity2); + + pushGhostQuadAbberated(copyBuffer, 1.25f, 0.2f * scale, 0, 0.4f, 0.7f, 0.2f, 0.02f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.22f, 0.1f * scale, 2, 0.3f, 0.7f, 0.7f, 0.05f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.27f, 0.1f * scale, 0, 0.5f, 0.7f, 0.5f, 0.15f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.30f, 0.08f * scale, 0, 0.7f, 0.7f, 0.7f, 0.15f * streakIntensity2); + + pushGhostQuadAbberated(copyBuffer, 1.45f, 0.3f * scale, 2, 0.3f, 0.7f, 0.2f, 0.02f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.55f, 0.1f * scale, 2, 0.3f, 0.7f, 0.7f, 0.05f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.59f, 0.1f * scale, 0, 0.5f, 0.7f, 0.5f, 0.15f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 2.0f, 0.3f * scale, 3, 0.3f, 0.7f, 0.2f, 0.03f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 1.98f, 0.2f * scale, 1, 0.3f, 0.7f, 0.2f, 0.04f * streakIntensity2); + pushGhostQuadAbberated(copyBuffer, 2.02f, 0.2f * scale, 1, 0.3f, 0.7f, 0.2f, 0.04f * streakIntensity2); + + copyBuffer.flip(); + + ghostsVertexArray = _wglGenVertexArrays(); + EaglercraftGPU.bindGLBufferArray(ghostsVertexArray); + EaglercraftGPU.bindGLArrayBuffer(DrawUtils.standardQuadVBO); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0); + _wglVertexAttribDivisor(0, 0); + + ghostsVertexBuffer = _wglGenBuffers(); + EaglercraftGPU.bindGLArrayBuffer(ghostsVertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, copyBuffer, GL_STATIC_DRAW); + + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 2, GL_FLOAT, false, 36, 0); + _wglVertexAttribDivisor(1, 1); + + _wglEnableVertexAttribArray(2); + _wglVertexAttribPointer(2, 4, GL_FLOAT, false, 36, 8); + _wglVertexAttribDivisor(2, 1); + + _wglEnableVertexAttribArray(3); + _wglVertexAttribPointer(3, 3, GL_FLOAT, false, 36, 24); + _wglVertexAttribDivisor(3, 1); + + streaksTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(streaksTexture); + byte[] flareTex = EagRuntime.getResourceBytes(streaksTextureLocation); + if(flareTex == null) { + throw new RuntimeException("Could not locate: " + streaksTextureLocation); + } + try(DataInputStream dis = new DataInputStream(new ByteArrayInputStream(flareTex))) { + loadFlareTexture(copyBuffer, dis); + }catch(IOException ex) { + EagRuntime.freeByteBuffer(copyBuffer); + throw new RuntimeException("Could not load: " + streaksTextureLocation, ex); + } + + ghostsTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(ghostsTexture); + flareTex = EagRuntime.getResourceBytes(ghostsTextureLocation); + if(flareTex == null) { + throw new RuntimeException("Could not locate: " + ghostsTextureLocation); + } + try(DataInputStream dis = new DataInputStream(new ByteArrayInputStream(flareTex))) { + loadFlareTexture(copyBuffer, dis); + }catch(IOException ex) { + EagRuntime.freeByteBuffer(copyBuffer); + throw new RuntimeException("Could not load: " + ghostsTextureLocation, ex); + } + + EagRuntime.freeByteBuffer(copyBuffer); + } + + static void loadFlareTexture(ByteBuffer copyBuffer, DataInputStream dis) throws IOException { + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + _wglPixelStorei(GL_UNPACK_ALIGNMENT, 1); + int mip = 0; + while(dis.read() == 'E') { + int w = dis.readShort(); + int h = dis.readShort(); + copyBuffer.clear(); + for(int i = 0, l = w * h; i < l; ++i) { + copyBuffer.put((byte)dis.read()); + } + copyBuffer.flip(); + _wglTexImage2D(GL_TEXTURE_2D, mip++, _GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, copyBuffer); + } + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mip - 1); + _wglPixelStorei(GL_UNPACK_ALIGNMENT, 4); + } + + static void pushStreakQuad(ByteBuffer copyBuffer, float x, float y, float w, float h, float tx, float ty, float tw, + float th, float rotation) { + tmpMat.m00 = MathHelper.cos(rotation); + tmpMat.m01 = MathHelper.sin(rotation); + tmpMat.m10 = -tmpMat.m01; + tmpMat.m11 = tmpMat.m00; + tmpMat.m20 = x; + tmpMat.m21 = y; + + tmpVec.x = -w; + tmpVec.y = -h; + tmpVec.z = 1.0f; + Matrix3f.transform(tmpMat, tmpVec, tmpVec); + + copyBuffer.putFloat(tmpVec.x); + copyBuffer.putFloat(tmpVec.y); + copyBuffer.putFloat(tx); + copyBuffer.putFloat(ty); + + tmpVec.x = w; + tmpVec.y = -h; + tmpVec.z = 1.0f; + Matrix3f.transform(tmpMat, tmpVec, tmpVec); + + copyBuffer.putFloat(tmpVec.x); + copyBuffer.putFloat(tmpVec.y); + copyBuffer.putFloat(tx + tw); + copyBuffer.putFloat(ty); + + tmpVec.x = w; + tmpVec.y = h; + tmpVec.z = 1.0f; + Matrix3f.transform(tmpMat, tmpVec, tmpVec); + + copyBuffer.putFloat(tmpVec.x); + copyBuffer.putFloat(tmpVec.y); + copyBuffer.putFloat(tx + tw); + copyBuffer.putFloat(ty + th); + + tmpVec.x = -w; + tmpVec.y = h; + tmpVec.z = 1.0f; + Matrix3f.transform(tmpMat, tmpVec, tmpVec); + + copyBuffer.putFloat(tmpVec.x); + copyBuffer.putFloat(tmpVec.y); + copyBuffer.putFloat(tx); + copyBuffer.putFloat(ty + th); + } + + static void pushGhostQuadAbberated(ByteBuffer copyBuffer, float offset, float scale, int sprite, float r, float g, float b, float a) { + pushGhostQuad(copyBuffer, offset, scale, sprite, 0.0f, g, b, a); + pushGhostQuad(copyBuffer, offset + 0.005f, scale, sprite, r, 0.0f, 0.0f, a); + } + + static void pushGhostQuad(ByteBuffer copyBuffer, float offset, float scale, int sprite, float r, float g, float b, float a) { + copyBuffer.putFloat(offset); + copyBuffer.putFloat(scale); + copyBuffer.putFloat(0.0f); + copyBuffer.putFloat((float)sprite / ghostsSpriteCount); + copyBuffer.putFloat(1.0f); + copyBuffer.putFloat(1.0f / ghostsSpriteCount); + copyBuffer.putFloat(r * a); + copyBuffer.putFloat(g * a); + copyBuffer.putFloat(b * a); + ++ghostsInstanceCount; + } + + static void drawLensFlares(float sunScreenX, float sunScreenY) { + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + + GlStateManager.setActiveTexture(GL_TEXTURE2); + GlStateManager.bindTexture(EaglerDeferredPipeline.instance.sunOcclusionValueTexture); + GlStateManager.setActiveTexture(GL_TEXTURE1); + GlStateManager.bindTexture(EaglerDeferredPipeline.instance.exposureBlendTexture); + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(streaksTexture); + + streaksProgram.useProgram(); + + Minecraft mc = Minecraft.getMinecraft(); + float aspectRatio = (float)mc.displayHeight / (float)mc.displayWidth; + + float fov = 90.0f / mc.entityRenderer.getFOVModifier(EaglerDeferredPipeline.instance.getPartialTicks(), true); + float size = 0.075f * fov * (1.0f + MathHelper.sqrt_float(sunScreenX * sunScreenX + sunScreenY * sunScreenY)); + + tmpMat.setIdentity(); + tmpMat.m00 = aspectRatio * 2.0f * size; + tmpMat.m11 = size; + tmpMat.m20 = sunScreenX; + tmpMat.m21 = sunScreenY; + + float rotation = sunScreenX * sunScreenX * Math.signum(sunScreenX) + sunScreenY * sunScreenY * Math.signum(sunScreenY); + + tmpMat2.setIdentity(); + tmpMat2.m00 = MathHelper.cos(rotation); + tmpMat2.m01 = MathHelper.sin(rotation); + tmpMat2.m10 = -tmpMat2.m01; + tmpMat2.m11 = tmpMat2.m00; + Matrix3f.mul(tmpMat, tmpMat2, tmpMat); + + EaglerDeferredPipeline.uniformMatrixHelper(streaksProgram.uniforms.u_sunFlareMatrix3f, tmpMat); + + Vector3f v = DeferredStateManager.currentSunLightColor; + float mag = 1.0f + DeferredStateManager.currentSunAngle.y * 0.8f; + if(mag > 1.0f) { + mag = 1.0f - (mag - 1.0f) * 20.0f; + if(mag < 0.0f) { + mag = 0.0f; + } + } + mag = 0.003f * (1.0f + mag * mag * mag * 4.0f); + _wglUniform3f(streaksProgram.uniforms.u_flareColor3f, v.x * mag * 0.5f, v.y * mag * 0.5f, v.z * mag * 0.5f); + + EaglercraftGPU.bindGLBufferArray(streaksVertexArray); + _wglDrawElements(GL_TRIANGLES, streaksVertexCount + (streaksVertexCount >> 1), GL_UNSIGNED_SHORT, 0); + + ghostsProgram.useProgram(); + + GlStateManager.setActiveTexture(GL_TEXTURE0); + GlStateManager.bindTexture(ghostsTexture); + + _wglUniform3f(ghostsProgram.uniforms.u_flareColor3f, v.x * mag, v.y * mag, v.z * mag); + _wglUniform1f(ghostsProgram.uniforms.u_aspectRatio1f, aspectRatio); + _wglUniform2f(ghostsProgram.uniforms.u_sunPosition2f, sunScreenX, sunScreenY); + _wglUniform1f(ghostsProgram.uniforms.u_baseScale1f, fov); + + EaglercraftGPU.bindGLBufferArray(ghostsVertexArray); + _wglDrawArraysInstanced(GL_TRIANGLES, 0, 6, ghostsInstanceCount); + + GlStateManager.disableBlend(); + } + + static void destroy() { + if(streaksVertexArray != null) { + _wglDeleteVertexArrays(streaksVertexArray); + streaksVertexArray = null; + } + if(streaksVertexBuffer != null) { + _wglDeleteBuffers(streaksVertexBuffer); + streaksVertexBuffer = null; + } + if(ghostsVertexArray != null) { + _wglDeleteVertexArrays(ghostsVertexArray); + ghostsVertexArray = null; + } + if(ghostsVertexBuffer != null) { + _wglDeleteBuffers(ghostsVertexBuffer); + ghostsVertexBuffer = null; + } + if(streaksTexture != -1) { + GlStateManager.deleteTexture(streaksTexture); + streaksTexture = -1; + } + if(ghostsTexture != -1) { + GlStateManager.deleteTexture(ghostsTexture); + ghostsTexture = -1; + } + if(streaksProgram != null) { + streaksProgram.destroy(); + streaksProgram = null; + } + if(ghostsProgram != null) { + ghostsProgram.destroy(); + ghostsProgram = null; + } + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LightSourceMesh.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LightSourceMesh.java new file mode 100644 index 0000000..14c9aa4 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/LightSourceMesh.java @@ -0,0 +1,135 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class LightSourceMesh { + + public final ResourceLocation meshLocation; + private final byte[] typeBytes; + + private IBufferGL meshVBO = null; + private IBufferGL meshIBO = null; + private IBufferArrayGL meshVAO = null; + + private int meshIndexType = -1; + private int meshIndexCount = -1; + + public LightSourceMesh(ResourceLocation is, String type) { + meshLocation = is; + typeBytes = type.getBytes(StandardCharsets.UTF_8); + } + + public void load() throws IOException { + destroy(); + try (DataInputStream is = new DataInputStream( + Minecraft.getMinecraft().getResourceManager().getResource(meshLocation).getInputStream())) { + if(is.read() != 0xEE || is.read() != 0xAA || is.read() != 0x66 || is.read() != '%') { + throw new IOException("Bad file type for: " + meshLocation.toString()); + } + byte[] bb = new byte[is.read()]; + is.read(bb); + if(!Arrays.equals(bb, typeBytes)) { + throw new IOException("Bad file type \"" + new String(bb, StandardCharsets.UTF_8) + "\" for: " + meshLocation.toString()); + } + + int vboLength = is.readInt() * 6; + byte[] readBuffer = new byte[vboLength]; + is.read(readBuffer); + + ByteBuffer buf = EagRuntime.allocateByteBuffer(readBuffer.length); + buf.put(readBuffer); + buf.flip(); + + meshVBO = _wglGenBuffers(); + EaglercraftGPU.bindGLArrayBuffer(meshVBO); + _wglBufferData(GL_ARRAY_BUFFER, buf, GL_STATIC_DRAW); + + EagRuntime.freeByteBuffer(buf); + + int iboLength = meshIndexCount = is.readInt(); + int iboType = is.read(); + iboLength *= iboType; + switch(iboType) { + case 1: + meshIndexType = GL_UNSIGNED_BYTE; + break; + case 2: + meshIndexType = GL_UNSIGNED_SHORT; + break; + case 4: + meshIndexType = GL_UNSIGNED_INT; + break; + default: + throw new IOException("Unsupported index buffer type: " + iboType); + } + + readBuffer = new byte[iboLength]; + is.read(readBuffer); + + buf = EagRuntime.allocateByteBuffer(readBuffer.length); + buf.put(readBuffer); + buf.flip(); + + meshVAO = _wglGenVertexArrays(); + EaglercraftGPU.bindGLBufferArray(meshVAO); + + meshIBO = _wglGenBuffers(); + _wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshIBO); + _wglBufferData(GL_ELEMENT_ARRAY_BUFFER, buf, GL_STATIC_DRAW); + EagRuntime.freeByteBuffer(buf); + + EaglercraftGPU.bindGLArrayBuffer(meshVBO); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 3, _GL_HALF_FLOAT, false, 6, 0); + } + } + + public void drawMeshVAO() { + EaglercraftGPU.bindGLBufferArray(meshVAO); + _wglDrawElements(GL_TRIANGLES, meshIndexCount, meshIndexType, 0); + } + + public void destroy() { + if(meshVBO != null) { + _wglDeleteBuffers(meshVBO); + meshVBO = null; + } + if(meshIBO != null) { + _wglDeleteBuffers(meshIBO); + meshIBO = null; + } + if(meshVAO != null) { + _wglDeleteVertexArrays(meshVAO); + meshVAO = null; + } + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ListSerial.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ListSerial.java new file mode 100644 index 0000000..a0d283e --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ListSerial.java @@ -0,0 +1,28 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.List; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public interface ListSerial extends List { + + int getEaglerSerial(); + + void eaglerIncrSerial(); + + void eaglerResetCheck(); + + boolean eaglerCheck(); + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/NameTagRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/NameTagRenderer.java new file mode 100644 index 0000000..8f3aa42 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/NameTagRenderer.java @@ -0,0 +1,52 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.minecraft.entity.Entity; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class NameTagRenderer { + + public static boolean doRenderNameTags = false; + public static final NameTagRenderer[] nameTagsThisFrame = new NameTagRenderer[256]; + public static int nameTagsCount = 0; + + static { + for(int i = 0; i < nameTagsThisFrame.length; ++i) { + nameTagsThisFrame[i] = new NameTagRenderer(); + } + } + + public Entity entityIn; + public String str; + public double x; + public double y; + public double z; + public int maxDistance; + public double dst2; + + public static void renderNameTag(Entity entityIn, String str, double x, double y, double z, int maxDistance) { + if(!doRenderNameTags || nameTagsCount >= nameTagsThisFrame.length) { + return; + } + NameTagRenderer n = nameTagsThisFrame[nameTagsCount++]; + n.entityIn = entityIn; + n.str = str; + n.x = x; + n.y = y; + n.z = z; + n.dst2 = x * x + y * y + z * z; + n.maxDistance = maxDistance; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfo.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfo.java new file mode 100644 index 0000000..84deb2b --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfo.java @@ -0,0 +1,77 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.util.HashSet; +import java.util.Set; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderPackInfo { + + public final String name; + public final String desc; + public final String vers; + public final String author; + public final int apiVers; + public final Set supportedFeatures; + + public final boolean WAVING_BLOCKS; + public final boolean DYNAMIC_LIGHTS; + public final boolean GLOBAL_AMBIENT_OCCLUSION; + public final boolean SHADOWS_SUN; + public final boolean SHADOWS_COLORED; + public final boolean SHADOWS_SMOOTHED; + public final boolean REFLECTIONS_PARABOLOID; + public final boolean REALISTIC_WATER; + public final boolean LIGHT_SHAFTS; + public final boolean SCREEN_SPACE_REFLECTIONS; + public final boolean POST_LENS_DISTORION; + public final boolean POST_LENS_FLARES; + public final boolean POST_BLOOM; + public final boolean POST_FXAA; + + public ShaderPackInfo(JSONObject json) { + name = json.optString("name", "Untitled"); + desc = json.optString("desc", "No Description"); + vers = json.optString("vers", "Unknown"); + author = json.optString("author", "Unknown"); + apiVers = json.optInt("api_vers", -1); + supportedFeatures = new HashSet(); + JSONArray features = json.getJSONArray("features"); + if(features.length() == 0) { + throw new JSONException("No supported features list has been defined for this shader pack!"); + } + for(int i = 0, l = features.length(); i < l; ++i) { + supportedFeatures.add(features.getString(i)); + } + WAVING_BLOCKS = supportedFeatures.contains("WAVING_BLOCKS"); + DYNAMIC_LIGHTS = supportedFeatures.contains("DYNAMIC_LIGHTS"); + GLOBAL_AMBIENT_OCCLUSION = supportedFeatures.contains("GLOBAL_AMBIENT_OCCLUSION"); + SHADOWS_SUN = supportedFeatures.contains("SHADOWS_SUN"); + SHADOWS_COLORED = supportedFeatures.contains("SHADOWS_COLORED"); + SHADOWS_SMOOTHED = supportedFeatures.contains("SHADOWS_SMOOTHED"); + REFLECTIONS_PARABOLOID = supportedFeatures.contains("REFLECTIONS_PARABOLOID"); + REALISTIC_WATER = supportedFeatures.contains("REALISTIC_WATER"); + LIGHT_SHAFTS = supportedFeatures.contains("LIGHT_SHAFTS"); + SCREEN_SPACE_REFLECTIONS = supportedFeatures.contains("SCREEN_SPACE_REFLECTIONS"); + POST_LENS_DISTORION = supportedFeatures.contains("POST_LENS_DISTORION"); + POST_LENS_FLARES = supportedFeatures.contains("POST_LENS_FLARES"); + POST_BLOOM = supportedFeatures.contains("POST_BLOOM"); + POST_FXAA = supportedFeatures.contains("POST_FXAA"); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfoReloadListener.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfoReloadListener.java new file mode 100644 index 0000000..9270e93 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShaderPackInfoReloadListener.java @@ -0,0 +1,46 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import java.io.IOException; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderPackInfoReloadListener implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger(); + + @Override + public void onResourceManagerReload(IResourceManager mcResourceManager) { + Minecraft mc = Minecraft.getMinecraft(); + try { + mc.gameSettings.deferredShaderConf.reloadShaderPackInfo(mcResourceManager); + }catch(IOException ex) { + logger.info("Could not reload shader pack info!"); + logger.info(ex); + logger.info("Shaders have been disabled"); + mc.gameSettings.shaders = false; + } + TextureMap tm = mc.getTextureMapBlocks(); + if(tm != null) { + mc.getTextureMapBlocks().setEnablePBREagler(mc.gameSettings.shaders); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShadersRenderPassFuture.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShadersRenderPassFuture.java new file mode 100644 index 0000000..f0de018 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/ShadersRenderPassFuture.java @@ -0,0 +1,66 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.entity.Entity; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public abstract class ShadersRenderPassFuture { + + public static enum PassType { + MAIN, SHADOW + } + + protected float x; + protected float y; + protected float z; + protected float partialTicks; + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public float getZ() { + return z; + } + + public ShadersRenderPassFuture(float x, float y, float z, float partialTicks) { + this.x = x; + this.y = y; + this.z = z; + this.partialTicks = partialTicks; + } + + public ShadersRenderPassFuture(Entity e, float partialTicks) { + this.x = (float)((e.posX - e.prevPosX) * partialTicks + e.prevPosX - TileEntityRendererDispatcher.staticPlayerX); + this.y = (float)((e.posY - e.prevPosY) * partialTicks + e.prevPosY - TileEntityRendererDispatcher.staticPlayerY); + this.z = (float)((e.posZ - e.prevPosZ) * partialTicks + e.prevPosZ - TileEntityRendererDispatcher.staticPlayerZ); + } + + public ShadersRenderPassFuture(Entity e) { + this(e, EaglerDeferredPipeline.instance.getPartialTicks()); + } + + public abstract void draw(PassType pass); + + private final float[] tmp = new float[1]; + + public float[] tmpValue() { + return tmp; + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/SkyboxRenderer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/SkyboxRenderer.java new file mode 100644 index 0000000..1c5aeea --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/SkyboxRenderer.java @@ -0,0 +1,199 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*; + +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class SkyboxRenderer { + + public final ResourceLocation skyboxLocation; + + private IBufferGL skyboxVBO = null; + private IBufferGL skyboxIBO = null; + private IBufferArrayGL skyboxVAO = null; + private int normalsLUT = -1; + private int atmosphereLUTWidth = -1; + private int atmosphereLUTHeight = -1; + + private int skyboxIndexType = -1; + private int skyboxIndexStride = -1; + private int skyboxIndexCount = -1; + + private int skyboxTopIndexOffset = -1; + private int skyboxTopIndexCount = -1; + + private int skyboxBottomIndexOffset = -1; + private int skyboxBottomIndexCount = -1; + + public SkyboxRenderer(ResourceLocation is) { + skyboxLocation = is; + } + + public void load() throws IOException { + destroy(); + try (DataInputStream is = new DataInputStream( + Minecraft.getMinecraft().getResourceManager().getResource(skyboxLocation).getInputStream())) { + if(is.read() != 0xEE || is.read() != 0xAA || is.read() != 0x66 || is.read() != '%') { + throw new IOException("Bad file type for: " + skyboxLocation.toString()); + } + byte[] bb = new byte[is.read()]; + is.read(bb); + if(!Arrays.equals(bb, new byte[] { 's', 'k', 'y', 'b', 'o', 'x' })) { + throw new IOException("Bad file type \"" + new String(bb, StandardCharsets.UTF_8) + "\" for: " + skyboxLocation.toString()); + } + atmosphereLUTWidth = is.readUnsignedShort(); + atmosphereLUTHeight = is.readUnsignedShort(); + byte[] readBuffer = new byte[atmosphereLUTWidth * atmosphereLUTHeight * 4]; + is.read(readBuffer); + + ByteBuffer buf = EagRuntime.allocateByteBuffer(readBuffer.length); + buf.put(readBuffer); + buf.flip(); + + normalsLUT = GlStateManager.generateTexture(); + GlStateManager.bindTexture(normalsLUT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + _wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, atmosphereLUTWidth, atmosphereLUTHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + + EagRuntime.freeByteBuffer(buf); + + skyboxTopIndexOffset = is.readInt(); + skyboxTopIndexCount = is.readInt(); + skyboxBottomIndexOffset = is.readInt(); + skyboxBottomIndexCount = is.readInt(); + + int vboLength = is.readInt() * 8; + readBuffer = new byte[vboLength]; + is.read(readBuffer); + + buf = EagRuntime.allocateByteBuffer(readBuffer.length); + buf.put(readBuffer); + buf.flip(); + + skyboxVBO = _wglGenBuffers(); + EaglercraftGPU.bindGLArrayBuffer(skyboxVBO); + _wglBufferData(GL_ARRAY_BUFFER, buf, GL_STATIC_DRAW); + + EagRuntime.freeByteBuffer(buf); + + int iboLength = skyboxIndexCount = is.readInt(); + int iboType = is.read(); + iboLength *= iboType; + switch(iboType) { + case 1: + skyboxIndexType = GL_UNSIGNED_BYTE; + break; + case 2: + skyboxIndexType = GL_UNSIGNED_SHORT; + break; + case 4: + skyboxIndexType = GL_UNSIGNED_INT; + break; + default: + throw new IOException("Unsupported index buffer type: " + iboType); + } + + skyboxIndexStride = iboType; + + readBuffer = new byte[iboLength]; + is.read(readBuffer); + + buf = EagRuntime.allocateByteBuffer(readBuffer.length); + buf.put(readBuffer); + buf.flip(); + + skyboxVAO = _wglGenVertexArrays(); + EaglercraftGPU.bindGLBufferArray(skyboxVAO); + + skyboxIBO = _wglGenBuffers(); + _wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skyboxIBO); + _wglBufferData(GL_ELEMENT_ARRAY_BUFFER, buf, GL_STATIC_DRAW); + EagRuntime.freeByteBuffer(buf); + + EaglercraftGPU.bindGLArrayBuffer(skyboxVBO); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 3, _GL_HALF_FLOAT, false, 8, 0); + + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, true, 8, 6); + } + } + + public int getNormalsLUT() { + return normalsLUT; + } + + public int getAtmosLUTWidth() { + return atmosphereLUTWidth; + } + + public int getAtmosLUTHeight() { + return atmosphereLUTHeight; + } + + public void drawTop() { + EaglercraftGPU.bindGLBufferArray(skyboxVAO); + _wglDrawElements(GL_TRIANGLES, skyboxTopIndexCount, skyboxIndexType, skyboxTopIndexOffset * skyboxIndexStride); + } + + public void drawBottom() { + EaglercraftGPU.bindGLBufferArray(skyboxVAO); + _wglDrawElements(GL_TRIANGLES, skyboxBottomIndexCount, skyboxIndexType, skyboxBottomIndexOffset * skyboxIndexStride); + } + + public void drawFull() { + EaglercraftGPU.bindGLBufferArray(skyboxVAO); + _wglDrawElements(GL_TRIANGLES, skyboxIndexCount, skyboxIndexType, 0); + } + + public void destroy() { + if(skyboxVBO != null) { + _wglDeleteBuffers(skyboxVBO); + skyboxVBO = null; + } + if(skyboxIBO != null) { + _wglDeleteBuffers(skyboxIBO); + skyboxVBO = null; + } + if(skyboxVAO != null) { + _wglDeleteVertexArrays(skyboxVAO); + skyboxVBO = null; + } + if(normalsLUT != -1) { + GlStateManager.deleteTexture(normalsLUT); + normalsLUT = -1; + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/VertexMarkerState.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/VertexMarkerState.java new file mode 100644 index 0000000..067ebc6 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/VertexMarkerState.java @@ -0,0 +1,23 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class VertexMarkerState { + + public static float localCoordDeriveHackX = 1.0f; + public static float localCoordDeriveHackY = 1.001f; + public static float localCoordDeriveHackZ = 1.0f; + public static int markId = 0; + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfig.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfig.java new file mode 100644 index 0000000..3bd4044 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfig.java @@ -0,0 +1,133 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui; + +import java.io.IOException; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GuiShaderConfig extends GuiScreen { + + private static final Logger logger = LogManager.getLogger(); + + boolean shaderStartState = false; + + private final GuiScreen parent; + private GuiShaderConfigList listView; + + private String title; + private GuiButton enableDisableButton; + + public GuiShaderConfig(GuiScreen parent) { + this.parent = parent; + this.shaderStartState = Minecraft.getMinecraft().gameSettings.shaders; + } + + public void initGui() { + this.title = I18n.format("shaders.gui.title"); + this.buttonList.clear(); + this.buttonList.add(enableDisableButton = new GuiButton(0, width / 2 - 155, height - 30, 150, 20, I18n.format("shaders.gui.enable") + + ": " + (mc.gameSettings.shaders ? I18n.format("gui.yes") : I18n.format("gui.no")))); + this.buttonList.add(new GuiButton(1, width / 2 + 5, height - 30, 150, 20, I18n.format("gui.done"))); + if(listView == null) { + this.listView = new GuiShaderConfigList(this, mc); + }else { + this.listView.resize(); + } + } + + protected void actionPerformed(GuiButton btn) { + if(btn.id == 0) { + mc.gameSettings.shaders = !mc.gameSettings.shaders; + listView.setAllDisabled(!mc.gameSettings.shaders); + enableDisableButton.displayString = I18n.format("shaders.gui.enable") + ": " + + (mc.gameSettings.shaders ? I18n.format("gui.yes") : I18n.format("gui.no")); + }else if(btn.id == 1) { + mc.displayGuiScreen(parent); + } + } + + public void onGuiClosed() { + if(shaderStartState != mc.gameSettings.shaders || listView.isDirty()) { + mc.gameSettings.saveOptions(); + if(shaderStartState != mc.gameSettings.shaders) { + mc.loadingScreen.eaglerShowRefreshResources(); + mc.refreshResources(); + }else { + logger.info("Reloading shaders..."); + try { + mc.gameSettings.deferredShaderConf.reloadShaderPackInfo(mc.getResourceManager()); + }catch(IOException ex) { + logger.info("Could not reload shader pack info!"); + logger.info(ex); + logger.info("Shaders have been disabled"); + mc.gameSettings.shaders = false; + mc.refreshResources(); + return; + } + + if(mc.gameSettings.shaders) { + ShaderSource.clearCache(); + } + + if (mc.renderGlobal != null) { + mc.renderGlobal.loadRenderers(); + } + } + } + } + + public void handleMouseInput() throws IOException { + super.handleMouseInput(); + listView.handleMouseInput(); + } + + protected void mouseClicked(int parInt1, int parInt2, int parInt3) { + super.mouseClicked(parInt1, parInt2, parInt3); + listView.mouseClicked(parInt1, parInt2, parInt3); + } + + protected void mouseReleased(int i, int j, int k) { + super.mouseReleased(i, j, k); + listView.mouseReleased(i, j, k); + } + + public void drawScreen(int i, int j, float f) { + this.drawBackground(0); + listView.drawScreen(i, j, f); + drawCenteredString(this.fontRendererObj, title, this.width / 2, 15, 16777215); + super.drawScreen(i, j, f); + listView.postRender(i, j, f); + } + + void renderTooltip(List txt, int x, int y) { + drawHoveringText(txt, x, y); + } + + FontRenderer getFontRenderer() { + return fontRendererObj; + } + + Minecraft getMinecraft() { + return mc; + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfigList.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfigList.java new file mode 100644 index 0000000..4c7b498 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShaderConfigList.java @@ -0,0 +1,657 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.EaglerDeferredConfig; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShaderPackInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiListExtended; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GuiShaderConfigList extends GuiListExtended { + + public static final ResourceLocation shaderPackIcon = new ResourceLocation("eagler:glsl/deferred/shader_pack_icon.png"); + + private final GuiShaderConfig screen; + + private final List list = new ArrayList(); + + private static abstract class ShaderOption { + + private final String label; + private final List desc; + + private ShaderOption(String label, List desc) { + this.label = label; + this.desc = desc; + } + + protected abstract String getDisplayValue(); + + protected abstract void toggleOption(GuiButton button, int dir); + + protected abstract boolean getDirty(); + + } + + private static List loadDescription(String key) { + List ret = new ArrayList(); + String msg; + int i = 0; + while(true) { + if((msg = I18n.format(key + '.' + i)).equals(key + '.' + i)) { + if(!I18n.format(key + '.' + (i + 1)).equals(key + '.' + (i + 1))) { + msg = ""; + }else { + break; + } + } + ret.add(msg); + ++i; + } + if(ret.size() == 0) { + ret.add("" + EnumChatFormatting.GRAY + EnumChatFormatting.ITALIC + "(no description found)"); + } + return ret; + } + + private static String loadShaderLbl(String key) { + return I18n.format("shaders.gui.option." + key + ".label"); + } + + private static List loadShaderDesc(String key) { + return loadDescription("shaders.gui.option." + key + ".desc"); + } + + private static String getColoredOnOff(boolean state, EnumChatFormatting on, EnumChatFormatting off) { + return state ? "" + on + I18n.format("options.on") : "" + off + I18n.format("options.off"); + } + + private void addAllOptions(List opts) { + for(int i = 0, l = opts.size(); i < l; ++i) { + ShaderOption opt1 = opts.get(i); + if(++i >= l) { + list.add(new ListEntryButtonRow(opt1, null, null)); + break; + } + ShaderOption opt2 = opts.get(i); + if(++i >= l) { + list.add(new ListEntryButtonRow(opt1, opt2, null)); + break; + } + list.add(new ListEntryButtonRow(opt1, opt2, opts.get(i))); + } + } + + public GuiShaderConfigList(GuiShaderConfig screen, Minecraft mcIn) { + super(mcIn, screen.width, screen.height, 32, screen.height - 40, 30); + this.screen = screen; + this.list.add(new ListEntryHeader("Current Shader Pack:")); + this.list.add(new ListEntryPackInfo()); + this.list.add(new ListEntrySpacing()); + this.list.add(new ListEntrySpacing()); + this.list.add(new ListEntryHeader(I18n.format("shaders.gui.headerTier1"))); + List opts = new ArrayList(); + EaglerDeferredConfig conf = mcIn.gameSettings.deferredShaderConf; + if(conf.shaderPackInfo.WAVING_BLOCKS) { + opts.add(new ShaderOption(loadShaderLbl("WAVING_BLOCKS"), loadShaderDesc("WAVING_BLOCKS")) { + private final boolean originalValue = conf.wavingBlocks; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.wavingBlocks, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.wavingBlocks = !conf.wavingBlocks; + } + @Override + protected boolean getDirty() { + return conf.wavingBlocks != originalValue; + } + }); + } + if(conf.shaderPackInfo.DYNAMIC_LIGHTS) { + opts.add(new ShaderOption(loadShaderLbl("DYNAMIC_LIGHTS"), loadShaderDesc("DYNAMIC_LIGHTS")) { + private final boolean originalValue = conf.dynamicLights; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.dynamicLights, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.dynamicLights = !conf.dynamicLights; + } + @Override + protected boolean getDirty() { + return conf.dynamicLights != originalValue; + } + }); + } + if(conf.shaderPackInfo.GLOBAL_AMBIENT_OCCLUSION) { + opts.add(new ShaderOption(loadShaderLbl("GLOBAL_AMBIENT_OCCLUSION"), loadShaderDesc("GLOBAL_AMBIENT_OCCLUSION")) { + private final boolean originalValue = conf.ssao; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.ssao, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.ssao = !conf.ssao; + } + @Override + protected boolean getDirty() { + return conf.ssao != originalValue; + } + }); + } + if(conf.shaderPackInfo.SHADOWS_SUN) { + opts.add(new ShaderOption(loadShaderLbl("SHADOWS_SUN"), loadShaderDesc("SHADOWS_SUN")) { + private final int originalValue = conf.shadowsSun; + @Override + protected String getDisplayValue() { + return conf.shadowsSun == 0 ? "" + EnumChatFormatting.RED + "0" : "" + EnumChatFormatting.YELLOW + (1 << (conf.shadowsSun + 3)); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.shadowsSun = (conf.shadowsSun + dir + 5) % 5; + } + @Override + protected boolean getDirty() { + return conf.shadowsSun != originalValue; + } + }); + } + if(conf.shaderPackInfo.REFLECTIONS_PARABOLOID) { + opts.add(new ShaderOption(loadShaderLbl("REFLECTIONS_PARABOLOID"), loadShaderDesc("REFLECTIONS_PARABOLOID")) { + private final boolean originalValue = conf.useEnvMap; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.useEnvMap, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.useEnvMap = !conf.useEnvMap; + } + @Override + protected boolean getDirty() { + return conf.useEnvMap != originalValue; + } + }); + } + if(conf.shaderPackInfo.POST_LENS_DISTORION) { + opts.add(new ShaderOption(loadShaderLbl("POST_LENS_DISTORION"), loadShaderDesc("POST_LENS_DISTORION")) { + private final boolean originalValue = conf.lensDistortion; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.lensDistortion, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.lensDistortion = !conf.lensDistortion; + } + @Override + protected boolean getDirty() { + return conf.lensDistortion != originalValue; + } + }); + } + if(conf.shaderPackInfo.POST_LENS_FLARES) { + opts.add(new ShaderOption(loadShaderLbl("POST_LENS_FLARES"), loadShaderDesc("POST_LENS_FLARES")) { + private final boolean originalValue = conf.lensFlares; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.lensFlares, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.lensFlares = !conf.lensFlares; + } + @Override + protected boolean getDirty() { + return conf.lensFlares != originalValue; + } + }); + } + if(conf.shaderPackInfo.POST_FXAA) { + opts.add(new ShaderOption(loadShaderLbl("POST_FXAA"), loadShaderDesc("POST_FXAA")) { + private final boolean originalValue = conf.fxaa; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.fxaa, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.fxaa = !conf.fxaa; + } + @Override + protected boolean getDirty() { + return conf.fxaa != originalValue; + } + }); + } + this.addAllOptions(opts); + opts.clear(); + this.list.add(new ListEntryHeader(I18n.format("shaders.gui.headerTier2"))); + if(conf.shaderPackInfo.SHADOWS_COLORED) { + opts.add(new ShaderOption(loadShaderLbl("SHADOWS_COLORED"), loadShaderDesc("SHADOWS_COLORED")) { + private final boolean originalValue = conf.shadowsColored; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.shadowsColored, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.shadowsColored = !conf.shadowsColored; + } + @Override + protected boolean getDirty() { + return conf.shadowsColored != originalValue; + } + }); + } + if(conf.shaderPackInfo.SHADOWS_SMOOTHED) { + opts.add(new ShaderOption(loadShaderLbl("SHADOWS_SMOOTHED"), loadShaderDesc("SHADOWS_SMOOTHED")) { + private final boolean originalValue = conf.shadowsSmoothed; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.shadowsSmoothed, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.shadowsSmoothed = !conf.shadowsSmoothed; + } + @Override + protected boolean getDirty() { + return conf.shadowsSmoothed != originalValue; + } + }); + } + if(conf.shaderPackInfo.REALISTIC_WATER) { + opts.add(new ShaderOption(loadShaderLbl("REALISTIC_WATER"), loadShaderDesc("REALISTIC_WATER")) { + private final boolean originalValue = conf.realisticWater; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.realisticWater, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.realisticWater = !conf.realisticWater; + } + @Override + protected boolean getDirty() { + return conf.realisticWater != originalValue; + } + }); + } + if(conf.shaderPackInfo.POST_BLOOM) { + opts.add(new ShaderOption(loadShaderLbl("POST_BLOOM"), loadShaderDesc("POST_BLOOM")) { + private final boolean originalValue = conf.bloom; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.bloom, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.bloom = !conf.bloom; + } + @Override + protected boolean getDirty() { + return conf.bloom != originalValue; + } + }); + } + if(conf.shaderPackInfo.LIGHT_SHAFTS) { + opts.add(new ShaderOption(loadShaderLbl("LIGHT_SHAFTS"), loadShaderDesc("LIGHT_SHAFTS")) { + private final boolean originalValue = conf.lightShafts; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.lightShafts, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.lightShafts = !conf.lightShafts; + } + @Override + protected boolean getDirty() { + return conf.lightShafts != originalValue; + } + }); + } + if(conf.shaderPackInfo.SCREEN_SPACE_REFLECTIONS) { + opts.add(new ShaderOption(loadShaderLbl("SCREEN_SPACE_REFLECTIONS"), loadShaderDesc("SCREEN_SPACE_REFLECTIONS")) { + private final boolean originalValue = conf.raytracing; + @Override + protected String getDisplayValue() { + return getColoredOnOff(conf.raytracing, EnumChatFormatting.GREEN, EnumChatFormatting.RED); + } + @Override + protected void toggleOption(GuiButton button, int dir) { + conf.raytracing = !conf.raytracing; + } + @Override + protected boolean getDirty() { + return conf.raytracing != originalValue; + } + }); + } + this.addAllOptions(opts); + setAllDisabled(!mcIn.gameSettings.shaders); + } + + public void setAllDisabled(boolean disable) { + for(int i = 0, l = list.size(); i < l; ++i) { + IGuiListEntry etr = list.get(i); + if(etr instanceof ListEntryButtonRow) { + ListEntryButtonRow etr2 = (ListEntryButtonRow)etr; + if(etr2.button1 != null) { + etr2.button1.enabled = !disable; + } + if(etr2.button2 != null) { + etr2.button2.enabled = !disable; + } + if(etr2.button3 != null) { + etr2.button3.enabled = !disable; + } + } + } + } + + @Override + public IGuiListEntry getListEntry(int var1) { + return list.get(var1); + } + + @Override + protected int getSize() { + return list.size(); + } + + @Override + public int getListWidth() { + return 225; + } + + private class ListEntryPackInfo implements IGuiListEntry { + + @Override + public void drawEntry(int entryID, int x, int y, int getListWidth, int var5, int var6, int var7, boolean var8) { + Minecraft mc = Minecraft.getMinecraft(); + ShaderPackInfo info = mc.gameSettings.deferredShaderConf.shaderPackInfo; + String packNameString = info.name; + int strWidth = mc.fontRendererObj.getStringWidth(packNameString) + 40; + if(strWidth < 210) { + strWidth = 210; + } + int x2 = strWidth > getListWidth * 2 ? x : x + (getListWidth - strWidth) / 2; + screen.drawString(mc.fontRendererObj, packNameString, x2 + 38, y + 3, 0xFFFFFF); + screen.drawString(mc.fontRendererObj, "Author: " + info.author, x2 + 38, y + 14, 0xBBBBBB); + screen.drawString(mc.fontRendererObj, "Version: " + info.vers, x2 + 38, y + 25, 0x888888); + List descLines = mc.fontRendererObj.listFormattedStringToWidth(info.desc, strWidth); + for(int i = 0, l = descLines.size(); i < l; ++i) { + screen.drawString(mc.fontRendererObj, descLines.get(i), x2, y + 43 + i * 9, 0xBBBBBB); + } + mc.getTextureManager().bindTexture(shaderPackIcon); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + Gui.drawModalRectWithCustomSizedTexture(x2, y + 2, 0, 0, 32, 32, 32, 32); + } + + @Override + public void setSelected(int var1, int var2, int var3) { + + } + + @Override + public boolean mousePressed(int var1, int var2, int var3, int var4, int var5, int var6) { + return false; + } + + @Override + public void mouseReleased(int var1, int var2, int var3, int var4, int var5, int var6) { + + } + + } + + private class ListEntrySpacing implements IGuiListEntry { + + @Override + public void setSelected(int var1, int var2, int var3) { + + } + + @Override + public void drawEntry(int var1, int var2, int var3, int var4, int var5, int var6, int var7, boolean var8) { + + } + + @Override + public boolean mousePressed(int var1, int var2, int var3, int var4, int var5, int var6) { + return false; + } + + @Override + public void mouseReleased(int var1, int var2, int var3, int var4, int var5, int var6) { + + } + + } + + private class ListEntryHeader implements IGuiListEntry { + + private final String text; + + private ListEntryHeader(String text) { + this.text = text; + } + + @Override + public void setSelected(int var1, int var2, int var3) { + + } + + @Override + public void drawEntry(int entryID, int x, int y, int getListWidth, int var5, int var6, int var7, boolean var8) { + screen.drawString(screen.getFontRenderer(), text, x, y + 10, 0xFFFFFF); + } + + @Override + public boolean mousePressed(int var1, int var2, int var3, int var4, int var5, int var6) { + return false; + } + + @Override + public void mouseReleased(int var1, int var2, int var3, int var4, int var5, int var6) { + + } + + } + + private class ListEntryButtonRow implements IGuiListEntry { + + private final ShaderOption opt1; + private final ShaderOption opt2; + private final ShaderOption opt3; + + private GuiButton button1; + private GuiButton button2; + private GuiButton button3; + + private ListEntryButtonRow(ShaderOption opt1, ShaderOption opt2, ShaderOption opt3) { + this.opt1 = opt1; + this.opt2 = opt2; + this.opt3 = opt3; + if(this.opt1 != null) { + this.button1 = new GuiButton(0, 0, 0, 73, 20, this.opt1.label + ": " + this.opt1.getDisplayValue()); + this.button1.fontScale = 0.78f - (this.opt1.label.length() * 0.01f); + } + if(this.opt2 != null) { + this.button2 = new GuiButton(0, 0, 0, 73, 20, this.opt2.label + ": " + this.opt2.getDisplayValue()); + this.button2.fontScale = 0.78f - (this.opt2.label.length() * 0.01f); + } + if(this.opt3 != null) { + this.button3 = new GuiButton(0, 0, 0, 73, 20, this.opt3.label + ": " + this.opt3.getDisplayValue()); + this.button3.fontScale = 0.78f - (this.opt3.label.length() * 0.01f); + } + } + + @Override + public void setSelected(int var1, int var2, int var3) { + + } + + @Override + public void drawEntry(int entryID, int x, int y, int getListWidth, int var5, int var6, int var7, boolean var8) { + if(this.button1 != null) { + this.button1.xPosition = x; + this.button1.yPosition = y; + this.button1.drawButton(mc, var6, var7); + if(this.button1.isMouseOver() && this.button1.yPosition + 10 < bottom && this.button1.yPosition + 10 > top) { + renderTooltip(var6, var7 + 15, this.opt1.desc); + } + } + if(this.button2 != null) { + this.button2.xPosition = x + 75; + this.button2.yPosition = y; + this.button2.drawButton(mc, var6, var7); + if(this.button2.isMouseOver() && this.button2.yPosition + 10 < bottom && this.button2.yPosition + 10 > top) { + renderTooltip(var6, var7 + 15, this.opt2.desc); + } + } + if(this.button3 != null) { + this.button3.xPosition = x + 150; + this.button3.yPosition = y; + this.button3.drawButton(mc, var6, var7); + if(this.button3.isMouseOver() && this.button3.yPosition + 10 < bottom && this.button3.yPosition + 10 > top) { + renderTooltip(var6, var7 + 15, this.opt3.desc); + } + } + } + + @Override + public boolean mousePressed(int var1, int var2, int var3, int var4, int var5, int var6) { + if(this.button1 != null) { + if(this.button1.yPosition + 15 < bottom && this.button1.yPosition + 5 > top) { + if(this.button1.mousePressed(mc, var2, var3)) { + this.opt1.toggleOption(this.button1, var4 == 1 ? -1 : 1); + this.button1.displayString = (this.opt1.getDirty() ? "*" : "") + this.opt1.label + ": " + this.opt1.getDisplayValue(); + this.button1.playPressSound(mc.getSoundHandler()); + } + } + } + if(this.button2 != null) { + if(this.button2.yPosition + 15 < bottom && this.button2.yPosition + 5 > top) { + if(this.button2.mousePressed(mc, var2, var3)) { + this.opt2.toggleOption(this.button2, var4 == 1 ? -1 : 1); + this.button2.displayString = (this.opt2.getDirty() ? "*" : "") + this.opt2.label + ": " + this.opt2.getDisplayValue(); + this.button2.playPressSound(mc.getSoundHandler()); + } + } + } + if(this.button3 != null) { + if(this.button3.yPosition + 15 < bottom && this.button3.yPosition + 5 > top) { + if(this.button3.mousePressed(mc, var2, var3)) { + this.opt3.toggleOption(this.button3, var4 == 1 ? -1 : 1); + this.button3.displayString = (this.opt3.getDirty() ? "*" : "") + this.opt3.label + ": " + this.opt3.getDisplayValue(); + this.button3.playPressSound(mc.getSoundHandler()); + } + } + } + return false; + } + + @Override + public void mouseReleased(int var1, int var2, int var3, int var4, int var5, int var6) { + + } + + } + + private List tooltipToShow = null; + private int tooltipToShowX = 0; + private int tooltipToShowY = 0; + + public void postRender(int mx, int my, float partialTicks) { + if(tooltipToShow != null) { + screen.width *= 2; + screen.height *= 2; + GlStateManager.pushMatrix(); + GlStateManager.scale(0.5f, 0.5f, 0.5f); + screen.renderTooltip(tooltipToShow, tooltipToShowX * 2, tooltipToShowY * 2); + GlStateManager.popMatrix(); + screen.width /= 2; + screen.height /= 2; + tooltipToShow = null; + } + } + + private void renderTooltip(int x, int y, List msg) { + renderTooltip(x, y, 250, msg); + } + + private void renderTooltip(int x, int y, int width, List msg) { + ArrayList tooltipList = new ArrayList(msg.size() * 2); + for(int i = 0, l = msg.size(); i < l; ++i) { + String s = msg.get(i); + if(s.length() > 0) { + tooltipList.addAll(screen.getFontRenderer().listFormattedStringToWidth(s, width)); + }else { + tooltipList.add(""); + } + } + tooltipToShow = tooltipList; + tooltipToShowX = x; + tooltipToShowY = y; + } + + public boolean isDirty() { + for(int i = 0, l = list.size(); i < l; ++i) { + IGuiListEntry etr = list.get(i); + if(etr instanceof ListEntryButtonRow) { + ListEntryButtonRow etr2 = (ListEntryButtonRow)etr; + if(etr2.opt1 != null) { + if(etr2.opt1.getDirty()) { + return true; + } + } + if(etr2.opt2 != null) { + if(etr2.opt2.getDirty()) { + return true; + } + } + if(etr2.opt3 != null) { + if(etr2.opt3.getDirty()) { + return true; + } + } + } + } + return false; + } + + public void resize() { + width = screen.width; + height = screen.height; + top = 32; + bottom = screen.height - 40; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShadersNotSupported.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShadersNotSupported.java new file mode 100644 index 0000000..6ac9345 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/gui/GuiShadersNotSupported.java @@ -0,0 +1,48 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GuiShadersNotSupported extends GuiScreen { + + private GuiScreen parent; + private String reason; + + public GuiShadersNotSupported(GuiScreen parent, String reason) { + this.parent = parent; + this.reason = reason; + } + + public void initGui() { + this.buttonList.clear(); + this.buttonList.add(new GuiButton(0, width / 2 - 100, height / 2 + 10, I18n.format("gui.back"))); + } + + public void drawScreen(int i, int j, float var3) { + this.drawBackground(0); + drawCenteredString(fontRendererObj, I18n.format("shaders.gui.unsupported.title"), width / 2, height / 2 - 30, 0xFFFFFF); + drawCenteredString(fontRendererObj, reason, width / 2, height / 2 - 10, 11184810); + super.drawScreen(i, j, var3); + } + + protected void actionPerformed(GuiButton parGuiButton) { + if(parGuiButton.id == 0) { + mc.displayGuiScreen(parent); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/GBufferExtPipelineShader.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/GBufferExtPipelineShader.java new file mode 100644 index 0000000..a841931 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/GBufferExtPipelineShader.java @@ -0,0 +1,130 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class GBufferExtPipelineShader extends ShaderProgram { + + public final int coreState; + public final int extState; + + public GBufferExtPipelineShader(IProgramGL program, int coreState, int extState) { + super(program, new Uniforms()); + this.coreState = coreState; + this.extState = extState; + } + + public static class Uniforms implements IProgramUniforms { + + public int materialConstantsSerial = -1; + + public float materialConstantsRoughness = -999.0f; + public float materialConstantsMetalness = -999.0f; + public float materialConstantsEmission = -999.0f; + public float materialConstantsUseEnvMap = -999.0f; + + public IUniformGL u_materialConstants3f = null; + public IUniformGL u_useEnvMap1f = null; + + public int constantBlock = -999; + public float clipPlaneY = -999.0f; + + public IUniformGL u_blockConstant1f = null; + public IUniformGL u_clipPlaneY1f = null; + + public int modelMatrixSerial = -1; + public int viewMatrixSerial = -1; + public int inverseViewMatrixSerial = -1; + public int modelViewProjMatrixAltSerial = -1; + public IUniformGL u_modelMatrix4f = null; + public IUniformGL u_viewMatrix4f = null; + public IUniformGL u_inverseViewMatrix4f = null; + public IUniformGL u_modelViewProjMat4f_ = null; + + public int waterWindOffsetSerial = -1; + public IUniformGL u_waterWindOffset4f = null; + + public int wavingBlockOffsetSerial = -1; + + public float wavingBlockOffsetX = -999.0f; + public float wavingBlockOffsetY = -999.0f; + public float wavingBlockOffsetZ = -999.0f; + + public IUniformGL u_wavingBlockOffset3f = null; + + public int wavingBlockParamSerial = -1; + + public float wavingBlockParamX = -999.0f; + public float wavingBlockParamY = -999.0f; + public float wavingBlockParamZ = -999.0f; + public float wavingBlockParamW = -999.0f; + + public IUniformGL u_wavingBlockParam4f = null; + + public int u_chunkLightingDataBlockBinding = -1; + public int u_worldLightingDataBlockBinding = -1; + + public IUniformGL u_farPlane1f = null; + public float farPlane1f = -1.0f; + + Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_materialConstants3f = _wglGetUniformLocation(prog, "u_materialConstants3f"); + u_useEnvMap1f = _wglGetUniformLocation(prog, "u_useEnvMap1f"); + u_blockConstant1f = _wglGetUniformLocation(prog, "u_blockConstant1f"); + u_clipPlaneY1f = _wglGetUniformLocation(prog, "u_clipPlaneY1f"); + u_modelMatrix4f = _wglGetUniformLocation(prog, "u_modelMatrix4f"); + u_viewMatrix4f = _wglGetUniformLocation(prog, "u_viewMatrix4f"); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_modelViewProjMat4f_ = _wglGetUniformLocation(prog, "u_modelViewProjMat4f_"); + u_wavingBlockOffset3f = _wglGetUniformLocation(prog, "u_wavingBlockOffset3f"); + u_wavingBlockParam4f = _wglGetUniformLocation(prog, "u_wavingBlockParam4f"); + u_farPlane1f = _wglGetUniformLocation(prog, "u_farPlane1f"); + u_waterWindOffset4f = _wglGetUniformLocation(prog, "u_waterWindOffset4f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_samplerNormalMaterial"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_metalsLUT"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowDepthTexture"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_environmentMap"), 5); + _wglUniform1i(_wglGetUniformLocation(prog, "u_brdfLUT"), 6); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reflectionMap"), 7); + _wglUniform1i(_wglGetUniformLocation(prog, "u_refractionMap"), 8); + _wglUniform1i(_wglGetUniformLocation(prog, "u_normalMap"), 9); + _wglUniform1i(_wglGetUniformLocation(prog, "u_irradianceMap"), 10); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lightShaftsTexture"), 11); + int blockIndex = _wglGetUniformBlockIndex(prog, "u_worldLightingData"); + if(blockIndex != -1) { + _wglUniformBlockBinding(prog, blockIndex, 0); + u_worldLightingDataBlockBinding = 0; + }else { + u_worldLightingDataBlockBinding = -1; + } + blockIndex = _wglGetUniformBlockIndex(prog, "u_chunkLightingData"); + if(blockIndex != -1) { + _wglUniformBlockBinding(prog, blockIndex, 1); + u_chunkLightingDataBlockBinding = 1; + }else { + u_chunkLightingDataBlockBinding = -1; + } + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/IProgramUniforms.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/IProgramUniforms.java new file mode 100644 index 0000000..947e118 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/IProgramUniforms.java @@ -0,0 +1,22 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public interface IProgramUniforms { + + void loadUniforms(IProgramGL prog); + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleForward.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleForward.java new file mode 100644 index 0000000..c974c83 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleForward.java @@ -0,0 +1,110 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderAccelParticleForward extends ShaderProgram { + + public static PipelineShaderAccelParticleForward compile(boolean dynamicLights, int sunShadows) { + IShaderGL accelParticleVSH = ShaderCompiler.compileShader("accel_particle_forward", GL_VERTEX_SHADER, + ShaderSource.accel_particle_vsh, "COMPILE_FORWARD_VSH"); + IShaderGL accelParticleFSH = null; + try { + List lst = new ArrayList(2); + if(dynamicLights) { + lst.add("COMPILE_DYNAMIC_LIGHTS"); + } + if(sunShadows > 0) { + int lods = sunShadows - 1; + if(lods > 2) { + lods = 2; + } + lst.add("COMPILE_SUN_SHADOW_LOD" + lods); + } + accelParticleFSH = ShaderCompiler.compileShader("accel_particle_forward", GL_FRAGMENT_SHADER, + ShaderSource.accel_particle_forward_fsh, lst); + IProgramGL prog = ShaderCompiler.linkProgram("accel_particle_forward", accelParticleVSH, accelParticleFSH); + return new PipelineShaderAccelParticleForward(prog); + }finally { + if(accelParticleVSH != null) { + accelParticleVSH.free(); + } + if(accelParticleFSH != null) { + accelParticleFSH.free(); + } + } + } + + private PipelineShaderAccelParticleForward(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_modelViewMatrix4f = null; + public IUniformGL u_projectionMatrix4f = null; + public IUniformGL u_inverseViewMatrix4f = null; + public IUniformGL u_texCoordSize2f_particleSize1f = null; + public IUniformGL u_transformParam_1_2_3_4_f = null; + public IUniformGL u_transformParam_5_f = null; + public IUniformGL u_textureYScale2f = null; + + public int u_chunkLightingDataBlockBinding = -1; + public int u_worldLightingDataBlockBinding = -1; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_modelViewMatrix4f = _wglGetUniformLocation(prog, "u_modelViewMatrix4f"); + u_projectionMatrix4f = _wglGetUniformLocation(prog, "u_projectionMatrix4f"); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_texCoordSize2f_particleSize1f = _wglGetUniformLocation(prog, "u_texCoordSize2f_particleSize1f"); + u_transformParam_1_2_3_4_f = _wglGetUniformLocation(prog, "u_transformParam_1_2_3_4_f"); + u_transformParam_5_f = _wglGetUniformLocation(prog, "u_transformParam_5_f"); + u_textureYScale2f = _wglGetUniformLocation(prog, "u_textureYScale2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_diffuseTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_samplerNormalMaterial"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_metalsLUT"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowDepthTexture"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_irradianceMap"), 10); + int blockIndex = _wglGetUniformBlockIndex(prog, "u_worldLightingData"); + if(blockIndex != -1) { + _wglUniformBlockBinding(prog, blockIndex, 0); + u_worldLightingDataBlockBinding = 0; + }else { + u_worldLightingDataBlockBinding = -1; + } + blockIndex = _wglGetUniformBlockIndex(prog, "u_chunkLightingData"); + if(blockIndex != -1) { + _wglUniformBlockBinding(prog, blockIndex, 1); + u_chunkLightingDataBlockBinding = 1; + }else { + u_chunkLightingDataBlockBinding = -1; + } + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleGBuffer.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleGBuffer.java new file mode 100644 index 0000000..ebad238 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderAccelParticleGBuffer.java @@ -0,0 +1,72 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderAccelParticleGBuffer extends ShaderProgram { + + public static PipelineShaderAccelParticleGBuffer compile() { + IShaderGL accelParticleVSH = ShaderCompiler.compileShader("accel_particle_gbuffer", GL_VERTEX_SHADER, + ShaderSource.accel_particle_vsh, "COMPILE_GBUFFER_VSH"); + IShaderGL accelParticleFSH = null; + try { + accelParticleFSH = ShaderCompiler.compileShader("accel_particle_gbuffer", GL_FRAGMENT_SHADER, + ShaderSource.accel_particle_gbuffer_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("accel_particle_gbuffer", accelParticleVSH, accelParticleFSH); + return new PipelineShaderAccelParticleGBuffer(prog); + }finally { + if(accelParticleVSH != null) { + accelParticleVSH.free(); + } + if(accelParticleFSH != null) { + accelParticleFSH.free(); + } + } + } + + private PipelineShaderAccelParticleGBuffer(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_matrixTransform = null; + public IUniformGL u_texCoordSize2f_particleSize1f = null; + public IUniformGL u_transformParam_1_2_3_4_f = null; + public IUniformGL u_transformParam_5_f = null; + public IUniformGL u_textureYScale2f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_matrixTransform = _wglGetUniformLocation(prog, "u_matrixTransform"); + u_texCoordSize2f_particleSize1f = _wglGetUniformLocation(prog, "u_texCoordSize2f_particleSize1f"); + u_transformParam_1_2_3_4_f = _wglGetUniformLocation(prog, "u_transformParam_1_2_3_4_f"); + u_transformParam_5_f = _wglGetUniformLocation(prog, "u_transformParam_5_f"); + u_textureYScale2f = _wglGetUniformLocation(prog, "u_textureYScale2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_diffuseTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_samplerNormalMaterial"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBlurPass.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBlurPass.java new file mode 100644 index 0000000..3dbaf97 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBlurPass.java @@ -0,0 +1,59 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderBloomBlurPass extends ShaderProgram { + + public static PipelineShaderBloomBlurPass compile() { + IShaderGL bloomBlurPass = ShaderCompiler.compileShader("post_bloom_blur", GL_FRAGMENT_SHADER, + ShaderSource.post_bloom_blur_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_bloom_blur", SharedPipelineShaders.deferred_local, bloomBlurPass); + return new PipelineShaderBloomBlurPass(prog); + }finally { + if(bloomBlurPass != null) { + bloomBlurPass.free(); + } + } + } + + private PipelineShaderBloomBlurPass(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sampleOffset2f = null; + public IUniformGL u_outputSize4f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_sampleOffset2f = _wglGetUniformLocation(prog, "u_sampleOffset2f"); + u_outputSize4f = _wglGetUniformLocation(prog, "u_outputSize4f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_inputTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBrightPass.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBrightPass.java new file mode 100644 index 0000000..1666566 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderBloomBrightPass.java @@ -0,0 +1,60 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderBloomBrightPass extends ShaderProgram { + + public static PipelineShaderBloomBrightPass compile() throws ShaderException { + IShaderGL bloomBrightPass = ShaderCompiler.compileShader("post_bloom_bright", GL_FRAGMENT_SHADER, + ShaderSource.post_bloom_bright_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_bloom_bright", SharedPipelineShaders.deferred_local, bloomBrightPass); + return new PipelineShaderBloomBrightPass(prog); + }finally { + if(bloomBrightPass != null) { + bloomBrightPass.free(); + } + } + } + + private PipelineShaderBloomBrightPass(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_outputSize4f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_outputSize4f = _wglGetUniformLocation(prog, "u_outputSize4f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lightingHDRFramebufferTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_framebufferLumaAvgInput"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferMaterialTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 3); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsNoise3D.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsNoise3D.java new file mode 100644 index 0000000..8e8a489 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsNoise3D.java @@ -0,0 +1,63 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderCloudsNoise3D extends ShaderProgram { + + public static PipelineShaderCloudsNoise3D compile() { + IShaderGL cloudsNoise3d = ShaderCompiler.compileShader("clouds_noise3d", GL_FRAGMENT_SHADER, + ShaderSource.clouds_noise3d_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("clouds_noise3d", SharedPipelineShaders.deferred_local, cloudsNoise3d); + return new PipelineShaderCloudsNoise3D(prog); + }finally { + if(cloudsNoise3d != null) { + cloudsNoise3d.free(); + } + } + } + + private PipelineShaderCloudsNoise3D(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_textureSlice1f = null; + public IUniformGL u_textureSize2f = null; + public IUniformGL u_sampleOffsetMatrix4f = null; + public IUniformGL u_cloudMovement3f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_textureSlice1f = _wglGetUniformLocation(prog, "u_textureSlice1f"); + u_textureSize2f = _wglGetUniformLocation(prog, "u_textureSize2f"); + u_sampleOffsetMatrix4f = _wglGetUniformLocation(prog, "u_sampleOffsetMatrix4f"); + u_cloudMovement3f = _wglGetUniformLocation(prog, "u_cloudMovement3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_noiseTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSample.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSample.java new file mode 100644 index 0000000..f186a2f --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSample.java @@ -0,0 +1,70 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderCloudsSample extends ShaderProgram { + + public static PipelineShaderCloudsSample compile() { + IShaderGL cloudsSample = ShaderCompiler.compileShader("clouds_sample", GL_FRAGMENT_SHADER, + ShaderSource.clouds_sample_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("clouds_sample", SharedPipelineShaders.deferred_local, cloudsSample); + return new PipelineShaderCloudsSample(prog); + }finally { + if(cloudsSample != null) { + cloudsSample.free(); + } + } + } + + private PipelineShaderCloudsSample(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_rainStrength1f = null; + public IUniformGL u_densityModifier4f = null; + public IUniformGL u_sampleStep1f = null; + public IUniformGL u_cloudTimer1f = null; + public IUniformGL u_cloudOffset3f = null; + public IUniformGL u_sunDirection3f = null; + public IUniformGL u_sunColor3f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_rainStrength1f = _wglGetUniformLocation(prog, "u_rainStrength1f"); + u_densityModifier4f = _wglGetUniformLocation(prog, "u_densityModifier4f"); + u_sampleStep1f = _wglGetUniformLocation(prog, "u_sampleStep1f"); + u_cloudTimer1f = _wglGetUniformLocation(prog, "u_cloudTimer1f"); + u_cloudOffset3f = _wglGetUniformLocation(prog, "u_cloudOffset3f"); + u_sunDirection3f = _wglGetUniformLocation(prog, "u_sunDirection3f"); + u_sunColor3f = _wglGetUniformLocation(prog, "u_sunColor3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_noiseTexture3D"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_skyIrradianceMap"), 1); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsShapes.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsShapes.java new file mode 100644 index 0000000..ac30b17 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsShapes.java @@ -0,0 +1,69 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderCloudsShapes extends ShaderProgram { + + public static PipelineShaderCloudsShapes compile() { + IShaderGL cloudsShapesVSH = ShaderCompiler.compileShader("clouds_shapes", GL_VERTEX_SHADER, + ShaderSource.clouds_shapes_vsh); + IShaderGL cloudsShapesFSH = null; + try { + cloudsShapesFSH = ShaderCompiler.compileShader("clouds_shapes", GL_FRAGMENT_SHADER, + ShaderSource.clouds_shapes_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("clouds_shapes", cloudsShapesVSH, cloudsShapesFSH); + return new PipelineShaderCloudsShapes(prog); + }finally { + if(cloudsShapesVSH != null) { + cloudsShapesVSH.free(); + } + if(cloudsShapesFSH != null) { + cloudsShapesFSH.free(); + } + } + } + + private PipelineShaderCloudsShapes(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_textureLevel1f = null; + public IUniformGL u_textureLod1f = null; + public IUniformGL u_transformMatrix3x2f = null; + public IUniformGL u_sampleWeights2f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_textureLevel1f = _wglGetUniformLocation(prog, "u_textureLevel1f"); + u_textureLod1f = _wglGetUniformLocation(prog, "u_textureLod1f"); + u_transformMatrix3x2f = _wglGetUniformLocation(prog, "u_transformMatrix3x2f"); + u_sampleWeights2f = _wglGetUniformLocation(prog, "u_sampleWeights2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_inputTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSunOcclusion.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSunOcclusion.java new file mode 100644 index 0000000..e2de5a5 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderCloudsSunOcclusion.java @@ -0,0 +1,56 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderCloudsSunOcclusion extends ShaderProgram { + + public static PipelineShaderCloudsSunOcclusion compile() { + IShaderGL cloudsOcclusion = ShaderCompiler.compileShader("clouds_sun_occlusion", GL_FRAGMENT_SHADER, + ShaderSource.clouds_sun_occlusion_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("clouds_sun_occlusion", SharedPipelineShaders.deferred_local, cloudsOcclusion); + return new PipelineShaderCloudsSunOcclusion(prog); + }finally { + if(cloudsOcclusion != null) { + cloudsOcclusion.free(); + } + } + } + private PipelineShaderCloudsSunOcclusion(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sampleMatrix4x3f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_sampleMatrix4x3f = _wglGetUniformLocation(prog, "u_sampleMatrix4x3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_cloudsTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderFXAA.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderFXAA.java new file mode 100644 index 0000000..27ed708 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderFXAA.java @@ -0,0 +1,57 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderFXAA extends ShaderProgram { + + public static PipelineShaderFXAA compile() throws ShaderException { + IShaderGL postFXAA = ShaderCompiler.compileShader("post_fxaa", GL_FRAGMENT_SHADER, + ShaderSource.post_fxaa_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_fxaa", SharedPipelineShaders.deferred_local, postFXAA); + return new PipelineShaderFXAA(prog); + }finally { + if(postFXAA != null) { + postFXAA.free(); + } + } + } + + private PipelineShaderFXAA(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_screenSize2f; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_screenTexture"), 0); + u_screenSize2f = _wglGetUniformLocation(prog, "u_screenSize2f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferCombine.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferCombine.java new file mode 100644 index 0000000..65344b1 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferCombine.java @@ -0,0 +1,96 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderGBufferCombine extends ShaderProgram { + + public static PipelineShaderGBufferCombine compile(boolean ssao, boolean env, boolean ssr) throws ShaderException { + IShaderGL coreGBuffer = null; + List compileFlags = new ArrayList(2); + if(ssao) { + compileFlags.add("COMPILE_GLOBAL_AMBIENT_OCCLUSION"); + } + if(env) { + compileFlags.add("COMPILE_ENV_MAP_REFLECTIONS"); + } + if(ssr) { + compileFlags.add("COMPILE_SCREEN_SPACE_REFLECTIONS"); + } + coreGBuffer = ShaderCompiler.compileShader("deferred_combine", GL_FRAGMENT_SHADER, + ShaderSource.deferred_combine_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("deferred_combine", SharedPipelineShaders.deferred_local, coreGBuffer); + return new PipelineShaderGBufferCombine(prog, ssao, env, ssr); + }finally { + if(coreGBuffer != null) { + coreGBuffer.free(); + } + } + } + + private PipelineShaderGBufferCombine(IProgramGL program, boolean ssao, boolean env, boolean ssr) { + super(program, new Uniforms(ssao, env, ssr)); + } + + public static class Uniforms implements IProgramUniforms { + + public final boolean ssao; + public final boolean env; + public final boolean ssr; + + public IUniformGL u_halfResolutionPixelAlignment2f; + public IUniformGL u_inverseProjMatrix4f; + public IUniformGL u_inverseViewMatrix4f; + public IUniformGL u_sunDirection3f; + public IUniformGL u_skyLightFactor1f; + + private Uniforms(boolean ssao, boolean env, boolean ssr) { + this.ssao = ssao; + this.ssr = ssr; + this.env = env; + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferColorTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferMaterialTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_ssaoTexture"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_ssrReflectionTexture"), 5); + _wglUniform1i(_wglGetUniformLocation(prog, "u_environmentMap"), 6); + _wglUniform1i(_wglGetUniformLocation(prog, "u_irradianceMap"), 7); + _wglUniform1i(_wglGetUniformLocation(prog, "u_brdfLUT"), 8); + _wglUniform1i(_wglGetUniformLocation(prog, "u_metalsLUT"), 9); + u_halfResolutionPixelAlignment2f = _wglGetUniformLocation(prog, "u_halfResolutionPixelAlignment2f"); + u_inverseProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjMatrix4f"); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_sunDirection3f = _wglGetUniformLocation(prog, "u_sunDirection3f"); + u_skyLightFactor1f = _wglGetUniformLocation(prog, "u_skyLightFactor1f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferDebugView.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferDebugView.java new file mode 100644 index 0000000..e7b2f6d --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferDebugView.java @@ -0,0 +1,64 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderGBufferDebugView extends ShaderProgram { + + public static PipelineShaderGBufferDebugView compile(int view) throws ShaderException { + IShaderGL debugView = ShaderCompiler.compileShader("gbuffer_debug_view", GL_FRAGMENT_SHADER, + ShaderSource.gbuffer_debug_view_fsh, ("DEBUG_VIEW_" + view)); + try { + IProgramGL prog = ShaderCompiler.linkProgram("gbuffer_debug_view", SharedPipelineShaders.deferred_local, debugView); + return new PipelineShaderGBufferDebugView(prog, view); + }finally { + if(debugView != null) { + debugView.free(); + } + } + } + + private PipelineShaderGBufferDebugView(IProgramGL prog, int mode) { + super(prog, new Uniforms(mode)); + } + + public static class Uniforms implements IProgramUniforms { + + public final int mode; + + public IUniformGL u_inverseViewMatrix = null; + public IUniformGL u_depthSliceStartEnd2f = null; + + private Uniforms(int mode) { + this.mode = mode; + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_texture0"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_texture1"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_texture3D0"), 0); + u_inverseViewMatrix = _wglGetUniformLocation(prog, "u_inverseViewMatrix"); + u_depthSliceStartEnd2f = _wglGetUniformLocation(prog, "u_depthSliceStartEnd2f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferFog.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferFog.java new file mode 100644 index 0000000..87f76d9 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderGBufferFog.java @@ -0,0 +1,84 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderGBufferFog extends ShaderProgram { + + public static PipelineShaderGBufferFog compile(boolean linear, boolean atmosphere, boolean lightShafts) { + List macros = new ArrayList(3); + if(linear) { + macros.add("COMPILE_FOG_LINEAR"); + } + if(atmosphere) { + macros.add("COMPILE_FOG_ATMOSPHERE"); + } + if(lightShafts) { + macros.add("COMPILE_FOG_LIGHT_SHAFTS"); + } + IShaderGL deferredFog = ShaderCompiler.compileShader("deferred_fog", GL_FRAGMENT_SHADER, + ShaderSource.deferred_fog_fsh, macros); + try { + IProgramGL prog = ShaderCompiler.linkProgram("deferred_fog", SharedPipelineShaders.deferred_local, deferredFog); + return new PipelineShaderGBufferFog(prog); + }finally { + if(deferredFog != null) { + deferredFog.free(); + } + } + } + + private PipelineShaderGBufferFog(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_inverseViewProjMatrix4f = null; + public IUniformGL u_linearFogParam2f = null; + public IUniformGL u_expFogDensity1f = null; + public IUniformGL u_fogColorLight4f = null; + public IUniformGL u_fogColorDark4f = null; + public IUniformGL u_sunColorAdd3f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_inverseViewProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewProjMatrix4f"); + u_linearFogParam2f = _wglGetUniformLocation(prog, "u_linearFogParam2f"); + u_expFogDensity1f = _wglGetUniformLocation(prog, "u_expFogDensity1f"); + u_fogColorLight4f = _wglGetUniformLocation(prog, "u_fogColorLight4f"); + u_fogColorDark4f = _wglGetUniformLocation(prog, "u_fogColorDark4f"); + u_sunColorAdd3f = _wglGetUniformLocation(prog, "u_sunColorAdd3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_fogDepthTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_environmentMap"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lightShaftsTexture"), 4); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderHandDepthMask.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderHandDepthMask.java new file mode 100644 index 0000000..8c9f6d8 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderHandDepthMask.java @@ -0,0 +1,53 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderHandDepthMask extends ShaderProgram { + + public static PipelineShaderHandDepthMask compile() { + IShaderGL handDepthMask = ShaderCompiler.compileShader("hand_depth_mask", GL_FRAGMENT_SHADER, + ShaderSource.hand_depth_mask_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("hand_depth_mask", SharedPipelineShaders.deferred_local, handDepthMask); + return new PipelineShaderHandDepthMask(prog); + }finally { + if(handDepthMask != null) { + handDepthMask.free(); + } + } + } + + private PipelineShaderHandDepthMask(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_depthTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensDistortion.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensDistortion.java new file mode 100644 index 0000000..2283bb3 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensDistortion.java @@ -0,0 +1,53 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLensDistortion extends ShaderProgram { + + public static PipelineShaderLensDistortion compile() throws ShaderException { + IShaderGL lensDistort = ShaderCompiler.compileShader("post_lens_distort", GL_FRAGMENT_SHADER, + ShaderSource.post_lens_distort_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_lens_distort", SharedPipelineShaders.deferred_local, lensDistort); + return new PipelineShaderLensDistortion(prog); + }finally { + if(lensDistort != null) { + lensDistort.free(); + } + } + } + + private PipelineShaderLensDistortion(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_inputTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensFlares.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensFlares.java new file mode 100644 index 0000000..42c5d8a --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensFlares.java @@ -0,0 +1,89 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLensFlares extends ShaderProgram { + + public static PipelineShaderLensFlares compileStreaks() { + IShaderGL vertexShader = ShaderCompiler.compileShader("post_lens_streaks", GL_VERTEX_SHADER, + ShaderSource.post_lens_streaks_vsh); + IShaderGL fragmentShader = null; + try { + fragmentShader = ShaderCompiler.compileShader("post_lens_streaks", GL_FRAGMENT_SHADER, + ShaderSource.post_lens_streaks_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("post_lens_streaks", vertexShader, fragmentShader); + return new PipelineShaderLensFlares(prog); + }finally { + if(vertexShader != null) { + vertexShader.free(); + } + if(fragmentShader != null) { + fragmentShader.free(); + } + } + } + + public static PipelineShaderLensFlares compileGhosts() { + IShaderGL vertexShader = ShaderCompiler.compileShader("post_lens_ghosts", GL_VERTEX_SHADER, + ShaderSource.post_lens_ghosts_vsh); + IShaderGL fragmentShader = null; + try { + fragmentShader = ShaderCompiler.compileShader("post_lens_ghosts", GL_FRAGMENT_SHADER, + ShaderSource.post_lens_ghosts_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("post_lens_ghosts", vertexShader, fragmentShader); + return new PipelineShaderLensFlares(prog); + }finally { + if(vertexShader != null) { + vertexShader.free(); + } + if(fragmentShader != null) { + fragmentShader.free(); + } + } + } + + private PipelineShaderLensFlares(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sunFlareMatrix3f = null; + public IUniformGL u_flareColor3f = null; + public IUniformGL u_sunPosition2f = null; + public IUniformGL u_aspectRatio1f = null; + public IUniformGL u_baseScale1f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + u_sunFlareMatrix3f = _wglGetUniformLocation(prog, "u_sunFlareMatrix3f"); + u_flareColor3f = _wglGetUniformLocation(prog, "u_flareColor3f"); + u_sunPosition2f = _wglGetUniformLocation(prog, "u_sunPosition2f"); + u_aspectRatio1f = _wglGetUniformLocation(prog, "u_aspectRatio1f"); + u_baseScale1f = _wglGetUniformLocation(prog, "u_baseScale1f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_flareTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_exposureValue"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunOcclusionValue"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensSunOcclusion.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensSunOcclusion.java new file mode 100644 index 0000000..fd90c0f --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLensSunOcclusion.java @@ -0,0 +1,55 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLensSunOcclusion extends ShaderProgram { + + public static PipelineShaderLensSunOcclusion compile() throws ShaderException { + IShaderGL sunOcclusion = ShaderCompiler.compileShader("lens_sun_occlusion", GL_FRAGMENT_SHADER, + ShaderSource.lens_sun_occlusion_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("lens_sun_occlusion", SharedPipelineShaders.deferred_local, sunOcclusion); + return new PipelineShaderLensSunOcclusion(prog); + }finally { + if(sunOcclusion != null) { + sunOcclusion.free(); + } + } + } + + private PipelineShaderLensSunOcclusion(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sampleMatrix3f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + u_sampleMatrix3f = _wglGetUniformLocation(prog, "u_sampleMatrix3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_depthBufferTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_cloudsSunOcclusion"), 1); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightShaftsSample.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightShaftsSample.java new file mode 100644 index 0000000..01a18d7 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightShaftsSample.java @@ -0,0 +1,80 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.Arrays; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLightShaftsSample extends ShaderProgram { + + public static PipelineShaderLightShaftsSample compile(int shadowsSun) { + if(shadowsSun == 0) { + throw new IllegalStateException("Enable shadows to compile this shader"); + } + int lods = shadowsSun - 1; + if(lods > 2) { + lods = 2; + } + IShaderGL lightShaftsSample = ShaderCompiler.compileShader("light_shafts_sample", GL_FRAGMENT_SHADER, + ShaderSource.light_shafts_sample_fsh, Arrays.asList("COMPILE_SUN_SHADOW_LOD" + lods)); + try { + IProgramGL prog = ShaderCompiler.linkProgram("light_shafts_sample", SharedPipelineShaders.deferred_local, lightShaftsSample); + return new PipelineShaderLightShaftsSample(prog); + }finally { + if(lightShaftsSample != null) { + lightShaftsSample.free(); + } + } + } + + private PipelineShaderLightShaftsSample(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_inverseViewProjMatrix4f = null; + public IUniformGL u_sampleStep1f = null; + public IUniformGL u_eyePosition3f = null; + public IUniformGL u_ditherScale2f = null; + public IUniformGL u_sunShadowMatrixLOD04f = null; + public IUniformGL u_sunShadowMatrixLOD14f = null; + public IUniformGL u_sunShadowMatrixLOD24f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_inverseViewProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewProjMatrix4f"); + u_sampleStep1f = _wglGetUniformLocation(prog, "u_sampleStep1f"); + u_eyePosition3f = _wglGetUniformLocation(prog, "u_eyePosition3f"); + u_ditherScale2f = _wglGetUniformLocation(prog, "u_ditherScale2f"); + u_sunShadowMatrixLOD04f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD04f"); + u_sunShadowMatrixLOD14f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD14f"); + u_sunShadowMatrixLOD24f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD24f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowDepthTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_ditherTexture"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingPoint.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingPoint.java new file mode 100644 index 0000000..1ca5da7 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingPoint.java @@ -0,0 +1,82 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLightingPoint extends ShaderProgram { + + public static PipelineShaderLightingPoint compile(boolean shadows) + throws ShaderException { + List compileFlags = new ArrayList(2); + if(shadows) { + compileFlags.add("COMPILE_PARABOLOID_SHADOW"); + } + IShaderGL lightingPoint = ShaderCompiler.compileShader("lighting_point", GL_FRAGMENT_SHADER, + ShaderSource.lighting_point_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("lighting_point", SharedPipelineShaders.lighting_mesh, lightingPoint); + return new PipelineShaderLightingPoint(prog, shadows); + }finally { + if(lightingPoint != null) { + lightingPoint.free(); + } + } + } + + private PipelineShaderLightingPoint(IProgramGL program, boolean shadows) { + super(program, new Uniforms(shadows)); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_viewportSize2f = null; + public IUniformGL u_modelViewProjMatrix4f = null; + public IUniformGL u_inverseProjectionMatrix4f = null; + public IUniformGL u_inverseViewMatrix4f = null; + public IUniformGL u_lightPosition3f = null; + public IUniformGL u_lightColor3f = null; + + public final boolean shadows; + + private Uniforms(boolean shadows) { + this.shadows = shadows; + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferColorTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferMaterialTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_metalsLUT"), 5); + u_viewportSize2f = _wglGetUniformLocation(prog, "u_viewportSize2f"); + u_modelViewProjMatrix4f = _wglGetUniformLocation(prog, "u_modelViewProjMatrix4f"); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_lightPosition3f = _wglGetUniformLocation(prog, "u_lightPosition3f"); + u_lightColor3f = _wglGetUniformLocation(prog, "u_lightColor3f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingSun.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingSun.java new file mode 100644 index 0000000..a9b70db --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderLightingSun.java @@ -0,0 +1,81 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderLightingSun extends ShaderProgram { + + public static PipelineShaderLightingSun compile(int shadowsSun, boolean coloredShadows) throws ShaderException { + IShaderGL sunShader = null; + List compileFlags = new ArrayList(1); + if(shadowsSun > 0) { + compileFlags.add("COMPILE_SUN_SHADOW"); + } + if(coloredShadows) { + compileFlags.add("COMPILE_COLORED_SHADOW"); + } + sunShader = ShaderCompiler.compileShader("lighting_sun", GL_FRAGMENT_SHADER, + ShaderSource.lighting_sun_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("lighting_sun", SharedPipelineShaders.deferred_local, sunShader); + return new PipelineShaderLightingSun(prog, shadowsSun); + }finally { + if(sunShader != null) { + sunShader.free(); + } + } + } + + private PipelineShaderLightingSun(IProgramGL program, int shadowsSun) { + super(program, new Uniforms(shadowsSun)); + } + + public static class Uniforms implements IProgramUniforms { + + public final int shadowsSun; + public IUniformGL u_inverseViewMatrix4f; + public IUniformGL u_inverseProjectionMatrix4f; + public IUniformGL u_sunDirection3f; + public IUniformGL u_sunColor3f; + + private Uniforms(int shadowsSun) { + this.shadowsSun = shadowsSun; + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferColorTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferMaterialTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowTexture"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_metalsLUT"), 5); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_sunDirection3f = _wglGetUniformLocation(prog, "u_sunDirection3f"); + u_sunColor3f = _wglGetUniformLocation(prog, "u_sunColor3f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderMoonRender.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderMoonRender.java new file mode 100644 index 0000000..878b650 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderMoonRender.java @@ -0,0 +1,72 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderMoonRender extends ShaderProgram { + + public static PipelineShaderMoonRender compile() { + IShaderGL moonRenderVSH = ShaderCompiler.compileShader("moon_render", GL_VERTEX_SHADER, + ShaderSource.moon_render_vsh); + IShaderGL moonRenderFSH = null; + try { + moonRenderFSH = ShaderCompiler.compileShader("moon_render", GL_FRAGMENT_SHADER, + ShaderSource.moon_render_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("moon_render", moonRenderVSH, moonRenderFSH); + return new PipelineShaderMoonRender(prog); + }finally { + if(moonRenderVSH != null) { + moonRenderVSH.free(); + } + if(moonRenderFSH != null) { + moonRenderFSH.free(); + } + } + } + + private PipelineShaderMoonRender(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_modelMatrix4f = null; + public IUniformGL u_viewMatrix4f = null; + public IUniformGL u_projMatrix4f = null; + public IUniformGL u_moonColor3f = null; + public IUniformGL u_lightDir3f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_modelMatrix4f = _wglGetUniformLocation(prog, "u_modelMatrix4f"); + u_viewMatrix4f = _wglGetUniformLocation(prog, "u_viewMatrix4f"); + u_projMatrix4f = _wglGetUniformLocation(prog, "u_projMatrix4f"); + u_moonColor3f = _wglGetUniformLocation(prog, "u_moonColor3f"); + u_lightDir3f = _wglGetUniformLocation(prog, "u_lightDir3f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_moonTextures"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_cloudsTexture"), 1); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureAvg.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureAvg.java new file mode 100644 index 0000000..5d68530 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureAvg.java @@ -0,0 +1,64 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderPostExposureAvg extends ShaderProgram { + + public static PipelineShaderPostExposureAvg compile(boolean luma) throws ShaderException { + List compileFlags = new ArrayList(1); + if(luma) { + compileFlags.add("CALCULATE_LUMINANCE"); + } + IShaderGL postExposureAvg = ShaderCompiler.compileShader("post_exposure_avg", GL_FRAGMENT_SHADER, + ShaderSource.post_exposure_avg_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_exposure_avg", SharedPipelineShaders.deferred_local, postExposureAvg); + return new PipelineShaderPostExposureAvg(prog); + }finally { + if(postExposureAvg != null) { + postExposureAvg.free(); + } + } + } + + private PipelineShaderPostExposureAvg(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sampleOffset4f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_inputTexture"), 0); + u_sampleOffset4f = _wglGetUniformLocation(prog, "u_sampleOffset4f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureFinal.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureFinal.java new file mode 100644 index 0000000..475a55a --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderPostExposureFinal.java @@ -0,0 +1,59 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderPostExposureFinal extends ShaderProgram { + + public static PipelineShaderPostExposureFinal compile() throws ShaderException { + IShaderGL postExposureFinal = ShaderCompiler.compileShader("post_exposure_final", GL_FRAGMENT_SHADER, + ShaderSource.post_exposure_final_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_exposure_final", SharedPipelineShaders.deferred_local, postExposureFinal); + return new PipelineShaderPostExposureFinal(prog); + }finally { + if(postExposureFinal != null) { + postExposureFinal.free(); + } + } + } + + private PipelineShaderPostExposureFinal(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_inputSize2f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_inputTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_exposureValue"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunOcclusionValue"), 2); + u_inputSize2f = _wglGetUniformLocation(prog, "u_inputSize2f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterControl.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterControl.java new file mode 100644 index 0000000..f1fc95c --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterControl.java @@ -0,0 +1,82 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderRealisticWaterControl extends ShaderProgram { + + public static PipelineShaderRealisticWaterControl compile() throws ShaderException { + IShaderGL realisticWaterControl = ShaderCompiler.compileShader("realistic_water_control", GL_FRAGMENT_SHADER, + ShaderSource.realistic_water_control_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("realistic_water_control", SharedPipelineShaders.deferred_local, realisticWaterControl); + return new PipelineShaderRealisticWaterControl(prog); + }finally { + if(realisticWaterControl != null) { + realisticWaterControl.free(); + } + } + } + + public PipelineShaderRealisticWaterControl(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_inverseProjectionMatrix4f = null; + public IUniformGL u_inverseViewProjMatrix4f = null; + public IUniformGL u_reprojectionMatrix4f = null; + public IUniformGL u_lastInverseProjMatrix4f = null; + public IUniformGL u_reprojectionInverseViewMatrix4f = null; + public IUniformGL u_projectionMatrix4f = null; + public IUniformGL u_viewToPreviousProjMatrix4f = null; + public IUniformGL u_nearFarPlane4f = null; + public IUniformGL u_pixelAlignment4f = null; + public IUniformGL u_refractFogColor4f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferColorTexture4f"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_realisticWaterMaskNormal"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_realisticWaterDepthTexture"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameReflectionInput4f"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameHitVectorInput4f"), 5); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameColorTexture"), 6); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameDepthTexture"), 7); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_inverseViewProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewProjMatrix4f"); + u_reprojectionMatrix4f = _wglGetUniformLocation(prog, "u_reprojectionMatrix4f"); + u_lastInverseProjMatrix4f = _wglGetUniformLocation(prog, "u_lastInverseProjMatrix4f"); + u_reprojectionInverseViewMatrix4f = _wglGetUniformLocation(prog, "u_reprojectionInverseViewMatrix4f"); + u_projectionMatrix4f = _wglGetUniformLocation(prog, "u_projectionMatrix4f"); + u_viewToPreviousProjMatrix4f = _wglGetUniformLocation(prog, "u_viewToPreviousProjMatrix4f"); + u_nearFarPlane4f = _wglGetUniformLocation(prog, "u_nearFarPlane4f"); + u_pixelAlignment4f = _wglGetUniformLocation(prog, "u_pixelAlignment4f"); + u_refractFogColor4f = _wglGetUniformLocation(prog, "u_refractFogColor4f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNoise.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNoise.java new file mode 100644 index 0000000..80e40b7 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNoise.java @@ -0,0 +1,54 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderRealisticWaterNoise extends ShaderProgram { + + public static PipelineShaderRealisticWaterNoise compile() throws ShaderException { + IShaderGL realisticWaterNoise = ShaderCompiler.compileShader("realistic_water_noise", GL_FRAGMENT_SHADER, + ShaderSource.realistic_water_noise_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("realistic_water_noise", SharedPipelineShaders.deferred_local, realisticWaterNoise); + return new PipelineShaderRealisticWaterNoise(prog); + }finally { + if(realisticWaterNoise != null) { + realisticWaterNoise.free(); + } + } + } + + private PipelineShaderRealisticWaterNoise(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_waveTimer4f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_noiseTexture"), 0); + u_waveTimer4f = _wglGetUniformLocation(prog, "u_waveTimer4f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNormalMap.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNormalMap.java new file mode 100644 index 0000000..07b242e --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderRealisticWaterNormalMap.java @@ -0,0 +1,54 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderRealisticWaterNormalMap extends ShaderProgram { + + public static PipelineShaderRealisticWaterNormalMap compile() throws ShaderException { + IShaderGL realisticWaterNormals = ShaderCompiler.compileShader("realistic_water_normals", GL_FRAGMENT_SHADER, + ShaderSource.realistic_water_normals_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("realistic_water_normals", SharedPipelineShaders.deferred_local, realisticWaterNormals); + return new PipelineShaderRealisticWaterNormalMap(prog); + }finally { + if(realisticWaterNormals != null) { + realisticWaterNormals.free(); + } + } + } + + private PipelineShaderRealisticWaterNormalMap(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sampleOffset2f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_displacementTexture"), 0); + u_sampleOffset2f = _wglGetUniformLocation(prog, "u_sampleOffset2f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojControl.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojControl.java new file mode 100644 index 0000000..956f849 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojControl.java @@ -0,0 +1,88 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderReprojControl extends ShaderProgram { + + public static PipelineShaderReprojControl compile(boolean ssao, boolean ssr) throws ShaderException { + List compileFlags = new ArrayList(2); + if(ssao) { + compileFlags.add("COMPILE_REPROJECT_SSAO"); + } + if(ssr) { + compileFlags.add("COMPILE_REPROJECT_SSR"); + } + IShaderGL reprojControl = ShaderCompiler.compileShader("reproj_control", GL_FRAGMENT_SHADER, + ShaderSource.reproject_control_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("reproj_control", SharedPipelineShaders.deferred_local, reprojControl); + return new PipelineShaderReprojControl(prog, ssao, ssr); + }finally { + if(reprojControl != null) { + reprojControl.free(); + } + } + } + + private PipelineShaderReprojControl(IProgramGL prog, boolean ssao, boolean ssr) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_inverseViewProjMatrix4f = null; + public IUniformGL u_projectionMatrix4f = null; + public IUniformGL u_reprojectionMatrix4f = null; + public IUniformGL u_inverseProjectionMatrix4f = null; + public IUniformGL u_lastInverseProjMatrix4f = null; + public IUniformGL u_reprojectionInverseViewMatrix4f = null; + public IUniformGL u_viewToPreviousProjMatrix4f = null; + public IUniformGL u_nearFarPlane4f = null; + public IUniformGL u_pixelAlignment4f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_ssaoSampleTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionSSAOInput4f"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionReflectionInput4f"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionHitVectorInput4f"), 5); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameColorInput4f"), 6); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionDepthTexture"), 7); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferMaterialTexture"), 8); + u_inverseViewProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewProjMatrix4f"); + u_projectionMatrix4f = _wglGetUniformLocation(prog, "u_projectionMatrix4f"); + u_reprojectionMatrix4f = _wglGetUniformLocation(prog, "u_reprojectionMatrix4f"); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_lastInverseProjMatrix4f = _wglGetUniformLocation(prog, "u_lastInverseProjMatrix4f"); + u_reprojectionInverseViewMatrix4f = _wglGetUniformLocation(prog, "u_reprojectionInverseViewMatrix4f"); + u_viewToPreviousProjMatrix4f = _wglGetUniformLocation(prog, "u_viewToPreviousProjMatrix4f"); + u_nearFarPlane4f = _wglGetUniformLocation(prog, "u_nearFarPlane4f"); + u_pixelAlignment4f = _wglGetUniformLocation(prog, "u_pixelAlignment4f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojSSR.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojSSR.java new file mode 100644 index 0000000..22129ea --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderReprojSSR.java @@ -0,0 +1,67 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderReprojSSR extends ShaderProgram { + + public static PipelineShaderReprojSSR compile() throws ShaderException { + IShaderGL reprojSSR = ShaderCompiler.compileShader("reproj_ssr", GL_FRAGMENT_SHADER, + ShaderSource.reproject_ssr_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("reproj_ssr", SharedPipelineShaders.deferred_local, reprojSSR); + return new PipelineShaderReprojSSR(prog); + }finally { + if(reprojSSR != null) { + reprojSSR.free(); + } + } + } + + private PipelineShaderReprojSSR(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_lastProjectionMatrix4f; + public IUniformGL u_lastInverseProjMatrix4x2f; + public IUniformGL u_inverseProjectionMatrix4f; + public IUniformGL u_sampleStep1f; + public IUniformGL u_pixelAlignment4f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionReflectionInput4f"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_reprojectionHitVectorInput4f"), 3); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameColorInput4f"), 4); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lastFrameDepthInput"), 5); + u_lastProjectionMatrix4f = _wglGetUniformLocation(prog, "u_lastProjectionMatrix4f"); + u_lastInverseProjMatrix4x2f = _wglGetUniformLocation(prog, "u_lastInverseProjMatrix4x2f"); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_sampleStep1f = _wglGetUniformLocation(prog, "u_sampleStep1f"); + u_pixelAlignment4f = _wglGetUniformLocation(prog, "u_pixelAlignment4f"); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSSAOGenerate.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSSAOGenerate.java new file mode 100644 index 0000000..978bf40 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSSAOGenerate.java @@ -0,0 +1,60 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderSSAOGenerate extends ShaderProgram { + + public static PipelineShaderSSAOGenerate compile() throws ShaderException { + IShaderGL ssaoGenerate = ShaderCompiler.compileShader("ssao_generate", GL_FRAGMENT_SHADER, + ShaderSource.ssao_generate_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("ssao_generate", SharedPipelineShaders.deferred_local, ssaoGenerate); + return new PipelineShaderSSAOGenerate(prog); + }finally { + if(ssaoGenerate != null) { + ssaoGenerate.free(); + } + } + } + + private PipelineShaderSSAOGenerate(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_projectionMatrix4f; + public IUniformGL u_inverseProjectionMatrix4f; + public IUniformGL u_randomizerDataMatrix2f; + + @Override + public void loadUniforms(IProgramGL prog) { + u_projectionMatrix4f = _wglGetUniformLocation(prog, "u_projectionMatrix4f"); + u_inverseProjectionMatrix4f = _wglGetUniformLocation(prog, "u_inverseProjectionMatrix4f"); + u_randomizerDataMatrix2f = _wglGetUniformLocation(prog, "u_randomizerDataMatrix2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_noiseConstantTexture"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderShadowsSun.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderShadowsSun.java new file mode 100644 index 0000000..49f16db --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderShadowsSun.java @@ -0,0 +1,95 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderShadowsSun extends ShaderProgram { + + public static PipelineShaderShadowsSun compile(int shadowsSun, boolean shadowsSunSmooth, boolean coloredShadows) + throws ShaderException { + IShaderGL shadowShader = null; + List compileFlags = new ArrayList(2); + if(shadowsSun == 0) { + throw new IllegalStateException("Enable shadows to compile this shader"); + } + int lods = shadowsSun - 1; + if(lods > 2) { + lods = 2; + } + compileFlags.add("COMPILE_SUN_SHADOW_LOD" + lods); + if(shadowsSunSmooth) { + compileFlags.add("COMPILE_SUN_SHADOW_SMOOTH"); + } + if(coloredShadows) { + compileFlags.add("COMPILE_COLORED_SHADOW"); + } + shadowShader = ShaderCompiler.compileShader("shadows_sun", GL_FRAGMENT_SHADER, + ShaderSource.shadows_sun_fsh, compileFlags); + try { + IProgramGL prog = ShaderCompiler.linkProgram("shadows_sun", SharedPipelineShaders.deferred_local, shadowShader); + return new PipelineShaderShadowsSun(prog, shadowsSun, shadowsSunSmooth); + }finally { + if(shadowShader != null) { + shadowShader.free(); + } + } + } + + private PipelineShaderShadowsSun(IProgramGL program, int shadowsSun, boolean shadowsSunSmooth) { + super(program, new Uniforms(shadowsSun, shadowsSunSmooth)); + } + + public static class Uniforms implements IProgramUniforms { + + public final int shadowsSun; + public final boolean shadowsSunSmooth; + public IUniformGL u_inverseViewMatrix4f; + public IUniformGL u_inverseViewProjMatrix4f; + public IUniformGL u_sunShadowMatrixLOD04f; + public IUniformGL u_sunShadowMatrixLOD14f; + public IUniformGL u_sunShadowMatrixLOD24f; + public IUniformGL u_sunDirection3f; + + private Uniforms(int shadowsSun, boolean shadowsSunSmooth) { + this.shadowsSun = shadowsSun; + this.shadowsSunSmooth = shadowsSunSmooth; + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferNormalTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_gbufferDepthTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowDepthTexture"), 2); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunShadowColorTexture"), 3); + u_inverseViewMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewMatrix4f"); + u_inverseViewProjMatrix4f = _wglGetUniformLocation(prog, "u_inverseViewProjMatrix4f"); + u_sunShadowMatrixLOD04f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD04f"); + u_sunShadowMatrixLOD14f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD14f"); + u_sunShadowMatrixLOD24f = _wglGetUniformLocation(prog, "u_sunShadowMatrixLOD24f"); + u_sunDirection3f = _wglGetUniformLocation(prog, "u_sunDirection3f"); + } + + } + + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxAtmosphere.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxAtmosphere.java new file mode 100644 index 0000000..b3712fb --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxAtmosphere.java @@ -0,0 +1,57 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderSkyboxAtmosphere extends ShaderProgram { + + public static PipelineShaderSkyboxAtmosphere compile() throws ShaderException { + IShaderGL skyboxAtmosphere = ShaderCompiler.compileShader("skybox_atmosphere", GL_FRAGMENT_SHADER, + ShaderSource.skybox_atmosphere_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("skybox_atmosphere", SharedPipelineShaders.deferred_local, skyboxAtmosphere); + return new PipelineShaderSkyboxAtmosphere(prog); + }finally { + if(skyboxAtmosphere != null) { + skyboxAtmosphere.free(); + } + } + } + + private PipelineShaderSkyboxAtmosphere(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_sunDirectionIntensity4f = null; + public IUniformGL u_altitude1f = null; + public IUniformGL u_blendColor4f = null; + + @Override + public void loadUniforms(IProgramGL prog) { + u_sunDirectionIntensity4f = _wglGetUniformLocation(prog, "u_sunDirectionIntensity4f"); + u_altitude1f = _wglGetUniformLocation(prog, "u_altitude1f"); + u_blendColor4f = _wglGetUniformLocation(prog, "u_blendColor4f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_skyNormals"), 0); + } + + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxIrradiance.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxIrradiance.java new file mode 100644 index 0000000..a2200bd --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxIrradiance.java @@ -0,0 +1,55 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.Arrays; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderSkyboxIrradiance extends ShaderProgram { + + public static PipelineShaderSkyboxIrradiance compile(int phase) throws ShaderException { + IShaderGL skyboxIrradiance = ShaderCompiler.compileShader("skybox_irradiance", GL_FRAGMENT_SHADER, + ShaderSource.skybox_irradiance_fsh, Arrays.asList("PHASE_" + phase)); + try { + IProgramGL prog = ShaderCompiler.linkProgram("skybox_irradiance", SharedPipelineShaders.deferred_local, skyboxIrradiance); + return new PipelineShaderSkyboxIrradiance(prog); + }finally { + if(skyboxIrradiance != null) { + skyboxIrradiance.free(); + } + } + } + + private PipelineShaderSkyboxIrradiance(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + _wglUniform1i(_wglGetUniformLocation(prog, "u_paraboloidSkyboxTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRender.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRender.java new file mode 100644 index 0000000..4294b63 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRender.java @@ -0,0 +1,88 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderSkyboxRender extends ShaderProgram { + + public static PipelineShaderSkyboxRender compile(boolean paraboloid, boolean clouds) throws ShaderException { + List compileFlags = new ArrayList(); + if(paraboloid) { + compileFlags.add("COMPILE_PARABOLOID_SKY"); + } + if(clouds) { + compileFlags.add("COMPILE_CLOUDS"); + } + IShaderGL vertexShader = ShaderCompiler.compileShader("skybox_render", GL_VERTEX_SHADER, + ShaderSource.skybox_render_vsh, compileFlags); + IShaderGL fragmentShader = null; + try { + fragmentShader = ShaderCompiler.compileShader("skybox_render", GL_FRAGMENT_SHADER, + ShaderSource.skybox_render_fsh, compileFlags); + IProgramGL prog = ShaderCompiler.linkProgram("skybox_render", vertexShader, fragmentShader); + return new PipelineShaderSkyboxRender(prog, paraboloid); + }finally { + if(vertexShader != null) { + vertexShader.free(); + } + if(fragmentShader != null) { + fragmentShader.free(); + } + } + } + + private PipelineShaderSkyboxRender(IProgramGL program, boolean paraboloid) { + super(program, new Uniforms(paraboloid)); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_viewMatrix4f = null; + public IUniformGL u_projMatrix4f = null; + public IUniformGL u_sunDirection3f = null; + public IUniformGL u_sunColor3f = null; + public IUniformGL u_lightningColor4f = null; + public IUniformGL u_farPlane1f = null; + + public final boolean paraboloid; + + private Uniforms(boolean paraboloid) { + this.paraboloid = paraboloid; + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_viewMatrix4f = _wglGetUniformLocation(prog, "u_viewMatrix4f"); + u_projMatrix4f = _wglGetUniformLocation(prog, "u_projMatrix4f"); + u_sunDirection3f = _wglGetUniformLocation(prog, "u_sunDirection3f"); + u_sunColor3f = _wglGetUniformLocation(prog, "u_sunColor3f"); + u_lightningColor4f = _wglGetUniformLocation(prog, "u_lightningColor4f"); + u_farPlane1f = _wglGetUniformLocation(prog, "u_farPlane1f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_renderedAtmosphere"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_cloudsTexture"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_sunOcclusion"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRenderEnd.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRenderEnd.java new file mode 100644 index 0000000..9048a3c --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderSkyboxRenderEnd.java @@ -0,0 +1,67 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderSkyboxRenderEnd extends ShaderProgram { + + public static PipelineShaderSkyboxRenderEnd compile() throws ShaderException { + IShaderGL vertexShader = ShaderCompiler.compileShader("skybox_render_end", GL_VERTEX_SHADER, + ShaderSource.skybox_render_end_vsh); + IShaderGL fragmentShader = null; + try { + fragmentShader = ShaderCompiler.compileShader("skybox_render_end", GL_FRAGMENT_SHADER, + ShaderSource.skybox_render_end_fsh); + IProgramGL prog = ShaderCompiler.linkProgram("skybox_render_end", vertexShader, fragmentShader); + return new PipelineShaderSkyboxRenderEnd(prog); + }finally { + if(vertexShader != null) { + vertexShader.free(); + } + if(fragmentShader != null) { + fragmentShader.free(); + } + } + } + + private PipelineShaderSkyboxRenderEnd(IProgramGL prog) { + super(prog, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_viewMatrix4f = null; + public IUniformGL u_projMatrix4f = null; + public IUniformGL u_skyTextureScale2f = null; + + private Uniforms() { + } + + @Override + public void loadUniforms(IProgramGL prog) { + u_viewMatrix4f = _wglGetUniformLocation(prog, "u_viewMatrix4f"); + u_projMatrix4f = _wglGetUniformLocation(prog, "u_projMatrix4f"); + u_skyTextureScale2f = _wglGetUniformLocation(prog, "u_skyTextureScale2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_skyTexture"), 0); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderTonemap.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderTonemap.java new file mode 100644 index 0000000..b56980e --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/PipelineShaderTonemap.java @@ -0,0 +1,58 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PipelineShaderTonemap extends ShaderProgram { + + public static PipelineShaderTonemap compile() throws ShaderException { + IShaderGL tonemapOperator = ShaderCompiler.compileShader("post_tonemap", GL_FRAGMENT_SHADER, + ShaderSource.post_tonemap_fsh); + try { + IProgramGL prog = ShaderCompiler.linkProgram("post_tonemap", SharedPipelineShaders.deferred_local, tonemapOperator); + return new PipelineShaderTonemap(prog); + }finally { + if(tonemapOperator != null) { + tonemapOperator.free(); + } + } + } + + private PipelineShaderTonemap(IProgramGL program) { + super(program, new Uniforms()); + } + + public static class Uniforms implements IProgramUniforms { + + public IUniformGL u_exposure3f; + public IUniformGL u_ditherScale2f; + + @Override + public void loadUniforms(IProgramGL prog) { + u_exposure3f = _wglGetUniformLocation(prog, "u_exposure3f"); + u_ditherScale2f = _wglGetUniformLocation(prog, "u_ditherScale2f"); + _wglUniform1i(_wglGetUniformLocation(prog, "u_lightingHDRFramebufferTexture"), 0); + _wglUniform1i(_wglGetUniformLocation(prog, "u_framebufferLumaAvgInput"), 1); + _wglUniform1i(_wglGetUniformLocation(prog, "u_ditherTexture"), 2); + } + + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompileException.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompileException.java new file mode 100644 index 0000000..5062724 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompileException.java @@ -0,0 +1,27 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderCompileException extends ShaderException { + + public final int stage; + public final String fileName; + + public ShaderCompileException(String shaderName, int stage, String fileName, String msg) { + super(shaderName, msg); + this.stage = stage; + this.fileName = fileName; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompiler.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompiler.java new file mode 100644 index 0000000..bbb70bf --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderCompiler.java @@ -0,0 +1,123 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.Arrays; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderCompiler { + + private static final Logger logger = LogManager.getLogger("DeferredPipelineCompiler"); + + public static IShaderGL compileShader(String name, int stage, ResourceLocation filename, String... compileFlags) throws ShaderCompileException { + return compileShader(name, stage, filename.toString(), ShaderSource.getSourceFor(filename), Arrays.asList(compileFlags)); + } + + public static IShaderGL compileShader(String name, int stage, String filename, String source, String... compileFlags) throws ShaderCompileException { + return compileShader(name, stage, filename, source, Arrays.asList(compileFlags)); + } + + public static IShaderGL compileShader(String name, int stage, ResourceLocation filename, List compileFlags) throws ShaderCompileException { + return compileShader(name, stage, filename.toString(), ShaderSource.getSourceFor(filename), compileFlags); + } + + public static IShaderGL compileShader(String name, int stage, String filename, String source, List compileFlags) throws ShaderCompileException { + logger.info("Compiling Shader: " + filename); + StringBuilder srcCat = new StringBuilder(); + srcCat.append(FixedFunctionShader.FixedFunctionConstants.VERSION).append('\n'); + + if(compileFlags != null && compileFlags.size() > 0) { + for(int i = 0, l = compileFlags.size(); i < l; ++i) { + srcCat.append("#define ").append(compileFlags.get(i)).append('\n'); + } + } + + IShaderGL ret = _wglCreateShader(stage); + _wglShaderSource(ret, srcCat.append(source).toString()); + _wglCompileShader(ret); + + if(_wglGetShaderi(ret, GL_COMPILE_STATUS) != GL_TRUE) { + logger.error("Failed to compile {} \"{}\" of program \"{}\"!", getStageName(stage), filename, name); + String log = _wglGetShaderInfoLog(ret); + if(log != null) { + String s2 = getStageNameV2(stage); + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + logger.error("[{}] [{}] [{}] {}", name, s2, filename, lines[i]); + } + } + _wglDeleteShader(ret); + throw new ShaderCompileException(name, stage, filename, "Compile status for " + getStageName(stage) + " \"" + filename + "\" of \"" + name + "\" is not GL_TRUE!"); + } + + return ret; + } + + public static IProgramGL linkProgram(String name, IShaderGL vert, IShaderGL frag) throws ShaderLinkException { + IProgramGL ret = _wglCreateProgram(); + + _wglAttachShader(ret, vert); + _wglAttachShader(ret, frag); + _wglLinkProgram(ret); + _wglDetachShader(ret, vert); + _wglDetachShader(ret, frag); + + if(_wglGetProgrami(ret, GL_LINK_STATUS) != GL_TRUE) { + logger.error("Failed to link program \"{}\"!", name); + String log = _wglGetProgramInfoLog(ret); + if(log != null) { + String[] lines = log.split("(\\r\\n|\\r|\\n)"); + for(int i = 0; i < lines.length; ++i) { + logger.error("[{}] [LINK] {}", name, lines[i]); + } + } + _wglDeleteProgram(ret); + throw new ShaderLinkException(name, "Link status for program \"" + name + "\" is not GL_TRUE!"); + } + + return ret; + } + + private static String getStageName(int stage) { + switch(stage) { + case GL_VERTEX_SHADER: + return "GL_VERTEX_SHADER"; + case GL_FRAGMENT_SHADER: + return "GL_FRAGMENT_SHADER"; + default: + return "stage_" + stage; + } + } + + private static String getStageNameV2(int stage) { + switch(stage) { + case GL_VERTEX_SHADER: + return "VERT"; + case GL_FRAGMENT_SHADER: + return "FRAG"; + default: + return "stage_" + stage; + } + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderException.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderException.java new file mode 100644 index 0000000..20808e6 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderException.java @@ -0,0 +1,25 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderException extends IllegalStateException { + + public final String shaderName; + + public ShaderException(String shaderName, String msg) { + super(msg); + this.shaderName = shaderName; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderLinkException.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderLinkException.java new file mode 100644 index 0000000..814efbd --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderLinkException.java @@ -0,0 +1,22 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderLinkException extends ShaderException { + + public ShaderLinkException(String shaderName, String msg) { + super(shaderName, msg); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderProgram.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderProgram.java new file mode 100644 index 0000000..52c397c --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderProgram.java @@ -0,0 +1,45 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderProgram { + + public final IProgramGL program; + public final U uniforms; + + public ShaderProgram(IProgramGL program, U uniforms) { + this.program = program; + this.uniforms = uniforms; + } + + public ShaderProgram loadUniforms() { + if(uniforms != null) { + EaglercraftGPU.bindGLShaderProgram(program); + uniforms.loadUniforms(program); + } + return this; + } + + public void useProgram() { + EaglercraftGPU.bindGLShaderProgram(program); + } + + public void destroy() { + program.free(); + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderSource.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderSource.java new file mode 100644 index 0000000..cdacf3e --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/ShaderSource.java @@ -0,0 +1,186 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.text.StrTokenizer; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class ShaderSource { + + private static final Logger logger = LogManager.getLogger("ShaderSource"); + + public static final ResourceLocation accel_particle_vsh = new ResourceLocation("eagler:glsl/deferred/accel_particle.vsh"); + public static final ResourceLocation accel_particle_gbuffer_fsh = new ResourceLocation("eagler:glsl/deferred/accel_particle_gbuffer.fsh"); + public static final ResourceLocation accel_particle_forward_fsh = new ResourceLocation("eagler:glsl/deferred/accel_particle_forward.fsh"); + public static final ResourceLocation deferred_core_vsh = new ResourceLocation("eagler:glsl/deferred/deferred_core.vsh"); + public static final ResourceLocation deferred_core_gbuffer_fsh = new ResourceLocation("eagler:glsl/deferred/deferred_core_gbuffer.fsh"); + public static final ResourceLocation deferred_shadow_vsh = new ResourceLocation("eagler:glsl/deferred/deferred_shadow.vsh"); + public static final ResourceLocation deferred_shadow_fsh = new ResourceLocation("eagler:glsl/deferred/deferred_shadow.fsh"); + public static final ResourceLocation deferred_local_vsh = new ResourceLocation("eagler:glsl/deferred/deferred_local.vsh"); + public static final ResourceLocation deferred_combine_fsh = new ResourceLocation("eagler:glsl/deferred/deferred_combine.fsh"); + public static final ResourceLocation deferred_fog_fsh = new ResourceLocation("eagler:glsl/deferred/deferred_fog.fsh"); + public static final ResourceLocation forward_core_vsh = new ResourceLocation("eagler:glsl/deferred/forward_core.vsh"); + public static final ResourceLocation forward_core_fsh = new ResourceLocation("eagler:glsl/deferred/forward_core.fsh"); + public static final ResourceLocation forward_glass_highlights_vsh = new ResourceLocation("eagler:glsl/deferred/forward_glass_highlights.vsh"); + public static final ResourceLocation forward_glass_highlights_fsh = new ResourceLocation("eagler:glsl/deferred/forward_glass_highlights.fsh"); + public static final ResourceLocation realistic_water_mask_vsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_mask.vsh"); + public static final ResourceLocation realistic_water_mask_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_mask.fsh"); + public static final ResourceLocation realistic_water_render_vsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_render.vsh"); + public static final ResourceLocation realistic_water_render_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_render.fsh"); + public static final ResourceLocation realistic_water_control_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_control.fsh"); + public static final ResourceLocation realistic_water_normals_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_normals.fsh"); + public static final ResourceLocation realistic_water_noise_fsh = new ResourceLocation("eagler:glsl/deferred/realistic_water_noise.fsh"); + public static final ResourceLocation gbuffer_debug_view_fsh = new ResourceLocation("eagler:glsl/deferred/gbuffer_debug_view.fsh"); + public static final ResourceLocation ssao_generate_fsh = new ResourceLocation("eagler:glsl/deferred/ssao_generate.fsh"); + public static final ResourceLocation lighting_sun_fsh = new ResourceLocation("eagler:glsl/deferred/lighting_sun.fsh"); + public static final ResourceLocation shadows_sun_fsh = new ResourceLocation("eagler:glsl/deferred/shadows_sun.fsh"); + public static final ResourceLocation light_shafts_sample_fsh = new ResourceLocation("eagler:glsl/deferred/light_shafts_sample.fsh"); + public static final ResourceLocation post_tonemap_fsh = new ResourceLocation("eagler:glsl/deferred/post_tonemap.fsh"); + public static final ResourceLocation post_bloom_bright_fsh = new ResourceLocation("eagler:glsl/deferred/post_bloom_bright.fsh"); + public static final ResourceLocation post_bloom_blur_fsh = new ResourceLocation("eagler:glsl/deferred/post_bloom_blur.fsh"); + public static final ResourceLocation post_lens_distort_fsh = new ResourceLocation("eagler:glsl/deferred/post_lens_distort.fsh"); + public static final ResourceLocation post_exposure_avg_fsh = new ResourceLocation("eagler:glsl/deferred/post_exposure_avg.fsh"); + public static final ResourceLocation post_exposure_final_fsh = new ResourceLocation("eagler:glsl/deferred/post_exposure_final.fsh"); + public static final ResourceLocation post_lens_streaks_vsh = new ResourceLocation("eagler:glsl/deferred/post_lens_streaks.vsh"); + public static final ResourceLocation post_lens_streaks_fsh = new ResourceLocation("eagler:glsl/deferred/post_lens_streaks.fsh"); + public static final ResourceLocation post_lens_ghosts_vsh = new ResourceLocation("eagler:glsl/deferred/post_lens_ghosts.vsh"); + public static final ResourceLocation post_lens_ghosts_fsh = new ResourceLocation("eagler:glsl/deferred/post_lens_ghosts.fsh"); + public static final ResourceLocation lens_sun_occlusion_fsh = new ResourceLocation("eagler:glsl/deferred/lens_sun_occlusion.fsh"); + public static final ResourceLocation skybox_atmosphere_fsh = new ResourceLocation("eagler:glsl/deferred/skybox_atmosphere.fsh"); + public static final ResourceLocation skybox_irradiance_fsh = new ResourceLocation("eagler:glsl/deferred/skybox_irradiance.fsh"); + public static final ResourceLocation skybox_render_vsh = new ResourceLocation("eagler:glsl/deferred/skybox_render.vsh"); + public static final ResourceLocation skybox_render_fsh = new ResourceLocation("eagler:glsl/deferred/skybox_render.fsh"); + public static final ResourceLocation skybox_render_end_vsh = new ResourceLocation("eagler:glsl/deferred/skybox_render_end.vsh"); + public static final ResourceLocation skybox_render_end_fsh = new ResourceLocation("eagler:glsl/deferred/skybox_render_end.fsh"); + public static final ResourceLocation moon_render_vsh = new ResourceLocation("eagler:glsl/deferred/moon_render.vsh"); + public static final ResourceLocation moon_render_fsh = new ResourceLocation("eagler:glsl/deferred/moon_render.fsh"); + public static final ResourceLocation clouds_noise3d_fsh = new ResourceLocation("eagler:glsl/deferred/clouds_noise3d.fsh"); + public static final ResourceLocation clouds_shapes_fsh = new ResourceLocation("eagler:glsl/deferred/clouds_shapes.fsh"); + public static final ResourceLocation clouds_shapes_vsh = new ResourceLocation("eagler:glsl/deferred/clouds_shapes.vsh"); + public static final ResourceLocation clouds_sample_fsh = new ResourceLocation("eagler:glsl/deferred/clouds_sample.fsh"); + public static final ResourceLocation clouds_sun_occlusion_fsh = new ResourceLocation("eagler:glsl/deferred/clouds_sun_occlusion.fsh"); + public static final ResourceLocation clouds_color_fsh = new ResourceLocation("eagler:glsl/deferred/clouds_color.fsh"); + public static final ResourceLocation lighting_mesh_vsh = new ResourceLocation("eagler:glsl/deferred/lighting_mesh.vsh"); + public static final ResourceLocation lighting_point_fsh = new ResourceLocation("eagler:glsl/deferred/lighting_point.fsh"); + public static final ResourceLocation reproject_control_fsh = new ResourceLocation("eagler:glsl/deferred/reproject_control.fsh"); + public static final ResourceLocation reproject_ssr_fsh = new ResourceLocation("eagler:glsl/deferred/reproject_ssr.fsh"); + public static final ResourceLocation post_fxaa_fsh = new ResourceLocation("eagler:glsl/deferred/post_fxaa.fsh"); + public static final ResourceLocation hand_depth_mask_fsh = new ResourceLocation("eagler:glsl/deferred/hand_depth_mask.fsh"); + + private static final Map sourceCache = new HashMap(); + + private static boolean isHighP = false; + + public static String getSourceFor(ResourceLocation path) { + return getSourceFor(path, 0); + } + + private static String getSourceFor(ResourceLocation path, int lineNumberOffset) { + String str = sourceCache.get(path); + if(str == null) { + try { + str = loadSource(path, lineNumberOffset); + }catch(IOException ex) { + str = ""; + logger.error("Could not load shader source \"{}\"! {}", deferred_core_vsh, ex.toString()); + logger.error("This may cause a NullPointerException when enabling certain features"); + logger.error(ex); + } + sourceCache.put(path, str); + } + return str.length() == 0 ? null : str; + } + + private static String loadSource(ResourceLocation resourceLocation, int fileID) throws IOException { + StringBuilder ret = new StringBuilder(); + try(InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream()) { + int lineCounter = 1; + BufferedReader lineReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + String line; + while((line = lineReader.readLine()) != null) { + if(line.startsWith("#line ")) { + String[] split = line.split("\\s+", 3); + try { + lineCounter = Integer.parseInt(split[1]); + }catch(NumberFormatException ex) { + throw new IOException("Invalid preprocessor directive: " + line, ex); + } + ret.append("#line ").append(lineCounter).append(' ').append(fileID).append('\n'); + }else if(line.startsWith("#EAGLER ")) { + StrTokenizer tokenizer = new StrTokenizer(line.substring(8)); + tokenizer.setDelimiterChar(' '); + tokenizer.setIgnoreEmptyTokens(true); + tokenizer.setQuoteChar('\"'); + if(tokenizer.hasNext()) { + String p1 = tokenizer.next(); + if(p1.equals("INCLUDE") && tokenizer.hasNext()) { + String fileIDStr = tokenizer.next(); + if(tokenizer.hasNext() && fileIDStr.charAt(0) == '(' && fileIDStr.charAt(fileIDStr.length() - 1) == ')') { + String includePath = tokenizer.next(); + if(!tokenizer.hasNext()) { // ignore if there are extra arguments + int newFileId = -1; + try { + newFileId = Integer.parseInt(fileIDStr.substring(1, fileIDStr.length() - 1)); + }catch(NumberFormatException ex) { + } + if(newFileId != -1) { + newFileId += fileID * 100; + ret.append('\n').append("////////////////////////////////////////////////////////////////////").append('\n'); + ret.append("//" + line).append('\n'); + ret.append("#line 1 ").append(newFileId).append('\n'); + ret.append(getSourceFor(new ResourceLocation(includePath), newFileId)).append('\n'); + ret.append("////////////////////////////////////////////////////////////////////").append('\n'); + ret.append("#line ").append(lineCounter - 1).append(' ').append(fileID).append('\n').append('\n'); + ++lineCounter; + continue; + } + } + } + } + } + logger.error("Skipping invalid preprocessor directive: " + line); + ret.append("// [INVALID]: " + line).append('\n'); + }else if(isHighP && line.startsWith("precision")) { + ret.append(line.replace("lowp", "highp").replace("mediump", "highp")).append('\n'); + }else { + ret.append(line).append('\n'); + } + ++lineCounter; + } + } + return ret.toString(); + } + + public static void clearCache() { + sourceCache.clear(); + logger.info("Cleared Cache"); + } + + public static void setHighP(boolean b) { + isHighP = b; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/SharedPipelineShaders.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/SharedPipelineShaders.java new file mode 100644 index 0000000..1319eb2 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/program/SharedPipelineShaders.java @@ -0,0 +1,42 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program; + +import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class SharedPipelineShaders { + + public static IShaderGL deferred_local = null; + public static IShaderGL lighting_mesh = null; + + public static void init() throws ShaderException { + free(); + deferred_local = ShaderCompiler.compileShader("deferred_local_vsh", GL_VERTEX_SHADER, ShaderSource.deferred_local_vsh); + lighting_mesh = ShaderCompiler.compileShader("lighting_mesh", GL_VERTEX_SHADER, ShaderSource.lighting_mesh_vsh); + } + + public static void free() { + if(deferred_local != null) { + deferred_local.free(); + deferred_local = null; + } + if(lighting_mesh != null) { + lighting_mesh.free(); + lighting_mesh = null; + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerBitwisePackedTexture.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerBitwisePackedTexture.java new file mode 100644 index 0000000..dd2a72d --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerBitwisePackedTexture.java @@ -0,0 +1,76 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.IOException; +import java.io.InputStream; + +import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class EaglerBitwisePackedTexture { + + private static int getFromBits(int idxx, int bits, byte[] bytes) { + int startByte = idxx >> 3; + int endByte = (idxx + bits - 1) >> 3; + if(startByte == endByte) { + return (((int)bytes[startByte] & 0xff) >> (8 - (idxx & 7) - bits)) & ((1 << bits) - 1); + }else { + return (((((int)bytes[startByte] & 0xff) << 8) | ((int)bytes[endByte] & 0xff)) >> (16 - (idxx & 7) - bits)) & ((1 << bits) - 1); + } + } + + public static ImageData loadTexture(InputStream is, int alpha) throws IOException { + if(is.read() != '%' || is.read() != 'E' || is.read() != 'B' || is.read() != 'P') { + throw new IOException("Not an EBP file!"); + } + int v = is.read(); + if(v != 1) { + throw new IOException("Unknown EBP version: " + v); + } + v = is.read(); + if(v != 3) { + throw new IOException("Invalid component count: " + v); + } + int w = is.read() | (is.read() << 8); + int h = is.read() | (is.read() << 8); + ImageData img = new ImageData(w, h, true); + alpha <<= 24; + v = is.read(); + if(v == 0) { + for(int i = 0, l = w * h; i < l; ++i) { + img.pixels[i] = is.read() | (is.read() << 8) | (is.read() << 16) | alpha; + } + }else if(v == 1) { + int paletteSize = is.read(); + int[] palette = new int[paletteSize + 1]; + palette[0] = alpha; + for(int i = 0; i < paletteSize; ++i) { + palette[i + 1] = is.read() | (is.read() << 8) | (is.read() << 16) | alpha; + } + int bpp = is.read(); + byte[] readSet = new byte[is.read() | (is.read() << 8) | (is.read() << 16)]; + is.read(readSet); + for(int i = 0, l = w * h; i < l; ++i) { + img.pixels[i] = palette[getFromBits(i * bpp, bpp, readSet)]; + } + }else { + throw new IOException("Unknown EBP storage type: " + v); + } + if(is.read() != ':' || is.read() != '>') { + throw new IOException("Invalid footer! (:>)"); + } + return img; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerTextureAtlasSpritePBR.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerTextureAtlasSpritePBR.java new file mode 100644 index 0000000..7e2ff49 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EaglerTextureAtlasSpritePBR.java @@ -0,0 +1,312 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Callable; + +import com.google.common.collect.Lists; + +import net.lax1dude.eaglercraft.v1_8.HString; +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite; +import net.lax1dude.eaglercraft.v1_8.minecraft.TextureAnimationCache; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; +import net.minecraft.client.renderer.texture.TextureUtil; +import net.minecraft.client.resources.data.AnimationFrame; +import net.minecraft.client.resources.data.AnimationMetadataSection; +import net.minecraft.crash.CrashReport; +import net.minecraft.crash.CrashReportCategory; +import net.minecraft.util.ReportedException; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class EaglerTextureAtlasSpritePBR extends EaglerTextureAtlasSprite { + + private static final Logger logger = LogManager.getLogger("EaglerTextureAtlasSpritePBR"); + + protected List[] frameTextureDataPBR = new List[] { Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList() }; + protected TextureAnimationCache[] animationCachePBR = new TextureAnimationCache[3]; + + public boolean dontAnimateNormals = true; + public boolean dontAnimateMaterial = true; + + public static EaglerTextureAtlasSpritePBR makeAtlasSprite(ResourceLocation spriteResourceLocation) { + String s = spriteResourceLocation.toString(); + return (EaglerTextureAtlasSpritePBR) (locationNameClock.equals(s) ? new TextureClockPBRImpl(s) + : (locationNameCompass.equals(s) ? new TextureCompassPBRImpl(s) : new EaglerTextureAtlasSpritePBR(s))); + } + + public EaglerTextureAtlasSpritePBR(String spriteName) { + super(spriteName); + } + + public void loadSpritePBR(ImageData[][] imageDatas, AnimationMetadataSection meta, + boolean dontAnimateNormals, boolean dontAnimateMaterial) { + this.resetSprite(); + if(imageDatas.length != 3) { + throw new IllegalArgumentException("loadSpritePBR required an array of 3 different textures (" + imageDatas.length + " given)"); + } + this.dontAnimateNormals = dontAnimateNormals; + this.dontAnimateMaterial = dontAnimateMaterial; + int i = imageDatas[0][0].width; + int j = imageDatas[0][0].height; + this.width = i; + this.height = j; + int[][][] aint = new int[3][imageDatas[0].length][]; + + for (int l = 0; l < imageDatas.length; ++l) { + ImageData[] images = imageDatas[l]; + for (int k = 0; k < images.length; ++k) { + ImageData bufferedimage = images[k]; + if (bufferedimage != null) { + if (k > 0 && (bufferedimage.width) != i >> k || bufferedimage.height != j >> k) { + throw new RuntimeException( + HString.format("Unable to load miplevel: %d, image is size: %dx%d, expected %dx%d", + new Object[] { Integer.valueOf(k), Integer.valueOf(bufferedimage.width), + Integer.valueOf(bufferedimage.height), Integer.valueOf(i >> k), + Integer.valueOf(j >> k) })); + } + + aint[l][k] = new int[bufferedimage.width * bufferedimage.height]; + bufferedimage.getRGB(0, 0, bufferedimage.width, bufferedimage.height, aint[l][k], 0, bufferedimage.width); + } + } + } + + if (meta == null) { + if (j != i) { + throw new RuntimeException("broken aspect ratio and not an animation"); + } + + this.frameTextureDataPBR[0].add(aint[0]); + this.frameTextureDataPBR[1].add(aint[1]); + this.frameTextureDataPBR[2].add(aint[2]); + } else { + int j1 = j / i; + int k1 = i; + int l = i; + this.height = this.width; + if (meta.getFrameCount() > 0) { + Iterator iterator = meta.getFrameIndexSet().iterator(); + + while (iterator.hasNext()) { + int i1 = ((Integer) iterator.next()).intValue(); + if (i1 >= j1) { + throw new RuntimeException("invalid frameindex " + i1); + } + + this.allocateFrameTextureData(i1); + this.frameTextureDataPBR[0].set(i1, getFrameTextureData(aint[0], k1, l, i1)); + this.frameTextureDataPBR[1].set(i1, getFrameTextureData(aint[1], k1, l, i1)); + this.frameTextureDataPBR[2].set(i1, getFrameTextureData(aint[2], k1, l, i1)); + } + + this.animationMetadata = meta; + } else { + ArrayList arraylist = Lists.newArrayList(); + + for (int l1 = 0; l1 < j1; ++l1) { + this.frameTextureDataPBR[0].add(getFrameTextureData(aint[0], k1, l, l1)); + this.frameTextureDataPBR[1].add(getFrameTextureData(aint[1], k1, l, l1)); + this.frameTextureDataPBR[2].add(getFrameTextureData(aint[2], k1, l, l1)); + arraylist.add(new AnimationFrame(l1, -1)); + } + + this.animationMetadata = new AnimationMetadataSection(arraylist, this.width, this.height, + meta.getFrameTime(), meta.isInterpolate()); + } + } + } + + public int[][][] getFramePBRTextureData(int index) { + return new int[][][] { frameTextureDataPBR[0].get(index), + frameTextureDataPBR[1].get(index), + frameTextureDataPBR[2].get(index) }; + } + + public int[][] getFrameTextureData(int index) { + return frameTextureDataPBR[0].get(index); + } + + public int getFrameCount() { + return frameTextureDataPBR[0].size(); + } + + public void setFramesTextureDataPBR(List[] newFramesTextureData) { + frameTextureDataPBR = newFramesTextureData; + } + + protected void allocateFrameTextureData(int index) { + for(int j = 0; j < 3; ++j) { + if (this.frameTextureDataPBR[j].size() <= index) { + for (int i = this.frameTextureDataPBR[j].size(); i <= index; ++i) { + this.frameTextureDataPBR[j].add((int[][]) null); + } + } + } + } + + public void generateMipmaps(int level) { + List[] arraylist = new List[] { Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList() }; + + for(int j = 0; j < 3; ++j) { + for (int i = 0; i < this.frameTextureDataPBR[j].size(); ++i) { + final int[][] aint = (int[][]) this.frameTextureDataPBR[j].get(i); + if (aint != null) { + try { + if(j == 0) { + arraylist[j].add(TextureUtil.generateMipmapData(level, this.width, aint)); + }else { + arraylist[j].add(PBRTextureMapUtils.generateMipmapDataIgnoreAlpha(level, this.width, aint)); + } + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Generating mipmaps for frame (pbr)"); + CrashReportCategory crashreportcategory = crashreport.makeCategory("Frame being iterated"); + crashreportcategory.addCrashSection("PBR Layer", Integer.valueOf(j)); + crashreportcategory.addCrashSection("Frame index", Integer.valueOf(i)); + crashreportcategory.addCrashSectionCallable("Frame sizes", new Callable() { + public String call() throws Exception { + StringBuilder stringbuilder = new StringBuilder(); + + for (int[] aint1 : aint) { + if (stringbuilder.length() > 0) { + stringbuilder.append(", "); + } + + stringbuilder.append(aint1 == null ? "null" : Integer.valueOf(aint1.length)); + } + + return stringbuilder.toString(); + } + }); + throw new ReportedException(crashreport); + } + } + } + } + + this.setFramesTextureDataPBR(arraylist); + this.bakeAnimationCache(); + } + + public void bakeAnimationCache() { + if(animationMetadata != null) { + for(int i = 0; i < 3; ++i) { + if(dontAnimateNormals && i == 1) continue; + if(dontAnimateMaterial && i == 2) continue; + int mipLevels = frameTextureDataPBR[i].get(0).length; + if(animationCachePBR[i] == null) { + animationCachePBR[i] = new TextureAnimationCache(width, height, mipLevels); + } + animationCachePBR[i].initialize(frameTextureDataPBR[i]); + } + } + } + + public void updateAnimationPBR(IFramebufferGL[] copyColorFramebuffer, IFramebufferGL[] copyMaterialFramebuffer, int materialTexOffset) { + if(animationCachePBR[0] == null || (!dontAnimateNormals && animationCachePBR[1] == null) + || (!dontAnimateMaterial && animationCachePBR[2] == null)) { + throw new IllegalStateException("Animation cache for '" + this.iconName + "' was never baked!"); + } + ++this.tickCounter; + if (this.tickCounter >= this.animationMetadata.getFrameTimeSingle(this.frameCounter)) { + int i = this.animationMetadata.getFrameIndex(this.frameCounter); + int j = this.animationMetadata.getFrameCount() == 0 ? this.frameTextureDataPBR[0].size() + : this.animationMetadata.getFrameCount(); + this.frameCounter = (this.frameCounter + 1) % j; + this.tickCounter = 0; + int k = this.animationMetadata.getFrameIndex(this.frameCounter); + if (i != k && k >= 0 && k < this.frameTextureDataPBR[0].size()) { + animationCachePBR[0].copyFrameLevelsToTex2D(k, this.originX, this.originY, this.width, this.height, copyColorFramebuffer); + if(!dontAnimateNormals) animationCachePBR[1].copyFrameLevelsToTex2D(k, this.originX, this.originY, this.width, this.height, copyMaterialFramebuffer); + if(!dontAnimateMaterial) animationCachePBR[2].copyFrameLevelsToTex2D(k, this.originX, this.originY + materialTexOffset, this.width, this.height, copyMaterialFramebuffer); + } + } else if (this.animationMetadata.isInterpolate()) { + float f = 1.0f - (float) this.tickCounter / (float) this.animationMetadata.getFrameTimeSingle(this.frameCounter); + int i = this.animationMetadata.getFrameIndex(this.frameCounter); + int j = this.animationMetadata.getFrameCount() == 0 ? this.frameTextureDataPBR[0].size() + : this.animationMetadata.getFrameCount(); + int k = this.animationMetadata.getFrameIndex((this.frameCounter + 1) % j); + if (i != k && k >= 0 && k < this.frameTextureDataPBR[0].size()) { + animationCachePBR[0].copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY, this.width, this.height, copyColorFramebuffer); + if(!dontAnimateNormals) animationCachePBR[1].copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY, this.width, this.height, copyMaterialFramebuffer); + if(!dontAnimateMaterial) animationCachePBR[2].copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY + materialTexOffset, this.width, this.height, copyMaterialFramebuffer); + } + } + } + + public void clearFramesTextureData() { + for(int i = 0; i < 3; ++i) { + this.frameTextureDataPBR[i].clear(); + if(this.animationCachePBR[i] != null) { + this.animationCachePBR[i].free(); + this.animationCachePBR[i] = null; + } + } + } + + public void loadSprite(ImageData[] images, AnimationMetadataSection meta) throws IOException { + Throwable t = new UnsupportedOperationException("Cannot call regular loadSprite in PBR mode, use loadSpritePBR"); + try { + throw t; + }catch(Throwable tt) { + logger.error(t); + } + } + + public void setFramesTextureData(List newFramesTextureData) { + Throwable t = new UnsupportedOperationException("Cannot call regular setFramesTextureData in PBR mode, use setFramesTextureDataPBR"); + try { + throw t; + }catch(Throwable tt) { + logger.error(t); + } + } + + public void updateAnimation(IFramebufferGL[] fb) { + Throwable t = new UnsupportedOperationException("Cannot call regular updateAnimation in PBR mode, use updateAnimationPBR"); + try { + throw t; + }catch(Throwable tt) { + logger.error(t); + } + } + + protected void resetSprite() { + this.animationMetadata = null; + this.setFramesTextureDataPBR(new List[] { Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList() }); + this.frameCounter = 0; + this.tickCounter = 0; + for(int i = 0; i < 3; ++i) { + if(this.animationCachePBR[i] != null) { + this.animationCachePBR[i].free(); + this.animationCachePBR[i] = null; + } + } + } + + public String toString() { + return "EaglerTextureAtlasSpritePBR{name=\'" + this.iconName + '\'' + ", frameCount=" + this.framesTextureData.size() + + ", rotated=" + this.rotated + ", x=" + this.originX + ", y=" + this.originY + ", height=" + + this.height + ", width=" + this.width + ", u0=" + this.minU + ", u1=" + this.maxU + ", v0=" + + this.minV + ", v1=" + this.maxV + '}'; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EmissiveItems.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EmissiveItems.java new file mode 100644 index 0000000..3707f17 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/EmissiveItems.java @@ -0,0 +1,86 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class EmissiveItems implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger("EmissiveItemsCSV"); + + private static final Map entries = new HashMap(); + + public static float[] getItemEmission(ItemStack itemStack) { + return getItemEmission(itemStack.getItem(), itemStack.getItemDamage()); + } + + public static float[] getItemEmission(Item item, int damage) { + return entries.get(Item.itemRegistry.getNameForObject(item).toString() + "#" + damage); + } + + @Override + public void onResourceManagerReload(IResourceManager var1) { + try { + IResource itemsCsv = var1.getResource(new ResourceLocation("eagler:glsl/deferred/emissive_items.csv")); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(itemsCsv.getInputStream(), StandardCharsets.UTF_8))) { + entries.clear(); + String line; + boolean firstLine = true; + while((line = reader.readLine()) != null) { + if((line = line.trim()).length() > 0) { + if(firstLine) { + firstLine = false; + continue; + } + String[] split = line.split(","); + if(split.length == 6) { + try { + int dmg = Integer.parseInt(split[1]); + float r = Float.parseFloat(split[2]); + float g = Float.parseFloat(split[3]); + float b = Float.parseFloat(split[4]); + float i = Float.parseFloat(split[5]); + r *= i; + g *= i; + b *= i; + entries.put(split[0] + "#" + dmg, new float[] { r, g, b }); + continue; + }catch(NumberFormatException ex) { + } + } + logger.error("Skipping bad emissive item entry: {}", line); + } + } + } + }catch(Throwable t) { + logger.error("Could not load list of emissive items!"); + logger.error(t); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/IEEE754.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/IEEE754.java new file mode 100644 index 0000000..345fd5f --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/IEEE754.java @@ -0,0 +1,32 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +public class IEEE754 { + + // source: https://stackoverflow.com/questions/6162651/half-precision-floating-point-in-java + + public static int encodeHalfFloat(float fval) { + int fbits = Float.floatToIntBits(fval); + int sign = fbits >>> 16 & 0x8000; // sign only + int val = (fbits & 0x7fffffff) + 0x1000; // rounded value + + if (val >= 0x47800000) // might be or become NaN/Inf + { // avoid Inf due to rounding + if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become NaN/Inf + if (val < 0x7f800000) // was value but too large + return sign | 0x7c00; // make it +/-Inf + return sign | 0x7c00 | // remains +/-Inf or NaN + (fbits & 0x007fffff) >>> 13; // keep NaN (and Inf) bits + } + return sign | 0x7bff; // unrounded not quite Inf + } + if (val >= 0x38800000) // remains normalized value + return sign | val - 0x38000000 >>> 13; // exp - 127 + 15 + if (val < 0x33000000) // too small for subnormal + return sign; // becomes +/-0 + val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc + return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit + + (0x800000 >>> val - 102) // round depending on cut off + >>> 126 - val); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0 + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/MetalsLUT.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/MetalsLUT.java new file mode 100644 index 0000000..4bf5fe9 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/MetalsLUT.java @@ -0,0 +1,149 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +/** + * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class MetalsLUT implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger("MetalsLUT"); + + private static int glTexture = -1; + + public static int getGLTexture() { + if(glTexture == -1) { + float[] lut = new float[128]; + for(int i = 0, j; i < 16; ++i) { + j = i << 3; + lut[i] = 1.0f; + lut[i + 1] = 1.0f; + lut[i + 2] = 1.0f; + lut[i + 3] = 0.0f; + lut[i + 4] = 1.0f; + lut[i + 5] = 1.0f; + lut[i + 6] = 1.0f; + lut[i + 7] = 0.0f; + } + try { + IResource metalsCsv = Minecraft.getMinecraft().getResourceManager() + .getResource(new ResourceLocation("eagler:glsl/deferred/metals.csv")); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(metalsCsv.getInputStream(), StandardCharsets.UTF_8))) { + String line; + int cnt = 0; + boolean firstLine = true; + while((line = reader.readLine()) != null) { + if((line = line.trim()).length() > 0) { + if(firstLine) { + firstLine = false; + continue; + } + String[] split = line.split(","); + if(split.length == 8) { + try { + int id = Integer.parseInt(split[1]); + float nr = Float.parseFloat(split[2]); + float ng = Float.parseFloat(split[3]); + float nb = Float.parseFloat(split[4]); + float kr = Float.parseFloat(split[5]); + float kg = Float.parseFloat(split[6]); + float kb = Float.parseFloat(split[7]); + if(id < 230 || id > 245) { + logger.error("Error, only metal IDs 230 to 245 are configurable!"); + }else { + int i = (id - 230) << 3; + lut[i] = nr; + lut[i + 1] = ng; + lut[i + 2] = nb; + lut[i + 4] = kr; + lut[i + 5] = kg; + lut[i + 6] = kb; + } + ++cnt; + continue; + }catch(NumberFormatException ex) { + } + } + logger.error("Skipping bad metal constant entry: {}", line); + } + } + logger.info("Loaded {} metal definitions", cnt); + } + } catch (IOException e) { + logger.error("Failed to load PBR metal lookup table!"); + logger.error(e); + } + if(EaglercraftGPU.checkHDRFramebufferSupport(16)) { + ByteBuffer pixels = EagRuntime.allocateByteBuffer(256); + for(int i = 0; i < 128; ++i) { + pixels.putShort((short)IEEE754.encodeHalfFloat(lut[i])); + } + pixels.flip(); + glTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(glTexture); + setupFiltering(); + EaglercraftGPU.createFramebufferHDR16FTexture(GL_TEXTURE_2D, 0, 2, 16, GL_RGBA, pixels); + EagRuntime.freeByteBuffer(pixels); + }else if(EaglercraftGPU.checkHDRFramebufferSupport(32)) { + logger.warn("16-bit HDR textures are not supported, using 32-bit fallback format"); + ByteBuffer pixels = EagRuntime.allocateByteBuffer(512); + for(int i = 0; i < 128; ++i) { + pixels.putFloat(lut[i]); + } + pixels.flip(); + glTexture = GlStateManager.generateTexture(); + GlStateManager.bindTexture(glTexture); + setupFiltering(); + EaglercraftGPU.createFramebufferHDR32FTexture(GL_TEXTURE_2D, 0, 2, 16, GL_RGBA, pixels); + EagRuntime.freeByteBuffer(pixels); + }else { + throw new UnsupportedOperationException("HDR textures are unavailable, could not create PBR metal definition LUT!"); + } + } + return glTexture; + } + + @Override + public void onResourceManagerReload(IResourceManager var1) { + if(glTexture != -1) { + GlStateManager.deleteTexture(glTexture); + glTexture = -1; + } + } + + private static void setupFiltering() { + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + _wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRMaterialConstants.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRMaterialConstants.java new file mode 100644 index 0000000..e526f0d --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRMaterialConstants.java @@ -0,0 +1,84 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PBRMaterialConstants implements IResourceManagerReloadListener { + + public static final Logger logger = LogManager.getLogger("PBRMaterialConstants"); + + public final ResourceLocation resourceLocation; + public final Map spriteNameToMaterialConstants = new HashMap(); + + public int defaultMaterial = 0x00000A77; + + public PBRMaterialConstants(ResourceLocation resourceLocation) { + this.resourceLocation = resourceLocation; + } + + @Override + public void onResourceManagerReload(IResourceManager var1) { + try(InputStream is = var1.getResource(resourceLocation).getInputStream()) { + spriteNameToMaterialConstants.clear(); + BufferedReader bf = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + String line; + boolean firstLine = true; + while((line = bf.readLine()) != null) { + if((line = line.trim()).length() == 0) { + continue; + } + if(firstLine) { + firstLine = false; + continue; + } + String[] cols = line.split(","); + if(cols.length == 4) { + try { + int value = Integer.parseInt(cols[1]) | (Integer.parseInt(cols[2]) << 8) | (Integer.parseInt(cols[3]) << 16); + if(cols[0].equals("default")) { + defaultMaterial = value; + }else { + Integer v = spriteNameToMaterialConstants.get(cols[0]); + if(v == null) { + spriteNameToMaterialConstants.put(cols[0], value); + }else if(v.intValue() != value) { + logger.warn("Inconsistent material definition for sprite \"{}\": {}", cols[0], line); + } + } + continue; + }catch(NumberFormatException fmt) { + } + } + logger.error("Skipping bad material constant entry: {}", line); + } + }catch(IOException ex) { + logger.error("Could not load \"{}\"!", resourceLocation.toString()); + logger.error(ex); + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRTextureMapUtils.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRTextureMapUtils.java new file mode 100644 index 0000000..3e51324 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/PBRTextureMapUtils.java @@ -0,0 +1,168 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; +import net.minecraft.client.renderer.texture.TextureUtil; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class PBRTextureMapUtils { + + public static final ImageData defaultNormalsTexture = new ImageData(1, 1, new int[] { 0 }, true); + + public static final PBRMaterialConstants blockMaterialConstants = new PBRMaterialConstants(new ResourceLocation("eagler:glsl/deferred/material_block_constants.csv")); + + public static final Logger logger = LogManager.getLogger("PBRTextureMap"); + + public static ImageData locateCompanionTexture(IResourceManager resMgr, IResource mainImage, String ext) { + ResourceLocation baseLocation = mainImage.getResourceLocation(); + String domain = baseLocation.getResourceDomain(); + String resourcePack = mainImage.getResourcePackName(); + String fname = baseLocation.getResourcePath(); + int idx = fname.lastIndexOf('.'); + if(idx != -1) { + fname = fname.substring(0, idx) + ext + fname.substring(idx); + }else { + fname += ext; + } + try { + List ress = resMgr.getAllResources(new ResourceLocation(domain, fname)); + for(IResource res : ress) { + if(res.getResourcePackName().equals(resourcePack)) { + ImageData toRet = TextureUtil.readBufferedImage(res.getInputStream()); + if(ext.equals("_s")) { + for(int i = 0, j; i < toRet.pixels.length; ++i) { + // swap B and A, because labPBR support + int a = (toRet.pixels[i] >>> 24) & 0xFF; + if(a == 0xFF) a = 0; + toRet.pixels[i] = (toRet.pixels[i] & 0x0000FFFF) | Math.min(a << 18, 0xFF0000) | 0xFF000000; + } + } + return toRet; + } + } + }catch(Throwable t) { + } + if("Default".equals(resourcePack)) { + idx = fname.lastIndexOf('.'); + if(idx != -1) { + fname = fname.substring(0, idx); + } + try { + return TextureUtil.readBufferedImage(resMgr.getResource(new ResourceLocation("eagler:glsl/deferred/assets_pbr/" + fname + ".png")).getInputStream()); + }catch(Throwable t) { + } + try { + return EaglerBitwisePackedTexture.loadTexture(resMgr.getResource(new ResourceLocation("eagler:glsl/deferred/assets_pbr/" + fname + ".ebp")).getInputStream(), 255); + }catch(Throwable t) { + // dead code because teavm + t.toString(); + } + } + return null; + } + + public static void unifySizes(int lvl, ImageData[]... imageSets) { + int resX = -1; + int resY = -1; + int iw, ih; + for(int i = 0; i < imageSets.length; ++i) { + iw = imageSets[i][lvl].width; + ih = imageSets[i][lvl].height; + if(iw != ih) { + } + if(iw > resX) { + resX = iw; + } + if(ih > resY) { + resY = ih; + } + } + if(resX == -1 || resY == -1) { + throw new IllegalArgumentException("No images were provided!"); + } + for(int i = 0; i < imageSets.length; ++i) { + ImageData in = imageSets[i][lvl]; + ImageData out = null; + if(in.width != resX || in.height != resY) { + out = new ImageData(resX, resY, true); + if(in.width == 1 && in.height == 1) { + int px = in.pixels[0]; + for(int j = 0; j < out.pixels.length; ++j) { + out.pixels[j] = px; + } + }else { + for(int y = 0; y < resY; ++y) { + for(int x = 0; x < resX; ++x) { + out.pixels[y * resX + x] = in.pixels[((y * in.height / resY)) * in.width + (x * in.width / resX)]; + } + } + } + } + if(out != null) { + imageSets[i][lvl] = out; + } + } + } + + public static ImageData generateMaterialTextureFor(String iconName) { + if(iconName.startsWith("minecraft:")) { + iconName = iconName.substring(10); + } + Integer in = blockMaterialConstants.spriteNameToMaterialConstants.get(iconName); + if(in == null) { + return new ImageData(1, 1, new int[] { blockMaterialConstants.defaultMaterial }, true); + }else { + return new ImageData(1, 1, new int[] { in.intValue() }, true); + } + } + + public static int[][] generateMipmapDataIgnoreAlpha(int level, int width, int[][] aint) { + int[][] ret = new int[level + 1][]; + ret[0] = aint[0]; + if (level > 0) { + for(int i = 1; i <= level; ++i) { + if(aint[i] != null) { + ret[i] = aint[i]; + }else { + int lvlW = width >> i, lvl2W = lvlW << 1; + int len = lvlW * lvlW; + ret[i] = new int[len]; + int x, y, s1, s2, s3, s4, c1, c2, c3, c4; + for(int j = 0; j < len; ++j) { + x = (j % len) << 1; + y = (j / len) << 1; + s1 = ret[i - 1][x + y * lvl2W]; + s2 = ret[i - 1][x + y * lvl2W + 1]; + s3 = ret[i - 1][x + y * lvl2W + lvl2W]; + s4 = ret[i - 1][x + y * lvl2W + lvl2W + 1]; + c1 = ((s1 >> 24) & 0xFF) + ((s2 >> 24) & 0xFF) + ((s3 >> 24) & 0xFF) + ((s4 >> 24) & 0xFF); + c2 = ((s1 >> 16) & 0xFF) + ((s2 >> 16) & 0xFF) + ((s3 >> 16) & 0xFF) + ((s4 >> 16) & 0xFF); + c3 = ((s1 >> 8) & 0xFF) + ((s2 >> 8) & 0xFF) + ((s3 >> 8) & 0xFF) + ((s4 >> 8) & 0xFF); + c4 = (s1 & 0xFF) + (s2 & 0xFF) + (s3 & 0xFF) + (s4 & 0xFF); + ret[i][j] = ((c1 >> 2) << 24) | ((c2 >> 2) << 16) | ((c3 >> 2) << 8) | (c4 >> 2); + } + } + } + } + return ret; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TemperaturesLUT.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TemperaturesLUT.java new file mode 100644 index 0000000..1540857 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TemperaturesLUT.java @@ -0,0 +1,68 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import java.io.IOException; +import java.io.InputStream; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class TemperaturesLUT implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger("TemperaturesLUT"); + + public static final float[][] colorTemperatureLUT = new float[390][3]; + + @Override + public void onResourceManagerReload(IResourceManager var1) { + try { + IResource res = var1.getResource(new ResourceLocation("eagler:glsl/deferred/temperatures.lut")); + try(InputStream is = res.getInputStream()) { + for(int i = 0; i < 390; ++i) { + colorTemperatureLUT[i][0] = ((int)is.read() & 0xFF) * 0.0039216f; + colorTemperatureLUT[i][0] *= colorTemperatureLUT[i][0]; + colorTemperatureLUT[i][1] = ((int)is.read() & 0xFF) * 0.0039216f; + colorTemperatureLUT[i][1] *= colorTemperatureLUT[i][1]; + colorTemperatureLUT[i][2] = ((int)is.read() & 0xFF) * 0.0039216f; + colorTemperatureLUT[i][2] *= colorTemperatureLUT[i][2]; + } + } + } catch (IOException e) { + logger.error("Failed to load color temperature lookup table!"); + logger.error(e); + } + } + + public static float[] getColorTemperature(int kelvin) { + if (kelvin < 1000) kelvin = 1000; + if (kelvin > 39000) kelvin = 39000; + int k = ((kelvin - 100) / 100); + return colorTemperatureLUT[k]; + } + + public static void getColorTemperature(int kelvin, float[] ret) { + if (kelvin < 1000) kelvin = 1000; + if (kelvin > 39000) kelvin = 39000; + int k = ((kelvin - 100) / 100); + ret[0] = colorTemperatureLUT[k][0]; + ret[1] = colorTemperatureLUT[k][1]; + ret[2] = colorTemperatureLUT[k][2]; + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureClockPBRImpl.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureClockPBRImpl.java new file mode 100644 index 0000000..089e8a8 --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureClockPBRImpl.java @@ -0,0 +1,74 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; +import net.minecraft.util.MathHelper; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class TextureClockPBRImpl extends EaglerTextureAtlasSpritePBR { + private double smoothParam1; + private double smoothParam2; + + public TextureClockPBRImpl(String spriteName) { + super(spriteName); + } + + public void updateAnimationPBR(IFramebufferGL[] copyColorFramebuffer, IFramebufferGL[] copyMaterialFramebuffer, int materialTexOffset) { + if (!this.frameTextureDataPBR[0].isEmpty()) { + Minecraft minecraft = Minecraft.getMinecraft(); + double d0 = 0.0; + if (minecraft.theWorld != null && minecraft.thePlayer != null) { + d0 = (double) minecraft.theWorld.getCelestialAngle(1.0f); + if (!minecraft.theWorld.provider.isSurfaceWorld()) { + d0 = Math.random(); + } + } + + double d1; + for (d1 = d0 - this.smoothParam1; d1 < -0.5; ++d1) { + ; + } + + while (d1 >= 0.5) { + --d1; + } + + d1 = MathHelper.clamp_double(d1, -1.0, 1.0); + this.smoothParam2 += d1 * 0.1; + this.smoothParam2 *= 0.8; + this.smoothParam1 += this.smoothParam2; + + int i, frameCount = this.frameTextureDataPBR[0].size(); + for (i = (int) ((this.smoothParam1 + 1.0) * frameCount) % frameCount; i < 0; i = (i + frameCount) % frameCount) { + ; + } + + if (i != this.frameCounter) { + this.frameCounter = i; + animationCachePBR[0].copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, this.width, + this.height, copyColorFramebuffer); + if (!dontAnimateNormals) + animationCachePBR[1].copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, + this.width, this.height, copyMaterialFramebuffer); + if (!dontAnimateMaterial) + animationCachePBR[2].copyFrameLevelsToTex2D(this.frameCounter, this.originX, + this.originY + materialTexOffset, this.width, this.height, copyMaterialFramebuffer); + } + + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureCompassPBRImpl.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureCompassPBRImpl.java new file mode 100644 index 0000000..325412a --- /dev/null +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/texture/TextureCompassPBRImpl.java @@ -0,0 +1,90 @@ +package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture; + +import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +/** + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ +public class TextureCompassPBRImpl extends EaglerTextureAtlasSpritePBR { + public double currentAngle; + public double angleDelta; + + public TextureCompassPBRImpl(String spriteName) { + super(spriteName); + } + + public void updateAnimationPBR(IFramebufferGL[] copyColorFramebuffer, IFramebufferGL[] copyMaterialFramebuffer, int materialOffset) { + Minecraft minecraft = Minecraft.getMinecraft(); + if (minecraft.theWorld != null && minecraft.thePlayer != null) { + this.updateCompassPBR(minecraft.theWorld, minecraft.thePlayer.posX, minecraft.thePlayer.posZ, + (double) minecraft.thePlayer.rotationYaw, false, copyColorFramebuffer, copyMaterialFramebuffer, materialOffset); + } else { + this.updateCompassPBR((World) null, 0.0, 0.0, 0.0, true, copyColorFramebuffer, copyMaterialFramebuffer, materialOffset); + } + } + + public void updateCompassPBR(World worldIn, double playerX, double playerY, double playerZ, boolean noWorld, + IFramebufferGL[] copyColorFramebuffer, IFramebufferGL[] copyMaterialFramebuffer, int materialOffset) { + if (!this.frameTextureDataPBR[0].isEmpty()) { + double d0 = 0.0; + if (worldIn != null && !noWorld) { + BlockPos blockpos = worldIn.getSpawnPoint(); + double d1 = (double) blockpos.getX() - playerX; + double d2 = (double) blockpos.getZ() - playerY; + playerZ = playerZ % 360.0; + d0 = -((playerZ - 90.0) * Math.PI / 180.0 - Math.atan2(d2, d1)); + if (!worldIn.provider.isSurfaceWorld()) { + d0 = Math.random() * Math.PI * 2.0; + } + } + + double d3; + for (d3 = d0 - this.currentAngle; d3 < -Math.PI; d3 += Math.PI * 2.0) { + ; + } + + while (d3 >= Math.PI) { + d3 -= Math.PI * 2.0; + } + + d3 = MathHelper.clamp_double(d3, -1.0, 1.0); + this.angleDelta += d3 * 0.1; + this.angleDelta *= 0.8; + this.currentAngle += this.angleDelta; + + int i, frameCount = this.frameTextureDataPBR[0].size(); + for (i = (int) ((this.currentAngle / Math.PI * 0.5 + 1.0) * frameCount) + % frameCount; i < 0; i = (i + frameCount) % frameCount) { + ; + } + + if (i != this.frameCounter) { + this.frameCounter = i; + animationCachePBR[0].copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, this.width, + this.height, copyColorFramebuffer); + if (!dontAnimateNormals) + animationCachePBR[1].copyFrameLevelsToTex2D(this.frameCounter, this.originX, this.originY, + this.width, this.height, copyMaterialFramebuffer); + if (!dontAnimateMaterial) + animationCachePBR[2].copyFrameLevelsToTex2D(this.frameCounter, this.originX, + this.originY + materialOffset, this.width, this.height, copyMaterialFramebuffer); + } + } + } + +} diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java index ee81d1e..b70db02 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java @@ -146,10 +146,18 @@ public class ConnectionHandshake { dat = new byte[msgLen]; di.read(dat); String versionStr = ArrayUtils.asciiString(dat); - + logger.info("Server version: {}", versionStr); logger.info("Server brand: {}", brandStr); + if(versionStr.equals("1.0.0") || versionStr.equals("1.0.1") || versionStr.equals("1.0.2") + || versionStr.equals("1.0.3") || versionStr.equals("1.0.4") || versionStr.equals("1.0.5")) { + mc.bungeeOutdatedMsgTimer = 80; + mc.bungeeOutdatedMsgVer = versionStr; + }else { + mc.bungeeOutdatedMsgTimer = 0; + } + int authType = di.read(); int saltLength = (int)di.readShort() & 0xFFFF; diff --git a/sources/main/java/net/lax1dude/eaglercraft/v1_8/vector/Matrix4f.java b/sources/main/java/net/lax1dude/eaglercraft/v1_8/vector/Matrix4f.java index 0ae7699..e493bcc 100644 --- a/sources/main/java/net/lax1dude/eaglercraft/v1_8/vector/Matrix4f.java +++ b/sources/main/java/net/lax1dude/eaglercraft/v1_8/vector/Matrix4f.java @@ -32,6 +32,8 @@ package net.lax1dude.eaglercraft.v1_8.vector; import java.io.Serializable; + +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; /** @@ -286,6 +288,29 @@ public class Matrix4f extends Matrix implements Serializable { buf.put(m33); return this; } + + /** + * eagler + */ + public Matrix store(ByteBuffer buf) { + buf.putFloat(m00); + buf.putFloat(m01); + buf.putFloat(m02); + buf.putFloat(m03); + buf.putFloat(m10); + buf.putFloat(m11); + buf.putFloat(m12); + buf.putFloat(m13); + buf.putFloat(m20); + buf.putFloat(m21); + buf.putFloat(m22); + buf.putFloat(m23); + buf.putFloat(m30); + buf.putFloat(m31); + buf.putFloat(m32); + buf.putFloat(m33); + return this; + } public Matrix store(float[] buf) { buf[0] = m00; diff --git a/sources/main/java/org/apache/commons/lang3/text/CompositeFormat.java b/sources/main/java/org/apache/commons/lang3/text/CompositeFormat.java index dd1d6d2..112967b 100644 --- a/sources/main/java/org/apache/commons/lang3/text/CompositeFormat.java +++ b/sources/main/java/org/apache/commons/lang3/text/CompositeFormat.java @@ -26,11 +26,11 @@ import java.text.ParsePosition; * example of use for this would be a webapp where data is taken in one way and * stored in a database another way. * - * @deprecated as of 3.6, use commons-text * CompositeFormat instead */ -@Deprecated +//@Deprecated public class CompositeFormat extends Format { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/ExtendedMessageFormat.java b/sources/main/java/org/apache/commons/lang3/text/ExtendedMessageFormat.java index 27bc4c1..ee90728 100644 --- a/sources/main/java/org/apache/commons/lang3/text/ExtendedMessageFormat.java +++ b/sources/main/java/org/apache/commons/lang3/text/ExtendedMessageFormat.java @@ -71,11 +71,11 @@ import org.apache.commons.lang3.Validate; * * * @since 2.4 - * @deprecated as of 3.6, use commons-text * ExtendedMessageFormat instead */ -@Deprecated +//@Deprecated public class ExtendedMessageFormat extends MessageFormat { private static final long serialVersionUID = -2362048321261811743L; private static final int HASH_SEED = 31; diff --git a/sources/main/java/org/apache/commons/lang3/text/FormatFactory.java b/sources/main/java/org/apache/commons/lang3/text/FormatFactory.java index 444ceb8..86e7933 100644 --- a/sources/main/java/org/apache/commons/lang3/text/FormatFactory.java +++ b/sources/main/java/org/apache/commons/lang3/text/FormatFactory.java @@ -23,11 +23,11 @@ import java.util.Locale; * Format factory. * * @since 2.4 - * @deprecated as of 3.6, use commons-text * FormatFactory instead */ -@Deprecated +//@Deprecated public interface FormatFactory { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/FormattableUtils.java b/sources/main/java/org/apache/commons/lang3/text/FormattableUtils.java index 8a560bc..fd8fe4d 100644 --- a/sources/main/java/org/apache/commons/lang3/text/FormattableUtils.java +++ b/sources/main/java/org/apache/commons/lang3/text/FormattableUtils.java @@ -39,11 +39,11 @@ import net.lax1dude.eaglercraft.v1_8.HString; *

* * @since 3.0 - * @deprecated as of 3.6, use commons-text * FormattableUtils instead */ -@Deprecated +//@Deprecated public class FormattableUtils { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/StrBuilder.java b/sources/main/java/org/apache/commons/lang3/text/StrBuilder.java index 7c0579a..6fd0a5b 100644 --- a/sources/main/java/org/apache/commons/lang3/text/StrBuilder.java +++ b/sources/main/java/org/apache/commons/lang3/text/StrBuilder.java @@ -77,11 +77,11 @@ import org.apache.commons.lang3.builder.Builder; * the interface. * * @since 2.2 - * @deprecated as of 3.6, use commons-text * TextStringBuilder instead */ -@Deprecated +//@Deprecated public class StrBuilder implements CharSequence, Appendable, Serializable, Builder { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/StrLookup.java b/sources/main/java/org/apache/commons/lang3/text/StrLookup.java index 43f58e6..fa69ba2 100644 --- a/sources/main/java/org/apache/commons/lang3/text/StrLookup.java +++ b/sources/main/java/org/apache/commons/lang3/text/StrLookup.java @@ -33,11 +33,11 @@ import java.util.Map; * * @param Unused. * @since 2.2 - * @deprecated as of 3.6, use commons-text * StringLookupFactory instead */ -@Deprecated +//@Deprecated public abstract class StrLookup { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/StrMatcher.java b/sources/main/java/org/apache/commons/lang3/text/StrMatcher.java index e02425d..80661d5 100644 --- a/sources/main/java/org/apache/commons/lang3/text/StrMatcher.java +++ b/sources/main/java/org/apache/commons/lang3/text/StrMatcher.java @@ -29,11 +29,11 @@ import org.apache.commons.lang3.StringUtils; * suffice, you can subclass and implement your own matcher. * * @since 2.2 - * @deprecated as of 3.6, use commons-text * StringMatcherFactory instead */ -@Deprecated +//@Deprecated public abstract class StrMatcher { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/StrSubstitutor.java b/sources/main/java/org/apache/commons/lang3/text/StrSubstitutor.java index 8f702d1..eb8a943 100644 --- a/sources/main/java/org/apache/commons/lang3/text/StrSubstitutor.java +++ b/sources/main/java/org/apache/commons/lang3/text/StrSubstitutor.java @@ -143,11 +143,11 @@ import org.apache.commons.lang3.StringUtils; *

* * @since 2.2 - * @deprecated as of 3.6, use commons-text * StringSubstitutor instead */ -@Deprecated +//@Deprecated public class StrSubstitutor { /** diff --git a/sources/main/java/org/apache/commons/lang3/text/StrTokenizer.java b/sources/main/java/org/apache/commons/lang3/text/StrTokenizer.java index 3856e54..2f116bd 100644 --- a/sources/main/java/org/apache/commons/lang3/text/StrTokenizer.java +++ b/sources/main/java/org/apache/commons/lang3/text/StrTokenizer.java @@ -94,11 +94,11 @@ import org.apache.commons.lang3.StringUtils; * * * @since 2.2 - * @deprecated as of 3.6, use commons-text * StringTokenizer instead */ -@Deprecated +//@Deprecated public class StrTokenizer implements ListIterator, Cloneable { private static final StrTokenizer CSV_TOKENIZER_PROTOTYPE; diff --git a/sources/main/java/org/apache/commons/lang3/text/WordUtils.java b/sources/main/java/org/apache/commons/lang3/text/WordUtils.java index 09141b2..68a30a7 100644 --- a/sources/main/java/org/apache/commons/lang3/text/WordUtils.java +++ b/sources/main/java/org/apache/commons/lang3/text/WordUtils.java @@ -33,11 +33,11 @@ import org.apache.commons.lang3.StringUtils; *

* * @since 2.0 - * @deprecated as of 3.6, use commons-text * WordUtils instead */ -@Deprecated +//@Deprecated public class WordUtils { /** diff --git a/sources/resources/assets/eagler/CREDITS.txt b/sources/resources/assets/eagler/CREDITS.txt index 5a59d44..b2d4d91 100644 --- a/sources/resources/assets/eagler/CREDITS.txt +++ b/sources/resources/assets/eagler/CREDITS.txt @@ -5,9 +5,11 @@ lax1dude: - Creator of Eaglercraft - - Wrote HW accelerated OpenGL 1.3 emulator - - Wrote all desktop emulation code - Ported the Minecraft 1.8 client src to TeaVM + - Wrote HW accelerated OpenGL 1.3 emulator + - Wrote the default shader pack + - Made the integrated PBR resource pack + - Wrote all desktop emulation code - Wrote EaglercraftXBungee - Wrote the patch and build system diff --git a/sources/resources/assets/eagler/glsl/accel_font.fsh b/sources/resources/assets/eagler/glsl/accel_font.fsh index 6fe1e21..36e3cf4 100644 --- a/sources/resources/assets/eagler/glsl/accel_font.fsh +++ b/sources/resources/assets/eagler/glsl/accel_font.fsh @@ -15,8 +15,8 @@ */ precision lowp int; -precision lowp float; -precision lowp sampler2D; +precision mediump float; +precision mediump sampler2D; in vec2 v_texCoord2f; in vec4 v_color4f; diff --git a/sources/resources/assets/eagler/glsl/accel_font.vsh b/sources/resources/assets/eagler/glsl/accel_font.vsh index 5c31fe7..578e0cc 100644 --- a/sources/resources/assets/eagler/glsl/accel_font.vsh +++ b/sources/resources/assets/eagler/glsl/accel_font.vsh @@ -15,8 +15,8 @@ */ precision lowp int; -precision lowp float; -precision lowp sampler2D; +precision highp float; +precision mediump sampler2D; layout(location = 0) in vec3 a_position3f; diff --git a/sources/resources/assets/eagler/glsl/accel_particle.fsh b/sources/resources/assets/eagler/glsl/accel_particle.fsh index 3a92266..60d4639 100644 --- a/sources/resources/assets/eagler/glsl/accel_particle.fsh +++ b/sources/resources/assets/eagler/glsl/accel_particle.fsh @@ -15,8 +15,8 @@ */ precision lowp int; -precision lowp float; -precision lowp sampler2D; +precision mediump float; +precision mediump sampler2D; in vec2 v_texCoord2f; in vec4 v_color4f; diff --git a/sources/resources/assets/eagler/glsl/accel_particle.vsh b/sources/resources/assets/eagler/glsl/accel_particle.vsh index ce714bb..6ed0113 100644 --- a/sources/resources/assets/eagler/glsl/accel_particle.vsh +++ b/sources/resources/assets/eagler/glsl/accel_particle.vsh @@ -15,8 +15,8 @@ */ precision lowp int; -precision lowp float; -precision lowp sampler2D; +precision highp float; +precision mediump sampler2D; layout(location = 0) in vec2 a_position2f; diff --git a/sources/resources/assets/eagler/glsl/core.fsh b/sources/resources/assets/eagler/glsl/core.fsh index b491e06..23ce5be 100644 --- a/sources/resources/assets/eagler/glsl/core.fsh +++ b/sources/resources/assets/eagler/glsl/core.fsh @@ -141,6 +141,10 @@ void main() { #endif #endif +#ifdef COMPILE_BLEND_ADD + color = color * u_colorBlendSrc4f + u_colorBlendAdd4f; +#endif + #ifdef COMPILE_ENABLE_ALPHA_TEST if(color.a < u_alphaTestRef1f) discard; #endif @@ -154,24 +158,21 @@ void main() { vec3 normal = u_uniformNormal3f; #endif float diffuse = 0.0; + vec4 light; for(int i = 0; i < u_lightsEnabled1i; ++i) { - vec4 light = u_lightsDirections4fv[i]; + light = u_lightsDirections4fv[i]; diffuse += max(dot(light.xyz, normal), 0.0) * light.w; } color.rgb *= min(u_lightsAmbient3f + vec3(diffuse), 1.0); #endif -#ifdef COMPILE_BLEND_ADD - color.rgba = color.rgba * u_colorBlendSrc4f + u_colorBlendAdd4f; -#endif - #ifdef COMPILE_ENABLE_FOG vec3 fogPos = v_position4f.xyz / v_position4f.w; float dist = sqrt(dot(fogPos, fogPos)); float fogDensity = u_fogParameters4f.y; float fogStart = u_fogParameters4f.z; float fogEnd = u_fogParameters4f.w; - float f = u_fogParameters4f.x > 0.0 ? 1.0 - pow(2.718, -(fogDensity * dist)) : + float f = u_fogParameters4f.x > 0.0 ? 1.0 - exp(-fogDensity * dist) : (dist - fogStart) / (fogEnd - fogStart); color.rgb = mix(color.rgb, u_fogColor4f.rgb, clamp(f, 0.0, 1.0) * u_fogColor4f.a); #endif diff --git a/sources/resources/assets/eagler/glsl/core.vsh b/sources/resources/assets/eagler/glsl/core.vsh index a347435..194ae44 100644 --- a/sources/resources/assets/eagler/glsl/core.vsh +++ b/sources/resources/assets/eagler/glsl/core.vsh @@ -50,29 +50,29 @@ out vec2 v_lightmap2f; uniform mat4 u_textureMat4f02; #endif +#ifdef _COMPILE_VARYING_POSITION uniform mat4 u_modelviewMat4f; uniform mat4 u_projectionMat4f; +#else +uniform mat4 u_modelviewProjMat4f; +#ifdef COMPILE_NORMAL_ATTRIB +uniform mat4 u_modelviewMat4f; +#endif +#endif + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) void main() { - #ifdef COMPILE_ENABLE_TEX_GEN v_objectPosition3f = a_position3f; #endif - vec4 pos = u_modelviewMat4f * vec4(a_position3f, 1.0); - #ifdef _COMPILE_VARYING_POSITION - v_position4f = pos; + v_position4f = u_modelviewMat4f * vec4(a_position3f, 1.0); #endif #ifdef COMPILE_TEXTURE_ATTRIB - mat4x3 texMat4x3 = mat4x3( - u_textureMat4f01[0].xyw, - u_textureMat4f01[1].xyw, - u_textureMat4f01[2].xyw, - u_textureMat4f01[3].xyw - ); - vec3 v_textureTmp3f = texMat4x3 * vec4(a_texture2f, 0.0, 1.0); + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; #endif @@ -85,19 +85,13 @@ void main() { #endif #ifdef COMPILE_LIGHTMAP_ATTRIB -#ifdef COMPILE_TEXTURE_ATTRIB - texMat4x3 = mat4x3( -#else - mat4x3 texMat4x3 = mat4x3( -#endif - u_textureMat4f02[0].xyw, - u_textureMat4f02[1].xyw, - u_textureMat4f02[2].xyw, - u_textureMat4f02[3].xyw - ); - vec3 v_lightmapTmp3f = texMat4x3 * vec4(a_lightmap2f, 0.0, 1.0); + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; #endif - gl_Position = u_projectionMat4f * pos; +#ifdef _COMPILE_VARYING_POSITION + gl_Position = u_projectionMat4f * v_position4f; +#else + gl_Position = u_modelviewProjMat4f * vec4(a_position3f, 1.0); +#endif } diff --git a/sources/resources/assets/eagler/glsl/deferred/accel_particle.vsh b/sources/resources/assets/eagler/glsl/deferred/accel_particle.vsh new file mode 100644 index 0000000..370b0ae --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/accel_particle.vsh @@ -0,0 +1,72 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision mediump sampler2D; + +layout(location = 0) in vec2 a_position2f; + +layout(location = 1) in vec3 p_position3f; +layout(location = 2) in vec2 p_texCoords2i; +layout(location = 3) in vec2 p_lightMap2f; +layout(location = 4) in vec2 p_particleSize_texCoordsSize_2i; +layout(location = 5) in vec4 p_color4f; + +out vec2 v_texCoord2f; +out vec4 v_color4f; +out vec2 v_lightmap2f; + +#ifdef COMPILE_FORWARD_VSH +out vec4 v_position4f; +uniform mat4 u_modelViewMatrix4f; +uniform mat4 u_projectionMatrix4f; +#endif + +#ifdef COMPILE_GBUFFER_VSH +uniform mat4 u_matrixTransform; +#endif + +uniform vec3 u_texCoordSize2f_particleSize1f; +uniform vec4 u_transformParam_1_2_3_4_f; +uniform float u_transformParam_5_f; + +void main() { + v_color4f = p_color4f.bgra; + v_lightmap2f = p_lightMap2f; + + vec2 tex2f = a_position2f * 0.5 + 0.5; + tex2f.y = 1.0 - tex2f.y; + tex2f = p_texCoords2i + tex2f * p_particleSize_texCoordsSize_2i.y; + v_texCoord2f = tex2f * u_texCoordSize2f_particleSize1f.xy; + + float particleSize = u_texCoordSize2f_particleSize1f.z * p_particleSize_texCoordsSize_2i.x; + + vec3 pos3f = p_position3f; + pos3f.x += u_transformParam_1_2_3_4_f.x * particleSize * a_position2f.x; + pos3f.x += u_transformParam_1_2_3_4_f.w * particleSize * a_position2f.y; + pos3f.y += u_transformParam_1_2_3_4_f.y * particleSize * a_position2f.y; + pos3f.z += u_transformParam_1_2_3_4_f.z * particleSize * a_position2f.x; + pos3f.z += u_transformParam_5_f * particleSize * a_position2f.y; + +#ifdef COMPILE_GBUFFER_VSH + gl_Position = u_matrixTransform * vec4(pos3f, 1.0); +#endif +#ifdef COMPILE_FORWARD_VSH + v_position4f = u_modelViewMatrix4f * vec4(pos3f, 1.0); + gl_Position = u_projectionMatrix4f * v_position4f; +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/accel_particle_forward.fsh b/sources/resources/assets/eagler/glsl/deferred/accel_particle_forward.fsh new file mode 100644 index 0000000..ba1d8e0 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/accel_particle_forward.fsh @@ -0,0 +1,233 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision mediump sampler2D; +precision highp sampler2DShadow; + +in vec4 v_position4f; +in vec2 v_texCoord2f; +in vec4 v_color4f; +in vec2 v_lightmap2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_diffuseTexture; + +uniform vec2 u_textureYScale2f; + +uniform mat4 u_inverseViewMatrix4f; + +#ifdef COMPILE_DYNAMIC_LIGHTS +struct DynamicLight { + mediump vec4 u_lightPosition4f; + mediump vec4 u_lightColor4f; +}; +layout(std140) uniform u_chunkLightingData { + mediump int u_dynamicLightCount1i; + mediump int _paddingA_; + mediump int _paddingB_; + mediump int _paddingC_; + DynamicLight u_dynamicLightArray[12]; +}; +#endif + +layout(std140) uniform u_worldLightingData { + mediump vec4 u_sunDirection4f; + mediump vec4 u_sunColor3f_sky1f; + mediump vec4 u_fogParameters4f; + mediump vec4 u_fogColorLight4f; + mediump vec4 u_fogColorDark4f; + mediump vec4 u_fogColorAddSun4f; + mediump vec4 u_blockSkySunDynamicLightFac4f; +#ifdef COMPILE_SUN_SHADOW_LOD0 + mediump mat4 u_sunShadowMatrixLOD04f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; + mediump mat4 u_sunShadowMatrixLOD24f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif +}; + +uniform sampler2D u_samplerNormalMaterial; + +uniform sampler2D u_metalsLUT; + +#define LIB_INCLUDE_PBR_LIGHTING_FUNCTION +#define LIB_INCLUDE_PBR_LIGHTING_PREFETCH +#EAGLER INCLUDE (3) "eagler:glsl/deferred/lib/pbr_lighting.glsl" + +uniform sampler2D u_irradianceMap; + +#ifdef DO_COMPILE_SUN_SHADOWS +uniform sampler2DShadow u_sunShadowDepthTexture; +#endif + +void main() { + vec4 worldPosition4f; + vec4 worldDirection4f; + vec4 diffuseColor4f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + vec3 materialData3f; + + // =========== RESOLVE CONSTANTS ============ // + + worldPosition4f = u_inverseViewMatrix4f * v_position4f; + worldPosition4f.xyz /= worldPosition4f.w; + worldPosition4f.w = 1.0; + worldDirection4f = u_inverseViewMatrix4f * vec4(v_position4f.xyz / v_position4f.w, 0.0); + worldDirection4f.xyz = normalize(worldDirection4f.xyz); + + lightmapCoords2f = v_lightmap2f; + + normalVector3f = normalize(u_inverseViewMatrix4f[2].xyz); + + // ========= CALCULATE DIFFUSE COLOR ========== // + + diffuseColor4f = texture(u_diffuseTexture, v_texCoord2f) * v_color4f; + + // ============= ALPHA TEST ============== // + + if(diffuseColor4f.a < 0.004) discard; + + // ========== RESOLVE MATERIALS =========== // + + materialData3f = texture(u_samplerNormalMaterial, vec2(v_texCoord2f.x, v_texCoord2f.y * u_textureYScale2f.x + u_textureYScale2f.y)).rgb; + + vec3 metalN, metalK; + PREFETCH_METALS(diffuseColor4f.rgb, materialData3f.g, metalN, metalK) + + // ============ SUN LIGHTING ============== // + + diffuseColor4f.rgb *= diffuseColor4f.rgb; + + vec3 lightColor3f = vec3(0.0); + if(dot(u_sunDirection4f.xyz, normalVector3f) > 0.0 && lightmapCoords2f.g > 0.5 && + (u_sunColor3f_sky1f.r + u_sunColor3f_sky1f.g + u_sunColor3f_sky1f.b) > 0.001) { +#ifdef DO_COMPILE_SUN_SHADOWS + + // ========== SUN SHADOW: LOD0 ============ // + + float skyLight = max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); + float shadowSample = 1.0; + vec4 shadowWorldPos4f = worldPosition4f; + shadowWorldPos4f.xyz += normalVector3f * 0.05; + + vec4 shadowTexPos4f; + vec2 tmpVec2; + for(;;) { + shadowTexPos4f = u_sunShadowMatrixLOD04f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy * vec2(1.0, SUN_SHADOW_MAP_FRAC), shadowTexPos4f.z), 0.0); + break; + } + +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowTexPos4f = u_sunShadowMatrixLOD14f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 1.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowTexPos4f = u_sunShadowMatrixLOD24f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 2.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + } +#endif + break; + } +#endif + lightColor3f = u_sunColor3f_sky1f.rgb * max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); +#ifdef DO_COMPILE_SUN_SHADOWS + lightColor3f *= shadowSample * skyLight; +#endif + vec3 normalWrap3f = normalVector3f * (dot(-worldDirection4f.xyz, normalVector3f) < 0.0 ? -1.0 : 1.0); + lightColor3f = eaglercraftLighting(diffuseColor4f.rgb, lightColor3f, -worldDirection4f.xyz, u_sunDirection4f.xyz, normalWrap3f, materialData3f, metalN, metalK) * u_blockSkySunDynamicLightFac4f.z; + } + + // =========== IRRADIANCE MAP =========== // + + lightmapCoords2f *= lightmapCoords2f; + + vec3 irradianceMapSamplePos2f = normalVector3f; + irradianceMapSamplePos2f.xz /= abs(irradianceMapSamplePos2f.y) + 1.0; + float dst = 1.0 - dot(irradianceMapSamplePos2f.xz, irradianceMapSamplePos2f.xz); + dst *= dst; + irradianceMapSamplePos2f.xz *= 0.975; + vec3 skyLight = vec3(sqrt(0.01 + max(u_sunDirection4f.w, 0.0))); + if(dst < 0.005) { + vec4 sample1 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + skyLight += mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, irradianceMapSamplePos2f.y * -12.5 + 0.5)).rgb; + }else { + irradianceMapSamplePos2f.xz *= vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : -0.25); + irradianceMapSamplePos2f.xz += vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : 0.75); + skyLight += textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz, 0.0).rgb; + } + skyLight *= lightmapCoords2f.g * u_sunColor3f_sky1f.w; + +#ifdef COMPILE_DYNAMIC_LIGHTS + + // =========== DYNAMIC LIGHTING =========== // + + vec3 dlightDist3f, dlightDir3f, dlightColor3f; + int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i; // hate this + for(int i = 0; i < safeLightCount; ++i) { + dlightDist3f = worldPosition4f.xyz - u_dynamicLightArray[i].u_lightPosition4f.xyz; + dlightDir3f = normalize(dlightDist3f); + dlightDir3f = dlightDir3f * (dot(dlightDir3f, normalVector3f) < 0.0 ? 1.0 : -1.0); + dlightDir3f = materialData3f.b == 1.0 ? normalVector3f : -dlightDir3f; + if(dot(dlightDir3f, normalVector3f) <= 0.0) { + continue; + } + dlightColor3f = u_dynamicLightArray[i].u_lightColor4f.rgb / dot(dlightDist3f, dlightDist3f); + if(dlightColor3f.r + dlightColor3f.g + dlightColor3f.b < 0.025) { + continue; + } + lightColor3f += eaglercraftLighting(diffuseColor4f.rgb, dlightColor3f, -worldDirection4f.xyz, dlightDir3f, normalVector3f, materialData3f, metalN, metalK) * u_blockSkySunDynamicLightFac4f.w; + } + +#endif + + // ============ OUTPUT COLOR ============== // + + vec3 blockLight = lightmapCoords2f.r * vec3(1.0, 0.5809, 0.2433) * 2.0 * u_blockSkySunDynamicLightFac4f.x; + skyLight *= u_blockSkySunDynamicLightFac4f.y; + float emissive = materialData3f.b == 1.0 ? 0.0 : materialData3f.b; + diffuseColor4f.rgb *= max(skyLight + blockLight, vec3(emissive * emissive * 20.0 + 0.075)) * 0.075; + diffuseColor4f.rgb += lightColor3f; + + output4f = vec4(diffuseColor4f.rgb * diffuseColor4f.a, diffuseColor4f.a); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/accel_particle_gbuffer.fsh b/sources/resources/assets/eagler/glsl/deferred/accel_particle_gbuffer.fsh new file mode 100644 index 0000000..db34c77 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/accel_particle_gbuffer.fsh @@ -0,0 +1,42 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision mediump float; +precision mediump sampler2D; + +in vec2 v_texCoord2f; +in vec4 v_color4f; +in vec2 v_lightmap2f; + +layout(location = 0) out vec4 gbufferColor4f; +layout(location = 1) out vec4 gbufferNormal4f; +layout(location = 2) out vec4 gbufferMaterial4f; + +uniform sampler2D u_diffuseTexture; +uniform sampler2D u_samplerNormalMaterial; + +uniform vec2 u_textureYScale2f; + +void main() { + vec4 diffuseRGBA = texture(u_diffuseTexture, v_texCoord2f) * v_color4f; + if(diffuseRGBA.a < 0.004) { + discard; + } + gbufferColor4f = vec4(diffuseRGBA.rgb, v_lightmap2f.r); + gbufferNormal4f = vec4(0.5, 0.5, 1.0, v_lightmap2f.g); + gbufferMaterial4f = vec4(texture(u_samplerNormalMaterial, vec2(v_texCoord2f.x, v_texCoord2f.y * u_textureYScale2f.x + u_textureYScale2f.y)).rgb, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/readme.txt b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/readme.txt new file mode 100644 index 0000000..9bd0364 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/readme.txt @@ -0,0 +1 @@ +these are just low quality fallback material textures for the default vanilla resource pack when no PBR resource pack is loaded, if you would like to make a PBR resource pack put your _n and _s textures in the "/assets/minecraft/textures/" directory of your zip file, do not modify any files within "/assets/eagler/glsl/deferred/assets_pbr/textures/" because they will not be recognized \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_feet_end_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_feet_end_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..f87d047870cdbcd8ebba6346bde07adaea15d3a8 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}QBAU~u4KDB)!=1E|CBL literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_end_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_end_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..9ab55d71b3c9f5d65c8c4a537669fa5bdce29a6a GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}QBEWhmiguoPyn6JpR8V_;5TV3_2oLL}%wI{rhFc)C5;byQGWMEEUVAys$mq;|pS!K=c+&rNtOD6di YN!(d8DRz>l%9ic9o+>~ZC$h2w0FjL~4gdfE literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bed_head_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4eeb6b06aae60039636453e6b365a522181cd523 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}QBEWiS$8Fc)C5=4P-LWMEEUV3?%xWZUjsFO?@5Q*%9+EJ>O4 z)>8#Yg4iyTVsn?OxJ(KKlMptHT=E1cn+Mc2X)e%&Op&*fR8=xnz@*vSN$M(ox2{g| LRM~br*UAn6C7Ul{ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bedrock_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bedrock_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..d3ec27b1f505e25ea0e717d9da6359ee5170ab96 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009L<2LN>n00jg9Ck6ma2mk|M001&bQfSE`B_xuGCQL3z zBv6uxD3Z!1Ng*joB#|VOkdq`VnHfma5+sz9B*`R>NeL-62`MC!GD#t1$q^+;lyM|U jWSB`vl9Mt?BuYskDke;k!crv3Bqbvul17mv$q70>k250c literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bookshelf_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/bookshelf_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..3258298584898f027ab0af1dd73e1aa957ffe0ac GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}SHwWGFReNE2j;=4Z$@VCWBI~{VCQ~&?} z&id;0f9mfUQ@z5cgk(+44WHT#BwtMl&YJ24Bqw>Q01;4q?lGYH|Np;M*MF^l^0j)} Z)%u95K4n+KBd&UvT@88yBO&Uo>;TyqJ+=S< literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/brewing_stand_base_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/brewing_stand_base_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..3f4a00b1048f5aeeb5632ac0ae1d4e98b7fee444 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009Mb7XV})09zsed=vm}8UO=e001&tWu{3alG7=q$w`%2 z5=k3Lk;x)Rmt-`_A|rl|?7q>LuCmA05?l+{P%#jN-Hr*n NodZ-1Bq8dp>;RYSF$Vwu literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_inner_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_inner_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..3742fd9a026b0fb829f4503030e97a8fa68e94ac GIT binary patch literal 91 wcmY#&bqZi)7GMxyU}O&ERxOlM)n-#=a$sQiPXN4H{cH8T|Np<=$APWv09qMAQvd(} literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/cake_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1c00111a49d00e8a48d49c36565eb7d7f34ea841 GIT binary patch literal 88 scmY#&bqZi)7GMxyU}OsARxOlMWpZF(2qgfrR;^kI!MM6*k0}ucZ009P73;=}`07nb}rxXB83;<3H00UqE0M^@yXIpOAl5M1y zwa(RTH)yuUZ1h^&Zp7Pdw317=Z6(f2UMEPB*&<8ZTWzk}cF{9-kdjH(+iXc&PT15< mbd$DwYqlpuOV-t+~x6N@*qCePmW*qv;!4wCwK2nvAvYHrh!vk1k3_XJnSr(07nu4C<_2v7XSlb0043l;jSeKaF+`$$y=4S zjcutblDL~~BO;|Fqe#}|E*fHnw%l%3+>y6pZKRVeNR)(@jV8+EjkcsFH3>n1|lrMVPs#@ddy+KI@NX||Y%LqkD$)hY-^(qm-@ E0EZMFIsgCw literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/comparator_on_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/comparator_on_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..090f2b370643e325d38d064fcebcb6b79ac4cc6c GIT binary patch literal 173 zcmY#&bqZi)7GMxyVB}nGX;z~>Z>5#g5)1QE28I=udRzTt7F*bzY)ofqU|nB$_@ap12s4R literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_front_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_front_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..aecf7553133d365fbb58906f4dc98fe0c69ed763 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SB3&RQeRFi(IXPl2IdkbyaYfuYDVb<;`ZB2C?Gp2|h8s+(Mu zGovPFEty=Tsk%{Rav_)mvNuf%&QzJ4DU@BLv~-hFaKR)HS*WyllT&b}c5tRvc9Ev? XCYNBK`b{1ny_-ChLF%<8TiF2svu`RZ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1553d92c5bfb44d9999819f05f63c9e0e7c29c2d GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}PC}_TMUm1uhm{LvB^P-s zmu=53y`7zMSvl<{5G5BK@-B+b2C6B$nq9U#yGUzwk*9LXs?{ksyo)@!(}3!4XO~^i cE{aG_nVk&OQY7SEa9Ozks2(VOJKM?*01gf@-2eap literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/crafting_table_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..6d0f74f015ace9b12410948ef03bd74200a63cf4 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}Pp+D3fI96=awv$iSSyz_9IhE)Xp_MM6*k0}ucZ009Qdff-c{07nb}(v}%a3;<3H00UqE0M^@*Yg=yFB(13@ zwa(LRS7>(2Z1g(YZpmA1wIq|bZ6(f2UQ0+x*p!poTWzk}cF?tUktCAV+iWD;R@qXO mbtSfYYqm>5lh)g9k`ivoLbasblG|Ht*)49i)|T5_b~--lraFfJ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..94cd1a4e08b0d95fac65027eb21bd18740324cd5 GIT binary patch literal 135 zcmV;20C@i;MM6*k0}ucZ009R@2mm$-0A~{bC+SNJM4w-!x@ma4@pQNU|Mu(u((_M}UT-|xuhL&7-%IqoIzDDeK7arK literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dirt_podzol_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..6588620a1a3d23c0e81f31b7d409830458fe596c GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009L+5ddH#07eu5R~-OO7ytuc001r0Nis7_b*f2Cnn|S6 zS&iCJZj)PVl2I)bTV#?=D3c8(5=$krX(YzWZL>`zmg{Vm%_O^RCYwn%t4mHYNhY^h jcCuNN(&=up)3w%3ZJJpn6f%}n+-I?Z7RA|sG3q%t8A9nY?exCwnA+vn@KjBYNXp$rCOD?*(s*UVNxPp jHj^o2)M}{GWwzU7rrSxXD+x79s*;;YHWOVY(rP+BbmuVD literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dispenser_front_horizontal_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dispenser_front_horizontal_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..03cb6faae63ab6b3b4837ee5c3f5f0ad939cc4b8 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}P=gVkp&RvfyKg6k&)JU|>#QU{IOl2}EYMQ?}j8G>gvJ=B;UV zW$jjNO(T`H6IC_Mw5G0f^)%C% literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_lower_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_lower_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..d27115115addd4e29557b0cdf2044fab50958f50 GIT binary patch literal 88 scmY#&bqZi)7GMxyU}SQVWSIVpfyse^VQOe-WGE2;s4f(Q(Sem60QH3#x&QzG literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_upper_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_acacia_upper_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..603f97e160aaa79c6657d1b081932a0abf83ea0c GIT binary patch literal 88 scmY#&bqZi)7GMxyU}SQVWSIVpfyse^AruWv1@b|d7%(+7bfuLY0P=+z3IG5A literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_lower_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_lower_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..2320e295b3f32c0059bfc743510da5ef8775c16f GIT binary patch literal 88 ocmY#&bqZi)7GMxyU}SQVWSIVpfyse^VQMIG0Hh9t(Sem60Q89&wg3PC literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_upper_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_birch_upper_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..85495b181e371ba9ea08ff7c078e46c97e3ce6dc GIT binary patch literal 88 tcmY#&bqZi)7GMxyU}SQVWSIVpfyse^AruWv1@b|d2oO0nG&Iu64gm478NL7j literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_lower_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_lower_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ac3b3cf9c195f4aecc13f492afca28c76eb9eaff GIT binary patch literal 91 ucmY#&bqZi)7GMxyU}ScZWSIVpVfu3hCI<$FsiEPa#DJ+lMIek0tn2`4V;eUB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_upper_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_dark_oak_upper_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ecf07ebcc057bcdebd4e10e78e3da334b61a628f GIT binary patch literal 91 vcmY#&bqZi)7GMxyU}ScZWSIVpVfu3hCI<$FP&6ZH8d>L$_@bY#Tp0z literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_lower_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_lower_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4680cea5dd6042d02757197dd0a944cf9a4012c8 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}SQVWSIVpfyse^VQOgD)X>n#R0syKv4fS%W@TcNw6X&LEU_CN literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_upper_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_spruce_upper_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ae3ae02afe3ab297eb46ea8e36df9b5aad86eae3 GIT binary patch literal 88 tcmY#&bqZi)7GMxyU}SQVWSIVpfyse^AruX)TsA9nDw-HBE=aAF9RL{m8!`X@ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_lower_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_lower_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..2320e295b3f32c0059bfc743510da5ef8775c16f GIT binary patch literal 88 ocmY#&bqZi)7GMxyU}SQVWSIVpfyse^VQMIG0Hh9t(Sem60Q89&wg3PC literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_upper_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/door_wood_upper_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5ffd31bfe4fa67900e2f0fceb2dbdeb3cf0636e7 GIT binary patch literal 88 ucmY#&bqZi)7GMxyU}SQVWSIVpfyse^AruWv1@b|dFbG>ZH8d>L$_@bY#Tp0z literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dropper_front_horizontal_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/dropper_front_horizontal_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..51ac891d4db55f1ff70f20c2fe5b0f0bb2cd899a GIT binary patch literal 132 zcmY#&bqZi)7GMxyU}P)cXDHKQh!AD4;AgPlV~7!CU`}9QP?_WjMApf(Z|4+RzTJFt z&qwQ&Z8vp3>Mq%qtMbuu&9sxIotDccd76B*1S#F93Labed`1&ONDVwhBmQntI*NJsoHUB#&yEs;W#1nW&{2)U{%w X+3lchE}f>HqCpxfA*Ml0wz2~NY6B~n literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_block_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_block_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..8ac491e8800180b6562f68a94115042c7b59da19 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}Sw*&v2!K;dvFq?PiAaJq*kV3=G?D~_#3r)0A$le#>-SE{Vt=Bd0=WtA6<)C97Hl9#GXnJ_7G%ZVv1(_U_y eDbg}M(9>C^W!GXakCfIci(RJO&Y5)E$_@Z{Vl}w{ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_ore_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/emerald_ore_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..921b4899fd49459749576c605330d094ba94ea82 GIT binary patch literal 132 zcmV-~0DJ!>MM6*k0}ucZ009Pob`(_%07nb}|AH7y3;<3H00UqE0M^@*Yg=yFB&4Y) zwa(XJS8TS+Z1URKF3DLfwJ1}!Xk^c8UQ2CZ+hmj5TWzk}cF8ql$t052+hKZ3R@qvW mb`>UjYqX1P3)b6dD%)<-B(=5OlF-|2*)49i)|T5_b~--EJ32D} literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_bottom_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_bottom_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e4f41424befe9668df162a49d8ca201424652cef GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009NzdH~gb0LO*^+qNL+=t zX=+l`r7LSn!(^pPY_=6-l9EZ3$t{vb+ojS?kl2)k6x5}w5|$LKvPojLm1MG8Er!Ts jgv(_v!qkncZ7oS{ktkFtDJ+&LEh!}}mRTf{$t*fPp8+&u literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/enchanting_table_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..179057055b1077ef36fec7a1e7b3267a1434178b GIT binary patch literal 185 zcmY#&bqZi)7GMxyVB~#R#qhMB;dmRv%Wej50fvhU7%nYfxLVI}Z7##@84NMv40mc6 z?p8CfG%yeZPFkTrut-I%GJ5y!t<#g#D@}Lrj-6h#a_))ft&N?tE?V4ajXl_L=gyh4 zC+=SCJ#**mox2C`96WPS=I&YHJHkDOE$-eG?m2t+Ovk|U5LI4| Wpkd-rbufJ}b71De?19;9Wd{I64nE`n literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/end_stone_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/end_stone_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5dac74bca7d653f4cf81a0164770eff9a500fc5a GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009MK5dd`#0B8^ZT@nCo4*&yT0043%%1%g9u`3l;$eW3` z6>iBDkuw{vMI=f|BatTIOr)fVI_x$k+>zU4WXUB?LnMhO5=xb1j=Ld9xe}7OB#p?E jl1P&>MQe#D)k;NdO4%ee$6S>%+>yg1u-77PM58)BwY@Fo literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5e064d522e61937b84dc3c29b445dbcc7d0f5f68 GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}T@5%HYDo&??DL%FmF^%g`&w5GTmMoWQ`KGRYGwy1DIk?zYco zmjI=2pViL)cV%`ih#l>_ciWB0vtEK^ulxn+T>AgN>i(a(pZrrN|ID9s|Npk%`QM`R Q|NZ{I@AjYVKW(k-0Nm?5Z2$lO literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/endframe_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0e706d395fa55e5402f34eb37e40e0bad2e168bb GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}T-3%Amx-P|D9xWx^0E#K4@uz@Re86Nn5ZYnllqs@(Eja?4X~ o+ey{!o@$#sRi*>UNuJ`KMj$c~!p0^7RteSxF#&2C*kmg^0OhpF literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/farmland_dry_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/farmland_dry_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e6f8a5d0a17c2ff0ba7276e3161ea0994cbf52dd GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009L+2>?O}07M4>Nd^Es3jhOP006Gm?Q*kSaFXS4w&k+Y z;WD<_E~4EqmgOv#=`y0_Znoua!tJJ)A##%Gu$Lupmgz8-<#M+RGPYeVw<#{t;VxHe jEz;RWS6p$@WG^2&Ii$$bbh9uKUBxH)li)h6n jjaHLP#ZhI}j7c?Zam18}v}BE1im1kHky#y$*y=hy{O&WY literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_off_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_off_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..2c743ff02e464c1b26f12d6cf6e729f34ca0a21c GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}P=RVTcf6u;62e5oE~cXJAfXVAys$7l<}_3Qh7%-RLoCqQ=rq znz`FMe*-pA literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_on_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/furnace_front_on_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0cc7e973334a9232e15ac8134dcc19eb3a9570fc GIT binary patch literal 132 zcmY#&bqZi)7GMxyU}P)PVTcf6u;2rt12KXO`TPvb2@DLkbGHG}wcA14Zm+uI-FG*p?gRaMeZRmp2MM6*k0}ucZ009P73;;(A0LkY7Obh_r=KxL&00UqE0Mbc`M@c5wl4OLH zw8}>$Givt7Y_)nxCdA1kkdjK1ZEVWf7AIQU*|JL8NhFF%Hr1mxw312ENhNK`4%o&_ mP?NS>X|^X;O43OrwzlTP)^v@{iQ7pe*qtVlL{8gDHab2ya5k0z literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_overlay_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_overlay_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..7669983d749f28b3eee5401b6db0082e96fb6e41 GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}RAiWf13QkQQdJlVD&@U|>+$c3XAZWj!J3BC*>|W*lk`GZ>f{ L5*rw(1+44<#+nMH literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0e0a24c31bd726cfa088b14235a03b4344046ae1 GIT binary patch literal 132 zcmY#&bqZi)7GMxyU}Q7nWJnig&|qVd5n<5dV6fw4U`}9QnB=JfLLMnVa++uABzINq zh<9z$y(Z6c^;X5MnH62OJMY@nyz5z++mmv2W_y~=%3g9icImCV+wQJh_O`IvDAa87 kN|$TdYc7>;yIr>Iw&!~5PSaPfZ_V~J7YMM6*k0}ucZ009P*4*)g^0H_ZDEeHW^5&%9400UqE03?!0B$8<*l8G&n zNpX`5CAmyjLnbJxlu>A;Qdp#sD5R1}CelkL(`cfTWTa6k5>hCniAf}iNhFd@qKa)Y mn?$TqC8DWFq>)6ll1Vm-NfMJul2U0T+9?uKB`iurq&hxa(kf8^ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/grass_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ec9cd191853ad3e9731b2e0485be7e72ccfd11a9 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M2CIBQD02K`Y8W8|I9{>Yj002cv97;)CQl!*&qa?A( z5=z+FawM8^DJ!zeWi8s|N!XH#Muoy8 jq_mt#I_+gg4RSXuHcHKP)m*g7>XoTuPAMafNaZ>{1ky7d literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_block_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_block_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..72ce37e6db9eabd18cf6b3a843c43fc58275e40a GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}Sy%jN$q-hFi}VUO!{F_l$u#fq}uu$y4Q|itd(4x!dmOZo3U6 prvZuEIhrbye7D^Mi`;~YsDWhB)Oebqi}=FS7H?10|3*WKD7V< literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_ore_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/iron_ore_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..dbcab9763fcfe0ade6af9684b8ac993ede16d580 GIT binary patch literal 132 zcmV-~0DJ!>MM6*k0}ucZ009PYJphC~096bCM+^W=3;<3H00UqE0M^@^k6Uipw(YIC zwbIjVcVu?YZ8AFBZq3_mwYJ>1Y?aX~W^W`(*p}SeTWzx2cF4zeNw(Y8+iE1+UfI&! mmAAH=YqoD9+}7J|NfK_&qV=TRo7-D$*}ZPI*xuV)b~-+phdMM6*k0}ucZ009P73;?ws07nb}Obh@{3;@n600UqE0J2F*X2~VAl4OLJ zY_DvjGS#i7+pgA0C8WtDkdjN1+qA7|9VV@^wIWNaNhFR*Ex9u;yJAVQNg_#TwY0=c mNfNbnC2c0!v$9B}Nl2BXl$1$JNw&?jw3{W8MoqTKEjm7F{xfs{ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..564a2cf4909d7854ae76247d0f2a3998d0cedb7e GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M34gfS704OW~OAi1(6aWKY005S=S+=UHHj>R|xT7|j z&1R^hvXqTxvdX5^t){Zdw%2W@vW==&X=PH4tkzj&N{y`6X{DP=u3F8dn#zdU%{7|i jDB8<4n#(NO%{7}#Hrl1On%Om)p>>*#wHs-+n`$~fku*CB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_acacia_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4a9b8258c1f420506b44a854f10dbe8da5c774ba GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}O)HVF>19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..564a2cf4909d7854ae76247d0f2a3998d0cedb7e GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M34gfS704OW~OAi1(6aWKY005S=S+=UHHj>R|xT7|j z&1R^hvXqTxvdX5^t){Zdw%2W@vW==&X=PH4tkzj&N{y`6X{DP=u3F8dn#zdU%{7|i jDB8<4n#(NO%{7}#Hrl1On%Om)p>>*#wHs-+n`$~fku*CB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_big_oak_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4a9b8258c1f420506b44a854f10dbe8da5c774ba GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}O)HVF>19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..564a2cf4909d7854ae76247d0f2a3998d0cedb7e GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M34gfS704OW~OAi1(6aWKY005S=S+=UHHj>R|xT7|j z&1R^hvXqTxvdX5^t){Zdw%2W@vW==&X=PH4tkzj&N{y`6X{DP=u3F8dn#zdU%{7|i jDB8<4n#(NO%{7}#Hrl1On%Om)p>>*#wHs-+n`$~fku*CB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_birch_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4a9b8258c1f420506b44a854f10dbe8da5c774ba GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}O)HVF>19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_jungle_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_jungle_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..aebc8aada84011a61c68d10d409cb0d5afe3a54b GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009MK4**pe09h6QT@wIL9RLGh001T1NhFgZs19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..564a2cf4909d7854ae76247d0f2a3998d0cedb7e GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M34gfS704OW~OAi1(6aWKY005S=S+=UHHj>R|xT7|j z&1R^hvXqTxvdX5^t){Zdw%2W@vW==&X=PH4tkzj&N{y`6X{DP=u3F8dn#zdU%{7|i jDB8<4n#(NO%{7}#Hrl1On%Om)p>>*#wHs-+n`$~fku*CB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_oak_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4a9b8258c1f420506b44a854f10dbe8da5c774ba GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}O)HVF>19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..564a2cf4909d7854ae76247d0f2a3998d0cedb7e GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M34gfS704OW~OAi1(6aWKY005S=S+=UHHj>R|xT7|j z&1R^hvXqTxvdX5^t){Zdw%2W@vW==&X=PH4tkzj&N{y`6X{DP=u3F8dn#zdU%{7|i jDB8<4n#(NO%{7}#Hrl1On%Om)p>>*#wHs-+n`$~fku*CB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/log_spruce_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4a9b8258c1f420506b44a854f10dbe8da5c774ba GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}O)HVF>19Fp**im16MXXRsD!h!J66PGDfTnL8<3ciSaTl}S!% z!Tb2kUV!8B=YR?$^ZW+ k17%ev39AK9<^<{r{`vp^Po+&j(>&E~=1#kvGR?{k06v{PGynhq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/netherrack_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/netherrack_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..7f4790add276ecab79778221aca5f99909e83257 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009LN4FDq_02L4b9uxo$3jhOP005FS$tFf*lDc6fl1weq zVYQlTW|-ur(+N?S-7Uijt(IMhwrwqwX(lqwZkY)-vukvdB#fImBTHE literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/obsidian_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/obsidian_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e4f41424befe9668df162a49d8ca201424652cef GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009NzdH~gb0LO*^+qNL+=t zX=+l`r7LSn!(^pPY_=6-l9EZ3$t{vb+ojS?kl2)k6x5}w5|$LKvPojLm1MG8Er!Ts jgv(_v!qkncZ7oS{ktkFtDJ+&LEh!}}mRTf{$t*fPp8+&u literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_bottom_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_bottom_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..9a6e99c1b979acc01bf1bfd6325da862710a27da GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}P=eX9yQz$lzy)5oCxLXJAfXU`UzdsXNKD$X%$&I-FG*p?gRaMeZRmp2h6+y6d6Q{`z&dU-sU+yZ`%5)9u@Cn|C79QEs7#7fndGURzNk9qqh;=<^*J;3HMgD4-Kd)})cJVRV8&*x7|$HsGU2- gJ7=PG?xfo(otC-Nf^{}(r%wXv0&3Tp&Fl~rk$nVDQycXUT*aS;_a5fOJ$ z5qEqwTe~$?Q#H)0az>% literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_top_sticky_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/piston_top_sticky_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..9e8c1f200061df1f27dc2866ee7c97888e6dee89 GIT binary patch literal 357 zcmWlTze@sf0L7nn)i*ifYa}%|T!n&5=oCqmcj`sjV1wn4Q==j@tj=HO=`E=>)YcXe zjx9A8Zsz$P1oa<8LrV?KeS^p2Gd$jVuCNrdj8ITmd?^PMitGmtW|3Er-$lWRLK;UY z6muxjF({eG1dooZ;J>WUJ!|3@;;9m=$-oLw+|g}Z6Yvri$dGBJs>o)`26y;=Xn&ZoPA2`wS03NM4;>Vfjz@ZJ~W1IJ^<9M81%TMD=j^d%%Vsc!{{WCui-6 hpLb`;LS{1O;(%XnacXcfA9AWD?`2!;Gjr3w`Uf@yV>ti- literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_acacia_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/planks_acacia_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e01979a595e0671b4b68dfd6d5dd88b79bf606d7 GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}S0HVkqTh$P{9Tl4W2{U|{Iou2STwG)YrB_qfu;ZBK$cl~g8q z0#WaFrQVe)xj-qm+mk$%ay?Zb;*&h)fVkULa#!4% jMp8_W(oHP02_{rcB(ofZ)g>&{WR6nXme*~rw_7?s3h^!% literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_dark_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_dark_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..2a99d360960975d47441fe076e34d01d1d6aecd6 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009Nj5dgOr0LT*ntQi2m6#xTZ002o^lZjhpO*>JE8k?$^ z=}8q+WV&0dnn{sWWvW_}m6)kfG?A*cSyh`+q?Svpy3LlO|-n>8UiS jtd`qlmf2QXrI9%ksXJRq8ELH;sjigUq?$==x?4Iv**rGJ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_rough_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/prismarine_rough_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..589b79e2818ca699f65688e66f7f80b7d33020e5 GIT binary patch literal 423 zcmV;Y0a*SeMM6*k0}uc}009SaDFC4m0EQj_nG^tOEC75X0FD^|1AqYl&EK~!h}R=Q`eG=Fb1p?b-X^H)rndpPsw3Uv%b9<(<3F{?9Le*`?EUzufJ$)9v5l@y+ka zw{F|^-CHL%Zg{p!ewV4YdQbG8{>MAF{PJ^eH~ruJ-}~F{&Ci!Po~_Q_fBiT#mHzh9XnVy|PA5`R4<(-qu{=Y9J*`?Dpztt_iS?%BAxy`PLcVya@r_((s zZe2EGYL}_8dRp-A{zt2~ojBiTde zCq*vmIh&nBA64{Y<(-pj{=dzo8KsjQKb0xI8R>uQzVb+kcVya)$Jae5Zc;X9>Ys_R zdRmij=UOA5QbJ^tCb{#i)R`0J&HtAInV#)K zAC&H1<(-piNk7j?8Ky|}ztt_T$?bpb9&gVH_h{Od_q#v%ZjZKmewE3u`d{$%CWp(n RpTcARCq3W&*ZbS%IzFQp@st1n literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/pumpkin_face_off_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/pumpkin_face_off_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e3e4a1b94114aa87aa68f870b8ac1e72fa290894 GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}P~7WH1wCFc)NyWoKYcU|`5Ko1D32cFGp7lr7#FJ2}&gfTUuP zTX5z{$>@Y{D2THrOlE3Y%e-fyk=l@ zSv;aq0trOZeF~fT{gA>o&W6^b2_Ch4Vf{=)s7c;fYx^k}XTu;==5Kru-mO5y?y;;JARYSw28GcXaFCddK A^8f$< literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_bottom_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_bottom_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..d09984340a3f5b0571a89b96a541213d3d5f3cd1 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}U}I!*I=w;g%i4T?>Z$#th5}3=E!XUPU)9c`5}Jxn1&@6kMb- zDPvM_rpn}uNwYJBW_!%e@|YClu`|nMl9%gFT_D?K%G*qpV2?>}b3tlu=PruwRhs1~ hbfeV+l1m}B+ax+ZYZ5WS literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_chiseled_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_chiseled_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..649ed0f2dbd7884507e5f3136edd9b94a003dd66 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009NiPyo_Q0OmUY)Jb7Wy<(Pn0l6_i1xrrFw0Z$apdd&AP**F6^Z}^^vQGiE$1FYN(*jfmRC5Z* I29Z{F02636$p8QV literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_lines_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_lines_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..4d020b2eed80596a710e08dfdb98fba7896684b0 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}U`z!0^z4;gToA3rmJq1`Nyz3=B(d`7XWXtLZVN(_@OpB=1bK ziyJ0+=WcttVag;=rKcKGZs#lt(b#f1Wl`Y9Ew^$OrEZvVDR)__28g@@l+6W+gH&$Z X=BYAmsV0b=0yb^p+Ni5QWMu~c_E0%s literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ce73796f6fc89aa496e489059904ebc214352157 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}U}I$8g1y;kqls`2dFZb_~o33=ESzRaz#i07>6XzLPwad?)#~ zc`CU8Nsl0x6QONxH`P3O+th9vd8$rSyRGJ_I>~9a%Vgd*kJ%m|HIqCgMKxvws+^dr dsgyFw<*uf($|SeDx<)CQ+pccAoeM-(b^u7CEt~)V literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_top_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_block_top_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ce73796f6fc89aa496e489059904ebc214352157 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}U}I$8g1y;kqls`2dFZb_~o33=ESzRaz#i07>6XzLPwad?)#~ zc`CU8Nsl0x6QONxH`P3O+th9vd8$rSyRGJ_I>~9a%Vgd*kJ%m|HIqCgMKxvws+^dr dsgyFw<*uf($|SeDx<)CQ+pccAoeM-(b^u7CEt~)V literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_ore_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/quartz_ore_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..f2ed48969ae09f215f1c4b24780936eae7ab3c90 GIT binary patch literal 135 zcmV;20C@i;MM6*k0}ucZ009TEKL8^i02dDcsyYE26abty01XZT17H9ECba+l*Us0! z@6rF^?f>SP|MP$RN#Fl}Rq|)=Z-4K3pN41u?oatUKKE~XN#DL>fBsId;$nXDCr@KP p{+;W2?fd#|+sFI=xBvb=_aCp{cJ9gF=idMR_WyKhC+`%X2!y0a J9AvVU9RLTsEQKhC+`%X2!y0a J9AvVU9RS_tEGGZ} literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_powered_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_powered_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..6b915f1a71ff6584db3c0bea1bd4e168fc32c09f GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SaTW4QE;q2)P4zm4jgXAH~<3=FD4o+`6CagxC*lcYLTgQfGZ MlVDlACRo`405Gp6UjP6A literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_detector_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0799d9bb4fae1279302238ae0dd1314fa5eab746 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SaTW4QE;q2)P4kfQ3GXAH~<3=FD4o+`6CagxC*lcYLTgQfGZ MlVDlACRo`401K)n2LJ#7 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_powered_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_powered_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..03de3af609a5bb2380800a2e85590d4c83fba073 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SaTW4QE;VGa;IXQIo7Fa>8S=MEqs>%*$|Q< JagfPYb^w0qEaw0K literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_golden_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..a29e96c94ee7653900554cbb72f478067f6216ce GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SaTW4QE;AxKem&NGHN&l#8#7#LK&JXLOVs(PJNMUdVpAU1@g KL>y$Yl^p;wrZEcu literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..87b59b13596d50b421b3c05978ef9318aa1646d9 GIT binary patch literal 91 ocmY#&bqZi)7GMxyU}SdUW4QE;Va_uKCI<$F=+Mxolwd160Fyx^2><{9 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_turned_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/rail_normal_turned_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1e70e81512cb7768d110e04c9d6afe416ee34ad6 GIT binary patch literal 91 zcmY#&bqZi)7GMxyU}SdUW4QE;Va_uKCI<$FPy|>N8XEOKG<1DvXxP`#&}g7UE)Z{p W;IOMeVIT$y#{+Q{5I+TBD?0%CFCXs! literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_off_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_off_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..cab76014682f4db3bbc219bde454e9fb76271c43 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}U|_$8b!DVTTyQ8YzakatzD~3=ArhJb_4K#!NkpKvi=gJrhsW z6DQToCK|bQrCKT)nZ)$0)YP5ybfeHkRiUR_Cv~b!PuZsAsXOV-R*{=pMnM_d6*WCN eUA-l>tOd2K6ICsx^mcS=EV-zs5(qKb$_@ZMswhYR literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_on_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_lamp_on_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..036a84095922c2cc3017fcf0d6d4a0e8e49472f5 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}T*mzhaL3($fNrbL1Phid!)!Ffin9yA4F8R~8qByv{q4Tj(8K z=B%CToSmr}+jl59)$2*%74IT*A-CPydAo&z%%gL6gs6tyE(+&ywN@_mdNcJzaM{V| ebxRhfI%Su-1m_${EjSWgdRx0N>NUh(!Xii%Vrp;5lGYR5a}408s~ zBGLrKld4$rF%Qc-u6b1H?n%eIQ$jxcJpnOF9<5&nC^Rs&h; Hx-82dki|4< literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_torch_off_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/redstone_torch_off_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..b3a8024e2cc3ad1925b18dd915a7add2e2ff3b35 GIT binary patch literal 88 pcmY#&bqZi)7GMxyU}Q?+XXv+4WpZF(2*m}$riO-sFacm?2LQ^f83O$Duz~sQdunHGgnYC&aJ`B}oWd{Iz94r$6 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sand_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sand_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..6672b3c0ea0af2b751769e8887b68b8c0e9422a6 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009Lc2>>(;04WLpNe%!!3;+XQ004C=lBp#cNmi1!B$ZYq zl2+7|X(duATT`m5ZAnz?NkvjsG?QtkQcA^AN~Ek!Dy^#2s!^npYNV1$RF$aLQnsZM jROzosy)DbySo}B~>XU5=kVKmRTj1*=;&LedR1^ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_normal_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/sandstone_normal_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..2de9bba4c0f77f38b38dde99bced4c29d95af93c GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009Ly3;-t&04NRsD-8fW3jhOP003z=(`mGla!Co2NZT?J zO(xQ9DWZ~YrqVJ(+m*=Vl0xH^$t8r6TeP<&sWgd65^7P&QjwIZjk#QMR_nIdWO5g6 jNi%Jhs?u$glBvSmZdoLRJNGAY+&(xkT2I+MIp za?Ni0ZkdxRG*M+zPpU|l#v-4LNnNT+K(fcsFJC+QfX5q jWhTvTwAx7|Rj%5LDU|DVG?68iU9F^2g(h8TmQp%CHu*3_ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/soul_sand_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/soul_sand_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..f128bdb325a40564f4f7b206fbbc6a31fa86acdd GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009Le2>>+;07)PKDhL2S5dZ^V002nC36dyGktD1oB2-Zl zibk0vhMJ0oNh6U`V~JZLgrf>E66aF jh}2X?q?|O;l!{cOjS_5D$s~!H8I>s|X;on*LTfrcm$oSa literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_andesite_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_andesite_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..7d3463dbadce67ee662b395ef4ad9ca014904413 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009L+3jj0+09POYN)P}n1^@$K001Q;5iu2GG7}|E*2yfp zWQemVMv_WSl?k<&Q)U=#Zp#^j%Ud>9WRlj&gs4hZ6=bE#t8my&WmejSl?;+HVMsE@(lg9B6K55fKN$*iuLF9qir=W|a>1*<5`BXCEN5@xZ^G zFR$z+8Kjg_GWyKvy`(UuFrzS`Fs9dvzD&ah(Wb1*xYHUCDfnqM3*gPsL7-uFkX9=g zi@t!UyjD=oi#h*aEDIZ*LvQMqJKeX&IuGr%xprWWF1n1txZ5lP6dTLYIse=?O>>Lw F4?nXtCwu?^ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_granite_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_granite_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..bb4dcb77c78d3d05b20e2267b716829e5361e586 GIT binary patch literal 129 zcmV-{0Dk`^MM6*k0}ucZ009M1CIBG`0456nJRkrs5dZ^V005TQ)3(=bwKilh%X?DkblBdd_ zoQgS_DwBNNll?6w`?$^WG?{%SWm2Za>q0&e nlRJ-GDoLB;sWQ(e0;qnHkIOtyb)g)$NtsV3`2dXsA}c!p71A<5 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1651f26b3076e94e0d7e5cf0443ad4354fa4325e GIT binary patch literal 126 zcmV-^0D=D{MM6*k0}ucZ009J53;;(A089)3P7DA8U;qG(w+Tiz+>nx6WR)X{wA(I7 zWQItgk+$4~w%cryN^VHoibm8XNXe2yN|H9)X}08qqU3~k~ZWzKEq@)SO5S3 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_slab_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stone_slab_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..dfcb2043c9c4adcd291584bd8ee94be97fb04eee GIT binary patch literal 135 zcmY#&bqZi)7GMxyU}SILWhmfeDCA@a;${fpW+>-osN!Z|PGDeAndGT5$edjbg>f`W93sK5tM;&+TIa!*4;EpZ<^UH;+Y`~K{7 zyatmw%_*2!ri!U$Dw*C)XQm6&lWF=PO8mFVhlxedNcmczfYHuI+II@nkpUo*{?wsY z9Pa8wRnpi255Pw2!4}DuKwCPjV$+yHHg>D6igxM1A>)sTL!sH&skqwv{1zrY-0lB% CFfCXB literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_carved_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_carved_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..cb99d6887ff5c795679d9f68e179ba97c1c81285 GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}SBOWGK{RNU~%oS7yjCW?)WWV94EdciZmFva2eSR3@&N@uLpjy0Qr-L{1rRhCTBn5Y6YZIY*z9RRJfG`9c% literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_cracked_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_cracked_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ad4593746cee0e0b1efa727b259036c92e9e6a1d GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}P=SVo0`Rs8C|aG-9ZiW?)WWVDQwK?Ww66nJItYq7OC^v|15E`NZ85K#LYI8Do)0+UxIagu zm|}`1*OH!VdP%BJ#GrddkDNYB8h?qV2lnpP^ojGX0y^7Tct|z(l3R401v^(O(?9@K zW@@1}Y_thMsiGKE!>V5-haGY@jsYiE{VY|0v?kFK;MQ26g_IX(ZLPIV-$Lt9gyDaL Ga{B|+WG#pQ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/stonebrick_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..6868e1408241bce47e0e6a93b00b29f019f1984d GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}R0OVkppLC|6?0Fk+~eVqi{SU{IOiGf7g_$WmP|4Ql9xP}%w%fTt)H2Ce(LWU|`6db`yv)-KM~ik+TXAQA^y)4gjrW BE2sbf literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/tnt_side_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/blocks/tnt_side_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1aa8886fe124893a456372cbf855fcf9825b31dc GIT binary patch literal 129 zcmY#&bqZi)7GMxyU}O#8VQ>{-2OKt&?&yq8(OQJkQx(t;j zc`9{jIZg6is-!dHmd})jZNgHX$|@6<3VEt5X%!aonW-{yMU?MSm7W#1JT(@zI!yxV UG7_5Pv*ecRk|>C25RTsNiCVm14-}XJAfXV94Ee8;CZls!VcK&AJ^j?bhT~ zle|18rLLOf(=jP@qmWm~q|{6ypMXihn>-dx@>JdAu>?r2y0s|m%G8ZQK0w*5Nl77- ag@NoTlT}v=c?AGQtG@2_h$Rs!RbZScD)|g+Oc%kVY@C-iaU*q6}=Bl^p<(kR{9j literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_pulling_1_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_pulling_1_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..be777dd673bd300152679cc461ad36ea527a380e GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}Op4VhE6ASpSS6{uu*v0t17}Bu^kxg^-&-Y#2&ZnG~op$p=Kv lyLO^mN+)OJw0Ir@Ua{vGU literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_standby_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bow_standby_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..af3c5cf0f7b73c390fe04ce6244baf9c52f9cd3f GIT binary patch literal 91 zcmY#&bqZi)7GMxyU}O&9VhE6Ah=0bw=;l^p;uR~s7u literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/brewing_stand_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/brewing_stand_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..cfff2fc1d2d8c22b011908ab359b39f3471b27f3 GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}VXXWr$W{s1afC7iM5iU|{f6nFK*zUJR2LMaa8)X0h literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bucket_water_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/bucket_water_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..a07b5187baa7a2b3b2a05631f73b7fc80a4acfed GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}WkFV#s^Oz~sQdunHMW4O_J`G&E~fXy~d{OQV1?OINL0whTyv OFbKeC2oFSB*#Q7x)+{Cf literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/carrot_on_a_stick_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/carrot_on_a_stick_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..339ee0704b7f7c22e509a94574a8458a9db9e736 GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}Op4VhE6AaA0MKf5yO^z`&p~$rFYqf*4c4+(jT#RVWZhYD@x= sE+EoN1w=wnCz#=>G7ZQ`aoKhfNV;wV>I%}`1SCCk!N%rH^0cx806kD9>;M1& literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/clock_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/clock_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..d2cd4830ae873b5692eaff80a77cb8b1ef9bfbe1 GIT binary patch literal 4123 zcmeH~v2MaJ5Qa_Z1Mmdhx|BEQ(4kU0cX1*iq3qei7V;Ds5fej>XFxnfo}m(Z*aG}# za1~V5l6^>sib$3R=gW6@K3Vbe$NN{WKTzti*Z+J{qi>bH3?I}$k$n~;qPQkX8mf{e zt>QYZqB5nZv~Rd)=Jf^m82(t`H+&lyzeWw%4_;$<=bxblt$>H0d3Fc+yZj#UuRQmU z`5b<*Jc9VF!>P~^?0;zfsDau4Yw~kp{4*iX=dUFHOYke(q3-!t|MLE^U&@zmuU-Aqf9Gw9ob$bY z=IlS7|9t-1{=M=3nF`~V@;jkl!cTDiNcgRg-(8V!(7zHt_~otg8FH7zpM!5t_1gyY zFW9B!Ct>`L-|PORiN^SU-6M7$ynnuY-r=VKd;z{V`6WDm!}tD$+{yUs)WqP+ Y8u176afc7NKU+S5KbUX4?(eT}2Rp{Ui2wiq literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/compass_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/compass_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..d66a293b47a35f1435a9714306197595130736fb GIT binary patch literal 3102 zcmeH}u}Z^G6ozlDqezL+C%6HH2E@_9K~l(VGK8*K@1W3v2(C_X52w%vu@LbQ@(7`; z^f^5D+*p%pAj8R4=#-{k{(kxSx$g8n9t=l9oD5Fma}n>vi#vMViJ>?XpydCbK*>Ua zqvT3vpi=g@(=dEI=^Y_|LucupB1(R&C`C`{wuF<{)X~@GM*2k eMtxGR)vN}0dZ*9QXl~oz`&_6 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_shovel_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_shovel_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..fdc6e0e356b9119d1c3588f3d8c60123d14e017d GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5VmML3z~sQd5DEujOG87WR)&UV0r4szjso(-rUEfs1vZA2 F9RM&K8w&sc literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_sword_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/diamond_sword_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..969b360de574a8eb3096ed4ebd094bd6b453532b GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5VmML3z~sQd5E>eq1;ndDL&JbLY9)}n6v&+#1>{D}S_u?g X3dB>vDnhe>bkx#N5Ckd&V=FrVoH!px literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_cast_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_cast_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5098437bf789863d5494de1fe26b04e3815d84f5 GIT binary patch literal 91 zcmY#&bqZi)7GMxyU}O&9VhE6Ah=0bwdDg;M? JI1pfE2LKrc8h!u( literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_uncast_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/fishing_rod_uncast_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0530e40cabddd9abcc5fd5a371b28d3308da609a GIT binary patch literal 126 zcmY#&bqZi)7GMxyU}Op4VhE6AD1OEe|BQh-fq_9~k|zvJ1Tm(7xr;!gs!$-1)R+V! lT|lIl3W$WDPA~(g49G}vfsi1*L8{Y$q^Ig85D7$9b^x6mCgA`8 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/flint_and_steel_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/flint_and_steel_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..8e55ba3e2d0627c76ff272e7a5d8ae907eee7e06 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}T!`j3G~sfyse^VHF5Oty;A*Y}Klzp+KAp#92@bVgtoMav(L> HfR!BpKFBLX literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_axe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_axe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e8c081ed280189682f9024f6555a7e4f46efa315 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56zz~sQd5DEsFKyp=RXc!Pjtps8ad)87Q0m4%uYOs@5 Fb^u1?8-V}- literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_hoe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_hoe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..7ec0ebeb0cec32d922ca7f817f91e7e395a3772b GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56zz~sQd5DEfeOG87WRs!i&Ku#7^Aap8_K@eEk0RSf( B8jSz| literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_pickaxe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_pickaxe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..ce0adb6c3c39eeabc8d2c8661c7c423cdc327ebc GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56zz~sQd5DEiPD?>xGR)vN}0dZ*9QXl~oz`&_6pb literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_shovel_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_shovel_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..1e3c5752e5ce19bb7dbbca9ee2419237f2f91224 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56zz~sQd5DEujOG87WR)&UV0r4szjso(-rUEfs1vZA2 F9RNKP8#(|0 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_sword_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/gold_sword_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..0023c9fff480dd07860ce2aac09c02f5a94d798d GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56zz~sQd5E>eq1;ndDL&JbLY9)}n6v&+#1>{D}S_u?g X3dB>vDnhe>bkx#N5Ckd&V=FrVsW2aQ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_axe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_axe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..96e75623c266db53eba60246c4d011f1cb621f39 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56rz~sQd5DEsFKyp=RXc!Pjtps8ad)87Q0m4%uYOs@5 Fb^u148-M@+ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_hoe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_hoe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..aabf4a1251c6d8e76efa078a7b99dda47813203c GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56rz~sQd5DEfeOG87WRs!i&Ku#7^Aap8_K@eEk0RSe` B8jJt{ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_pickaxe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_pickaxe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..e9a82c5d6805a41f9c8be7ce4707fb96ba0a9a58 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56rz~sQd5DEiPD?>xGR)vN}0dZ*9QXl~oz`&_6~ literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_sword_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/iron_sword_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..dc31fb660d18fce2ae8c685bebb5423791facc50 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V(56rz~sQd5E>eq1;ndDL&JbLY9)}n6v&+#1>{D}S_u?g X3dB>vDnhe>bkx#N5Ckd&V=FrVsOTSc literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_chest_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_chest_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5cce2f98fa733661d9643aa6c6a5f72fa1ca8bea GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V#s^Oz~sQd5Q+t)hK5FFhK6Qlg@&!nnwqsTYuT!mS*up9 Vj9Rs7X&4ZP0#Rrd5Cegg9ROooA65VW literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_command_block_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_command_block_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5cce2f98fa733661d9643aa6c6a5f72fa1ca8bea GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V#s^Oz~sQd5Q+t)hK5FFhK6Qlg@&!nnwqsTYuT!mS*up9 Vj9Rs7X&4ZP0#Rrd5Cegg9ROooA65VW literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_furnace_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_furnace_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5cce2f98fa733661d9643aa6c6a5f72fa1ca8bea GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V#s^Oz~sQd5Q+t)hK5FFhK6Qlg@&!nnwqsTYuT!mS*up9 Vj9Rs7X&4ZP0#Rrd5Cegg9ROooA65VW literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_tnt_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/minecart_tnt_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..5cce2f98fa733661d9643aa6c6a5f72fa1ca8bea GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V#s^Oz~sQd5Q+t)hK5FFhK6Qlg@&!nnwqsTYuT!mS*up9 Vj9Rs7X&4ZP0#Rrd5Cegg9ROooA65VW literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/shears_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/shears_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..f6ee11cfbd679ec122262ff92ba2717183cd77e8 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5Vkmybz~sQd5Q+k_fV`DcL&KH<@vNz#p&))HSVb6+7nusd KAT|tG*#Q780UKoi literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_axe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_axe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..8584d6eb6ec8914f33d92016186755ae2b9a6ba1 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V({f+U~*t!2nB;oAh{|uGz^HNRsu1IJ!>hD0O6?+HP}fj FI{^3E8fgFk literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_hoe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_hoe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..da948d76259d5237a60fed4af10b9b9e3ab606c8 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V({f+U~*t!2nB(#rJ3 AbpQYW literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_pickaxe_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_pickaxe_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..56feb8450af41a044e44aadb376cbb933a030ae7 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V({f+U~*t!2!(;Dm7$?ot3pGgfH*X4DUbjPVBl1kau{u8 F2LJ$w8u0)C literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_shovel_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_shovel_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..818e25af160493bc91981882501e6f3f3c5ddd79 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V({f+U~*t!2!(^NrJxGfOr)UM*;a^Q-K(+0vp51 F4gl^78X^Dy literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_sword_s.ebp b/sources/resources/assets/eagler/glsl/deferred/assets_pbr/textures/items/stone_sword_s.ebp new file mode 100644 index 0000000000000000000000000000000000000000..439f95352e5ff205fa74fe26c24f83b6210692c0 GIT binary patch literal 88 zcmY#&bqZi)7GMxyU}Os5V({f+U~*t!2n`L*0^(Jnp&h-6`@%`I%;Vs2m%#?v6USFS~VVC literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/brdf_lut.bmp b/sources/resources/assets/eagler/glsl/deferred/brdf_lut.bmp new file mode 100644 index 0000000000000000000000000000000000000000..54b6c70ddcc9b9f9f050345fbb8d67aedc25d094 GIT binary patch literal 8192 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 Dm+SG| literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/clouds_noise3d.fsh b/sources/resources/assets/eagler/glsl/deferred/clouds_noise3d.fsh new file mode 100644 index 0000000..d262432 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/clouds_noise3d.fsh @@ -0,0 +1,55 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out float output1f; + +uniform sampler2D u_noiseTexture; + +uniform float u_textureSlice1f; +uniform vec2 u_textureSize2f; +uniform mat4x3 u_sampleOffsetMatrix4f; +uniform vec3 u_cloudMovement3f; + +#define GET_CLOUDS(pos3f, accum, factor, tmp3f)\ + tmp3f.z = floor(pos3f.z);\ + tmp3f.xy = pos3f.xy * 0.015625 + (tmp3f.z * 0.265625);\ + pos3f.x = textureLod(u_noiseTexture, tmp3f.xy, 0.0).x;\ + pos3f.y = textureLod(u_noiseTexture, tmp3f.xy + 0.265625, 0.0).x;\ + accum += mix(pos3f.x, pos3f.y, pos3f.z - tmp3f.z) * factor; + +void main() { + vec3 p = vec3(v_position2f.x, u_textureSlice1f, v_position2f.y) * vec3(u_textureSize2f.x, 1.0, u_textureSize2f.y); + p = u_sampleOffsetMatrix4f * vec4(p, 1.0); + vec3 sampleCoord3f = p + u_cloudMovement3f; + float noise = 0.0; + + vec3 in3f = sampleCoord3f; + GET_CLOUDS(in3f, noise, 0.5, p) + in3f = sampleCoord3f * 2.0 + u_cloudMovement3f; + GET_CLOUDS(in3f, noise, 0.25, p) + in3f = sampleCoord3f * 7.0 - u_cloudMovement3f; + GET_CLOUDS(in3f, noise, 0.125, p) + in3f = (sampleCoord3f + u_cloudMovement3f) * 16.0; + GET_CLOUDS(in3f, noise, 0.0625, p) + + output1f = noise; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/clouds_sample.fsh b/sources/resources/assets/eagler/glsl/deferred/clouds_sample.fsh new file mode 100644 index 0000000..b943090 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/clouds_sample.fsh @@ -0,0 +1,92 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; +precision highp sampler3D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform float u_rainStrength1f; +uniform vec4 u_densityModifier4f; +uniform float u_sampleStep1f; +uniform float u_cloudTimer1f; +uniform vec3 u_cloudOffset3f; +uniform vec3 u_sunDirection3f; +uniform vec3 u_sunColor3f; + +uniform sampler3D u_noiseTexture3D; +uniform sampler2D u_skyIrradianceMap; +#define GET_CLOUDS(pos3f, out1f)\ + if(pos3f == clamp(pos3f, vec3(0.0), vec3(1.0))) {\ + out1f = length(pos3f - clamp(pos3f, vec3(0.05), vec3(0.95)));\ + out1f = smoothstep(0.0, 1.0, max(1.0 - out1f * 15.0, 0.0));\ + out1f *= textureLod(u_noiseTexture3D, pos3f.xzy, 0.0).r;\ + out1f += u_densityModifier4f.w;\ + out1f = max(out1f * out1f * u_densityModifier4f.x + out1f * u_densityModifier4f.y + u_densityModifier4f.z, 0.0);\ + }else out1f = 0.0; + +void main() { + vec2 latLong = v_position2f * 2.0 - 1.0; + float latLongLen = dot(latLong, latLong); + if(latLongLen > 1.025) { + output4f = vec4(0.0); + return; + } + + float mag2 = 2.0 / (latLongLen + 1.0); + vec3 dir; + dir.y = mag2 - 1.0; + dir.xz = latLong * mag2; + + vec3 samplePos = vec3(0.0, -4.5 + u_cloudOffset3f.y * 0.05, 0.0) + dir * u_sampleStep1f * 0.2; + samplePos = samplePos * vec3(0.05, 0.1, 0.05) + vec3(0.5, 0.0, 0.5); + + float sample0, sample1; + GET_CLOUDS(samplePos, sample0) + + if(sample0 < 0.002) { + output4f = vec4(0.0, 0.0, 0.0, 1.0); + return; + } + + output4f.a = exp2(-sample0 * 5.0); + + vec3 sunDirection = u_sunDirection3f * vec3(1.0, 2.0, 1.0) * 0.025; + float sunVisibility = sample0; + + GET_CLOUDS((samplePos + sunDirection), sample1) + sunVisibility += sample1; + GET_CLOUDS((samplePos + sunDirection * 2.0), sample1) + sunVisibility += sample1; + GET_CLOUDS((samplePos + sunDirection * 3.0), sample1) + sunVisibility += sample1; + GET_CLOUDS((samplePos + sunDirection * 4.0), sample1) + sunVisibility += sample1; + GET_CLOUDS((samplePos + sunDirection * 5.0), sample1) + sunVisibility += sample1; + + sunVisibility = exp2(-sunVisibility * 50.0); + sunVisibility *= 1.0 - exp2(-sample0 * 1.2); + + vec3 sky = textureLod(u_skyIrradianceMap, v_position2f * vec2(1.0, 0.5) + vec2(0.0, 0.5), 0.0).rgb * 0.05; + float intergal = exp2(-7.33 * sample0) * -9.0 + 9.0; + + output4f.rgb = (u_sunColor3f * sunVisibility + sky) * intergal; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/clouds_shapes.bmp b/sources/resources/assets/eagler/glsl/deferred/clouds_shapes.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f4743c8dd933bbdbd4c37f80fdaf61a38f60c3af GIT binary patch literal 12288 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 0.0 ? ao.g : 1.0; + shadow = mix(shadow, shadow * ao.g, 0.9); +#endif + + lightmapCoords2f *= lightmapCoords2f; + vec3 irradianceMapSamplePos2f = normalVector3f; + irradianceMapSamplePos2f.xz /= abs(irradianceMapSamplePos2f.y) + 1.0; + float dst = 1.0 - dot(irradianceMapSamplePos2f.xz, irradianceMapSamplePos2f.xz); + dst *= dst; + irradianceMapSamplePos2f.xz *= 0.975; + vec3 skyLight = vec3(sqrt(0.01 + max(-u_sunDirection3f.y, 0.0))); + if(dst < 0.005) { + vec4 sample1 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + skyLight += mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, irradianceMapSamplePos2f.y * -12.5 + 0.5)).rgb; + }else { + irradianceMapSamplePos2f.xz *= vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : -0.25); + irradianceMapSamplePos2f.xz += vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : 0.75); + skyLight += textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz, 0.0).rgb; + } + + skyLight *= lightmapCoords2f.g * u_skyLightFactor1f; + + vec3 blockLight = lightmapCoords2f.r * vec3(1.0, 0.5809, 0.2433) * 2.0; + float emissive = materialData4f.b == 1.0 ? 0.0 : materialData4f.b; + vec3 specular = vec3(0.0); + +#ifdef COMPILE_ENV_MAP_REFLECTIONS + float f = materialData4f.g < 0.06 ? 1.0 : 0.0; + f += materialData4f.r < 0.5 ? 1.0 : 0.0; + while((materialData4f.a >= 0.5 ? f : -1.0) == 0.0) { + vec4 worldPosition4f = vec4(v_position2f, depth, 1.0) * 2.0 - 1.0; + worldPosition4f = u_inverseProjMatrix4f * worldPosition4f; + worldPosition4f.xyz /= worldPosition4f.w; + float posDst = dot(worldPosition4f.xyz, worldPosition4f.xyz); + if(posDst > 25.0) { + break; + } + worldPosition4f = u_inverseViewMatrix4f * vec4(worldPosition4f.xyz, 0.0); + vec3 viewDir3f = normalize(worldPosition4f.xyz); // need confirmation this should be negative + vec3 reflectDir = reflect(viewDir3f, normalVector3f); + reflectDir.xz /= abs(reflectDir.y) + 1.0; + float dst = 1.0 - dot(reflectDir.xz, reflectDir.xz); + dst *= dst; + reflectDir.xz = reflectDir.xz * 0.975; + vec4 envMapSample4f; + if(dst < 0.005) { + vec4 sample1 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + envMapSample4f = vec4(mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, reflectDir.y * -12.5 + 0.5)).rgb, min(sample1.a, sample2.a)); + }else { + reflectDir.xz = reflectDir.xz * vec2(0.5, reflectDir.y > 0.0 ? 0.25 : -0.25); + reflectDir.xz += vec2(0.5, reflectDir.y > 0.0 ? 0.25 : 0.75); + envMapSample4f = textureLod(u_environmentMap, reflectDir.xz, 0.0); + } + if(envMapSample4f.a > 0.0) { + specular = eaglercraftIBL_Specular(diffuseColor3f.rgb, envMapSample4f.rgb, viewDir3f, normalVector3f, materialData4f.rgb); + specular *= 1.0 - sqrt(posDst) * 0.2; + } + break; + } +#endif + +#ifdef COMPILE_SCREEN_SPACE_REFLECTIONS +#ifndef COMPILE_ENV_MAP_REFLECTIONS + float f = materialData4f.g < 0.06 ? 1.0 : 0.0; + f += materialData4f.r < 0.5 ? 1.0 : 0.0; + if(f == 0.0) { +#else + if((materialData4f.a < 0.5 ? f : -1.0) == 0.0) { +#endif + vec4 ssrSample = textureLod(u_ssrReflectionTexture, min(v_position2f * u_halfResolutionPixelAlignment2f, 1.0), 0.0); + if(ssrSample.g > 0.0) { + ssrSample.g -= 0.005; + vec4 worldPosition4f = vec4(v_position2f, depth, 1.0) * 2.0 - 1.0; + worldPosition4f = u_inverseProjMatrix4f * worldPosition4f; + worldPosition4f = u_inverseViewMatrix4f * vec4(worldPosition4f.xyz / worldPosition4f.w, 0.0); + vec3 viewDir3f = normalize(worldPosition4f.xyz); // need confirmation this should be negative + specular = eaglercraftIBL_Specular(diffuseColor3f.rgb, ssrSample.rgb, viewDir3f, normalVector3f.xyz, materialData4f.rgb); + } + } +#endif + + output4f = vec4((diffuseColor3f.rgb * max(skyLight + blockLight, vec3(emissive * emissive * 20.0 + 0.075)) + specular * 8.0) * shadow, 1.0); + +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_core.vsh b/sources/resources/assets/eagler/glsl/deferred/deferred_core.vsh new file mode 100644 index 0000000..2c55f01 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_core.vsh @@ -0,0 +1,114 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 a_texture2f; +out vec2 v_texture2f; +uniform mat4 u_textureMat4f01; +#endif + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 a_color4f; +out vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +out vec3 v_normal3f; +out float v_block1f; +#endif + +#ifdef COMPILE_STATE_WAVING_BLOCKS +uniform mat4 u_modelMatrix4f; +uniform mat4 u_viewMatrix4f; +uniform vec3 u_wavingBlockOffset3f; +uniform vec4 u_wavingBlockParam4f; +#ifndef COMPILE_NORMAL_ATTRIB +uniform float u_blockConstant1f; +#endif +#define DO_COMPILE_STATE_WAVING_BLOCKS +#define FAKE_SIN(valueIn, valueOut)\ + valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ + valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; +#define LIB_INCLUDE_WAVING_BLOCKS_FUNCTION +#endif + +#EAGLER INCLUDE (2) "eagler:glsl/deferred/lib/waving_blocks.glsl" + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE +out vec3 v_viewdir3f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +out vec2 v_lightmap2f; +uniform mat4 u_textureMat4f02; +#endif + +uniform mat4 u_modelviewMat4f; +uniform mat4 u_projectionMat4f; + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { + +#ifdef COMPILE_TEXTURE_ATTRIB + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; +#endif + +#ifdef COMPILE_COLOR_ATTRIB + v_color4f = a_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); + float blockId = v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; +#endif + + vec4 pos = vec4(a_position3f, 1.0); + +#ifdef DO_COMPILE_STATE_WAVING_BLOCKS +#ifndef COMPILE_NORMAL_ATTRIB + float blockId = u_blockConstant1f; +#endif +#ifdef COMPILE_LIGHTMAP_ATTRIB + if(v_lightmap2f.y > 0.33) { + COMPUTE_WAVING_BLOCKS(pos, min(v_lightmap2f.y * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + }else { + pos = u_modelviewMat4f * pos; + } +#else + COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) +#endif +#else + pos = u_modelviewMat4f * pos; +#endif + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE + v_viewdir3f = pos.xyz / pos.w; +#endif + + gl_Position = u_projectionMat4f * pos; + +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_core_gbuffer.fsh b/sources/resources/assets/eagler/glsl/deferred/deferred_core_gbuffer.fsh new file mode 100644 index 0000000..0eb9113 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_core_gbuffer.fsh @@ -0,0 +1,166 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 v_texture2f; +#endif + +uniform vec4 u_color4f; + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec3 v_normal3f; +in float v_block1f; +#else +uniform vec3 u_uniformNormal3f; +uniform float u_blockConstant1f; +#endif + +uniform float u_useEnvMap1f; + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 v_lightmap2f; +#endif + +#ifdef COMPILE_ENABLE_TEXTURE2D +uniform sampler2D u_samplerTexture; +#ifndef COMPILE_TEXTURE_ATTRIB +uniform vec2 u_textureCoords01; +#endif +#endif + +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifndef COMPILE_LIGHTMAP_ATTRIB +uniform vec2 u_textureCoords02; +#endif +#endif + +#ifdef COMPILE_ENABLE_ALPHA_TEST +uniform float u_alphaTestRef1f; +#endif + +#ifdef COMPILE_ENABLE_ANISOTROPIC_FIX +uniform vec2 u_textureAnisotropicFix; +#endif + +#ifdef COMPILE_BLEND_ADD +uniform vec4 u_colorBlendSrc4f; +uniform vec4 u_colorBlendAdd4f; +#endif + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE +uniform sampler2D u_samplerNormalMaterial; +in vec3 v_viewdir3f; +#ifndef COMPILE_TEXTURE_ATTRIB +uniform vec2 u_textureCoords01; +#endif +#else +uniform vec3 u_materialConstants3f; +#endif + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE +mat3 cotangent_frame(in vec3 N, in vec3 p, in vec2 uv) { + vec3 dp1 = dFdx(p); + vec3 dp2 = dFdy(p); + vec2 duv1 = dFdx(uv); + vec2 duv2 = dFdy(uv); + vec3 dp2perp = cross(dp2, N); + vec3 dp1perp = cross(N, dp1); + vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; + vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; + float invmax = inversesqrt(max(dot(T,T), dot(B,B))); + return mat3(T * invmax, B * invmax, N); +} +#endif + +layout(location = 0) out vec4 gbufferColor4f; +layout(location = 1) out vec4 gbufferNormal4f; +layout(location = 2) out vec4 gbufferMaterial4f; + +void main() { +#ifdef COMPILE_COLOR_ATTRIB + vec4 color = v_color4f * u_color4f; +#else + vec4 color = u_color4f; +#endif + + vec3 normal; +#ifdef COMPILE_NORMAL_ATTRIB + normal = normalize(v_normal3f); +#else + normal = u_uniformNormal3f; +#endif + +#if defined(COMPILE_ENABLE_TEXTURE2D) || defined(COMPILE_NORMAL_MATERIAL_TEXTURE) + vec2 uv; +#ifdef COMPILE_TEXTURE_ATTRIB +#ifdef COMPILE_ENABLE_ANISOTROPIC_FIX + uv = floor(uv * u_textureAnisotropicFix) + 0.5; + uv /= u_textureAnisotropicFix; +#else + uv = v_texture2f; +#endif +#else + uv = u_textureCoords01; +#endif +#ifdef COMPILE_ENABLE_TEXTURE2D + color *= texture(u_samplerTexture, uv); +#endif +#endif + + vec2 lightmap = vec2(0.0, 1.0); + +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB + lightmap = v_lightmap2f; +#else + lightmap = u_textureCoords02; +#endif +#endif + +#ifdef COMPILE_BLEND_ADD + color = color * u_colorBlendSrc4f + u_colorBlendAdd4f; +#endif + +#ifdef COMPILE_ENABLE_ALPHA_TEST + if(color.a < u_alphaTestRef1f) discard; +#endif + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE + vec2 uv2 = vec2(1.0, 0.5) * uv; + vec2 normal2 = texture(u_samplerNormalMaterial, uv2).xy; + mat3 cf; + if(normal2.x + normal2.y > 0.0) { + normal2 *= 2.0; + normal2 -= 1.0; + cf = cotangent_frame(normal, normalize(v_viewdir3f), uv); + normal = cf * vec3(normal2, sqrt(1.0 - dot(normal2, normal2))); + } + uv2.y += 0.5; + vec3 material = texture(u_samplerNormalMaterial, uv2).rgb; +#else + vec3 material = u_materialConstants3f; +#endif + + gbufferColor4f.rgb = color.rgb; + gbufferColor4f.a = lightmap.r; + gbufferNormal4f.rgb = normal * 0.5 + 0.5; + gbufferNormal4f.a = lightmap.g; + gbufferMaterial4f = vec4(material.rgb, u_useEnvMap1f); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_fog.fsh b/sources/resources/assets/eagler/glsl/deferred/deferred_fog.fsh new file mode 100644 index 0000000..5de9250 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_fog.fsh @@ -0,0 +1,101 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) out vec4 output4f; + +in vec2 v_position2f; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_fogDepthTexture; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +uniform sampler2D u_lightShaftsTexture; +#endif + +#ifdef COMPILE_FOG_ATMOSPHERE +uniform sampler2D u_environmentMap; +uniform vec3 u_sunColorAdd3f; +#endif + +uniform mat4 u_inverseViewProjMatrix4f; + +#ifdef COMPILE_FOG_LINEAR +uniform vec2 u_linearFogParam2f; +#else +uniform float u_expFogDensity1f; +#endif + +uniform vec4 u_fogColorLight4f; +uniform vec4 u_fogColorDark4f; + +void main() { + vec4 fragPos4f = vec4(v_position2f, textureLod(u_fogDepthTexture, v_position2f, 0.0).r, 1.0); + +#ifdef COMPILE_FOG_ATMOSPHERE + if(fragPos4f.z <= 0.0000001) { + discard; + } +#endif + + float solidDepth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + if(solidDepth != fragPos4f.z) { + discard; + } + + fragPos4f.xyz *= 2.0; + fragPos4f.xyz -= 1.0; + + fragPos4f = u_inverseViewProjMatrix4f * fragPos4f; + fragPos4f.xyz /= fragPos4f.w; + fragPos4f.w = 1.0; + + float l = sqrt(dot(fragPos4f.xyz, fragPos4f.xyz)); +#ifdef COMPILE_FOG_LINEAR + float f = (l - u_linearFogParam2f.x) / (u_linearFogParam2f.y - u_linearFogParam2f.x); +#else + float f = 1.0 - exp(-u_expFogDensity1f * l); +#endif + float f2 = textureLod(u_gbufferNormalTexture, v_position2f, 0.0).a; + vec4 fogColor4f = mix(u_fogColorDark4f, u_fogColorLight4f, f2 * f2); + f = clamp(f, 0.0, 1.0) * fogColor4f.a; + +#ifdef COMPILE_FOG_ATMOSPHERE + fragPos4f.xyz /= -l; + fragPos4f.xz /= abs(fragPos4f.y) + 1.0; + fragPos4f.xz *= 0.75; + + vec3 envMapSample3f; + + fragPos4f.xz *= vec2(-0.5, -0.25); + fragPos4f.xz += vec2(0.5, 0.25); + envMapSample3f = textureLod(u_environmentMap, fragPos4f.xz, 0.0).rgb + u_sunColorAdd3f; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS + envMapSample3f *= pow(textureLod(u_lightShaftsTexture, v_position2f, 0.0).r * 0.9 + 0.1, 2.25); + f = f * 0.9 + 0.1; +#endif + + output4f = vec4(envMapSample3f * fogColor4f.rgb, f); +#else + output4f = vec4(fogColor4f.rgb, f); +#endif + +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_local.vsh b/sources/resources/assets/eagler/glsl/deferred/deferred_local.vsh new file mode 100644 index 0000000..5eb264a --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_local.vsh @@ -0,0 +1,28 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec2 a_position2f; + +out vec2 v_position2f; + +void main() { + v_position2f = a_position2f * 0.5 + 0.5; + gl_Position = vec4(a_position2f, 0.0, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.fsh b/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.fsh new file mode 100644 index 0000000..bcebefb --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.fsh @@ -0,0 +1,59 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +#if !defined(COMPILE_ENABLE_ALPHA_TEST) && !defined(COMPILE_COLORED_SHADOWS) +#undef COMPILE_ENABLE_TEXTURE2D +#endif + +#ifdef COMPILE_COLORED_SHADOWS +layout(location = 0) out vec4 output4f; +uniform vec4 u_color4f; +#endif + +#ifdef COMPILE_ENABLE_TEXTURE2D +uniform sampler2D u_samplerTexture; +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 v_texture2f; +#else +uniform vec2 u_textureCoords01; +#endif +#ifdef COMPILE_ENABLE_ALPHA_TEST +uniform float u_alphaTestRef1f; +#endif +#endif + +void main() { +#ifdef COMPILE_COLORED_SHADOWS + vec4 color = u_color4f; +#else + vec4 color = vec4(1.0); +#endif + +#ifdef COMPILE_ENABLE_TEXTURE2D +#ifdef COMPILE_TEXTURE_ATTRIB + color *= texture(u_samplerTexture, v_texture2f); +#else + color *= texture(u_samplerTexture, u_textureCoords01); +#endif +#ifdef COMPILE_ENABLE_ALPHA_TEST + if(color.a < u_alphaTestRef1f) discard; +#endif +#endif + +#ifdef COMPILE_COLORED_SHADOWS + output4f = vec4(mix(vec3(1.0), color.rgb, color.a), color.a); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh b/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh new file mode 100644 index 0000000..e44f3f4 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh @@ -0,0 +1,101 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +#if defined(COMPILE_ENABLE_ALPHA_TEST) && defined(COMPILE_ENABLE_TEXTURE2D) +#define DO_SHADOW_ALPHA_TEST +#endif + +#ifdef DO_SHADOW_ALPHA_TEST +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 a_texture2f; +out vec2 v_texture2f; +uniform mat4 u_textureMat4f01; +#endif +#endif + +uniform mat4 u_modelviewProjMat4f; + +#ifdef COMPILE_STATE_WAVING_BLOCKS +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +#else +uniform float u_blockConstant1f; +#endif +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +uniform mat4 u_textureMat4f02; +#else +uniform vec2 u_textureCoords02; +#endif +#endif +uniform mat4 u_modelMatrix4f; +uniform mat4 u_viewMatrix4f; +uniform vec3 u_wavingBlockOffset3f; +uniform vec4 u_wavingBlockParam4f; +#define DO_COMPILE_STATE_WAVING_BLOCKS +#define FAKE_SIN(valueIn, valueOut)\ + valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ + valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; +#define LIB_INCLUDE_WAVING_BLOCKS_FUNCTION +#endif + +#EAGLER INCLUDE (2) "eagler:glsl/deferred/lib/waving_blocks.glsl" + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { +#ifdef DO_SHADOW_ALPHA_TEST +#ifdef COMPILE_TEXTURE_ATTRIB + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; +#endif +#endif +#ifdef DO_COMPILE_STATE_WAVING_BLOCKS + vec4 pos = vec4(a_position3f, 1.0); +#ifdef COMPILE_NORMAL_ATTRIB + float blockId = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); +#else + float blockId = u_blockConstant1f; +#endif +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB + mat4x2 texMat4x2 = mat4x2( + u_textureMat4f02[0].yw, + u_textureMat4f02[1].yw, + u_textureMat4f02[2].yw, + u_textureMat4f02[3].yw + ); + vec2 v_lightmapTmp2f = texMat4x2 * vec4(a_lightmap2f, 0.0, 1.0); + v_lightmapTmp2f.x = v_lightmapTmp2f.x / v_lightmapTmp2f.y; +#else + vec2 v_lightmapTmp2f = vec2(u_textureCoords02.y, 0.0); +#endif + if(v_lightmapTmp2f.x > 0.33) { + COMPUTE_WAVING_BLOCKS(pos, min(v_lightmapTmp2f.x * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + }else { + pos = u_modelviewProjMat4f * pos; + } +#else + COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) +#endif + gl_Position = pos; +#else + gl_Position = u_modelviewProjMat4f * vec4(a_position3f, 1.0); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/dither16.bmp b/sources/resources/assets/eagler/glsl/deferred/dither16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..57813a0eac518617529b20819770b2de50e9e4b2 GIT binary patch literal 256 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

9l6`#^^@lh|h~e^7^sA#bs^^IY$u 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

(+==jz`kMw^zvu$ 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%0ASbMRrLZ*Y=nY6pv`ed1-!{&!86q(O8^YJGa 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 literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/emissive_items.csv b/sources/resources/assets/eagler/glsl/deferred/emissive_items.csv new file mode 100644 index 0000000..6056c8b --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/emissive_items.csv @@ -0,0 +1,9 @@ +item,damage,red,green,blue,intensity +minecraft:beacon,0,0.4493,0.6007,1.0000,500.0 +minecraft:glowstone,0,1.0000,0.6636,0.3583,10.0 +minecraft:lit_pumpkin,0,1.0000,0.5447,0.2005,10.0 +minecraft:torch,0,1.0000,0.5983,0.2655,10.0 +minecraft:redstone_torch,0,1.0000,0.1578,0.0000,4.0 +minecraft:sea_lantern,0,0.5530,0.6468,1.0000,10.0, +minecraft:lava_bucket,0,1.0000,0.4461,0.1054,6.0, +minecraft:nether_star,0,0.5711,0.6611,1.0000,6.0 \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/forward_core.fsh b/sources/resources/assets/eagler/glsl/deferred/forward_core.fsh new file mode 100644 index 0000000..107648f --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/forward_core.fsh @@ -0,0 +1,471 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision highp sampler2DShadow; + +in vec4 v_position4f; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +in vec2 v_positionClip2f; +#endif + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 v_texture2f; +#endif + +uniform vec4 u_color4f; + +#ifdef COMPILE_BLEND_ADD +uniform vec4 u_colorBlendSrc4f; +uniform vec4 u_colorBlendAdd4f; +#endif + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec3 v_normal3f; +in float v_block1f; +#else +uniform vec3 u_uniformNormal3f; +uniform float u_blockConstant1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 v_lightmap2f; +#else +uniform vec2 u_textureCoords02; +#endif + +#ifdef COMPILE_ENABLE_TEXTURE2D +uniform sampler2D u_samplerTexture; +#ifndef COMPILE_TEXTURE_ATTRIB +uniform vec2 u_textureCoords01; +#endif +#else +#undef COMPILE_NORMAL_MATERIAL_TEXTURE +#endif + +#ifdef COMPILE_ENABLE_TEX_GEN +in vec3 v_objectPosition3f; +uniform ivec4 u_texGenPlane4i; +uniform vec4 u_texGenS4f; +uniform vec4 u_texGenT4f; +uniform vec4 u_texGenR4f; +uniform vec4 u_texGenQ4f; +uniform mat4 u_textureMat4f01; +#endif + +#ifdef COMPILE_ENABLE_ALPHA_TEST +uniform float u_alphaTestRef1f; +#endif + +#ifdef COMPILE_ENABLE_ANISOTROPIC_FIX +uniform vec2 u_textureAnisotropicFix; +#endif + +uniform mat4 u_inverseViewMatrix4f; + +layout(location = 0) out vec4 output4f; + +#ifdef COMPILE_DYNAMIC_LIGHTS +struct DynamicLight { + mediump vec4 u_lightPosition4f; + mediump vec4 u_lightColor4f; +}; +layout(std140) uniform u_chunkLightingData { + mediump int u_dynamicLightCount1i; + mediump int _paddingA_; + mediump int _paddingB_; + mediump int _paddingC_; + DynamicLight u_dynamicLightArray[12]; +}; +#endif + +layout(std140) uniform u_worldLightingData { + mediump vec4 u_sunDirection4f; + mediump vec4 u_sunColor3f_sky1f; + mediump vec4 u_fogParameters4f; + mediump vec4 u_fogColorLight4f; + mediump vec4 u_fogColorDark4f; + mediump vec4 u_fogColorAddSun4f; + mediump vec4 u_blockSkySunDynamicLightFac4f; +#ifdef COMPILE_SUN_SHADOW_LOD0 + mediump mat4 u_sunShadowMatrixLOD04f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; + mediump mat4 u_sunShadowMatrixLOD24f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif +}; + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE +uniform sampler2D u_samplerNormalMaterial; +#else +uniform vec3 u_materialConstants3f; +#endif + +uniform sampler2D u_metalsLUT; + +#define LIB_INCLUDE_PBR_LIGHTING_FUNCTION +#define LIB_INCLUDE_PBR_LIGHTING_PREFETCH +#EAGLER INCLUDE (3) "eagler:glsl/deferred/lib/pbr_lighting.glsl" + +#ifdef COMPILE_PARABOLOID +#undef COMPILE_SUN_SHADOW_SMOOTH +#undef COMPILE_SUN_SHADOW_LOD1 +#undef COMPILE_SUN_SHADOW_LOD2 +#endif + +#ifdef COMPILE_PARABOLOID_ENV_MAP +uniform sampler2D u_environmentMap; +uniform sampler2D u_brdfLUT; +#define LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING_SPECULAR +#define LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING_PREFETCH +#endif + +uniform sampler2D u_irradianceMap; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +uniform sampler2D u_lightShaftsTexture; +#endif + +#EAGLER INCLUDE (4) "eagler:glsl/deferred/lib/pbr_env_map.glsl" + +#ifdef DO_COMPILE_SUN_SHADOWS +uniform sampler2DShadow u_sunShadowDepthTexture; +#ifdef COMPILE_SUN_SHADOW_SMOOTH +const vec2 POISSON_DISK[7] = vec2[]( +vec2(-0.077, 0.995), vec2(0.998, 0.015), +vec2(-0.116, -0.987), vec2(-0.916, 0.359), +vec2(-0.697, -0.511), vec2(0.740, -0.612), +vec2(0.675, 0.682)); +#define SMOOTH_SHADOW_SAMPLES 1.0 / 8.0 +#define SMOOTH_SHADOW_RADIUS 0.00075 +#define SMOOTH_SHADOW_POISSON_SAMPLE(idx, tex, lod, vec3Pos, accum, tmpVec2)\ + tmpVec2 = vec3Pos.xy + POISSON_DISK[idx] * SMOOTH_SHADOW_RADIUS;\ + tmpVec2 = clamp(tmpVec2, vec2(0.001), vec2(0.999));\ + tmpVec2.y += lod;\ + tmpVec2.y *= SUN_SHADOW_MAP_FRAC;\ + accum += textureLod(tex, vec3(tmpVec2, vec3Pos.z), 0.0) * SMOOTH_SHADOW_SAMPLES; +#endif +#endif + +void main() { + vec4 worldPosition4f; + vec4 worldDirection4f; + vec4 diffuseColor4f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + vec3 materialData3f; + float block1f; + + // =========== RESOLVE CONSTANTS ============ // + + worldPosition4f = u_inverseViewMatrix4f * v_position4f; + worldPosition4f.xyz /= worldPosition4f.w; + worldPosition4f.w = 1.0; + worldDirection4f = u_inverseViewMatrix4f * vec4(v_position4f.xyz / v_position4f.w, 0.0); + worldDirection4f.xyz = normalize(worldDirection4f.xyz); + +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB + lightmapCoords2f = v_lightmap2f; +#else + lightmapCoords2f = u_textureCoords02; +#endif +#else + lightmapCoords2f = vec2(0.0, 1.0); +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + normalVector3f = normalize(v_normal3f); + block1f = v_block1f; +#else + normalVector3f = u_uniformNormal3f; + block1f = u_blockConstant1f; +#endif + + normalVector3f = normalize(mat3(u_inverseViewMatrix4f) * normalVector3f); + + // ========= CALCULATE DIFFUSE COLOR ========== // + +#ifdef COMPILE_COLOR_ATTRIB + diffuseColor4f = v_color4f * u_color4f; +#else + diffuseColor4f = u_color4f; +#endif + +#ifdef COMPILE_ENABLE_TEXTURE2D + vec2 texCoords2f; +#ifdef COMPILE_ENABLE_TEX_GEN + vec4 texGenVector; + vec4 texGenPosSrc[2]; + texGenPosSrc[0] = vec4(v_objectPosition3f, 1.0); + texGenPosSrc[1] = v_position4f; + texGenVector.x = dot(texGenPosSrc[u_texGenPlane4i.x], u_texGenS4f); + texGenVector.y = dot(texGenPosSrc[u_texGenPlane4i.y], u_texGenT4f); + texGenVector.z = dot(texGenPosSrc[u_texGenPlane4i.z], u_texGenR4f); + texGenVector.w = dot(texGenPosSrc[u_texGenPlane4i.w], u_texGenQ4f); + texGenVector = vec4(mat4x3( + u_textureMat4f01[0].xyw, + u_textureMat4f01[1].xyw, + u_textureMat4f01[2].xyw, + u_textureMat4f01[3].xyw + ) * texGenVector, 0.0); + texCoords2f = texGenVector.xy / texGenVector.z; +#else + +#ifdef COMPILE_TEXTURE_ATTRIB +#ifdef COMPILE_ENABLE_ANISOTROPIC_FIX + texCoords2f = floor(v_texture2f * u_textureAnisotropicFix) + 0.5; + texCoords2f /= u_textureAnisotropicFix; +#else + texCoords2f = v_texture2f; +#endif +#else + texCoords2f = u_textureCoords01; +#endif +#endif + diffuseColor4f *= texture(u_samplerTexture, texCoords2f); +#endif + +#ifdef COMPILE_BLEND_ADD + diffuseColor4f = diffuseColor4f * u_colorBlendSrc4f + u_colorBlendAdd4f; +#endif + + // ============= ALPHA TEST ============== // + +#ifdef COMPILE_ENABLE_ALPHA_TEST + if(diffuseColor4f.a < u_alphaTestRef1f) discard; +#endif + + // ========== RESOLVE MATERIALS =========== // + +#ifdef COMPILE_NORMAL_MATERIAL_TEXTURE + vec2 uv2 = vec2(1.0, 0.5) * texCoords2f; + uv2.y += 0.5; + materialData3f = texture(u_samplerNormalMaterial, uv2).rgb; +#else + materialData3f = u_materialConstants3f; +#endif + + vec3 metalN, metalK; + PREFETCH_METALS(diffuseColor4f.rgb, materialData3f.g, metalN, metalK) + + // ============ SUN LIGHTING ============== // + + diffuseColor4f.rgb *= diffuseColor4f.rgb; + + vec3 lightColor3f = vec3(0.0); + if(dot(u_sunDirection4f.xyz, normalVector3f) > 0.0 && lightmapCoords2f.g > 0.5 && + (u_sunColor3f_sky1f.r + u_sunColor3f_sky1f.g + u_sunColor3f_sky1f.b) > 0.001) { +#ifdef DO_COMPILE_SUN_SHADOWS + + // ========== SUN SHADOW: LOD0 ============ // + + float skyLight = max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); + float shadowSample = 1.0; + vec4 shadowWorldPos4f = worldPosition4f; + shadowWorldPos4f.xyz += normalVector3f * 0.05; + + vec4 shadowTexPos4f; + vec2 tmpVec2; + for(;;) { + shadowTexPos4f = u_sunShadowMatrixLOD04f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy * vec2(1.0, SUN_SHADOW_MAP_FRAC), shadowTexPos4f.z), 0.0); +#ifdef COMPILE_SUN_SHADOW_SMOOTH + shadowSample *= SMOOTH_SHADOW_SAMPLES; + SMOOTH_SHADOW_POISSON_SAMPLE(0, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(1, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(2, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(3, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(4, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(5, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(6, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + shadowSample = max(shadowSample * 2.0 - 1.0, 0.0); +#endif + break; + } + +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowTexPos4f = u_sunShadowMatrixLOD14f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 1.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowTexPos4f = u_sunShadowMatrixLOD24f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 2.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + } +#endif + break; + } +#endif + lightColor3f = u_sunColor3f_sky1f.rgb * max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); +#ifdef DO_COMPILE_SUN_SHADOWS + lightColor3f *= shadowSample * skyLight; +#endif + lightColor3f = eaglercraftLighting(diffuseColor4f.rgb, lightColor3f, -worldDirection4f.xyz, u_sunDirection4f.xyz, normalVector3f, materialData3f, metalN, metalK) * u_blockSkySunDynamicLightFac4f.z; + } + + float f; +#ifdef COMPILE_PARABOLOID_ENV_MAP + + // =========== ENVIRONMENT MAP =========== // + + f = materialData3f.g < 0.06 ? 1.0 : 0.0; + f += materialData3f.r < 0.5 ? 1.0 : 0.0; + while(f == 0.0) { + float dst2 = dot(worldPosition4f.xyz, worldPosition4f.xyz); + if(dst2 > 16.0) { + break; + } + vec3 reflectDir = reflect(worldDirection4f.xyz, normalVector3f); + reflectDir.xz /= abs(reflectDir.y) + 1.0; + float dst = 1.0 - dot(reflectDir.xz, reflectDir.xz); + dst *= dst; + reflectDir.xz = reflectDir.xz * 0.975; + vec4 envMapSample4f; + if(dst < 0.005) { + vec4 sample1 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + envMapSample4f = vec4(mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, reflectDir.y * -12.5 + 0.5)).rgb, min(sample1.a, sample2.a)); + }else { + reflectDir.xz = reflectDir.xz * vec2(0.5, reflectDir.y > 0.0 ? 0.25 : -0.25); + reflectDir.xz += vec2(0.5, reflectDir.y > 0.0 ? 0.25 : 0.75); + envMapSample4f = textureLod(u_environmentMap, reflectDir.xz, 0.0); + } + if(envMapSample4f.a > 0.0) { + lightColor3f += eaglercraftIBL_Specular(diffuseColor4f.rgb, envMapSample4f.rgb, worldDirection4f.xyz, normalVector3f, materialData3f, metalN, metalK) * (1.0 - sqrt(dst2) * 0.25); + } + break; + } + +#endif + + // =========== IRRADIANCE MAP =========== // + + lightmapCoords2f *= lightmapCoords2f; + + vec3 irradianceMapSamplePos2f = normalVector3f; + irradianceMapSamplePos2f.xz /= abs(irradianceMapSamplePos2f.y) + 1.0; + float dst = 1.0 - dot(irradianceMapSamplePos2f.xz, irradianceMapSamplePos2f.xz); + dst *= dst; + irradianceMapSamplePos2f.xz *= 0.975; + vec3 skyLight = vec3(sqrt(0.01 + max(u_sunDirection4f.w, 0.0))); + if(dst < 0.005) { + vec4 sample1 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + skyLight += mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, irradianceMapSamplePos2f.y * -12.5 + 0.5)).rgb; + }else { + irradianceMapSamplePos2f.xz *= vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : -0.25); + irradianceMapSamplePos2f.xz += vec2(0.5, irradianceMapSamplePos2f.y > 0.0 ? 0.25 : 0.75); + skyLight += textureLod(u_irradianceMap, irradianceMapSamplePos2f.xz, 0.0).rgb; + } + skyLight *= lightmapCoords2f.g * u_sunColor3f_sky1f.w; + +#ifdef COMPILE_DYNAMIC_LIGHTS + + // =========== DYNAMIC LIGHTING =========== // + + vec3 dlightDist3f, dlightDir3f, dlightColor3f; + int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i; // hate this + for(int i = 0; i < safeLightCount; ++i) { + dlightDist3f = worldPosition4f.xyz - u_dynamicLightArray[i].u_lightPosition4f.xyz; + dlightDir3f = normalize(dlightDist3f); + dlightDir3f = materialData3f.b == 1.0 ? normalVector3f : -dlightDir3f; + if(dot(dlightDir3f, normalVector3f) <= 0.0) { + continue; + } + dlightColor3f = u_dynamicLightArray[i].u_lightColor4f.rgb / dot(dlightDist3f, dlightDist3f); + if(dlightColor3f.r + dlightColor3f.g + dlightColor3f.b < 0.025) { + continue; + } + lightColor3f += eaglercraftLighting(diffuseColor4f.rgb, dlightColor3f, -worldDirection4f.xyz, dlightDir3f, normalVector3f, materialData3f, metalN, metalK) * u_blockSkySunDynamicLightFac4f.w; + } + +#endif + + // ============ CACLULATE FOG ============= // + + vec4 fogBlend4f = vec4(0.0); +#ifndef COMPILE_ENABLE_TEX_GEN + while(u_fogParameters4f.x > 0.0) { + float atmos = u_fogParameters4f.x >= 4.0 ? 4.0 : 0.0; + float type = u_fogParameters4f.x - atmos; + fogBlend4f = mix(u_fogColorLight4f, u_fogColorDark4f, lightmapCoords2f.g); + + float l = sqrt(dot(v_position4f.xyz, v_position4f.xyz)); + if(type == 1.0) { + f = (l - u_fogParameters4f.z) / (u_fogParameters4f.w - u_fogParameters4f.z); + }else { + f = 1.0 - exp(-u_fogParameters4f.y * l); + } + + fogBlend4f.a *= clamp(f, 0.0, 1.0); + + if(atmos == 0.0) { + break; + } + + vec3 atmosSamplePos = v_position4f.xyz / -l; + atmosSamplePos.xz /= abs(atmosSamplePos.y) + 1.0; + atmosSamplePos.xz *= vec2(-0.5, -0.25) * 0.75; + atmosSamplePos.xz += vec2(0.5, 0.25); + + fogBlend4f.rgb *= textureLod(u_irradianceMap, atmosSamplePos.xz, 0.0).rgb; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS + fogBlend4f.rgb *= pow(textureLod(u_lightShaftsTexture, v_positionClip2f * 0.5 + 0.5, 0.0).r * 0.9 + 0.1, 2.25); + fogBlend4f.a = fogBlend4f.a * 0.9 + 0.1; +#endif + break; + } +#endif + + // ============ OUTPUT COLOR ============== // + + vec3 blockLight = lightmapCoords2f.r * vec3(1.0, 0.5809, 0.2433) * 2.0 * u_blockSkySunDynamicLightFac4f.x; + skyLight *= u_blockSkySunDynamicLightFac4f.y; + float emissive = materialData3f.b == 1.0 ? 0.0 : materialData3f.b; + diffuseColor4f.rgb *= max(skyLight + blockLight, vec3(emissive * emissive * 20.0 + 0.075)) * 0.075; + diffuseColor4f.rgb += lightColor3f; + + diffuseColor4f.rgb = mix(diffuseColor4f.rgb, fogBlend4f.rgb, fogBlend4f.a); + + output4f = vec4(diffuseColor4f.rgb * diffuseColor4f.a, diffuseColor4f.a); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/forward_core.vsh b/sources/resources/assets/eagler/glsl/deferred/forward_core.vsh new file mode 100644 index 0000000..0ce8b14 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/forward_core.vsh @@ -0,0 +1,101 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +out vec4 v_position4f; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +out vec2 v_positionClip2f; +#endif + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 a_texture2f; +out vec2 v_texture2f; +uniform mat4 u_textureMat4f01; +#endif + +#ifdef COMPILE_ENABLE_TEX_GEN +out vec3 v_objectPosition3f; +#endif + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 a_color4f; +out vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +out vec3 v_normal3f; +out float v_block1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +out vec2 v_lightmap2f; +uniform mat4 u_textureMat4f02; +#endif + +uniform mat4 u_modelviewMat4f; + +#ifdef COMPILE_PARABOLOID +uniform float u_farPlane1f; +#else +uniform mat4 u_projectionMat4f; +#endif + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { +#ifdef COMPILE_ENABLE_TEX_GEN + v_objectPosition3f = a_position3f; +#endif + v_position4f = u_modelviewMat4f * vec4(a_position3f, 1.0); + +#ifdef COMPILE_TEXTURE_ATTRIB + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; +#endif + +#ifdef COMPILE_COLOR_ATTRIB + v_color4f = a_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); + v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; +#endif + +#ifdef COMPILE_PARABOLOID + vec3 pos = v_position4f.xyz / v_position4f.w; + float dist = pos.z; + pos.xyz = normalize(pos.xyz); + pos.xy /= 1.0 - pos.z; + pos.z = dist / u_farPlane1f + 1.00005; + gl_Position = vec4(pos.xyz, 1.0); +#else + gl_Position = u_projectionMat4f * v_position4f; +#endif + +#ifdef COMPILE_FOG_LIGHT_SHAFTS + v_positionClip2f = gl_Position.xy / gl_Position.w; +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.fsh b/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.fsh new file mode 100644 index 0000000..25a55c1 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.fsh @@ -0,0 +1,306 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision highp sampler2DShadow; + +in vec4 v_position4f; + +uniform vec4 u_color4f; + +#ifdef COMPILE_NORMAL_ATTRIB +in vec3 v_normal3f; +in float v_block1f; +#else +uniform vec3 u_uniformNormal3f; +uniform float u_blockConstant1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 v_lightmap2f; +#else +uniform vec2 u_textureCoords02; +#endif + +uniform mat4 u_inverseViewMatrix4f; + +layout(location = 0) out vec4 output4f; + +#ifdef COMPILE_DYNAMIC_LIGHTS +struct DynamicLight { + mediump vec4 u_lightPosition4f; + mediump vec4 u_lightColor4f; +}; +layout(std140) uniform u_chunkLightingData { + mediump int u_dynamicLightCount1i; + mediump int _paddingA_; + mediump int _paddingB_; + mediump int _paddingC_; + DynamicLight u_dynamicLightArray[12]; +}; +#endif + +layout(std140) uniform u_worldLightingData { + mediump vec4 u_sunDirection4f; + mediump vec4 u_sunColor3f_sky1f; + mediump vec4 u_fogParameters4f; + mediump vec4 u_fogColorLight4f; + mediump vec4 u_fogColorDark4f; + mediump vec4 u_fogColorAddSun4f; + mediump vec4 u_blockSkySunDynamicLightFac4f; +#ifdef COMPILE_SUN_SHADOW_LOD0 + mediump mat4 u_sunShadowMatrixLOD04f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; + mediump mat4 u_sunShadowMatrixLOD24f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif +}; + +uniform sampler2D u_environmentMap; +uniform sampler2D u_brdfLUT; + +#define GLASS_ROUGHNESS 0.15 +#define GLASS_F0 0.4 + +vec3 eaglercraftLighting_Glass(in vec3 radiance, in vec3 viewDir, in vec3 lightDir, in vec3 normalVec) { + float roughness = 1.0 - GLASS_ROUGHNESS * 0.85; + vec3 H = normalize(viewDir + lightDir); + vec3 NdotHVL = max(normalVec * mat3(H, viewDir, lightDir), vec3(0.0)); + float NDF = (GLASS_ROUGHNESS * GLASS_ROUGHNESS * GLASS_ROUGHNESS * GLASS_ROUGHNESS); + float denom = NdotHVL.x * NdotHVL.x * (NDF - 1.0) + 1.0; + NDF /= denom * denom * 3.141592; + float gs = GLASS_ROUGHNESS + 1.0; + gs *= gs * 0.125; + vec2 Ndot = NdotHVL.yz; + Ndot /= Ndot * (1.0 - gs) + gs; + NDF *= Ndot.x * Ndot.y; + float fresnel = pow(max(1.0 - NdotHVL.x, 0.0), 5.0); + vec3 F = vec3(GLASS_F0 + (1.0 - GLASS_F0) * fresnel); + denom = 4.0 * NdotHVL.y * NdotHVL.z + 0.0001; + return (NDF * F / denom) * radiance * NdotHVL.z; +} + +vec3 eaglercraftIBL_Specular_Glass(in vec3 envMapSample, in vec3 viewDir, in vec3 normalVec) { + float NdotV = dot(normalVec, -viewDir); + float fresnel = pow(max(1.0 - NdotV, 0.0), 5.0); + vec3 F = vec3(GLASS_F0 + (max(1.0 - GLASS_ROUGHNESS, GLASS_F0) - GLASS_F0) * fresnel); + vec2 brdf2f = vec2(max(NdotV, 0.0), GLASS_ROUGHNESS); + brdf2f = 1.0 - brdf2f; + brdf2f *= brdf2f; + brdf2f = 1.0 - brdf2f; + brdf2f = textureLod(u_brdfLUT, brdf2f, 0.0).rg; + return envMapSample * (F * brdf2f.r + brdf2f.g); +} + +#ifdef DO_COMPILE_SUN_SHADOWS +uniform sampler2DShadow u_sunShadowDepthTexture; +#ifdef COMPILE_SUN_SHADOW_SMOOTH +const vec2 POISSON_DISK[7] = vec2[]( +vec2(-0.077, 0.995), vec2(0.998, 0.015), +vec2(-0.116, -0.987), vec2(-0.916, 0.359), +vec2(-0.697, -0.511), vec2(0.740, -0.612), +vec2(0.675, 0.682)); +#define SMOOTH_SHADOW_SAMPLES 1.0 / 8.0 +#define SMOOTH_SHADOW_RADIUS 0.00075 +#define SMOOTH_SHADOW_POISSON_SAMPLE(idx, tex, lod, vec3Pos, accum, tmpVec2)\ + tmpVec2 = vec3Pos.xy + POISSON_DISK[idx] * SMOOTH_SHADOW_RADIUS;\ + tmpVec2 = clamp(tmpVec2, vec2(0.001), vec2(0.999));\ + tmpVec2.y += lod;\ + tmpVec2.y *= SUN_SHADOW_MAP_FRAC;\ + accum += textureLod(tex, vec3(tmpVec2, vec3Pos.z), 0.0) * SMOOTH_SHADOW_SAMPLES; +#endif +#endif + +void main() { + vec4 worldPosition4f; + vec4 worldDirection4f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + float block1f; + + // =========== RESOLVE CONSTANTS ============ // + + worldPosition4f = u_inverseViewMatrix4f * v_position4f; + worldPosition4f.xyz /= worldPosition4f.w; + worldPosition4f.w = 1.0; + worldDirection4f = u_inverseViewMatrix4f * vec4(v_position4f.xyz / v_position4f.w, 0.0); + worldDirection4f.xyz = normalize(worldDirection4f.xyz); + +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB + lightmapCoords2f = v_lightmap2f; +#else + lightmapCoords2f = u_textureCoords02; +#endif +#else + lightmapCoords2f = vec2(0.0, 1.0); +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + normalVector3f = normalize(v_normal3f); + block1f = v_block1f; +#else + normalVector3f = u_uniformNormal3f; + block1f = u_blockConstant1f; +#endif + + normalVector3f = normalize(mat3(u_inverseViewMatrix4f) * normalVector3f); + + // ============ SUN LIGHTING ============== // + + vec3 lightColor3f = vec3(0.0); + if(dot(u_sunDirection4f.xyz, normalVector3f) > 0.0 && lightmapCoords2f.g > 0.5 && + (u_sunColor3f_sky1f.r + u_sunColor3f_sky1f.g + u_sunColor3f_sky1f.b) > 0.001) { +#ifdef DO_COMPILE_SUN_SHADOWS + + // ========== SUN SHADOW: LOD0 ============ // + + float skyLight = max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); + float shadowSample = 1.0; + vec4 shadowWorldPos4f = worldPosition4f; + shadowWorldPos4f.xyz += normalVector3f * 0.05; + + vec4 shadowTexPos4f; + vec2 tmpVec2; + for(;;) { + shadowTexPos4f = u_sunShadowMatrixLOD04f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy * vec2(1.0, SUN_SHADOW_MAP_FRAC), shadowTexPos4f.z), 0.0); +#ifdef COMPILE_SUN_SHADOW_SMOOTH + shadowSample *= SMOOTH_SHADOW_SAMPLES; + SMOOTH_SHADOW_POISSON_SAMPLE(0, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(1, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(2, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(3, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(4, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(5, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(6, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + shadowSample = max(shadowSample * 2.0 - 1.0, 0.0); +#endif + break; + } + +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowTexPos4f = u_sunShadowMatrixLOD14f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 1.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowTexPos4f = u_sunShadowMatrixLOD24f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 2.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + } +#endif + break; + } +#endif + lightColor3f = u_sunColor3f_sky1f.rgb * max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); +#ifdef DO_COMPILE_SUN_SHADOWS + lightColor3f *= shadowSample * skyLight; +#endif + lightColor3f = eaglercraftLighting_Glass(lightColor3f, -worldDirection4f.xyz, u_sunDirection4f.xyz, normalVector3f) * u_blockSkySunDynamicLightFac4f.z; + } + + // =========== ENVIRONMENT MAP =========== // + + for(;;) { + float dst2 = dot(worldPosition4f.xyz, worldPosition4f.xyz); + if(dst2 > 16.0) { + break; + } + vec3 reflectDir = reflect(worldDirection4f.xyz, normalVector3f); + reflectDir.xz /= abs(reflectDir.y) + 1.0; + float dst = 1.0 - dot(reflectDir.xz, reflectDir.xz); + dst *= dst; + reflectDir.xz = reflectDir.xz * 0.975; + vec4 envMapSample4f; + if(dst < 0.005) { + vec4 sample1 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + envMapSample4f = vec4(mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, reflectDir.y * -12.5 + 0.5)).rgb, min(sample1.a, sample2.a)); + }else { + reflectDir.xz = reflectDir.xz * vec2(0.5, reflectDir.y > 0.0 ? 0.25 : -0.25); + reflectDir.xz += vec2(0.5, reflectDir.y > 0.0 ? 0.25 : 0.75); + envMapSample4f = textureLod(u_environmentMap, reflectDir.xz, 0.0); + } + if(envMapSample4f.a > 0.0) { + lightColor3f += eaglercraftIBL_Specular_Glass(envMapSample4f.rgb, worldDirection4f.xyz, normalVector3f) * (1.0 - sqrt(dst2) * 0.25); + } + break; + } + +#ifdef COMPILE_DYNAMIC_LIGHTS + + // =========== DYNAMIC LIGHTING =========== // + + vec3 dlightDist3f, dlightDir3f, dlightColor3f; + int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i; // hate this + for(int i = 0; i < safeLightCount; ++i) { + dlightDist3f = u_dynamicLightArray[i].u_lightPosition4f.xyz - worldPosition4f.xyz; + dlightDir3f = normalize(dlightDist3f); + if(dot(dlightDir3f, normalVector3f) <= 0.0) { + continue; + } + dlightColor3f = u_dynamicLightArray[i].u_lightColor4f.rgb / dot(dlightDist3f, dlightDist3f); + if(dlightColor3f.r + dlightColor3f.g + dlightColor3f.b < 0.025) { + continue; + } + lightColor3f += eaglercraftLighting_Glass(dlightColor3f, -worldDirection4f.xyz, dlightDir3f, normalVector3f) * u_blockSkySunDynamicLightFac4f.w; + } + +#endif + + // ============ CACLULATE FOG ============= // + + float fogFade = 0.0; + if(u_fogParameters4f.x > 0.0) { + float atmos = u_fogParameters4f.x >= 4.0 ? 4.0 : 0.0; + float type = u_fogParameters4f.x - atmos; + fogFade = mix(u_fogColorDark4f.a, u_fogColorLight4f.a, lightmapCoords2f.g); + + float f; + float l = sqrt(dot(v_position4f.xyz, v_position4f.xyz)); + if(type == 1.0) { + f = (l - u_fogParameters4f.z) / (u_fogParameters4f.w - u_fogParameters4f.z); + }else { + f = 1.0 - exp(-u_fogParameters4f.y * l); + } + + fogFade *= clamp(f, 0.0, 1.0); + } + + // ============ OUTPUT COLOR ============== // + + output4f = vec4(lightColor3f * (1.0 - fogFade), 0.1); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.vsh b/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.vsh new file mode 100644 index 0000000..d98b245 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/forward_glass_highlights.vsh @@ -0,0 +1,52 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +out vec4 v_position4f; + +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +out vec3 v_normal3f; +out float v_block1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +out vec2 v_lightmap2f; +uniform mat4 u_textureMat4f02; +#endif + +uniform mat4 u_modelviewMat4f; +uniform mat4 u_projectionMat4f; + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { + v_position4f = u_modelviewMat4f * vec4(a_position3f, 1.0); + +#ifdef COMPILE_NORMAL_ATTRIB + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); + v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; +#endif + + gl_Position = u_projectionMat4f * v_position4f; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/gbuffer_debug_view.fsh b/sources/resources/assets/eagler/glsl/deferred/gbuffer_debug_view.fsh new file mode 100644 index 0000000..1135edc --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/gbuffer_debug_view.fsh @@ -0,0 +1,109 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_texture0; +uniform sampler2D u_texture1; + +#ifdef DEBUG_VIEW_18 +precision highp sampler3D; +uniform sampler3D u_texture3D0; +uniform float u_fuckU1f; +#endif + +uniform mat4 u_inverseViewMatrix; +uniform vec2 u_depthSliceStartEnd2f; + +void main() { +#ifdef DEBUG_VIEW_0 + output4f = vec4(textureLod(u_texture0, v_position2f, 0.0).rgb, 1.0); +#endif +#ifdef DEBUG_VIEW_1 + vec3 color3f = textureLod(u_texture0, v_position2f, 0.0).rgb; + if(color3f.x == 0.0 && color3f.y == 0.0 && color3f.z == 0.0) { + output4f = vec4(0.0, 0.0, 0.0, 1.0); + }else { + output4f = vec4(normalize(mat3(u_inverseViewMatrix) * (color3f * 2.0 - 1.0)), 1.0); + } +#endif +#ifdef DEBUG_VIEW_2 + output4f = vec4(textureLod(u_texture0, v_position2f, 0.0).a, textureLod(u_texture1, v_position2f, 0.0).a, 0.0, 1.0); +#endif +#ifdef DEBUG_VIEW_3 + vec4 color4f = textureLod(u_texture0, v_position2f, 0.0); + output4f = vec4(color4f.b > 0.99 ? 1.0 : 0.0, color4f.a, 0.0, 1.0); +#endif +#ifdef DEBUG_VIEW_4 + output4f = vec4(vec3(clamp((textureLod(u_texture0, v_position2f, 0.0).r - u_depthSliceStartEnd2f.x) * u_depthSliceStartEnd2f.y, 0.0, 1.0)), 1.0); +#endif +#ifdef DEBUG_VIEW_5 + output4f = vec4(vec3(textureLod(u_texture0, (v_position2f + vec2(0.0, u_depthSliceStartEnd2f.y)) * vec2(1.0, u_depthSliceStartEnd2f.x), 0.0).r), 1.0); +#endif +#ifdef DEBUG_VIEW_6 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).r), 1.0); +#endif +#ifdef DEBUG_VIEW_7 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).a > 0.0 ? 1.0 : 0.0), 1.0); +#endif +#ifdef DEBUG_VIEW_8 + output4f = vec4(textureLod(u_texture0, v_position2f, 0.0).rgb * 10.0, 1.0); + output4f.xyz /= (output4f.xyz + 1.0); + output4f.xyz = sqrt(output4f.xyz); +#endif +#ifdef DEBUG_VIEW_9 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).g), 1.0); +#endif +#ifdef DEBUG_VIEW_10 + vec2 coord = (v_position2f + vec2(0.0, u_depthSliceStartEnd2f.y)) * vec2(1.0, u_depthSliceStartEnd2f.x); + vec4 color2 = textureLod(u_texture1, coord, 0.0); + output4f = vec4(mix(color2.rgb, vec3(textureLod(u_texture0, coord, 0.0).r), color2.a), 1.0); +#endif +#ifdef DEBUG_VIEW_11 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).a * 0.017), 1.0); +#endif +#ifdef DEBUG_VIEW_12 + output4f = vec4(abs(textureLod(u_texture0, v_position2f, 0.0).rgb) * 0.1, 1.0); +#endif +#ifdef DEBUG_VIEW_13 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).g > 0.0 ? 1.0 : 0.0), 1.0); +#endif +#ifdef DEBUG_VIEW_14 + output4f = vec4(textureLod(u_texture0, v_position2f.yx, 0.0).rgb * 2.5, 1.0); + output4f.xyz /= (output4f.xyz + 1.0); + output4f.xyz = sqrt(output4f.xyz); +#endif +#ifdef DEBUG_VIEW_15 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f.yx, 0.0).a > 0.0 ? 1.0 : 0.0), 1.0); +#endif +#ifdef DEBUG_VIEW_16 + output4f = vec4(textureLod(u_texture0, v_position2f, 0.0).rg, 0.0, 1.0); +#endif +#ifdef DEBUG_VIEW_17 + output4f = vec4(vec3(textureLod(u_texture0, v_position2f, 0.0).r) * 10.0, 1.0); + output4f.xyz /= (output4f.xyz + 1.0); + output4f.xyz = sqrt(output4f.xyz); +#endif +#ifdef DEBUG_VIEW_18 + output4f = vec4(vec3(textureLod(u_texture3D0, vec3(v_position2f, u_fuckU1f), 0.0).r), 1.0); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/hand_depth_mask.fsh b/sources/resources/assets/eagler/glsl/deferred/hand_depth_mask.fsh new file mode 100644 index 0000000..5c25e67 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/hand_depth_mask.fsh @@ -0,0 +1,27 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision mediump float; +precision highp sampler2D; + +in vec2 v_position2f; + +uniform sampler2D u_depthTexture; + +void main() { + gl_FragDepth = textureLod(u_depthTexture, v_position2f, 0.0).r <= 0.0000001 ? 0.0 : 1.0; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/lens_ghosts.bmp b/sources/resources/assets/eagler/glsl/deferred/lens_ghosts.bmp new file mode 100644 index 0000000000000000000000000000000000000000..29fd027e797b942c82022a286afca9f1c4545f58 GIT binary patch literal 21880 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

    ym%iSAV`GKeFOP?7qREkskN6GEkj);&GBGyN z$9Tu`k7`%M-iy)pu@L`j*N1;1LqSqXS^>*HxDio3bN~fP^?)8>iRmB|KAfD0VBrEO z08P?|H-V@hMAe9jnvRut!NO&kD{|MZ+g!0@=U!M%`MPz5pJgstxG;InjOj60C4~A% z$fUpkFE3Z9A9h0F!`5aDkv`tlJ-~346jAGcw#UEM&42YKwFhG+$jT|w>0rmIOm(5^ zrK^X&U~EE}DP=e+wJSgb8dksD+{XJ&2%0=4Zdy`O>Ox8fS-W=aimU~xDbwQOrc4f= z2>r{~!-FVbT&{zIz5QrQ4%9EhUy&Zv`sfS{?Q$96+1R zrW8=PZ2+n7?R6O>+b{*l>BBkyn`-^NZvXa8!lghFh!F|+UDcZ?l0?S`K47R6O8Z7U zP%oyY<`z~~PHy9&eoux4csn{+S(%%gni4gSL`|rHlW(f3zN3E2(rC!G(8#TSd!A4F zGdYm3IEGJ1MMe1Z11Nd(>_brziYcOD!m?o7*h0IpWm~XJNS2}XzcCU!tgSG@-O$yB z?UTCrr*Ho2zzCmyktl#vL$m`?9e(;He4;_(_mSnhKYjAQ=ZjSTK>H9rFp*^brRSk%7r8Gd1;D<}5uO zCS6`e22%lxt^@=uB4T|kP?2ka_)xdQ)Tc8ci|82{nXt^wIb+6ohQ!22PV(Z~Lxndo zGC~X2QDc&i!Ib66p`=%gb9;EB4d;0WvnhM zUtcIl=f{Un!kd16?kY z0<|XS8XgQ%wI0ZSdcP1J|;3Ud=l0aKW}$; zM|&&INOPP*gF%;*{4lr^rYS8?r>koln3!{{9bLWsCq_h1OMuvtLGHVLV|Cr0{fCaX zoxaf3{X<`0-w)kg7dqOG9ctWDQ&mP*Wq}|a+aflm$gqhxg`sA#)q+GyHijNEr_V;ibXKy{y*ieh9EH6!-PW%?~ zM1TaTA`w^DF)|s+88g<|-8&#CB5K;Kl(fth1;rc6tLygeKXmj&d&i|K-}T<^$GxAw zq@=W0FJC+vdN^?B=JoEb&ND`tfi)^ zC@UikJ@lPp0BIQ4vI=yDh7OQMJa_ly1&2q+C-BoUvR6XgtgNZqw;y}_8QlN+&Ax#L zLr;j32QBZ_%jZuXJ?O{%uU_gr-Fo!!{=Ie8st>StakRB&o3RW? z?a9kXz6W*hy|?g96d{&9I)ka9h1O$Yj%U1Vv=uuXhH5_(!Xpz>(w7%+tg2eGJe{8q z6CQ#FM2gMMny`3t7Ku0MJ$NAb2NC~g#}KX>X!Y`>38D?+KeS&xLnCxH^O4r}T)%K^ z*pq!-P+Yj7iII^ma!mDJbUdo}ew@)nCJ*KSF`^2RX&@t`KxgV2nR7-O=`xiSsCT5K z$V{ik)Q9EypLzaa@00jQVe|iMK6;6`ib%irhLqFj3sUk74Q29&H^aWY_rveJ305E@ zhe4^YZ_FO!FwWIKa#2QNxaT+r8;+@wk-na$nu?;V)cZ?8Ok7%?smro*^a`31pEN&X z<%aT|P3_-a?QGdwy>WH+qLjpGQ$zgS##*xUm~y|m1PO+`iuQ<6HZHy)ar~wE>nrOI z9P9X|=ck8He|hojQGf51uTCD^y=_y;iY3X@!u;LrM;T}+!7X7sz}IOqiVQvTG0wh| zqLUUaU%heL?t>>fuiP9MdX5Ja4}a>p+Wj6_F( literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/lens_sun_occlusion.fsh b/sources/resources/assets/eagler/glsl/deferred/lens_sun_occlusion.fsh new file mode 100644 index 0000000..83c27a2 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lens_sun_occlusion.fsh @@ -0,0 +1,68 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) out float occlusionOut1f; + +uniform mat3 u_sampleMatrix3f; +uniform sampler2D u_depthBufferTexture; +uniform sampler2D u_cloudsSunOcclusion; + +#define SAMPLE_DEPTH(v, a, f)\ + f = u_sampleMatrix3f * v;\ + f.xy /= f.z;\ + if(f.xy == clamp(f.xy, vec2(0.001), vec2(0.999)))\ + a += textureLod(u_depthBufferTexture, f.xy, 0.0).r > 0.000001 ? 0.0 : 0.0417; + +void main() { + vec3 f; + float accum = 0.0; + float cloud = textureLod(u_cloudsSunOcclusion, vec2(0.5, 0.5), 0.0).r; + if(cloud < 0.01) { + occlusionOut1f = 0.0; + return; + } + + SAMPLE_DEPTH(vec3(0.0, 0.0, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.235, -0.962, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.029, 0.996, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.834, -0.509, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.981, -0.086, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.821, 0.478, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.614, 0.563, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.251, -0.578, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.571, -0.491, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.142, 0.494, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.533, -0.036, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.970, -0.035, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.388, 0.918, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.521, 0.067, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.140, -0.471, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.487, 0.692, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.157, 0.331, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.559, -0.760, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.156, -0.956, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.181, -0.267, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.773, 0.272, 1.0), accum, f) + SAMPLE_DEPTH(vec3(0.329, 0.228, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.341, -0.187, 1.0), accum, f) + SAMPLE_DEPTH(vec3(-0.121, 0.689, 1.0), accum, f) + + occlusionOut1f = min(accum * cloud, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/lib/pbr_env_map.glsl b/sources/resources/assets/eagler/glsl/deferred/lib/pbr_env_map.glsl new file mode 100644 index 0000000..7eb62fc --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lib/pbr_env_map.glsl @@ -0,0 +1,120 @@ + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +#ifdef LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING +#ifndef _HAS_PBR_IMAGE_BASED_LIGHTING_FUNCTION +#define _HAS_PBR_IMAGE_BASED_LIGHTING_FUNCTION + +vec3 eaglercraftIBL_NoBlur(in vec3 albedo, in vec3 irradiance, in vec3 envMapSample, in vec3 viewDir, in vec3 normalVec, in vec3 materials) { + if(materials.g < 0.25) { + return albedo * irradiance * 0.1; + }else { + float roughness = 1.0 - materials.r * 0.85; + float NdotV = dot(normalVec, -viewDir); + float fresnel = pow(max(1.0 - NdotV, 0.0), 5.0); + vec3 kD = vec3(0.05); + vec3 F; + if(materials.g < 0.9) { + F = vec3(materials.g + (max(1.0 - roughness, materials.g) - materials.g) * fresnel); + kD = (1.0 - F) * albedo / 3.141592; + }else if(materials.g < 0.964) { + vec2 lutUV = vec2(0.25, (materials.g - 0.9) * 15.625); + vec3 mN = textureLod(u_metalsLUT, lutUV, 0.0).rgb; + lutUV.x += 0.5; + vec3 mK = textureLod(u_metalsLUT, lutUV, 0.0).rgb; + fresnel = 1.0 - fresnel; + mK *= mK; + mK += mN * mN; + vec3 nv = mN * fresnel * 2.0; + fresnel *= fresnel; + vec3 num = mK - nv + fresnel; + vec3 den = mK + nv + fresnel; + vec3 r = num / den; + mK *= fresnel; + mK += 1.0; + num = mK - nv; + den = mK + nv; + r += num / den; + r = clamp(r * 0.5, vec3(0.0), vec3(1.0)); + F = r * r; + }else { + F = (1.0 - albedo) + albedo * fresnel; + kD = vec3(0.05); + } + vec2 brdf2f = vec2(max(NdotV, 0.0), roughness); + brdf2f = 1.0 - brdf2f; + brdf2f *= brdf2f; + brdf2f = 1.0 - brdf2f; + brdf2f = textureLod(u_brdfLUT, brdf2f, 0.0).rg; + return kD * albedo * irradiance + envMapSample * (F * brdf2f.r + brdf2f.g); + } +} + +#endif +#endif + +#ifdef LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING_SPECULAR +#ifndef _HAS_PBR_IMAGE_BASED_LIGHTING_SPECULAR_FUNCTION +#define _HAS_PBR_IMAGE_BASED_LIGHTING_SPECULAR_FUNCTION + +#ifdef LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING_PREFETCH +vec3 eaglercraftIBL_Specular(in vec3 albedo, in vec3 envMapSample, in vec3 viewDir, in vec3 normalVec, in vec3 materials, vec3 metalN, vec3 metalK) { +#else +vec3 eaglercraftIBL_Specular(in vec3 albedo, in vec3 envMapSample, in vec3 viewDir, in vec3 normalVec, in vec3 materials) { +#endif + float NdotV = dot(normalVec, -viewDir); + float roughness = 1.0 - materials.r * 0.85; + float fresnel = pow(max(1.0 - NdotV, 0.0), 5.0); + vec3 F; + if(materials.g < 0.9) { + F = vec3(materials.g + (max(1.0 - roughness, materials.g) - materials.g) * fresnel); + }else if(materials.g < 0.964) { +#ifdef LIB_INCLUDE_PBR_IMAGE_BASED_LIGHTING_PREFETCH + vec3 mN = metalN; + vec3 mK = metalK; +#else + vec2 lutUV = vec2(0.25, (materials.g - 0.9) * 15.625); + vec3 mN = textureLod(u_metalsLUT, lutUV, 0.0).rgb; + lutUV.x += 0.5; + vec3 mK = textureLod(u_metalsLUT, lutUV, 0.0).rgb; +#endif + fresnel = 1.0 - fresnel; + mK *= mK; + mK += mN * mN; + vec3 nv = mN * fresnel * 2.0; + fresnel *= fresnel; + vec3 num = mK - nv + fresnel; + vec3 den = mK + nv + fresnel; + vec3 r = num / den; + mK *= fresnel; + mK += 1.0; + num = mK - nv; + den = mK + nv; + r += num / den; + r = clamp(r * 0.5, vec3(0.0), vec3(1.0)); + F = r * r; + }else { + F = (1.0 - albedo) + albedo * fresnel; + } + vec2 brdf2f = vec2(max(NdotV, 0.0), roughness); + brdf2f = 1.0 - brdf2f; + brdf2f *= brdf2f; + brdf2f = 1.0 - brdf2f; + brdf2f = textureLod(u_brdfLUT, brdf2f, 0.0).rg; + return envMapSample * (F * brdf2f.r + brdf2f.g); +} + +#endif +#endif \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/lib/pbr_lighting.glsl b/sources/resources/assets/eagler/glsl/deferred/lib/pbr_lighting.glsl new file mode 100644 index 0000000..87f9072 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lib/pbr_lighting.glsl @@ -0,0 +1,86 @@ + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +#ifdef LIB_INCLUDE_PBR_LIGHTING_FUNCTION +#ifndef _HAS_PBR_LIGHTING_FUNCTION +#define _HAS_PBR_LIGHTING_FUNCTION + +#ifdef LIB_INCLUDE_PBR_LIGHTING_PREFETCH +#define PREFETCH_METALS(albedo, materialG1f, metalN3f, metalK3f)\ + if(materialG1f >= 0.9 && materialG1f < 0.964) {\ + metalK3f.xy = vec2(0.25, (materialG1f - 0.9) * 15.625);\ + metalN3f = textureLod(u_metalsLUT, metalK3f.xy, 0.0).rgb;\ + metalK3f.x += 0.5;\ + metalK3f = textureLod(u_metalsLUT, metalK3f.xy, 0.0).rgb;\ + } +#endif + +#ifdef LIB_INCLUDE_PBR_LIGHTING_PREFETCH +vec3 eaglercraftLighting(in vec3 albedo, in vec3 radiance, in vec3 viewDir, in vec3 lightDir, in vec3 normalVec, in vec3 materials, in vec3 metalN, in vec3 metalK) { +#else +vec3 eaglercraftLighting(in vec3 albedo, in vec3 radiance, in vec3 viewDir, in vec3 lightDir, in vec3 normalVec, in vec3 materials) { +#endif + float roughness = 1.0 - materials.r * 0.85; + vec3 H = normalize(viewDir + lightDir); + vec3 NdotHVL = max(normalVec * mat3(H, viewDir, lightDir), vec3(0.0)); + float NDF = roughness * roughness; + NDF *= NDF; + float denom = NdotHVL.x * NdotHVL.x * (NDF - 1.0) + 1.0; + NDF /= denom * denom * 3.141592; + float gs = roughness + 1.0; + gs *= gs * 0.125; + vec2 Ndot = NdotHVL.yz; + Ndot /= Ndot * (1.0 - gs) + gs; + NDF *= Ndot.x * Ndot.y; + float fresnel = pow(max(1.0 - NdotHVL.x, 0.0), 5.0); + vec3 kD = vec3(0.03); + vec3 F; + if(materials.g < 0.9) { + F = vec3(materials.g + (1.0 - materials.g) * fresnel); + kD = (1.0 - F) * albedo / 3.141592; + }else if(materials.g < 0.964) { +#ifdef LIB_INCLUDE_PBR_LIGHTING_PREFETCH + vec3 mN = metalN; + vec3 mK = metalK; +#else + vec2 lutUV = vec2(0.25, (materials.g - 0.9) * 15.625); + vec3 mN = textureLod(u_metalsLUT, lutUV, 0.0).rgb; + lutUV.x += 0.5; + vec3 mK = textureLod(u_metalsLUT, lutUV, 0.0).rgb * length(albedo); +#endif + fresnel = 1.0 - fresnel; + mK *= mK; + mK += mN * mN; + vec3 nv = mN * fresnel * 2.0; + fresnel *= fresnel; + vec3 num = mK - nv + fresnel; + vec3 den = mK + nv + fresnel; + vec3 r = num / den; + mK *= fresnel; + mK += 1.0; + num = mK - nv; + den = mK + nv; + r += num / den; + r = clamp(r * 0.5, vec3(0.0), vec3(1.0)); + F = r * r; + }else { + F = albedo + (1.0 - albedo) * fresnel; + } + denom = 4.0 * NdotHVL.y * NdotHVL.z + 0.0001; + return (kD + (NDF * F / denom)) * radiance * NdotHVL.z; +} + +#endif +#endif diff --git a/sources/resources/assets/eagler/glsl/deferred/lib/waving_blocks.glsl b/sources/resources/assets/eagler/glsl/deferred/lib/waving_blocks.glsl new file mode 100644 index 0000000..8d9d61f --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lib/waving_blocks.glsl @@ -0,0 +1,218 @@ + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +#ifdef LIB_INCLUDE_WAVING_BLOCKS_FUNCTION +#ifndef _HAS_INCLUDED_WAVING_BLOCKS +#define _HAS_INCLUDED_WAVING_BLOCKS + +#define _WAVING_BLOCK_TYPE_LEAF_BLOCK 1 +#define _WAVING_BLOCK_TYPE_LEAF_BLOCK_F 1.0 +#define _WAVING_BLOCK_TYPE_TALL_GRASS 2 +#define _WAVING_BLOCK_TYPE_TALL_GRASS_F 2.0 +#define _WAVING_BLOCK_TYPE_CROPS 3 +#define _WAVING_BLOCK_TYPE_CROPS_F 3.0 +#define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM 4 +#define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM_F 4.0 +#define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP 5 +#define _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP_F 5.0 +#define _WAVING_BLOCK_TYPE_PLANT 6 +#define _WAVING_BLOCK_TYPE_PLANT_F 6.0 +#define _WAVING_BLOCK_TYPE_SUGARCANE 7 +#define _WAVING_BLOCK_TYPE_SUGARCANE_F 7.0 +#define _WAVING_BLOCK_TYPE_VINES 8 +#define _WAVING_BLOCK_TYPE_VINES_F 8.0 +#define _WAVING_BLOCK_TYPE_WATER_STILL 9 +#define _WAVING_BLOCK_TYPE_WATER_STILL_F 9.0 +#define _WAVING_BLOCK_TYPE_WATER_FLOW 10 +#define _WAVING_BLOCK_TYPE_WATER_FLOW_F 10.0 +#define _WAVING_BLOCK_TYPE_LILYPAD 11 +#define _WAVING_BLOCK_TYPE_LILYPAD_F 11.0 +#define _WAVING_BLOCK_TYPE_FIRE_FLOOR 12 +#define _WAVING_BLOCK_TYPE_FIRE_FLOOR_F 12.0 +#define _WAVING_BLOCK_TYPE_FIRE_WALL 13 +#define _WAVING_BLOCK_TYPE_FIRE_WALL_F 13.0 + +// ignore wall fire for now, they clip +#define _WAVING_BLOCK_MIN _WAVING_BLOCK_TYPE_LEAF_BLOCK_F +#define _WAVING_BLOCK_MAX _WAVING_BLOCK_TYPE_FIRE_FLOOR_F + +#ifndef FAKE_SIN +#error the FAKE_SIN function must be defined to use waving blocks +#endif + +#define _WAVING_BLOCK_COORD_DERIVE_HACK 0.001 +#define _WAVING_BLOCK_COORD_DERIVE_HACK_05 0.0005 +#define _WAVING_BLOCK_COORD_DERIVE_HACK_INV 1000.0 + +vec3 _computeWavingBlockNoise(in vec3 pos, in vec3 amp1, in float timer) { + float fac, fac2; + fac = dot(vec4(pos, timer), vec4(0.5, 0.5, 0.5, 0.0027)); + FAKE_SIN(fac, fac2) + fac2 *= 0.04; + fac2 += 0.04; + vec3 vf0, d0; + vf0 = timer * vec3(0.0127, 0.0089, 0.0114); + FAKE_SIN(vf0, d0); + d0.xyz += d0.yzx; + d0.xyz += timer * vec3(0.0063, 0.0224, 0.0015); + d0.y += pos.z; + d0.xz += pos.y; + d0.xz += pos.zx; + d0.xz -= pos.xz; + vec3 ret; + FAKE_SIN(d0, ret) + ret *= fac2; + return ret * amp1; +} + +vec3 _computeWavingBlockNoise(in vec3 pos, in vec3 vf_a, in vec3 vf_b, in vec3 amp1, in vec3 amp2, in float timer) { + float fac, fac2; + fac = dot(vec4(pos, timer), vec4(0.5, 0.5, 0.5, 0.0027)); + FAKE_SIN(fac, fac2) + fac2 *= 0.04; + fac2 += 0.04; + vec3 vf0, d0; + vf0 = timer * vec3(0.0127, 0.0089, 0.0114); + FAKE_SIN(vf0, d0); + d0.xyz += d0.yzx; + d0.xyz += timer * vec3(0.0063, 0.0224, 0.0015); + d0.y += pos.z; + d0.xz += pos.y; + d0.xz += pos.zx; + d0.xz -= pos.xz; + vec3 ret; + FAKE_SIN(d0, ret) + ret *= fac2; + vec3 move = ret * amp1; + vec3 pos2 = move + pos; + fac = dot(vec4(pos2, timer), vec4(0.5, 0.5, 0.5, 0.0027)); + FAKE_SIN(fac, fac2) + fac2 *= 0.04; + fac2 += 0.04; + vf0 = timer * vf_a; + FAKE_SIN(vf0, d0); + d0.xyz += d0.yzx; + d0.xyz += timer * vf_b; + d0.y += pos2.z; + d0.xz += pos2.y; + d0.xz += pos2.zx; + d0.xz -= pos2.xz; + FAKE_SIN(d0, ret) + ret *= fac2; + move += ret * amp2; + return move; +} + +vec3 _computeWavingBlockById(in vec3 realPos, in vec3 referencePos, in vec4 wavingBlockParam, in float type) { + int typeInt = int(type); + highp float refY, fractY1, fractY2; + refY = referencePos.y; + switch(typeInt) { + case _WAVING_BLOCK_TYPE_CROPS: + refY += 0.0625625; + case _WAVING_BLOCK_TYPE_TALL_GRASS: + case _WAVING_BLOCK_TYPE_PLANT: + case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM: + case _WAVING_BLOCK_TYPE_FIRE_FLOOR: + // check if it is the bottom half of the block, + // if vertex is at Y = 0.0 then don't offset + fractY1 = fract(refY + _WAVING_BLOCK_COORD_DERIVE_HACK_05); + fractY2 = fract(refY - _WAVING_BLOCK_COORD_DERIVE_HACK_05); + if(fractY2 > fractY1) { + return vec3(0.0); + } + default: + break; + } + vec3 ret = vec3(0.0); + switch(typeInt) { + case _WAVING_BLOCK_TYPE_LEAF_BLOCK: + ret = _computeWavingBlockNoise( + referencePos, + vec3(0.0040, 0.0064, 0.0043), + vec3(0.0035, 0.0037, 0.0041), + vec3(1.0, 0.2, 1.0), + vec3(0.5, 0.1, 0.5), + wavingBlockParam.y); + break; + case _WAVING_BLOCK_TYPE_TALL_GRASS: + case _WAVING_BLOCK_TYPE_CROPS: + ret = _computeWavingBlockNoise( + referencePos, + vec3(1.0, 0.2, 1.0), + wavingBlockParam.y); + break; + case _WAVING_BLOCK_TYPE_PLANT: + case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_BOTTOM: + case _WAVING_BLOCK_TYPE_DOUBLE_PLANT_TOP: + ret = _computeWavingBlockNoise( + referencePos, + vec3(0.0041, 0.007, 0.0044), + vec3(0.0038, 0.024, 0.0), + vec3(0.8, 0.0, 0.8), + vec3(0.4, 0.0, 0.4), + wavingBlockParam.y); + break; + case _WAVING_BLOCK_TYPE_SUGARCANE: + ret = _computeWavingBlockNoise( + referencePos, + vec3(0.3, 0.0, 0.3), + wavingBlockParam.y); + break; + case _WAVING_BLOCK_TYPE_VINES: + ret = _computeWavingBlockNoise( + referencePos, + vec3(0.0040, 0.0064, 0.0043), + vec3(0.0035, 0.0037, 0.0041), + vec3(0.5, 0.3, 0.5), + vec3(0.25, 0.2, 0.25), + wavingBlockParam.y); + break; + case _WAVING_BLOCK_TYPE_WATER_STILL: + + break; + case _WAVING_BLOCK_TYPE_WATER_FLOW: + + break; + case _WAVING_BLOCK_TYPE_FIRE_FLOOR: + ret = _computeWavingBlockNoise( + referencePos, + vec3(0.0105, 0.0096, 0.0087), + vec3(0.0063, 0.0097, 0.0156), + vec3(1.2, 0.4, 1.2), + vec3(0.8, 0.8, 0.8), + wavingBlockParam.y); + break; + default: + break; + } + return ret; +} + +#define COMPUTE_WAVING_BLOCKS(pos4f, amount, range, block1f, modelMatrix, viewMatrix, modelViewMatrix, wavingBlockOffset, wavingBlockParam)\ + if(block1f >= _WAVING_BLOCK_MIN && block1f <= _WAVING_BLOCK_MAX) {\ + pos4f = modelMatrix * pos4f;\ + pos4f.xyz /= pos4f.w;\ + pos4f.w = 1.0;\ + if(dot(pos4f.xyz, pos4f.xyz) < range * range) {\ + pos4f.xyz += _computeWavingBlockById(pos4f.xyz, pos4f.xyz + wavingBlockOffset, wavingBlockParam, block1f) * amount;\ + }\ + pos4f = viewMatrix * pos4f;\ + }else {\ + pos4f = modelViewMatrix * pos4f;\ + } + +#endif +#endif diff --git a/sources/resources/assets/eagler/glsl/deferred/light_point_mesh.dat b/sources/resources/assets/eagler/glsl/deferred/light_point_mesh.dat new file mode 100644 index 0000000000000000000000000000000000000000..0ff3f4944073b7eb0ae75968a906d0e2e883a300 GIT binary patch literal 522 zcmXAkNp9Of5Jig==SieE58@;a&Flh`5l#CpUL~;sWdP!hmcEBikX-;GqG_MN3mzp1 zbb_=yiv}9M{`OX_oJbvZ_(t6m@}6u`8Oa$jUNHvnI~sJdd|=6UJeZghANUVI4(v zFH<+o-CR}kt+P#>M3R!g4k9}egs3uip6OYZx7JfvcMZc;)UBgB zn&ya7U`w_v+bf~+1)pL34ZpE?i{q>{w>CI~WetT@G*+W1O=LDa!_zbmlqgd&P0Oo) D=p=kF literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/light_shafts_sample.fsh b/sources/resources/assets/eagler/glsl/deferred/light_shafts_sample.fsh new file mode 100644 index 0000000..ee2a1c3 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/light_shafts_sample.fsh @@ -0,0 +1,158 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; +precision highp sampler2DShadow; + +in vec2 v_position2f; + +layout(location = 0) out float output1f; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2DShadow u_sunShadowDepthTexture; +uniform sampler2D u_ditherTexture; + +uniform mat4 u_inverseViewProjMatrix4f; + +uniform vec2 u_ditherScale2f; +uniform vec3 u_eyePosition3f; +uniform float u_sampleStep1f; + +#define SAMPLES_PER_STEP 8.0 +#define SAMPLES_PER_STEP_1 0.125 + +#ifdef COMPILE_SUN_SHADOW_LOD0 +uniform mat4 u_sunShadowMatrixLOD04f; +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 +uniform mat4 u_sunShadowMatrixLOD04f; +uniform mat4 u_sunShadowMatrixLOD14f; +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 +uniform mat4 u_sunShadowMatrixLOD04f; +uniform mat4 u_sunShadowMatrixLOD14f; +uniform mat4 u_sunShadowMatrixLOD24f; +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif + +float shadow(in vec3 coords) { + vec4 shadowSpacePosition = u_sunShadowMatrixLOD04f * vec4(coords, 1.0); + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; + return textureLod(u_sunShadowDepthTexture, shadowSpacePosition.xyz, 0.0); + } +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowSpacePosition = u_sunShadowMatrixLOD14f * vec4(coords, 1.0); + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSpacePosition.y += 1.0; + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; + return textureLod(u_sunShadowDepthTexture, shadowSpacePosition.xyz, 0.0); + } +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowSpacePosition = u_sunShadowMatrixLOD24f * vec4(coords, 1.0); + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSpacePosition.y += 2.0; + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; + return textureLod(u_sunShadowDepthTexture, shadowSpacePosition.xyz, 0.0); + } +#endif + return -1.0; +} + +#define STEP2DST(stepNum) (stepNum * stepNum * 0.06 + stepNum * 0.05) + +void main() { + output1f = 1.0; + float depth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + if(depth < 0.00001) { + return; + } + + vec4 fragPos4f = vec4(v_position2f, depth, 1.0); + fragPos4f.xyz *= 2.0; + fragPos4f.xyz -= 1.0; + + fragPos4f = u_inverseViewProjMatrix4f * fragPos4f; + fragPos4f.xyz /= fragPos4f.w; + fragPos4f.w = 1.0; + fragPos4f.xyz -= u_eyePosition3f; + + float viewDist = length(fragPos4f.xyz); + fragPos4f.xyz /= viewDist; + float sampleNum = textureLod(u_ditherTexture, u_ditherScale2f * v_position2f, 0.0).r; + sampleNum += u_sampleStep1f * SAMPLES_PER_STEP + 1.0; + + float cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + + sampleNum += 1.0; + cloudSample = STEP2DST(sampleNum); + if(cloudSample > viewDist) return; + cloudSample = shadow(u_eyePosition3f + fragPos4f.xyz * cloudSample); + if(cloudSample < 0.0) return; + output1f -= SAMPLES_PER_STEP_1 - cloudSample * SAMPLES_PER_STEP_1; + +} diff --git a/sources/resources/assets/eagler/glsl/deferred/lighting_mesh.vsh b/sources/resources/assets/eagler/glsl/deferred/lighting_mesh.vsh new file mode 100644 index 0000000..1ee1c2f --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lighting_mesh.vsh @@ -0,0 +1,27 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec3 a_position3f; + +uniform mat4 u_modelViewProjMatrix4f; + +void main() { + gl_Position = u_modelViewProjMatrix4f * vec4(a_position3f, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/lighting_point.fsh b/sources/resources/assets/eagler/glsl/deferred/lighting_point.fsh new file mode 100644 index 0000000..b3b15ac --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lighting_point.fsh @@ -0,0 +1,86 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_gbufferColorTexture; +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_gbufferMaterialTexture; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_metalsLUT; + +uniform mat4 u_inverseProjectionMatrix4f; +uniform mat4 u_inverseViewMatrix4f; + +uniform vec2 u_viewportSize2f; +uniform vec3 u_lightPosition3f; +uniform vec3 u_lightColor3f; + +#define LIB_INCLUDE_PBR_LIGHTING_FUNCTION +#EAGLER INCLUDE (3) "eagler:glsl/deferred/lib/pbr_lighting.glsl" + +void main() { + vec2 v_position2f = gl_FragCoord.xy * u_viewportSize2f; + vec3 diffuseColor3f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + vec3 materialData3f; + + float depth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + if(depth < 0.00001) { + discard; + } + + vec4 worldSpacePosition = vec4(v_position2f, depth, 1.0); + worldSpacePosition.xyz *= 2.0; + worldSpacePosition.xyz -= 1.0; + worldSpacePosition = u_inverseProjectionMatrix4f * worldSpacePosition; + vec4 worldSpacePosition2 = worldSpacePosition; + worldSpacePosition = u_inverseViewMatrix4f * worldSpacePosition; + vec3 lightDist = (worldSpacePosition.xyz / worldSpacePosition.w) - u_lightPosition3f; + vec3 color3f = u_lightColor3f / dot(lightDist, lightDist); + + if(color3f.r + color3f.g + color3f.b < 0.025) { + discard; + } + + vec4 sampleVar4f = textureLod(u_gbufferColorTexture, v_position2f, 0.0); + diffuseColor3f.rgb = sampleVar4f.rgb; + lightmapCoords2f.x = sampleVar4f.a; + sampleVar4f = textureLod(u_gbufferNormalTexture, v_position2f, 0.0); + normalVector3f.xyz = sampleVar4f.rgb * 2.0 - 1.0; + lightmapCoords2f.y = sampleVar4f.a; + materialData3f = textureLod(u_gbufferMaterialTexture, v_position2f, 0.0).rgb; + + vec3 worldSpaceNormal = normalize(mat3(u_inverseViewMatrix4f) * normalVector3f); + + vec3 lightDir3f = normalize(lightDist); + lightDir3f = materialData3f.b == 1.0 ? worldSpaceNormal : -lightDir3f; + + if(dot(lightDir3f, worldSpaceNormal) <= 0.0) { + discard; + } + + diffuseColor3f *= diffuseColor3f; + worldSpacePosition2 = u_inverseViewMatrix4f * vec4(worldSpacePosition2.xyz / worldSpacePosition2.w, 0.0); + worldSpacePosition2.xyz = normalize(worldSpacePosition2.xyz); + output4f = vec4(eaglercraftLighting(diffuseColor3f, color3f, -worldSpacePosition2.xyz, lightDir3f, worldSpaceNormal, materialData3f), 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/lighting_sun.fsh b/sources/resources/assets/eagler/glsl/deferred/lighting_sun.fsh new file mode 100644 index 0000000..d74cb59 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/lighting_sun.fsh @@ -0,0 +1,100 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_gbufferColorTexture; +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_gbufferMaterialTexture; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_metalsLUT; + +uniform mat4 u_inverseViewMatrix4f; +uniform mat4 u_inverseProjectionMatrix4f; + +#ifdef COMPILE_SUN_SHADOW +uniform sampler2D u_sunShadowTexture; +#endif + +uniform vec3 u_sunDirection3f; +uniform vec3 u_sunColor3f; + +#define LIB_INCLUDE_PBR_LIGHTING_FUNCTION +#EAGLER INCLUDE (3) "eagler:glsl/deferred/lib/pbr_lighting.glsl" + +void main() { + vec3 diffuseColor3f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + vec3 materialData3f; + +#ifdef COMPILE_SUN_SHADOW +#ifdef COMPILE_COLORED_SHADOW + vec4 shadow = textureLod(u_sunShadowTexture, v_position2f, 0.0); + if(shadow.a < 0.05) { + discard; + } +#else + vec3 shadow = vec3(textureLod(u_sunShadowTexture, v_position2f, 0.0).r); + if(shadow.r < 0.05) { + discard; + } +#endif +#endif + + vec4 sampleVar4f = textureLod(u_gbufferNormalTexture, v_position2f, 0.0); + +#ifndef COMPILE_SUN_SHADOW + vec3 shadow = vec3(sampleVar4f.a, 0.0, 0.0); + if(shadow.r < 0.5) { + discard; + } + shadow = vec3(max(shadow.r * 2.0 - 1.0, 0.0)); +#endif + + normalVector3f.xyz = sampleVar4f.rgb * 2.0 - 1.0; + lightmapCoords2f.y = sampleVar4f.a; + + float depth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + +#ifndef COMPILE_SUN_SHADOW + if(depth < 0.00001) { + discard; + } +#endif + + sampleVar4f = textureLod(u_gbufferColorTexture, v_position2f, 0.0); + diffuseColor3f.rgb = sampleVar4f.rgb; + lightmapCoords2f.x = sampleVar4f.a; + materialData3f = textureLod(u_gbufferMaterialTexture, v_position2f, 0.0).rgb; + + vec3 worldSpaceNormal = normalize(mat3(u_inverseViewMatrix4f) * normalVector3f); + vec4 worldSpacePosition = vec4(v_position2f, depth, 1.0); + worldSpacePosition.xyz *= 2.0; + worldSpacePosition.xyz -= 1.0; + worldSpacePosition = u_inverseProjectionMatrix4f * worldSpacePosition; + worldSpacePosition = u_inverseViewMatrix4f * vec4(worldSpacePosition.xyz / worldSpacePosition.w, 0.0); + + diffuseColor3f *= diffuseColor3f; + output4f = vec4(eaglercraftLighting(diffuseColor3f, u_sunColor3f * shadow.rgb, normalize(-worldSpacePosition.xyz), u_sunDirection3f, worldSpaceNormal, materialData3f), 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/material_block_constants.csv b/sources/resources/assets/eagler/glsl/deferred/material_block_constants.csv new file mode 100644 index 0000000..1c4f7a2 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/material_block_constants.csv @@ -0,0 +1,583 @@ +textureId,smoothness,reflectance,emission +blocks/anvil_base,158,230,0 +blocks/anvil_top_damaged_0,150,230,0 +blocks/anvil_top_damaged_1,143,230,0 +blocks/anvil_top_damaged_2,158,230,0 +blocks/beacon,158,16,200 +blocks/bed_feet_end,31,10,0 +blocks/bed_feet_side,28,9,0 +blocks/bed_feet_top,61,13,0 +blocks/bed_head_end,31,10,0 +blocks/bed_head_side,31,9,0 +blocks/bed_head_top,80,13,0 +blocks/bedrock,46,5,0 +blocks/bookshelf,64,13,0 +blocks/brewing_stand,130,47,0 +blocks/brewing_stand_base,149,10,0 +blocks/brick,37,8,0 +blocks/cactus_bottom,60,7,0 +blocks/cactus_side,71,7,0 +blocks/cactus_top,71,7,0 +blocks/cake_bottom,64,4,0 +blocks/cake_inner,29,3,0 +blocks/cake_side,43,3,0 +blocks/cake_top,127,10,0 +blocks/carrots_stage_0,71,7,0 +blocks/carrots_stage_1,71,7,0 +blocks/carrots_stage_2,71,7,0 +blocks/carrots_stage_3,71,7,0 +blocks/cauldron_bottom,38,230,0 +blocks/cauldron_inner,122,230,0 +blocks/cauldron_side,110,230,0 +blocks/cauldron_top,76,230,0 +blocks/clay,133,13,0 +blocks/coal_block,155,20,0 +blocks/coal_ore,84,10,0 +blocks/coarse_dirt,50,4,0 +blocks/cobblestone,83,10,0 +blocks/cobblestone_mossy,117,8,0 +blocks/cocoa_stage_0,133,8,0 +blocks/cocoa_stage_1,146,8,0 +blocks/cocoa_stage_2,156,8,0 +blocks/command_block,136,99,8 +blocks/comparator_off,115,5,0 +blocks/comparator_on,115,5,14 +blocks/crafting_table_front,113,29,0 +blocks/crafting_table_side,104,20,0 +blocks/crafting_table_top,97,14,0 +blocks/daylight_detector_inverted_top,95,6,0 +blocks/daylight_detector_side,70,5,0 +blocks/daylight_detector_top,95,6,0 +blocks/deadbush,18,10,0 +blocks/diamond_block,235,150,0 +blocks/diamond_ore,90,25,0 +blocks/dirt,50,4,0 +blocks/dirt_podzol_side,27,1,0 +blocks/dirt_podzol_top,47,15,0 +blocks/dispenser_front_horizontal,138,9,0 +blocks/dispenser_front_vertical,114,9,0 +blocks/door_acacia_lower,92,2,0 +blocks/door_acacia_upper,91,5,0 +blocks/door_birch_lower,79,14,0 +blocks/door_birch_upper,110,14,0 +blocks/door_dark_oak_lower,88,3,0 +blocks/door_dark_oak_upper,87,4,0 +blocks/door_iron_lower,214,230,0 +blocks/door_iron_upper,214,230,0 +blocks/door_jungle_lower,56,2,0 +blocks/door_jungle_upper,58,5,0 +blocks/door_spruce_lower,57,16,0 +blocks/door_spruce_upper,58,17,0 +blocks/door_wood_lower,70,2,0 +blocks/door_wood_upper,74,6,0 +blocks/double_plant_fern_bottom,71,7,0 +blocks/double_plant_fern_top,71,7,0 +blocks/double_plant_grass_bottom,71,7,0 +blocks/double_plant_grass_top,71,7,0 +blocks/double_plant_paeonia_bottom,71,7,0 +blocks/double_plant_paeonia_top,71,7,0 +blocks/double_plant_rose_bottom,71,7,0 +blocks/double_plant_rose_top,71,7,0 +blocks/double_plant_sunflower_back,71,7,0 +blocks/double_plant_sunflower_bottom,71,7,0 +blocks/double_plant_sunflower_front,71,7,0 +blocks/double_plant_sunflower_top,71,7,0 +blocks/double_plant_syringa_bottom,71,7,0 +blocks/double_plant_syringa_top,71,7,0 +blocks/dragon_egg,45,15,16 +blocks/dropper_front_horizontal,138,9,0 +blocks/dropper_front_vertical,112,9,0 +blocks/emerald_block,228,130,0 +blocks/emerald_ore,93,26,0 +blocks/enchanting_table_bottom,210,120,0 +blocks/enchanting_table_side,199,8,0 +blocks/enchanting_table_top,118,16,0 +blocks/end_stone,107,15,0 +blocks/endframe_eye,144,37,46 +blocks/endframe_side,141,19,0 +blocks/endframe_top,144,13,0 +blocks/farmland_dry,60,5,0 +blocks/farmland_wet,41,40,0 +blocks/fern,71,7,0 +blocks/fire_layer_0,30,5,162 +blocks/fire_layer_1,30,5,159 +blocks/flower_allium,71,7,0 +blocks/flower_blue_orchid,71,7,0 +blocks/flower_dandelion,71,7,0 +blocks/flower_houstonia,71,7,0 +blocks/flower_oxeye_daisy,71,7,0 +blocks/flower_pot,59,5,0 +blocks/flower_rose,71,7,0 +blocks/flower_tulip_orange,71,7,0 +blocks/flower_tulip_pink,71,7,0 +blocks/flower_tulip_red,71,7,0 +blocks/flower_tulip_white,71,7,0 +blocks/furnace_front_off,102,6,0 +blocks/furnace_front_on,102,7,25 +blocks/furnace_side,140,10,0 +blocks/furnace_top,114,10,0 +blocks/glass,210,100,0 +blocks/glass_black,230,100,0 +blocks/glass_blue,230,100,0 +blocks/glass_brown,230,100,0 +blocks/glass_cyan,230,100,0 +blocks/glass_gray,230,100,0 +blocks/glass_green,230,100,0 +blocks/glass_light_blue,230,100,0 +blocks/glass_lime,230,100,0 +blocks/glass_magenta,230,100,0 +blocks/glass_orange,230,100,0 +blocks/glass_pane_top,230,100,0 +blocks/glass_pane_top_black,230,100,0 +blocks/glass_pane_top_blue,230,100,0 +blocks/glass_pane_top_brown,230,100,0 +blocks/glass_pane_top_cyan,230,100,0 +blocks/glass_pane_top_gray,230,100,0 +blocks/glass_pane_top_green,230,100,0 +blocks/glass_pane_top_light_blue,230,100,0 +blocks/glass_pane_top_lime,230,100,0 +blocks/glass_pane_top_magenta,230,100,0 +blocks/glass_pane_top_orange,230,100,0 +blocks/glass_pane_top_pink,230,100,0 +blocks/glass_pane_top_purple,230,100,0 +blocks/glass_pane_top_red,230,100,0 +blocks/glass_pane_top_silver,230,100,0 +blocks/glass_pane_top_white,230,100,0 +blocks/glass_pane_top_yellow,230,100,0 +blocks/glass_pink,230,100,0 +blocks/glass_purple,230,100,0 +blocks/glass_red,230,100,0 +blocks/glass_silver,230,100,0 +blocks/glass_white,230,100,0 +blocks/glass_yellow,230,100,0 +blocks/glowstone,194,60,150 +blocks/gold_block,218,231,0 +blocks/gold_ore,96,37,0 +blocks/grass_side,50,4,0 +blocks/grass_side_overlay,12,5,0 +blocks/grass_side_snowed,146,15,0 +blocks/grass_top,12,5,0 +blocks/gravel,68,5,0 +blocks/hardened_clay,59,5,0 +blocks/hardened_clay_stained_black,59,5,0 +blocks/hardened_clay_stained_blue,59,5,0 +blocks/hardened_clay_stained_brown,59,5,0 +blocks/hardened_clay_stained_cyan,59,5,0 +blocks/hardened_clay_stained_gray,59,5,0 +blocks/hardened_clay_stained_green,59,5,0 +blocks/hardened_clay_stained_light_blue,59,5,0 +blocks/hardened_clay_stained_lime,59,5,0 +blocks/hardened_clay_stained_magenta,59,5,0 +blocks/hardened_clay_stained_orange,59,5,0 +blocks/hardened_clay_stained_pink,59,5,0 +blocks/hardened_clay_stained_purple,59,5,0 +blocks/hardened_clay_stained_red,59,5,0 +blocks/hardened_clay_stained_silver,59,5,0 +blocks/hardened_clay_stained_white,59,5,0 +blocks/hardened_clay_stained_yellow,59,5,0 +blocks/hay_block_side,112,12,0 +blocks/hay_block_top,114,13,0 +blocks/hopper_inside,71,230,0 +blocks/hopper_outside,173,230,0 +blocks/hopper_top,105,230,0 +blocks/ice,180,70,0 +blocks/ice_packed,168,40,0 +blocks/iron_bars,64,230,0 +blocks/iron_block,232,230,0 +blocks/iron_ore,95,15,0 +blocks/iron_trapdoor,214,230,0 +blocks/itemframe_background,0,0,0 +blocks/jukebox_side,89,13,0 +blocks/jukebox_top,83,13,0 +blocks/ladder,30,6,0 +blocks/lapis_block,222,20,0 +blocks/lapis_ore,96,10,0 +blocks/lava_flow,30,15,200 +blocks/lava_still,30,15,200 +blocks/leaves_acacia,60,10,0 +blocks/leaves_big_oak,105,4,0 +blocks/leaves_birch,73,5,0 +blocks/leaves_jungle,71,7,0 +blocks/leaves_oak,77,6,0 +blocks/leaves_spruce,59,6,0 +blocks/lever,97,10,0 +blocks/log_acacia,15,10,0 +blocks/log_acacia_top,9,10,0 +blocks/log_big_oak,26,10,0 +blocks/log_big_oak_top,20,10,0 +blocks/log_birch,24,5,0 +blocks/log_birch_top,20,10,0 +blocks/log_jungle,14,10,0 +blocks/log_jungle_top,20,10,0 +blocks/log_oak,18,10,0 +blocks/log_oak_top,20,10,0 +blocks/log_spruce,23,10,0 +blocks/log_spruce_top,21,10,0 +blocks/melon_side,156,14,0 +blocks/melon_stem_connected,18,10,0 +blocks/melon_stem_disconnected,18,10,0 +blocks/melon_top,153,14,0 +blocks/mob_spawner,71,230,0 +blocks/mushroom_block_inside,151,10,0 +blocks/mushroom_block_skin_brown,96,10,0 +blocks/mushroom_block_skin_red,148,10,0 +blocks/mushroom_block_skin_stem,142,10,0 +blocks/mushroom_brown,96,10,0 +blocks/mushroom_red,148,10,0 +blocks/mycelium_side,63,15,0 +blocks/mycelium_top,70,15,0 +blocks/nether_brick,37,15,0 +blocks/nether_wart_stage_0,11,5,0 +blocks/nether_wart_stage_1,30,5,0 +blocks/nether_wart_stage_2,39,5,0 +blocks/netherrack,20,10,0 +blocks/noteblock,89,13,0 +blocks/obsidian,210,120,0 +blocks/piston_bottom,80,4,0 +blocks/piston_inner,87,4,0 +blocks/piston_side,104,22,0 +blocks/piston_top_normal,109,25,0 +blocks/piston_top_sticky,116,28,0 +blocks/planks_acacia,92,11,0 +blocks/planks_big_oak,92,11,0 +blocks/planks_birch,92,11,0 +blocks/planks_jungle,92,11,0 +blocks/planks_oak,92,11,0 +blocks/planks_spruce,92,11,0 +blocks/portal,71,7,120 +blocks/potatoes_stage_0,71,7,0 +blocks/potatoes_stage_1,71,7,0 +blocks/potatoes_stage_2,71,7,0 +blocks/potatoes_stage_3,71,7,0 +blocks/prismarine_bricks,230,20,0 +blocks/prismarine_dark,194,26,0 +blocks/prismarine_rough,115,33,0 +blocks/pumpkin_face_off,56,15,0 +blocks/pumpkin_face_on,56,15,74 +blocks/pumpkin_side,52,15,0 +blocks/pumpkin_stem_connected,18,10,0 +blocks/pumpkin_stem_disconnected,18,10,0 +blocks/pumpkin_top,130,15,0 +blocks/quartz_block_bottom,220,60,0 +blocks/quartz_block_chiseled,220,60,0 +blocks/quartz_block_chiseled_top,220,60,0 +blocks/quartz_block_lines,220,60,0 +blocks/quartz_block_lines_top,220,60,0 +blocks/quartz_block_side,220,60,0 +blocks/quartz_block_top,220,60,0 +blocks/quartz_ore,45,10,0 +blocks/rail_activator,84,50,0 +blocks/rail_activator_powered,84,50,32 +blocks/rail_detector,102,62,0 +blocks/rail_detector_powered,102,62,32 +blocks/rail_golden,112,75,0 +blocks/rail_golden_powered,112,75,48 +blocks/rail_normal,85,50,0 +blocks/rail_normal_turned,85,50,0 +blocks/red_sand,32,2,0 +blocks/red_sandstone_bottom,52,10,0 +blocks/red_sandstone_carved,90,10,0 +blocks/red_sandstone_normal,43,10,0 +blocks/red_sandstone_smooth,90,10,0 +blocks/red_sandstone_top,128,15,0 +blocks/redstone_block,184,15,0 +blocks/redstone_dust_cross,100,5,0 +blocks/redstone_dust_cross_overlay,100,5,0 +blocks/redstone_dust_line,100,5,0 +blocks/redstone_dust_line_overlay,100,5,0 +blocks/redstone_lamp_off,191,20,0 +blocks/redstone_lamp_on,191,20,132 +blocks/redstone_ore,88,10,0 +blocks/redstone_torch_off,135,9,0 +blocks/redstone_torch_on,135,9,64 +blocks/reeds,71,7,0 +blocks/repeater_off,151,5,0 +blocks/repeater_on,151,5,32 +blocks/sand,46,8,0 +blocks/sandstone_bottom,52,8,0 +blocks/sandstone_carved,113,10,0 +blocks/sandstone_normal,43,10,0 +blocks/sandstone_smooth,90,10,0 +blocks/sandstone_top,128,15,0 +blocks/sapling_acacia,71,7,0 +blocks/sapling_birch,71,7,0 +blocks/sapling_jungle,71,7,0 +blocks/sapling_oak,71,7,0 +blocks/sapling_roofed_oak,71,7,0 +blocks/sapling_spruce,71,7,0 +blocks/sea_lantern,194,60,80 +blocks/slime,209,0,0 +blocks/snow,146,15,0 +blocks/soul_sand,35,15,0 +blocks/sponge,38,11,0 +blocks/sponge_wet,240,16,0 +blocks/stone,77,10,0 +blocks/stone_andesite,50,9,0 +blocks/stone_andesite_smooth,230,20,0 +blocks/stone_diorite,54,9,0 +blocks/stone_diorite_smooth,230,20,0 +blocks/stone_granite,38,9,0 +blocks/stone_granite_smooth,230,20,0 +blocks/stone_slab_side,120,20,0 +blocks/stone_slab_top,120,20,0 +blocks/stonebrick,70,10,0 +blocks/stonebrick_carved,58,10,0 +blocks/stonebrick_cracked,37,10,0 +blocks/stonebrick_mossy,53,9,0 +blocks/tallgrass,71,7,0 +blocks/tnt_bottom,78,5,0 +blocks/tnt_side,94,15,0 +blocks/tnt_top,61,5,0 +blocks/torch_on,135,9,128 +blocks/trapdoor,43,5,0 +blocks/trip_wire,230,20,0 +blocks/trip_wire_source,132,142,0 +blocks/vine,116,13,0 +blocks/water_flow,220,40,0 +blocks/water_still,220,40,0 +blocks/waterlily,78,15,0 +blocks/web,230,20,0 +blocks/wheat_stage_0,71,7,0 +blocks/wheat_stage_1,71,7,0 +blocks/wheat_stage_2,71,7,0 +blocks/wheat_stage_3,71,7,0 +blocks/wheat_stage_4,71,7,0 +blocks/wheat_stage_5,71,7,0 +blocks/wheat_stage_6,71,7,0 +blocks/wheat_stage_7,71,7,0 +blocks/wool_colored_black,50,10,0 +blocks/wool_colored_blue,50,10,0 +blocks/wool_colored_brown,50,10,0 +blocks/wool_colored_cyan,50,10,0 +blocks/wool_colored_gray,50,10,0 +blocks/wool_colored_green,50,10,0 +blocks/wool_colored_light_blue,50,10,0 +blocks/wool_colored_lime,50,10,0 +blocks/wool_colored_magenta,50,10,0 +blocks/wool_colored_orange,50,10,0 +blocks/wool_colored_pink,50,10,0 +blocks/wool_colored_purple,50,10,0 +blocks/wool_colored_red,50,10,0 +blocks/wool_colored_silver,50,10,0 +blocks/wool_colored_white,50,10,0 +blocks/wool_colored_yellow,50,10,0 +default,64,2,0 +items/apple,90,25,0 +items/apple_golden,150,231,0 +items/arrow,64,2,0 +items/barrier,64,2,0 +items/bed,80,15,0 +items/beef_cooked,70,10,0 +items/beef_raw,50,20,0 +items/blaze_powder,64,15,30 +items/blaze_rod,75,20,30 +items/boat,90,11,0 +items/bone,110,40,0 +items/book_enchanted,64,10,0 +items/book_normal,64,10,0 +items/book_writable,64,10,0 +items/book_written,64,10,0 +items/bow_pulling_0,80,15,0 +items/bow_pulling_1,80,15,0 +items/bow_pulling_2,80,15,0 +items/bow_standby,80,15,0 +items/bowl,90,10,0 +items/bread,75,5,0 +items/brewing_stand,64,10,0 +items/brick,40,8,0 +items/bucket_empty,110,230,0 +items/bucket_lava,110,230,0 +items/bucket_milk,110,230,0 +items/bucket_water,110,230,32 +items/cake,70,10,0 +items/carrot,64,5,0 +items/carrot_golden,90,231,0 +items/carrot_on_a_stick,80,10,0 +items/cauldron,75,230,0 +items/chainmail_boots,100,230,0 +items/chainmail_chestplate,100,230,0 +items/chainmail_helmet,100,230,0 +items/chainmail_leggings,100,230,0 +items/charcoal,130,20,0 +items/chicken_cooked,64,20,0 +items/chicken_raw,50,20,0 +items/clay_ball,120,13,0 +items/clock,90,230,0 +items/coal,130,20,0 +items/comparator,115,5,0 +items/compass,80,230,0 +items/cookie,64,5,0 +items/diamond,200,120,0 +items/diamond_axe,80,10,0 +items/diamond_boots,200,120,0 +items/diamond_chestplate,200,120,0 +items/diamond_helmet,200,120,0 +items/diamond_hoe,80,10,0 +items/diamond_horse_armor,200,120,0 +items/diamond_leggings,200,120,0 +items/diamond_pickaxe,80,10,0 +items/diamond_shovel,80,10,0 +items/diamond_sword,80,10,0 +items/door_acacia,66,25,0 +items/door_birch,66,25,0 +items/door_dark_oak,66,25,0 +items/door_iron,200,230,0 +items/door_jungle,66,25,0 +items/door_spruce,66,25,0 +items/door_wood,66,25,0 +items/dye_powder_black,64,5,0 +items/dye_powder_blue,64,5,0 +items/dye_powder_brown,64,5,0 +items/dye_powder_cyan,64,5,0 +items/dye_powder_gray,64,5,0 +items/dye_powder_green,64,5,0 +items/dye_powder_light_blue,64,5,0 +items/dye_powder_lime,64,5,0 +items/dye_powder_magenta,64,5,0 +items/dye_powder_orange,64,5,0 +items/dye_powder_pink,64,5,0 +items/dye_powder_purple,64,5,0 +items/dye_powder_red,64,5,0 +items/dye_powder_silver,64,5,0 +items/dye_powder_white,64,5,0 +items/dye_powder_yellow,64,5,0 +items/egg,75,15,0 +items/emerald,228,130,0 +items/ender_eye,80,10,40 +items/ender_pearl,80,10,0 +items/experience_bottle,210,100,0 +items/feather,64,10,0 +items/fireball,64,5,40 +items/fireworks,80,20,0 +items/fireworks_charge,70,15,0 +items/fireworks_charge_overlay,70,15,0 +items/fish_clownfish_raw,90,25,0 +items/fish_cod_cooked,70,10,0 +items/fish_cod_raw,90,25,0 +items/fish_pufferfish_raw,90,25,0 +items/fish_salmon_cooked,70,10,0 +items/fish_salmon_raw,90,25,0 +items/fishing_rod_cast,80,10,0 +items/fishing_rod_uncast,80,10,0 +items/flint,110,30,0 +items/flint_and_steel,90,230,0 +items/flower_pot,80,5,0 +items/ghast_tear,120,50,0 +items/glowstone_dust,120,20,70 +items/gold_axe,80,10,0 +items/gold_boots,200,231,0 +items/gold_chestplate,200,231,0 +items/gold_helmet,200,231,0 +items/gold_hoe,80,10,0 +items/gold_horse_armor,200,231,0 +items/gold_ingot,200,231,0 +items/gold_leggings,200,231,0 +items/gold_nugget,200,231,0 +items/gold_pickaxe,80,10,0 +items/gold_shovel,80,10,0 +items/gold_sword,80,10,0 +items/gunpowder,64,15,0 +items/hopper,90,230,0 +items/iron_axe,80,10,0 +items/iron_boots,200,230,0 +items/iron_chestplate,200,230,0 +items/iron_helmet,200,230,0 +items/iron_hoe,80,10,0 +items/iron_horse_armor,200,230,0 +items/iron_ingot,200,230,0 +items/iron_leggings,200,230,0 +items/iron_pickaxe,80,10,0 +items/iron_shovel,80,10,0 +items/iron_sword,80,10,0 +items/item_frame,70,20,0 +items/lead,64,5,0 +items/leather,70,15,0 +items/leather_boots,70,15,0 +items/leather_boots_overlay,70,15,0 +items/leather_chestplate,70,15,0 +items/leather_chestplate_overlay,70,15,0 +items/leather_helmet,70,15,0 +items/leather_helmet_overlay,70,15,0 +items/leather_leggings,70,15,0 +items/leather_leggings_overlay,70,15,0 +items/magma_cream,90,20,32 +items/map_empty,64,10,0 +items/map_filled,64,10,0 +items/melon,90,15,0 +items/melon_speckled,90,25,20 +items/minecart_chest,110,230,0 +items/minecart_command_block,110,230,0 +items/minecart_furnace,110,230,0 +items/minecart_hopper,110,230,0 +items/minecart_normal,110,230,0 +items/minecart_tnt,110,230,0 +items/mushroom_stew,90,10,0 +items/mutton_cooked,70,10,0 +items/mutton_raw,50,20,0 +items/name_tag,64,5,0 +items/nether_star,90,20,50 +items/nether_wart,45,20,0 +items/netherbrick,37,15,0 +items/painting,70,20,0 +items/paper,64,10,0 +items/porkchop_cooked,70,10,0 +items/porkchop_raw,50,20,0 +items/potato,60,10,0 +items/potato_baked,60,10,0 +items/potato_poisonous,60,5,0 +items/potion_bottle_drinkable,210,100,0 +items/potion_bottle_empty,210,100,0 +items/potion_bottle_splash,210,100,0 +items/potion_overlay,210,100,0 +items/prismarine_crystals,230,90,0 +items/prismarine_shard,230,20,0 +items/pumpkin_pie,90,25,0 +items/quartz,220,60,0 +items/rabbit_cooked,70,10,0 +items/rabbit_foot,64,5,0 +items/rabbit_hide,70,15,0 +items/rabbit_raw,50,20,0 +items/rabbit_stew,90,10,0 +items/record_11,135,40,0 +items/record_13,135,40,0 +items/record_blocks,135,40,0 +items/record_cat,135,40,0 +items/record_chirp,135,40,0 +items/record_far,135,40,0 +items/record_mall,135,40,0 +items/record_mellohi,135,40,0 +items/record_stal,135,40,0 +items/record_strad,135,40,0 +items/record_wait,135,40,0 +items/record_ward,135,40,0 +items/redstone_dust,70,10,0 +items/reeds,70,7,0 +items/repeater,115,5,0 +items/rotten_flesh,70,15,0 +items/saddle,70,15,0 +items/seeds_melon,64,5,0 +items/seeds_pumpkin,64,5,0 +items/seeds_wheat,64,5,0 +items/shears,90,230,0 +items/sign,90,15,0 +items/slimeball,150,50,0 +items/snowball,130,20,0 +items/spawn_egg,75,15,0 +items/spawn_egg_overlay,75,15,0 +items/spider_eye,100,30,0 +items/spider_eye_fermented,100,40,0 +items/stick,80,10,0 +items/stone_axe,80,10,0 +items/stone_hoe,80,10,0 +items/stone_pickaxe,80,10,0 +items/stone_shovel,80,10,0 +items/stone_sword,80,10,0 +items/string,80,25,0 +items/sugar,100,30,0 +items/wheat,110,15,0 +items/wood_axe,80,10,0 +items/wood_hoe,80,10,0 +items/wood_pickaxe,80,10,0 +items/wood_shovel,80,10,0 +items/wood_sword,80,10,0 +items/wooden_armorstand,80,10,0 diff --git a/sources/resources/assets/eagler/glsl/deferred/metals.csv b/sources/resources/assets/eagler/glsl/deferred/metals.csv new file mode 100644 index 0000000..80c2dbb --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/metals.csv @@ -0,0 +1,9 @@ +Metal,ID,Nr,Ng,Nb,Kr,Kg,Kb +Iron,230,2.9114,2.9497,2.5845,3.0893,2.9318,2.7670 +Gold,231,0.18299,0.42108,1.3734,3.4242,2.3459,1.7704 +Aluminum,232,1.3456,0.96521,0.61722,7.4746,6.3995,5.3031 +Chrome,233,3.1071,3.1812,2.3230,3.3314,3.3291,3.1350 +Copper,234,0.27105,0.67693,1.3164,3.6092,2.6248,2.2921 +Lead,235,1.9100,1.8300,1.4400,3.5100,3.4000,3.1800 +Platinum,236,2.3757,2.0847,1.8453,4.2655,3.7153,3.1365 +Silver,237,0.15943,0.14512,0.13547,3.9291,3.1900,2.3808 \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/moon_render.fsh b/sources/resources/assets/eagler/glsl/deferred/moon_render.fsh new file mode 100644 index 0000000..f2c234b --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/moon_render.fsh @@ -0,0 +1,50 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; +in vec3 v_position3f; + +layout(location = 0) out vec4 output4f; + +uniform vec3 u_moonColor3f; +uniform vec3 u_lightDir3f; + +uniform sampler2D u_moonTextures; +uniform sampler2D u_cloudsTexture; + +void main() { + gl_FragDepth = 0.0; + vec4 color4f = texture(u_moonTextures, v_position2f); + if(color4f.a < 0.99) { + discard; + } + vec3 moonNormal3f; + moonNormal3f.xy = color4f.rg * 2.0 - 1.0; + moonNormal3f.z = sqrt(1.0 - dot(moonNormal3f.xy, moonNormal3f.xy)); + float NdotV = dot(moonNormal3f, u_lightDir3f); + output4f = vec4(u_moonColor3f * (color4f.b * color4f.b * mix(max(NdotV, 0.0), max(NdotV + 0.45, 0.0) * 0.5f, max(u_lightDir3f.z * u_lightDir3f.z * -u_lightDir3f.z, 0.0))), 0.0); + vec3 viewDir = normalize(v_position3f); + if(viewDir.y < 0.01) { + return; + } + vec2 cloudSampleCoord2f = (viewDir.xz / (viewDir.y + 1.0)) * 0.975 * 0.5 + 0.5; + vec4 cloudSample = textureLod(u_cloudsTexture, cloudSampleCoord2f, 0.0); + output4f.rgb = mix(output4f.rgb, output4f.rgb * max(cloudSample.a * 1.25 - 0.25, 0.0), smoothstep(0.0, 1.0, min(viewDir.y * 8.0, 1.0))); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/moon_render.vsh b/sources/resources/assets/eagler/glsl/deferred/moon_render.vsh new file mode 100644 index 0000000..015bceb --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/moon_render.vsh @@ -0,0 +1,35 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec2 a_position2f; + +out vec2 v_position2f; +out vec3 v_position3f; + +uniform mat4 u_modelMatrix4f; +uniform mat4 u_viewMatrix4f; +uniform mat4 u_projMatrix4f; + +void main() { + v_position2f = a_position2f * 0.5 + 0.5; + v_position3f = (u_modelMatrix4f * vec4(a_position2f, -13.0, 1.0)).xyz; + gl_Position = u_viewMatrix4f * vec4(v_position3f, 0.0); + gl_Position = u_projMatrix4f * vec4(gl_Position.xyz, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/particles_s.png b/sources/resources/assets/eagler/glsl/deferred/particles_s.png new file mode 100644 index 0000000000000000000000000000000000000000..8382136f9fc2ff49949fc53c8f2baaf131217091 GIT binary patch literal 528 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5dq9|R>YgG`1_s7M zo-U3d6}R5rRrF>~lsNG5`>{`dSeOqga5pI&6K!@B(~~lp>08&Bt#<-Y@KZXFlUN=-QFkvFQ4E2xV}~{aaLav`-kb1=SSPe zzd!ru+YVL*2By1AJ+;ChZD!9+4}3ga`>mxv{@_@S9=s+drJ`>wiA(S2w@;`05L--+K;pXK#oTPPq4SdFAr_r%G%a zc6{i4xpZo`SVOnGO~cVv^MB0unOq*YF1X#ma6`rQcgfE4+!ech=lwQkgxRIQaLsvh zP5dY8lFz?6{;L0GQG+@H=<5Sr8mEk|P83hD=-KO^$OQ5S#6b#Ep8d1<#>C?b 0.0) { + emission = textureLod(u_gbufferMaterialTexture, alignedUV, 0.0).b; + }else { + emission = textureLod(u_gbufferDepthTexture, alignedUV, 0.0).r <= 0.0000001 ? 10.0 : 0.0; + } + float f = dot(inputColor.rgb, vec3(0.2126, 0.7152, 0.0722)) * (5.0 + emission * 15.0); + if(f > 2.0 + exposure) { + output4f = vec4(min(inputColor.rgb, vec3(5.0)) * (0.75 + exposure * 1.5) * min(f - 2.0 - exposure, 1.0), 1.0); + }else { + output4f = vec4(0.0); + } +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_exposure_avg.fsh b/sources/resources/assets/eagler/glsl/deferred/post_exposure_avg.fsh new file mode 100644 index 0000000..473e3cf --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_exposure_avg.fsh @@ -0,0 +1,44 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out float exposureOut1f; + +uniform sampler2D u_inputTexture; +uniform vec4 u_sampleOffset4f; + +#ifdef CALCULATE_LUMINANCE +#define TAKE_SAMPLE(samplerIn, posIn) dot(textureLod(samplerIn, posIn, 0.0).rgb, vec3(0.299, 0.587, 0.114)) +#else +#define TAKE_SAMPLE(samplerIn, posIn) textureLod(samplerIn, posIn, 0.0).r +#endif + +void main() { + + vec2 pixelPos = floor(v_position2f / u_sampleOffset4f.xy); + + float a = min(TAKE_SAMPLE(u_inputTexture, (pixelPos + vec2(0.25, 0.25)) * u_sampleOffset4f.zw), 250.0); + a += min(TAKE_SAMPLE(u_inputTexture, (pixelPos + vec2(0.75, 0.25)) * u_sampleOffset4f.zw), 250.0); + a += min(TAKE_SAMPLE(u_inputTexture, (pixelPos + vec2(0.75, 0.75)) * u_sampleOffset4f.zw), 250.0); + a += min(TAKE_SAMPLE(u_inputTexture, (pixelPos + vec2(0.25, 0.75)) * u_sampleOffset4f.zw), 250.0); + + exposureOut1f = a * 0.25; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_exposure_final.fsh b/sources/resources/assets/eagler/glsl/deferred/post_exposure_final.fsh new file mode 100644 index 0000000..0f250c0 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_exposure_final.fsh @@ -0,0 +1,40 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out float exposureOut1f; + +uniform sampler2D u_inputTexture; +uniform vec2 u_inputSize2f; + +void main() { + + float a = 0.0; + float b = 0.0; + for(vec2 v = vec2(0.0, u_inputSize2f * 0.5); v.y < 1.0; v.y += u_inputSize2f.y) { + for(v.x = u_inputSize2f.x * 0.5; v.x < 1.0; v.x += u_inputSize2f.x) { + a += textureLod(u_inputTexture, v, 0.0).r * (1.0 - length(v - 0.5)); + b += 1.0; + } + } + + exposureOut1f = a / b; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_fxaa.fsh b/sources/resources/assets/eagler/glsl/deferred/post_fxaa.fsh new file mode 100644 index 0000000..7abf36e --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_fxaa.fsh @@ -0,0 +1,273 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +/* + * This file was modified by lax1dude to remove dead code + * + * Original: https://gist.github.com/kosua20/0c506b81b3812ac900048059d2383126 + * + */ + +/* + * ============================================================================ + * + * + * NVIDIA FXAA 3.11 by TIMOTHY LOTTES + * + * + * ------------------------------------------------------------------------------ + * COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. + * ------------------------------------------------------------------------------ + * TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED + * *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS + * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA + * OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR + * LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, + * OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE + * THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. + * + */ + + +precision lowp int; +precision mediump float; +precision mediump sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_screenTexture; +uniform vec2 u_screenSize2f; + +#ifndef FXAA_GREEN_AS_LUMA + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 +#endif + +#ifndef FXAA_DISCARD + // 1 = Use discard on pixels which don't need AA. + // 0 = Return unchanged color on pixels which don't need AA. + #define FXAA_DISCARD 0 +#endif + +/*============================================================================ + API PORTING +============================================================================*/ + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D +/*--------------------------------------------------------------------------*/ + + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaLuma(rgba) rgba.a + +/*============================================================================ + FXAA3 CONSOLE - PC VERSION +============================================================================*/ +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( + // See FXAA Quality FxaaPixelShader() source for docs on Inputs! + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy__} = upper left of pixel + // {__zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {___a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x___} = -N/screenWidthInPixels + // {_y__} = -N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x___} = -2.0/screenWidthInPixels + // {_y__} = -2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin +) { +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); + FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); + FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); + FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); + FxaaFloat lumaM = FxaaLuma(rgbyM); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); + lumaNe += 1.0/384.0; + FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); + FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); + FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ + FxaaFloat lumaMinM = min(lumaMin, lumaM); + FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); + FxaaFloat lumaMaxM = max(lumaMax, lumaM); + FxaaFloat dirSwMinusNe = lumaSw - lumaNe; + FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; + FxaaFloat dirSeMinusNw = lumaSe - lumaNw; + if(lumaMaxSubMinM < lumaMaxScaledClamped) + { + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif + } +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir; + dir.x = dirSwMinusNe + dirSeMinusNw; + dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir1 = normalize(dir.xy); + FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); + FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ + FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; + FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 dir2x = dir2 * fxaaConsoleRcpFrameOpt2.zw; + FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2x); + FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2x); +/*--------------------------------------------------------------------------*/ + FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; + FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ + float lumaB = FxaaLuma(rgbyB); + if((lumaB < lumaMin) || (lumaB > lumaMax)) rgbyB.xyz = rgbyA.xyz * 0.5; + return rgbyB; +} +/*==========================================================================*/ + +#define edgeSharpness 3.0 +#define edgeThreshold 0.15 +#define edgeThresholdMin 0.05 + +void main(){ + vec2 screenSize05 = 0.5 * u_screenSize2f; + + vec4 posPos; + posPos.xy = v_position2f; + posPos.zw = v_position2f + u_screenSize2f; + + vec4 rcpFrameOpt; + rcpFrameOpt.xy = -screenSize05; + rcpFrameOpt.zw = screenSize05; + + output4f = vec4(FxaaPixelShader(v_position2f + screenSize05, posPos, u_screenTexture, rcpFrameOpt, rcpFrameOpt * 4.0, edgeSharpness, edgeThreshold, edgeThresholdMin).rgb, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_lens_distort.fsh b/sources/resources/assets/eagler/glsl/deferred/post_lens_distort.fsh new file mode 100644 index 0000000..d2d6922 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_lens_distort.fsh @@ -0,0 +1,38 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_inputTexture; + +vec2 distortUV(in vec2 uv, in float k){ + vec2 t = uv - 0.5; + return dot(t, t) * k * t + t + 0.5; +} + +#define DISTORT_AMOUNT -0.05 + +void main() { + output4f = vec4(textureLod(u_inputTexture, distortUV(v_position2f, DISTORT_AMOUNT + 0.01), 0.0).r, + textureLod(u_inputTexture, distortUV(v_position2f, DISTORT_AMOUNT), 0.0).ga, + textureLod(u_inputTexture, distortUV(v_position2f, DISTORT_AMOUNT - 0.01), 0.0).b).rgab; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.fsh b/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.fsh new file mode 100644 index 0000000..80a949a --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.fsh @@ -0,0 +1,34 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision mediump float; +precision mediump sampler2D; + +layout(location = 0) out vec4 output4f; + +in vec2 v_texcoord2f; +in vec3 v_color3f; +in float v_occlusion1f; + +uniform sampler2D u_flareTexture; + +uniform vec3 u_flareColor3f; + +void main() { + vec3 color3f = vec3(texture(u_flareTexture, v_texcoord2f).r); + output4f = vec4(color3f * color3f * v_color3f * v_occlusion1f * u_flareColor3f, 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh b/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh new file mode 100644 index 0000000..65584f9 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh @@ -0,0 +1,65 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec2 a_position2f; + +layout(location = 1) in vec2 e_elementOffsetScale; +layout(location = 2) in vec4 e_elementTexture4f; +layout(location = 3) in vec3 e_elementColor3f; + +out vec2 v_texcoord2f; +out vec3 v_color3f; +out float v_occlusion1f; + +uniform sampler2D u_exposureValue; +uniform sampler2D u_sunOcclusionValue; + +uniform vec2 u_sunPosition2f; +uniform float u_aspectRatio1f; +uniform float u_baseScale1f; + +#define FAKE_SIN(valueIn, valueOut)\ + valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ + valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; + +void main() { + v_occlusion1f = max(textureLod(u_sunOcclusionValue, vec2(0.5, 0.5), 0.0).r * 1.5 - 0.5, 0.0); + if(v_occlusion1f == 0.0) { + gl_Position = vec4(-10.0, -10.0, -10.0, 1.0); + return; + } + + v_texcoord2f = e_elementTexture4f.xy + (a_position2f * 0.5 + 0.5) * e_elementTexture4f.zw; + + float r = textureLod(u_exposureValue, vec2(0.5, 0.5), 0.0).r * 7.5; + + mat2 rotationMatrix; + FAKE_SIN(vec2(r + 1.570795, r), rotationMatrix[0]) + rotationMatrix[1].x = -rotationMatrix[0].y; + rotationMatrix[1].y = rotationMatrix[0].x; + + vec2 transformedVertex = rotationMatrix * (a_position2f * u_baseScale1f * e_elementOffsetScale.y / (4.0 + r * 0.75)); + transformedVertex.x *= u_aspectRatio1f; + transformedVertex += u_sunPosition2f * (1.0 - e_elementOffsetScale.x); + + v_color3f = e_elementColor3f * (0.05 + dot(u_sunPosition2f, u_sunPosition2f)); + + gl_Position = vec4(transformedVertex, 0.0, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.fsh b/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.fsh new file mode 100644 index 0000000..2eeeb63 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.fsh @@ -0,0 +1,34 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision mediump float; +precision mediump sampler2D; + +layout(location = 0) out vec4 output4f; + +in vec2 v_texcoord2f; +in float v_occlusion1f; + +uniform sampler2D u_flareTexture; + +uniform vec3 u_flareColor3f; + +void main() { + vec3 color = vec3(texture(u_flareTexture, v_texcoord2f).r); + color = length(u_flareColor3f * color) * vec3(0.0, 0.05, 0.3) + u_flareColor3f * color * color * color; + output4f = vec4(color * v_occlusion1f, 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.vsh b/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.vsh new file mode 100644 index 0000000..2436095 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_lens_streaks.vsh @@ -0,0 +1,40 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec2 a_position2f; +layout(location = 1) in vec2 a_texcoord2f; + +out vec2 v_texcoord2f; +out float v_occlusion1f; + +uniform sampler2D u_sunOcclusionValue; + +uniform mat3 u_sunFlareMatrix3f; + +void main() { + v_occlusion1f = max(textureLod(u_sunOcclusionValue, vec2(0.5, 0.5), 0.0).r * 1.5 - 0.5, 0.0); + if(v_occlusion1f == 0.0) { + gl_Position = vec4(-10.0, -10.0, -10.0, 1.0); + return; + } + v_texcoord2f = a_texcoord2f; + vec3 pos3f = u_sunFlareMatrix3f * vec3(a_position2f, 1.0); + gl_Position = vec4(pos3f.x, pos3f.y, 0.0, pos3f.z); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/post_tonemap.fsh b/sources/resources/assets/eagler/glsl/deferred/post_tonemap.fsh new file mode 100644 index 0000000..27798fe --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/post_tonemap.fsh @@ -0,0 +1,55 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_lightingHDRFramebufferTexture; +uniform sampler2D u_framebufferLumaAvgInput; +uniform sampler2D u_ditherTexture; +uniform vec3 u_exposure3f; +uniform vec2 u_ditherScale2f; + +void main() { + float lumaHDR = textureLod(u_framebufferLumaAvgInput, vec2(0.5), 0.0).r; + vec3 input3f = textureLod(u_lightingHDRFramebufferTexture, v_position2f, 0.0).rgb; + + input3f /= (0.1 + min(lumaHDR * 6.0, 4.0)); + + input3f *= u_exposure3f; + + // ACES, modified to approximate gamma correction + const float a = 1.22; + const float b = 1.78; + const float c = 1.22; + const float d = 1.79; + const float e = 0.29; + + input3f = clamp((input3f * (a * input3f + b)) / (input3f * (c * input3f + d) + e), 0.0, 1.0); + + // desaturate a bit, makes it look like less of a cartoon + float sat = 0.8; + float luma = dot(input3f, vec3(0.299, 0.587, 0.114)); + input3f = (input3f - luma) * sat + luma; + input3f += textureLod(u_ditherTexture, v_position2f * u_ditherScale2f, 0.0).r / 255.0; + + output4f = vec4(clamp(input3f, 0.0, 1.0), luma); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/rain.png b/sources/resources/assets/eagler/glsl/deferred/rain.png new file mode 100644 index 0000000000000000000000000000000000000000..fe8d59c248feb86a1e61a7f87e6dc2da6dc29eb9 GIT binary patch literal 2046 zcmVpMut`KgRCwC$ojq(@RTRhXyRUInCry*k3{+~U(pIf*znEJIDj~WO zBq|o95?GKrR2>*#0fZC=HUtw>0jUx!rCTt`s;AnCgK2Qgy^o=# za$VbbANPITbN*ZWZ0Gs+{^#CvzZvTg0Js|)8)Hm^0AM!E^?s_=YTq!8;@vMyOiXNP z`fj)Th0V>)tAnn4)ZdW;(5Q{>7lww0T7#~8)T2xQ5JLRk{aU--ZVtNcQSFW}dLzva zU_BhL6ZSilQkz)`ffqC~GV*iS@0gmJ`k~{`$69X?09=Ml900~U{@y_cfH5}HSyN#I zFr5_utE;Qmq5yD2L){#Uq?B3SWhhgDP=C9a$!14t*a

    9Ez|&n5WnnFgS?&z0QGwP!hp|&nS;M469C%nc5c8^{w&EvX=P<)K8_I3 zzEmCn4usfF` z6$k)J_{^d6=g;3v6o75p4Igoq=HqH=y8-}!_q#9n?0HFT-{Niqw*2Xa#CG?EnVA_s zr%tJ~{qSB7wcnFF${71MqUuze9LJgS`4QXejZZVi!j1(-?f}lY-|+xX50wicZnE&h z*4(E(eQ$uKl=3?sFy#5hg%H={bU=`Oz&ZCFWotn?LV&jSW&QX|al4UD+1yFbnM8#w@_l+Io0^bd^0&`q^JV zUI>n32cT^dweDI#`)PAM33IM(S30l#d{hRcECe>N1886eP$vhZKzHxnoki^c*LBUF zUb9=XJ4pw`rGbquDJ72uK(Sc7kPv`@jjn!c7NT%KQp02ehv?6pJ9pFc5C}9t%hPfr zNjXnDfRiUr{)XKF47CFiR1-UZ26h0!Qf}GjtyaIwQZ*QbrceWLU3Z@`02US&e2>XnmSqlr;o)H(zyZn_0IgO_1#m!S z`WbeeB^Ja1J3BkgEIHulElr1&;Tlx%C8>V z1==@P0Dw?OcX7@qLjeGQ!%8Vn8>L#76~%;!u$#2zLp#97!N^g}847!JmlXtY$Mi+%vm$bJFvIIa%nd_0%%%A~a+x81t>zOlWRx<%WN6Iaw%=d7> csW9L9AKa+Bt{W;$I{*Lx07*qoM6N<$f(ikVOaK4? literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_control.fsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_control.fsh new file mode 100644 index 0000000..e914e71 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_control.fsh @@ -0,0 +1,194 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 realisticWaterReflectionOutput4f; +layout(location = 1) out vec4 realisticWaterHitVectorOutput4f; +layout(location = 2) out vec4 realisticWaterRefraction4f; + +uniform sampler2D u_gbufferColorTexture4f; +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_realisticWaterMaskNormal; +uniform sampler2D u_realisticWaterDepthTexture; +uniform sampler2D u_lastFrameReflectionInput4f; +uniform sampler2D u_lastFrameHitVectorInput4f; +uniform sampler2D u_lastFrameColorTexture; +uniform sampler2D u_lastFrameDepthTexture; + +uniform mat4 u_inverseProjectionMatrix4f; +uniform mat4 u_inverseViewProjMatrix4f; +uniform mat4 u_reprojectionMatrix4f; +uniform mat4 u_lastInverseProjMatrix4f; +uniform mat4 u_reprojectionInverseViewMatrix4f; +uniform mat4 u_projectionMatrix4f; +uniform mat4 u_viewToPreviousProjMatrix4f; + +// x = near plane +// y = far plane +// z = near plane * 2 +// w = far plane - near plane +uniform vec4 u_nearFarPlane4f; + +uniform vec4 u_pixelAlignment4f; + +uniform vec4 u_refractFogColor4f; + +#define reprojDepthLimit 0.25 + +#define GET_LINEAR_DEPTH_FROM_VALUE(depthSample) (u_nearFarPlane4f.z / (u_nearFarPlane4f.y + u_nearFarPlane4f.x + (depthSample * 2.0 - 1.0) * u_nearFarPlane4f.w)) + +#define CREATE_DEPTH_MATRIX(matrix4fInput) mat4x2(matrix4fInput[0].zw,matrix4fInput[1].zw,matrix4fInput[2].zw,matrix4fInput[3].zw) + +void main() { + vec2 v_position2f2 = (floor(v_position2f * u_pixelAlignment4f.xy) + 0.25) * (2.0 / u_pixelAlignment4f.zw); + realisticWaterReflectionOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + realisticWaterHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + realisticWaterRefraction4f = vec4(0.0, 0.0, 0.0, 0.0); + vec4 waterSurfaceNormal4f = textureLod(u_realisticWaterMaskNormal, v_position2f2, 0.0); + + if(waterSurfaceNormal4f.a <= 0.0) { + return; + } + + float gbufferDepth = textureLod(u_gbufferDepthTexture, v_position2f2, 0.0).r; + vec4 gbufferDepthClipSpace4f = vec4(v_position2f2, gbufferDepth, 1.0); + gbufferDepthClipSpace4f.xyz *= 2.0; + gbufferDepthClipSpace4f.xyz -= 1.0; + vec2 gbufferDepthView = CREATE_DEPTH_MATRIX(u_inverseProjectionMatrix4f) * gbufferDepthClipSpace4f; + gbufferDepthView.x /= gbufferDepthView.y; + + float waterSurfaceDepth = textureLod(u_realisticWaterDepthTexture, v_position2f2, 0.0).r; + vec4 waterSurfaceDepthClipSpace4f = vec4(gbufferDepthClipSpace4f.xy, waterSurfaceDepth * 2.0 - 1.0, 1.0); + vec2 waterDepthView = CREATE_DEPTH_MATRIX(u_inverseProjectionMatrix4f) * waterSurfaceDepthClipSpace4f; + waterDepthView.x /= waterDepthView.y; + + float fog = clamp(1.25 - 1.0 / exp((waterDepthView.x - gbufferDepthView.x) * 0.05), 0.0, 1.0); + + vec3 refractColor3f = textureLod(u_gbufferColorTexture4f, v_position2f2, 0.0).rgb; + refractColor3f *= mix(vec3(1.0), vec3(0.02, 0.025, 0.12), min(fog + 0.1, 1.0)); + vec3 fogColor3f = u_refractFogColor4f.rgb * (waterSurfaceNormal4f.a * u_refractFogColor4f.a * 0.95 + 0.05); + realisticWaterRefraction4f = vec4(mix(refractColor3f, fogColor3f, fog), 1.0); + + vec4 fragPos4f = u_inverseViewProjMatrix4f * waterSurfaceDepthClipSpace4f; + fragPos4f.xyz /= fragPos4f.w; + fragPos4f.w = 1.0; + vec4 reprojPos4f = u_reprojectionMatrix4f * fragPos4f; + vec4 reprojClipPos4f = vec4(reprojPos4f.xyz / reprojPos4f.w, 1.0); + reprojPos4f = reprojClipPos4f; + reprojPos4f.xyz *= 0.5; + reprojPos4f.xyz += 0.5; + reprojPos4f.xy = (floor(reprojPos4f.xy * u_pixelAlignment4f.zw) + 0.5) * (0.5 / u_pixelAlignment4f.xy); + if(reprojPos4f.xy != clamp(reprojPos4f.xy, vec2(0.001), vec2(0.999)) || abs(GET_LINEAR_DEPTH_FROM_VALUE(textureLod(u_lastFrameDepthTexture, reprojPos4f.xy, 0.0).r) - GET_LINEAR_DEPTH_FROM_VALUE(reprojPos4f.z)) > reprojDepthLimit) { + realisticWaterHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 50.0); + return; + } + + vec4 lastFrameHitVector4f = textureLod(u_lastFrameHitVectorInput4f, reprojPos4f.xy, 0.0); + if(lastFrameHitVector4f.g <= 0.0) { + realisticWaterReflectionOutput4f = textureLod(u_lastFrameReflectionInput4f, reprojPos4f.xy, 0.0); + realisticWaterHitVectorOutput4f = vec4(0.0, 0.0, 0.0, lastFrameHitVector4f.a); + return; + } + + realisticWaterReflectionOutput4f = vec4(0.0, 0.0, 0.0, 1.0); + + lastFrameHitVector4f.g -= 0.004; + + vec4 lastFrameFragPosView4f = u_lastInverseProjMatrix4f * vec4(reprojClipPos4f.xyz, 1.0); + lastFrameFragPosView4f.xyz /= lastFrameFragPosView4f.w; + lastFrameFragPosView4f.w = 1.0; + vec4 lastFrameHitPos4f = vec4(lastFrameFragPosView4f.xyz + lastFrameHitVector4f.xyz, 1.0); + + vec4 thisFrameHitPos4f = u_reprojectionInverseViewMatrix4f * lastFrameHitPos4f; + thisFrameHitPos4f.xyz /= thisFrameHitPos4f.w; + thisFrameHitPos4f.w = 1.0; + + vec4 thisFrameHitPosProj4f = u_projectionMatrix4f * thisFrameHitPos4f; + thisFrameHitPosProj4f.xyz /= thisFrameHitPosProj4f.w; + thisFrameHitPosProj4f.w = 1.0; + vec3 thisFrameHitPosProjTex3f = thisFrameHitPosProj4f.xyz * 0.5 + 0.5; + + if(thisFrameHitPosProjTex3f.xy != clamp(thisFrameHitPosProjTex3f.xy, vec2(0.001), vec2(0.999))) { + return; + } + + float fragDepthSample = textureLod(u_gbufferDepthTexture, thisFrameHitPosProjTex3f.xy, 0.0).r * 2.0 - 1.0; + vec2 thisFrameHitPosProjDepthPos = CREATE_DEPTH_MATRIX(u_inverseProjectionMatrix4f) * vec4(thisFrameHitPosProj4f.xy, fragDepthSample, 1.0); + thisFrameHitPosProjDepthPos.x /= thisFrameHitPosProjDepthPos.y; + + if(thisFrameHitPosProjDepthPos.x - thisFrameHitPos4f.z - 0.125 < 0.0) { + return; + } + + waterSurfaceNormal4f.xyz *= 2.0; + waterSurfaceNormal4f.xyz -= 1.0; + + vec3 lastFrameHitPosNormal3f = textureLod(u_realisticWaterMaskNormal, thisFrameHitPosProjTex3f.xy, 0.0).rgb; + lastFrameHitPosNormal3f *= 2.0; + lastFrameHitPosNormal3f -= 1.0; + + vec4 fragPosView4f = u_inverseProjectionMatrix4f * waterSurfaceDepthClipSpace4f; + fragPosView4f.xyz /= fragPosView4f.w; + fragPosView4f.w = 1.0; + + vec3 rayOrigin = fragPosView4f.xyz; + vec3 planePos = thisFrameHitPos4f.xyz; + vec3 planeNormal = lastFrameHitPosNormal3f; + + vec3 newRayDirection = reflect(normalize(rayOrigin), waterSurfaceNormal4f.xyz); + + float dist = dot(planeNormal, newRayDirection); + if(dist > 0.9) { + return; + } + + dist = dot(planeNormal, planePos - rayOrigin) / dist; + if(dist < 0.0) { + return; + } + + realisticWaterHitVectorOutput4f = vec4(newRayDirection * dist, 1.0); + realisticWaterHitVectorOutput4f.y += 0.004; + + thisFrameHitPosProj4f = u_viewToPreviousProjMatrix4f * vec4(rayOrigin + newRayDirection * dist, 1.0); + thisFrameHitPosProj4f.xyz /= thisFrameHitPosProj4f.w; + thisFrameHitPosProj4f.w = 1.0; + thisFrameHitPosProjTex3f = thisFrameHitPosProj4f.xyz * 0.5 + 0.5; + + if(thisFrameHitPosProjTex3f.xy != clamp(thisFrameHitPosProjTex3f.xy, vec2(0.001), vec2(0.999))) { + return; + } + + fragDepthSample = textureLod(u_lastFrameDepthTexture, thisFrameHitPosProjTex3f.xy, 0.0).r * 2.0 - 1.0; + + vec2 thisFrameHitPosProjPos = CREATE_DEPTH_MATRIX(u_lastInverseProjMatrix4f) * thisFrameHitPosProj4f; + thisFrameHitPosProjPos.x /= thisFrameHitPosProjPos.y; + + thisFrameHitPosProjDepthPos = CREATE_DEPTH_MATRIX(u_lastInverseProjMatrix4f) * vec4(thisFrameHitPosProj4f.xy, fragDepthSample, 1.0); + thisFrameHitPosProjDepthPos.x /= thisFrameHitPosProjDepthPos.y; + + if(thisFrameHitPosProjDepthPos.x - thisFrameHitPosProjPos.x - 0.125 < 0.0) { + realisticWaterHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + + realisticWaterReflectionOutput4f = vec4(textureLod(u_lastFrameColorTexture, thisFrameHitPosProjTex3f.xy, 0.0).rgb, 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.fsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.fsh new file mode 100644 index 0000000..bf50e7a --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.fsh @@ -0,0 +1,40 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +layout(location = 0) out vec4 output4f; + +#ifdef COMPILE_NORMAL_ATTRIB +in vec3 v_normal3f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 v_lightmap2f; +#else +uniform vec2 u_textureCoords02; +#endif + +void main() { +#ifdef COMPILE_NORMAL_ATTRIB + output4f = vec4(v_normal3f * 0.5 + 0.5, +#else + output4f = vec4(0.0, 1.0, 0.0, +#endif +#ifdef COMPILE_LIGHTMAP_ATTRIB + v_lightmap2f.y * v_lightmap2f.y * 0.99 + 0.01); +#else + u_textureCoords02.y * u_textureCoords02.y * 0.99 + 0.01); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.vsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.vsh new file mode 100644 index 0000000..ffb9427 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_mask.vsh @@ -0,0 +1,44 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +out vec3 v_normal3f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +out vec2 v_lightmap2f; +uniform mat4 u_textureMat4f02; +#endif + +uniform mat4 u_modelviewMat4f; +uniform mat4 u_modelviewProjMat4f; + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { +#ifdef COMPILE_NORMAL_ATTRIB + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); +#endif +#ifdef COMPILE_LIGHTMAP_ATTRIB + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; +#endif + gl_Position = u_modelviewProjMat4f * vec4(a_position3f, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.bmp b/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.bmp new file mode 100644 index 0000000..324756b --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.bmp @@ -0,0 +1 @@ +_[_]a_gaqa|b†cŽf“j”p’w‡†}q—ežZ¡S PšQ‘U…\xcngihggjfpexf‚iŒn•v››•™Š¡~¦s¥lŸi•kˆq||sˆo“mšmœp™u’{‡zˆmŒb^Š^„\|[tZmYfYbY_[_]a_gajtpnslwo|t€z„‡‚‡‚„€z{qvhr_qVqQrNtPvTw[wdukqpout~|ˆ†’™—œ™š“‘Š‡€z{uxrvpuptqrrnqgobjbdfan`vaf†nŠwŠ„‰{Žq‘i‘cŽa‰aƒe{jtpnslwomkonqpvrqˆo‘n–m™o˜r”wŽ~††|o™d¡[¥V¥U Y—a‹jsvwpwmtmqomtk{k‚nˆt~‹ˆ˜~£t©jªd¥b›elwwƒqn—mœoœs˜x†„|ˆs‰p†on|lvkrjoimjmkonqpvrkzruvtzx„‡ˆ‹‘‹’ˆ„‰~€xuskqbq[sXuXw\yczjyqvutyxŠ‡’˜”›—š––‘‡‡~yywvwuzv|w~yz|yuvnongqaw]~^…b‹is‹~„‡yn‘e’_^`‡e€kzruvtzxyz|}€€„€‹~’y˜u›q›o—p‘rˆx€€vŠj•`ŸZ¥X§Z¤ak“v‰€€„yƒtqzpurquoyp}v€€{›r§i¯a°\¬\£`—hŠs€€yŒt–qœpŸržu™y’}‰‚€€}z~w|uztytxvyyz|}€€„€sƒ{€€€ƒ„ˆ‹“’š”ž“ž‘›Œ”†Š€€{uylyezb}bf‚mƒuƒ|€€~ƒ€‰…‹•™“™“–‘‰‰€€wxsuttwu|y}†ˆƒ†ƒ€€ywwnye}_‚]‡^‹d‹mˆw€€t‡jŒb^_cŒj‡sƒ{€€€ƒ„ƒ†ˆˆŒŠ‘Š–†š€œz›t—om‡n}styk„aZœV¥W©\ªe¥qž}•†ŒŠ…‰~…yuystsrtsvyw‚vržjªb²[´W±X©\ep†|€ˆy’ušržqŸrs˜u’wv‹u‹sŠrˆs‡u†y…~…ƒ†ˆˆŒŠ‘Š€ŠŽŽ’’—˜›žŸ£ ¦ ¥ ˜™“…ˆ{‡r‡mˆjŠlqx€ˆ‹Œˆ‰”Œ˜Ž›œ™Ž“‰‹wwoplnnpstzz‚ˆ‡ŒŒŒŽ†Š‚}w}ld‚_„^…a„h€pwym€e‡a`‘d“k“u’€ŠŽŽ’’”‘™’œŸ‹ …ž}™v‘r†ozoosfy_ƒYTœS§V®]±g¯rª~¢‡š‹’‰Š„ƒ~}xysvrustytƒsožh©a±[³X°X¨\c‘mˆw‚|Šw’t—ršršr˜s–t“t“r”q”r”t“y“~’…‘”‘™’œ‘Ÿ›ž ž£ ¦¤©§«©¬©«¦© ¤™ ›‡˜~—w˜s™r›tœy€œ‰™‘•–‘™žŽ¡¢‹ ˆ›„’}‡u{kqdjcifllsu|~…‡Ž”–‹“…Š~€sjdb}dziupmwfa‡aŽe•mšx„ž‘Ÿ›ž ž£ ”˜œ–¢•¦“§¥†Ÿ–yŠu|sntbw[|V…R‘PžQªV³]·g¸r´}®„¦‡ž„•Œy…so{nxqwwvuŽq›k¦e¬`®]ª]¢_˜dk†rz|y‡vŒut’t”u”v•u—tšsœtžwž|žƒœ‹š”˜œ–¢•¦“¡¬«¬°¬±¬³¬´¬´ª´§³¢°›­”ª§†¥€¦{¨xªw«y«©†¦¡—›œ•¡‘¦Œ©ˆ©ƒ¦}žw“p†hx`lZfYf]kdsm}xˆ‚“ŠšŽ™ˆ…„‚xo|iyguipmjtdz__‰c’k›w¢…§“ª¡¬«¬°¬±¬–Ÿ˜§•«‘«Œ¦…ž’{ƒxsxezY}SPˆO“P S¬Xµ`»h½q»y¶®€¦}œw“q‹l…i€j}m|u{y‹v—r m¥i¦f¢eše‘g‡ko~s{vyzx~x‚x†y‹zz“z˜xx¢x¥z§§…¥¢–Ÿ˜§•«‘­¶¶¶ºµº²º¯¹ª¸¥¶Ÿ´™³“±°ˆ¯„°€²}µ{·{¸}·‚³ˆ­¦˜žŸ—¥«‡¯€°y¬r£k–d‡^xWkReReUj\sfq‹|•…‹ ›Š‘‡†ƒ{~synsmmogtbz]\…`h–t ‚¨‘¯ ³­¶¶¶ºµº²•Ÿž˜§’¬«‡¥‚›~Ž{~{n}_€TƒP†PŒR–U¡Y¬^µd¼j¾p½v¸y±y¨uŸo–ie‰c…d‚ir}ˆ}“zšwžtq˜o‘nˆm€m{mzmzmzmzo{s}x~~†€Ž€•~œ}¤|ª|­®„¬Œ¦•Ÿž˜§’¬´º»º¾·¼³º¬·¤´›±“°¯‡¯ƒ¯±´€¹~¾}Á}Á~¿‚¹‡°Ž§–”¦Š®€´wµn±g¨a›\‹WzRmOfNfQkWu_€iŒt–~‡ŸŠšŠˆ…„|~uwrpsivb{][…]‰d‘oš}£Œ¬›³©¸´º»º¾·¼³Ÿ™•¢¨†¨€¢|˜zŠz{}k€^…U‰S‹VZ–^ cªg²k¸nºq¹sµt®s¥nœg”aŽ^Š]‡`†f†o†z…†„‚”—•}{ˆx€uyqvnwjye{a}ac‚hƒq…{†††„™£~¬}±}³°‡©Ÿ™•¢¨†µ¸¹·º³·¬³£®˜©¦„¤~¤z¦y©z­}³»Á~Æ}Æ~»ƒ°‰¤™˜Ž£‚­wµm¹e¶_®[¡XVSpQiOhPmTvZcŒm•w›œ‡–Š‹‰…zuwtovg{`\‡\Šak“x›†¤”¬¡²­·µ¸¹·º³·¬†ž‘š†¡¢yv”vˆxz|l‚aˆZ[Ž`f•ko¥r¬t°t²s±r¬q¥oœi•bŽ\ŠX‡X‡\ˆd‰n‹yŠ„‰Œ‰Š‘ŠŽ‰‰†ƒz}twsqvhy_}X€TƒU†Zˆc‰pŠ~Š‰ˆ•„¡¬{³yµz²ª†ž‘š†¡°±±®¯ª«¡¥•Ÿˆ™|•s”n•m™ožt¥{­·ÀÅ}Æ|Â|¹~¬‚žˆ’‘†yªnµd»]ºZ³X§Y–Z„ZuWmUlTpUxX^Šg’p—z—ƒˆ„‰{†u€sytqxi~c…`‹bju“‚š¢›¨¤­«°°±±®¯ª«¡|œ…Ž˜xšr—pp†t{zp‚hˆdgnu‘{—~€¢¦|§x¥t q™ng‰_„Y‚VVƒ[†c‰nŒyŒƒ‹‹ŽŽ’‹’…‘~w†s~suwj{]RƒK†I‰NŠX‹f‹vŒƒŠ„Ÿ}«w´s·r³uª|œ…Ž˜x¦¥£¢ ››‘”„Œv…kc`ƒb‰hp˜y¢¯¹€Á}Âz¾xµw§z—Š‰}—p¦e³]¼Y½X¸Z¬^œbŠd{cr_p[sYyY\‰ck’u€ˆ‡}‰uˆpƒo|rtwmh†gŒkt€‘Œ––œŸ¡¤¥¦¦¦¥£¢ ››‘qœzŒ†~t“n’kŽl‡pww~q…p‰t‰|ˆ„ŠŠŽ“Ž—‹š†š€˜z“v‹qƒj}ay[xWyX|\e…oˆ{‰…‰Œ’Ž–‹˜…˜•yŽu…wz{m€]ƒO‡F‰CŠGŠQ‰`‰p‰†€x«pµk¸i´kªqœzŒ†~t™˜““Œ‰tyfr\nVnVqZxdo‹{–‚¤„±‚º~¼y¹u¯s¡t‘xƒ‚v‘j¢`±Z¼X¿[»`°g nŽrpvkseu`z]€^‡bŒiŽs‹~‚‡w‹oŠj‡jmztt{pƒpˆv‰€ˆ‹‹•œ“ —¡™žš™˜““Œ‰jŸtŽ€€‰uŽnjj‰lƒq~wz}z€€€ˆ~‘€—„šˆšŒ—Ž‘ŽŠŒ„‡€€{wrqinbm^n]rawi|t€€Š€†””“‘˜Œš†˜“~‹€€„q‡`‰QŠG‰D‡G…Q‚`€q€€}ŽwŸo®g¸c»a·d­jŸtŽ€€‰uŒ…‡€€zurhi\cS_P`RdZleus€€Œ‡›ˆ©†³·{µu¬ržrŽv€€sh¡_±\»\¿a»i±r¡{€€~vxspuizd€c†eŠkŒt‰€€‰tŽkŽf‹e‡hm|ty{y€€Š~“›„Ÿˆ ŒœŽ–ŽŒ…‡€€zud¤n•z‡…|‹sŽlihŠj†m„p…rŠq“o›r w¤|¤ …›†”…Ž€‰y„q|ksgkfggfjjnqs{v†vx–~™†™—–“›Žœ‰˜†‘ˆ‡‹yhŒY‰N…J€LzUucqrq€oi b¯]¹Y¾Y»]²d¤n•z‡…|€„w€qyloed^ZYTWSYW^`fnp|y‰…”‘¢Ž«‰°‚®|¦wšv‹y}‚q‘g¡`°^¹`¼g¸p­{ž„‰~‡vszurzm€k…l‰qŠy‡„~r’h“b’_Ž`‰d…iƒo„sŠs“sšužzŸ›ƒ•…‹†€„w€qylo]«gs~„‡yp‘i’e’c‘b‘b’b–`_£b¨iªp©w¦} ™“~Žw‰o‚izesdpephslzp‚sŒs”t™{›„›™˜•ž¡Œ Š›‹’…Œtˆe‚Y{SsSkYecap`}_Š[›V«Q·O½P½U¶]«gs~„p€f}`w]oXfU^S[S\Wb]lfzo‰w•œŽ™›¡•¤Ž¢‡›~‚€v‡l“d¡_¬^³bµi°s¦~™‡ŠŒ}‹v†u€w{|wu…vˆz‡‚Šy’m—b™[˜W–V“Y‘^c‘h–iœj mŸs›x”}‰€}p€f}`w]oV°a¤l˜xŒƒ€t”j™b›]œYœVT Q¥P©U¬]­g«q§y¡~š”xŠpƒj~gyfwgyj|nƒrŠt‘t–u™{š…™—š“¢Ž§‹¨‰¥‰žŠ‘‡€rxeo]eZ]\VcRmRwRƒO“K£H±G¹I¼N¸V°a¤l˜xŒa€W}RyQsPlPgQfUh[obzj‡r•y¡€¨ˆª§•¢—›””ƒˆxˆnŒf•`ž]¦^ªb©j¥sœ}‘††‹|‹xˆx…{‚€€„††„ƒ‰}s–gš\œSNLœN›S›Y_¡b¤d£ižo•uŠ{|~n€a€W}RyQsR³\©gžt’…x˜lŸa¤Y¦S¦N¦J¦G¨FªL«V«a¨m¤wž˜ƒ‘‚Œ|‡tƒnk}j~l€o…sŠvy”x–x—~–‡”’‘œ¥Š«‡®…¬…¦„›w~mqcgYaQ`KdHiIpJ{HŠEšC¨C³E¸J¸R³\©gžt’UL€I}JyLuPrUr\uc|j†q’xŸ|©°„³‡²‰®ˆ¨„ ™w’og‘b•^š\œ^b›i–rz‰‚†|ˆ{ˆ}ˆˆ…ˆˆ‰‰‹†x”n˜b›VLŸF¡D¢F£K¤S¥Z¨_¨c£i™pv{paUL€I}JyQ²Z«e¡r•ˆzœm¥b«Y­Q¬KªG¨C§C§I¦T¥`¢mžy™“††‡€‚ys~qp‚r†u‹y}”•~”}’‚‰Œ“‰œ†¥ƒ¬¯€¯«}¢v•m‡c{XpPiIeEeDgFkHsGE‘DŸD«E²JµQ²Z«e¡r•M„GƒF‚IOV}^~go‡v{™¤€­€´€¸¹}·z²v«q£l›g•c“`”^“^‘`ŽcŠi‡oƒv|}€|ƒ~†ƒŠ‰’”ˆ•€–u–j—^™R›Gž@¡>¤@§F¨OªYª`§fžm’tƒzte‚W„M„GƒF‚IS®[©e s•ƒˆ“{¡o«d°[±T¯OªK¥G¢GŸMW›d™q–}’…Š‡Š…}}{x}v€v…xŠ|€“ƒ•…“„‚Š…†‹ƒ’€š~¢|¨{¬{­zªv£n™dŽ[‚RxKpFkEhFgJiMnMzLˆJ–I¢J«M¯S®[©e s•K‡H‡J‡OˆX‡b‡lˆv‹}ƒ•…œ†¤„¬³|¸w»r»n¸j²g©d c™b”aaŠb„c~fyjvnusvwyz}~‚„Š‹‘‘–––™“›Œš˜u•i“]”P–Eš>ž;¢>¦E¨P©[¨e¡l–tˆ{x€i„\†R‡K‡H‡J‡OˆY§`£i›w‡…˜z¥p¯h³a²\­X¥UžQ˜Q”V’`lŽwŒ‚ŠŠ‡Ž‚Ž|ˆxw|zz€{†}Œ‘…”‰”Šˆˆ†‚‡|Šyw•v›v¡w¥w¦u¤pŸh˜_V‡OKwIqKmOjTiXmXvW‚USšS¢T§Y§`£i›wO‰P‰TŠ[eŽqŽ}†Œ’•™ŒŸ‡¥€¬x³p¸i»d¹a´`­a£c™e’fŠh€iujmkhlfnhpnsvv}{†ƒ‘Œš”Ÿ›Ÿž›Ÿ‘…˜w’k_ŒRŽF’>—<œ? G£S¤` l˜u‹}|ƒnˆaŠW‹QŠO‰P‰TŠ[aŸg›o“}‰€wªq²l´h°f¨ežc”`Œ_ˆd…l„u„„ˆ„Ž‚y‰t‚u~y|}‡ƒ‘ˆ“‹‘ŒŠŠ€‡y†s‡p‰op‘r–t™v›tšn—f“]ŽV‰QƒO}QxUt[pcmgnhufc‰`“^š^žaŸg›o“}‰W‰\ˆb‹jv‘ƒ‘Ž‘–šš–’•ˆš¡tªj±b¶]·[³]¬a¢f—ko‚qurhr^rXqXq^qgrst~zŠƒ—Ž¡—§ž¨¡£¡™œ‹•|Œp†dƒV…JˆB?“B˜K›X›g–uŒ~‡pŒdŽ[UT‹W‰\ˆb‹jj•o‘w‰…€”y£t®q´p³p­q¢s•s‰q€o{szxz|†~Œy†uu{zz€{‡~‚‘†‘‰Š„ˆy„ql€jkƒn†r‰vŒxwqŒiŠa‰[‡W…Xƒ[b|jxruwtxyu€q‡mŽj“i–j•o‘w‰…€a†j„rˆ{Œ‡“œŽ¢Œ£‰ ˆ™‡ˆ†Œ{”pže§]®Z°Z®^¨ežm’u‡yz|j}\}Q{LyNwVubuqw}‡œ’¨›¯¡°£«¡¡š’‘ƒ†w~kz]{P~GƒD‰GŽP‘^nŠ|‡rŽf’\“W‘WZ‰a†j„rˆ{Œswˆ€€Œw›r¨p±p´r±v¨{›€€w~ss‚u†zŠƒ†‹…‡€€zx{t~s„t‰vŽz~‰‚€€u{mxivivlwqyw|}~€€€yq€i‚d„a†b‡g†n…wƒ€€„~…‚…}ŠyŽusswˆ€€Œwk~w|€€ˆ…“‡ž‡¥…¨‚¦ }–{Š|€€u‡j’aœ[¤Y§\¦c m—w‹€€„r‡b‰TˆI†E„HR`~p€€†Žž˜« ´¤¶¤²Ÿ¨—š‹Œ€€wssesWvM{I€K…T‡a†q€€uŠi‘_“Y“WZ‰aƒk~w|€€ˆ…|‰€‚ˆz”s¡o¬o³q´v¯|¥ƒ˜ˆ‰‹|‰t‡q†r‡vˆ|ˆ‚ˆˆ…ŒŒ{ˆsƒl‚i„g‡i‹lpuŠx„zzwpskojmlkrkzlƒnŠoqŽp‡qtwxp}mƒm‡qŠwŒ‹‡‰Œ‡Œˆ‰‹…~||‰€‚ˆz”ssx~u‡x}˜~ }¥{¥w¡s˜pŒn€nurkza…ZW™Yž^h™t…‡yŒl\’O’E‘BEŽOŒ]Œn}’‹š›¡ª¦´¨¸¥¶ž¯“£‡–{‹rmpmapUtOyO~Ua€oz}pˆfŽ^YZŠ_„g}sx~u‡x}‡†Š€‘yšs¥q­s²w±}¬„¢Š–ˆ‘}v‹s‰t‡x…~‚„~Šztmeˆ^‡[ˆ\ˆ_‰c‰i†o‚t{wrukpikkgqc{a…__™_ž``—aŽf…l~ty|wƒyˆ~Œ„ŽŠŽ‹ŒŽ‹ˆ†Ž…‹‡†Š€‘yšswvt‰vz—ywŸrl—gb€_s_hb^kWwR„QŽU•]–i“u‹€ŠuŽh“Y–K™Bš?›CšLšYšh›vžƒ¤“¨£«¯ª¶¥¸´‘­„£w™nŽi~hnj`nWtTyV}_}jywp‚hˆb‹_‹`‡e‚m|wvt‰vz†”€˜{Ÿw¦w«{­€¬†§ŒŸ‘””‰•€‘{Œyˆyƒ|€z…tŠng‘_XŒRŠP‰RˆW†^ƒf~nytrxjwfrglnex_„Y‘UžS§Q¬Q«Q¤T›Y’a‰jƒs€|€ƒ‚‰…ŒŠŒŒŽŽŽŽŽŽŽŠ†”€˜{Ÿwzy‚w‡yz’x•s–k“c‹\VtRgR\US_MlJzL†QŽ[‘gtˆ€~ˆsŒf’W—KœB ?£B¥J¥U¦c¦n§zª‰­˜®¦«°¥µ›¶³‚­u¦lœfŒd{eki_oYvX{\}e{puzn‚j†h‡h†l‚r~zy‚w‡yz˜†š‚ ~£€¥„¦Š¤ “š–“—Œ•†Š„~~wq„kˆdŒ]ŽVŽNIŒIŠL†R‚[}ewopwj|d|cwhorf^ŽVœO©J²H¶G´H­K¤Q›Y’b‹l†u„}„ƒ…‡‡‰ˆ‰Š‹ŒŒŽŒ’‹•‰˜†š‚ ~{€|ƒ}†}ŠyŒq‹gˆ]€TvMjI^HTLLVGeEtH‚O‹YeŽrˆ}~ƒs‡fX•LœD£A¨C¬I­S­^¬g¬p­~®Œ­šª¦£¯š´µ‚´u°k§d˜a†auegk^sYzZ`j{tw|t‚r†r†t…w‚{€|ƒ}†}œ†ž…žƒž…‰œ›”™˜–›“š˜“‹Œˆ……~ƒwpj‚d„^†X‰QŒKFŒF‰K…R\xgqrj{da‚c}ltxj‡`—V¥M°G·DºC·E°I§OŸV–^gŠo†v„|ƒ‚„ƒ……‡ˆ‰ŒŠŠ•‰™ˆœ†ž…žƒž…|…}ƒ~ƒ‚{‚q‚e~ZxPoIeEZEQJITEcDtG‚NŒX‘doŠy€}thˆ[PšH¢E©G®L°T°\­b«iªsª€©¦š ¥™­Ž²ƒ´w´k­cŸ^^~anhcq\zZ^„f‚py€~†}‰|‰|ˆ|…}ƒ~ƒ‚†ž‡œˆ˜‹“’˜Œ‹ Š ‹Œ—Ž‡Šw†p‚je~`~\€XƒS‡M‹I‹JˆNƒV}`ukmvg€b†aˆgƒrz€odžYªP³J¸F¸F³I¬M¥RX–^e‹k‡pƒv€z}~|~ƒƒ…‰†‡•‡š††ž‡œˆ˜‹}Œz‰x‰x…y}zrzfxZsQmJeG\HSMLXHhHxK‡Q‘Z–d•mŽuƒxwzk_‹U•OŸL§N­R¯X®^©a¥e£l£u¢ œ˜—¢ª…¯y±m­c¡]“[ƒ^tehn`y\ƒ^ˆe‰nŠxŠ‰ˆ‡Œ„ŽŽ}Œz‰x‰x…›…›‡–Š‡˜ }¥{§}¥Ÿ†–Œ‹xŒq‡k‚f}cyax_y]}ZƒVˆRŠRˆVƒ]|ftpm{g„dŠeŒm‡z‰t—i£_¬W²Q³O°OªS£W\—_’cŽfŠj†m‚q~uyyw}y€~‚…ƒŒ„“„˜„›…›‡–Š‘yŽuŒsˆtusugu\sToOjNcQ[VTbPqO‚RW™^f›m“rˆt{vo|d†\‘W›U¢V§Z©_¦c dšd˜g˜m˜u˜—Š””ž‡¥|©o§dž\’Y…Zxalkdx`ƒa‹gp’z“„“‹‘Œ“†“‘yŽuŒsˆ—ƒ•†ŽŠ„’zœr¥mªl¬o¨v ~•‡‰Ž}tŒm†hfyeterfsgwfc†_‰^ˆ`„e}mvup~k†i‹mŒv‰ƒ‘xžn§f¬_­[©[£]œb–f‘iŽkŒkŠlˆl†m‚o~rxwt|uz€‰•—ƒ•†ŽŠ„’ƒ“ztq‡r~ssuiw`wZvXrYm]fd_o[~ZŽ[›_£d¥j¡p˜sŒs~tsziƒc_–_a e iœk”kh‹gŒiŽms’{’…‰—~œqœd—[ŽV„Wz]qgjtgg‹m‘u–šˆ›˜•“—‹–ƒ“ztq‡’~Ž†‡z‘nœd¦^¬^®bªj¢u–€ˆ‰|‹sˆl‚i{hujpmnqottu}r†mŠkŠl†nr{xu~q„qˆv‰€†€™x£q¨k©g¦fžh•lr‡v„x„x„v†t†r†q„q€syxt~u€y€†}‘}’~Ž†‡z‘ˆ’~w‰tƒt{vryi|c~`a~ezktsm~hŒg›g¦j¬m¬r¦uœxŽv€vu{mƒh‹f’g—k™o—t’vˆtok€h„hˆjowŽŠ‡€rdŒY‡SRzWtbpon}p‡u}—†œŽŸ”ž˜™˜‘–ˆ’~w‰tƒw‰z€€sŠe–[¢TªS®W¬`¤k™wŒ€€‚v€q|nvoqrnwm|o€v‚€€‰{wŽt‹s‡tv}yy|z€€Š}–y t¦p¨m¦mžo”s‰y€€z„z†{„‚ƒ~‡{‰y‰x†z€€z…y†|…‚‡~‹zŽxw‰z€€sŠ‹‡„€€|{|sl‚g…dˆeŠh‰o†w€€yŠt˜s¥s®u²x°|©œŽ€€uƒnˆjŽj“n•s•y‘Š‚€€xyvrxl}hƒgˆhŒms‰z€€q‚c‚V€O}MzQwZvgwuz€€ˆ‡’Žš”Ÿ˜ ™ž–˜‘‹‡„€€|{Œr‡s~xq‚dXœQ¦N«Q«X¦al’t†w~vysxpzn}nƒp‰uŽ}‡Žˆ•ƒ–~“yvŠt…ssr†rpšm¢k¦j¥l o—t‹{‚u‰ppsŽyŒ‰††‹„„Œ††Š€Ž‚‹††ŠzŽuŒr‡s~xq‚™ƒ’{‹v‡r‡mˆh‹eŽei‘oxŽ‚ˆ‹‚•~¡|¬}³€µƒ±ˆ§‹˜ˆŒz‹pŽj’i–k˜q˜y•ˆ‡Œ}Šuƒszuqyid„bˆc‰g…l}qot`uTvLvIvLwSy_|kt‡}ˆ““—›˜ –¡’ž‹™ƒ’{‹v‡rrŠrvuhŠ]–TŸP¥P§T¤[žb–hk†kƒjƒk†l‹p‘u˜}‡Ÿ’ž›™Ÿ’ ‹ƒ˜|’uŒo‡k†gŠe‘c™bŸb¡eŸj˜pŽytŠje“e•h”o“w‘†‹Œ‘ˆ•„—„–†‘ŠŠŽƒ|‘vrŠrvu ~›w•soŽlŽiŽhj’p“x“‚‘–ˆ …«„³…¸ˆ¶®‘¢•‘˜€˜q˜h›ežf k¡sŸ}š‡“‰“‘w‰t~trwg{_Z‚XƒX€[y`mc`fUiMlJoKsPwX}b‚iˆrŽ}’Š•••’¢Œ£… ~›w•so”vu‡w|~p‡e\˜VT UŸXœ]—`‘aaŒcŽe’j˜qŸ{¥†ª’­¬¥¨©¡©˜¦Ž¡„™y’o‹fˆ_ŠZX•Y™[ša—ir…|y†lb“\•Z—]—c—l—u—~˜…˜‰š‡„†š‰•ŽŽ’†•–y”vu‡w|~¦{£vs–q’omnqŽw€‹–Ž ‹©Š³Š¹‹º¶“«—œœ‰Ÿw¡i¢a¦_©b«jªt§¡‹˜“Ž˜„•|ŒwuqudwYyQ{L{KzMuPlTcXZ]SbPgOmRtVz\€a†gŠsŽ€Ž™Œ¡‡¥¦{£vs–q™{•zŽ{„z„pŠha“]–[—Z—[•[“Z’Z”\—aœh¢s©®³š¶¥¶­³±­±¤®š¨Ÿ€–rŽfˆ[‡TŠRŽS‘W‘_Žhˆts‰g‘]”V”S•T–X˜`šjœt}Ÿƒ ƒ¡ƒŸ†›Œ–‘–‰™ƒš~™{•zŽ{„¨{¦x w˜v‘t‹t‡t…x†~ˆ†Š›¥Œ¯Œ·¼Ž»‘´•¨š–žƒ£p¦a©[­[±`³i²u®§ž•”™Š–‚‹|}wnt_sSsJsDtBtCrFmIhNbT^Z[aYhXoYvZ|[`„k†x‡†‡”…ž‚¥~¨{¦x w˜v™€“€Œ€„|ƒu…n‡iŠdŒa^‘[“X•W™X^£g©s®³‘¶Ÿ¹ªº°¸´´µ­²£¬–£ˆ™yj‡]ƒT„P†QˆV‰_‡j‚v{q‹g‘\‘TNM’O•U™^œi s¢|¢¡†™“”Ž™Š†žƒ™€“€Œ€§{¦{ |–}Œ|ƒ{}{z}z‚}‰’†œŠ§‹°Œ¸¼º‘²”¤˜’œ~¡k¦]«X±Y¶`¹j¸v³ƒ¬Ž¢•˜˜“ˆˆyxjr[nOmFmAn?p@pBpEoJnPlVj^gedl`r]wZ{]}e~r€~Ž~š}£|§{¦{ |–}ž‡›†–…‘‚Œ~‡{‚z|zw|q€k…e‹_Z•V›W [¦dªq®€±³Ÿµ©¶¯·´¶µ²³ª®Ÿ¥‘›‚r…cX~S~T€Ybmxzƒs‹j`V‰N‰IŒIM•Uš_žk¡u¡{—†’ŽŽ•‹›ˆŸ‡ ‡ž‡›†–…‘‚£|¢›‚ƒƒ‚xp€llƒp‰w™…£‰­‹µŒ¹·Ž°¢’–}›j¡]©Y±[·bºmºy¶„®Ž¥“›”“Ž‹‚‚txepXjNgFgCiBmCqEuHyL|Q}X|^yesjlpds^u]vdvov|w‰w•xžz£|¢›‚ƒ‹š‹–ˆ“‚‘{tnŠl…nrwzoƒfŒ_“YšW Z¥b¨m©|ªŒªšª£¬©°®²±±±®­¦¥š›Œ|„m{ax[x[z_|g~q~{}„xŠqŒg‡[‚QI„F‰GM•Wšdœoœw–~†‰†—…œ…Ÿ‡Ÿ‰‹š‹–ˆ“‚}œ‚”‡‡‰xˆk…aƒ]]‚c…mŠw’œ†§‰¯‰´‰´ˆ­ˆ¡Š‘Œ‘n™b£^­`´h¹q¹|µ†®¤‘›”ˆŒ|‚nwamWfObKcJfKlNsP{Q„U‹Y^cŒh„lzooqerbrfqnpyp…rt˜x}œ‚”‡‡‰™Œ–’Š‘“v•k–c•_’`Œf„oz{p‡f^˜YY¡_¡h uŸ„‘œ™žŸ£¥©ª­¬®ªª¤¢›—ˆ„yzltesdvgzn}v€~…‰z‰p‚c{VyL|FEˆJS”`–m”v~…ˆ}—~œ€„œ‰™Œ–’Š‘–|”ƒ‹‰}ŒmŠ^‡TƒOQ}X~drˆ}’„‡¨‡®…°‚¬€¢€”‚„†uj›f¦i¯o´xµ±ˆª¡Ž—‹‘‚Švjs_iWbS^R`TeXm]w_‚`bše¡h£lŸn–q‰r{roripjnplxl‚n‹q’v–|”ƒ‹‰}Œ“ŠŽ‹‹‡‹}p•c™Y›TšU–\g…uy‚mc•[™Y›[™b–m’yŽ…ŒŒŽ“•šž¡¦¦«¦¬£¨œŸ‘“……zxtpsmvpzu€|„‚‡‡‡‰ƒ‡ykv]tPwH|F‚J‰SŽ`ny…‚{‹v’t˜všzš€—…“ŠŽ‹‹‡‹}y€„‡uŠd‰T„JFzIwRv_xo~|‡„”† …¨‚­~«z¥xšxŒ|~…t’qžs¨y­€®†«Œ£ŽšˆŠƒsyhm_d[]Y\\^aehpm{p‰q™r¦t¯v²w¯x¥y–x†wxvqsppsmykkˆnsy€„‡uŠ‰ƒƒ„€€u‡gZ–Q›MœOšV”b‹q€€s‹f’]•W•W’[d†ny~€€†ˆ“˜ž ¦£ª£©ž£•™ŠŒ€€ywwtzv{„€‰†ŠŒ‰ˆ€€qwbtVvNzK€O†YŠfŒt‰€€ˆuo–n™o™s–y~‰ƒƒ„€€uŒs‰y€€pƒ_Q}GxDsHoRnapqv€€‡Œ‰š‡¥‚«}­w©s¡s•v‰€€Œ|˜~¢‚¦ˆ§¢‘š’†Š€€ytpjfc^`YaYf^mgvs}€€Ž€Ÿ®‚¸ƒ»„¸„®„ŸƒŽ€€w|uwwr|m‚k‡k‹nŒs‰y€€pƒ}y}vyxobˆW‘O˜LœOœX˜e‘t†‚yŒl’a”Z“WY†_~hwqswt}|‡ˆ‘”šžŸ¥¡¦ž¢—šŽ„ƒ~z|w~x‚|‡‚Œ‡Ž‹ŽŠŠ‚tzfw[yU}TƒYˆcŒqŒ€‰‹€“v™pmœn™q’uŠy}y}vyxo‰j„n{tmw]vOsGoDkIiTjdmtt‚}ŠŠ‹˜‰£ƒ«}®v¬q¥p›r{ˆ‡…’‡™‹œ•–˜™‚–xq…kycp\iWgViYoawl€zˆ‡‹•Œ¥³½‘À’¼“²“¤’”†~Š{ƒ|{tƒn‡j‰i‰j„n{tmw||t|qwtn|c†Z‘TšS W¡`Ÿm™{ˆ„‘w–l–d“_Œ_‚bxhooitizp‚|Œ‰””™œ› šž”˜„ƒz}vv‚y†~‰ƒ‹ˆ‹Šˆ‰€‚u|j{a}]‚_ˆeq‘Ž™… {¤u¥r¢r›t’w‡z||t|qwtn‚d|eshfkXjLhEfDeIfTicosw€€‡Œ‰˜†¢ª{¬tªo¥lœm“tŒ~Š‡’˜‡ }¡rh–aŒ\€VvRoQmTo\tg}u†„‘“ž•­™¹œÁ Ã¢¿¤¶¤©£š¡ŽŸ‡šƒ’ƒ‡ƒ|„s…k„f‚d|eshfk{s~pztr}iˆa“]^¤c§l¦x¢…š—…›z™q”lŒjkvnkrduazg€q‡}‰‘’“˜’˜Ž”ˆŒ‚}x|r}qr‚v„{†€…„ƒ…}u~m~hƒg‰jr”~—Œ—š”¦Œ¬ƒ®}¬z§yz’|†~{s~pztryar^i_^`R`I_C`CbHfSl`so|{†‚„™ƒ¡¦y¨r¥m i™i‘mŒuŒ|‘€˜Ÿ~¥x¨o¨e¤[T’O†K|JtMpTq_vn‰’œ˜§œ³¡½§Ã¬Ä°À³·´¬³Ÿ±–®¨ŒžŠ’ˆ††yƒofyar^i_^`{…tƒrwxqŒl—j k§p«y«„¨¢—š‘žˆœ€—zŽwƒvwvkxbz]|`€i„t‡‰‰‰ˆ‘…‰}zuymyizi|l}q~w~}}€z€uq‚oˆpu–~›‰ž—¤š®“´‹µ†±ƒ©‚Ÿ‚“ƒ†„{…tƒrwxraj\bZYZOYHYD[D`IgRo^yjƒuŒ{”~šŸ|¡x rm˜h’fŒhŠmŒq“tœt¥q«l¯d®[ªR¢K—G‹DEvKqUpcuu}‡ˆ˜’¤™®Ÿ·§½¯Á¶À»¼¿´¿«¾¢»›·˜±”§‘›ŒŽ‡€tziraj\bZYZ}Šw‰w…}†zwšv£x©}¬…¬ª–§œ¡ ›¡”žŽ™ˆ‘„†z€n€d€^€^€dmw€ˆ~‹|‹z†x|wqvhvbv_v`vewlwtw{v~u€t†uŽx–~œ†¡‘£œ¢¨ž±˜¶’¶Ž²‹©ŠŸŠ“Š‡‹}Šw‰w…}led^]ZWWPUJVGYG`LhSs]g‰o‘v—zš|›|šy—u’pŽj‰f†e…gŠi“jžj¨h°d³^²W­O¥IšDB€DuKnWlgpyxŒ‚Ž©–°ž¶©¹³º¼¸Â´Å­Æ§Ã¡¿žº´š«– “‰‡€zvoled^]ZWW{}Šƒ…Œ‚•€£ƒ§ˆªŽª”¨š¦ž¤Ÿ  œŸ˜›””‹Œ‰u‡j†b„_c~jzrx{u‚t†s†tƒtzuntcsZrVqVpZpbqlrut|vxŠ{“›…¢Œ¥”¦¤¦ ¯š³–³’®‘¦œ‘‡{}Šƒ…kmbd\^XYTVPVNYN`QjVv]ƒeŽl•r—w—{•}‘}Œz‡u‚oj~f€e‡d“eŸeªd²aµ^´Y®S¤L™GŒE}HqOh[ejh|oŽzž‡¨‘­›°§±³¯½¬Ä§Ç£ÆŸÂœ¼·ž±©™ “–‹Œ€uvkmbd\^XY€’‚‰Š‘‡˜‡ˆ¡‹£Ž¤“£—¢š¡›¢›¡œ ž›œ—˜‘”ˆ~sŠi†de{iuppwm~lƒm„orxult_sTpNnLlPlYmeoqt{yƒ}—„ ‰¥§“¦™£Ÿž§™«–«”¦“Ÿ“–“Ž“†“€’‚‰Šlvdn`e^^[YYXX[XbYl]xa„fk•q–x’~‚‡ƒ€‚{}wwvpwi|e…d’c d¬d³dµc³a«\¡V•PˆMxNjT`^\l^|eŒqš£Š¦–¦¤¤± »œÁ˜Ã•À“»”³˜¬œ§¢›œ•–‚ˆwlvdn`e^^€’€†Š”‰˜Šœ‹œ›“™•˜–˜•›”–Ÿ˜Ÿ™Ÿ™œ–˜”‡}‹r†kiwkopjwg}giƒnsyvkw]tPqHnFkJjSk`oou{|…‚‘…›ˆ¢Š¦Œ§Ž¤ž”˜š”Ÿ’Ÿ‘›‘•‘’ˆ’ƒ’€’€†Šrkyhohfg_e\d^dcdlewhƒkn’t‘{‹ƒ„‰}Œv‹q‡ooxspyj„g’f¡g¬i³k´m°m§j›d]XqWbZWaRlTy\†h’w™„›‘™Ÿ”¬¶‹»‡»†·‡¯Š¦‘ž—™š–š•–“‘†|ˆrkyhohf}Œ…‰‡’†–‡—‰–‹“ŒŽŒŽ‹ŽŒ‹Š•™’›–œ˜š˜—•’†ˆ{ƒrznroksfxd~eƒj…pƒw{|m|]yPuFqCnGlPm^qny|‚ˆ‡”ŠŠ£Š¥ˆ£†ž†—‡Œ‹‘Š‘ŠŠŠ‹…~Ž}Œ…‰‡zŠtƒsytntes`r`qcpjptq~r†uŠzˆ‚ƒ‹{’t–n–j’i‹l‚rwzp†l”l¢n­r²u±y«z¡y“s‡kydi`Z`OcJjLsU}b‡qŠ›…¨±z´w²w«z¡–ˆ‰–‰˜‹–Ž‘Š‚zŠtƒsytnv„y‚€€‡}Œ}Ž~Ž€Œ‚ˆƒ„„€„~ƒ€€„‰ƒŽ‰‘’•‘˜Ž—‰“„‹€€zvsrlsfvd|e‚i‡o‰w‡€€„r„bS|IxFtIrRsawq€€ˆŒŒ—ŸŒ£ˆ¢ƒž–|{„€€„~…ƒ€{ƒx„v„v„y‚€€‡}„€Š€€tj€c_~`}e|l|u}|€€…~x•rœm i hœj”oŠv€€x‹t™t¦v¯{²¯„§†›…Œ€€wrnbgTdJcFfIlRsazq€€€|›w¦q­m®kªl¡o•v‰€€‰|~•‚–ˆ”‘Š’„€Š€€tjtmssp{o€oƒpƒru~wzywzuyvvzv{‚‚…Š…ƒ”€•{‘uŠqmvgsctayb€f‡mv‘€‰‰{kŠ\…R€M|PyYyf|v„„Œ™Ÿ‹ †€•z‹vuuxp}o}ozpvrqsmtjujtmssp{o‹‰Š‰€ŠtŠjŠa‰]ˆ[‡^†c†i‡o‰qŽp•lh£e¦d¥f¡k™rŽ{„…|yz©}°ƒ²ˆ®¤—ˆŠ{nv_mQfHbEbIdShbmrq€ro™k£g¨d¨c£e™jqzwƒu‹w‘}”ƒ”Š’‘‹‰Š‰€Št]b_ae_l^r_wayeyixmupsrqsrrtrwxxx‡vs‘o‘je…az^r[pYsZz^ƒeo•zš…›•”ˆ”x’h]ˆX‚Y~`|m~|„Š‹•œŒŸ‰„–~‹x~tptdw^z]y]u^o`iacb_b]b_ae_l^ŒŠ‹…Œ|qŽgŽ_ŽYWŒW‹Z‹^‹aca—^[¢[¥\£aŸh—q{ƒ„|{œ}¦‚®‰°‘¬—£›–›ˆ•{‹n_sSjJbG^K]T^a`pc}cˆa“_›]Ÿ]Ÿ_šb’h‡o|wtr†uŒz†ŠŽŒŒŠ‹…Œ|qQRRQWP_OfQlUqYt_uetjsnrqrqrsryp€m‡iŒdŽ_ŒZ‡VStRmQlQqTzZ…c‘oœ{£‡¦’¡˜•™…˜u”iŽcˆb‚h~s}€Ž†˜ˆž‡Ÿ…š}‚yrwbvUzO|NyNsNkObP[QURQRRQWP_O‰ƒ‰~ŠvŒmdŽ]ŽXŽTŽTTŒVŒWŒWT”Q™PPžTZ™c’m‰w€zŠz–~¡†©Ž¬—ªŸ¢¤—¤‰ž}“q‡cyWmOcL\NXUV`VmWwV€V‰UW“Y“]cŠj‚q{wu}t‚w†{ˆ€Š„Š†Š†‰ƒ‰~ŠvŒmJFIFMEUF]HfLmRrYv`wgwmurttswo}j„dŠ^XR‰N‚KyJnJgKhMnQxX…b“mŸz©‡­’ª™Ÿœœ€™s“kŒj…nw|„}‘€›Ÿž€—~‹}{{j{X|JDC{CsCiD_DVENFJFIFMEUFƒ|„v…oˆhŠbŒ]YVTŒSŠS‰RˆO‰LH‘G”H•L”S]Šh‚sz{u„w~›‡£’¨œ§¤¡©˜ªŒ¤™u‹h~]qUfQ]SWXS`PjOqNwN~PƒT†Y‡`†gƒou{yy|y~{~€‚‚‚‚€ƒ|„v…oˆhGAFAIBQBZEdJnPuWz_}g}o|uyyu}o„fŠ^ŽVOŽJˆGGuHjIdJeMkQvX„a’l x«„°®—¤–Ÿ‡z˜q‘nˆq€yz…x‘y›zŸzž{–|‰}y~f€T‚F„@„?~?u?j?_?U@L@GAFAIBQB{v}pj‚e…bˆ_Š]Š\ŠZ‰X‡V…RƒNƒI„D‡B‰C‹HŠO‡Y‚c|nuuq}t‰|”‡“£ž¤§¡¬š«¥…šzn€dt]iY`YY\TbPhMmKpLsPwUy]{e}n}u}z}|~{zyƒxƒx‚x€y|{v}pj‚eJCIDLESG]IhMsS{Ya…i…qƒy~y„o‹e‘[”R”LH‰G~HsKhNcPcRiUtZajœt§€®Š­”¤œ— ˆ |œs•pŒr‚yyƒttšsžtv–yŠ|z€h„WˆJŠDˆCBxBmAbAXBPBJCIDLESGsrwlyg|e€eƒe†fˆeˆd†bƒ^€X}R{K|F}CC€G€MW|awjqqnxr‚{Ž†˜’Ÿ¢¥ ª›©’¢‰—~‹t€kvdmaf``b[eVhQjNkOkTl[ndqmtvx}|€€ƒ|…w‡sˆp‡o„oqysrwlyg|eSLRNTP[QeSpV{Z„_ŠemŒu‰|„ƒ|Šq’e˜Z›QšL•JŒL€PtUjYdZd[i\q_}c‰i•q z¦…¦Ÿš“¡…£z¡qšno„vy€rŒp—oœpœr—w|‚o‡_‹SNŠN„M{LqKgK^KWKSLRNTP[Qmqrkuhxh|kn„q†s†r„oj|cx[uSuLuHwGxIyOyWwatioomur~{Š†”‘››Ÿ¢Ÿ¥›£”›Š‡x~qwlrimhiiej`lZkVhWf\edemhvl~s„z†ƒ‡|‹tmi‹f†g€iymqrkuhxh_[_]a_gaqa|b†cŽf“j”p’w‡†}q—ežZ¡S PšQ‘U…\xcngihggjfpexf‚iŒn•v››•™Š¡~¦s¥lŸi•kˆq||sˆo“mšmœp™u’{‡zˆmŒb^Š^„\|[tZmYfYbY_[_]a_gajtpnslwo|t€z„‡‚‡‚„€z{qvhr_qVqQrNtPvTw[wdukqpout~|ˆ†’™—œ™š“‘Š‡€z{uxrvpuptqrrnqgobjbdfan`vaf†nŠwŠ„‰{Žq‘i‘cŽa‰aƒe{jtpnslwomkonqpvrqˆo‘n–m™o˜r”wŽ~††|o™d¡[¥V¥U Y—a‹jsvwpwmtmqomtk{k‚nˆt~‹ˆ˜~£t©jªd¥b›elwwƒqn—mœoœs˜x†„|ˆs‰p†on|lvkrjoimjmkonqpvrkzruvtzx„‡ˆ‹‘‹’ˆ„‰~€xuskqbq[sXuXw\yczjyqvutyxŠ‡’˜”›—š––‘‡‡~yywvwuzv|w~yz|yuvnongqaw]~^…b‹is‹~„‡yn‘e’_^`‡e€kzruvtzxyz|}€€„€‹~’y˜u›q›o—p‘rˆx€€vŠj•`ŸZ¥X§Z¤ak“v‰€€„yƒtqzpurquoyp}v€€{›r§i¯a°\¬\£`—hŠs€€yŒt–qœpŸržu™y’}‰‚€€}z~w|uztytxvyyz|}€€„€s€{„€€ƒ„ˆ‹“’š”ž“ž‘›Œ”†Š€€{uylyezb}bf‚mƒuƒ|€€~ƒ€‰…‹•™“™“–‘‰‰€€wxsuttwu|y}†ˆƒ†ƒ€€ywwnye}_‚]‡^‹d‹mˆw€€t‡jŒb^_cŒj‡sƒ{€€€ƒ„ƒ†ˆˆŒŠ‘Š–†š€œz›t—om‡n}styk„aZœV¥W©\ªe¥qž}•†ŒŠ…‰~…yuystsrtsvyw‚vržjªb²[´W±X©\ep†|€ˆy’ušržqŸrs˜u’wv‹u‹sŠrˆs‡u†y…~…ƒ†ˆˆŒŠ‘Š€ŽŠ’Ž’’—˜›žŸ£ ¦ ¥ ˜™“…ˆ{‡r‡mˆjŠlqx€ˆ‹Œˆ‰”Œ˜Ž›œ™Ž“‰‹wwoplnnpstzz‚ˆ‡ŒŒŒŽ†Š‚}w}ld‚_„^…a„h€pwym€e‡a`‘d“k“u’€ŠŽŽ’’bklSuKƒR—Y¤]¥]™Y…TvXpfswz„ˆzh|T„EŽA•F“P…Xs_jgholyoƒkŠ`ŠWˆS‡S‰V’X™[–gŒy}Žp£l¯p¹pÂlÇdÃZ¹S­U˜azocz[c|u{…†”œ‘œ”Ÿ|¦i`‡bklSuKƒRg”\OhlMœP›hhea`q°Œ¥œ¦zº©|vzB…>ƒl‰v¥_ªV”q~ovPmI]jL|hn“dŒŽj©n‘ˆf”Z h¦« œ±¨_‹]r~‰œ|›{wtaejvk l³€³ˆ·j¨OŒMrKkQvfkwarrg”\OhlM`}jktei”m¡o¡m•jgsmsz{†„‹‰‡‚{nuZ{O‡Q[g‚jtgrewg}o}vŠg_Ž^Šcˆii•f•iŽr‚€vp™q p©n­kªi¢g—l…vl\ƒZ€gw|uŠ~ŒŠˆ”ƒ•‚‹w›f›^`}jkteimciN`un¢zŸmvZq[–f©f{Ž “”±w{FoAzc”c§R­Y°€Ÿ’~‰WwJ\bLel`”o‰¢gµh˜v„Š}¦q¢f†Ž°ºv¦dƒpv…”Ÿ~ZqUw}‰­‰¿³…­_šR}ThKrT‰d€nk}fmciN`ungŽuƒ€€Œƒœ†¦†¤„•€€s…s{—…—‰Ž€€lx\}X‡aŽq€€€txuolˆq‹€€o‘il„v}€€‰wpo‹r„y€€†~Ž~“~‘‰€€…o\“R’V‹h€€{ŒŠ‡Œx‹u€€n‘a™_˜gŽuƒ€€Œƒ–z‹w€€–žš¥€€]g]s€€Œa‚[€€Š³‡³€€mWd]€€”z‰o€€šŸ—€€_{c~€€u“iž€€­e©q€€Œ‘–€€TdXl€€žwŸs€€^¡]§€€€KrK€€“¥‡Ÿ€€~…tŽ€€„fwj€€‚…s„€€–z‹w€€–žwžŒ™™—¤š°œµœ®š—‰”{˜w¡y¦}¤~›u‹f‚\„]‰jŒ}ˆŒzŒoƒsz€uŽy•‡•~–z~‡srŽ{ƒ„w‹ompŒtŒy~ŽŽzŽpŽf‘Y—KšH™S’iˆ‚€Ž…zyun|a^šf wžŒ™™—¤š{´‰®Š¨Œ¶vµT”7w@j’|xvw‹ƒ¨œvwpouŽ‡²€Ÿ]LŠeœn„WlVv†ˆ¯˜¬‚¦„z›kŒ„a”^“z—„‡ib_LgJy_{`²:Â5µS‡WRPDacztqe_Lcls¡†¬Œ‰YN€fc•a³{´‰®Š¨Œ¶ˆ¬¡¬±ªºªÁ¬Á­¸«§¨—£Š£¨{¬wªt¡o’f‡a…c†n†~ŒrŽh†o}€x”}¡‹žš“ž–‘…•t—m’q…wx}pƒnˆrŠvy’w•p•d“WMŽD>BT‹n„ˆ}—wšr“kˆd}[~W‹]šo¥ˆ¬¡¬±ªºªdÅvÁy¤qŸf§R›7rCir…•Œ•‰——•vˆpŒŠŽ¥€³a–KuK‚Zb~Tzd‚—~®‹£±™«‹xˆm‚ƒf†I{^Œˆ”x’XpJmeu™d²;¸6°RSeNW^]„U‡LfL]qn¢w®}‘ŠjƒOnWc‡]²dÅvÁy¤qŸ‘¯ª³¹°Á­Å®Â°¸°ª­ ¥– ˆ£|§s§n o‘n„k€lq€z{…m‰c‚iz|w“{¦Š¨œ¡¦Ÿ¢Ÿ“~˜qŽmktmosq{y‚€ˆx–k–[‘L‰Cƒ>=}E}X}szŒtžl§d¥\™WŠS‚Vˆc–w¤‘¯ª³¹°Á­w ¤€€zqƒ€€\YWW€€—™‹€€pŽh€€Ž˜™€€aljb€€‡‹Šz€€‚…Šu€€³Ž³€€yt‹†€€MhMr€€³|³€€u‚‡†€€Z‰_”€€}msy€€ªn­o€€n|€€ƒŠ€€pf~g€€w ¤€€zq¦¢¬°¦· ¸¢´¦«¨¢¦ž›˜’‰”z™oœm™t‹z}yzv{s}t{}nb|euur‹wŸ†¥œ£­¥°¤£Ÿ”y…mubl_kdto€x‰‚‡Ž}•o”_‹R€MtJlHiOk^pusŒo¡f±^´X©V•Z…aƒn~š¦¢¬°¦· “{¨{®`¥d¡{ |ƒ[d[j„yli\Qgduƒwž–…vthcgup“’¡›«x«d™ou€\ŸhÈrÇ^œ_‡ˆ„˜ykZYK{M°`º‹’§‹šŸoŸLƒ^€vŒh‹X”r¬ŠÊ~Û‘‘Œ‰o|¥¢Ÿ°†ƒ‡Z^“{¨{®`¥d‡•Žš˜’ŸŠ Œœ“•™‘—’‹€ƒu‰mn{ƒ‡u‡t€yxr€xu~gycrkn|r•š™²Ÿº¢°œ˜}nm]dWf\riu‹Šƒ—y•n‰gzekb`]]]bdktsˆq iµc¼`²cœk…u||€‹‡•Žš˜’ŸŠ–w¥i®^£z‘‘™£k…]dzkr_bT[t¤‰ž€wqahu`h~„“–®’¨e™]m{_¥|¾{¼[£Q‰ssœk‰YpIM¯^¸}œ¢”¥žw¦LŸ`‘y}isJŠX®y¾v·r£‚ ¤•¢{~|yœ˜¤²€‰o]€e–w¥i®^£z|†z‰€€‡w‡{„„~Œ|Œ€€€twvm€i‰o‹€€ŽssŠ|€…z‰€€…ndudolqy€€š†³“¼›²›™‘€€km[bW``iqv€€Œš€¢~ž}~€€p{epcgjfvo€€~˜x°r¹p°u™€€‡t‡u‚}|†z‰€€‡wƒ€€yšl–€€¬e¨_€€‚‹‘|€€b©kª€€yQwP€€u‰kw€€ˆ¯y¯€€„]tb€€¨¥€€^t\u€€zqu€€£yœl€€u¡vš€€’Ž—˜€€bVeZ€€‹‡r€€ª–ª€€re}l€€`m\c€€ƒ€€yšqwfzhrolqtn€k‹hkƒlxhyf€j†v…ˆy•p˜u’‰Žƒ”‡‹Šwev[nZo`}d—m®~·®“—npech^vb‰j—p rªv­}¨†›Ž•€y‚ys‚lo™}—–­†¶‚­„•Ž}•oŽmqqwfzhrol†›a¥P¬V°b‰„]«O­`—¥Ž°™›«j»P™Y`iD…V¡Ÿu•Y¤]˜‡g—Z…ud‹S¤c»v©xƒp_sH~U‰U“T¢o­•“um‚[­^¶p–¢µ¯ª }{V€Q¦]¯n¤v¥¶­¦«•n„lxoaY`Wƒ{†›a¥P¬V°ifUiQgWg\r^^Ž\“\\…]‚cq„x–l h t™†—ƒžƒ•‚~wdjQcHfHuKU¥g±x¬‚›‚ˆy~m{eƒc‘f¢kªl¬j­nªx¤†œ—”£¢”…šz¦y°„®š£°–¸¯™—p”fdifUiQgWg~ž_±O¯V¯g’Šd›WkŽv³u¼‘ ®m³L’__rZ€x™‡¨f¡P¦W—bfmX|{t˜`©l©~r€dˆV~RvE’I­n¬Ÿ‡¢s{Œ[¸_¼€“©Š½Ÿ«¥Šƒh€R£TÀq½‰¨•Ÿ§–®‘¤”“’‹tXcOxt~ž_±O¯V¯kXR^GcLjTw[†^‘]—Y–U‘W‹c„wyŽn c¦e¤v›Œ€£{˜uhb\KX?_>nA…KœZ©i©ržt’oŽk’l›p§t°u±p©iŸf—m’~’””¦—©™ ž’¦‡¯ƒ¸‹· ª´š¼Ž³Œž–‡ s™b†XkXR^GcLj‘ž†—€€w‘l›€€…qt‚€€ªf¥l€€[“W™€€‡zuŠ€€“a„h€€ƒpxf€€†‰t€€„ƒ€€„’‡Š€€c”\˜€€°[¯Z€€V­W¯€€¡hŸu€€}a‡]€€k¥p¢€€~l{p€€ƒ”€š€€rUiT€€‘ž†—€€w‘xP^[PiSu]g‹m’k•b—X—Y’e‡zy‘kŸb£i¡}˜’‹Ÿ}¡t”jz[^QJQB\EmLS•^¡g¢lœm–k—n x©‚¯†®„§z—k…_y_xn†œ—¥¢ ˜¢Ž§‰®¯£¢µ’¼…´ƒ Štž]PxP^[PiSu«™¨Š™uy‹U¦\™mŒm¡u©ˆƒZqY\x\Œ~x‡„—|r˜W´a¢|ƒ Ÿ|ohKl\szb‰\‘n–„™sœvzœRÀC®NweKŽJ¨t‰h{dco|W¦H¯\“€y{mVfMj`vqmqYjVY\Slm«™¨Š™uy‹Ow`guhƒsŒ~ƒ€‹rc•^“e‹uˆs“m–v—ˆ“˜‹Ÿšt‰frW[OPSPaZse„k“pšr™q”pp–y¡ˆ¨”©—¡“‚}lfXYQ][os„‹’™˜›—•“Œ‘‡—Œ™ž°·w°w„‰˜q¢YžKOw`guhƒ³€µ†‡c‘I¦WŸrŽ{™n¬^Še]_x}izn”l–{šŽ£œƒ«YµJ±f–œw¥iweKdRfhgv\„LŒ`|f–vq¡PÁb³s€jQwR—’†en_j}’v°Z±Z«}™}|XgWquˆ‚ucVQ\Xhym”…‹³€µ†‡c‘¡Qg€€€Ž‰’’•„}€€m‰aaŽj‰x‚€€„ˆ‹– Ÿ‰“€€pj`ZXW]amr€€Ž…•†•…‚„€€‡‰”—›Ÿš‘€€hgQOFEONff€€ŽŽ’‘ŒŒƒ‚|{€€ƒ‘|¤s¬m¥q”€€–i§R«I¡Qg€€€Ž´h´u€€Za‡€€šižj€€UuUi€€…œu“€€•t‰n€€œ ‰€€R•Qœ€€¢r›~€€xzŒ€€ŽR”P€€_™_Ž€€¦œ©£€€OsP…€€…SsS€€ž•€€€’¢š¤€€`ufƒ€€t]i^€€†©u­€€´h´u€€Z³Q¥l˜†™” –¥Ž¤›v‰vue]–_šf›jšož|£‰¢’™“‡Œt~do]hbnr|†Œ”•–”•Š’|ŽoŒku•…Ÿ’—‰ˆzwcbLLCBLHd\~s€€Šx~muewh{zxŽs˜s”yƒ‰pŸ[±H¸D³Q¥l˜†™”¾¬zsq\_zX©U¿E¼A¤Q„bp}| €¯{¢™}Žfwdz’Š³|©es{NŸc¤Ž›œ¤‹©Œ§¢¨µŸ³†ž‚œg¨b z¡ ¯¥œ~wGk:lahkXeav{…Ÿs©‹¿’¿tžRˆWtpv[m‹£¤‘«™”¾¬zsq\_¾P¶n¯Š²š¸ž»—µŠ§|”x‚m‘a \¬\²Z³^°m©›Ž‰”ue‚_xdus|‡ˆ™“¢’ž‡–wŽhŠ]Š]Žl•€˜–”Œ€}ugfOTEHLHbS{cŒl’ja†U|N{Q~c|x|„€ƒ‰u˜b©N¹>À>¾P¶n¯Š²š¶¤œœi€TXpF¥WµV¬K¦S®q ‡¦‚œ‚…yW™Nn‹š¢±—¬q‡e\ƒ^¦„¤žy§z¨šœµž§­†«q¢lŽu‚‹™ª ­‚†oOl>b_kh‰a–p‡‰Œˆ£…¨¢¬¤²}œX‹`‹…{Šk‹y §x˜Šžœ¶¤œœi€TX¼N¹m¸Š¾Æ¦È£¿˜­ˆ˜…‡u•j¥c³^¼W¼W³d¢vŒ‡wfŠ^czr}††™¤“¤ˆ˜u‰b~V{T\‡o‡Ž˜Šœ‚”z…wnrUfHZMR`RxY‹^˜ZšR“IˆDƒGƒXƒn…|‹|–p¢^­I¶:»:¼N¹m¸Š¾ œŸ €€[XXX€€Œˆ~{€€¤¥‡€€{qŠf€€N•Mˆ€€›¢§€€xUqY€€€œt€€o„su€€¢}€€{_vY€€Ÿ£€€TUq€€„¯u­€€wƒ…€€£}¨Œ€€VxZ‰€€uu…€€ˆ]{a€€ œŸ €€[X¨Lªj¯‡ºœÅ«È®¿¤«”•‰…Š{”u¡q¬l³a²[¥cryhˆ`axoy…šŠ¥¥Œšyˆ`sOgLfUpf~}„–ƒ¦~§x›vŠ|t[}MsOga]x[]žX¥R M”K‹P‡_…tˆŽ‚˜w d¥N§<¨;¨Lªj¯‡ºœ˜wºŠ®xˆTn\w‰x’hƒa†p‘m‚Uvijše¥pŒQgfMrjcx]buI”X¯{¹p¤U…ZicVW\Ymur’UG~Zx~‹††€aƒO‰vˆª“­œ¡‚¥^˜Zn]eT“b§…Š‡XxCr\^b\[xh|p^_Vc^˜wºŠ®xˆT‹Kf˜‚§™¶¬¼²´ª¡™‹Š‡}‹’™r™h‹jwtga„d{ns‚wš©‹«Žžƒ‹jsP]CRIV]guxŽ¦|²u­rœtŠ€tŽ\“OR€dqzj‘i¤e¬a¦_˜a‹f…t€‡“†’Ž…”r“ZD‹>‹Kf˜‚§™Ÿk¼‡°„¢X“T}u‡swewOŠK‹S‰ov›eª{‰en^LUTO]e[Ž^©v±§vˆUsX]jOadUviwp‚Y™X—vŠ€Žs€s^t[ˆ”­”®q¬W©^…ga^nQži®–•g†Jr`YjW`iomwmcsieŸk¼‡°„¢XpLve€€‘—£©¬­§£•€€vzy{‚~ŠƒŒ„€€srsd{^„bˆp€€w”{©…³­˜€€dgJR@KJUdk€€˜…­³u©o”r€€k“VžMžS•h‡€€–}¦y«w¡wz€€wŒrœq¥u¢{“€€}fvMqCpLve€€‘—¥ržƒ€€‹U—T€€w‰€€\Žb‡€€‰p‡f€€¡š€€hx_y€€Ÿ•€€€}s|m€€m–c’€€|–€€|—€€‰l’z€€o‚x€€€R†S€€^”XŠ€€¦ŠŸ‰€€bƒ\ˆ€€†yt~€€‰Žv™€€¥ržƒ€€‹U\U_mg‡w›Š¦•£“‘†yufoawc…iq“u‡s{i|`„_Žg’wŠˆ€š„¬Œ±’¥‘Ž„ui`QRGTOef€–’™ ¢•v€tn€_”R£O¨[¥q‡˜˜˜¡•““w•fš^£X­W¯\¦d”j€iicS]K\U_mg‡w›£—Œr|r_~gz‡‚‡œ~œ„Ž‹›~«vžt…qv~x”ƒ–‰v‡d™|®—ŸˆntMKŠcŒˆ€«}¼Ž´™¯œ›¦|žrp|R{v}œš“ªy«s¡ojfiu\—B¡Hk“ˆŠhtbZtW‰vw‘ft§·r¸œ£—Œr|r_NdL}O”[¢j¥u™y€ubmNoJ~MW›d›oŽr‚mƒfŒd•j˜v……•ˆ£¤—–—~‹frV]RS^Ywj—z­„®ˆ „Žy€j|_‡[šZ©`°n°­­•°•²Š³v²_±O²Eµ?´>­EQ‰[w]fYXSVNdL}O”[¢¨¢§Ÿƒ‰gyf~€}•fŸb¡s²}¹ƒ§ˆ“‡Œ‰v{nqt{vrrcˆx«’¬Ž}†N•@‘R{z~¢º‘´Œ£†©m…\XaU|‡Ž¥›‹¨y½³~uƒu’b’L‹Vd…r]ˆO…lh|\{ib‹Yn¡w½l»{£¨¢§Ÿƒ‰gyPsGŠEžK§S¤\’cvhXkEv@‹CžN¦^¡o‘y…x†rŽm–m™rŽ}„Œ‡——™‰šr]zRjUcffƒp£v·tµm§e•_‡[„\Žcžn©{¯†°¯³Ž¼†ÃxÆfÄT¿F»;·2®1 :ŽI{Xm_c_^YcPsGŠEžK§¬‹©“€€V}SŒ€€“_…f€€¡¤}€€g™oŸ€€rims€€|jne€€” ‡ž€€˜bš`€€‚š•€€l}y€€€bd_\€€­¯€€q¤‚¤€€|€€€ns|…€€zN„M€€lp|€€r„it€€„Ÿs—€€¬‹©“€€V}c|UŽNL¤L OWyc_oNƒGœG­O¯_£sŽ‚‚…ƒ‹w“p”o‰v~„‹•„˜qŽ_}Ws[qkt„xŸu¯g­XŸNN†W†cu‰¢˜£¢—¢©ƒ·xÃmÇcÃYºO±B©6œ3<~Nqbjoetfomc|UŽNL¤™{€‡To4v:šbšjuYsXŒvzfwY•S©N’Sƒzž©´¥ˆ‘VœTž‡z²l±›œ”† … ‰r\`hlŽo›dq[¤z¯Šœzzzput~zt…ttfmnƒ–ˆ£n{\oU‘g˜–¯ƒ ƒ•dž]›nŠhŒ`™{€‡To4v}pˆe’^™T™P’V„esxf’]¬V¹W´cŸu‡†{}Š…€vŽp‚uvƒyƒ’ŽŠ’{ˆm{dxd|l€|Žx™b–MŒCI|]€s‹‹•¤•±­‹œ‹†”w¥n´k¹k³l¥g™XHƒBzIs]pso…not}pˆe’^™y˜h¡Sy=yBš[›UnKb[{lŽf‘i‰|o©PJ~rœ¨´«‹™[ŸQ›zz¨x²›±—®vž|‘Š€vcih}Œ}x\•N¤v„Šl„tˆx¥t¥}Ž‘w†ch_kq}“y§UšFVš‚”­v­v¤ƒ¥lžX–P–Q‹jy˜h¡Sy=y›w‹z€€tˆdZ”]‘kˆ€€šs´f¾^³bšo€€t‰wŠ…ŠŒ{€€stš}Ÿ†šŠ€€uuwm€lˆpŠy€€f}NuEnNmfs€€š‡²…¼}³wšv€€p’k¡o¦yžŽ€€ow\rRqWui|€€”~¢z¤w›w‹z€€tˆl´z³€€mtq…€€qYg\€€…”t‘€€ª§›€€]e\q€€ˆs{s€€€‰qˆ€€¦¢™€€‡y•‹€€rw„‰€€vL„L€€UT€€€‡˜v”€€£qœo€€„‚Œ{€€^ƒ]{€€¤~£s€€}™Œ”€€{dŒ\€€l´z³€€mt±p¤mšqŒ{wˆg’b•j“{Ž”©p±b§_gxuq€x……†„“„ˆ‹{™y¥~©ƒ£‚—wŒmsulj–mruq^jUe^eslŠx €µ}¼t±k˜g~np~p‹zŠ…˜u™gˆatbhkiyxˆŒ‘¡Ž±„¶y±p¤mšqŒ{•—”¦{o”j^wQhd~„‰‡ˆ™v·‚¯••Žyrh\{Nˆ]xŒl¨b–Sq]Sg°ƒ¢všl”|wt\f\wZ}Y^oYwu]u`aˆfwze€O¯Z»~¡¤¢¡±y­\’]\¢]¥kŽŠs§r«užn–rˆ„v|•—”¦{oÅo»i²l¢xˆ„pŽc’c’o‘‚ˆ’w—hb€fqsr„…„ „•Œ‰™…¢„¤„ž~”ph…qz„p—k¢k›p†rtnnkuk…q”|¤„³¸v®h˜^€^thwp†q›j­]±P£KO„]ƒsŠ˜¯—À‹Ç|Åo»i²l¢xb•e¢€³€¢g~\^hVpqs€‡Œˆ£~Ž…‹•Ž”t‰O¤dš—u£[ŠQpXV~b¦ƒœ|Œi‰pskLOFXWx\‚mvƒi{VmPmŽz`‰Pº`ÁzšŸ¶¦—®b¥]§h¡c€ho’§ˆpvsˆ£›†zb•e¢€³€ÌrÄk»pª|…t‰cŠ^‰f‹qˆy||oxhrjnwx‚Œ†žƒ©©~ž†“‘Ž—Œ–ˆ‰o†g…q}…všq§q¢w‘|…{ƒx‰x“{™…Ÿ©Œ­¨p˜_„WxZ{^Š_¡[µR¼G°@¢B—P•hœƒ§–¶˜ÄŽÍ€ÌrÄk»pª|ŠKyK€€ª¨€€^–`‘€€‚u†€€€hpd€€ ž€€©ƒ¬‘€€fuq…€€|™€€vn‡|€€YX^U€€{¤pž€€ƒ_sY€€‹’{ƒ€€¯}±o€€j²x²€€„w‰€€RoR~€€„WsU€€Š²x³€€ŠKyK€€ªÁwºr±z¡„‰‡s„e€`}d‚h†hgugojqq}ƒ‰™‰ª‚°zªwœ~”ˆ’Š’†Ž€„{s~i‚q€‚{–x¢yž€‘ˆŒ‰Ž†”ƒ˜„•‹“–™™ž’ž–m†^yYxZ…[˜\¬Y²Q«F¡A›H™[v¤Œ¯“»ŽÂ‚Áwºr±z¡„eDa?up¤–µ¦¤«‰»y¶„¢†ƒtbmVcJ\Kuf{Œa˜]‰’ˆªˆŒ|||‹“—ˆœ¢t‚{£ƒ¡„ˆb”c­™¸tÁj±fŠfh„}—¡ˆ¬­ž˜wkm[Šm’u}kxgYwGf[fhˆ`…n‘ˆŠ§i¥bzeDa?up¤–©{¢x™‹Œ{Šo‚ixitm|k„d_z`uivx‚¥Œ±ƒ¯x¡r‘yŒƒ‚“|“u‹rzyn‚qƒ~€Œ|•}†‡ˆ‘Ž”ˆ”†‹‹ƒ˜†¢¢“–’…nuepcvf„k”mšh–X‘JŽHŽS‘j•œŒ¥‹ªƒ©{¢x™‹ŒLAT?}o›¡¡·£¬Ÿ²‚²sš†eŠHuZQ]KXlmm†Y€_y•}®{–„Š’ˆ…’`±[´u—œ‚´z¦sŸZªa«Ž›°‡µo°M•Qoz¥ª¥»Ž®¤…ŠemaY}]…uizWqUmfg„aŽoŽ‘—š˜ƒ…„kŠ]tLAT?}o›¡y‰v€€uŠn‰mqyyv€€z‰n…e}dumt€€—‹ª‹¯„¦|’x€€}‰…‡Ž€“yw€€r‰pˆwz†x€€x‰|Š…†‹‹{€€ux €¨‰£‹“€€ntesexnz„€€}nzZyPzV}i€€…‹Š’‚y‰v€€uŠ[OVO€€§|£€€–‡Ž”€€˜M¡O€€R…Vs€€€’rƒ€€¦£q€€ƒ†t€€N¨M£€€§w¡}€€‚cŒ\€€”‡€€KxKk€€ª§¥¡€€ˆŠ•€€vO‚P€€il€€“}–n€€{µ‡´€€wt†€€[OVO€€§…oivqom…r†{…††‡–{r„qyyuˆ›Š¨‹¨†š‚ƒ‚o‹l•t”Š„‹€€†ts‰x€~wszyrtyv|l{dogfxiŽrž{¡—w‡f|[{W[‹c“h’gƒhqjgmjqxt‹y“‹…}…oivqorvfqt›q²[›Xx€~¦€°g§Q‹qg¡Ož`Ž˜¡wŒ{ƒwpNnfu™w¥ƒ–x™y y•U–_xdrSŽV‰oarRMeK}u››«™“{u~€ŠˆtsVxjzŸq´z¯ˆ®“œ‰~hŠU¿UÂU^‡{ ˆ£rvfqt›q²„b€Zycuuv…{ƒ–Šš ˆ¡™~„†€‘‡œŽ£‹Ÿ†‚y…f‘^bžm—yŒ‚‚‚z†|ƒ‚~†y‡x€xƒs{pmm\fP\OU_Xx`k—r“p†dyXwP~N‹P™UžY—`g‡n‡sŽv™{™€‰„t„b€Zycuu‹„‹~už`¬V˜Uˆr¢®_‰ega¤[—b•€¡ˆ›r‚or{~f‚Mqdq’…ª‰Ÿ{š¢Š‹œa¢X‰pslQšF~SViS`uY”l£œ—‰Œ†Œ„€rhg[urŠ ‹¼€¼v°‡”{qHÀ@ÂU’a†mx§‹„‹~už`¬ˆW†Sƒ]‚s„Š‡›‰¥ˆ§…¦‚¢š…’‹Œ‘Œ•‘˜šˆ–‹|x‚fXŸT¤Yžg‘v~{{‰zz’}‚Šˆ‰w~mlcYZJREMRNiU_ŒiŒn€jq_kTpL€J”O¡Z¤f¥q¤y¡~Ÿ€ ‚—†€ˆhˆW†Sƒ]‚s§e«b€€jŒw€€€•Š•€€ab‹€€}mps€€ƒƒ€€‘Š›€€}t{†€€…^„d€€l›e¢€€¡gœq€€gleh€€…”yŽ€€“sŒn€€ˆ“‹€€lkke€€›–€€‘fœ`€€S®W¯€€†k{w€€§e«b€€jŒŒR‹T‹by”¦Œ­…©| y˜~‘ˆ‘Ž–’’•ŽŽŽŽs‰p~ynŠZœL¦J¤W•k‚}t‰q•q›v›–‰‰}ƒptdc[TWNTVQiS{Z†f…rzuhn\b]WmS„Y˜h¦x²ƒ¶‰±‰¦‰Š‹s‹]ŒR‹T‹by¢a­e˜}‘¥t±w™’uš]‰W|pl™TœG…Yr“Œ£©±«°¢™Šnxl\‡X‡lfpZb\`n†¦„·q´l¨r–lƒo…‚‘b•O…S_WL]mq›’¯§Œ‰c[cUƒg‘d‰\‰OƒLoidƒˆ®[¬Vl…u¢a­e˜}‘‰RŠ^Œp‘‡– –¯®„¡w‘t…|ˆ€’†“‰„‚q‡e‹cˆoy‚`˜J§B©Mœe†}uml¢r}”ˆŽ‰Œ€‡vmuhliefj_v[‚^ˆi…yxƒc€QuMkYfqmŠ ³”»”´¢‹‹|Šd‰T‰RŠ^Œp‘‡{z„ŸŒ¥}­y²‰”šg’awjntfTªE–]sƒy¨™»²¦¡ŠtxdimSŒ]”ˆˆ{mdfKŒZª~š„’~¤‚­†“xuq‚f”PŒQboFxNaiRp­¡•šjklRŽQŒQwcff_[jk€‰›x°V¬eƒt…{z„ŸŒ¥}{W|j€€‡•’ª—±–©Œ•€€{rmŠov~€€usyb‚X‹[Œj€€d—J«@±J§d’€€“užožo•u‡|€€~€{ƒy…y…{„€€|q‰g‘e“n€€ŒhŒQ„GzOvf€€˜š®šµ‘«†•€€l}X{P{W|j€€‡•lxj€€‰iƒi€€s•h•€€†tˆ€€­aªa€€l¤r§€€wjtt€€vj„€€²Œ³˜€€iLvL€€`\€€¥’¡‹€€‡t”m€€V¨[ª€€€NvN€€}™n€€£oœd€€h‰bw€€”Ÿ‹–€€ŠŽ€€lxj€€‰i__bvf‹q›§§—™–ƒŽn‰dŠa‹d‰krsrlgsYSˆX‰h}|b’J¦A®K¨d˜}ˆ|–q”k‰j{nspsuv{‰„Ž’–’…•y›sžxšˆ–z˜a“R‹R‡aŽu™‹›Ÿ‘¤šo„eod^aQ_Q__bvf‹q›qlSiNW]Jc[_q^ƒy’£ˆ§‡„‡¦f·T«\”|~”rƒys˜±‰ub~]šr’hqTOd[uY–Hv^oˆ‹ œ‰›}‘xzt¸Â­¡n^^Y‚p—‘‰®sºa³w¤‚—p s‘z”]‰h…wŠkqlSiNW]JCjIP‘\—o—Ž~–l–_’\Ž`‡h~prtgqgfsZ€U‰Y‡exs`‚K’DšM˜at„y‡m‰eƒdzgtlsuv…~“‹›š›§•¦š’—„†¡”ž£Ž©x¨e¡[š]›gŸx—‰†oˆZvNbITDOAWCjIP‘\—wa„NZaWttg€[y}}¨wµv¥€…x}k“i¬_°gŸˆƒ‘†€¢{±w¡[‰Otdpzou`fSZge†v•XzZzp“ˆ“v–i~fu˜¬±º¬§|ƒQr[Œ†žŸŒ™v—c£X³o¼~µo g”vxevOl\exuwa„NZaW4u=‰H‘T‹duqƒdŽ\”Y•`Žlƒxthbxjm{b‰^Ž_‡euk`rPzL€S‚blzrrzg€a‚ah}qxw’|Ÿ‰£›œ«‘®†¦‚™†œš¢¬·Ž¹|²k§`¡_œjx|€f~RqF_=S5T1a4u=‰H‘T‹”°’¯€€v™…€€\qd}€€›~¢ˆ€€W\€€›lœx€€vz€€€€‚bŽ[€€p˜zŒ€€hsgg€€„‰zw€€{œl“€€‹nye€€©ž¦—€€[jYd€€¥—£€€goih€€›“ŸŠ€€|ƒ€€€Wn\d€€”°’¯€€v7DŒR‹\zdfmWvRW`’oŒ‚p“ffvv‹n™k™k‹lvjdgYgXj_nhrkrkmqdz`ƒcˆm‡z}t¡s«}¨Ž™¡‡©w¥l›l’xŒ˜œ¬¢»ŸÀ’¹ªl›a‘e„qv{h}[vPfD\7`3m7DŒR‹\z ¬›Ã™¢¥¦Š’j~R›[­x°µl®X¢[’j}yp…s|wh„[šV˜wx¥t¥™š¶§°©†{q^{s‰Š…•„€“n…‹›|˜t¢Ž¬¢„YRKI\]†™—~¤[ªY§aži¢x¨ˆ›Š‰¡Ž’žwˆ†e¡p ¬›Ã™¢¥I†XŒiƒpkoSmGnKu\ƒo„Šš¦s¤l—r†ˆ|Ÿx«x¦y‘xzrjge`h`oeumrrlnogxcƒf‹rŠ‚|˜m¬e´j«z–ši™W’SŠ_†wŽŽ£ž¶§½¤µ•¢Žnmyvu€s†o‚htXjInDyI†XŒiƒpkv©pÁŽ¤Ÿ›—Š^–c¬vµn³f¯‰|uqh{y‚ˆu W¨YŒŠk²v§ ¢¾®¹¥“ˆ`ƒNŒs˜Ÿ¥‹Žby]nˆy¤r¥m§‰˜§k‹[U^Obp{‚ŒhŽ^¥Á½t¢d–tŒ}§d²l—”‹Ž›l›nv©pÁŽ¤Ÿ^ŠnŒ€€„e~NuEoPqg€€Œ•Œ¨„¯{§w“€€˜w¯x¹~°…™‡€€rrpivhn…y€€v{tpwg}g‚p€€q—_®V·Z¯j˜€€ŒgP†G}Pxg€€••©¨²­ª¥–‘€€s|rƒwŒ‘„Ž€€ou_wX^ŠnŒ€€„eK«K©€€Žk~q€€rql€€‹‚€€ª|­s€€]‹d‚€€u¡k¦€€¦V¤[€€¥Œª€€iJsK€€®š«€€LaLc€€—vŠi€€x°n®€€†jwr€€†ivb€€°¬±«€€Wu[ƒ€€ U£R€€}‹x€€K«K©€€Žkr“ƒ”•ˆšp“Z‡QZ~n‰„”–”£¤„—€€‡k›e®j¶w­„™‹ƒ‡xzxr€s‹{“‡†‰}zukpckfetYŒM¥J²S¯h~‰Šr‰X€ItKk[opƒ‡˜ž£« ¨š{Šq†tŒ”Œš•™‘Œ€ƒp…kŒr“ƒ”•ˆšpZ¶T©p{|fwa_IzJiŽ}‘wª’bE‘>lKWPrh†‘s£Gƒ9ZN^re‚ZlWOian—zº—©˜uj`Yp|ŠymlP‡]½{Ê•©ˆ|uV‚N—D’CZž‰ayJˆW¨y¨“x‹ibŽY˜p‡zZ¶T©p{|fƒ¢–¡©—°ƒ«o¡d—e‘p–~Š›’”‹‚…l‡X’RœY h›x„‚‚}w€pˆq“zœˆ“•‡wle`V_LkD‚?™D§T§m„‘e…QtJePb`pw…‘”¡˜£˜€‰w„}‰‹“šž¢£Œ–}˜yžƒ¢–¡©—°ƒ…¸t²eŠk€{|g†?{B‘q˜—‚›‡‰—”y¢]˜WƒMpK[JX_i‹h“Ko@]Mg\_dWcrbŠw}œm½±‚‡notz›^}`Q‰b¹‰Ä¬g€YSwPŸU§QŒVog\v[…_©s¼Š§Ÿz‘od”D˜T…}…¸t²eŠk€ˆ«¨±¡»“¼ƒµv«p quŸ{€—~s‡bƒP‚IN€\€l€x€xn„gŠh’qšŸŽ‘€}ne`O]Bi=}=G™[šu–Œ“™‰›t‘^~PiN]Xenvˆ‡˜’›’‘‡‚€{‡~”‰¡˜§¤ ¦¤~¦|©ˆ«¨±¡»“¤©¥€€s†s”€€rJgJ€€‡¦uŸ€€•‹ˆ—€€‹t†…€€llbw€€p{q€€„y€€Ÿ|¢s€€Y¦[§€€}rn€€«X§U€€„£’œ€€PlRh€€­Œ¯…€€Yv_l€€ƒ§}¦€€X£W€€MƒLr€€¤©¥€€s†~¨•¥© ¶™¾½…³|¥t›p™q—u•upˆf~XrOeP`Xeepp}qƒh†_‡]‰eŽu˜…ž‰˜ˆppeXbLnHI‰RŒd‹{‰Žž¦‚ o_wWd]cqoˆ•–“ŠŒz†pŒo—x¡ˆ¢™˜£ƒ¥s¨qª~¨•¥© ¶™‹«¡Ÿ£uŒsj{elgBiJƒ€——”~–`¢x˜‘Ž‰•Ž– “pxZƒs˜‘™“§¢­¡ž‰·„¡im\MwXŠ|€s}e’zŸ©x¬Zˆp‡†—n’RldcŒª¢³ž²p¬RŠc[ˆV~ofmeW”K´^¢‚l€Ptg†‹«¡Ÿ£uŒsj›–•“¥”²“¶Ž¯†Ÿ|r‹pŒtyŽzˆv|kf`Q\I_Qgfp|r†i‡]‚X~]kŠ}™…€•u„lpkexa…]‡`ƒk}{|Œ†¬Œ®€¡r‰hsljn’z›ˆ—ˆŠw„jŠc“g™t—†Š”sšaž^žj›–•“¥”c³z­œ„”qqkpb€H€RŽƒ¯±q™i“„Ž“|®†³€XcLelŽ“¡Œ«›ž¡‰…—x½Š­~s_ZWopuŠd‰}™¨‹¢ixpp|†bœU‰‚q©oª‰«²k©M‚X\vSkP]NoV¢l¹…§‘ƒ€dv_Žc³z­œ„”qW†l€€… Œ§¡‘‰€€z|€€‰†ŽŠŒ‰€€ftNnDoMve}€€‹vˆh_vatm€€“‰Ÿ… |—sˆs€€y‹o‰ijvrt€€”Ž¨‘²‹«‚—{€€s‘q¢w¨€¢…‘€€zo€bŠ]dŽr€€g‡S‹MŠW†l€€…c§\¥€€ˆpvx€€c€\€€¦ˆ§v€€x‘‡‚€€w©…¬€€XKXK€€“ˆŠv€€p”e‡€€µ¡µ¥€€cXmZ€€f|^n€€¬‰¨w€€fi}€€‡¥ƒ¤€€•|›Š€€alfu€€rmfi€€¦– ’€€zhc€€c§\¥€€ˆpEvWtitz|ŠŠ’—ž~m•it„“’”˜‡w}`zV]ˆsŒ’•‡w‚ntom|uŽˆ—˜’ ‡ }š{–‡Ž‘}Œmcrbllvƒ‡Ž®¯‰¡…Œ‰|˜s¨q°q­p¡i’fpm~^‰Y‰]|fcnKt@wEvWtitz|upSpb]lqaŸf³hSxSŽqxmfmp|sšw£”²¦h}InM‚qvddNfPc‰~Š ¤¬µ“¥nQfJiMhik{©«†›ž‰ w†u‡ƒ™}²S¶T¦fjŠyž¡³³˜¡{”‹˜ª˜›ua~E›>¢VupSpb]lq6oCsRuc€v“€¤}¯o°^¨ZŸg™~••‘¤‹¢‚|zo‰t•†›œ£Žœ~Šuuyfˆfœu¤…Ÿ““žˆ¤…¨¡™‹r^lUc[jt|•‡­Œ´Š«†™‡†‘ui§`ªZ¨R£S”c|vd„R‡J{M`WEa6i6oCsRuc€lRSR[`d‹e±_³Q—GˆQ˜X[lidzo‡s—…ºŽÃu¦bˆdydtfkj^fO_\l{}€zw~ˆ™œ©ˆ¥_Jrbm‰~˜…o€”¤©—Ÿx†{†’i°R§R‰Z„p¤š··³²”¬¤“±…¨€‡jF¤@šRlRSR[`d‹1q;zHYŠmžy°x¹k¸Z®S¡_–v‘‡§€¬xžwŽ€„Ž†š’¡£œ«Š¥x“q{yfŒ^¢eªo¤~˜ Š­•©““w^jQ]Ubpu“„­Œ·Š°„Ÿ€Š‚uˆc‘VšN£H¨M `Švn†U‰E|DaMEZ3f1q;zHYŠbmld€€ˆ¢Œ€€lmmm€€s‚g{€€‰}ws€€¬Š©~€€w”ƒ€€y„ƒ‰€€…€“Š€€Wh\m€€‹š†¢€€Žv’‰€€YYT`€€ªx¥n€€ee„€€zvli€€¥§Ÿ¡€€fŠc—€€ v‰€€‡_”i€€bmld€€ˆ¢9yD‚Qˆa”u¦´¹t³b¥W•[ˆl…zw§q s”€Œ‹š“œ ’ª}©jœd†nn…aœ]¥^ g•y‹ˆ£“¤›”“|emX`]dxw˜ˆ¯¶­ƒ›x‡rqoatWR’O¡W¡k“€|dŒQ~MdUJa:m9yD‚Qˆa”“‰¡š¤˜¬vŸ]SI±L¡^Œu‘†‰wvW„S¡r†SœV«v²„¦Œ¤¨±°²¯¬¦­ƒ¨O’Eyel‹z¬€´g¢fz_vWQaYzx“zyoƒJ‹A]Ÿj ju‘Š¥z•Ws:{;Š_v†n‚xxƒi™‡ŽŸ“‰¡š¤˜LZ…g‹v–‰¦”¯“®…£q’b‚\wcqurŠt–r“uŒƒ…ƒ—ˆ”’…Ÿm¦X¢Q“]~vnŽ`˜U”U‹b‚y€Š—”€ƒptgkno‡‚¢“²š±•¢†Žv|hl\cZafd{fn™€–Š—y‘i€egkRrHyLZ…g‹v––‰£–˜›“r¢U™dŠq ^±LªX¢k’trjlXŽQ r€˜Q–M–a§s …¤ ²³º¦¯ž†¨O´D n{žm¹k´`jeƒev‡XizŠ}’‰‰|vJc=nb—€·}±j˜s˜t•\ƒ4€5…apkž‰uŽpž˜––‰£–˜›“r^}q}€€Ž‹Ÿš¨¢¤Ÿ”’€€lq^k\meut~€€‚yt—r™v‘€€ežN¤EŸOg€€m‰Y†P~Vviu€€‹ŒŠ‚‡y~vy€€–‘«¢³©«¢–‘€€plgYgPoWzj€€‡Ž••ž“ž‹“€€i‚X‚T^}q}€€Ž‹‡s•„€€vO‰N€€jŸx–€€…’ƒ€€R~T€€ž‘šœ€€pur‡€€„aj€€˜q k€€K¨K©€€£nœy€€d‰]•€€´^´f€€s“…™€€OTOQ€€¨­£ª€€„y‘…€€P~PŒ€€£zž‹€€~x†Š€€‡s•„€€vOhp{fŠe˜p¨±‰¬ˆœ}‡mrbacZn^}h‹pnf—_ž\ž_”h‚yhP›DžK—^Œs{zfvZn\fje~oŠ|Š„„ˆ}Šzƒ––§¥·§½š·‚§l–`_ggWvU†bv’‡ž’¥—£—–”‚•m•^Œ\hp{fŠe˜p}{˜„p‚J†[s•R®V¦fš}Ÿ”•‰\•^¦|£™˜¥”|„}‡Ž‰‡r{nvv€n…nw}`—j“f§X‹r`ˆO‰f‡šrº`¤fmpj{„Š†‰fgf]‚¤¢¹”±r«j©aœR‚a„€£|±|™šxŸz‹„sy}{˜„p‚JiezQ‡K•V§d±m®mŸeŠXvSf[_la€hŽleX—LžFŸH–Q…alvV‡K‘N“[h„judj\jVuU†\iw†…|”v¡{­‰¼’ÊЀÊi»V¬P•Vvd_wW‡^p‘‚œ¤™¥ž› Š¥u¥d–`~iezQ‡K•V‚š™ž™vPŒbqšE Go›žª‹Œvx’«Š›’qšd‡|x‘€™•v–€ˆ‰vˆkŒzŒ“•‹g«K–ZivOujmŸh¬{ŒŠc€kf‰e”|vŠl|„|—›†²~¤€—fžP©eªy¨o¦n—Š¥”Œ—r‚w‚š™ž™vPfbsI~AŒJŸU«\«]W‰NwNl[iolqŒqŠd‡RC—<›?–H†Upd`sXZ‡a‹f‰aY{R{NOŽS–\”l‰€|–q©q·zÃ}ÏxÔkÏZÃLµKžV~fdwY„_…p‡‚’ž—£œž ©z«iœafbsI~AŒJt´€´€€„P’S€€LKq€€¯œ­’€€v™‚¡€€€KJ€€s—ƒŠ€€mv€€cƒ[ˆ€€ˆ“”€€˜[¡a€€SWy€€”Ÿ€€~W€W€€‘ƒ›s€€_‹gy€€s•jŠ€€œ‘–“€€zn{p€€p–e€€t´€´€€„PbklSuKƒR—Y¤]¥]™Y…TvXpfswz„ˆzh|T„EŽA•F“P…Xs_jgholyoƒkŠ`ŠWˆS‡S‰V’X™[–gŒy}Žp£l¯p¹pÂlÇdÃZ¹S­U˜azocz[c|u{…†”œ‘œ”Ÿ|¦i`‡bklSuKƒRg”\OhlMœP›hhea`q°Œ¥œ¦zº©|vzB…>ƒl‰v¥_ªV”q~ovPmI]jL|hn“dŒŽj©n‘ˆf”Z h¦« œ±¨_‹]r~‰œ|›{wtaejvk l³€³ˆ·j¨OŒMrKkQvfkwarrg”\OhlM`}jktei”m¡o¡m•jgsmsz{†„‹‰‡‚{nuZ{O‡Q[g‚jtgrewg}o}vŠg_Ž^Šcˆii•f•iŽr‚€vp™q p©n­kªi¢g—l…vl\ƒZ€gw|uŠ~ŒŠˆ”ƒ•‚‹w›f›^`}jkteimciN`un¢zŸmvZq[–f©f{Ž “”±w{FoAzc”c§R­Y°€Ÿ’~‰WwJ\bLel`”o‰¢gµh˜v„Š}¦q¢f†Ž°ºv¦dƒpv…”Ÿ~ZqUw}‰­‰¿³…­_šR}ThKrT‰d€nk}fmciN`ungŽuƒ€€Œƒœ†¦†¤„•€€s…s{—…—‰Ž€€lx\}X‡aŽq€€€txuolˆq‹€€o‘il„v}€€‰wpo‹r„y€€†~Ž~“~‘‰€€…o\“R’V‹h€€{ŒŠ‡Œx‹u€€n‘a™_˜gŽuƒ€€Œƒ–z‹w€€–žš¥€€]g]s€€Œa‚[€€Š³‡³€€mWd]€€”z‰o€€šŸ—€€_{c~€€u“iž€€­e©q€€Œ‘–€€TdXl€€žwŸs€€^¡]§€€€KrK€€“¥‡Ÿ€€~…tŽ€€„fwj€€‚…s„€€–z‹w€€–žwžŒ™™—¤š°œµœ®š—‰”{˜w¡y¦}¤~›u‹f‚\„]‰jŒ}ˆŒzŒoƒsz€uŽy•‡•~–z~‡srŽ{ƒ„w‹ompŒtŒy~ŽŽzŽpŽf‘Y—KšH™S’iˆ‚€Ž…zyun|a^šf wžŒ™™—¤š{´‰®Š¨Œ¶vµT”7w@j’|xvw‹ƒ¨œvwpouŽ‡²€Ÿ]LŠeœn„WlVv†ˆ¯˜¬‚¦„z›kŒ„a”^“z—„‡ib_LgJy_{`²:Â5µS‡WRPDacztqe_Lcls¡†¬Œ‰YN€fc•a³{´‰®Š¨Œ¶ \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.fsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.fsh new file mode 100644 index 0000000..b48472d --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_noise.fsh @@ -0,0 +1,39 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out float realisticWaterDisplacementOutput1f; + +uniform sampler2D u_noiseTexture; + +uniform vec4 u_waveTimer4f; + +void main() { + vec2 sampleA = v_position2f + vec2(-0.093, -0.056) * (u_waveTimer4f.x + 0.12); + sampleA = textureLod(u_noiseTexture, fract(sampleA) * 0.46875 + vec2(0.015625, 0.015625), 0.0).rg; + vec2 sampleB = v_position2f + vec2(0.075, 0.153) * (u_waveTimer4f.x + 1.33); + sampleB = textureLod(u_noiseTexture, fract(sampleB) * 0.46875 + vec2(0.515625, 0.015625), 0.0).rg; + vec2 sampleC = v_position2f + vec2(0.075, -0.113) * u_waveTimer4f.x + vec2(sampleA.g, sampleB.g) * 0.15; + sampleC = textureLod(u_noiseTexture, fract(sampleC) * 0.46875 + vec2(0.515625, 0.515625), 0.0).rg; + vec2 sampleD = v_position2f + vec2(-0.135, 0.092) * u_waveTimer4f.x + sampleC * 0.1; + sampleD = textureLod(u_noiseTexture, fract(sampleD) * 0.46875 + vec2(0.015625, 0.515625), 0.0).rg; + realisticWaterDisplacementOutput1f = dot(vec4(sampleA.r, sampleB.r, sampleC.r, sampleD.r), vec4(0.63, 0.40, 0.035, 0.035)) + dot(vec2(sampleC.g, sampleD.g), vec2(-0.075 * sampleA.g, 0.053 * sampleA.r)); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_normals.fsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_normals.fsh new file mode 100644 index 0000000..f255eb8 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_normals.fsh @@ -0,0 +1,33 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec2 realisticWaterNormalOutput2f; + +uniform sampler2D u_displacementTexture; +uniform vec2 u_sampleOffset2f; + +void main() { + float A = textureLod(u_displacementTexture, v_position2f, 0.0).r; + float B = textureLod(u_displacementTexture, v_position2f + vec2(u_sampleOffset2f.x, 0.0), 0.0).r; + float C = textureLod(u_displacementTexture, v_position2f - vec2(0.0, u_sampleOffset2f.y), 0.0).r; + realisticWaterNormalOutput2f = clamp((vec2(A * A) - vec2(B, C) * vec2(B, C)) * 10.0 + 0.5, vec2(0.0), vec2(1.0)); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.fsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.fsh new file mode 100644 index 0000000..93b416b --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.fsh @@ -0,0 +1,433 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision highp sampler2DShadow; + +in vec4 v_position4f; +in vec2 v_positionClip2f; + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 v_texture2f; +#else +uniform vec2 u_textureCoords01; +#endif + +uniform vec4 u_color4f; + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec3 v_normal3f; +in float v_block1f; +#else +uniform vec3 u_uniformNormal3f; +uniform float u_blockConstant1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 v_lightmap2f; +#else +uniform vec2 u_textureCoords02; +#endif + +uniform mat4 u_inverseViewMatrix4f; +uniform mat4 u_modelViewProjMat4f_; + +layout(location = 0) out vec4 output4f; + +#ifdef COMPILE_DYNAMIC_LIGHTS +struct DynamicLight { + mediump vec4 u_lightPosition4f; + mediump vec4 u_lightColor4f; +}; +layout(std140) uniform u_chunkLightingData { + mediump int u_dynamicLightCount1i; + mediump int _paddingA_; + mediump int _paddingB_; + mediump int _paddingC_; + DynamicLight u_dynamicLightArray[12]; +}; +#endif + +layout(std140) uniform u_worldLightingData { + mediump vec4 u_sunDirection4f; + mediump vec4 u_sunColor3f_sky1f; + mediump vec4 u_fogParameters4f; + mediump vec4 u_fogColorLight4f; + mediump vec4 u_fogColorDark4f; + mediump vec4 u_fogColorAddSun4f; + mediump vec4 u_blockSkySunDynamicLightFac4f; +#ifdef COMPILE_SUN_SHADOW_LOD0 + mediump mat4 u_sunShadowMatrixLOD04f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 + mediump mat4 u_sunShadowMatrixLOD04f; + mediump mat4 u_sunShadowMatrixLOD14f; + mediump mat4 u_sunShadowMatrixLOD24f; +#define DO_COMPILE_SUN_SHADOWS +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif +}; + +#ifdef DO_COMPILE_SUN_SHADOWS +uniform sampler2DShadow u_sunShadowDepthTexture; +#ifdef COMPILE_SUN_SHADOW_SMOOTH +const vec2 POISSON_DISK[7] = vec2[]( +vec2(-0.077, 0.995), vec2(0.998, 0.015), +vec2(-0.116, -0.987), vec2(-0.916, 0.359), +vec2(-0.697, -0.511), vec2(0.740, -0.612), +vec2(0.675, 0.682)); +#define SMOOTH_SHADOW_SAMPLES 1.0 / 8.0 +#define SMOOTH_SHADOW_RADIUS 0.00075 +#define SMOOTH_SHADOW_POISSON_SAMPLE(idx, tex, lod, vec3Pos, accum, tmpVec2)\ + tmpVec2 = vec3Pos.xy + POISSON_DISK[idx] * SMOOTH_SHADOW_RADIUS;\ + tmpVec2 = clamp(tmpVec2, vec2(0.001), vec2(0.999));\ + tmpVec2.y += lod;\ + tmpVec2.y *= SUN_SHADOW_MAP_FRAC;\ + accum += textureLod(tex, vec3(tmpVec2, vec3Pos.z), 0.0) * SMOOTH_SHADOW_SAMPLES; +#endif +#endif + +uniform sampler2D u_environmentMap; +uniform sampler2D u_irradianceMap; +uniform sampler2D u_reflectionMap; +uniform sampler2D u_refractionMap; +uniform sampler2D u_brdfLUT; +uniform sampler2D u_normalMap; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +uniform sampler2D u_lightShaftsTexture; +#endif + +uniform vec4 u_waterWindOffset4f; +uniform vec3 u_wavingBlockOffset3f; + +#define WATER_ROUGHNESS 0.03 +#define WATER_F0 0.6 + +vec3 eaglercraftLighting_Water(in vec3 albedo, in vec3 radiance, in vec3 viewDir, in vec3 lightDir, in vec3 normalVec) { + float roughness = 1.0 - WATER_ROUGHNESS * 0.85; + vec3 H = normalize(viewDir + lightDir); + vec3 NdotHVL = max(normalVec * mat3(H, viewDir, lightDir), vec3(0.0)); + float NDF = (WATER_ROUGHNESS * WATER_ROUGHNESS * WATER_ROUGHNESS * WATER_ROUGHNESS); + float denom = NdotHVL.x * NdotHVL.x * (NDF - 1.0) + 1.0; + NDF /= denom * denom * 3.141592; + float gs = WATER_ROUGHNESS + 1.0; + gs *= gs * 0.125; + vec2 Ndot = NdotHVL.yz; + Ndot /= Ndot * (1.0 - gs) + gs; + NDF *= Ndot.x * Ndot.y; + float fresnel = pow(max(1.0 - NdotHVL.x, 0.0), 5.0); + vec3 F = vec3(WATER_F0 + (1.0 - WATER_F0) * fresnel); + vec3 kD = (1.0 - F) * albedo / 3.141592; + denom = 4.0 * NdotHVL.y * NdotHVL.z + 0.0001; + return (kD + (NDF * F / denom)) * radiance * NdotHVL.z; +} + +vec3 eaglercraftIBL_Specular_Water(in vec3 envMapSample, in vec3 viewDir, in vec3 normalVec) { + float NdotV = dot(normalVec, -viewDir); + float fresnel = pow(max(1.0 - NdotV, 0.0), 5.0); + vec3 F = vec3(WATER_F0 + (max(1.0 - WATER_ROUGHNESS, WATER_F0) - WATER_F0) * fresnel); + vec2 brdf2f = vec2(max(NdotV, 0.0), WATER_ROUGHNESS); + brdf2f = 1.0 - brdf2f; + brdf2f *= brdf2f; + brdf2f = 1.0 - brdf2f; + brdf2f = textureLod(u_brdfLUT, brdf2f, 0.0).rg; + return envMapSample * (F * brdf2f.r + brdf2f.g); +} + +mat3 cotangent_frame(in vec3 N, in vec3 p, in vec2 uv) { + vec3 dp1 = dFdx(p); + vec3 dp2 = dFdy(p); + vec2 duv1 = dFdx(uv); + vec2 duv2 = dFdy(uv); + vec3 dp2perp = cross(dp2, N); + vec3 dp1perp = cross(N, dp1); + vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; + vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; + float invmax = inversesqrt(max(dot(T,T), dot(B,B))); + return mat3(T * invmax, B * invmax, N); +} + +void main() { + vec4 worldPosition4f; + vec4 worldDirection4f; + vec4 diffuseColor4f; + vec3 normalVector3f; + vec2 lightmapCoords2f; + float block1f; + + // =========== RESOLVE CONSTANTS ============ // + + worldPosition4f = u_inverseViewMatrix4f * v_position4f; + worldPosition4f.xyz /= worldPosition4f.w; + worldPosition4f.w = 1.0; + worldDirection4f = u_inverseViewMatrix4f * vec4(v_position4f.xyz / v_position4f.w, 0.0); + worldDirection4f.xyz = normalize(worldDirection4f.xyz); + +#ifdef COMPILE_ENABLE_LIGHTMAP +#ifdef COMPILE_LIGHTMAP_ATTRIB + lightmapCoords2f = v_lightmap2f; +#else + lightmapCoords2f = u_textureCoords02; +#endif +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + normalVector3f = normalize(v_normal3f); + block1f = round(v_block1f); +#else + normalVector3f = u_uniformNormal3f; + block1f = u_blockConstant1f; +#endif + + normalVector3f = normalize(mat3(u_inverseViewMatrix4f) * normalVector3f); + + // ========= CALCULATE DIFFUSE COLOR ========== // + +#ifdef COMPILE_COLOR_ATTRIB + diffuseColor4f = v_color4f * u_color4f; +#else + diffuseColor4f = u_color4f; +#endif + + diffuseColor4f *= vec4(0.0478, 0.0585, 0.1, 1.0); + + // ======== SAMPLE REFLECT/REFRACT ======== // + +#ifdef COMPILE_TEXTURE_ATTRIB + vec2 texCoords2f = v_texture2f; +#else + vec2 texCoords2f = u_textureCoords01; +#endif + + vec4 worldPosition4fOff = worldPosition4f; + worldPosition4fOff.xyz += u_wavingBlockOffset3f; + + vec2 rotatedUV2f = worldPosition4fOff.xz + (block1f == 10.0 ? u_waterWindOffset4f.z * texCoords2f : u_waterWindOffset4f.xy); + rotatedUV2f *= (block1f == 10.0 ? 0.75 : 0.25); + mat3 cf = cotangent_frame(normalVector3f, worldDirection4f.xyz, rotatedUV2f); + vec3 surfaceNormalsMap3f = vec3(textureLod(u_normalMap, rotatedUV2f, 0.0).rg, 0.0); + surfaceNormalsMap3f.xy *= 2.0; + surfaceNormalsMap3f.xy -= 1.0; + + vec3 surfaceNormalsMapFlat3f = cf * surfaceNormalsMap3f; + surfaceNormalsMapFlat3f *= 0.1; + + surfaceNormalsMap3f.z = 8.0; + surfaceNormalsMap3f = normalize(surfaceNormalsMap3f); + normalVector3f = surfaceNormalsMap3f = cf * surfaceNormalsMap3f; + + vec4 worldPosition4fOff2 = worldPosition4f; + worldPosition4fOff2.xyz -= surfaceNormalsMapFlat3f * 4.0; + vec3 reflectCoordsR = mat4x3( + u_modelViewProjMat4f_[0].xyw, + u_modelViewProjMat4f_[1].xyw, + u_modelViewProjMat4f_[2].xyw, + u_modelViewProjMat4f_[3].xyw) * worldPosition4fOff2; + reflectCoordsR.xy /= reflectCoordsR.z; + reflectCoordsR.xy *= 0.5; + reflectCoordsR.xy += 0.5; + + worldPosition4fOff2 = worldPosition4f; + worldPosition4fOff2.xyz += surfaceNormalsMapFlat3f; + vec3 reflectCoordsL = mat4x3( + u_modelViewProjMat4f_[0].xyw, + u_modelViewProjMat4f_[1].xyw, + u_modelViewProjMat4f_[2].xyw, + u_modelViewProjMat4f_[3].xyw) * worldPosition4fOff2; + reflectCoordsL.xy /= reflectCoordsL.z; + reflectCoordsL.xy *= 0.5; + reflectCoordsL.xy += 0.5; + + vec4 envMapSample4f = textureLod(u_reflectionMap, reflectCoordsR.xy, 0.0); + vec4 refractionSample = textureLod(u_refractionMap, reflectCoordsL.xy, 0.0); + +#ifdef COMPILE_COLOR_ATTRIB + refractionSample *= v_color4f * v_color4f * u_color4f * u_color4f; +#else + refractionSample *= u_color4f * u_color4f; +#endif + + // ============ SUN LIGHTING ============== // + + diffuseColor4f.rgb *= diffuseColor4f.rgb; + + vec3 lightColor3f = vec3(0.0); + if(dot(u_sunDirection4f.xyz, normalVector3f) > 0.0 && lightmapCoords2f.g > 0.5 && + (u_sunColor3f_sky1f.r + u_sunColor3f_sky1f.g + u_sunColor3f_sky1f.b) > 0.001) { +#ifdef DO_COMPILE_SUN_SHADOWS + + // ========== SUN SHADOW: LOD0 ============ // + + float skyLight = max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); + float shadowSample = 1.0; + vec4 shadowWorldPos4f = worldPosition4f; + shadowWorldPos4f.xyz += normalVector3f * 0.05; + + vec4 shadowTexPos4f; + vec2 tmpVec2; + for(;;) { + shadowTexPos4f = u_sunShadowMatrixLOD04f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy * vec2(1.0, SUN_SHADOW_MAP_FRAC), shadowTexPos4f.z), 0.0); +#ifdef COMPILE_SUN_SHADOW_SMOOTH + shadowSample *= SMOOTH_SHADOW_SAMPLES; + SMOOTH_SHADOW_POISSON_SAMPLE(0, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(1, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(2, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(3, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(4, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(5, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(6, u_sunShadowDepthTexture, 0.0, shadowTexPos4f.xyz, shadowSample, tmpVec2) + shadowSample = max(shadowSample * 2.0 - 1.0, 0.0); +#endif + break; + } + +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowTexPos4f = u_sunShadowMatrixLOD14f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 1.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowTexPos4f = u_sunShadowMatrixLOD24f * shadowWorldPos4f; + if(shadowTexPos4f.xyz == clamp(shadowTexPos4f.xyz, vec3(0.005), vec3(0.995))) { + shadowTexPos4f.y += 2.0; + shadowTexPos4f.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowTexPos4f.xy, shadowTexPos4f.z + 0.00015), 0.0); + } +#endif + break; + } +#endif + lightColor3f = u_sunColor3f_sky1f.rgb * max(lightmapCoords2f.g * 2.0 - 1.0, 0.0); +#ifdef DO_COMPILE_SUN_SHADOWS + lightColor3f *= shadowSample * skyLight; +#endif + lightColor3f = eaglercraftLighting_Water(diffuseColor4f.rgb, lightColor3f, -worldDirection4f.xyz, u_sunDirection4f.xyz, normalVector3f) * u_blockSkySunDynamicLightFac4f.z; + } + + // =========== REFLECTION MAP =========== // + + lightmapCoords2f *= lightmapCoords2f; + + float e = 0.0; + e += envMapSample4f.g <= 0.0 ? 0.0 : 1.0; + e += lightmapCoords2f.y > 0.5 ? 0.0 : 1.0; + //e += abs(normalVector3f.y) > 0.1 ? 0.0 : 1.0; + if(e == 0.0) { + vec3 reflectDir = reflect(worldDirection4f.xyz, normalVector3f); + reflectDir.xz /= abs(reflectDir.y) + 1.0; + float dst = 1.0 - dot(reflectDir.xz, reflectDir.xz); + dst *= dst; + reflectDir.xz *= 0.975; + if(dst < 0.005) { + vec4 sample1 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, 0.25) + vec2(0.5, 0.25), 0.0); + vec4 sample2 = textureLod(u_environmentMap, reflectDir.xz * vec2(0.5, -0.25) + vec2(0.5, 0.75), 0.0); + envMapSample4f = vec4(mix(sample1.rgb, sample2.rgb, smoothstep(0.0, 1.0, reflectDir.y * -12.5 + 0.5)).rgb, min(sample1.a, sample2.a)); + }else { + reflectDir.xz *= vec2(0.5, reflectDir.y > 0.0 ? 0.25 : -0.25); + reflectDir.xz += vec2(0.5, reflectDir.y > 0.0 ? 0.25 : 0.75); + envMapSample4f = textureLod(u_environmentMap, reflectDir.xz, 0.0); + } + envMapSample4f.rgb *= (lightmapCoords2f.y * 2.0 - 1.0); + } + + if(envMapSample4f.g > 0.0) { + lightColor3f += eaglercraftIBL_Specular_Water(envMapSample4f.rgb, worldDirection4f.xyz, normalVector3f) * 0.5; + } + +#ifdef COMPILE_DYNAMIC_LIGHTS + + // =========== DYNAMIC LIGHTING =========== // + + vec3 dlightDist3f, dlightDir3f, dlightColor3f; + int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i; // hate this + for(int i = 0; i < safeLightCount; ++i) { + dlightDist3f = u_dynamicLightArray[i].u_lightPosition4f.xyz - worldPosition4f.xyz; + dlightDir3f = normalize(dlightDist3f); + if(dot(dlightDir3f, normalVector3f) <= 0.0) { + continue; + } + dlightColor3f = u_dynamicLightArray[i].u_lightColor4f.rgb / dot(dlightDist3f, dlightDist3f); + if(dlightColor3f.r + dlightColor3f.g + dlightColor3f.b < 0.025) { + continue; + } + lightColor3f += eaglercraftLighting_Water(diffuseColor4f.rgb, dlightColor3f, -worldDirection4f.xyz, dlightDir3f, normalVector3f) * u_blockSkySunDynamicLightFac4f.w; + } + +#endif + + // ============ CACLULATE FOG ============= // + + vec4 fogBlend4f = vec4(0.0); + while(u_fogParameters4f.x > 0.0) { + float atmos = u_fogParameters4f.x >= 4.0 ? 4.0 : 0.0; + float type = u_fogParameters4f.x - atmos; + fogBlend4f = mix(u_fogColorLight4f, u_fogColorDark4f, lightmapCoords2f.g); + + float f, l = sqrt(dot(v_position4f.xyz, v_position4f.xyz)); + if(type == 1.0) { + f = (l - u_fogParameters4f.z) / (u_fogParameters4f.w - u_fogParameters4f.z); + }else { + f = 1.0 - exp(-u_fogParameters4f.y * l); + } + + fogBlend4f.a *= clamp(f, 0.0, 1.0); + + if(atmos == 0.0) { + break; + } + + vec3 atmosSamplePos = v_position4f.xyz / -l; + atmosSamplePos.xz /= abs(atmosSamplePos.y) + 1.0; + atmosSamplePos.xz *= vec2(-0.5, -0.25) * 0.75; + atmosSamplePos.xz += vec2(0.5, 0.25); + + fogBlend4f.rgb *= textureLod(u_irradianceMap, atmosSamplePos.xz, 0.0).rgb + u_fogColorAddSun4f.rgb; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS + fogBlend4f.rgb *= pow(textureLod(u_lightShaftsTexture, v_positionClip2f * 0.5 + 0.5, 0.0).r * 0.9 + 0.1, 2.25); + fogBlend4f.a = fogBlend4f.a * 0.9 + 0.1; +#endif + break; + } + + // ============ OUTPUT COLOR ============== // + + vec3 blockLight = lightmapCoords2f.r * vec3(1.0, 0.5809, 0.2433) * 2.0 * u_blockSkySunDynamicLightFac4f.x; + vec3 skyLight = (lightmapCoords2f.g + 0.05) * vec3(0.9102, 0.9, 1.0) * u_blockSkySunDynamicLightFac4f.y; + diffuseColor4f.rgb *= (skyLight + blockLight) * 0.075; + diffuseColor4f.rgb += lightColor3f; + diffuseColor4f.rgb = mix(diffuseColor4f.rgb + refractionSample.rgb, fogBlend4f.rgb, fogBlend4f.a); + output4f = vec4(diffuseColor4f.rgb, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.vsh b/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.vsh new file mode 100644 index 0000000..cd6e01d --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/realistic_water_render.vsh @@ -0,0 +1,80 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +in vec3 a_position3f; + +out vec4 v_position4f; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS +out vec2 v_positionClip2f; +#endif + +#ifdef COMPILE_TEXTURE_ATTRIB +in vec2 a_texture2f; +out vec2 v_texture2f; +uniform mat4 u_textureMat4f01; +#endif + +#ifdef COMPILE_COLOR_ATTRIB +in vec4 a_color4f; +out vec4 v_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB +in vec4 a_normal4f; +out vec3 v_normal3f; +out float v_block1f; +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB +in vec2 a_lightmap2f; +out vec2 v_lightmap2f; +uniform mat4 u_textureMat4f02; +#endif + +uniform mat4 u_modelviewMat4f; +uniform mat4 u_projectionMat4f; + +#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) + +void main() { + v_position4f = u_modelviewMat4f * vec4(a_position3f, 1.0); + +#ifdef COMPILE_TEXTURE_ATTRIB + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; +#endif + +#ifdef COMPILE_COLOR_ATTRIB + v_color4f = a_color4f; +#endif + +#ifdef COMPILE_NORMAL_ATTRIB + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); + v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); +#endif + +#ifdef COMPILE_LIGHTMAP_ATTRIB + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; +#endif + + gl_Position = u_projectionMat4f * v_position4f; + +#ifdef COMPILE_FOG_LIGHT_SHAFTS + v_positionClip2f = gl_Position.xy / gl_Position.w; +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/reproject_control.fsh b/sources/resources/assets/eagler/glsl/deferred/reproject_control.fsh new file mode 100644 index 0000000..8feaccf --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/reproject_control.fsh @@ -0,0 +1,236 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +#ifdef COMPILE_REPROJECT_SSAO +layout(location = 0) out vec4 reprojectionSSAOOutput4f; +#ifdef COMPILE_REPROJECT_SSR +layout(location = 1) out vec4 reprojectionReflectionOutput4f; +layout(location = 2) out vec4 reprojectionHitVectorOutput4f; +#endif +#else +layout(location = 0) out vec4 reprojectionReflectionOutput4f; +layout(location = 1) out vec4 reprojectionHitVectorOutput4f; +#endif + +uniform sampler2D u_gbufferDepthTexture; +#ifdef COMPILE_REPROJECT_SSAO +uniform sampler2D u_ssaoSampleTexture; +// R: ssao history length +// G: ssao value +// B: pixel opacity +// A: padding +uniform sampler2D u_reprojectionSSAOInput4f; +#endif + +#ifdef COMPILE_REPROJECT_SSR +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_gbufferMaterialTexture; + +// R: reflection R +// G: reflection G +// B: reflection B +// A: current step +uniform sampler2D u_reprojectionReflectionInput4f; + +// R: relative X of reflected pixel from origin +// G: relative Y of reflected pixel from origin +// B: relative Z of reflected pixel from origin +// A: is reflected flag +uniform sampler2D u_reprojectionHitVectorInput4f; + +uniform sampler2D u_lastFrameColorInput4f; + +uniform mat4 u_projectionMatrix4f; +uniform mat4 u_inverseProjectionMatrix4f; +uniform mat4 u_lastInverseProjMatrix4f; + +// matrix to transform view pos in old frame to view pos in current frame +uniform mat4 u_reprojectionInverseViewMatrix4f; +uniform mat4 u_viewToPreviousProjMatrix4f; + +#endif + +uniform sampler2D u_reprojectionDepthTexture; + +uniform mat4 u_inverseViewProjMatrix4f; +uniform mat4 u_reprojectionMatrix4f; + +// x = near plane +// y = far plane +// z = near plane * 2 +// w = far plane - near plane +uniform vec4 u_nearFarPlane4f; + +uniform vec4 u_pixelAlignment4f; + +#define reprojDepthLimit 0.25 + +#define GET_LINEAR_DEPTH_FROM_VALUE(depthSample) (u_nearFarPlane4f.z / (u_nearFarPlane4f.y + u_nearFarPlane4f.x + (depthSample * 2.0 - 1.0) * u_nearFarPlane4f.w)) + +#define CREATE_DEPTH_MATRIX(matrix4fInput) mat4x2(matrix4fInput[0].zw,matrix4fInput[1].zw,matrix4fInput[2].zw,matrix4fInput[3].zw) + +void main() { + vec2 v_position2f2 = (floor(v_position2f * u_pixelAlignment4f.xy) + 0.25) * (2.0 / u_pixelAlignment4f.zw); +#ifdef COMPILE_REPROJECT_SSAO + reprojectionSSAOOutput4f = vec4(0.0, 1.0, 0.0, 0.0); +#endif +#ifdef COMPILE_REPROJECT_SSR + reprojectionReflectionOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + reprojectionHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 0.0); +#endif + float fragDepth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + + if(fragDepth < 0.000001) { + return; + } + + vec4 fragClipSpacePos4f = vec4(v_position2f, fragDepth, 1.0) * 2.0 - 1.0; + vec4 fragPos4f = u_inverseViewProjMatrix4f * fragClipSpacePos4f; + fragPos4f.xyz /= fragPos4f.w; + fragPos4f.w = 1.0; + vec4 reprojPos4f = u_reprojectionMatrix4f * fragPos4f; + vec4 reprojClipPos4f = vec4(reprojPos4f.xyz / reprojPos4f.w, 1.0); + reprojPos4f = reprojClipPos4f; + reprojPos4f.xyz *= 0.5; + reprojPos4f.xyz += 0.5; + reprojPos4f.xy = (floor(reprojPos4f.xy * u_pixelAlignment4f.zw) + 0.5) * (0.5 / u_pixelAlignment4f.xy); + if(reprojPos4f.xy != clamp(reprojPos4f.xy, vec2(0.001), vec2(0.999)) || abs(GET_LINEAR_DEPTH_FROM_VALUE(textureLod(u_reprojectionDepthTexture, reprojPos4f.xy, 0.0).r) - GET_LINEAR_DEPTH_FROM_VALUE(reprojPos4f.z)) > reprojDepthLimit) { +#ifdef COMPILE_REPROJECT_SSAO + reprojectionSSAOOutput4f = vec4(0.01, textureLod(u_ssaoSampleTexture, v_position2f, 0.0).r, 1.0, 0.0); +#endif +#ifdef COMPILE_REPROJECT_SSR + reprojectionHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 50.0); +#endif + return; + } + +#ifdef COMPILE_REPROJECT_SSAO + vec4 reprojectionSSAOInput4f = textureLod(u_reprojectionSSAOInput4f, reprojPos4f.xy, 0.0); + reprojectionSSAOInput4f.g = mix(textureLod(u_ssaoSampleTexture, v_position2f, 0.0).r, reprojectionSSAOInput4f.g, min(reprojectionSSAOInput4f.r * 10.0, 0.85)); + reprojectionSSAOInput4f.r = min(reprojectionSSAOInput4f.r + 0.01, 1.0); + reprojectionSSAOInput4f.b = 1.0; + reprojectionSSAOOutput4f = reprojectionSSAOInput4f; +#endif + +#ifdef COMPILE_REPROJECT_SSR + vec4 materials = textureLod(u_gbufferMaterialTexture, v_position2f2, 0.0); + float f = materials.g < 0.06 ? 1.0 : 0.0; + f += materials.r < 0.5 ? 1.0 : 0.0; + f += materials.a > 0.5 ? 1.0 : 0.0; + if(f > 0.0) { + return; + } + + vec4 lastFrameHitVector4f = textureLod(u_reprojectionHitVectorInput4f, reprojPos4f.xy, 0.0); + if(lastFrameHitVector4f.g <= 0.0) { + reprojectionReflectionOutput4f = textureLod(u_reprojectionReflectionInput4f, reprojPos4f.xy, 0.0); + reprojectionReflectionOutput4f.a = max(reprojectionReflectionOutput4f.a - 1.0, 1.0); + reprojectionHitVectorOutput4f = vec4(0.0, 0.0, 0.0, lastFrameHitVector4f.a); + return; + } + + reprojectionReflectionOutput4f = vec4(0.0, 0.0, 0.0, 1.0); + + lastFrameHitVector4f.g -= 0.0004; + + vec4 lastFrameFragPosView4f = u_lastInverseProjMatrix4f * vec4(reprojClipPos4f.xyz, 1.0); + lastFrameFragPosView4f.xyz /= lastFrameFragPosView4f.w; + lastFrameFragPosView4f.w = 1.0; + vec4 lastFrameHitPos4f = vec4(lastFrameFragPosView4f.xyz + lastFrameHitVector4f.xyz, 1.0); + + vec4 thisFrameHitPos4f = u_reprojectionInverseViewMatrix4f * lastFrameHitPos4f; + thisFrameHitPos4f.xyz /= thisFrameHitPos4f.w; + thisFrameHitPos4f.w = 1.0; + + vec4 thisFrameHitPosProj4f = u_projectionMatrix4f * thisFrameHitPos4f; + thisFrameHitPosProj4f.xyz /= thisFrameHitPosProj4f.w; + thisFrameHitPosProj4f.w = 1.0; + vec3 thisFrameHitPosProjTex3f = thisFrameHitPosProj4f.xyz * 0.5 + 0.5; + + if(thisFrameHitPosProjTex3f.xy != clamp(thisFrameHitPosProjTex3f.xy, vec2(0.001), vec2(0.999))) { + return; + } + + float fragDepthSample = textureLod(u_gbufferDepthTexture, thisFrameHitPosProjTex3f.xy, 0.0).r * 2.0 - 1.0; + vec2 thisFrameHitPosProjDepthPos = CREATE_DEPTH_MATRIX(u_inverseProjectionMatrix4f) * vec4(thisFrameHitPosProj4f.xy, fragDepthSample, 1.0); + thisFrameHitPosProjDepthPos.x /= thisFrameHitPosProjDepthPos.y; + + if(thisFrameHitPosProjDepthPos.x - thisFrameHitPos4f.z - 0.125 < 0.0) { + return; + } + + vec3 lastFrameHitPosNormal3f = textureLod(u_gbufferNormalTexture, thisFrameHitPosProjTex3f.xy, 0.0).rgb; + lastFrameHitPosNormal3f *= 2.0; + lastFrameHitPosNormal3f -= 1.0; + + vec3 currentNormal3f = textureLod(u_gbufferNormalTexture, v_position2f2, 0.0).xyz; + currentNormal3f *= 2.0; + currentNormal3f -= 1.0; + + vec4 fragPosView4f = u_inverseProjectionMatrix4f * fragClipSpacePos4f; + fragPosView4f.xyz /= fragPosView4f.w; + fragPosView4f.w = 1.0; + + vec3 rayOrigin = fragPosView4f.xyz; + vec3 planePos = thisFrameHitPos4f.xyz; + vec3 planeNormal = lastFrameHitPosNormal3f; + + vec3 newRayDirection = reflect(normalize(rayOrigin), currentNormal3f.xyz); + + float dist = dot(planeNormal, newRayDirection); + if(dist > 0.9) { + return; + } + + dist = dot(planeNormal, planePos - rayOrigin) / dist; + if(dist < 0.0) { + return; + } + + reprojectionHitVectorOutput4f = vec4(newRayDirection * dist, 1.0); + reprojectionHitVectorOutput4f.y += 0.0004; + + thisFrameHitPosProj4f = u_viewToPreviousProjMatrix4f * vec4(rayOrigin + newRayDirection * dist, 1.0); + thisFrameHitPosProj4f.xyz /= thisFrameHitPosProj4f.w; + thisFrameHitPosProj4f.w = 1.0; + thisFrameHitPosProjTex3f = thisFrameHitPosProj4f.xyz * 0.5 + 0.5; + + if(thisFrameHitPosProjTex3f.xy != clamp(thisFrameHitPosProjTex3f.xy, vec2(0.001), vec2(0.999))) { + return; + } + + fragDepthSample = textureLod(u_reprojectionDepthTexture, thisFrameHitPosProjTex3f.xy, 0.0).r * 2.0 - 1.0; + + vec2 thisFrameHitPosProjPos = CREATE_DEPTH_MATRIX(u_lastInverseProjMatrix4f) * thisFrameHitPosProj4f; + thisFrameHitPosProjPos.x /= thisFrameHitPosProjPos.y; + + thisFrameHitPosProjDepthPos = CREATE_DEPTH_MATRIX(u_lastInverseProjMatrix4f) * vec4(thisFrameHitPosProj4f.xy, fragDepthSample, 1.0); + thisFrameHitPosProjDepthPos.x /= thisFrameHitPosProjDepthPos.y; + + if(thisFrameHitPosProjDepthPos.x - thisFrameHitPosProjPos.x - 0.125 < 0.0) { + reprojectionHitVectorOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + return; + } + + reprojectionReflectionOutput4f = vec4(textureLod(u_lastFrameColorInput4f, thisFrameHitPosProjTex3f.xy, 0.0).rgb, 0.0); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/reproject_ssr.fsh b/sources/resources/assets/eagler/glsl/deferred/reproject_ssr.fsh new file mode 100644 index 0000000..f6c1e32 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/reproject_ssr.fsh @@ -0,0 +1,110 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 reflectionOutput4f; +layout(location = 1) out vec4 hitVectorOutput4f; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_reprojectionReflectionInput4f; +uniform sampler2D u_reprojectionHitVectorInput4f; +uniform sampler2D u_lastFrameColorInput4f; +uniform sampler2D u_lastFrameDepthInput; + +uniform mat4 u_lastProjectionMatrix4f; +uniform mat4x2 u_lastInverseProjMatrix4x2f; + +uniform mat4 u_inverseProjectionMatrix4f; + +uniform float u_sampleStep1f; + +uniform vec4 u_pixelAlignment4f; + +#define maxAge 55.0 +#define maxSamples 50.0 + +void main() { + vec2 v_position2f2 = (floor(v_position2f * u_pixelAlignment4f.xy) + 0.25) * (2.0 / u_pixelAlignment4f.zw); + reflectionOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + hitVectorOutput4f = vec4(0.0, 0.0, 0.0, 0.0); + float fragDepth = textureLod(u_gbufferDepthTexture, v_position2f2, 0.0).r; + + if(fragDepth < 0.000001) { + return; + } + + vec4 reflectionInput4f = textureLod(u_reprojectionReflectionInput4f, v_position2f, 0.0); + vec4 hitVectorInput4f = textureLod(u_reprojectionHitVectorInput4f, v_position2f, 0.0); + hitVectorInput4f.a += 1.0; + float f = reflectionInput4f.a < 1.0 ? 1.0 : reflectionInput4f.a; + reflectionInput4f.a = hitVectorInput4f.a > maxAge ? f : reflectionInput4f.a; + if(reflectionInput4f.a < 1.0) { + reflectionOutput4f = reflectionInput4f; + hitVectorOutput4f = hitVectorInput4f; + return; + } + + vec4 fragPos4f = u_inverseProjectionMatrix4f * (vec4(v_position2f2, fragDepth, 1.0) * 2.0 - 1.0); + fragPos4f.xyz /= fragPos4f.w; + fragPos4f.w = 1.0; + vec4 reflectionNormal4f = textureLod(u_gbufferNormalTexture, v_position2f2, 0.0); + reflectionNormal4f.xyz *= 2.0; + reflectionNormal4f.xyz -= 1.0; + reflectionNormal4f.xyz = reflect(normalize(fragPos4f.xyz), reflectionNormal4f.xyz); + reflectionNormal4f.w = 1.0; + float sampleStepMod = (reflectionInput4f.a * 0.03 + 0.15 + length(fragPos4f.xyz) * 0.03) * u_sampleStep1f; + vec3 sampleOffset3f = reflectionNormal4f.xyz * reflectionInput4f.a * sampleStepMod; + fragPos4f.xyz += sampleOffset3f; + reflectionNormal4f = u_lastProjectionMatrix4f * fragPos4f; + reflectionNormal4f.xyz /= reflectionNormal4f.w; + reflectionNormal4f.w = 1.0; + vec3 reflectionSamplePos3f = reflectionNormal4f.xyz; + reflectionSamplePos3f *= 0.5; + reflectionSamplePos3f += 0.5; + reflectionSamplePos3f.xy = (floor(reflectionSamplePos3f.xy * u_pixelAlignment4f.zw) + 0.5) * (0.5 / u_pixelAlignment4f.xy); + + if(clamp(reflectionSamplePos3f.xy, vec2(0.001), vec2(0.999)) != reflectionSamplePos3f.xy) { + return; + } + + float reflectDepthSample = textureLod(u_lastFrameDepthInput, reflectionSamplePos3f.xy, 0.0).r; + vec2 sampleFragDepth = u_lastInverseProjMatrix4x2f * vec4(reflectionNormal4f.xy, reflectDepthSample * 2.0 - 1.0, 1.0); + sampleFragDepth.x /= sampleFragDepth.y; + + reflectDepthSample = sampleFragDepth.x - fragPos4f.z; + if(reflectDepthSample < sampleStepMod * 3.0) { + reflectionInput4f.a += 1.0; + reflectionOutput4f = reflectionInput4f.a >= maxSamples ? vec4(0.0, 0.0, 0.0, 0.0) : reflectionInput4f; + hitVectorOutput4f = vec4(0.0, 0.0, 0.0, hitVectorInput4f.a); + return; + } + + if(abs(reflectDepthSample) > sampleStepMod * 6.0) { + return; + } + + vec4 colorSample = textureLod(u_lastFrameColorInput4f, reflectionSamplePos3f.xy, 0.0); + reflectionOutput4f = vec4(colorSample.rgb, 0.0); + reflectionOutput4f.g += 0.0005; + hitVectorOutput4f = vec4(colorSample.a > 0.0 ? sampleOffset3f : vec3(0.0), 0.0); + hitVectorOutput4f.g += colorSample.a > 0.0 ? 0.0004 : 0.0; +} diff --git a/sources/resources/assets/eagler/glsl/deferred/shader_pack_icon.png b/sources/resources/assets/eagler/glsl/deferred/shader_pack_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0f1d18b12e9e68668aad5acedfee47771451eb GIT binary patch literal 4307 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 NjpbE~ii;j`{{@OCjDY|E literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/shader_pack_info.json b/sources/resources/assets/eagler/glsl/deferred/shader_pack_info.json new file mode 100644 index 0000000..75294c2 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/shader_pack_info.json @@ -0,0 +1,24 @@ +{ + "name": "§eHigh Performance PBR", + "desc": "Pack made from scratch specifically for this client, designed to give what I call the best balance between quality and performance possible in a browser but obviously that's just my opinion", + "vers": "1.0.0", + "author": "lax1dude", + "api_vers": 1, + "features": [ + "WAVING_BLOCKS", + "DYNAMIC_LIGHTS", + "GLOBAL_AMBIENT_OCCLUSION", + "SHADOWS_SUN", + "SHADOWS_COLORED", + "SHADOWS_SMOOTHED", + "REFLECTIONS_PARABOLOID", + "REFLECTIONS_ROUGHNESS", + "REALISTIC_WATER", + "LIGHT_SHAFTS", + "SCREEN_SPACE_REFLECTIONS", + "POST_LENS_DISTORION", + "POST_LENS_FLARES", + "POST_BLOOM", + "POST_FXAA" + ] +} \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/shadows_sun.fsh b/sources/resources/assets/eagler/glsl/deferred/shadows_sun.fsh new file mode 100644 index 0000000..9b2ef53 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/shadows_sun.fsh @@ -0,0 +1,168 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; +precision highp sampler2DShadow; + +in vec2 v_position2f; + +#ifdef COMPILE_COLORED_SHADOW +layout(location = 0) out vec4 output4f; +#else +layout(location = 0) out float output1f; +#endif + +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2DShadow u_sunShadowDepthTexture; +#ifdef COMPILE_COLORED_SHADOW +uniform sampler2D u_sunShadowColorTexture; +#endif + +uniform mat4 u_inverseViewMatrix4f; +uniform mat4 u_inverseViewProjMatrix4f; + +#ifdef COMPILE_SUN_SHADOW_LOD0 +uniform mat4 u_sunShadowMatrixLOD04f; +#define SUN_SHADOW_MAP_FRAC 1.0 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD1 +uniform mat4 u_sunShadowMatrixLOD04f; +uniform mat4 u_sunShadowMatrixLOD14f; +#define SUN_SHADOW_MAP_FRAC 0.5 +#endif +#ifdef COMPILE_SUN_SHADOW_LOD2 +uniform mat4 u_sunShadowMatrixLOD04f; +uniform mat4 u_sunShadowMatrixLOD14f; +uniform mat4 u_sunShadowMatrixLOD24f; +#define SUN_SHADOW_MAP_FRAC 0.3333333 +#endif +#ifdef COMPILE_SUN_SHADOW_SMOOTH +const vec2 POISSON_DISK[7] = vec2[]( +vec2(-0.077, 0.995), vec2(0.998, 0.015), +vec2(-0.116, -0.987), vec2(-0.916, 0.359), +vec2(-0.697, -0.511), vec2(0.740, -0.612), +vec2(0.675, 0.682)); +#define SMOOTH_SHADOW_SAMPLES 1.0 / 8.0 +#define SMOOTH_SHADOW_RADIUS 0.00075 +#define SMOOTH_SHADOW_POISSON_SAMPLE(idx, tex, lod, vec3Pos, accum, tmpVec2)\ + tmpVec2 = vec3Pos.xy + POISSON_DISK[idx] * SMOOTH_SHADOW_RADIUS;\ + tmpVec2 = clamp(tmpVec2, vec2(0.001), vec2(0.999));\ + tmpVec2.y += lod;\ + tmpVec2.y *= SUN_SHADOW_MAP_FRAC;\ + accum += textureLod(tex, vec3(tmpVec2, vec3Pos.z), 0.0) * SMOOTH_SHADOW_SAMPLES; +#endif + +uniform vec3 u_sunDirection3f; + +void main() { +#ifdef COMPILE_COLORED_SHADOW + output4f = vec4(0.0); +#else + output1f = 0.0; +#endif + float depth = textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r; + if(depth < 0.00001) { + return; + } + vec4 normalVector4f = textureLod(u_gbufferNormalTexture, v_position2f, 0.0); + if(normalVector4f.a < 0.5) { + return; + } + normalVector4f.xyz *= 2.0; + normalVector4f.xyz -= 1.0; + vec3 worldSpaceNormal = normalize(mat3(u_inverseViewMatrix4f) * normalVector4f.xyz); + if(dot(u_sunDirection3f, worldSpaceNormal) < 0.0) { + return; + } + vec4 worldSpacePosition = vec4(v_position2f, depth, 1.0); + worldSpacePosition.xyz *= 2.0; + worldSpacePosition.xyz -= 1.0; + worldSpacePosition = u_inverseViewProjMatrix4f * worldSpacePosition; + worldSpacePosition.xyz /= worldSpacePosition.w; + worldSpacePosition.xyz += worldSpaceNormal * 0.05; + worldSpacePosition.w = 1.0; + float skyLight = max(normalVector4f.a * 2.0 - 1.0, 0.0); + float shadowSample; + vec2 tmpVec2; + vec4 shadowSpacePosition; + for(;;) { + shadowSpacePosition = u_sunShadowMatrixLOD04f * worldSpacePosition; + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowSpacePosition.xy * vec2(1.0, SUN_SHADOW_MAP_FRAC), shadowSpacePosition.z), 0.0); +#ifdef COMPILE_SUN_SHADOW_SMOOTH + shadowSample *= SMOOTH_SHADOW_SAMPLES; + SMOOTH_SHADOW_POISSON_SAMPLE(0, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(1, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(2, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(3, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(4, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(5, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + SMOOTH_SHADOW_POISSON_SAMPLE(6, u_sunShadowDepthTexture, 0.0, shadowSpacePosition.xyz, shadowSample, tmpVec2) + shadowSample = max(shadowSample * 2.0 - 1.0, 0.0); +#endif +#ifdef COMPILE_COLORED_SHADOW + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; +#endif + break; + } + +#if defined(COMPILE_SUN_SHADOW_LOD1) || defined(COMPILE_SUN_SHADOW_LOD2) + shadowSpacePosition = u_sunShadowMatrixLOD14f * worldSpacePosition; + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSpacePosition.y += 1.0; + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowSpacePosition.xy, shadowSpacePosition.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_SUN_SHADOW_LOD2 + shadowSpacePosition = u_sunShadowMatrixLOD24f * worldSpacePosition; + if(shadowSpacePosition.xyz == clamp(shadowSpacePosition.xyz, vec3(0.005), vec3(0.995))) { + shadowSpacePosition.y += 2.0; + shadowSpacePosition.y *= SUN_SHADOW_MAP_FRAC; + shadowSample = textureLod(u_sunShadowDepthTexture, vec3(shadowSpacePosition.xy, shadowSpacePosition.z + 0.00015), 0.0); + break; + } +#endif + +#ifdef COMPILE_COLORED_SHADOW + output4f = vec4(normalVector4f.a); +#else + output1f = normalVector4f.a; +#endif + return; + } + + shadowSample *= skyLight; + +#ifdef COMPILE_COLORED_SHADOW + // reuse normalVector4f: + normalVector4f = shadowSample > 0.05 ? textureLod(u_sunShadowColorTexture, shadowSpacePosition.xy, 0.0) : vec4(0.0); + + // saturate the colors, looks nice + float luma = dot(normalVector4f.rgb, vec3(0.299, 0.587, 0.114)); + normalVector4f.rgb = clamp((normalVector4f.rgb - luma) * 1.5 + luma, vec3(0.0), vec3(1.0)); + + output4f = vec4(mix(normalVector4f.rgb, vec3(1.0), normalVector4f.a) * shadowSample, shadowSample); +#else + output1f = shadowSample; +#endif + +} diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox.dat b/sources/resources/assets/eagler/glsl/deferred/skybox.dat new file mode 100644 index 0000000000000000000000000000000000000000..7d258a94c0b69de9440abc4d3be8f43a77569310 GIT binary patch literal 9204 zcmeI1`(Ko0-p8+7#3@OWMjaFJ1U93Hjm~*)6or(OJfe+;c%ougkZQ@uWqSs*np~|# zaU)mF6;`QG8)aZlrYUO&D4$wOcV#yQzy?X2oMqi{YZ*^_^w%-}|1DSNxC48#OEB)m?@1ns=eRS~Ev}cW{Bc zTt8i2XwH>CdZ)>*O_Sso4Gwv_*&@I4TIJbInewxGqx|4ty8N3rU4C3MRKB}wu#EWc zmhIj_@@S1-26raQz59}7?aoBGZC{ey;O{Nh*C=xBuAb8C74j+aYYz67tLl5nN1FS} zGOr?6Z0ac&H6+Qo&Hd# zvCi|Xw~O^(V!c1G{%-cu&HjF1KiAmb4fcDDeP3n2xA4I&{BZ-{T*W66|J=e~*YQ_3 z{=1C-F5}aS__GWDeu;0t!q?~U`x*Ryn)B$u|7SRlPdK0VIIk$@)6RLl!}+yvj&E>& zAuY>pM4d{x8biJA2EwYI@5s{@q^FQ|`gmY=oenvyCR2{$ zeDyUG+oMD`+Jb!~{Z!z9g#<|9rKgb(9z4BJgdU*@K z-l|zGV;jB28Tb!vOta@?VhWLoH$9Dgz>ha8$gK8t*wtUZ)WA3c52<@bjk zmp_KQ^6W{k+-9?`Ape zN3R^+xstwnNViDCkwvoq(K4w&<|W-sc{l3~u#O#!+roJ5tljCYoCzhe9@ z=DEy%F0w``9yhPsY9ME&y=T^ zn&cTEtk>WQ%^G+?Qr0-6Ori zD>wCNLDS_6X-2tHpN)>l4DgOKSUl07hdZ6cbLd2Bts1V8{jcTGb>`%~DsA1c0_9p36b&!3^LA@@d zn#}W?Q*=w!9IG#orrWLxaV3zUdq^!ZUv9DJPP>ckGh0;MMR%F?L~E`t$Gy?ME|{-N zr=KlYpnKO{Wljkd>KyJW>vN%E-CEa1dq=2Lx5h0*AXK3fw2uu}>6W<4tZT#TboI_+ zyFa`^SML&Hf4Ej>a21*Lk!`wiXO4AFq(S$DW03ukNRuw$6k<)JSvSIIGQS&%>TcK* zt(PKgy1llr?b}F)?wUE#x;uJOr?-S{Inhqt&CEge#nB78v`mxvn`oCVF+IoH8tv9; zE(O);GJ3-L`f%`myS%G?^wFdPX~ zS!YEphG5G^dnlqBt^|bG9?dn3Y^^fSisljgQIWe-q;0-5QpA6R;4u-?F&qCV_7b1z) zfx!ktVI*uj6KpaZj|{S3YiTyji<-q4P7^21Y zXPY|>TcTxF%Yh4qsnL!0k^8y~7wI?hKsRZXdFsBKhW*hhE3shI+B1`k;!rZK(Hph) z%oL;c{P;AZHl8Je`eZS3yv3-^V^NLT{I*=9wk}(~k#$sGu@)G$_1O!J+WH;EMs59$ zQlqv%SA|jApR>xS`N6f$sO{gq!KnGiU2DWI)oa|_jGEuv4MxqM?k1z=Uw5-n^S?W4 zoEJ>4PF35Cn*Y@fqjo;(NuzdtYNzo^Ah~+GdcmljpW0>A&R6X=YUi!qG;+Sx->3-= zEe_NqhZY~I-l4^fn&QA2)gmj+p~a7y;n3nswK%l+QdNf*f9_m|7Ju%1hZd*q0*4l# z?m~wazwTlOam#*69a>zwD;!$9yQ&;o{JYjUwEN-Q;HY;cSMPV#I<))Y+UC&ikF&v{ z-7iOzV~u-cb->x|(C(Kr>d@|=z0INBM_Y#@T^(6%bDVT&_te(u(C)AGf%?Wwh{U4i@_rA5Cb#YXmr?=;r3!*7`^YB1wG%fF8OHM5Q^R5sr z+oP7e^XAySQ1fyl{j3{9xp}%sj@cN_&#Mo|?r%X}8|Cy+VcwcZ?7kQ0r4x6yU}?O+ zvm)N^tcumM-gWWkT^nNk*%xZF+a3^^x zEV-^jF1@E$c&p=6XNspiY;xF~X`XYTT-QKHhG$e{t7B8EC0-v=pjn!(v#`I?uJSht=K98$34W z3Eq&ko_3o_wFS0$Qe5pWTcE*X8Bcwv$zyU*4mErBxD%bbo1>oo?o{WuEp48)E}K(? zIy`=7s`K;ENzY+NqVrI=)1&P#a=}x5@UR;8cX`VECiO&Xx98ZK?XI=qo1PP`C)`&8 z2_@|BXF3W*}5^Y>-VZ1!PxTHFg=nMx+OBy4o&al6tm@eXfr9dfg}E>vwm? z_v5}$qMeVst3>mwwYx;~qw{8o=3i?q-nf87{8OaGCsx zk<<*2KW2$hOK6 zA(Q{zNJC{PYVyx-ZmMjICI-U(=E|?5IeukdwDRp}zksN2i>@&1<1`19@y z@$uYU@$uE}_uPg{?gV4XJ-6=k8{jM~hwjWo9Puri<;?wr)RDIh1 z9l1WuANG8o%~|9RMGAcN&YS?>Ki^1um48;W*f-fy#Xd`YMPrL%`}dg~Wq}isD&G-n zRbWobIl{Cxj?<)NGa-+!NoRQbn-n|$w*ri7Y(4@Hao zms_H~CE>Eb+HjlC5vdA17wYg`j4*ENN#D|FPQVxFjQ6u$h?lKh@#mf0@$pa^$VNp;#dPJNv=t}CTZo8O&Qr>$GfsMFS`TI#g@sA`?IKQ*^b+qXNvPTPlCP^axn zEv(b_=`OC*{NXOG^Q%SvgO-ZAd^IPa*sAI-s#X4}nd{=|z76sA=GwX~YFWTCep}ss zwTkm?h?fsE#h+_wu4{J<4ceU1x@xx!hOKRN=bV$m105Z8Wr3l=6Yi6BuQbZwC3k0? zDLOPLsxQ>-iOAq?OIN%-(p`5rD1(Q>H{;`k5*nvCW$?*xQlrgk4y}pk8@1;nDUEBx z=8y=bHEPc{XT-}+OQZI@OO5w;=frQ)g3SMf0Ta zp>T7fDR?|=3q>2-ThgMoKwD!p{LJ z)KTt9O)q#G(!tx{?ey#=dSksr61oj0!8_3H@DA9A)+EsvOA>dYJK&wLAL;}9!DL$R z6n9~F3O(uv^{_umhW+6HTJ>TerWXd(9~$5wGyo2QcZ9+U>}fks+K2@^I-j7Ims(Qphh!Z9#|*3n`t zHd`Au7Jg~E*B4D%f%yT1$+cPii+W*utfYq{8FqGrKDwI6=^xSmE_CdW0cFNDTj}v z$Kd1e33`@`Ut#5<0zD2Z;FIVH_#|9SYlV0Us}PmwNmvP=Myuh|a1E`M;@4QEs6tP} zD)<|;2L1*xLZ8SeHkRyaf1xvIm#*2JPQX?`z-bA z;PYrOd>*FKZyi0KgD;@x;S11*QlSqHBVsM$MPhh@SWi@s7r&)!qvl0urS?VY*TW6S z3O7Ip{npd-w{Roc05`&ykORI1T}07L@iKAsfcPDemM>~3&!*;OIE&hsssA0^gl54_ za4!9RN6#9#8Et}_VJ(^qYheK=TOzh_){lzcbNY{nS1A9Inl11b)NY~v_plEA0@lG& z`u(1sufSJP9efpTMWt{nT!pvSia+50YO#$I@rvz~6>9zf1+{;mejD6@1l$1==(mlY z+u>_y2Ye0gLIF4eiuZwrZd+2qZ_lx)G{kHgk(mSG^ z-23D|fE|=Spr##uh&teha5p{M#Yf@k44y`(;AvP-&(FkP#oth@^|Ux6I#H~(Ui@AB1J(1qAJ3j5{hZP% zahBX$M#TO{ndQMyrU!qv+esNKJh4vG9f8>p_3;vRR zE48$Qa_qUsco#gu6OU1Up10CJh}SPDKcTHFR^CNTG4Hg$^X}^;jjg?q(o!w;P+q{! zJlg&iQ1Vb(z?J09 zU_pLm#3EFOh4?iQB0g`&!u)E8MQa}{!mon}v6_rU`4te0+yU4j-f@SxBX?tO@}7H> z8)!Eb>#h|D3_F~0w?I30nt@ttoYO4G1E^F5EntPwlTcl$UIn}NN{_c<27_hRqy zrhAW@Xu%qJ+ck18ZP*^Z(tC(cJNA+01(o!VM8SEyyBja>A&Ng@4Nc6wm$Q%UFre+H zRa<=%Yi;A+#8z-ro9}f-KS8|5y!@ed2D>?%zY(XglRmA*K|N9M1@RR-xpSJA_v6#A zd3W>{-;jQbdc$vFUuwP;m#}X|7wQYU;9b;oiSMv3aT(nOFT;W2d*1cw;-92Hpmg{H zG*R<|_!0X-TtOyy1&*cWis;6!h^uHUyb8_YU%c5TiGP#+geJkCU=B4uiEG$T;yTKK z*Wom3u8SMkb#W6-gE!#}@gLsf3&kzcpV312Gh9r~&q889^Mm$h%CV4I%$J`3MkujA zq4Yq@L=Vzsy!{iDReXtiDhWy=`jto|{T1Kco}|67L`8?55<1eS_}2C!y$#bTx1(Q+ z+ev@TyZ$mh>aBc7nxqWmo7r3Gtvo00Krg^Mlov!FUTQOYaAh+c(8K-@- z8Q~b1flM$1jzy#4SeS_tU?%LzDgTcc$GP9G+)Hjd`Ekm2VMeb(v+|l4k9NZG%1$u> zCBg|xBDd~#`reC;Q!K~~EzpX_Lo2kQ3D5@Z=xbpo{hC|qP@IZOaWJz}akFn#$-?Us zl}Vg=wlbNBn?h?(BGs+jBFeLre{*LhDgWdKPFB9*K2M=fk}`#u%E9g=o^ptzTr8Ow z%BANdC7aRu!$Hb@*dWgSKF)k9Hkk9C%9vToMCMI}Ba~^_2+nC5=aYw}aW;9(?q+og z{#Eho{n!|MdOyCLj*Z2S(^+S1KeyovCq9^gS=j#!_MMN}*mFK>o~%5;&Za0cNoOgu zl{v~>a#P69f;rUBQs!Z^lme6k3t+A?pPuvRJ4abST0nU|d=TZr2jL_b+wFW(kFt=S zv0OHJ54?|3tac$>gzkfj;8ez&qdbJoQ3`2Y1PkF}G!-s}Sup0KLee5uI7eARZX)?2 zIF0%uZG<9aDYnAIh_;O6)O%{u_ep-~>MSNxRj)_Iq-C9hg o5KR-g{joS2sYOsav7-_ p.y) return vec3(0.0); + p.y = min(p.y, rsi(r0, r, rPlanet).x); + float iStepSize = (p.y - p.x) / float(iSteps); + + float iTime = 0.0; + + vec3 totalRlh = vec3(0.0); + vec3 totalMie = vec3(0.0); + + float iOdRlh = 0.0; + float iOdMie = 0.0; + + float mu = dot(r, pSun); + float mumu = mu * mu; + float gg = g * g; + float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu); + float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg)); + + for (int i = 0; i < iSteps; i++) { + vec3 iPos = r0 + r * (iTime + iStepSize * 0.5); + float iHeight = length(iPos) - rPlanet; + float odStepRlh = exp(-iHeight / shRlh) * iStepSize; + float odStepMie = exp(-iHeight / shMie) * iStepSize; + iOdRlh += odStepRlh; + iOdMie += odStepMie; + float jStepSize = rsi(iPos, pSun, rAtmos).y / float(jSteps); + float jTime = 0.0; + float jOdRlh = 0.0; + float jOdMie = 0.0; + for (int j = 0; j < jSteps; j++) { + vec3 jPos = iPos + pSun * (jTime + jStepSize * 0.5); + float jHeight = length(jPos) - rPlanet; + jOdRlh += exp(-jHeight / shRlh) * jStepSize; + jOdMie += exp(-jHeight / shMie) * jStepSize; + jTime += jStepSize; + } + vec3 attn = exp(-(kMie * (iOdMie + jOdMie) + kRlh * (iOdRlh + jOdRlh))); + totalRlh += odStepRlh * attn; + totalMie += odStepMie * attn; + iTime += iStepSize; + + } + return iSun * (pRlh * kRlh * totalRlh + pMie * kMie * totalMie); +} + +void main() { + if(u_blendColor4f.a >= 1.0) { + output4f = vec4(u_blendColor4f.rgb, 0.0); + return; + } + vec4 normalIn = textureLod(u_skyNormals, v_position2f, 0.0); + if(normalIn.a != 1.0) { + output4f = vec4(0.0); + return; + } + normalIn.xyz *= 2.0; + normalIn.xyz -= 1.0; + output4f = vec4(atmosphere( + normalIn.xyz, // normalized ray direction + vec3(0,6373e3 + u_altitude1f * 50.0,0), // ray origin + u_sunDirectionIntensity4f.xyz, // position of the sun + u_sunDirectionIntensity4f.w, // intensity of the sun + 6371e3, // radius of the planet in meters + 6471e3, // radius of the atmosphere in meters + vec3(5.5e-6, 13.0e-6, 22.4e-6), // Rayleigh scattering coefficient + 21e-6, // Mie scattering coefficient + 8e3, // Rayleigh scale height + 1.2e3, // Mie scale height + 0.758 // Mie preferred scattering direction + ), 0.0); + if(u_blendColor4f.a > 0.0) { + output4f.rgb = mix(output4f.rgb, u_blendColor4f.rgb, u_blendColor4f.a); + } +} diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox_irradiance.fsh b/sources/resources/assets/eagler/glsl/deferred/skybox_irradiance.fsh new file mode 100644 index 0000000..d6d8f11 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/skybox_irradiance.fsh @@ -0,0 +1,231 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out vec4 output4f; + +uniform sampler2D u_paraboloidSkyboxTexture; + +#define SAMPLE_IRRADIANCE(tex, tmat3f, st, sm, accum3f, tmp3f)\ + tmp3f = tmat3f * st;\ + tmp3f.xz /= abs(tmp3f.y) + 1.0;\ + tmp3f.xz *= vec2(0.4875, tmp3f.y >= 0.0 ? 0.24375 : -0.24375);\ + tmp3f.xz += vec2(0.5, tmp3f.y >= 0.0 ? 0.25 : 0.75);\ + accum3f += textureLod(tex, tmp3f.xz, 0.0).rgb * sm * clamp(1.0 + tmp3f.y * 2.0, 0.0, 1.0); + +void main() { + vec2 latLong = v_position2f * vec2(2.0, 4.0); + latLong -= vec2(1.0, v_position2f.y >= 0.5 ? 3.0 : 1.0); + float latLongLen2 = dot(latLong, latLong); + if(latLongLen2 > 1.2) { + output4f = vec4(0.0); + return; + } + + vec2 texCoords = v_position2f; + texCoords = mod(texCoords, vec2(1.0, 0.5)); + texCoords = texCoords * vec2(2.0, 4.0) - 1.0; + texCoords *= (v_position2f.y < 0.5) ? vec2(1.0, 1.0) : vec2(1.0, -1.0); + + float mag2 = 2.0 / (latLongLen2 + 1.0); + vec3 dir; + dir.y = ((v_position2f.y < 0.5) ? 1.0 : -1.0) * (mag2 - 1.0); + if(dir.y < -0.25) { + output4f = vec4(0.0); + return; + } + + dir.xz = texCoords * mag2; + + vec3 tmp3f = cross(dir, vec3(0.0, 1.0, 0.0)); + mat3 tmat3f = mat3(tmp3f, cross(dir, tmp3f), dir); + vec3 accum3f = vec3(0.0); + + // note: sampling is divided into 3 draw calls to allow better driver multitasking, + // shader would otherwise run the full 156 texture samples in only a single thread + // per pixel which is not ideal. The resulting values of the 3 draw calls are added + // together using GL_ONE, GL_ONE blending on the destination framebuffer + +#ifdef PHASE_1 + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.247, 0.000, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.479, 0.000, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.682, 0.000, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.841, 0.000, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.949, 0.000, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.997, 0.000, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.240, 0.061, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.465, 0.119, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.660, 0.169, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.815, 0.208, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.919, 0.235, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.966, 0.247, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.217, 0.119, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.421, 0.230, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.598, 0.327, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.738, 0.403, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.833, 0.455, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.875, 0.478, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.181, 0.169, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.351, 0.327, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.499, 0.465, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.616, 0.574, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.694, 0.647, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.730, 0.680, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.134, 0.208, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.259, 0.403, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.368, 0.574, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.455, 0.708, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.513, 0.799, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.539, 0.839, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.078, 0.235, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.151, 0.455, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.215, 0.647, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.265, 0.799, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.299, 0.901, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.315, 0.947, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.018, 0.247, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.034, 0.478, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.048, 0.680, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.060, 0.839, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.067, 0.947, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.071, 0.995, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.044, 0.243, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.085, 0.472, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.121, 0.671, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.150, 0.828, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.169, 0.934, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.178, 0.982, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.103, 0.225, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.200, 0.436, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.284, 0.620, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.350, 0.765, 0.540), 0.0092, accum3f, tmp3f) +#endif +#ifdef PHASE_2 + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.395, 0.863, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.415, 0.907, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.155, 0.192, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.301, 0.373, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.428, 0.530, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.529, 0.655, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.596, 0.738, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.627, 0.776, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.198, 0.148, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.384, 0.287, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.546, 0.408, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.674, 0.504, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.760, 0.568, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.799, 0.597, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.229, 0.094, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.443, 0.183, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.630, 0.260, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.778, 0.321, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.877, 0.362, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.922, 0.381, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.245, 0.035, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.475, 0.068, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.675, 0.096, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.833, 0.119, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.939, 0.134, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.988, 0.141, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.246, -0.027, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.477, -0.052, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.678, -0.074, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.837, -0.091, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.943, -0.103, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.992, -0.108, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.232, -0.087, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.449, -0.168, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.638, -0.239, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.788, -0.295, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.889, -0.333, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.934, -0.350, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.203, -0.141, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.393, -0.274, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.559, -0.390, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.690, -0.481, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.779, -0.542, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.819, -0.570, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.162, -0.187, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.313, -0.363, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.446, -0.516, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.550, -0.637, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.620, -0.718, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.652, -0.755, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.110, -0.221, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.214, -0.429, 0.878), 0.0085, accum3f, tmp3f) +#endif +#ifdef PHASE_3 + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.304, -0.610, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.375, -0.753, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.423, -0.849, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.445, -0.893, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.052, -0.242, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.101, -0.469, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.144, -0.666, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.177, -0.823, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.200, -0.928, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(-0.210, -0.975, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.009, -0.247, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.018, -0.479, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.026, -0.681, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.032, -0.841, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.036, -0.948, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.038, -0.997, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.070, -0.237, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.136, -0.460, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.193, -0.654, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.239, -0.807, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.269, -0.910, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.283, -0.957, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.127, -0.213, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.246, -0.412, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.349, -0.585, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.431, -0.723, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.486, -0.815, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.511, -0.857, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.175, -0.175, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.340, -0.338, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.483, -0.481, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.596, -0.594, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.673, -0.670, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.707, -0.704, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.213, -0.126, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.413, -0.244, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.587, -0.346, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.725, -0.428, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.817, -0.482, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.859, -0.507, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.238, -0.069, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.460, -0.134, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.654, -0.190, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.808, -0.235, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.911, -0.265, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.958, -0.279, 0.071), 0.0014, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.247, -0.008, 0.969), 0.0048, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.479, -0.016, 0.878), 0.0085, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.681, -0.023, 0.732), 0.0100, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.841, -0.028, 0.540), 0.0092, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.948, -0.031, 0.315), 0.0060, accum3f, tmp3f) + SAMPLE_IRRADIANCE(u_paraboloidSkyboxTexture, tmat3f, vec3(0.997, -0.033, 0.071), 0.0014, accum3f, tmp3f) +#endif + + output4f = vec4(accum3f * min(1.0 + dir.y * 4.0, 1.0), 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox_render.fsh b/sources/resources/assets/eagler/glsl/deferred/skybox_render.fsh new file mode 100644 index 0000000..809ce2a --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/skybox_render.fsh @@ -0,0 +1,60 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec3 v_position3f; +in vec3 v_color3f; + +layout(location = 0) out vec4 output4f; + +uniform vec3 u_sunDirection3f; +uniform vec3 u_sunColor3f; +uniform vec4 u_lightningColor4f; + +#ifdef COMPILE_CLOUDS +uniform sampler2D u_cloudsTexture; +#endif + +uniform sampler2D u_sunOcclusion; + +#define SKY_BRIGHTNESS 5.0 + +void main() { + gl_FragDepth = 0.0; + vec3 viewDir = normalize(v_position3f); +#ifdef COMPILE_PARABOLOID_SKY + output4f = vec4(v_color3f * SKY_BRIGHTNESS, 0.0); +#else + float f = max(dot(viewDir, u_sunDirection3f) - 0.995, 0.0) * 100.0; + float intensity = min(f * 2.0, 1.0); + intensity *= intensity * intensity * intensity * textureLod(u_sunOcclusion, vec2(0.5, 0.5), 0.0).r * 2.0; + output4f = vec4(v_color3f * SKY_BRIGHTNESS + intensity * u_sunColor3f, 0.0); +#endif +#ifdef COMPILE_CLOUDS + if(viewDir.y < 0.01) { + output4f.rgb = output4f.rgb * u_lightningColor4f.a + u_lightningColor4f.rgb; + return; + } + vec2 cloudSampleCoord2f = (viewDir.xz / (viewDir.y + 1.0)) * 0.975 * 0.5 + 0.5; + vec4 cloudSample = textureLod(u_cloudsTexture, cloudSampleCoord2f, 0.0); + output4f.rgb = mix(output4f.rgb, output4f.rgb * cloudSample.a + cloudSample.rgb, smoothstep(0.0, 1.0, min(viewDir.y * 8.0, 1.0))); +#endif + output4f.rgb = output4f.rgb * u_lightningColor4f.a + u_lightningColor4f.rgb; + +} \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox_render.vsh b/sources/resources/assets/eagler/glsl/deferred/skybox_render.vsh new file mode 100644 index 0000000..d3017a2 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/skybox_render.vsh @@ -0,0 +1,49 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +layout(location = 0) in vec3 a_position3f; +layout(location = 1) in vec2 a_colorIndex2f; + +out vec3 v_position3f; +out vec3 v_color3f; + +uniform mat4 u_viewMatrix4f; +#ifdef COMPILE_PARABOLOID_SKY +uniform float u_farPlane1f; +#else +uniform mat4 u_projMatrix4f; +#endif +uniform sampler2D u_renderedAtmosphere; + +void main() { + v_position3f = a_position3f; + v_color3f = textureLod(u_renderedAtmosphere, a_colorIndex2f, 0.0).rgb; + vec4 pos = u_viewMatrix4f * vec4(a_position3f, 0.0); + +#ifdef COMPILE_PARABOLOID_SKY + float dist = pos.z; + pos.xyz = normalize(pos.xyz); + pos.xy /= 1.0 - pos.z; + pos.z = dist / u_farPlane1f; + gl_Position = vec4(pos.xyz, 1.0); +#else + gl_Position = u_projMatrix4f * vec4(pos.xyz, 1.0); +#endif +} diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.fsh b/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.fsh new file mode 100644 index 0000000..91b8ef0 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.fsh @@ -0,0 +1,45 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec3 v_position3f; + +layout(location = 0) out vec4 output4f; + +#define SKY_BRIGHTNESS 0.015 + +uniform sampler2D u_skyTexture; + +uniform vec2 u_skyTextureScale2f; + +void main() { + gl_FragDepth = 0.0; + vec3 viewDir = normalize(v_position3f); + + vec3 blending = abs(viewDir * viewDir * viewDir); + blending = normalize(max(blending, 0.00001)); + float b = (blending.x + blending.y + blending.z); + blending /= b; + + vec3 blendedSkyColor = texture(u_skyTexture, v_position3f.zy * u_skyTextureScale2f).rgb * blending.x; + blendedSkyColor += texture(u_skyTexture, v_position3f.xz * u_skyTextureScale2f).rgb * blending.y; + blendedSkyColor += texture(u_skyTexture, v_position3f.xy * u_skyTextureScale2f).rgb * blending.z; + + output4f = vec4(blendedSkyColor * blendedSkyColor * blendedSkyColor * SKY_BRIGHTNESS, 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.vsh b/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.vsh new file mode 100644 index 0000000..77b5786 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/skybox_render_end.vsh @@ -0,0 +1,33 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision mediump sampler2D; + +layout(location = 0) in vec3 a_position3f; +layout(location = 1) in vec2 a_colorIndex2f; + +out vec3 v_position3f; + +uniform mat4 u_viewMatrix4f; +uniform mat4 u_projMatrix4f; + +void main() { + v_position3f = a_position3f; + vec4 pos = u_viewMatrix4f * vec4(a_position3f, 0.0); + gl_Position = u_projMatrix4f * vec4(pos.xyz, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/ssao_generate.fsh b/sources/resources/assets/eagler/glsl/deferred/ssao_generate.fsh new file mode 100644 index 0000000..bb2702b --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/ssao_generate.fsh @@ -0,0 +1,96 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_position2f; + +layout(location = 0) out float output1f; + +uniform sampler2D u_gbufferDepthTexture; +uniform sampler2D u_gbufferNormalTexture; +uniform sampler2D u_noiseConstantTexture; + +uniform mat4 u_projectionMatrix4f; +uniform mat4 u_inverseProjectionMatrix4f; + +uniform mat2 u_randomizerDataMatrix2f; + +const vec3 ssaoKernel[8] = vec3[]( +vec3(0.599,0.721,0.350),vec3(0.114,0.791,0.601), +vec3(0.067,0.995,0.069),vec3(0.511,-0.510,0.692), +vec3(0.626,-0.667,0.404),vec3(0.896,-0.169,0.411), +vec3(0.716,-0.439,0.543),vec3(-0.400,0.733,0.550)); +#define radius 1.5 +#define SAMPLE_SSAO(idx, pos, matTBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2)\ + tmpVec4_1.xyz = pos + (matTBN * ssaoKernel[idx]) * radius;\ + tmpVec4_1.w = 1.0;\ + tmpVec4_2 = u_projectionMatrix4f * tmpVec4_1;\ + tmpVec4_2.xyz /= tmpVec4_2.w;\ + tmpVec4_2.xyz = clamp(tmpVec4_2.xyz, -0.99, 0.99);\ + tmpVec4_2.zw = matProjInv2f * vec4(tmpVec4_2.xy, textureLod(u_gbufferDepthTexture, tmpVec4_2.xy * 0.5 + 0.5, 0.0).r * 2.0 - 1.0, 1.0);\ + tmpVec4_2.z /= tmpVec4_2.w;\ + tmpVec4_2.x = smoothstep(0.0, 1.0, radius * 0.5 / abs(pos.z - tmpVec4_2.z));\ + divisor += tmpVec4_2.x > 0.0 ? 1.0 : 0.0;\ + occlusion += (tmpVec4_2.z >= tmpVec4_1.z ? 1.0 : 0.0) * tmpVec4_2.x; + +void main() { + vec3 originalClipSpacePos = vec3(v_position2f, textureLod(u_gbufferDepthTexture, v_position2f, 0.0).r); + + if(originalClipSpacePos.z <= 0.0000001) { + output1f = 1.0; + return; + } + + originalClipSpacePos *= 2.0; + originalClipSpacePos -= 1.0; + + vec3 normal3f = textureLod(u_gbufferNormalTexture, v_position2f, 0.0).rgb; + normal3f *= 2.0; + normal3f -= 1.0; + + vec4 originalViewSpacePos = u_inverseProjectionMatrix4f * vec4(originalClipSpacePos, 1.0); + originalViewSpacePos.xyz /= originalViewSpacePos.w; + originalViewSpacePos.w = 1.0; + + vec4 noiseVec = textureLod(u_noiseConstantTexture, u_randomizerDataMatrix2f * (v_position2f + originalViewSpacePos.xy + normal3f.xz), 0.0); + noiseVec.xyz *= 2.0; + noiseVec.xyz -= 1.0; + + vec3 tangent = normalize(noiseVec.xyz - normal3f * dot(noiseVec.xyz, normal3f)); + vec3 bitangent = cross(normal3f, tangent); + mat3 TBN = mat3(tangent, bitangent, normal3f) * noiseVec.w; + + float divisor = 0.0; + float occlusion = 0.0; + vec4 tmpVec4_1; + vec4 tmpVec4_2; + + mat4x2 matProjInv2f = mat4x2(u_inverseProjectionMatrix4f[0].zw, u_inverseProjectionMatrix4f[1].zw, u_inverseProjectionMatrix4f[2].zw, u_inverseProjectionMatrix4f[3].zw); + + SAMPLE_SSAO(0, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(1, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(2, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(3, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(4, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(5, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(6, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + SAMPLE_SSAO(7, originalViewSpacePos.xyz, TBN, matProjInv2f, divisor, occlusion, tmpVec4_1, tmpVec4_2) + + output1f = max(1.0 - (occlusion / max(divisor, 0.001)), 0.0); +} diff --git a/sources/resources/assets/eagler/glsl/deferred/ssao_noise.bmp b/sources/resources/assets/eagler/glsl/deferred/ssao_noise.bmp new file mode 100644 index 0000000000000000000000000000000000000000..22acc00915ff126c622de1779463e946725a5a1e GIT binary patch literal 16384 zcmW-oZCDa^|Ms_CTi3Q~TUU=%6ctHDilR}NBo!rPMNv`FtSH-PR<0~pmQySY#V|=x zGzt|JMMY6jR8$ldMMXgoP*hYD6{SL{sE*_2{=elocmuzO^ZPkJKl~F1m=rL}+TYQI zE^x$%60<%4|9kB82e(rN z(?<)ykw2BNUJUf2e<2o%tOr>@MO`-oKx;=XdYUI#Db5E!@fcx!q-CM~A6P~0dLeLo zb{_)_d5+vj>J-pDM!>}e1xuA>K%ZWkE%Jtx1Gj>oG46j8hcv$E5&V297kr{@l684` zHM*!~T%^s`0H>)kMi$SG^g6B;93E%@M@-3C!TMhGdaswF2SyFhe)1*5P}zhGKn)7` zo_g?KD;rrw^(M3wGboz!V*t;x?TlT+Imq?Dw+duyxVBv<2O^D?b(&6T2Wj?rjzdrA zqBbmlZot4)gEPZ_wLM)HcMa@+DMZe)FwRRhzANS?8y4zizximeB9i^m*`lZ&af)ked(Pcr$NXojt6zc%u7I7`#tP)ABVJnQg9c2iSE z+YL9UU&v|ytFf68%*a)T@-+=UU8I~vv5w`aL~2)iouNylAv@l@vi%rc6e(C;tyzvQ zB|*!&9Bi^)=kVYu%U^ zO&0OUAqnIwEtc(ms57wpghsjvBZa}P7`cP29?bshGh+7|CFIAje75|yCD7}_fOOgA z3fLH&&h;5j#8?TX;<#TVkT>@}vHOoJ1529+q(a#+Oy4f#{#wq#2>i#yuJr&BE-zwl zg%<~AW!k0t+te_x@KJ8(#X*eB!V+JunTDL5tY$~|8Usad=A_1sEEr}kk$W-OfvL0< zh~0W$L5>2%Yz%KI@aWPM>8Xv)Fv;3d?(|>vm}!AXJpa59;SILq=t-ycpGQpmx_6nOvY0h4k^W#|dq zw36*RLEIpbSjwCA;eW(_mS_Jr6~Bd~Hf3_>LwB{cDt|AVC8iP`mW}R7;kTcBk?(&z zhew_oGPRx=3Y|!AQtt0=BgTFcWBF0=EPS>$PVV+Vk1udMHJx0bgbr7WmG|#|CDym8 zEO*P^g&#dODaXIf#Q#h9V1f-~g}(BgP%a6GCjPy(-y**<9zK66NnTNA#(SrkOfwB} zp~{hTWo?Uw=)Q?wJEpS`FH_ESh<@)Q&p$;hFIMAD;oj`51b`RSTkNbvl1Veg)_{?mZLH zQ-@LlVui2!v;e{V1$xd;uMnd5@%*$g1*m1Kn3)Y!p!EOhgnhpC0AOb_{bkr^#O{Za z{FT4gf|g}fFxC5-Q9ip`gfX>q0F0ZQp7SFM(Rjtochh8o%32J}6UEag_?sbNg1;4j zIyywZvS%F8{AP?l(wYUz(|0o4Z;Yajmrn`}Eg}G)y`QXr+gs3(BihKf^B@h z^Tbb4v=cAv#@^QI5St|4e)y1y@{duY6)lbr-uSG?`CW26t+l1ySf`PPRQ)+?zuPiN z5xmXR@{Y^|6HHCclUX)e`%soq6E_&L6;@!szNCc00<>x;Duuzh>OSZF(+jj$hpa|= zl`W)m1KaL56HW2M4r>3MY6=Eos+=znX4=}D?M6xbT!?#5sr|}t6_lTz6lux+)4_Dq zjI+8?M|)cJ)=1Q7Lk5+(_8hlv3cRdOYoW=5K}Q>Lptc;DmNEdxm(1`Ohiuq}fl5iI ze+QIwaE9ZvAq%(P-yqv~w+F5)()0RJb=aMLa*2Cq74+~wZ#nK8892#KrEJ;Z*YG06 z0IzUUD^}b0MlxJl5543&&Kcr#;@oM&GUD-Bc+zw|Z?lg8D^ThskKa{5i%X|CjZHl` z07fWF{A^YJMvDllc0q@@-}n)hs$u}{(f0?-2lAus+G50A;I3x{vf&7 zql2PTr#ZW-`f!N#Su%K+6fV0v%_~+Iu!*)xiT80GG~A%&n4h=ddYDF8>Ms>=bifd= z@!Tl(wj)mx-8c-b_XA@9zmIvl4S_gDOmX)27n* zaDzVlnQ1j1Z;EI>F{mgAwi7Ou&Y3Hv#;}XocGa1cl|g>f3~SJ6OT@R~35q=dI>JF8 zwRxUg5Vl^>s5+Zr4{BW%Z4EbSBK9qdQgn1l3Fx&&=HuYDF!5%YDyqd21VL0<5BnJ+ zkd57n^*1{S9Zd?ezFHRc*rZaeB-I54I}@#B`D6so(4|;kFC@DL^*%fMcEMtlCF&=$2DP z5&3^opz@@ik-54aSyetJc;q(&-qS5(?W*fW$FFV`eRrJ-Ot*;`&-)BW{Ox%`(CP*- zX0M+0=|(C#f$tEBM(Ti#2XzeJL<{mj+Kj+;M}a#~O4ev&9{PCHyvQTV06aP(WelsB z$Q;?Yp#6vzT-7kZQsxYzp{3oTo!VUBx@ImzBA7txJOzR!cgn#5Guf<|%und>z0;zq z;920k8=n~g2S$)b{(38T<~s2pUu6?dSkrGp}Mk`Z_U(!tobRf;@PFeSKPZm=a2 z79x92YBcIV70H!R99y63s1LqLFdXgZCFd`GW0N%LBAX9tHNRkDNk6`RJW> z8rE}EF}uasgQn~LSGWOYb;Ik(qJ7y{M_IEE0TWY0bw|o_*C394Kt=$B{nd;eN zY(=2`T7h)u_CgpiubEpX8o{Ve^ooz*CLujTiR=-0M&O+_3hAnoVwfLX$-RJ?!XW#r z#mH4JAs=%n?EWx);HC>5(y^QEu;?K*H!WZevv>JZ@kV4Jr1H3#-I+cV7<=x6bO&Dp zt5{XU_3&-R1U>j9COrNC5&7uY|M`Ovm|rs?jjMbM!$=3Y5vLX~>}In#evJZxUY*Bw zi_r(RLBvu@=NN1xtCjouw+albpkKWFz$=J*vy80>9t)(fK1;1vt6&;MHCO4?fC(2Y zi1WM$As$^4w$7_4a1fd-{rWcr_7XnI#aQy>s?;HTNcWKGZ^>Nfp>dJ2Ct--_I!`Ts z;}^mk4(R2gqZ9Z7zfn_F{$!|b8(RsisUTj~_E`ckW8v=AN;$Z=9e?cNoM}h2F|=T& zM5(TCCSDzHwxFc_;i<-MdHYZ{K4(H|x;-fmrNw?#o=sXHCi;w9nyYl-os9~4;y^F{ z_v3S>y`%ilV^Wjy{BI@12IjP-zEc@~>pyAos51`yiu5{@d}U&2^5378*!DhR@|k(d zA>wqn<@Z|op2Ir)E2P3nU(q^}`c>Nu?RIM95|abgEG) zpQD7A0dl}#eI-5MEgfMHDEZ6xMuT?r6ftZ2WvI=M`-I4yGC&Keg5xpp^~K6?D>f z4zLk!d#d<9UCRR{{~~6Z%gazX5VdgIQ6<3d{xrQaUyrEA8u{>I9ccUDGv@Mt8c`i% zPldOCsdSE!+i2U1RmOpyjF60DHv6sZ1C*7y)!Jl@A=vk}#hHC*iuT=|B;&%V=#a>B zAM8?K8HLj@seN+(WAJ|QuoKnOOdImfHg;6?glr4Z+tc4TDBwh`mip#X@Y^GaPTIOo zS`VzkcxX?5Nb8eHJ2GO5()+q!`#FUXyhmH@>|7U3JKWlDT;KL8WYN7GyY@&s1(P(V zbsvrkj&dJye!QDSOLxW^ds}KkzDVbHw1Y|$XU`b#t!@o* ztyMeWxRvsA7EinOq%_#`jnR2dEpBOw zNcK6IzCAUPqe~K@ zU3=slDNuxavltwxQdEGd_GihH0ZA1`pcda7`bvF~I9g$nq{9To4W zEgkE5&LBZ(tDtV~d7QW%M%*#^pltu1UU>AQ0~9($;gnU5;VvV` zWq%aEhldz@c6w}(|8rJ5k$u`Fxl6>CJ+ zpAN;v@Q(!Ef0<@hw=t}1eS(U6>TOVW`hfKlH#&l%9#WXjG!k~FjhnaZDh}Je>8a`i z`&Cdwv)ZcbWk;N!DOb$jDJH0(W#(V_d0|J44JzqsUeK$1PAmU}HNsfXs@T5u6+!n} zZ9a1QZP@wky{hyj!l3mqnsx0iR>YBa@rrkXH-xJ7Vl&iR62@A{RY_`%L7?6z*1kAH z#EBrAg5y3wcy(~by!nMDti4FD;x>&39d8=4smssaJL8uXm!ujwinZqb^RcDwbuUWB>UolDSEN&1eln zkvoJe_Av-PUS@)e`?^?Sk8X7APsJkFe-8Zha1w(`{D{P!vIq|O8^O1NKe4i;lW4}M zQk0th5vbsdGRAUc$m{181Z&~X!77!QwZj;Veuv8tf$#PM#i&7s-b;Y29uW%~+Pc6q z)CShBiDzi*u^f@-9TPBqTE-Y|EJof^m<8Sf19*bn#PYA#p#i&?qQ0jCz`CYBhH{L7 z+;h|*_%1CLeBomZYiX7Mow9#Mv==G^I+FxVy)n~~e}D5-a}us26>RHq6#uV?dS>^q;h%9Od6L#_ z+Xroq?DMVD^pbQW7e{b3fXb;iY!!xYpVP>g>?zy+oo$gr@JvnV&v7IXa=^j(oJ{pp zmm9Q6dh)4vZ*1Ndh9YIALXF|6mb4ev>Nw=qOojD`4I#c3a?lU)wy1x#HlMu=;kxujLu!ow38V zfOnM0$nIfHs^~3gT+VT<=e1Bd3t0x!Llt>Z_6wVDS4(6^XT8Ri(@BThHIDI?bZR-y zV(={KBd^+%gdw$?#3=$hWc$E#w)t6GV3VI(dg#{_*w4qGa|d@MVtflm#7De(A-kCq z?5l$JfwD5AG(PtO4C&Xyy<%>{^yF#99>7G1KBbS%dz&9vbi^VpR`>B3o(N$r3 zSVnR3zG=w$)?xM@swMD&Y)1O4gaJFfxt;syzkJN@3Z2+9(+G*#qGg}RnhV^#S1k1! zeGW_O8sZ+WG-JrEPYm!U+Gu-YSs?u1;%`4(zXm$@0dyej!tG z{Ld-)?xJ4P4)>DKJ@_GIH2E`e&#Q6EsePm2*PlD(z8A;wv9CXw^hNEVe#jo>rbG>K zQ}1)jcfn7>L2Z1w{JsT0u`koKC@v?I@YjO!rz8Q9P%~*kYOBMCTJq(@Zase6K#b{7 z%~0sY3afJIJu&e#!f2^HH5o3{x5+g=)p!GhYKl~uLLqRG@|(x;M98rY%bLFx;gI7U z^3*H`J~{J)>8z$Vv_qg%+WxI3u6@yNx!tb|pFPBur!SY{B`dN_c~zFsjC{LtKCFo7 zn>A+HS>GC-*lLzvo-N1s4n8-T{c}R~2W85o3^CD9qPN_1eg9#G6OcJuMtAW&#Qfid z{E{~|kbY|nGxiGub+)@-cm}Tez=53s~0`O_wm{5DA$d`Rki=L5HtenFzuV zs(dC_SXw^l{8`JOxUbt7Lk%HlbciEyAC#@d4`V z19ausGepBd1Ak?x9JK6I5pz1S3H1+1BRsUa(D}f9gtqQ=tC7}a3aRK-+EWI5C`f6a zcHiBZ;2!p%b8Bxp&2=ssPxW<&ygT;NUOmmB+`RWiyZ(MxaLsU~^M}VgT6*bQBL>nO zqClza`hF@U_|UAj?T9v5)TVQS_ey9WpIqa;Ne3WjFtoFnd3T8>+fu}4)F0;y`Td&BA}0e{)F z#KDeWduXw*gPkFB z0c?B9hAzq;Rg*T`)EwNnTZLQcn;?7nQvp14&nRy^tPR^-p_i2BO+$@w8cy+q7`Lsw zUB(q#;YWAtd6*q-*!lbvNo$`3y0^QT^DR9NC%tKvwaeS!{7dh71IZffg=&k01~EVl ztwK)LrFmRttwnaBPXqT|pU)eYzs8=)pOXN+Uqg+FJ)Db#cesvHt?awRWH_VK#H-7m zzcKnwU_fWgAD9wMU`aOzZ}{! z8OLd>Q>j*GGzHZwx~@|-2PRf*l@CmknBHWZoNDjR%+v@qQ4{tp$_P+i}N`Vluf;gnOYWswNYjM zhDr@nmh`KRT$l+ed1|*lUEdXPc1N$`-VP&S({_rv)Vn`St4mV#UhNMm`X$rK?Hr7V z^foKnAmxNOyU>injf9Q+<*2G`Pl5>TgH~8iMZ}Bx83jaEPYCfCGFNYH41;M4!P!4^ zS^mqOquu=#qU^R|pj%x7LlHTF+#fJ3m>|o+-djspkKdQ0XI|8aw3V$u&+t)3+M?IU zf4@EzfNLATKLPIwIN;mSg`$Q2iQq|$w~#ZqD8}XqWG^dzz5&Z8HV3gNIYCGsB~)q@7veU z>T75~@4h`DLX_!%Sb>GHCTSsSj&$03Wet(R zTYELT_Nho$eib>)C#t9|)qREmWghwWRdu%9yB{LIO^(&{(1uAqZsiUmwt>2vG-lX+ zeuP{*T53B*TZoKsrfWJjWRN)Ij}GrUzGgDQ-2J}Go0<|BiC$ewmoKki461~*8KAwo3t!J>PVBDsmD%O3{Y4ZSz%7J3CgA- zU;mt^an0eRkRS6MrAv~jE&4LUGmVjaH|8tmV%xCz)JZGkpSc=#%2sXQ*?r^EkHje0 z)*vMO;h^qFpRLI09(~ykft^ z%m%jHo{%Q>4#2qkEnFDSfcd?1P`vrF3bH?YlC4m*2A;-FNjG3?VgF1waX(aQY~IT;fU9TI*4wGk?xvoquZ(W;)56S*uT3t~Z+Nf?)rY$KZZmp}gj5lS4*M(cFv1`E6*&+{*zxP#s20w>qss~NNer0GTXF*x8u7P+a-eK9p z9Scu_kIKKh@eE&DHEwb{)EtW7jVLol6-1v5lLcWY4ZqoAl#fJoN!(~eW>&=p9U@?pA@=<2jA|3Zhup@ww%&Lds; z3hcOP&tOUDvHB6^&fY>|4~S{G-ZT;3p(&U5C+P7(mljN6U!R8R`kBh0Ate#}Q)8YDh4&MfoPpeo^N z;imdZ0JD0Q-bOPc(g%C^>?3m^cBX^r;>M_*{|pKDm5cxwj4$+6!7@ZgiI)H5pRXX_ z%Vy?sei=%$oiB8)2|#Gh2YSSJDTr&!B>cF;u7_7-~9@)`J`}3Cy<99dcA#zi$J*{q<@)Iszd-CK= zuq1oRx#Z|`+V;*;Bl&Yw$j!V3d-vfk3QsYteKgV?TwgNcY=_m;4(@C>7T>jpTp4e+ zZ{R5?jKX=X`@@mo+Pn#8-?l8;G5a%Pak=aMZmYN7=^dcxkG5#NRnlO#YRGxq#-W96 z=r+>#Ooo^qsqB{m=P0f{pz-WGGT4eI9LC#za<#i~Bp%^$e%L2?hT>#7mk zF6x(@Y&Sq}9I$d|&>`Hp$|+gUqGb4+)iR!Yb0hYqu3r-SO*Hh;$$1W-s0QcafU*Hk z9=ztk9M5|+1)JrjmQ3fBLpNM(-?-mitYeuhr=Vr@Hocd3E5?2l@!YQItv?>-DQrL}Vmm%4FpPQI0O zDjMN!UX8qKThv%@pJvJKay@jFG?TN3IicdMX$V5@QCSC3;)tb3n2Ig^R6^R?R`c3} zrC~=)CspE3b&#K5ul2|~dPGjOMbUa~jIhnU$UM}=4y#u7sDNF}pifD!tir`FBYevS z73H7?LY;e?`Ng;KVS7_2RmZzELF0;K>$#coh@{OL#fth=f^@jtd}FmdtoZ)C>c*$E zpfxoDYx87W1hk`40pHb3z}%WMFAjVXhETMrmf-|0KEbmNu{$HY(JIA8R5^j)FlJ6) zlpYrPk*oUpAUfzRA=f&FmqrYvXcSv9azbNWpZWTK;=;VU>Qt6vr9mAByRH7ax+AC% zgJMfrGa;yK*8JqJFJX5ceFc{VjI&lfYehec`YJm9GY!~QWMFv66v*Ap9fI>GX2EBw zCRr}thdz7$tte-@64(;Z&nW$whSVNu6P#!m0Y`X^vHqK!gWi5tBYN0o2D0#W2Hd?G zc^&so@N~BYyy{sCOVnaOcjg*IxoHbPMMo0@4lYEtoHPo4CcFlZWwf%&_6(qZpk|4D z&I|$r&siC6U4_UuqpgBpa|*#NK5Z;j_y~IL*c(yuz0bhyuu_IDzYD43s|12!IXLzk zI!h!OLnBwGib8T1fG6H^7%OYDknr3=fltCX_^x`0)u63MySSF<#7I5x+WE89VH=d zm>p@lKI%`m3Jpo$#*??5=&~ic4@KVapVs`fL`15P4mq}^=&6%0hVx#7)!szqo4-Os*{zZ z-!jV_3uh9k1KXkveLiAxYh#x!scJ6rcIkVKuS`Q~Q#LtVoe=f@h91MxGdwb1r@{=^ zi^Seg2?W@Z%YHW68Tea7oiqt*ge7;FxR-QlOwbPrVyc?~LR?+P?m@Q&iuVpk5#uaa zS6e;TQzgMP`u2$1{xL%)9w^wZeI9scra^iU&2=oV*ND=*&urKsPZjYZFv%kAt z%(53iRwEMF0d6gU8y@sXU+lHO8XnGY4Y{2d?tn_Xn3oM1XcMr#9*qT-sk@{JU!KEs zvRZEM_H4`^d8at+YYgO0zn)FHFdumLM}bt%F~gw7c>#6gxa!; zl!&1`Vvmt!Np~iMuk%WhmJ6- zSQe9uvxIiw`jsz(KM{R43oNv2&hV+yB6)h}(EsIw&q;})ve;>*XZ$E}#537a-O?96 z^G}1^KW75(eNt~a2&xHHZWSuAf7yu2^{E!gIZOEVkO4WxYYcxNV8oQqnhyIGiSR(>FyQQeX>{trIm8895g&3|1@bK( zX1YE{xqeF_zEcNi-=m;6`>PS%+5*05Zvp6)*AUa-Q-tbG91unyvjbfGk$$1C7XhfK z;O{)!2b#$#XPVQRQ6N#1kR_i0Y}lPg_mOoXruWA1NjnXo)&e85u}Y6R)oK*p%liNT zH`LI9SKATM?j!u7b_3|h9z8R@&WbW~nuOc0=>f0RdirNt8luj(kMEIg1Vw&kGhf$P zP%4pH*dQ@DL$>K@b{xa#1rdg5+N$iST|*QXC)b9qX$`g%mOFQDN~Wd%hi>eojfVJb zDz_slbd<*ScI~F%?%)>wu+!~IFAaatY@Du74hit-v)3+rLAgFvuO&d#!KIbs&a&JY z+M?JT<3U?=NK)7rdy7{yB}p@=-PuwfTzAFdWLc|eySLXE-SqU3)l#0lcT)l-cBVml zdb>Kf)3eq&Ei9syO$v=sE94=lbprd%4c(OaSGn2@zsca<-L=jWKhtSVwc7vl6aIg{ zuVM{R9zln+J0RJ?n=0#_DGRx@#qniE&sWBfSIS|#E>1_O9;nxjlNG_CtD12Ez6Kd~ zDILB?($6bwFk!#D%aR;J4MFSo>o}GKIc_4bOtyrW2j6+VpBE#sVRN$IOY$H+PIf!{Gf8^G0#3u<%Swurk`2nat`3t3JtFWGmbs-Hc7Jh5+91bW96_GW#W!y&&m?g zobZ5+Qr_B*7%VI0ljOA60)2Ap3ugtl8fU<_%fjRqIL}td^ElXv_1#<{as77CZbco( z9IwDtwe`w+HM#J+&67Mg-3x3~_*cn)Sv)Avo5QK~)v7XId>n*7&V&`zs{bhC5 z_pkX8l7V`KtAiyZMtv~{TV!EDO9iU^!{VS#)Lv`Ehr9?lv`X>KztM!Bk3TVAmraJr zZcM3eeS8y?GTCI+>z+p3iTJ&*$ z7Q&b^(d?y^g#~PCP`U1upq=Nn*3Oouh$El|MKRM(SQ}Vn?%Dh*EK)kF>I-NK+8sY> z9gk8*Y}y{BXv!KRWB}XEo@#NJ{zf0zvtG$^-cCUWRGCCBHw&m?>lveaGLib?c7cmO zg0E~)vV3G+=pz#%5jpb%aQa{-W9iKbWY=)201!|HPJ)fFk`?3V%g!iK`bY;*eapyr zIM#u5zit$?x{1N7(wbP@W##Ci&VG^0=K`KNI?Xs+YeojFE*4a-$OW&%RV2dgX zeDLpCmWzj@d36(_AL6+{*w%c8=tlFf zHAp|vkih)A%(k>3JMs`*tzoD}NME9o9fw!sQB%1e43I-D=#`3V4!~@72ZEIQ7TOPxP=XN34?S;68dq;B3OpX%V6jgM=Y7n2ckP#0jG21R_ z#mfszAh2RBJEUJ12xAUQt;h3Vo_`E;|J^Z!iO&8gKER!VAT|}UKS!|w&m_-FT^%T_ zZy<`xgpFYACm3RW^&}+Z`wX^GLkslC)k(`AyoX8uwsIk%dQ6d9r+BY#59C$LIQuW^ zm%u}|SSfmW226B$j!PZTV(w11h?gXaAcele?91LGfgrzfsYmPx?0)t~E~~|i$^X|O z-mEBscr>=K*U%M#zgx?tswX3`3rqOi$&(crB+e*S<_tlo6HhPTeq!JR|Of`U0BawXle3CaxT*Nw~ftY+ff zch#ASn}$PO&Y%*P@s1edIcm|}>JRtH9F}KXcHljuMop)IjiH2}Un&2H{7gI_iS|$upLGvgemqGH-_~6yFJ#Q) zU3s>yPyjpIVx-1Pp+-LxhN89P?=xIdUgRgv79|0QKSHi6Q^$F_S z#rML4ohksHF;CwaI)qq9@BBZ${!?*0GZ@%`dh`3d@cX26z(}ToUjNrL;@0iY`~p7{ zD8*-tsY%zP498oAy4Etlfw?$3D}NpV;|}nzBPT$yMf1$R-<6?E@*LqV+63S>ppDLb zTZqX2k;y-=>jrgIb~6Qx1=N--mC(gM0X?0S^iW$RVl}y$PrLaAG`N$^JTUzlrPoCZ z|F)L^Hq=zoHwJeh@XbSf@2exAj0h+5;#>*p;t8AZNc=m%Ltrf$>V*Z`%L7(pXyJT_%OSD%s=n$?aWvx28C*E*Z`_t7++<;M4<{E(xvA^YcBNtE@lcLE!4+A&3x}q# zi7{U!&rDrV=6_fmQ*k{m2HY=WeMg03Pfqfb7Y4EM%rBBlpW>k%k{-_fn^v68ohMrt z(*?V$leU9;I;5>-oW`zY{-;M zvTXkg=uzK6j`c!0F8kHIY|A|@TzPqz*Lp~ceevXr#A755dh~5Fr>bU1wTadn&J2}cRb|k`UXJzH&YpfKtH%v=AOJznHs0tT0f|OVy2ysvziJgVrMf;}H#SCKLjM zk>K*!%#05?VSd$mmHg&pkOb0f&BDKpaOFuwd7GAi{q42+T=isF+0Az4&FHtD zQtBg?kO~#wK422O0nz57Uvt8cug6uHVr$UhOEXqjWp~7y;wnYvdp;rIn^<$VPi+_{ z+NoOGo)l!*o@_1a?Ti5XlqfjIYy?>1hCS%4A=dbL0z>W&-%_HAV` z-j*jLrw(Qb&g~ik_utg9S{V~)*K96|*SYw6{uHBhmmaw|q(mSs8UvR>RjixsV`x{u zCAxfM7Fe`g$XNPZj08M#@qd{GeDhByD<9I0Mm6+_R%bK<+tm`rjsYgp<#!2g#(x1P zUH-`G-SiY)b7@L+e1{6S^^KbG+rwJqWrAHm0cpUC0~xHSMLFm#8kXqPc^i;FUCuZs zoj~?Ovjl%t&4GowcGmr-DKsR%Tf~340IUF1F#dBV9of{`BG`DS2K*}D&N{xT4Bd~B ziy^{OJfn653b zc_1=sk45t}>NzRJ*zNfKGJ|SvNi(>3Cpl|%gRR~g6^SHIYIcH>NJ~z=a=4sIs@rqD zq3`J+d6!&iOZcre@+7cPqa1%m8YZ+jd<;d@?G;Kxe?Tj_V>HQjT&0PuziQE}uH%v1 zUk*8*m%gWNI8bTuFlLYyg@d+ESaqcTGOFftcnXQqIPD-#)=~R%HHH!Q7&57P+P1|r zFLJ81SYtU`NkRhojs{3Q_3luQq3iDv^0CFwZ6OtJBUh)%HA&W5()Tf$4)njXRCQmD z0k+{KSspTp**jDs7B&w;dfIE)GLs+>#xY6-z$VxQXFuR6w#Q;GqWO-v8yLVqx;BAi)=?(}F)=$%OTR?@Fl1nzR zS6wIM@|q^LNTUjjYMqeYSD0aZ+$DiD47#};$b@|trr;%U9u8aeTFsaz2OOC*; zfAmQ+;X^RYDn1wcHW4#*;EmV^EQD-L?_;~(IRv_TE-3@7g~?kxxsHMud1{Cg?{dpc zdtXh2zDpD-S1XD-yS+dGfv`U1Sz{Z~1Nhvs^>kNw8Av8iJo*kVN_cM? zMHh$qFN;&Q?5HJfZZ5UJcFDp6#G~>%-*fQUeSM~|O}(N0Njl|H@pIzui61RPYI^vI zl_L3@ln?m+ZoUcK*%_*2nUn|P=7{C^Da*rU_2Ke+7C>F%44p96fN<*)@Pqm_phL^K z%wKL)pb8Qegr}Aj0w%cibX##IBKN=~zXqiT?YyXC7TsS!t@BP37J2jmAVIzK!Ao5T zzyDGBt%tQB*$O7pk2HzeJ)R*XV5b3VFUjfWg69#ZhMM_%Bd0;;rZ>!f-3t^pV@`N* zjsZ9dZlSvzYlNay&yP`#gU)ylFdu&N40RbkEPP8A0bHF7JzVr2@xvPiziksA6&dg(&8o$9uq{}4kN7Rt1q4eh}$@6mZZ_A`y!HE68hT0;ozc{_xqqwLzq z*9HWP2H$WWaxS@1LYt8?jn(yrkS}*%*sa9{6uBu!`{`Cj@V*z*&bxlowD!6#W1CNN z$juEZ`%yn5B~dx1-3mzw&X{O)&b+Rq3HFa0ySHS9ocMR%?gn8~tk)#kxX7=;x(oYPS|$%a!+P}e-q5s_@T;axeh6Sv;OW!)`2 z%_asG)z&2;Q@%j!dz(1>{Q7WZTNSc_Lk;lit}dP}z6xtpW=mf09)ki8OE|;T65OuF zPT88&W_VW97?065j$KyCk!;;v4qX$|#<88v!(Fn9WjE-b;ThjEc?TPH*gp&Gl2J@K z^m}eB2aw)^qxnwBzK?wk??pHBYKO(xk zQ6~1&l|;!a?gBJ%tew+@?!zfPYGu~w2DtjLlGnR~k8NX&OIq4np&jZ~^ z!V3k4U?E`KJIycFD8lAn6smNG0_jbq41FTMyao_Pm0!Je>+cl4kQJ2|4q z8Y2)2uVl2;sgWd@QD8e54PJgu%zAxr8hvY~UXFY_ zKu;&R5Y%G3mGLRk>_gE^9xf!gZ+Px71goh{m3qUFw36)NShhIVe7-uRSyRkcEv*sG+X;z3YO3Tuh(0z3SCPy1EGsrlpT`O&7pcxJyHV*Y@Sh*Q32K|)r@*fzk(O1!~HgiiW%_WidV{#A$Jyw*xuFZz|$vYq_6F{uz}nT z?sjN_ykj5_uSJMWfqRXizr{+Gg2Z{^vZGlR&-Dr6XA>9X$BDD}tdCDjrAtyn115@< z{%#G#FG&>3VcOepXZlmQ(7hM0-q&JU+wn9M+?%EhZkiw--8WV^(EY;kmh4|w$0I-jcUQ{=VFsL*5c{V;M^Y|RIQl&!e_wEs1 zDtHG-pJ=3~SIi++6;$zOkL7?CGfJ5!i)K)F!2QCc@6!R0tX?|a_5SWpk0Czv@eoK| z*TTFp)QzeeE)&+f)dO_c7JBS#En?I84!-7~0yK?gF}v>#qp%}2!rJOVKsN6^Jz!}( z;^5pfe%8JT(1BJBGvUZPl*@Ax&PLP%Fy3l9I6#hA%WUIs-Od5^{i$aL=$lcwk3R@= zxpshPw}Gz2_93EGBYYHE2ii5vW9~50P!F1{)V)>HbOJ$x;#cvNa!Q&t{wDdmG*(@{Z@)(mKe{!#_En<>scn@VV2z!YP9 zt}*0~IkCMtXpGWWGNj!fKO0O7`Ql8s)YHyivKt#~bRo4DC+$g#g%ozZMf)WoHhA|K z$9c-sKy!PjH_D+6A*H!i`zgJWBA;Msbm6{+30l zY0zm;*Nq1cB1@gV+oZI+GxbKFHPnz}gL3;t?Hb9%W-WHTzx$92t$S$Yl$@Bt9j+aceU4_sUww+_ zCHMDZkG*3_cFLNe_(28dCFdg!e5ym1*QJL8UbgWtd6U>>!4kr>tj|GLpE|92bw-2~YIEwe)KZH}EiN_GP$!MlFvzGVQd79VKYXUa}ZV3zu+!h!*!QGSGKgGk- zjGSfkJlYHBFJZWXaRAd*X09`L6LApx9h^gW?%{nv;1MAWk#S-=;sz2%Qd6X7$%^D8 z3T}!%N+HTo*5XuBR5R4_Y!s=NX;f&|Xw~`Jq}^t7o9%COe*En4eT&W}TW#7cT1^^X zs5e-zQ{AAl&T5TvmC|R56$)$QS6L~OEtC1ga*0%tWRb*2mI^Euh~l^w#JZ)@+cOyIf^;LoO*Tv`G@W> zGwSIu(;?+lcaZnHO+icn<-6T){rqn9WAyEOhvm)@_uDCd=izrXa*d(y*BH4B(e!;Ha-1U~O3QH%TR2)X!v}qA=BR%G1TwQ- literal 0 HcmV?d00001 diff --git a/sources/resources/assets/eagler/glsl/deferred/vertex_ids.csv b/sources/resources/assets/eagler/glsl/deferred/vertex_ids.csv new file mode 100644 index 0000000..ad3d472 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/deferred/vertex_ids.csv @@ -0,0 +1,120 @@ +model,value +minecraft:block/leaves,1 +minecraft:block/web,1 +minecraft:block/tallgrass,2 +minecraft:block/crop,3 +minecraft:block/double_fern_bottom,4 +minecraft:block/double_grass_bottom,4 +minecraft:block/double_paeonia_bottom,4 +minecraft:block/double_rose_bottom,4 +minecraft:block/double_sunflower_bottom,4 +minecraft:block/double_syringa_bottom,4 +minecraft:block/double_fern_top,5 +minecraft:block/double_grass_top,5 +minecraft:block/double_paeonia_top,5 +minecraft:block/double_rose_top,5 +minecraft:block/double_sunflower_top,5 +minecraft:block/double_syringa_top,5 +minecraft:block/acacia_sapling,6 +minecraft:block/birch_sapling,6 +minecraft:block/daisy,6 +minecraft:block/dandelion,6 +minecraft:block/dead_bush,6 +minecraft:block/houstonia,6 +minecraft:block/jungle_sapling,6 +minecraft:block/oak_sapling,6 +minecraft:block/orchid,6 +minecraft:block/poppy,6 +minecraft:block/red_tulip,6 +minecraft:block/spruce_sapling,6 +minecraft:block/white_tulip,6 +minecraft:block/pink_tulip,6 +minecraft:block/orange_tulip,6 +minecraft:block/allium,6 +minecraft:block/reeds,7 +minecraft:block/vine_1,8 +minecraft:block/vine_1u,8 +minecraft:block/vine_2,8 +minecraft:block/vine_2_opposite,8 +minecraft:block/vine_2u,8 +minecraft:block/vine_2u_opposite,8 +minecraft:block/vine_3,8 +minecraft:block/vine_3u,8 +minecraft:block/vine_4,8 +minecraft:block/vine_4u,8 +minecraft:block/vine_u,8 +eagler:builtin/water_still_vertex_id,9 +eagler:builtin/water_flow_vertex_id,10 +minecraft:block/waterlily,11 +minecraft:block/fire_floor_main,12 +minecraft:block/fire_n_main,13 +minecraft:block/fire_ne_main,13 +minecraft:block/fire_ns_main,13 +minecraft:block/fire_nse_main,13 +minecraft:block/fire_nsew_main,13 +minecraft:block/fire_u1_main,13 +minecraft:block/fire_nu1_main,13 +minecraft:block/fire_neu1_main,13 +minecraft:block/fire_nsu1_main,13 +minecraft:block/fire_nseu1_main,13 +minecraft:block/fire_nsewu1_main,13 +minecraft:block/fire_u2_main,13 +minecraft:block/fire_nu2_main,13 +minecraft:block/fire_neu2_main,13 +minecraft:block/fire_nsu2_main,13 +minecraft:block/fire_nseu2_main,13 +minecraft:block/fire_nsewu2_main,13 +minecraft:block/fire_n_alt,13 +minecraft:block/fire_ne_alt,13 +minecraft:block/fire_ns_alt,13 +minecraft:block/fire_nse_alt,13 +minecraft:block/fire_nsew_alt,13 +minecraft:block/fire_nu2_alt,13 +minecraft:block/fire_neu2_alt,13 +minecraft:block/fire_nsu2_alt,13 +minecraft:block/fire_nseu2_alt,13 +minecraft:block/fire_nsewu2_alt,13 +minecraft:block/fire_n_flip_main,13 +minecraft:block/fire_ne_flip_main,13 +minecraft:block/fire_ns_flip_main,13 +minecraft:block/fire_nse_flip_main,13 +minecraft:block/fire_nsew_flip_main,13 +minecraft:block/fire_nu1_flip_main,13 +minecraft:block/fire_neu1_flip_main,13 +minecraft:block/fire_nsu1_flip_main,13 +minecraft:block/fire_nseu1_flip_main,13 +minecraft:block/fire_nsewu1_flip_main,13 +minecraft:block/fire_nu2_flip_main,13 +minecraft:block/fire_neu2_flip_main,13 +minecraft:block/fire_nsu2_flip_main,13 +minecraft:block/fire_nseu2_flip_main,13 +minecraft:block/fire_nsewu2_flip_main,13 +minecraft:block/fire_n_alt_flip,13 +minecraft:block/fire_ne_alt_flip,13 +minecraft:block/fire_ns_alt_flip,13 +minecraft:block/fire_nse_alt_flip,13 +minecraft:block/fire_nsew_alt_flip,13 +minecraft:block/fire_nu1_alt_flip,13 +minecraft:block/fire_neu1_alt_flip,13 +minecraft:block/fire_nsu1_alt_flip,13 +minecraft:block/fire_nseu1_alt_flip,13 +minecraft:block/fire_nsewu1_alt_flip,13 +minecraft:block/fire_nu2_alt_flip,13 +minecraft:block/fire_neu2_alt_flip,13 +minecraft:block/fire_nsu2_alt_flip,13 +minecraft:block/fire_nseu2_alt_flip,13 +minecraft:block/fire_nsewu2_alt_flip,13 +minecraft:block/fire_nsewu2_alt_flip,13 +minecraft:block/glass,14 +minecraft:block/glass_pane_n,14 +minecraft:block/glass_pane_ne,14 +minecraft:block/glass_pane_new,14 +minecraft:block/glass_pane_ns,14 +minecraft:block/glass_pane_nse,14 +minecraft:block/glass_pane_nsew,14 +minecraft:block/glass_pane_nsw,14 +minecraft:block/glass_pane_nw,14 +minecraft:block/glass_pane_s,14 +minecraft:block/glass_pane_se,14 +minecraft:block/glass_pane_sew,14 +minecraft:block/glass_pane_sw,14 \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/local.vsh b/sources/resources/assets/eagler/glsl/local.vsh index 6cb7523..05e350e 100644 --- a/sources/resources/assets/eagler/glsl/local.vsh +++ b/sources/resources/assets/eagler/glsl/local.vsh @@ -15,7 +15,7 @@ */ precision lowp int; -precision lowp float; +precision highp float; precision lowp sampler2D; layout(location = 0) in vec2 a_position2f; @@ -23,6 +23,6 @@ layout(location = 0) in vec2 a_position2f; out vec2 v_position2f; void main() { - v_position2f = a_position2f; - gl_Position = vec4(a_position2f * 2.0 - 1.0, 0.0, 1.0); + v_position2f = a_position2f * 0.5 + 0.5; + gl_Position = vec4(a_position2f, 0.0, 1.0); } diff --git a/sources/resources/assets/eagler/glsl/post_fxaa.fsh b/sources/resources/assets/eagler/glsl/post_fxaa.fsh index a3628a9..be20844 100644 --- a/sources/resources/assets/eagler/glsl/post_fxaa.fsh +++ b/sources/resources/assets/eagler/glsl/post_fxaa.fsh @@ -1,5 +1,9 @@ #line 2 +// Remove this line below if you plan to modify this file +#define USE_OPTIMIZED + + /* * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. * @@ -48,7 +52,8 @@ precision lowp int; precision mediump float; -precision lowp sampler2D; +precision mediump sampler2D; + in vec2 v_position2f; @@ -57,6 +62,7 @@ layout(location = 0) out vec4 output4f; uniform sampler2D u_screenTexture; uniform vec2 u_screenSize2f; +#ifndef USE_OPTIMIZED #ifndef FXAA_GREEN_AS_LUMA // For those using non-linear color, // and either not able to get luma in alpha, or not wanting to, @@ -102,7 +108,7 @@ uniform vec2 u_screenSize2f; #define FxaaTex sampler2D /*--------------------------------------------------------------------------*/ - #define FxaaTexTop(t, p) texture(t, p) + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) /*============================================================================ GREEN AS LUMA OPTION SUPPORT FUNCTION @@ -292,3 +298,74 @@ void main(){ output4f = vec4(FxaaPixelShader(v_position2f + screenSize05, posPos, u_screenTexture, rcpFrameOpt, rcpFrameOpt * 4.0, edgeSharpness, edgeThreshold, edgeThresholdMin).rgb, 1.0); } +#else + +// This 'optimized' code was generated using glslangValidator + spirv-cross + spirv-opt on the source code above +// Is it faster? Idfk, probably compiles faster at least, what matters it I tried + +float _616; +vec4 _617; + +void main() +{ + mediump vec2 _257 = u_screenSize2f * 0.5; + mediump vec4 _611 = vec4(v_position2f, v_position2f + u_screenSize2f); + mediump vec4 _612 = vec4(_616, _616, _257); + mediump vec2 _290 = v_position2f + _257; + mediump vec4 _608; + for(;;) + { + mediump vec3 _532 = textureLod(u_screenTexture, _611.xy, 0.0).xyz; + mediump float _536 = dot(_532 * _532, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); + mediump vec3 _540 = textureLod(u_screenTexture, _611.xw, 0.0).xyz; + mediump float _544 = dot(_540 * _540, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); + mediump vec3 _548 = textureLod(u_screenTexture, _611.zy, 0.0).xyz; + mediump vec3 _556 = textureLod(u_screenTexture, _611.zw, 0.0).xyz; + mediump float _560 = dot(_556 * _556, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); + mediump vec4 _390 = textureLod(u_screenTexture, _290, 0.0); + mediump vec3 _564 = _390.xyz; + mediump float _568 = dot(_564 * _564, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); + mediump float _397 = dot(_548 * _548, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)) + 0.00260416674427688121795654296875; + mediump float _409 = max(max(_397, _560), max(_536, _544)); + mediump float _412 = min(min(_397, _560), min(_536, _544)); + mediump float _427 = _544 - _397; + mediump float _433 = _560 - _536; + if ((max(_409, _568) - min(_412, _568)) < max(0.0500000007450580596923828125, _409 * 0.1500000059604644775390625)) + { + _608 = _390; + break; + } + mediump vec2 _449 = normalize(vec2(_427 + _433, _427 - _433)); + vec2 hp_copy_449 = _449; + mediump vec2 _454 = _612.zw; + vec2 _614 = -hp_copy_449; + mediump vec2 mp_copy_614 = _614; + mediump vec2 _481 = clamp(_449 / vec2(min(abs(_449.x), abs(_449.y)) * 3.0), vec2(-2.0), vec2(2.0)); + vec2 hp_copy_481 = _481; + mediump vec2 _484 = (_612 * 4.0).zw; + vec2 _615 = -hp_copy_481; + mediump vec2 mp_copy_615 = _615; + mediump vec4 _498 = textureLod(u_screenTexture, mp_copy_614 * _454 + _290, 0.0) + textureLod(u_screenTexture, _449 * _454 + _290, 0.0); + mediump vec4 _505 = ((textureLod(u_screenTexture, mp_copy_615 * _484 + _290, 0.0) + textureLod(u_screenTexture, _481 * _484 + _290, 0.0)) * 0.25) + (_498 * 0.25); + mediump float _576 = dot(_505.xyz * _505.xyz, vec3(0.2989999949932098388671875, 0.58700001239776611328125, 0.114000000059604644775390625)); + mediump vec4 _607; + if ((_576 < _412) || (_576 > _409)) + { + mediump vec3 _518 = _498.xyz * 0.5; + mediump vec4 _600; + _600.x = _518.x; + _600.y = _518.y; + _600.z = _518.z; + _607 = _600; + } + else + { + _607 = _505; + } + _608 = _607; + break; + } + output4f = vec4(_608.xyz, 1.0); +} + +#endif \ No newline at end of file diff --git a/sources/resources/assets/eagler/glsl/texture_blit.fsh b/sources/resources/assets/eagler/glsl/texture_blit.fsh new file mode 100644 index 0000000..9f82680 --- /dev/null +++ b/sources/resources/assets/eagler/glsl/texture_blit.fsh @@ -0,0 +1,45 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision highp float; +precision highp sampler2D; + +in vec2 v_texCoords2f; + +#ifndef COMPILE_BLIT_DEPTH +layout(location = 0) out vec4 output4f; +#endif + +uniform sampler2D u_inputTexture; +uniform float u_textureLod1f; + +#ifdef COMPILE_PIXEL_ALIGNMENT +uniform vec4 u_pixelAlignmentSizes4f; +uniform vec2 u_pixelAlignmentOffset2f; +#endif + +void main() { + vec2 uv2f = v_texCoords2f; +#ifdef COMPILE_PIXEL_ALIGNMENT + uv2f = (floor(uv2f * u_pixelAlignmentSizes4f.xy) + u_pixelAlignmentOffset2f) * u_pixelAlignmentSizes4f.zw; +#endif +#ifndef COMPILE_BLIT_DEPTH + output4f = textureLod(u_inputTexture, uv2f, u_textureLod1f); +#else + gl_FragDepth = textureLod(u_inputTexture, uv2f, u_textureLod1f).r; +#endif +} diff --git a/sources/resources/assets/eagler/glsl/texture_blit.vsh b/sources/resources/assets/eagler/glsl/texture_blit.vsh new file mode 100644 index 0000000..fd5f9bf --- /dev/null +++ b/sources/resources/assets/eagler/glsl/texture_blit.vsh @@ -0,0 +1,32 @@ +#line 2 + +/* + * Copyright (c) 2023 LAX1DUDE. All Rights Reserved. + * + * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES + * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED + * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE + * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. + * + * NOT FOR COMMERCIAL OR MALICIOUS USE + * + * (please read the 'LICENSE' file this repo's root directory for more info) + * + */ + +precision lowp int; +precision lowp float; +precision lowp sampler2D; + +layout(location = 0) in vec2 a_position2f; + +out vec2 v_texCoords2f; + +uniform vec4 u_srcCoords4f; +uniform vec4 u_dstCoords4f; + +void main() { + vec2 uv = a_position2f * 0.5 + 0.5; + v_texCoords2f = u_srcCoords4f.xy + u_srcCoords4f.zw * uv; + gl_Position = vec4(u_dstCoords4f.xy + u_dstCoords4f.zw * uv, 0.0, 1.0); +} diff --git a/sources/resources/assets/eagler/glsl/texture_mix.fsh b/sources/resources/assets/eagler/glsl/texture_mix.fsh index 523bc6b..bbe93fe 100644 --- a/sources/resources/assets/eagler/glsl/texture_mix.fsh +++ b/sources/resources/assets/eagler/glsl/texture_mix.fsh @@ -15,8 +15,8 @@ */ precision lowp int; -precision lowp float; -precision lowp sampler2D; +precision highp float; +precision highp sampler2D; in vec2 v_position2f; diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index 658ea8e..da91032 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -22,7 +22,6 @@ import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.Int8Array; import net.lax1dude.eaglercraft.v1_8.Base64; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass; /** * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. @@ -40,7 +39,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.teavm.MainClass; public class PlatformApplication { public static void openLink(String url) { - Window.current().open(url, "_blank"); + Window.current().open(url, "_blank", "noopener,noreferrer"); } public static void setClipboard(String text) { diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java index 72252b2..3b1b3ba 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java @@ -227,6 +227,35 @@ public class PlatformAudio { return null; } } + + public static interface IAudioCacheLoader { + byte[] loadFile(String filename); + } + + public static IAudioResource loadAudioDataNew(String filename, boolean holdInCache, IAudioCacheLoader loader) { + BrowserAudioResource buffer; + synchronized(soundCache) { + buffer = soundCache.get(filename); + } + if(buffer == null) { + byte[] file = loader.loadFile(filename); + if(file == null) return null; + Uint8Array buf = Uint8Array.create(file.length); + buf.set(file); + buffer = new BrowserAudioResource(decodeAudioAsync(buf.getBuffer(), filename)); + if(holdInCache) { + synchronized(soundCache) { + soundCache.put(filename, buffer); + } + } + } + if(buffer.buffer != null) { + buffer.cacheHit = System.currentTimeMillis(); + return buffer; + }else { + return null; + } + } @Async public static native AudioBuffer decodeAudioAsync(ArrayBuffer buffer, String errorFileName); @@ -260,6 +289,12 @@ public class PlatformAudio { } } } + + public static void flushAudioCache() { + synchronized(soundCache) { + soundCache.clear(); + } + } public static boolean available() { return true; // this is not used diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java index 94e309d..9ce5309 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java @@ -1,10 +1,16 @@ package net.lax1dude.eaglercraft.v1_8.internal; +import org.teavm.jso.webgl.WebGLUniformLocation; + import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerArrayBufferAllocator; import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; import net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext; +import net.lax1dude.eaglercraft.v1_8.log4j.Level; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; /** * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. @@ -21,13 +27,19 @@ import net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext; */ public class PlatformOpenGL { - static WebGL2RenderingContext ctx = null; + private static final Logger logger = LogManager.getLogger("PlatformOpenGL"); + static WebGL2RenderingContext ctx = null; + static boolean hasDebugRenderInfoExt = false; + static boolean hasFramebufferHDR16FSupport = false; + static boolean hasFramebufferHDR32FSupport = false; static void setCurrentContext(WebGL2RenderingContext context) { ctx = context; hasDebugRenderInfoExt = ctx.getExtension("WEBGL_debug_renderer_info") != null; + hasFramebufferHDR16FSupport = ctx.getExtension("EXT_color_buffer_half_float") != null; + hasFramebufferHDR32FSupport = ctx.getExtension("EXT_color_buffer_float") != null; _wglClearColor(1.0f, 1.0f, 1.0f, 1.0f); } @@ -80,6 +92,10 @@ public class PlatformOpenGL { ctx.blendEquation(glEnum); } + public static final void _wglBlendColor(float r, float g, float b, float a) { + ctx.blendColor(r, g, b, a); + } + public static final void _wglColorMask(boolean r, boolean g, boolean b, boolean a) { ctx.colorMask(r, g, b, a); } @@ -236,6 +252,12 @@ public class PlatformOpenGL { public static final void _wglTexParameteri(int target, int param, int value) { ctx.texParameteri(target, param, value); } + + public static final void _wglTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, + int border, int format, int type, ByteBuffer data) { + ctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, + data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + } public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) { @@ -243,6 +265,12 @@ public class PlatformOpenGL { data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); } + public static final void _wglTexImage2Du16(int target, int level, int internalFormat, int width, + int height, int border, int format, int type, ByteBuffer data) { + ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, + data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data)); + } + public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, IntBuffer data) { ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, @@ -261,6 +289,12 @@ public class PlatformOpenGL { data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); } + public static final void _wglTexSubImage2Du16(int target, int level, int xoffset, int yoffset, + int width, int height, int format, int type, ByteBuffer data) { + ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, + data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data)); + } + public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer data) { ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, @@ -277,7 +311,11 @@ public class PlatformOpenGL { int x, int y, int width, int height) { ctx.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } - + + public static final void _wglTexStorage2D(int target, int levels, int internalFormat, int w, int h) { + ctx.texStorage2D(target, levels, internalFormat, w, h); + } + public static final void _wglPixelStorei(int pname, int value) { ctx.pixelStorei(pname, value); } @@ -338,74 +376,118 @@ public class PlatformOpenGL { public static final void _wglDrawArrays(int mode, int first, int count) { ctx.drawArrays(mode, first, count); + //checkErr("_wglDrawArrays(" + mode + ", " + first + ", " + count + ");"); } public static final void _wglDrawArraysInstanced(int mode, int first, int count, int instanced) { ctx.drawArraysInstanced(mode, first, count, instanced); + //checkErr("_wglDrawArraysInstanced(" + mode + ", " + first + ", " + count + ", " + instanced + ");"); } public static final void _wglDrawElements(int mode, int count, int type, int offset) { ctx.drawElements(mode, count, type, offset); + //checkErr("_wglDrawElements(" + mode + ", " + count + ", " + type + ", " + offset + ");"); } public static final void _wglDrawElementsInstanced(int mode, int count, int type, int offset, int instanced) { ctx.drawElementsInstanced(mode, count, type, offset, instanced); + //checkErr("_wglDrawElementsInstanced(" + mode + ", " + count + ", " + type + ", " + offset + ", " + instanced + ");"); } public static final IUniformGL _wglGetUniformLocation(IProgramGL obj, String name) { - return new OpenGLObjects.UniformGL(ctx.getUniformLocation(obj == null ? null : ((OpenGLObjects.ProgramGL)obj).ptr, name)); + WebGLUniformLocation loc = ctx.getUniformLocation(((OpenGLObjects.ProgramGL)obj).ptr, name); + if(loc != null) { + return new OpenGLObjects.UniformGL(loc); + }else { + return null; + } + } + + public static final int _wglGetUniformBlockIndex(IProgramGL obj, String name) { + int i = ctx.getUniformBlockIndex(((OpenGLObjects.ProgramGL)obj).ptr, name); + if(i == 0xFFFFFFFFl) { + i = -1; + } + return i; + } + + public static final void _wglBindBufferRange(int target, int index, IBufferGL buffer, int offset, int size) { + ctx.bindBufferRange(target, index, ((OpenGLObjects.BufferGL)buffer).ptr, offset, size); + } + + public static final void _wglUniformBlockBinding(IProgramGL obj, int blockIndex, int bufferIndex) { + ctx.uniformBlockBinding(((OpenGLObjects.ProgramGL)obj).ptr, blockIndex, bufferIndex); } public static final void _wglUniform1f(IUniformGL obj, float x) { - ctx.uniform1f(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x); + if(obj != null) ctx.uniform1f(((OpenGLObjects.UniformGL)obj).ptr, x); } public static final void _wglUniform2f(IUniformGL obj, float x, float y) { - ctx.uniform2f(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y); + if(obj != null) ctx.uniform2f(((OpenGLObjects.UniformGL)obj).ptr, x, y); } public static final void _wglUniform3f(IUniformGL obj, float x, float y, float z) { - ctx.uniform3f(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y, z); + if(obj != null) ctx.uniform3f(((OpenGLObjects.UniformGL)obj).ptr, x, y, z); } public static final void _wglUniform4f(IUniformGL obj, float x, float y, float z, float w) { - ctx.uniform4f(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y, z, w); + if(obj != null) ctx.uniform4f(((OpenGLObjects.UniformGL)obj).ptr, x, y, z, w); } public static final void _wglUniform1i(IUniformGL obj, int x) { - ctx.uniform1i(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x); + if(obj != null) ctx.uniform1i(((OpenGLObjects.UniformGL)obj).ptr, x); } public static final void _wglUniform2i(IUniformGL obj, int x, int y) { - ctx.uniform2i(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y); + if(obj != null) ctx.uniform2i(((OpenGLObjects.UniformGL)obj).ptr, x, y); } public static final void _wglUniform3i(IUniformGL obj, int x, int y, int z) { - ctx.uniform3i(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y, z); + if(obj != null) ctx.uniform3i(((OpenGLObjects.UniformGL)obj).ptr, x, y, z); } public static final void _wglUniform4i(IUniformGL obj, int x, int y, int z, int w) { - ctx.uniform4i(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, x, y, z, w); + if(obj != null) ctx.uniform4i(((OpenGLObjects.UniformGL)obj).ptr, x, y, z, w); } public static final void _wglUniformMatrix2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { - ctx.uniformMatrix2fv(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, transpose, + if(obj != null) ctx.uniformMatrix2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); } public static final void _wglUniformMatrix3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { - ctx.uniformMatrix3fv(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, transpose, + if(obj != null) ctx.uniformMatrix3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, + mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + } + + public static final void _wglUniformMatrix3x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if(obj != null) ctx.uniformMatrix3x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); } public static final void _wglUniformMatrix4fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { - ctx.uniformMatrix4fv(obj == null ? null : ((OpenGLObjects.UniformGL)obj).ptr, transpose, + if(obj != null) ctx.uniformMatrix4fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, + mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + } + + public static final void _wglUniformMatrix4x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if(obj != null) ctx.uniformMatrix4x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, + mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + } + + public static final void _wglUniformMatrix4x3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { + if(obj != null) ctx.uniformMatrix4x3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); } public static final void _wglBindFramebuffer(int target, IFramebufferGL framebuffer) { - ctx.bindFramebuffer(target, framebuffer == null ? PlatformRuntime.mainFramebuffer - : ((OpenGLObjects.FramebufferGL) framebuffer).ptr); + if(framebuffer == null) { + ctx.bindFramebuffer(target, PlatformRuntime.mainFramebuffer); + ctx.drawBuffers(new int[] { WebGL2RenderingContext.COLOR_ATTACHMENT0 }); + }else { + ctx.bindFramebuffer(target, ((OpenGLObjects.FramebufferGL) framebuffer).ptr); + } } public static final int _wglCheckFramebufferStatus(int target) { @@ -418,6 +500,11 @@ public class PlatformOpenGL { texture == null ? null : ((OpenGLObjects.TextureGL)texture).ptr, level); } + public static final void _wglFramebufferTextureLayer(int target, int attachment, ITextureGL texture, int level, int layer) { + ctx.framebufferTextureLayer(target, attachment, + texture == null ? null : ((OpenGLObjects.TextureGL) texture).ptr, level, layer); + } + public static final void _wglBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int bits, int filter) { ctx.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, bits, filter); @@ -470,5 +557,32 @@ public class PlatformOpenGL { public static final int _wglGetError() { return ctx.getError(); } + + public static final boolean checkHDRFramebufferSupport(int bits) { + switch(bits) { + case 16: + return hasFramebufferHDR16FSupport; + case 32: + return hasFramebufferHDR32FSupport; + default: + return false; + } + } + private static final void checkErr(String name) { + int i = ctx.getError(); + if(i != 0) { + logger.error("########## GL ERROR ##########"); + logger.error("@ {}", name); + do { + logger.error("#{} - {}", i, EaglercraftGPU.gluErrorString(i)); + }while((i = ctx.getError()) != 0); + try { + throw new RuntimeException("GL Error Detected!"); + }catch(Throwable t) { + logger.log(Level.ERROR, t); + } + logger.error("##############################"); + } + } } diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java index ba8cd87..a4eed43 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java @@ -3,6 +3,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.DataView; import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.typedarrays.Uint16Array; import org.teavm.jso.typedarrays.Uint8Array; /** @@ -68,6 +69,19 @@ public class EaglerArrayBufferAllocator { } } + public static Uint16Array getDataViewStupid16(ByteBuffer buffer) { + if(buffer instanceof EaglerArrayByteBuffer) { + EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; + DataView d = b.dataView; + int p = b.position; + int l = b.limit; + int i = d.getByteOffset(); + return Uint16Array.create(d.getBuffer(), i + p, (l - p) >> 1); + }else { + throw notEagler(buffer); + } + } + public static DataView getDataView(IntBuffer buffer) { if(buffer instanceof EaglerArrayIntBuffer) { EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java index f36e5cc..80c7030 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java @@ -187,7 +187,10 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer put(byte[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - dataView.set(src, position); + //dataView.set(src, position); // doesn't work + for(int i = 0; i < src.length; ++i) { + dataView.setInt8(position + i, src[i]); + } position += src.length; return this; } diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/EarlyLoadScreen.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/EarlyLoadScreen.java index a1c81b0..4ec60f8 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/EarlyLoadScreen.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/EarlyLoadScreen.java @@ -34,7 +34,7 @@ import net.lax1dude.eaglercraft.v1_8.EagUtils; */ public class EarlyLoadScreen { - public static final String loadScreen = "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cENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICB4bWxuczpHSU1QPSJodHRwOi8vd3d3LmdpbXAub3JnL3htcC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgeG1wTU06RG9jdW1lbnRJRD0iZ2ltcDpkb2NpZDpnaW1wOmVlODc0NzUwLWYyMTgtNGZhYi04ZmVkLTk3YjdiNTRlMTRmOSIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2ZjJlY2IyYi1lZDdlLTRiNDktYTlkZS03YmRlNTNlOWVjZDciCiAgIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjNDQ3M2M4Yy02MmJhLTQyYjctYWQ0Yi02MjE4ODNiOTM5NDgiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICBHSU1QOkFQST0iMi4wIgogICBHSU1QOlBsYXRmb3JtPSJXaW5kb3dzIgogICBHSU1QOlRpbWVTdGFtcD0iMTYzOTc5MDc4MDQ5ODI0MSIKICAgR0lNUDpWZXJzaW9uPSIyLjEwLjI0IgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjYxMDQ5ZjkxLTE0N2ItNDJjNy1hYzRhLWMyNmU0ZDIzZmEwNSIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMS0xMi0xN1QxNzoyNjoyMCIvPgogICAgPC9yZGY6U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz4gG/WSAAAABmJLR0QAnQCdAJ2roJyEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5QwSARoUHogWFQAAB8dJREFUeNrt3Wtu4yAUQGG36hadRbqLzPxixDCAwYbESb4jVWqbGGPMubz8+Lrf7/cF+FC+FQEIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgADAa/OjCN6L39/f4v/WdV3WdVVIBHjfyn+73arfIYAu0FujghPgoyv/tm3L/X4n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"; + public static final String loadScreen = "iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAYAAABS3GwHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHx0lEQVR42u3da27jIBRAYbfqFp1FuovM/GLEMIDBhsRJviNVapsYY8y5vPz4ut/v9wX4UL4VAQgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAAgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAMBr86MI3ovf39/i/9Z1XdZ1VUgEeN/Kf7vdqt8hgC7QW6OCE+CjK/+2bcv9fieCLtDjux9x/1t/u1xOveWSlisBXmQASoB/+fr6+vv7/X7vHteE8hxZrrpAkyo/2mU42soSgAAfN8YZ3aoSQOV/GNu2ZX9vGdjPEuBnVmXIVYqePly8famCne0TtuS1tt/a9kfSbWnqZw2u9yQesc91XZv7/iO2a+I+iG3b7uu63pdl2f1Z17WaTksaaXrbtk3JaynvR/O5l6/WtPaON3d8tf3v7e9d+RkVPeIVyDRKpREtfL+nGdxL7/f3d9m2bTdS5VZL4/Rz0fcRszm32604jZrLUyi/UXlb1/WlunKhTE63iCMif0tkao1IaXqlqFWKlr2RsTUPpXRLrUnYpqVlircfdby9LUCpbHpa1lyeW8tgL51SmZ9N+2dE5GqJlrkI0xJxaumV0ixt0xrd07TDdrl+aDoeGNnfbzne0RE1HqSOaF3SljptyXP7qF3QN3zi4Yw9LdF0r5+Zs7u175mLirU85KJiLbK3pt2bj1qZ1CJaz356WoD0u2ejaq11XNf1708uf73jqqeOAXotbIlgZ/t0tfSPRulZ050j0jubRjz2CGU/clyRRvvwv1LPIR4X5r6TtlJPmwY9W5la54vfea5+Zhm2dnniyj+j3GtdxCsMzL+vWAmuyujK2dLXnVGGYSZsduXPlV0625Vbk0nlnFlXhrYAezdjPFOa2sD4GRetlY5hdhnmpoHjKcXZlb927Llp4JCvWYHy8leDxpHgbCH0zBo9s3vyiLK8QiBIxwiPaHWnjwFGZbjl9r5RAtxut92Fp5GLTqPHP735qpXDrK5QbjFz27b/Wp802IXu2Yz6cGoadDmwCHV0enVJFpbCfkqLQ6Mvg9g7riPToEfyfrYMl4ZLOUadw1rZh33H/ytNjcbnunfavakeX02As3P1rZVoT4KeVdBXESDN05HV4pFXDaQrxqkE6TnISfC0dYAZA5PSSu3orkeYiSil/Sl3cm3b9t+NKbMHxHtTpenvcT7C33Gez+b1e3QFvvrUY2nhZ/Qi0KtMC+f6/KWpytnnsjWoXuKWyNaZkyud/HTh55mVvTYt++h8zDiXlTFnkwS1wfhlBZgxj917acNe9H9mZWuJvjPuez0azJ5RPj1T3kMe/zJyUNMzkMpdJts6MNybyckNXo/cwLI0XtZ8ZkaldBwt2x65RHvGMRwZoO9dWLh3CfqofC0zZhtKU5fpiWkVIE4n3b423Zemf0SA5cQdVenxt9x70FJ+8TEfkbxUuXqDytnp0L2p0kewzJjeOnMSWtKKt92rQCNageXEDTot05xH1iZy5Xf2lsra9iMrZDjW2dG9ha/7wLuNS5ctpDevt9y2WBu0ptvnxh2l75YutOrtu+/1m+N8tw66022PlGHrcfVuP+NCwNrg+2ETFPcPI45yLSu8s1Yg8UY3xb8K6WP2WualrzJjhDl8f2Ll721iPeiWAG8hwMw+LQhw6co/cpWaPO/DR4wBchU23APQMiMy43EhuAZDp0FfaQxwRCJjAQK8xTigp0uk4hPgowbH+vkEAD4GL8gAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAK7NJR6M9S6PLQzPHZr1sulSuXmCxQu3APHz+sNP6wOspr09/CL76ym3Tzr2t2sBHhk13+UYwgsmnvFeXwI8qUtRinZxZNq27e/3tm3Lvg8gjWRpxc09Rj3eb2l/ufTiZ5CG78Sfn305eO7durX8tH4W8pB+Pz32vTQJcGAcED+0Nv5//Pbw9GTl+sKh8sVRMo2WoWkPJy0WpiRB6XVFpa5IvF28v3RfvX36mpylBwKXPktbkjiI1I69liYBTg6E4wqTkyOWolRB4nTSE5XuszaI3dvfngRppM1F+9auTG4fuW1raeXendYiWk+aBBjQf44jZW/TWoriV3gRddwi9L57IPfY9lA5Q3nF6YZyq33WIkLt/NTSJMCAcUD4/Wzhxt2o3Hjg0a3emSdPt7Q2t9vtn3KrfXY0L7U091rWo599xBggjSgh0pSa79aTl4ugaR8913qU9ld6vWlvd6bn+7mB+96MUHpcLULtHftemlqAAwKEwVd6MtNBbK4C7kWLuMkuDT5zA+za/nKzMC0VOu0CtXQhal2UeKCfG2PUPsvNZrUcey3NV8Dj0Z/cvctNQ77DmogWAM0S7M0gQQvwluS6HFZ0CQA8DJdDgwAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgAAAAQACAAQACAAQACAAQACAAAABAAIABAAIABAAIABAAIAAAAEAAgAEAAgAEAAgAEAAgAAAAYBlWf4A1W4Hx65cJAoAAAAASUVORK5CYII="; public static final String enableScreen = "iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAC4jAAAuIwF4pT92AAAEAklEQVR42u2dvXbjIBBG7T0+xw+gTp06v//LmE6dO/VR5a3wGZNh+BGSFeveJgkIBrDy8TGKds8/Pz/PExyW8/P55AY4MP9YgmNzmeeZVUABAA8AKADgAQAFADwAoACABwAUAPAAgAIAHgBQAMADAAoAeABAAY7LOI7fpQDX65VPtZCt18w5d7rdbigAbOgBxnE8DcPwJnnDMCTrNJlsUVcizTnj9HWxeVvINfN9y361OdTEk30551ZZt3PsvYDYxOSChoPQ6sJ21mRLBm61jY0lpy61gDKWNdfcNcv5wErWLbfPF88I9/s9WtayzopXS85YtPqcMeT23SqedV1pucal1V4iTUooV/IaWSfbWHU5JmkvpmzrsayaB9DqfJnVTpMff72sc869/WzVlcjjOI7mOOVYfBzfT05exLfT5pqae008a71Ly6tPASV79CfPylvFjpm+teLH+tXiF5nA2LOAUMpCibckWpPBUOJT20btFuDjyK8p+S45Z4fX+ti+LDb3pef62PosWbfkDbBW8mFPhB/gt8Vr7gG+kZK9+C/GM2+ArffnnKRHbT5gSdJoK0+ydrziGyCW115LolLxnHOr59q3lt89b6U8Czg4pgdI5bUtKY3VzfOclGBtTLVSmmqn1cdyC7Iud+5791KX1MLJDz3Mg2s59pK6sM/asdTmLrRx5pzjS+e+awWw9lstVeuv1/a10rqwT8sn5LQr8RzaMVfmKrR2qfnFjs57/puLS0nyoTZp0fL8XGq+ap8v4AES+3Msx74kN2/tmblewWoXPl9o+RykZH5/5hTQYv+y+vj084XcPHpJbHmt1s7yGbV1q+UBnHO/gnoZje2RmuzK/Vr2F3sWEF6TGkvutqH5CG08qTmk5u77tLyK5Qtq62rgxRA8AO8FHBkygQeHLQAFADwAoACABwAUAPAAgAIAHgBQAMADAAoAeABAAQAPACgA4AEABQA8AKAAgAcAFAC+3gNM03Tqum7VQSyN4dtvMdZDKcBWC9oqhr8JoIEHeDwep77vf5VJfL0vl9fLa/u+f+vPfx9eszSGNXZo5AH6vlcXW36gsqykrzViwAIPYL3r3nXd63v5m6i9J2+VaT8viWGNHZQbYE97+KdjHPIGKH0XPSyL7eXSjPk2YZlsN03Tq21OjLAs598ZggIT2MpMbW3IMICFN0Dsv4xpfUbfAvIAK9wAcOAtAMgDwJHzAIACAB4AUADAAwAKAHgAQAEADwAoAOABAAUAPACgAIAHABQA8ACAAgAeAFAAwAMACgB4AEABAA8AKADgAQAFADwAoACABwAUAPAAgAIAHgBQAMADAAoAeABAAQAPACgA4AEABQA8AKAAgAcAFADwANCe/0of1jQ8XY5YAAAAAElFTkSuQmCC"; private static IBufferGL vbo = null; @@ -74,18 +74,17 @@ public class EarlyLoadScreen { PlatformRuntime.freeByteBuffer(upload); IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER); - _wglShaderSource(vert, "#version 300 es\nprecision lowp float; in vec2 a_pos; out vec2 v_pos; void main() { gl_Position = vec4(((v_pos = a_pos) - 0.5) * vec2(2.0, -2.0), 0.0, 1.0); }"); + _wglShaderSource(vert, "#version 300 es\nprecision lowp float; layout(location = 0) in vec2 a_pos; out vec2 v_pos; void main() { gl_Position = vec4(((v_pos = a_pos) - 0.5) * vec2(2.0, -2.0), 0.0, 1.0); }"); _wglCompileShader(vert); IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER); - _wglShaderSource(frag, "#version 300 es\nprecision lowp float; in vec2 v_pos; out vec4 fragColor; uniform sampler2D tex; uniform vec2 aspect; void main() { fragColor = vec4(texture(tex, clamp(v_pos * aspect - ((aspect - 1.0) * 0.5), 0.02, 0.98)).rgb, 1.0); }"); + _wglShaderSource(frag, "#version 300 es\nprecision lowp float; in vec2 v_pos; layout(location = 0) out vec4 fragColor; uniform sampler2D tex; uniform vec2 aspect; void main() { fragColor = vec4(texture(tex, clamp(v_pos * aspect - ((aspect - 1.0) * 0.5), 0.02, 0.98)).rgb, 1.0); }"); _wglCompileShader(frag); program = _wglCreateProgram(); _wglAttachShader(program, vert); _wglAttachShader(program, frag); - _wglBindAttribLocation(program, 0, "a_pos"); _wglLinkProgram(program); _wglDetachShader(program, vert); _wglDetachShader(program, frag); diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/MainClass.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/MainClass.java index 68e949a..f15d13c 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/MainClass.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/MainClass.java @@ -18,6 +18,7 @@ import org.teavm.jso.webgl.WebGLRenderingContext; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; import net.minecraft.client.main.Main; @@ -90,6 +91,8 @@ public class MainClass { configLocalesFolder = configLocalesFolder.substring(0, configLocalesFolder.length() - 1); } + DeferredStateManager.doCheckErrors = eaglercraftOpts.optBoolean("checkShaderGLErrors", false); + ((TeaVMClientConfigAdapter)TeaVMClientConfigAdapter.instance).loadJSON(eaglercraftOpts); systemOut.println("MainClass: [INFO] configuration was successful"); @@ -317,10 +320,13 @@ public class MainClass { ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)).append('\n'); ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)).append('\n'); }else { - ret.append("webgl.renderer = ").append("" + ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); - ret.append("webgl.vendor = ").append("" + ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]").append('\n'); + ret.append("webgl.renderer = ").append(ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); + ret.append("webgl.vendor = ").append(ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]").append('\n'); } - //ret.append("\nwebgl.anisotropicGlitch = ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO + //ret.append('\n').append("\nwebgl.anisotropicGlitch = ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO + ret.append('\n').append("webgl.ext.HDR16f = ").append(ctx.getExtension("EXT_color_buffer_half_float") != null).append('\n'); + ret.append("webgl.ext.HDR32f = ").append(ctx.getExtension("EXT_color_buffer_float") != null).append('\n'); + }else { ret.append("Failed to query GPU info!\n"); } diff --git a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/WebGL2RenderingContext.java b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/WebGL2RenderingContext.java index d05cdb9..579f1f6 100644 --- a/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/WebGL2RenderingContext.java +++ b/sources/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/WebGL2RenderingContext.java @@ -1,6 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.teavm; +import org.teavm.jso.typedarrays.ArrayBufferView; +import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.webgl.WebGLBuffer; +import org.teavm.jso.webgl.WebGLProgram; import org.teavm.jso.webgl.WebGLRenderingContext; +import org.teavm.jso.webgl.WebGLTexture; +import org.teavm.jso.webgl.WebGLUniformLocation; /** * Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved. @@ -16,14 +22,15 @@ import org.teavm.jso.webgl.WebGLRenderingContext; * */ public interface WebGL2RenderingContext extends WebGLRenderingContext { - - int TEXTURE_MAX_LEVEL = 0x0000813D; - int TEXTURE_MAX_ANISOTROPY_EXT = 0x000084FE; - int UNSIGNED_INT_24_8 = 0x000084FA; + + int TEXTURE_MAX_LEVEL = 0x0000813D; + int TEXTURE_MAX_ANISOTROPY_EXT = 0x000084FE; + int UNSIGNED_INT_24_8 = 0x000084FA; int ANY_SAMPLES_PASSED = 0x00008D6A; int QUERY_RESULT = 0x00008866; int QUERY_RESULT_AVAILABLE = 0x00008867; int DEPTH24_STENCIL8 = 0x000088F0; + int DEPTH_COMPONENT24 = 0x000081A6; int DEPTH_COMPONENT32F = 0x00008CAC; int READ_FRAMEBUFFER = 0x00008CA8; int DRAW_FRAMEBUFFER = 0x00008CA9; @@ -61,5 +68,24 @@ public interface WebGL2RenderingContext extends WebGLRenderingContext { void drawArraysInstanced(int p1, int p2, int p3, int p4); void drawElementsInstanced(int p1, int p2, int p3, int p4, int p5); - + + int getUniformBlockIndex(WebGLProgram p1, String p2); + + void bindBufferRange(int p1, int p2, WebGLBuffer p3, int p4, int p5); + + void uniformBlockBinding(WebGLProgram p1, int p2, int p3); + + void uniformMatrix3x2fv(WebGLUniformLocation location, boolean transpose, Float32Array value); + + void uniformMatrix4x2fv(WebGLUniformLocation location, boolean transpose, Float32Array value); + + void uniformMatrix4x3fv(WebGLUniformLocation location, boolean transpose, Float32Array value); + + void texStorage2D(int target, int levels, int internalFormat, int width, int height); + + void texImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, int format, + int type, ArrayBufferView pixels); + + void framebufferTextureLayer(int target, int attachment, WebGLTexture texture, int level, int layer); + }