Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0781cbd964 | ||
|
|
71296a9cfb |
@@ -20,13 +20,11 @@ La [vision complète](docs/vision.md) conserve les intentions ; le
|
||||
L’économie, les claims et les dimensions décrits dans la vision restent
|
||||
à implémenter.
|
||||
|
||||
La version **beta.135** corrige le SSGI en contre-plongée et près des surfaces :
|
||||
normales indépendantes de la taille des pixels et atténuation progressive au
|
||||
contact. Bloom initial à **20 %**, PBR et SSGI **activés par défaut**.
|
||||
**Options → Shaders** ; réglages existants conservés.
|
||||
Le [ticket de livraison](docs/shader-beta135.md) décrit le rendu et ses limites.
|
||||
Release publiée et même instance **Sanctuary Beta** synchronisée, sauvegardes
|
||||
et réglages conservés.
|
||||
La version **beta.136** ajoute un **lens flare rectangulaire doux** pour le
|
||||
soleil et la lune, activé à 30 % et réglable indépendamment du bloom.
|
||||
**Options → Shaders** ; les blocs masquent les astres et leurs reflets.
|
||||
Le [ticket de livraison](docs/shader-beta136.md) décrit le rendu et ses vérifications.
|
||||
Release publiée et même instance Prism synchronisée ; sauvegardes et réglages conservés.
|
||||
La [livraison précédente](docs/clay-workshop-integration-beta110.md) réunit déjà
|
||||
l’atelier, les œufs et la neige saisonnière dans l’instance **Sanctuary Beta**.
|
||||
Les [synchronisations antérieures](docs/git-sync-beta092.md) restent documentées.
|
||||
@@ -37,6 +35,13 @@ La [carte native beta.005](docs/atlas-beta005.md) prend le relais après
|
||||
l’étude de Xaero et des alternatives libres.
|
||||
|
||||
|
||||
## beta.136 — Lens flare rectangulaire
|
||||
|
||||
Soleil et lune, reflets doux et intensité indépendante du bloom.
|
||||
[Contrat et vérifications](docs/shader-beta136.md) ·
|
||||
[Pack normal](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.136/Sanctuary-beta.136.mrpack) ·
|
||||
[Pack de test](https://git.botsu.net/koka/sanctuary-beta/releases/download/beta.136/Sanctuary-Test-beta.136.mrpack).
|
||||
|
||||
## beta.135 — SSGI près des surfaces
|
||||
|
||||
Correction des coupures à courte distance, sans flouter les textures.
|
||||
|
||||
@@ -14,6 +14,18 @@ JAR Sanctuary sont des pièces jointes de releases Gitea. Aucun JAR de mod ou
|
||||
dépendance téléchargée n'entre dans l'historique Git. Le canal Beta est distinct
|
||||
de l'ancien pack 26.2.
|
||||
|
||||
## beta.136 — Lens flare rectangulaire
|
||||
|
||||
Rectangles à dégradé doux pour le soleil et la lune, activés à 30 % et
|
||||
réglables indépendamment du bloom. Occultation par les blocs et phases lunaires.
|
||||
[Contrat et vérifications](shader-beta136.md).
|
||||
[Release beta.136](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.136)
|
||||
publiée ; canal `dd5b545a7cfbb957f2c70e9dc17034b44caef98f`. Deux synchronisations isolées,
|
||||
puis deux dans la même instance Sanctuary Beta réussies. Les 923 fichiers
|
||||
personnels suivis gardent leurs hashes. Aucun monde personnel ouvert ;
|
||||
sauvegarde préalable `sanctuary-backups/before-beta.136/`.
|
||||
Packs normal/Test/template vérifiés dans `sanctuary-beta/build/`.
|
||||
|
||||
## beta.135 — SSGI en proximité et nouveaux défauts
|
||||
|
||||
Normales stables près des surfaces, atténuation progressive du rebond au contact.
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# SHADER-136 — Lens flare rectangulaire doux
|
||||
|
||||
Demande : ajouter un lens flare avec des rectangles dégradés, exclusivement
|
||||
pour le soleil et la lune. Socle beta.135, branche `codex/lens-flare-beta136`.
|
||||
Minecraft 26.3 / Java 25. Aucun changement de gameplay ou de monde.
|
||||
|
||||
## Contrat
|
||||
|
||||
Effet activé initialement à **30 %**, intensité réglable 0–100, indépendant du halo de bloom.
|
||||
Rectangles translucides aux bords doux, suivant la position de l'astre à l'écran.
|
||||
La visibilité provient de l'image émissive céleste native, avant les blocs :
|
||||
les murs masquent l'effet, les sources de terrain ne le déclenchent pas.
|
||||
L'astre sortant du champ doit s'atténuer sans sauter sur le bord opposé.
|
||||
Pas d'historique, ni lecture GPU vers le CPU, ni texture générée sur disque.
|
||||
|
||||
## Rendu et budget
|
||||
|
||||
Trois rectangles à dégradé doux par astre : un halo horizontal près de sa
|
||||
position et deux reflets plus petits le long de l'axe passant par le centre de
|
||||
l'écran. Teinte solaire chaude, lunaire légèrement bleue. Intégration de la
|
||||
lumière réellement dessinée par le ciel natif ; phases de lune conservées.
|
||||
Atténuation aux bords de l'écran et à l'horizon, sans projection derrière la caméra.
|
||||
|
||||
Le masque céleste est mesuré avant l'ajout des émissifs de terrain. Réduction
|
||||
vers une texture 2 × 1 RGBA16F (512 échantillons au maximum au total), puis une
|
||||
passe de composition avec deux lectures de cette texture et des dégradés analytiques.
|
||||
La cible d'émission plein écran existante est réutilisée. Quand seul le flare
|
||||
fonctionne, aucun maillage d'émissif de terrain ni tampon de flou n'est construit.
|
||||
OFF et zéro libèrent la cible du flare ; les autres effets gardent leur autonomie.
|
||||
|
||||
## Vérification
|
||||
|
||||
Le scénario client natif réussit en **1 min 52 s** sur macOS / Apple M1 / OpenGL.
|
||||
Soleil OFF/30/80, lune et nouvelle lune, mur occultant, source hors champ,
|
||||
glowstone exclue, image statique, redimensionnement et rechargement des ressources.
|
||||
Le flare reste actif sans bloom ; OFF/zéro libèrent ses ressources. Préférences
|
||||
vierges, partielles, personnalisées, bornage et libellés FR/EN vérifiés.
|
||||
Les contrôles existants du bloom et des minerais émissifs passent également.
|
||||
Log : `build/shader136-client-final.log`, marqueurs `EMISSIVE131_PASS` et
|
||||
`LENS_FLARE136_PASS`. Les captures natives restent dans le dossier de tests ; comparatif autonome
|
||||
`build/Shader-beta.136-comparaison.html` (soleil OFF/30/80 et lune OFF/30).
|
||||
|
||||
Une première tentative s'est arrêtée sur l'attente d'un angle de caméra :
|
||||
Minecraft normalise 180° en −180°. Le scénario utilise maintenant un angle
|
||||
canonique ; ce changement concerne uniquement le test.
|
||||
|
||||
## Limites
|
||||
|
||||
Effet optique en espace écran : il s'atténue quand l'astre quitte le champ et
|
||||
à l'horizon. Le masque natif du ciel contrôle l'occultation ; la lune reste
|
||||
volontairement beaucoup plus discrète. Le brouillard de submersion suspend
|
||||
l'effet comme le bloom existant. Aucun essai Windows/Vulkan ni mesure de FPS
|
||||
revendiqués.
|
||||
|
||||
|
||||
## Construction et archives
|
||||
|
||||
`./gradlew check build assemblePack assembleTestPack -x :sanctuary:runGameTest`
|
||||
réussit en **2 min 29 s**, 126 tâches. Le serveur GameTest dédié reste exclu
|
||||
conformément au refus EULA antérieur. Log : `build/shader136-build.log`.
|
||||
Comparaison à beta.135 : **9 entrées de production** modifiées, uniquement
|
||||
le rendu, ses préférences et ses libellés. Gameplay et textures des gemmes
|
||||
strictement conservés. JAR normal/Test identique, sources et template vérifiés.
|
||||
Reçu local : `build/shader136-artifact.json`.
|
||||
|
||||
- `Sanctuary-beta.136.mrpack` : 10424821 octets ; SHA-256 `808006bf2b0cb3fe63d3e16ae3a0003d27ad0b7e793a3a05f25b5d73ae88bc8d`.
|
||||
|
||||
- `Sanctuary-Test-beta.136.mrpack` : 10443744 octets ; SHA-256 `70f593ad16d1f4fd4305b276ce2727a63f87bcb84df45e55840c1427a314a1eb`.
|
||||
|
||||
JAR : `086afede22903f8988889f6085631451f65d6d55c2e4c81f249d2234698e68e5`.
|
||||
|
||||
## Livraison
|
||||
|
||||
[Release beta.136](https://git.botsu.net/koka/sanctuary-beta/releases/tag/beta.136)
|
||||
publiée depuis `71296a9cfb0f6b1a6e6f0c48145f3cc432c8afd0`. Canal packwiz
|
||||
`dd5b545a7cfbb957f2c70e9dc17034b44caef98f` ; téléchargements publics vérifiés par SHA-256.
|
||||
Deux synchronisations isolées puis deux dans la même instance **Sanctuary Beta**
|
||||
réussissent. Un seul JAR beta.136 actif ; les **923 fichiers personnels suivis**,
|
||||
dont sauvegardes et préférences, gardent leurs hashes. Copie préalable dans
|
||||
`sanctuary-backups/before-beta.136/`, aucun monde personnel ouvert.
|
||||
|
||||
Packs normal/Test/template et comparatif natif également vérifiés dans
|
||||
`sanctuary-beta/build/`. Le checkout original garde ses changements préexistants.
|
||||
Reçus locaux ignorés : `build/shader136-artifact.json`, `build/shader136-isolated.json`,
|
||||
`build/shader136-prism.json`, `build/shader136-publication.log`.
|
||||
+2
-2
@@ -9,8 +9,8 @@ loom_version=1.17.20
|
||||
fabric_api_version=0.160.5+26.3
|
||||
|
||||
# Release counter: beta.001, .002, .003, ... (see docs/versioning.md).
|
||||
mod_version=beta.135
|
||||
pack_version=beta.135
|
||||
mod_version=beta.136
|
||||
pack_version=beta.136
|
||||
resource_pack_version=beta.121
|
||||
maven_group=fr.koka.sanctuary
|
||||
jei_version=30.32.0-sanctuary.3
|
||||
|
||||
+2
-1
@@ -23,7 +23,7 @@ public final class Bloom130ClientChecks implements FabricClientGameTest {
|
||||
String ns=name.equals("ruby")||name.equals("sapphire")?"sanctuary:":"minecraft:";result.add(ns+name+"_ore");result.add(ns+"deepslate_"+name+"_ore");}
|
||||
result.add("minecraft:nether_quartz_ore");result.add("minecraft:nether_gold_ore");return List.copyOf(result);}
|
||||
static void run(ClientGameTestContext c,TestServerContext server){
|
||||
c.runOnClient(m->{preferences();VanillaLight.setPbr(false);VanillaLight.setSsgi(false);analyseTextures();VanillaLight.setSaturation(100);VanillaLight.setPixelShadows(false);VanillaLight.setEdgeHighlights(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);});
|
||||
c.runOnClient(m->{preferences();VanillaLight.setLensFlare(false);VanillaLight.setPbr(false);VanillaLight.setSsgi(false);analyseTextures();VanillaLight.setSaturation(100);VanillaLight.setPixelShadows(false);VanillaLight.setEdgeHighlights(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);});
|
||||
server.runOnServer(s->{command(s,"time set 18000");
|
||||
for(int x=4;x<=20;x++)for(int z=4;z<=20;z++){
|
||||
s.overworld().setBlockAndUpdate(new BlockPos(x,64,z),Blocks.CONCRETE.black().defaultBlockState());
|
||||
@@ -97,6 +97,7 @@ public final class Bloom130ClientChecks implements FabricClientGameTest {
|
||||
unchanged(coveredOff,capture(c,null),"Zero bloom leaves no residual glow");
|
||||
c.runOnClient(m->{VanillaLight.setBloomIntensity(35);VanillaLight.setBloom(false);VanillaLight.setOreEmission(true);VanillaLight.setOreIntensity(50);});
|
||||
System.out.println("EMISSIVE131_PASS independent cores with halo OFF/zero; blur resources released; defaults; masks for 20 ore textures; selective night glow; halo intensity/spread; no through-wall glow; live edits; torch/glowstone/lamp/lava/sun; resource reload; defaults/migration; orePixels="+orePixels+" oreGain="+oreGain+" haloLow="+low+" haloHigh="+high+" sunHalo="+sunlight);
|
||||
LensFlare136ClientChecks.run(c,server);
|
||||
}
|
||||
private static BlockPos orePos(int i){return new BlockPos(8+i%5,65,8+i/5);}
|
||||
private static void preferences(){try{
|
||||
|
||||
+1
@@ -160,6 +160,7 @@ final class EdgeHighlights129ClientChecks {
|
||||
check(VanillaLight.edgeHighlights(),"Toggle persists independently");
|
||||
VanillaLight.setEdgeHighlights(false);
|
||||
VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);
|
||||
VanillaLight.setLensFlare(false);
|
||||
VanillaLight.setPbr(false);VanillaLight.setSsgi(false);
|
||||
} catch(java.io.IOException e) { throw new AssertionError(e); }
|
||||
}
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package fr.koka.sanctuary.client.shader;
|
||||
|
||||
import static fr.koka.sanctuary.client.shader.PixelShadows122ClientChecks.*;
|
||||
import java.nio.file.Files;
|
||||
import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext;
|
||||
import net.fabricmc.fabric.api.client.gametest.v1.context.TestServerContext;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
/** Native sky image, not a generated mockup; explicit independent effect controls. */
|
||||
final class LensFlare136ClientChecks {
|
||||
static void run(ClientGameTestContext c,TestServerContext server){
|
||||
c.runOnClient(m->{preferences();VanillaLight.setEnabled(true);VanillaLight.setSaturation(100);VanillaLight.setPbr(false);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setPixelShadows(false);VanillaLight.setEdgeHighlights(false);VanillaLight.setLensFlare(false);});
|
||||
server.runOnServer(s->{command(s,"time add 1");command(s,"time set 3000");});
|
||||
camera(c,server,100.5,130,100.5,70);aim(c,server,false);
|
||||
var off=capture(c,"flare-sun-off");enable(c,true);var on=capture(c,"flare-sun-30");
|
||||
long low=gain(off,on);check(low>1000,"Default sun flare is visible: "+low);
|
||||
c.runOnClient(m->check(!Bloom.haloAllocated()&&Bloom.flareAllocated(),"Flare runs without bloom blur targets"));
|
||||
unchanged(on,capture(c,null),"Static rectangular flare has no animated noise");
|
||||
c.runOnClient(m->VanillaLight.setLensFlareIntensity(80));frames(c);var high=capture(c,"flare-sun-80");
|
||||
check(gain(off,high)>low*1.5,"Flare intensity changes native pixels");
|
||||
var reload=c.computeOnClient(net.minecraft.client.Minecraft::reloadResourcePacks);c.waitFor(m->reload.isDone()&&m.gui.overlay()==null,1200);reload.join();frames(c);
|
||||
unchanged(high,capture(c,"flare-reloaded"),"Flare recovers after resource reload");
|
||||
int width=c.computeOnClient(m->m.getWindow().getScreenWidth()),height=c.computeOnClient(m->m.getWindow().getScreenHeight());
|
||||
c.runOnClient(m->m.getWindow().setWindowed(961,541));c.waitFor(m->m.gameRenderer.mainRenderTarget().width!=off.width(),200);frames(c);
|
||||
enable(c,false);var smallOff=capture(c,null);enable(c,true);check(gain(smallOff,capture(c,"flare-resized"))>1000,"Flare survives odd-sized targets");
|
||||
c.runOnClient(m->m.getWindow().setWindowed(width,height));c.waitFor(m->m.gameRenderer.mainRenderTarget().width==off.width(),200);frames(c);
|
||||
var direction=c.computeOnClient(m->PixelShadows.sunDirection(m.gameRenderer.gameRenderState().levelRenderState.skyRenderState.sunAngle));
|
||||
var eye=c.computeOnClient(m->m.player.getEyePosition());var center=BlockPos.containing(eye.x+direction.x*8,eye.y+direction.y*8,eye.z+direction.z*8);
|
||||
cover(server,center,true);c.waitTicks(35);frames(c);var hiddenOn=capture(c,"flare-sun-covered");enable(c,false);
|
||||
unchanged(hiddenOn,capture(c,null),"Occluded sun produces no rectangular flare through a wall");
|
||||
cover(server,center,false);c.waitTicks(35);aim(c,server,false);
|
||||
c.runOnClient(m->{VanillaLight.setBloom(true);VanillaLight.setBloomIntensity(20);VanillaLight.setLensFlareIntensity(30);});enable(c,true);capture(c,"flare-bloom-combined");
|
||||
c.runOnClient(m->VanillaLight.setBloom(false));look(c,server,0,80);enable(c,false);var away=capture(c,null);enable(c,true);unchanged(away,capture(c,"flare-away"),"Behind-camera celestial sources produce no reflected screen edge");
|
||||
server.runOnServer(s->s.overworld().setBlockAndUpdate(new BlockPos(100,129,104),Blocks.GLOWSTONE.defaultBlockState()));
|
||||
look(c,server,0,35);c.waitTicks(25);enable(c,false);var lampOff=capture(c,null);enable(c,true);unchanged(lampOff,capture(c,"flare-glowstone-excluded"),"Visible glowstone does not create a celestial flare");
|
||||
server.runOnServer(s->command(s,"time set 15000"));c.waitTicks(20);aim(c,server,true);
|
||||
enable(c,false);var moonOff=capture(c,"flare-moon-off");enable(c,true);long moon=gain(moonOff,capture(c,"flare-moon-30"));
|
||||
check(moon>200,"Native visible moon creates its own subtle flare: "+moon);
|
||||
server.runOnServer(s->command(s,"time set 111000"));c.waitFor(m->m.gameRenderer.gameRenderState().levelRenderState.skyRenderState.moonPhase.index()==4,200);aim(c,server,true);
|
||||
enable(c,false);var newOff=capture(c,null);enable(c,true);check(gain(newOff,capture(c,"flare-new-moon"))<moon*.1,"Dark new moon does not retain full moon flare");
|
||||
c.runOnClient(m->VanillaLight.setLensFlareIntensity(0));c.waitTicks(8);c.runOnClient(m->check(!Bloom.flareAllocated()&&!Bloom.allocated(),"Zero frees all resources with other effects OFF"));
|
||||
unchanged(newOff,capture(c,null),"Zero flare restores source image");
|
||||
c.runOnClient(m->{VanillaLight.setLensFlareIntensity(30);VanillaLight.setLensFlare(false);});
|
||||
for(String locale:new String[]{"fr_fr","en_us"})c.runOnClient(m->{
|
||||
m.getLanguageManager().setSelected(locale);m.getLanguageManager().onResourceManagerReload(m.getResourceManager());
|
||||
for(String suffix:new String[]{"lens_flare","lens_flare_help","lens_flare_intensity","lens_flare_intensity_help"}){
|
||||
String key="sanctuary.shaders."+suffix;check(!Component.translatable(key).getString().equals(key),"Localized flare control: "+locale+" "+key);
|
||||
}
|
||||
});
|
||||
System.out.println("LENS_FLARE136_PASS sunGain="+low+" moonGain="+moon+" visibility, resize, reload, strength, independent bloom, zero, preferences, FR/EN");
|
||||
}
|
||||
private static void cover(TestServerContext server,BlockPos center,boolean on){server.runOnServer(s->{for(int x=-4;x<=4;x++)for(int y=-4;y<=4;y++)for(int z=-4;z<=4;z++)s.overworld().setBlockAndUpdate(center.offset(x,y,z),on?Blocks.STONE.defaultBlockState():Blocks.AIR.defaultBlockState());});}
|
||||
private static void aim(ClientGameTestContext c,TestServerContext server,boolean moon){
|
||||
var direction=c.computeOnClient(m->PixelShadows.sunDirection(moon?m.gameRenderer.gameRenderState().levelRenderState.skyRenderState.moonAngle:m.gameRenderer.gameRenderState().levelRenderState.skyRenderState.sunAngle));
|
||||
look(c,server,net.minecraft.util.Mth.wrapDegrees((float)Math.toDegrees(Math.atan2(-direction.x,direction.z))+12),-(float)Math.toDegrees(Math.asin(direction.y))+8);
|
||||
}
|
||||
private static void frames(ClientGameTestContext c){int before=c.computeOnClient(m->Bloom.renderedFrames());c.waitFor(m->Bloom.applied()&&Bloom.ready()&&Bloom.renderedFrames()>before+10,1200);c.waitTicks(8);}
|
||||
private static void enable(ClientGameTestContext c,boolean value){c.runOnClient(m->VanillaLight.setLensFlare(value));if(value)frames(c);else c.waitTicks(8);}
|
||||
private static long gain(Frame off,Frame on){long sum=0;for(int i=0;i<off.pixels().length;i++)for(int shift:new int[]{0,8,16})sum+=Math.max(0,(on.pixels()[i]>>shift&255)-(off.pixels()[i]>>shift&255));return sum;}
|
||||
private static void preferences(){try{
|
||||
var path=FabricLoader.getInstance().getConfigDir().resolve("sanctuary-shaders.json");Files.writeString(path,"{\"bloom\":false,\"bloomIntensity\":20}");forgetPreferences();
|
||||
check(VanillaLight.lensFlare()&&VanillaLight.lensFlareIntensity()==30&&!VanillaLight.bloom()&&VanillaLight.bloomIntensity()==20,"Flare defaults preserve bloom choices");
|
||||
VanillaLight.setLensFlare(false);VanillaLight.setLensFlareIntensity(73);forgetPreferences();check(!VanillaLight.lensFlare()&&VanillaLight.lensFlareIntensity()==73,"Saved custom flare retained");
|
||||
for(int n:new int[]{-10,0,30,100,150}){VanillaLight.setLensFlareIntensity(n);forgetPreferences();check(VanillaLight.lensFlareIntensity()==Math.clamp(n,0,100),"Flare intensity persists and clamps");}
|
||||
VanillaLight.setLensFlareIntensity(30);
|
||||
}catch(java.io.IOException e){throw new AssertionError(e);}}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.util.Arrays;
|
||||
public final class Pbr134ClientChecks implements FabricClientGameTest {
|
||||
public void runTest(ClientGameTestContext c){new PixelShadows122ClientChecks(false,false,true).runTest(c);}
|
||||
static void run(ClientGameTestContext c,TestServerContext server){
|
||||
c.runOnClient(m->{preferences();materials();VanillaLight.setEnabled(true);VanillaLight.setSaturation(100);VanillaLight.setPbr(false);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setEdgeHighlights(false);VanillaLight.setPixelShadows(false);});
|
||||
c.runOnClient(m->{preferences();VanillaLight.setLensFlare(false);materials();VanillaLight.setEnabled(true);VanillaLight.setSaturation(100);VanillaLight.setPbr(false);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setEdgeHighlights(false);VanillaLight.setPixelShadows(false);});
|
||||
server.runOnServer(s->{command(s,"time set 1000");for(int x=-5;x<=24;x++)for(int z=-5;z<=24;z++){
|
||||
s.overworld().setBlockAndUpdate(new BlockPos(x,64,z),(x<10?Blocks.BRICKS:x<17?Blocks.OAK_PLANKS:Blocks.IRON_BLOCK).defaultBlockState());
|
||||
for(int y=65;y<=102;y++)s.overworld().setBlockAndUpdate(new BlockPos(x,y,z),Blocks.AIR.defaultBlockState());
|
||||
|
||||
+3
-2
@@ -266,7 +266,7 @@ public final class PixelShadows122ClientChecks implements FabricClientGameTest {
|
||||
});
|
||||
});
|
||||
c.waitTicks(3);
|
||||
c.takeScreenshot("sanctuary-beta135-shader-options-" + locale);
|
||||
c.takeScreenshot("sanctuary-beta136-shader-options-" + locale);
|
||||
}
|
||||
c.runOnClient(m -> m.gui.setScreen(null));
|
||||
}
|
||||
@@ -446,6 +446,7 @@ public final class PixelShadows122ClientChecks implements FabricClientGameTest {
|
||||
|
||||
private static void checkPreferences() {
|
||||
checkDefaults135();
|
||||
VanillaLight.setLensFlare(false);
|
||||
VanillaLight.setPbr(false);
|
||||
VanillaLight.setSsgi(false);
|
||||
VanillaLight.setBloom(false);
|
||||
@@ -549,7 +550,7 @@ public final class PixelShadows122ClientChecks implements FabricClientGameTest {
|
||||
}
|
||||
|
||||
static Frame capture(ClientGameTestContext c, String name) {
|
||||
if (name != null) c.takeScreenshot("sanctuary-beta135-shader-" + name);
|
||||
if (name != null) c.takeScreenshot("sanctuary-beta136-shader-" + name);
|
||||
var result = new CompletableFuture<Frame>();
|
||||
c.runOnClient(m -> Screenshot.takeScreenshot(m.gameRenderer.mainRenderTarget(), image -> {
|
||||
try (image) {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.nio.file.Files;
|
||||
public final class Ssgi132ClientChecks implements FabricClientGameTest {
|
||||
public void runTest(ClientGameTestContext c){new PixelShadows122ClientChecks(false,true).runTest(c);}
|
||||
static void run(ClientGameTestContext c,TestServerContext server){
|
||||
c.runOnClient(m->{preferences();VanillaLight.setPbr(false);VanillaLight.setEnabled(true);VanillaLight.setSaturation(100);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setPixelShadows(false);VanillaLight.setEdgeHighlights(false);});
|
||||
c.runOnClient(m->{preferences();VanillaLight.setLensFlare(false);VanillaLight.setPbr(false);VanillaLight.setEnabled(true);VanillaLight.setSaturation(100);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setPixelShadows(false);VanillaLight.setEdgeHighlights(false);});
|
||||
server.runOnServer(s->{command(s,"time set 6000");for(int x=-5;x<=24;x++)for(int z=-5;z<=24;z++){
|
||||
s.overworld().setBlockAndUpdate(new BlockPos(x,64,z),Blocks.CONCRETE.white().defaultBlockState());
|
||||
for(int y=65;y<=102;y++)s.overworld().setBlockAndUpdate(new BlockPos(x,y,z),Blocks.AIR.defaultBlockState());
|
||||
|
||||
@@ -42,16 +42,18 @@ public final class Bloom {
|
||||
var builder=RenderPipeline.builder().withLocation(id("pipeline/"+name)).withVertexShader("core/screenquad").withFragmentShader(id("core/"+name)).withBindGroupLayout(layout.build());
|
||||
if(scene)builder.withBindGroupLayout(SCENE);
|
||||
return RenderPipelines.register(builder.withPrimitiveTopology(PrimitiveTopology.TRIANGLES).withCull(false)
|
||||
.withColorTargetState(new ColorTargetState(Optional.ofNullable(blend),name.equals("bloom_blur")||name.equals("bloom_downsample")?GpuFormat.RGBA16_FLOAT:GpuFormat.RGBA8_UNORM,blend==null?ColorTargetState.WRITE_ALL:ColorTargetState.WRITE_COLOR)).withDepthStencilState(Optional.empty()).build());
|
||||
.withColorTargetState(new ColorTargetState(Optional.ofNullable(blend),name.equals("bloom_blur")||name.equals("bloom_downsample")||name.equals("lens_flare_source")?GpuFormat.RGBA16_FLOAT:GpuFormat.RGBA8_UNORM,blend==null?ColorTargetState.WRITE_ALL:ColorTargetState.WRITE_COLOR)).withDepthStencilState(Optional.empty()).build());
|
||||
}
|
||||
private static final RenderPipeline SKY=screen("bloom_sky",null,true,false);
|
||||
private static final RenderPipeline DOWNSAMPLE=screen("bloom_downsample",null,false,false);
|
||||
private static final RenderPipeline BLUR=screen("bloom_blur",null,false,true);
|
||||
private static final RenderPipeline CORE=screen("bloom_core",new BlendFunction(BlendFactor.ONE,BlendFactor.ONE_MINUS_SRC_ALPHA,BlendFactor.ZERO,BlendFactor.ONE),false,false);
|
||||
private static final RenderPipeline APPLY=screen("bloom_apply",new BlendFunction(BlendFactor.ONE,BlendFactor.ONE_MINUS_SRC_COLOR,BlendFactor.ZERO,BlendFactor.ONE),true,false);
|
||||
private static final RenderPipeline FLARE_SOURCE=screen("lens_flare_source",null,true,false);
|
||||
private static final RenderPipeline FLARE=screen("lens_flare",new BlendFunction(BlendFactor.ONE,BlendFactor.ONE_MINUS_SRC_COLOR,BlendFactor.ZERO,BlendFactor.ONE),true,false);
|
||||
private static final BloomTerrain TERRAIN=new BloomTerrain();
|
||||
private static final Matrix4f projection=new Matrix4f();
|
||||
private static TextureTarget emission,small,ping;
|
||||
private static TextureTarget emission,small,ping,flareSource;
|
||||
private static MappableRingBuffer scene,horizontal,vertical;
|
||||
private static int frames;
|
||||
private static boolean applied;
|
||||
@@ -62,8 +64,9 @@ public final class Bloom {
|
||||
public static void render(){
|
||||
applied=false;var mc=Minecraft.getInstance();
|
||||
boolean halo=VanillaLight.bloom()&&VanillaLight.bloomIntensity()>0;
|
||||
boolean flare=VanillaLight.lensFlare()&&VanillaLight.lensFlareIntensity()>0;
|
||||
boolean cores=VanillaLight.oreEmission()&&VanillaLight.oreIntensity()>0;
|
||||
if(!VanillaLight.active()||(!halo&&!cores)||mc.level==null){release();return;}
|
||||
if(!VanillaLight.active()||(!halo&&!cores&&!flare)||mc.level==null){release();return;}
|
||||
if(PanoramaCapture.rendering())return;
|
||||
var state=mc.gameRenderer.gameRenderState().levelRenderState;var camera=state.cameraRenderState;
|
||||
if(camera.fogType!=FogType.NONE)return;
|
||||
@@ -71,21 +74,28 @@ public final class Bloom {
|
||||
if(emission==null||emission.width!=main.width||emission.height!=main.height){
|
||||
targetsClose();emission=target("emission",main.width,main.height);
|
||||
}
|
||||
if(scene==null)scene=uniforms("bloom scene",144);
|
||||
if(scene==null)scene=uniforms("bloom scene",192);
|
||||
if(halo){
|
||||
if(small==null){small=target("bloom low",Math.max(1,main.width/8),Math.max(1,main.height/8));ping=target("bloom ping",small.width,small.height);}
|
||||
if(horizontal==null){horizontal=uniforms("bloom horizontal",16);vertical=uniforms("bloom vertical",16);}
|
||||
}else haloClose();
|
||||
var entries=TERRAIN.update();var atlas=TERRAIN.materials.atlas();
|
||||
if(flare){if(flareSource==null)flareSource=target("lens flare sources",2,1);}else flareClose();
|
||||
// A celestial-only flare never needs to scan or mesh terrain emitters.
|
||||
var entries=(halo||cores)?TERRAIN.update():List.<BloomTerrain.Entry>of();
|
||||
if(!halo&&!cores)TERRAIN.close();
|
||||
var atlas=TERRAIN.materials.atlas();
|
||||
var vp=new Matrix4f(projection).mul(camera.viewRotationMatrix);var inverse=new Matrix4f(vp).invert();
|
||||
var sun=PixelShadows.sunDirection(state.skyRenderState.sunAngle);var moon=PixelShadows.sunDirection(state.skyRenderState.moonAngle);
|
||||
float celestial=state.skyRenderState.skybox==DimensionType.Skybox.OVERWORLD?state.skyRenderState.rainBrightness:0;
|
||||
var flareSun=projectFlare(vp,sun,celestial);
|
||||
var flareMoon=projectFlare(vp,moon,celestial*.35f);
|
||||
var fog=camera.fogData;scene.rotate();
|
||||
try(var mapped=scene.currentBuffer().map(false,true)){
|
||||
Std140Builder.intoBuffer(mapped.data()).putMat4f(inverse)
|
||||
.putVec4(VanillaLight.oreEmission()?VanillaLight.oreIntensity()/100f:0,RenderSystem.getDevice().getDeviceInfo().isZZeroToOne()?1:0,VanillaLight.bloomIntensity()/50f,0)
|
||||
.putVec4(sun.x,sun.y,sun.z,celestial).putVec4(moon.x,moon.y,moon.z,celestial*.35f)
|
||||
.putVec4(fog.renderDistanceStart,fog.renderDistanceEnd,fog.environmentalStart,fog.environmentalEnd).putVec4(fog.color.w,0,0,0);
|
||||
.putVec4(fog.renderDistanceStart,fog.renderDistanceEnd,fog.environmentalStart,fog.environmentalEnd).putVec4(fog.color.w,0,0,0)
|
||||
.putVec4(flareSun).putVec4(flareMoon).putVec4(flare?VanillaLight.lensFlareIntensity()/100f:0,(float)main.width/main.height,0,0);
|
||||
}
|
||||
if(halo){
|
||||
float radius=.25f+VanillaLight.bloomRadius()*.0075f;
|
||||
@@ -98,9 +108,11 @@ public final class Bloom {
|
||||
transforms.add(RenderSystem.getDynamicUniforms().writeTransform(new Matrix4f(vp).translate(offset),new Vector4f(1,1,1,1),offset,new Matrix4f()));max=Math.max(max,entry.indices());}
|
||||
var indices=RenderSystem.getSequentialBuffer(PrimitiveTopology.QUADS);indices.requestIndexCount(max);
|
||||
var nearest=RenderSystem.getSamplerCache().getClampToEdge(FilterMode.NEAREST);
|
||||
if(halo)screen(SKY,emission.getColorTextureView(),main.getColorTextureView(),true,null);
|
||||
if(halo||flare)screen(SKY,emission.getColorTextureView(),main.getColorTextureView(),true,null);
|
||||
else try(var clear=RenderSystem.getDevice().createCommandEncoder().createRenderPass(()->"Sanctuary clear emission",emission.getColorTextureView(),Optional.of(new Vector4f(0,0,0,0)))){ }
|
||||
|
||||
// Reduce the celestial-only mask before drawing any torch, ore or other terrain emitter.
|
||||
if(flare)screen(FLARE_SOURCE,flareSource.getColorTextureView(),emission.getColorTextureView(),true,null);
|
||||
if(atlas!=null&&!entries.isEmpty())try(var pass=RenderSystem.getDevice().createCommandEncoder().createRenderPass(()->"Sanctuary visible emitters",emission.getColorTextureView(),Optional.empty())){
|
||||
pass.setPipeline(RenderSystem.getCompiledPipeline(EMITTERS));pass.setUniform("BloomScene",scene.currentBuffer());pass.setUniform("WorldDepth",main.getDepthTextureView(),nearest);
|
||||
pass.setUniform("BlockAtlas",mc.getTextureManager().getTexture(TextureAtlas.LOCATION_BLOCKS).getTextureView(),nearest);pass.setUniform("EmissionMasks",atlas.getTextureView(),nearest);
|
||||
@@ -114,8 +126,19 @@ public final class Bloom {
|
||||
}
|
||||
if(cores)screen(CORE,main.getColorTextureView(),emission.getColorTextureView(),false,null);
|
||||
if(halo)screen(APPLY,main.getColorTextureView(),small.getColorTextureView(),true,null);
|
||||
if(flare)screen(FLARE,main.getColorTextureView(),flareSource.getColorTextureView(),true,null);
|
||||
applied=true;frames++;
|
||||
}
|
||||
private static Vector4f projectFlare(Matrix4f vp,Vector3f direction,float strength){
|
||||
var clip=vp.transform(new Vector4f(direction,0));
|
||||
if(clip.w<=.05f||direction.y<=0||strength<=0)return new Vector4f(0,0,0,0);
|
||||
float x=clip.x/clip.w*.5f+.5f,y=clip.y/clip.w*.5f+.5f;
|
||||
// Actual sprite light is measured on GPU. This is only its projected sampling region.
|
||||
float radius=Math.min(.3f,Math.abs(projection.m11())*.08f/clip.w);
|
||||
float horizon=Math.clamp(direction.y/.08f,0,1);
|
||||
return new Vector4f(x,y,radius,strength*horizon*horizon*(3-2*horizon));
|
||||
}
|
||||
private static void flareClose(){if(flareSource!=null){flareSource.destroyBuffers();flareSource=null;}}
|
||||
private static void screen(RenderPipeline pipeline,GpuTextureView output,GpuTextureView input,boolean useScene,MappableRingBuffer blur){
|
||||
try(var pass=RenderSystem.getDevice().createCommandEncoder().createRenderPass(()->"Sanctuary bloom",output,Optional.empty())){
|
||||
pass.setPipeline(RenderSystem.getCompiledPipeline(pipeline));pass.setUniform("InputTexture",input,RenderSystem.getSamplerCache().getClampToEdge(pipeline==CORE||pipeline==SKY?FilterMode.NEAREST:FilterMode.LINEAR));
|
||||
@@ -129,8 +152,10 @@ public final class Bloom {
|
||||
if(small!=null){small.destroyBuffers();ping.destroyBuffers();small=ping=null;}
|
||||
if(horizontal!=null){horizontal.close();vertical.close();horizontal=vertical=null;}
|
||||
}
|
||||
private static void targetsClose(){haloClose();if(emission!=null){emission.destroyBuffers();emission=null;}}
|
||||
private static void targetsClose(){haloClose();flareClose();if(emission!=null){emission.destroyBuffers();emission=null;}}
|
||||
public static void release(){TERRAIN.close();targetsClose();if(scene!=null){scene.close();scene=null;}applied=false;}
|
||||
static TextureTarget flareTarget(){return flareSource;}
|
||||
static boolean flareAllocated(){return flareSource!=null;}
|
||||
static boolean haloAllocated(){return small!=null||horizontal!=null;}
|
||||
static boolean applied(){return applied;}
|
||||
static boolean allocated(){return emission!=null;}
|
||||
|
||||
@@ -30,6 +30,9 @@ public final class ShaderOptionsScreen extends OptionsSubScreen {
|
||||
Component.translatable("sanctuary.shaders.bloom_help")),VanillaLight.bloom(),VanillaLight::setBloom));
|
||||
slider("bloom_intensity",VanillaLight.bloomIntensity(),VanillaLight::setBloomIntensity);
|
||||
slider("bloom_radius",VanillaLight.bloomRadius(),VanillaLight::setBloomRadius);
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.lens_flare",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.lens_flare_help")),VanillaLight.lensFlare(),VanillaLight::setLensFlare));
|
||||
slider("lens_flare_intensity",VanillaLight.lensFlareIntensity(),VanillaLight::setLensFlareIntensity);
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.ore_emission",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.ore_emission_help")),VanillaLight.oreEmission(),VanillaLight::setOreEmission));
|
||||
slider("ore_intensity",VanillaLight.oreIntensity(),VanillaLight::setOreIntensity);
|
||||
|
||||
@@ -19,6 +19,8 @@ public final class VanillaLight {
|
||||
int saturation=142;
|
||||
boolean pixelShadows=true;
|
||||
boolean bloom=true;
|
||||
boolean lensFlare=true;
|
||||
int lensFlareIntensity=30;
|
||||
boolean pbr=true;
|
||||
int pbrIntensity=50;
|
||||
boolean ssgi=true;
|
||||
@@ -39,6 +41,7 @@ public final class VanillaLight {
|
||||
try{if(Files.isRegularFile(path()))preferences=new GsonBuilder().create().fromJson(Files.readString(path()),Preferences.class);}
|
||||
catch(Exception e){SanctuaryMod.LOGGER.warn("Cannot read Sanctuary shader preference",e);}
|
||||
if(preferences==null)preferences=new Preferences();
|
||||
preferences.lensFlareIntensity=Math.clamp(preferences.lensFlareIntensity,0,100);
|
||||
preferences.pbrIntensity=Math.clamp(preferences.pbrIntensity,0,100);
|
||||
preferences.ssgiIntensity=Math.clamp(preferences.ssgiIntensity,0,100);
|
||||
preferences.bloomIntensity=Math.clamp(preferences.bloomIntensity,0,100);
|
||||
@@ -61,6 +64,10 @@ public final class VanillaLight {
|
||||
public static int edgeIntensity(){enabled();return preferences.edgeIntensity;}
|
||||
public static void setEdgeHighlights(boolean value){enabled();preferences.edgeHighlights=value;save();}
|
||||
public static void setEdgeIntensity(int value){enabled();preferences.edgeIntensity=Math.clamp(value,0,100);save();}
|
||||
public static boolean lensFlare(){enabled();return preferences.lensFlare;}
|
||||
public static int lensFlareIntensity(){enabled();return preferences.lensFlareIntensity;}
|
||||
public static void setLensFlare(boolean value){enabled();preferences.lensFlare=value;save();}
|
||||
public static void setLensFlareIntensity(int value){enabled();preferences.lensFlareIntensity=Math.clamp(value,0,100);save();}
|
||||
public static boolean pbr(){enabled();return preferences.pbr;}
|
||||
public static int pbrIntensity(){enabled();return preferences.pbrIntensity;}
|
||||
public static void setPbr(boolean value){enabled();preferences.pbr=value;save();}
|
||||
|
||||
@@ -2298,5 +2298,10 @@
|
||||
"sanctuary.shaders.pbr_help": "Experimental: procedural block normals and roughness, sun and moon highlights. Range 32 blocks. ON by default.",
|
||||
"sanctuary.shaders.pbr_intensity": "PBR strength",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Material relief and highlights. Zero stops rendering and frees the cache. Original textures remain unchanged.",
|
||||
"sanctuary.shaders.pbr_intensity_value": "PBR: %s%%"
|
||||
"sanctuary.shaders.pbr_intensity_value": "PBR: %s%%",
|
||||
"sanctuary.shaders.lens_flare": "Lens flare · soft rectangles",
|
||||
"sanctuary.shaders.lens_flare_help": "Soft rectangular sun and moon reflections. Obstacles hide the sources. Independent of the bloom halo.",
|
||||
"sanctuary.shaders.lens_flare_intensity": "Lens flare intensity",
|
||||
"sanctuary.shaders.lens_flare_intensity_help": "Celestial reflection strength. Zero disables the effect.",
|
||||
"sanctuary.shaders.lens_flare_intensity_value": "Lens flare: %s %%"
|
||||
}
|
||||
|
||||
@@ -2298,5 +2298,10 @@
|
||||
"sanctuary.shaders.pbr_help": "Expérimental : normales procédurales et rugosité des blocs, reflets du soleil et de la lune. Portée 32 blocs. Activé par défaut.",
|
||||
"sanctuary.shaders.pbr_intensity": "Intensité du PBR",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Relief et reflets des matériaux. Zéro coupe le calcul et libère le cache. Ne modifie pas les textures originales.",
|
||||
"sanctuary.shaders.pbr_intensity_value": "PBR : %s %%"
|
||||
"sanctuary.shaders.pbr_intensity_value": "PBR : %s %%",
|
||||
"sanctuary.shaders.lens_flare": "Lens flare · rectangles doux",
|
||||
"sanctuary.shaders.lens_flare_help": "Reflets rectangulaires du soleil et de la lune, aux bords dégradés. Les obstacles masquent les sources. Indépendant du halo de bloom.",
|
||||
"sanctuary.shaders.lens_flare_intensity": "Intensité du lens flare",
|
||||
"sanctuary.shaders.lens_flare_intensity_help": "Force des reflets célestes. Zéro désactive le calcul.",
|
||||
"sanctuary.shaders.lens_flare_intensity_value": "Lens flare : %s %%"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#version 330
|
||||
#extension GL_ARB_separate_shader_objects : require
|
||||
#include <sanctuary:bloom_scene.glsl>
|
||||
uniform sampler2D InputTexture;
|
||||
layout(location=0) in vec2 texCoord;
|
||||
layout(location=0) out vec4 fragColor;
|
||||
float softBox(vec2 center,vec2 halfSize){
|
||||
vec2 q=abs((texCoord-center)*vec2(FlareParams.y,1))/halfSize;
|
||||
float fade=1.0-smoothstep(.08,1.0,max(q.x,q.y));
|
||||
return fade*fade;
|
||||
}
|
||||
vec3 flare(vec4 source,vec3 light,vec3 tint){
|
||||
vec2 axis=source.xy-vec2(.5);
|
||||
float shape=softBox(source.xy,vec2(.26,.075))*.55;
|
||||
shape+=softBox(vec2(.5)-axis*.4,vec2(.115,.085))*.35;
|
||||
shape+=softBox(vec2(.5)-axis*.9,vec2(.055,.045))*.22;
|
||||
return light*tint*shape;
|
||||
}
|
||||
void main(){
|
||||
vec3 sun=texture(InputTexture,vec2(.25,.5)).rgb;
|
||||
vec3 moon=texture(InputTexture,vec2(.75,.5)).rgb;
|
||||
vec3 light=flare(FlareSun,sun,vec3(1,.92,.78))+flare(FlareMoon,moon,vec3(.75,.87,1));
|
||||
fragColor=vec4(1.0-exp(-light*FlareParams.x*6.0),0.0);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#version 330
|
||||
#extension GL_ARB_separate_shader_objects : require
|
||||
#include <sanctuary:bloom_scene.glsl>
|
||||
uniform sampler2D InputTexture;
|
||||
layout(location=0) in vec2 texCoord;
|
||||
layout(location=0) out vec4 fragColor;
|
||||
void main(){
|
||||
vec4 source=gl_FragCoord.x<1.0?FlareSun:FlareMoon;
|
||||
fragColor=vec4(0.0);
|
||||
if(source.w<=0.0)return;
|
||||
float border=min(min(source.x,source.y),min(1.0-source.x,1.0-source.y));
|
||||
float edge=smoothstep(0.0,.08,border);
|
||||
if(edge<=0.0)return;
|
||||
vec3 color=vec3(0);
|
||||
// Two output pixels only: stable area integration, not a full-screen sampling loop.
|
||||
for(int y=0;y<16;y++)for(int x=0;x<16;x++){
|
||||
vec2 offset=(vec2(x,y)+.5)/16.0*2.0-1.0;
|
||||
vec2 uv=source.xy+offset*source.z/vec2(FlareParams.y,1);
|
||||
if(any(lessThan(uv,vec2(0)))||any(greaterThan(uv,vec2(1))))continue;
|
||||
color+=texture(InputTexture,uv).rgb;
|
||||
}
|
||||
fragColor=vec4(color/256.0*source.w*edge,1.0);
|
||||
}
|
||||
@@ -6,6 +6,9 @@ layout(std140) uniform BloomScene {
|
||||
vec4 MoonDirection;
|
||||
vec4 FogDistance;
|
||||
vec4 FogInfo;
|
||||
vec4 FlareSun; // projected UV, sampling radius in screen-height units, visibility
|
||||
vec4 FlareMoon;
|
||||
vec4 FlareParams; // strength, aspect ratio, reserved, reserved
|
||||
};
|
||||
vec3 bloomPosition(vec2 uv,float depth) {
|
||||
vec4 p=InverseViewProjection*vec4(uv*2.0-1.0,BloomParams.y>0.5?depth:depth*2.0-1.0,1.0);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name = "Sanctuary"
|
||||
author = "KOKA99CAB"
|
||||
version = "beta.135"
|
||||
version = "beta.136"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
|
||||
Reference in New Issue
Block a user