Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c23d0c17e | ||
|
|
6f871446bb |
@@ -1,5 +1,17 @@
|
||||
# Sanctuary
|
||||
|
||||
## beta.149 — Distances PBR / SSR et feuillage (pack local)
|
||||
|
||||
Deux distances séparées, 64 blocs par défaut chacune, jusqu’à 256 blocs.
|
||||
Option renommée « SSR » et suppression du voile spéculaire sur le feuillage.
|
||||
[Contrat et vérifications](docs/independent-distances-beta149.md).
|
||||
|
||||
## beta.148 — PBR 50 % et soleil diffus (pack local)
|
||||
|
||||
PBR à 50 %, reflet solaire plus doux avec fusion par texel préservant
|
||||
la texture de l’eau. SSR à 20 %, portée commune jusqu’à 256 blocs.
|
||||
[Contrat et vérifications](docs/pbr-soft-sun-beta148.md).
|
||||
|
||||
## beta.147 — PBR proche, lune et portée 256 (pack local)
|
||||
|
||||
Correction du scintillement à très courte distance, reflet lunaire adouci
|
||||
@@ -2342,7 +2354,7 @@ Depuis beta.090, la cible est **Minecraft 26.3 finale**, publiée le 15 septembr
|
||||
| Fabric API | 0.160.5+26.3 |
|
||||
| Fabric Loom | 1.17.20 |
|
||||
| Gradle Wrapper | 9.5.1, distribution vérifiée par SHA-256 |
|
||||
| Sanctuary / pack | beta.147 |
|
||||
| Sanctuary / pack | beta.149 |
|
||||
|
||||
Java 25 et Python 3.11 ou plus récent sont nécessaires. Le script pack utilise
|
||||
uniquement la bibliothèque standard et repère aussi une installation Python
|
||||
@@ -2371,7 +2383,7 @@ décrits dans [Validation](docs/testing.md).
|
||||
|
||||
Résultats :
|
||||
|
||||
- `mods/sanctuary/build/libs/sanctuary-beta.147.jar` : mod à installer avec
|
||||
- `mods/sanctuary/build/libs/sanctuary-beta.149.jar` : mod à installer avec
|
||||
Fabric API sur la version Minecraft indiquée.
|
||||
- `build/packwiz/` : pack de développement complet, avec le mod construit et
|
||||
l'index vérifié. Voir [Installation packwiz](packwiz/README.md).
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# RENDER-149 — Distances PBR et SSR indépendantes
|
||||
|
||||
Branche `codex/separate-reflection-distances-beta149`, socle beta.148 `6f87144`.
|
||||
|
||||
- Deux réglages : Distance PBR et Distance SSR, chacun à 64 blocs par défaut.
|
||||
Choix 16, 32, 64, 128, 256 blocs, enregistrés séparément.
|
||||
- Le PBR conserve son propre fondu et sa propre limite de portée. Le SSR
|
||||
utilise sa distance pour les surfaces réfléchissantes et sa recherche de
|
||||
paysage. Le maillage et la sélection des surfaces couvrent le maximum des
|
||||
deux portées actives, afin que réduire l’une ne coupe pas l’autre.
|
||||
- Ancien défaut commun 32 migré une fois vers PBR 64 ; nouveau réglage SSR 64.
|
||||
Les anciennes valeurs PBR différentes de 32 restent conservées. Après la
|
||||
migration, un choix explicite 32 est conservé comme les autres valeurs.
|
||||
- Option nommée exactement « SSR » en français et en anglais, sans la mention
|
||||
« expérimental ». Les autres options expérimentales du jeu sont inchangées.
|
||||
- Intensités PBR 50 % et SSR 20 %, rendu solaire diffus de beta.148 conservés.
|
||||
SSR conserve sa dépendance au PBR et les limites du paysage visible/chargé
|
||||
et du budget de maillage.
|
||||
|
||||
- Les feuilles (et fibres de laine, même profil entièrement mat) ne reçoivent
|
||||
plus de large éclat spéculaire blanc. Leur relief normal reste présent.
|
||||
La pierre et le bois retrouvent exactement leur poids spéculaire précédent,
|
||||
comme les surfaces polies, les métaux, l’eau et le verre. La suppression
|
||||
concerne les profils non métalliques de rugosité 0,98, avec transition 0,90–0,98.
|
||||
|
||||
## Vérifications
|
||||
|
||||
Contrôles de persistance indépendante, valeurs par défaut et libellés FR/EN.
|
||||
Scènes graphiques avec PBR variable/SSR 256 puis PBR 256/SSR variable.
|
||||
- Suite PBR/préférences Vulkan réussie : deux défauts 64 et persistance
|
||||
indépendante sur 16/32/64/128/256 ; libellés FR/EN et nom SSR vérifiés.
|
||||
Journal : `build/beta149-pbr-vulkan.log`.
|
||||
- Suites SSR Vulkan et OpenGL réussies avec les portées dissociées, F5,
|
||||
intersections, eau/verre/métal, soleil/lune, OFF/zéro et rechargement.
|
||||
Journaux : `build/beta149-ssr-vulkan.log`, `build/beta149-ssr-opengl.log`.
|
||||
Ces passes précèdent l’ajustement final du profil entièrement mat.
|
||||
- Suite PBR Vulkan finale avec feuillage réussie : 170 172 pixels de feuilles
|
||||
contrôlés, saturation relative 1,00007, relief visible sur 63 236 pixels.
|
||||
Journal : `build/beta149-foliage-vulkan.log` ; captures correspondantes
|
||||
dans `build/evidence/beta149-foliage-vulkan/`.
|
||||
- Bois et briques après recentrage sur le feuillage : aucun pixel modifié
|
||||
par rapport à la capture précédant l’ajustement, sur les zones de contrôle
|
||||
de 26 304 et 40 896 pixels respectivement.
|
||||
- `./gradlew check build` exécuté dans l’instantané isolé : 252 tests serveur,
|
||||
229 réussis et 23 échecs, mêmes identifiants qu’en beta.148. Aucun nouvel échec.
|
||||
Journal : `build/beta149-check-build-isolated.log` ; comparaison :
|
||||
`build/beta149-server-failures.json`. L’ajustement final du feuillage concerne
|
||||
seulement le shader et son test client. Le contrôle global reste en échec.
|
||||
|
||||
- Suite PBR OpenGL finale réussie également : 170 199 pixels de feuilles,
|
||||
saturation relative 1,00001, relief visible sur 63 263 pixels.
|
||||
Journal : `build/beta149-foliage-opengl.log` ; captures correspondantes
|
||||
dans `build/evidence/beta149-foliage-opengl/`.
|
||||
- Assemblage final réussi : `./gradlew build assemblePack -x :sanctuary:check`,
|
||||
sans répéter les contrôles purs/serveur exécutés dans l’instantané.
|
||||
Journal : `build/beta149-build-pack.log`. Cette exclusion ne transforme
|
||||
pas le contrôle complet en réussite.
|
||||
|
||||
## Artefact
|
||||
|
||||
[Sanctuary-beta.149.mrpack](../build/Sanctuary-beta.149.mrpack), copié aussi dans
|
||||
`sanctuary-beta/build/` avec les autres versions. Archive vérifiée, un seul JAR
|
||||
Sanctuary beta.149 identique au JAR construit, shaders identiques aux sources,
|
||||
libellés SSR et deux portées FR/EN vérifiés. Minecraft 26.3 / Loader 0.19.5.
|
||||
Taille : 10 520 465 octets. SHA-256 :
|
||||
`ef5519d9a0e2006b865b62371a6f8712db02ab138aa9698339d6fdb02fb4befa`.
|
||||
Reçu : `build/beta149-artifacts.json`. Aucune installation Prism ni publication.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# RENDER-148 — PBR 50 % et reflet solaire diffus
|
||||
|
||||
Branche `codex/pbr-soft-sun-beta148`, socle beta.147 `96a36d9`.
|
||||
Minecraft 26.3, Java 25, dépendances et sauvegardes inchangés.
|
||||
|
||||
## Résultat
|
||||
|
||||
- PBR à 50 % par défaut, SSR toujours à 20 % et portée commune jusqu’à 256.
|
||||
- Les configurations anciennes contenant exactement PBR 80 % passent à 50 %.
|
||||
Un marqueur de migration conserve ensuite tout choix explicite, y compris
|
||||
un nouveau choix 80 %. Les autres anciennes intensités restent conservées.
|
||||
- Le reflet solaire de l’eau avait un renforcement ×20 et une compression
|
||||
exponentielle qui effaçait les détails dans une large zone blanche.
|
||||
Le renforcement passe à ×6 et le lobe est plus diffus (rugosité minimale
|
||||
de 0,42 au lieu de 0,34 pour le lobe céleste de l’eau).
|
||||
- Pour le soleil sur l’eau, fusion par texel entre éclaircissement vers le
|
||||
blanc et lumière douce fondée sur la couleur native. La pondération emploie
|
||||
une compression rationnelle, sans atteindre brutalement un plateau blanc.
|
||||
La texture et ses animations restent natives ; aucun bruit ajouté.
|
||||
- La lune conserve son intensité atténuée, sans renforcement solaire.
|
||||
Les lampes et matières solides conservent leur fusion spéculaire précédente.
|
||||
Le bloom reste réglable et suit la lumière réellement ajoutée.
|
||||
|
||||
## Vérifications
|
||||
|
||||
Scènes plates jetables, Apple M1, Vulkan et OpenGL. Le test solaire contrôle
|
||||
une lumière largement visible et limite les pixels quasi blancs à moins de
|
||||
0,5 % de l’image, au lieu d’imposer une grande tache blanche.
|
||||
|
||||
Premier contrôle Vulkan à PBR 50 % / SSR 20 % : 149 908 pixels éclaircis,
|
||||
zéro pixel quasi blanc sur 854 × 480. Captures vues du dessus et à soleil bas
|
||||
inspectées : la texture reste visible dans la traînée lumineuse.
|
||||
Preuves : `build/evidence/beta148-preview/`.
|
||||
Rendu de la traînée solaire approuvé par le créateur après inspection de la capture.
|
||||
|
||||
- Suites SSR complètes Vulkan et OpenGL réussies : F5, intersections, portées,
|
||||
eau/verre/métal, OFF/zéro, lune, bloom, rechargement et redimensionnement.
|
||||
Journaux : `build/beta148-ssr-vulkan.log`, `build/beta148-ssr-opengl.log`.
|
||||
Sous OpenGL, 146 680 pixels éclaircis et zéro pixel quasi blanc dans la scène
|
||||
solaire. La lune reste visible sans saturation (35 865 pixels modifiés).
|
||||
Preuves : `build/evidence/beta148-ssr-vulkan/` et
|
||||
`build/evidence/beta148-ssr-opengl/`.
|
||||
|
||||
- Suites PBR/préférences Vulkan et OpenGL réussies : défaut 50 %, migration
|
||||
de l’ancien 80 %, conservation d’un nouveau choix explicite 80 %, valeurs
|
||||
personnalisées, FR/EN, proximité, OFF/zéro, intensités et rechargement.
|
||||
Journaux : `build/beta148-pbr-vulkan.log`, `build/beta148-pbr-opengl.log`.
|
||||
- `./gradlew check build` dans l’instantané isolé : 252 tests serveur,
|
||||
229 réussis, 23 échecs. Exactement les mêmes identifiants que beta.147,
|
||||
aucun nouvel échec. Journal : `build/beta148-check-build-isolated.log` ;
|
||||
comparaison : `build/beta148-server-failures.json`. Le contrôle global
|
||||
demeure donc en échec.
|
||||
- Assemblage final réussi : `./gradlew build assemblePack -x :sanctuary:check`,
|
||||
sans répéter les contrôles purs et serveur déjà exécutés dans l’instantané.
|
||||
Journal : `build/beta148-build-pack.log`. L’exclusion ne constitue pas
|
||||
une réussite du contrôle complet.
|
||||
|
||||
## Artefact
|
||||
|
||||
[Sanctuary-beta.148.mrpack](../build/Sanctuary-beta.148.mrpack), également copié
|
||||
à côté des autres versions dans `sanctuary-beta/build/`. Archive ZIP vérifiée,
|
||||
un seul JAR Sanctuary beta.148 identique au JAR construit, shaders finaux
|
||||
identiques aux sources, textes FR/EN 50 % et dépendances exactes vérifiés.
|
||||
Taille : 10 520 050 octets. SHA-256 :
|
||||
`597cc2a96eabc3cf0ebf8ac59b4f94cf7cabf0c773e1dce13c10736ca6fcba38`.
|
||||
Reçu : `build/beta148-artifacts.json`.
|
||||
Aucune publication ni installation Prism effectuée.
|
||||
|
||||
+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.147
|
||||
pack_version=beta.147
|
||||
mod_version=beta.149
|
||||
pack_version=beta.149
|
||||
resource_pack_version=beta.121
|
||||
maven_group=fr.koka.sanctuary
|
||||
jei_version=30.32.0-sanctuary.3
|
||||
|
||||
+33
-4
@@ -50,10 +50,33 @@ public final class Pbr134ClientChecks implements FabricClientGameTest {
|
||||
c.runOnClient(m->m.getWindow().setWindowed(oldWidth,oldHeight));c.waitFor(m->m.gameRenderer.mainRenderTarget().width==on.width(),200);frames(c);
|
||||
c.runOnClient(m->{VanillaLight.setPixelShadows(true);VanillaLight.setSsgi(true);VanillaLight.setBloom(true);VanillaLight.setOreEmission(true);VanillaLight.setEdgeHighlights(true);});
|
||||
c.waitFor(m->PixelShadows.applied()&&PixelShadows.ready()&&ScreenSpaceGI.applied()&&Bloom.applied()&&EdgeHighlights.applied()&&ProceduralPbr.applied(),1200);frames(c);capture(c,"pbr-combined");
|
||||
foliage(c,server);
|
||||
c.runOnClient(m->VanillaLight.setEnabled(false));c.waitTicks(8);c.runOnClient(m->check(!ProceduralPbr.allocated()&&ProceduralPbr.materialCount()==0,"Global OFF releases PBR"));
|
||||
c.runOnClient(m->{VanillaLight.setEnabled(true);VanillaLight.setPbr(false);VanillaLight.setSsgi(false);});
|
||||
System.out.println("PBR134_PASS normals; profiles; texture cache; directional lighting; intensity; OFF/zero; tiny camera; reload; resize; combined; default="+delta+" high="+high+" directional="+directions);
|
||||
}
|
||||
private static void foliage(ClientGameTestContext c,TestServerContext server){
|
||||
c.runOnClient(m->{VanillaLight.setSsr(false);VanillaLight.setPbrIntensity(50);VanillaLight.setPixelShadows(false);VanillaLight.setSsgi(false);VanillaLight.setBloom(false);VanillaLight.setOreEmission(false);VanillaLight.setEdgeHighlights(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),Blocks.OAK_LEAVES.defaultBlockState().setValue(net.minecraft.world.level.block.LeavesBlock.PERSISTENT,true));});
|
||||
camera(c,server,10.5,69,5.5,65);look(c,server,0,40);settle(c);
|
||||
enable(c,false);var off=capture(c,"pbr149-leaves-off");enable(c,true);var on=capture(c,"pbr149-leaves-on");
|
||||
double nativeChroma=0,pbrChroma=0;int samples=0,relief=0;
|
||||
for(int y=off.height()/3;y<off.height()*9/10;y++)for(int x=off.width()/10;x<off.width()*9/10;x++){
|
||||
int i=y*off.width()+x,a=off.pixels()[i],b=on.pixels()[i],r=a>>16&255,g=a>>8&255,blue=a&255;
|
||||
if(g<30||g<r*1.1||g<blue*1.1)continue;
|
||||
nativeChroma+=chroma(a);pbrChroma+=chroma(b);samples++;
|
||||
if(Math.abs((b>>16&255)-r)+Math.abs((b>>8&255)-g)+Math.abs((b&255)-blue)>6)relief++;
|
||||
}
|
||||
double retained=pbrChroma/nativeChroma;
|
||||
System.out.println("PBR149_LEAVES samples="+samples+" chromaRetained="+retained+" relief="+relief);
|
||||
check(samples>1000&&retained>.985,"Leaves preserve green colour without specular veil: "+retained);
|
||||
check(relief>100,"Leaf normal relief remains visible");
|
||||
}
|
||||
private static double chroma(int pixel){
|
||||
int r=pixel>>16&255,g=pixel>>8&255,b=pixel&255,max=Math.max(r,Math.max(g,b)),min=Math.min(r,Math.min(g,b));
|
||||
return (max-min)/(double)Math.max(1,max);
|
||||
}
|
||||
private static void closeRange(ClientGameTestContext c,TestServerContext server){
|
||||
int failures=0;
|
||||
c.runOnClient(m->VanillaLight.setPbrIntensity(80));
|
||||
@@ -86,11 +109,16 @@ public final class Pbr134ClientChecks implements FabricClientGameTest {
|
||||
}
|
||||
private static void preferences(){try{
|
||||
var p=FabricLoader.getInstance().getConfigDir().resolve("sanctuary-shaders.json");Files.writeString(p,"{\"ssgi\":true,\"ssgiIntensity\":35,\"bloom\":false}");forgetPreferences();
|
||||
check(VanillaLight.pbr()&&VanillaLight.pbrIntensity()==80&&VanillaLight.ssgi()&&!VanillaLight.bloom(),"Missing PBR setting defaults ON while preserving explicit old choices");
|
||||
check(VanillaLight.pbr()&&VanillaLight.pbrIntensity()==50&&VanillaLight.ssgi()&&!VanillaLight.bloom(),"Missing PBR setting defaults ON while preserving explicit old choices");
|
||||
Files.writeString(p,"{\"pbrIntensity\":80}");forgetPreferences();
|
||||
check(VanillaLight.pbrIntensity()==50,"Previous 80 percent baseline migrates to 50 once");
|
||||
VanillaLight.setPbrIntensity(80);forgetPreferences();check(VanillaLight.pbrIntensity()==80,"New explicit 80 percent choice persists after migration");
|
||||
for(int n:new int[]{-1,0,50,100,101}){VanillaLight.setPbr(true);VanillaLight.setPbrIntensity(n);forgetPreferences();check(VanillaLight.pbr()&&VanillaLight.pbrIntensity()==Math.clamp(n,0,100),"PBR preference persistence/clamp");}
|
||||
check(VanillaLight.pbrDistance()==32,"Shared distance default");
|
||||
check(VanillaLight.pbrDistance()==64&&VanillaLight.ssrDistance()==64,"Independent distances default to 64");
|
||||
check(!VanillaLight.naturalWater(false)&&VanillaLight.naturalWater(true),"World-specific water defaults");
|
||||
for(int n:new int[]{16,32,64,128,256}){VanillaLight.setPbrDistance(n);forgetPreferences();check(VanillaLight.pbrDistance()==n,"Shared distance persistence");}
|
||||
for(int n:new int[]{16,32,64,128,256}){VanillaLight.setPbrDistance(n);forgetPreferences();check(VanillaLight.pbrDistance()==n&&VanillaLight.ssrDistance()==64,"PBR distance changes independently");}
|
||||
for(int n:new int[]{16,32,64,128,256}){VanillaLight.setSsrDistance(n);forgetPreferences();check(VanillaLight.ssrDistance()==n&&VanillaLight.pbrDistance()==256,"SSR distance changes independently");}
|
||||
VanillaLight.setSsrDistance(64);
|
||||
for(int n:new int[]{0,1,2,4,8}){VanillaLight.setWaterBlendRadius(n);forgetPreferences();check(VanillaLight.waterBlendRadius()==n,"Water blend persistence");}
|
||||
VanillaLight.setPbrDistance(32);VanillaLight.setWaterBlendRadius(4);
|
||||
check(!VanillaLight.ssr()&&VanillaLight.ssrIntensity()==20,"Missing SSR defaults OFF at 20 percent");
|
||||
@@ -99,10 +127,11 @@ public final class Pbr134ClientChecks implements FabricClientGameTest {
|
||||
var manager=net.minecraft.client.Minecraft.getInstance().getLanguageManager();var oldLanguage=manager.getSelected();
|
||||
for(String locale:new String[]{"fr_fr","en_us"}){
|
||||
manager.setSelected(locale);manager.onResourceManagerReload(net.minecraft.client.Minecraft.getInstance().getResourceManager());
|
||||
for(String key:new String[]{"pbr_distance","pbr_distance_help","pbr_distance_value","water_blend","water_blend_help","water_blend_value","ssr","ssr_help","ssr_intensity","ssr_intensity_help","ssr_intensity_value"}){
|
||||
for(String key:new String[]{"ssr_distance","ssr_distance_help","ssr_distance_value","pbr_distance","pbr_distance_help","pbr_distance_value","water_blend","water_blend_help","water_blend_value","ssr","ssr_help","ssr_intensity","ssr_intensity_help","ssr_intensity_value"}){
|
||||
String full="sanctuary.shaders."+key;check(!net.minecraft.network.chat.Component.translatable(full,50).getString().equals(full),"SSR FR/EN "+full);
|
||||
}
|
||||
}
|
||||
check(net.minecraft.network.chat.Component.translatable("sanctuary.shaders.ssr").getString().equals("SSR"),"SSR label without experimental qualifier");
|
||||
manager.setSelected(oldLanguage);manager.onResourceManagerReload(net.minecraft.client.Minecraft.getInstance().getResourceManager());
|
||||
Files.writeString(p,"{\"naturalWater\":false,\"pbrIntensity\":37}");forgetPreferences();
|
||||
check(!VanillaLight.naturalWater(false)&&!VanillaLight.naturalWater(true)&&VanillaLight.pbrIntensity()==37,"Legacy water OFF and personal PBR intensity are preserved");
|
||||
|
||||
+20
-5
@@ -46,15 +46,30 @@ final class PixelReflectionsClientChecks {
|
||||
c.runOnClient(m->m.options.setCameraType(net.minecraft.client.CameraType.FIRST_PERSON));c.waitTicks(20);
|
||||
server.runOnServer(s->command(s,"gamemode spectator @a"));c.waitTicks(10);
|
||||
for(int distance:new int[]{16,64,128,256,32}){
|
||||
c.runOnClient(m->VanillaLight.setPbrDistance(distance));settle(c);frames(c);capture(c,"ssr146-distance-"+distance);
|
||||
c.runOnClient(m->check(ProceduralPbr.applied()&&PixelReflections.applied(),"Both material passes share distance "+distance));
|
||||
c.runOnClient(m->{VanillaLight.setPbrDistance(distance);VanillaLight.setSsrDistance(256);});settle(c);frames(c);capture(c,"ssr146-distance-"+distance);
|
||||
c.runOnClient(m->check(ProceduralPbr.applied()&&PixelReflections.applied(),"Independent material distances render at PBR "+distance+" / SSR 256"));
|
||||
}
|
||||
|
||||
c.runOnClient(m->{VanillaLight.setPbrIntensity(80);VanillaLight.setSsrIntensity(20);});
|
||||
for(int distance:new int[]{16,64,256}){
|
||||
c.runOnClient(m->{VanillaLight.setPbrDistance(256);VanillaLight.setSsrDistance(distance);});settle(c);frames(c);
|
||||
capture(c,"ssr149-independent-"+distance);
|
||||
c.runOnClient(m->check(ProceduralPbr.applied()&&PixelReflections.applied(),"PBR 256 remains active with independent SSR "+distance));
|
||||
}
|
||||
c.runOnClient(m->VanillaLight.setPbrDistance(32));
|
||||
c.runOnClient(m->VanillaLight.setSsrDistance(32));
|
||||
c.runOnClient(m->{VanillaLight.setPbrIntensity(50);VanillaLight.setSsrIntensity(20);});
|
||||
camera(c,server,.5,68,10,70);settle(c);frames(c);
|
||||
c.runOnClient(m->VanillaLight.setPbr(false));c.waitTicks(8);var solarOff=capture(c,"ssr148-solar-water-off");
|
||||
c.runOnClient(m->VanillaLight.setPbr(true));frames(c);
|
||||
var solar=capture(c,"ssr146-solar-water");
|
||||
int white=0;for(int pixel:solar.pixels())if((pixel>>16&255)>235&&(pixel>>8&255)>235&&(pixel&255)>235)white++;
|
||||
check(white>300,"Solar reflection has a broad near-white footprint at PBR 80 / SSR 20 percent: "+white);
|
||||
int brightened=0;for(int i=0;i<solar.pixels().length;i++){
|
||||
int a=solarOff.pixels()[i],b=solar.pixels()[i];
|
||||
if((b>>16&255)+(b>>8&255)+(b&255)>(a>>16&255)+(a>>8&255)+(a&255)+24)brightened++;
|
||||
}
|
||||
check(brightened>5000,"Soft solar reflection remains broadly visible: "+brightened);
|
||||
check(white<solar.pixels().length*.005,"Soft solar reflection preserves texture instead of a white plateau: "+white);
|
||||
System.out.println("PBR148_SOLAR brightened="+brightened+" white="+white);
|
||||
System.out.println("SSR146_SOLAR_WHITE pixels="+white+" width="+solar.width()+" height="+solar.height());
|
||||
c.runOnClient(m->VanillaLight.setBloom(true));frames(c);capture(c,"ssr146-solar-water-bloom");
|
||||
c.runOnClient(m->check(MaterialBloom.contribution()!=null,"Material light reaches bloom"));
|
||||
@@ -64,7 +79,7 @@ final class PixelReflectionsClientChecks {
|
||||
c.runOnClient(m->VanillaLight.setSsr(false));c.waitTicks(8);
|
||||
var moon=capture(c,"ssr147-moon-water");
|
||||
int moonWhite=0;for(int pixel:moon.pixels())if((pixel>>16&255)>235&&(pixel>>8&255)>235&&(pixel&255)>235)moonWhite++;
|
||||
check(moonWhite<white*.05,"Moon reflection stays much softer than the sun: "+moonWhite+" / "+white);
|
||||
check(moonWhite<Math.max(10,white*.05),"Moon reflection stays much softer than the sun: "+moonWhite+" / "+white);
|
||||
c.runOnClient(m->VanillaLight.setPbr(false));c.waitTicks(8);var moonOff=capture(c,"ssr147-moon-water-off");
|
||||
check(changed(moonOff,moon)>100,"Soft moon reflection remains visible");
|
||||
System.out.println("PBR147_MOON white="+moonWhite+" sunWhite="+white+" changed="+changed(moonOff,moon));
|
||||
|
||||
+1
-1
@@ -454,7 +454,7 @@ public final class PixelShadows122ClientChecks implements FabricClientGameTest {
|
||||
var path=FabricLoader.getInstance().getConfigDir().resolve("sanctuary-shaders.json");
|
||||
Files.deleteIfExists(path);forgetPreferences();
|
||||
check(VanillaLight.bloom()&&VanillaLight.bloomIntensity()==20&&VanillaLight.pbr()&&VanillaLight.ssgi(),"Fresh defaults: bloom20, PBR and SSGI ON");
|
||||
check(VanillaLight.pbrIntensity()==80&&VanillaLight.ssrIntensity()==20&&VanillaLight.ssgiIntensity()==35,"PBR 80 and SSR 20 defaults, SSGI strength retained");
|
||||
check(VanillaLight.pbrIntensity()==50&&VanillaLight.ssrIntensity()==20&&VanillaLight.ssgiIntensity()==35,"PBR 50 and SSR 20 defaults, SSGI strength retained");
|
||||
Files.writeString(path,"{\"pbr\":false,\"ssgi\":false,\"bloomIntensity\":73}");forgetPreferences();
|
||||
check(!VanillaLight.pbr()&&!VanillaLight.ssgi()&&VanillaLight.bloomIntensity()==73,"Explicit personal toggles and intensity survive changed defaults");
|
||||
Files.writeString(path,"{\"bloom\":false}");forgetPreferences();
|
||||
|
||||
@@ -48,7 +48,7 @@ final class PbrTerrain implements AutoCloseable {
|
||||
long frame=mc.level.getGameTime();var active=new ArrayList<Section>();
|
||||
for(var render:mc.levelRenderer.visibleSections()){
|
||||
long key=render.getSectionNode();var pos=render.getRenderOrigin();
|
||||
if(pos.offset(8,8,8).distToCenterSqr(camera)>Math.pow(VanillaLight.pbrDistance()+16,2))continue;
|
||||
if(pos.offset(8,8,8).distToCenterSqr(camera)>Math.pow(VanillaLight.materialDistance()+16,2))continue;
|
||||
var chunk=mc.level.getChunkSource().getChunk(pos.getX()>>4,pos.getZ()>>4,ChunkStatus.FULL,false);
|
||||
if(chunk==null)continue;
|
||||
var storage=chunk.getSection(mc.level.getSectionIndex(pos.getY()));
|
||||
|
||||
@@ -90,8 +90,8 @@ public final class PixelReflections {
|
||||
if(uniform==null)uniform=new MappableRingBuffer(()->"Sanctuary reflection parameters",GpuBuffer.USAGE_UNIFORM|GpuBuffer.USAGE_MAP_WRITE,160);
|
||||
uniform.rotate();try(var map=uniform.currentBuffer().map(false,true)){
|
||||
Std140Builder.intoBuffer(map.data()).putMat4f(vp).putMat4f(new Matrix4f(vp).invert())
|
||||
.putVec4(RenderSystem.getDevice().getDeviceInfo().isZZeroToOne()?1:0,VanillaLight.ssrIntensity()/100f,VanillaLight.pbrIntensity()/100f,VanillaLight.pbrDistance())
|
||||
.putVec4(Math.max(128,VanillaLight.pbrDistance()),32,0,0);
|
||||
.putVec4(RenderSystem.getDevice().getDeviceInfo().isZZeroToOne()?1:0,VanillaLight.ssrIntensity()/100f,VanillaLight.pbrIntensity()/100f,VanillaLight.ssrDistance())
|
||||
.putVec4(Math.max(128,VanillaLight.ssrDistance()),32,VanillaLight.materialDistance(),0);
|
||||
}
|
||||
int max=java.util.stream.Stream.concat(solid.stream(),transparent.stream()).mapToInt(PbrTerrain.Entry::indices).max().orElse(0);
|
||||
RenderSystem.getSequentialBuffer(PrimitiveTopology.QUADS).requestIndexCount(max);
|
||||
|
||||
+6
-3
@@ -29,12 +29,15 @@ public final class ShaderOptionsScreen extends OptionsSubScreen {
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.pbr",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.pbr_help")),VanillaLight.pbr(),VanillaLight::setPbr));
|
||||
slider("pbr_intensity",VanillaLight.pbrIntensity(),VanillaLight::setPbrIntensity);
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.ssr",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.ssr_help")),VanillaLight.ssr(),VanillaLight::setSsr));
|
||||
slider("ssr_intensity",VanillaLight.ssrIntensity(),VanillaLight::setSsrIntensity);
|
||||
list.addBig(new OptionInstance<Integer>("sanctuary.shaders.pbr_distance",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.pbr_distance_help")),(caption,value)->Component.translatable("sanctuary.shaders.pbr_distance_value",value),
|
||||
new OptionInstance.Enum<>(List.of(16,32,64,128,256),Codec.INT),VanillaLight.pbrDistance(),VanillaLight::setPbrDistance));
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.ssr",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.ssr_help")),VanillaLight.ssr(),VanillaLight::setSsr));
|
||||
slider("ssr_intensity",VanillaLight.ssrIntensity(),VanillaLight::setSsrIntensity);
|
||||
list.addBig(new OptionInstance<Integer>("sanctuary.shaders.ssr_distance",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.ssr_distance_help")),(caption,value)->Component.translatable("sanctuary.shaders.ssr_distance_value",value),
|
||||
new OptionInstance.Enum<>(List.of(16,32,64,128,256),Codec.INT),VanillaLight.ssrDistance(),VanillaLight::setSsrDistance));
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.colored_lights",OptionInstance.cachedConstantTooltip(
|
||||
Component.translatable("sanctuary.shaders.colored_lights_help")),VanillaLight.coloredLights(),VanillaLight::setColoredLights));
|
||||
list.addBig(OptionInstance.createBoolean("sanctuary.shaders.warm_torches",OptionInstance.cachedConstantTooltip(
|
||||
|
||||
@@ -29,8 +29,11 @@ public final class VanillaLight {
|
||||
boolean lensFlare=true;
|
||||
int lensFlareIntensity=30;
|
||||
boolean pbr=true;
|
||||
int pbrIntensity=80;
|
||||
int pbrDistance=32;
|
||||
int pbrIntensity=50;
|
||||
int pbrBalanceVersion;
|
||||
int pbrDistance=64;
|
||||
int ssrDistance=64;
|
||||
int reflectionDistanceVersion;
|
||||
boolean ssr=false;
|
||||
int ssrIntensity=20;
|
||||
boolean ssgi=true;
|
||||
@@ -63,7 +66,13 @@ public final class VanillaLight {
|
||||
preferences.sunshaftIntensity=Math.clamp(preferences.sunshaftIntensity,0,100);
|
||||
preferences.lensFlareIntensity=Math.clamp(preferences.lensFlareIntensity,0,100);
|
||||
preferences.ssrIntensity=Math.clamp(preferences.ssrIntensity,0,100);
|
||||
if(preferences.reflectionDistanceVersion<1&&preferences.pbrDistance==32)preferences.pbrDistance=64;
|
||||
preferences.reflectionDistanceVersion=1;
|
||||
preferences.pbrDistance=normalizePbrDistance(preferences.pbrDistance);
|
||||
preferences.ssrDistance=normalizePbrDistance(preferences.ssrDistance);
|
||||
// Migrate the previous 80% baseline once; later explicit 80% choices persist.
|
||||
if(preferences.pbrBalanceVersion<1&&preferences.pbrIntensity==80)preferences.pbrIntensity=50;
|
||||
preferences.pbrBalanceVersion=1;
|
||||
preferences.pbrIntensity=Math.clamp(preferences.pbrIntensity,0,100);
|
||||
preferences.coloredLightIntensity=Math.clamp(preferences.coloredLightIntensity,0,100);
|
||||
preferences.coloredLightDistance=normalizeColoredLightDistance(preferences.coloredLightDistance);
|
||||
@@ -110,6 +119,9 @@ public final class VanillaLight {
|
||||
public static int ssrIntensity(){enabled();return preferences.ssrIntensity;}
|
||||
public static void setSsr(boolean value){enabled();preferences.ssr=value;save();}
|
||||
public static void setSsrIntensity(int value){enabled();preferences.ssrIntensity=Math.clamp(value,0,100);save();}
|
||||
public static int ssrDistance(){enabled();return preferences.ssrDistance;}
|
||||
public static void setSsrDistance(int value){enabled();preferences.ssrDistance=normalizePbrDistance(value);save();}
|
||||
static int materialDistance(){return Math.max(pbrDistance(),ssr()&&ssrIntensity()>0?ssrDistance():0);}
|
||||
public static int pbrDistance(){enabled();return preferences.pbrDistance;}
|
||||
public static void setPbrDistance(int value){enabled();preferences.pbrDistance=normalizePbrDistance(value);save();}
|
||||
static int normalizePbrDistance(int value){return value<24?16:value<48?32:value<96?64:value<192?128:256;}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sanctuary.shaders.ssr_intensity_value": "Reflection strength: %s%%",
|
||||
"sanctuary.shaders.ssr_intensity_help": "Strength of visible landscape reflections on solids and water. Default: 20%.",
|
||||
"sanctuary.shaders.ssr": "Landscape reflections — experimental",
|
||||
"sanctuary.shaders.ssr": "SSR",
|
||||
"sanctuary.shaders.ssr_help": "Colours material texels with the visible landscape. Requires PBR; off-screen objects cannot be reflected.",
|
||||
"sanctuary.shaders.ssr_intensity": "Reflection strength",
|
||||
"sanctuary.graphics.default_vulkan": "Vulkan (default)",
|
||||
@@ -2303,7 +2303,7 @@
|
||||
"sanctuary.shaders.pbr": "PBR · material relief",
|
||||
"sanctuary.shaders.pbr_help": "Experimental: procedural block normals and roughness, sun, moon and local light highlights. Enable Colored lights for local direction. Range 32 blocks. ON at 80% by default.",
|
||||
"sanctuary.shaders.pbr_intensity": "PBR intensity",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Material relief and highlights, including water. Default: 80%.",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Material relief and highlights, including water. Default: 50%.",
|
||||
"sanctuary.shaders.pbr_intensity_value": "PBR intensity: %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.",
|
||||
@@ -2330,10 +2330,13 @@
|
||||
"sanctuary.shaders.water_intensity": "Water intensity",
|
||||
"sanctuary.shaders.water_intensity_help": "At 0%, keeps native rendering. At 100%, applies all three profiles.",
|
||||
"sanctuary.shaders.water_intensity_value": "Water intensity: %s%%",
|
||||
"sanctuary.shaders.pbr_distance": "PBR and SSR distance",
|
||||
"sanctuary.shaders.pbr_distance_value": "PBR and SSR distance: %s blocks",
|
||||
"sanctuary.shaders.pbr_distance_help": "Shared range for relief and reflecting surfaces. 16, 32, 64, 128 or 256 blocks. Longer distances cost more; mesh memory is bounded.",
|
||||
"sanctuary.shaders.pbr_distance": "PBR distance",
|
||||
"sanctuary.shaders.pbr_distance_value": "PBR distance: %s blocks",
|
||||
"sanctuary.shaders.pbr_distance_help": "Independent PBR range: 16, 32, 64, 128 or 256 blocks. Default: 64 blocks. Limited to visible terrain and mesh budget.",
|
||||
"sanctuary.shaders.water_blend": "Water blending",
|
||||
"sanctuary.shaders.water_blend_value": "Water blending: %s × %s blocks",
|
||||
"sanctuary.shaders.water_blend_help": "Transition width between bed-dependent water colours: 1, 3, 5, 9 or 17 blocks. Default: 9 × 9."
|
||||
"sanctuary.shaders.water_blend_help": "Transition width between bed-dependent water colours: 1, 3, 5, 9 or 17 blocks. Default: 9 × 9.",
|
||||
"sanctuary.shaders.ssr_distance": "SSR distance",
|
||||
"sanctuary.shaders.ssr_distance_value": "SSR distance: %s blocks",
|
||||
"sanctuary.shaders.ssr_distance_help": "Independent SSR range: 16, 32, 64, 128 or 256 blocks. Default: 64 blocks. Limited to visible terrain and mesh budget."
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sanctuary.shaders.ssr_intensity_value": "Intensité des reflets : %s %%",
|
||||
"sanctuary.shaders.ssr_intensity_help": "Intensité des reflets du paysage visible, sur les solides et l’eau. Défaut : 20 %.",
|
||||
"sanctuary.shaders.ssr": "Reflets du paysage — expérimental",
|
||||
"sanctuary.shaders.ssr": "SSR",
|
||||
"sanctuary.shaders.ssr_help": "Colore les pixels de matière avec le paysage visible. PBR requis ; les objets hors écran ne sont pas réfléchis.",
|
||||
"sanctuary.shaders.ssr_intensity": "Intensité des reflets",
|
||||
"sanctuary.graphics.default_vulkan": "Vulkan (par défaut)",
|
||||
@@ -2303,7 +2303,7 @@
|
||||
"sanctuary.shaders.pbr": "PBR · relief des matériaux",
|
||||
"sanctuary.shaders.pbr_help": "Expérimental : normales procédurales et rugosité des blocs, reflets du soleil, de la lune et des lumières locales. Activer Lumières colorées pour la direction locale. Portée 32 blocs. Activé par défaut à 80 %.",
|
||||
"sanctuary.shaders.pbr_intensity": "Intensité PBR",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Relief et éclats des matières, eau comprise. Défaut : 80 %.",
|
||||
"sanctuary.shaders.pbr_intensity_help": "Relief et éclats des matières, eau comprise. Défaut : 50 %.",
|
||||
"sanctuary.shaders.pbr_intensity_value": "Intensité 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.",
|
||||
@@ -2330,10 +2330,13 @@
|
||||
"sanctuary.shaders.water_intensity": "Intensité de l’eau",
|
||||
"sanctuary.shaders.water_intensity_help": "À 0 %, conserve le rendu natif. À 100 %, applique les trois profils.",
|
||||
"sanctuary.shaders.water_intensity_value": "Intensité de l’eau: %s%%",
|
||||
"sanctuary.shaders.pbr_distance": "Distance PBR et SSR",
|
||||
"sanctuary.shaders.pbr_distance_value": "Distance PBR et SSR : %s blocs",
|
||||
"sanctuary.shaders.pbr_distance_help": "Portée commune du relief et des surfaces réfléchissantes. 16, 32, 64, 128 ou 256 blocs. Les distances élevées coûtent davantage ; budget de maillage limité.",
|
||||
"sanctuary.shaders.pbr_distance": "Distance PBR",
|
||||
"sanctuary.shaders.pbr_distance_value": "Distance PBR: %s blocs",
|
||||
"sanctuary.shaders.pbr_distance_help": "Portée indépendante du PBR : 16, 32, 64, 128 ou 256 blocs. Défaut : 64 blocs. Limitée au terrain visible et au budget de maillage.",
|
||||
"sanctuary.shaders.water_blend": "Mélange des eaux",
|
||||
"sanctuary.shaders.water_blend_value": "Mélange des eaux : %s × %s blocs",
|
||||
"sanctuary.shaders.water_blend_help": "Étendue de la transition des teintes selon le fond : 1, 3, 5, 9 ou 17 blocs. Défaut : 9 × 9."
|
||||
"sanctuary.shaders.water_blend_help": "Étendue de la transition des teintes selon le fond : 1, 3, 5, 9 ou 17 blocs. Défaut : 9 × 9.",
|
||||
"sanctuary.shaders.ssr_distance": "Distance SSR",
|
||||
"sanctuary.shaders.ssr_distance_value": "Distance SSR: %s blocs",
|
||||
"sanctuary.shaders.ssr_distance_help": "Portée indépendante du SSR : 16, 32, 64, 128 ou 256 blocs. Défaut : 64 blocs. Limitée au terrain visible et au budget de maillage."
|
||||
}
|
||||
|
||||
@@ -128,10 +128,10 @@ void main(){
|
||||
// A broad solar lobe gives water an extended glitter path at grazing angles.
|
||||
// Local lamps retain the material's original narrow lobe.
|
||||
vec4 solarMaterial=material;
|
||||
solarMaterial.b=max(material.b,family>1.5?.34:.24);
|
||||
solarMaterial.b=max(material.b,family>1.5?.42:.24);
|
||||
vec3 specular=localShine(n,v,l,solarMaterial,albedo);
|
||||
// PbrEnvironment.z identifies sunlight: moonlight keeps its modest base radiance.
|
||||
float solarRadiance=mix(1.0,family>1.5?20.0:4.0,PbrEnvironment.z);
|
||||
float solarRadiance=mix(1.0,family>1.5?6.0:4.0,PbrEnvironment.z);
|
||||
float fog=max(clamp((max(length(relativePosition.xz),abs(relativePosition.y))-PbrFog.x)/max(PbrFog.y-PbrFog.x,.001),0.0,1.0),
|
||||
clamp((length(relativePosition)-PbrFog.z)/max(PbrFog.w-PbrFog.z,.001),0.0,1.0));
|
||||
float amount=PbrSun.w*pow(tint.a,8.0)*visibility(relativePosition,baseNormal)*(1.0-fog*PbrEnvironment.x)
|
||||
@@ -148,8 +148,20 @@ void main(){
|
||||
lit=clamp(lit*(1.0+localRelief*localAmount),0.0,1.0);
|
||||
}
|
||||
// Preserve bright solar highlights instead of capping them at a medium grey.
|
||||
vec3 shine=min((specular*amount*solarRadiance+localShine(n,v,arrival.xyz,material,albedo)*localAmount)*intensity*5.0,vec3(8.0));
|
||||
lit+=(1.0-lit)*(1.0-exp(-shine));
|
||||
// Fully matte foliage/fibres receive normal relief, not a broad white specular veil.
|
||||
// Stone/wood (roughness <= .88), polished surfaces, metals and water are unchanged.
|
||||
float fullyMatte=smoothstep(.9,.98,material.b)*(1.0-material.a);
|
||||
float shineWeight=family<.5?1.0-fullyMatte:1.0;
|
||||
vec3 skyShine=min(specular*amount*solarRadiance*intensity*5.0*shineWeight,vec3(8.0));
|
||||
vec3 lampShine=min(localShine(n,v,arrival.xyz,material,albedo)*localAmount*intensity*5.0*shineWeight,vec3(8.0));
|
||||
if(family>1.5&&PbrEnvironment.z>.5){
|
||||
// Soft-light/screen blend per native texel: broad daylight lifts the water
|
||||
// without replacing its colour and detail with a saturated white cone.
|
||||
vec3 weight=skyShine/(1.0+skyShine);
|
||||
vec3 highlight=mix(vec3(1.0),sqrt(lit),.55);
|
||||
lit=mix(lit,highlight,weight);
|
||||
}else lit+=(1.0-lit)*(1.0-exp(-skyShine));
|
||||
lit+=(1.0-lit)*(1.0-exp(-lampShine));
|
||||
if(any(isnan(lit))||any(isinf(lit)))discard;
|
||||
fragColor=vec4(sqrt(clamp(lit,0.0,1.0)),1.0);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ layout(location=2) in vec2 maskUv;
|
||||
layout(location=3) in vec4 tint;
|
||||
void main(){
|
||||
vec2 dx=dFdx(blockUv),dy=dFdy(blockUv);
|
||||
if(length(relativePosition)>=ReflectionParams.w)discard;
|
||||
if(length(relativePosition)>=ReflectionLimits.z)discard;
|
||||
// Minecraft's world projection uses reverse depth: zero is the far plane.
|
||||
float opaque=texelFetch(OpaqueDepth,ivec2(gl_FragCoord.xy),0).r;
|
||||
// Native and material transforms differ slightly in evaluation order. A fixed
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name = "Sanctuary"
|
||||
author = "KOKA99CAB"
|
||||
version = "beta.147"
|
||||
version = "beta.149"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
|
||||
Reference in New Issue
Block a user