Compare commits

..

25 Commits

Author SHA1 Message Date
63aa7aa104 Commit vor Änderung Umstellung auf eine einzelne Animation 2026-06-28 22:59:36 +02:00
6d061cd621 Sicherstellen des Zustands der passt 2026-06-28 21:31:00 +02:00
cd350a92fa Bank-Sitz: blockingAnimRemaining +1Frame, applyMotionKfOffset als Lerp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 15:11:44 +02:00
b44d583dc3 Bank-Sitz-Fix: clearKfOffset-Timing, Approach-Distanz, Animationsübergänge
- clearKfOffset() erst nach get_up-Animation (Callback) statt sofort beim Start
  → kein Slide des Visuals während der Aufsteh-Animation
- Approach-Distanz zur Bank um 17.5cm verkürzt (läuft näher ran, sitzt tiefer)
- blockingAnimRemaining um 1 Frame (1/60s) gekürzt → verhindert Extra-Keyframe-Hold
  am Animationsende (noch zu beobachten)
- Diverses aus vorheriger Session: AnimSet-Editor, Navigation, Assets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:51:11 +02:00
ba0b80f524 Navigation, Bank-Setzen und AnimSet-Editor Keyframes
- CharacterNavigator: universelle Pfad-Navigation für Spieler und NPCs
  (PathFinder + Terrain-Slope-Check + Stuck-Erkennung, Walk/Run)
- PlayerInputControl: navigateTo/stopNavigation-API, Navigator hat Vorrang
  vor WASD; setNavigationSources für PathFinder + TerrainChunkState
- WorldInteractableState: Bank-Setzen komplett neu (< 5m, E-Taste),
  Navigator läuft zum Sitzpunkt, dreht Rücken zur Bank, spielt
  sit_down_bench / sitting / get_up_sitting; Bett weiterhin mit Rücklauf
- AnimSet-Editor: Kamera startet mit -45° Pitch; AnimKeyframe-Offset-Editor
- WorldScene: PathFinder + ObstacleRoot an PlayerInputControl übergeben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 18:18:58 +02:00
79f9cf12a3 Animationen jetzt heil und Keyframes eingebaut 2026-06-23 17:44:22 +02:00
914bf6e673 Zwischenstand - animationen passen weitesgehend 2026-06-22 22:36:44 +02:00
b3b943e588 Charakter-Liegend-Fix: T-Pose im Editor, CullHint im Spiel, Strip in src+bin
Editor (AnimPreviewState):
- __tpose__ AnimClip mit Einzel-Frame-Track für Root-Joints (behebt NPE in
  ClipAction.doInterpolate; leerer Clip hatte null-tracks-Array)
- Beim Laden: eingebettete Clips automatisch strippt und in src+bin speichern;
  danach __tpose__ abspielen → Charakter steht in Bind-Pose
- stopAll(): zurück zur T-Pose statt SkinningControl deaktivieren
- Achsen-Indikator immer fest auf (0,0,0) statt bounding-box-Mitte

Spiel (WorldScene):
- CullHint.Always beim Laden, Inherit nach Animation-Setup (kein liegender Charakter)
- stripEmbeddedClips: speichert jetzt in src + bin + build (alle bekannten Pfade);
  besseres Logging bei fehlendem Pfad

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 22:25:23 +02:00
d3c6e8ed77 Zwischenstand: CullHint-Workaround gegen liegenden Charakter + stripEmbeddedClips-Fix
- WorldScene: Charakter wird beim Laden mit CullHint.Always versteckt, erst nach
  setupAnimationContext (idle läuft) wieder sichtbar
- WorldScene: stripEmbeddedClips nutzt jetzt AnimationLibrary.findAssetRoot() statt
  hartkodierter Pfad-Liste; besseres Logging wenn Datei nicht gefunden
- AnimPreviewState: Modell beim Laden versteckt (CullHint.Always), erst bei playClip
  sichtbar; stopAll versteckt Modell wieder
- PlayerInputControl: tryPlay setzt Action VOR SkinningControl-Aktivierung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 22:03:48 +02:00
7a3b2b8733 snapRootBoneXZ: Achsen-Fix für Mixamo-Hips (X=0, Y=0/frei, Z=frei)
In diesen Mixamo-Exporten ist Local-Y die Vorwärts-Richtung (nicht Höhe),
Local-Z die Höhe. Bisheriger Code fror Z=0 ein → Charakter 1m zu tief.
Und Y war frei → Lauf-Drift blieb.

Neue Logik:
  X → 0 (kein Seiten-Drift)
  Y → 0 für Lauf-Clips (running/walking/sprinting/running_jump), normalisiert sonst
  Z → vollständig frei (Höhe und Setz/Aufsteh-Bewegung erhalten)

Nur der flachste Bone (Hips) wird modifiziert, alle anderen unberührt.
Clips vollständig neu importiert mit korrektem Snap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 18:28:51 +02:00
e669e29096 Zwischenstand 2026-06-21 23:04:40 +02:00
52c1fb1fe8 Revert Variante B – zurück zu snapRootBoneXZ mit frame0-XZ
RootDriftCompensatorControl entfernt, AnimationLibrary auf Stand 7dcf16f
zurückgesetzt (snapRootBoneXZ friert XZ auf frame0-Wert ein, Early-Return
bleibt, kein Clip-Clearing in applyAllTo).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 23:01:29 +02:00
197a820ef9 Option B: RootDriftCompensatorControl verhindert Mesh-Drift ohne Animation zu verändern
Neues Control auf dem Modell-Spatial (nach AnimComposer hinzugefügt):
- Läuft nach AnimComposer aber vor SkinningControl → liest aktuellen Frame
- Findet den flachsten Knochen mit nicht-nullem Model-Space XZ (= Hüft-Bone)
- Verschiebt den Modell-Spatial in die entgegengesetzte Richtung
- Mesh bleibt immer über der Physik-Kapsel; Y (sit_down/Jump) wird nicht berührt
- Animations-Daten, J3Os und AnimationLibrary bleiben unverändert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 11:35:12 +02:00
7dcf16fddf snapRootBoneXZ: flachsten Joint mit Translations snappen statt nur Tiefe-0
Rigs wo Hips auf Tiefe 1 liegt (Kind des Root) wurden bisher nicht gesnappt
weil nur Tiefe-0-Joints gefunden wurden. Jetzt wird die kleinste Tiefe unter
allen Joints mit Translation-Track gesucht und nur diese Ebene eingefroren.
Passt zu beiden Rig-Strukturen (Root-Translation und Hips-Translation).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 10:09:27 +02:00
71ba297657 Root-Bone XZ in-memory einfrieren beim Clip-Apply (kein Drift mehr ingame)
Beim Anwenden eines Clips auf ein Modell (AnimationLibrary.applyTo) wird der
Root-Joint-Track jetzt in-memory gepatcht: X und Z werden auf Frame-0-Wert
eingefroren, Y (Höhenachse) bleibt vollständig frei. Damit bleibt das Mesh
immer über der Physik-Kapsel, sit_down/Jump/Bounce laufen korrekt weiter.
J3O-Dateien werden nicht verändert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 10:01:37 +02:00
07a4c6a323 Animations neu importiert, SLF4J-Format-Bugs gefixt, stripRootXZ als tote Methode für später
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 09:58:15 +02:00
c8f1dd9432 Animations-Import, Massenimport-Queue, Asset-Archivierung, Voxel-Refactor
- Animations-Import: GLB wird direkt vom Ursprungspfad geladen (kein Zwischenkopieren), J3O in clips/ gespeichert
- RetargetingSystem: Translations-Tracks im Full-Retarget-Pfad erhalten (Hips-Y für sit_down)
- AnimationLibrary: lädt nur J3O, Clip-Name wird bei applyTo() auf Library-Key umbenannt
- SharedInput: animPreviewAddAnimPath → ConcurrentLinkedQueue animImportQueue (Massenimport-Fix)
- EditorApp: archiveOriginal() archiviert Originaldateien nach assets/imported/<assettyp>/
- EditorApp: Animations-Unterknoten im Asset-Baum zeigen enthaltene Clip-Namen
- Neue Animations-Clips: sit_down, get_up_sitting, sitting, pickup, sprinting u.a.
- Voxel: VoxelChunkState entfernt, VoxelChunkNode/MarchingCubes überarbeitet
- Map: Voxel-Chunks bereinigt, Terrain-Chunks aktualisiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 20:52:04 +02:00
a369647e9c Weiter gearbeitet 2026-06-16 07:03:08 +02:00
a80269e681 Commit vor Voxel Update für die Klippen 2026-06-11 21:52:00 +02:00
fe5dfc19b1 Commit vor dem Einfügen von Gebierge über Voxels 2026-06-10 12:56:29 +02:00
edb9cfc946 Weiter gebastelt 2026-06-09 19:25:30 +02:00
5e85051716 Weiter am Editor gearbeitet, unter anderem LOD System, Items, Trees, Modelle 2026-06-08 22:25:47 +02:00
1297869dfa Commit vor großem Terrain refactoring 2026-06-08 08:42:45 +02:00
7faed35287 Einmal den Fortschritt mit dem Wasser sichern 2026-06-06 09:05:25 +02:00
d56f2ea41f Weiter gearbeitet 2026-06-04 22:40:17 +02:00
1587 changed files with 37977 additions and 2618 deletions

6
.gitignore vendored
View File

@@ -16,3 +16,9 @@ bin/
# Lokale Downloads (nicht ins Repo) # Lokale Downloads (nicht ins Repo)
downloads/ downloads/
# Ingame-Karten-Sessions (vom Editor beim Spielstart erzeugt)
run/
# Spielstände
saves/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -1,13 +1,14 @@
MaterialDef TreeLeaf { MaterialDef Fern {
MaterialParameters { MaterialParameters {
Color Diffuse (Color) : 0.18 0.60 0.10 1.0 Color Diffuse (Color) : 0.18 0.60 0.10 1.0
Float WindStrength : 0.30 Float WindStrength : 0.15
Float WindSpeed : 0.7 Float WindSpeed : 0.6
Texture2D LeafMap Texture2D DiffuseMap
Boolean HasLeafMap : false Boolean HasDiffuseMap : false
Texture2D NormalMap -LINEAR
Boolean HasNormalMap : false
// Vom Shadow-Renderer befüllt (PostShadow-Pass) — vollständige Liste aus PostShadow.j3md
Int BoundDrawBuffer Int BoundDrawBuffer
Int FilterMode Int FilterMode
Boolean HardwareShadows Boolean HardwareShadows
@@ -15,8 +16,6 @@ MaterialDef TreeLeaf {
Texture2D ShadowMap1 Texture2D ShadowMap1
Texture2D ShadowMap2 Texture2D ShadowMap2
Texture2D ShadowMap3 Texture2D ShadowMap3
Texture2D ShadowMap4
Texture2D ShadowMap5
Float ShadowIntensity : 1.0 Float ShadowIntensity : 1.0
Vector4 Splits Vector4 Splits
Vector2 FadeInfo Vector2 FadeInfo
@@ -24,18 +23,15 @@ MaterialDef TreeLeaf {
Matrix4 LightViewProjectionMatrix1 Matrix4 LightViewProjectionMatrix1
Matrix4 LightViewProjectionMatrix2 Matrix4 LightViewProjectionMatrix2
Matrix4 LightViewProjectionMatrix3 Matrix4 LightViewProjectionMatrix3
Matrix4 LightViewProjectionMatrix4
Matrix4 LightViewProjectionMatrix5
Vector3 LightPos
Vector3 LightDir Vector3 LightDir
Float PCFEdge Float PCFEdge
Float ShadowMapSize Float ShadowMapSize
Boolean BackfaceShadows : false Boolean BackfaceShadows : false
} }
Technique { Technique {
VertexShader GLSL150 : Shaders/Tree.vert VertexShader GLSL150 : Shaders/Fern.vert
FragmentShader GLSL150 : Shaders/TreeLeaf.frag FragmentShader GLSL150 : Shaders/Fern.frag
WorldParameters { WorldParameters {
WorldViewProjectionMatrix WorldViewProjectionMatrix
@@ -48,22 +44,6 @@ MaterialDef TreeLeaf {
} }
} }
Technique PostShadow {
VertexShader GLSL150 : Shaders/LeafPostShadow.vert
FragmentShader GLSL150 : Shaders/LeafPostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
ForcedRenderState {
Blend Modulate
FaceCull Off
DepthWrite Off
}
}
Technique PreShadow { Technique PreShadow {
VertexShader GLSL150 : Shaders/LeafPreShadow.vert VertexShader GLSL150 : Shaders/LeafPreShadow.vert
FragmentShader GLSL150 : Shaders/LeafPreShadow.frag FragmentShader GLSL150 : Shaders/LeafPreShadow.frag
@@ -80,4 +60,20 @@ MaterialDef TreeLeaf {
ColorWrite Off ColorWrite Off
} }
} }
Technique PostShadow {
VertexShader GLSL150 : Shaders/LeafPostShadow.vert
FragmentShader GLSL150 : Shaders/LeafPostShadow.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
ForcedRenderState {
Blend Modulate
FaceCull Off
DepthWrite Off
}
}
} }

View File

@@ -0,0 +1,25 @@
MaterialDef Flowing Water {
MaterialParameters {
Texture2D NormalMap
Texture2D FoamMap
Texture2D DiffuseMap
Color Tint
Float UVScale : 6.0
Float NormalUVScale : 0.5
Float Time : 0.0
Float FlowSpeed : 1.0
Float FoamAmount : 0.0
}
Technique {
VertexShader GLSL150: Shaders/FlowingWater.vert
FragmentShader GLSL150: Shaders/FlowingWater.frag
WorldParameters {
WorldViewProjectionMatrix
}
Defines {
HAS_NORMALMAP : NormalMap
HAS_FOAMMAP : FoamMap
HAS_DIFFUSEMAP : DiffuseMap
}
}
}

View File

@@ -3,8 +3,11 @@ MaterialDef Grass {
MaterialParameters { MaterialParameters {
Color Color (Color) : 1.0 1.0 1.0 1.0 Color Color (Color) : 1.0 1.0 1.0 1.0
Texture2D ColorMap Texture2D ColorMap
Texture2D NormalMap
Float WindSpeed : 0.5 Float WindSpeed : 0.5
Float WindStrength : 0.12 Float WindStrength : 0.12
Vector3 SunDir : 0.55 0.80 0.35
Color SunColor : 1.0 1.0 0.95 1.0
} }
Technique { Technique {
@@ -15,6 +18,7 @@ MaterialDef Grass {
WorldViewProjectionMatrix WorldViewProjectionMatrix
WorldMatrix WorldMatrix
Time Time
AmbientLightColor
} }
RenderState { RenderState {
@@ -22,7 +26,8 @@ MaterialDef Grass {
} }
Defines { Defines {
HAS_COLORMAP : ColorMap HAS_COLORMAP : ColorMap
HAS_NORMALMAP : NormalMap
} }
} }
} }

View File

@@ -0,0 +1,25 @@
MaterialDef GrassVertex {
MaterialParameters {
Float WindSpeed : 1.0
Float WindStrength : 0.15
Vector3 SunDir : 0.35 0.8 0.45
Color SunColor : 0.95 0.90 0.75 1.0
}
Technique {
VertexShader GLSL150: Shaders/GrassVertex.vert
FragmentShader GLSL150: Shaders/GrassVertex.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
Time
AmbientLightColor
}
RenderState {
FaceCull Off
}
}
}

View File

@@ -0,0 +1,40 @@
MaterialDef TerrainArray {
MaterialParameters {
TextureArray DiffuseArray
FloatArray DiffuseScales
TextureArray NormalArray
Float Shininess : 32.0
Vector3 LightDir
Vector3 SunColor
Vector3 AmbientColor
Boolean DebugNoLight
Boolean DebugSlot0Only
Texture2D DebugDirectTex
Texture2D AlphaMap
Texture2D AlphaMap_1
Texture2D AlphaMap_2
}
Technique {
VertexShader GLSL150 : Shaders/TerrainArray.vert
FragmentShader GLSL150 : Shaders/TerrainArray.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
ViewProjectionMatrix
}
Defines {
HAS_NORMAL_ARRAY : NormalArray
HAS_ALPHA_1 : AlphaMap_1
HAS_ALPHA_2 : AlphaMap_2
HAS_LIGHTDIR : LightDir
HAS_SCENE_LIGHT : SunColor
DEBUG_NO_LIGHT : DebugNoLight
DEBUG_SLOT0_ONLY : DebugSlot0Only
DEBUG_DIRECT_TEX : DebugDirectTex
}
}
}

View File

@@ -0,0 +1,19 @@
MaterialDef Topology {
MaterialParameters {
Float Interval : 10.0
Float LineWidth : 0.12
Float Opacity : 0.55
}
Technique {
VertexShader GLSL150: Shaders/Topology.vert
FragmentShader GLSL150: Shaders/Topology.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
RenderState {
Blend Alpha
DepthWrite Off
}
}
}

View File

@@ -6,6 +6,9 @@ MaterialDef Tree {
Float WindSpeed : 0.5 Float WindSpeed : 0.5
Texture2D BarkMap Texture2D BarkMap
Boolean HasBarkMap : false Boolean HasBarkMap : false
Vector3 LightDir
Vector3 SunColor
Vector3 AmbientColor
} }
Technique { Technique {
@@ -17,5 +20,9 @@ MaterialDef Tree {
WorldMatrix WorldMatrix
Time Time
} }
Defines {
HAS_SCENE_LIGHT : SunColor
}
} }
} }

View File

@@ -28,6 +28,8 @@ MaterialDef TreeLeaf {
Matrix4 LightViewProjectionMatrix5 Matrix4 LightViewProjectionMatrix5
Vector3 LightPos Vector3 LightPos
Vector3 LightDir Vector3 LightDir
Vector3 SunColor
Vector3 AmbientColor
Float PCFEdge Float PCFEdge
Float ShadowMapSize Float ShadowMapSize
Boolean BackfaceShadows : false Boolean BackfaceShadows : false
@@ -46,6 +48,10 @@ MaterialDef TreeLeaf {
RenderState { RenderState {
FaceCull Off FaceCull Off
} }
Defines {
HAS_SCENE_LIGHT : SunColor
}
} }
Technique PostShadow { Technique PostShadow {

View File

@@ -0,0 +1,69 @@
MaterialDef Voxel {
MaterialParameters {
Texture2D TexFlat
Texture2D TexSteep
Texture2D NormalMapFlat
Texture2D NormalMapSteep
Texture2D DisplacementMapFlat
Texture2D DisplacementMapSteep
Float TexScale : 8.0
Float DisplacementScale : 0.3
Float TessellationLevel : 4.0
Vector3 LightDir
Vector3 SunColor
Vector3 AmbientColor
Boolean DebugNoLight
}
Technique {
VertexShader GLSL150 : Shaders/Voxel.vert
FragmentShader GLSL150 : Shaders/Voxel.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
Defines {
HAS_NM_FLAT : NormalMapFlat
HAS_NM_STEEP : NormalMapSteep
HAS_LIGHTDIR : LightDir
HAS_SCENE_LIGHT : SunColor
DEBUG_NO_LIGHT : DebugNoLight
}
RenderState {
FaceCull Off
}
}
Technique Tessellation {
VertexShader GLSL400 : Shaders/VoxelTess.vert
TessellationControlShader GLSL400 : Shaders/Voxel.tsctrl
TessellationEvaluationShader GLSL400 : Shaders/Voxel.tseval
FragmentShader GLSL400 : Shaders/Voxel.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
ViewProjectionMatrix
CameraPosition
}
Defines {
HAS_NM_FLAT : NormalMapFlat
HAS_NM_STEEP : NormalMapSteep
HAS_DISP_FLAT : DisplacementMapFlat
HAS_DISP_STEEP : DisplacementMapSteep
HAS_LIGHTDIR : LightDir
HAS_SCENE_LIGHT : SunColor
}
RenderState {
FaceCull Off
}
}
}

View File

@@ -0,0 +1,80 @@
MaterialDef Advanced Water Polygon {
MaterialParameters {
Int BoundDrawBuffer
Int NumSamples
Int NumSamplesDepth
Texture2D FoamMap
Texture2D CausticsMap
Texture2D NormalMap -LINEAR
Texture2D ReflectionMap
Texture2D HeightMap -LINEAR
Texture2D Texture
Texture2D DepthTexture
Vector3 CameraPosition
Float Time
Vector3 frustumCorner
Matrix4 TextureProjMatrix
Float WaterHeight
Vector3 LightDir
Float WaterTransparency
Float NormalScale
Float R0
Float MaxAmplitude
Color LightColor
Float ShoreHardness
Float FoamHardness
Float RefractionStrength
Float WaveScale
Vector3 FoamExistence
Float SunScale
Vector3 ColorExtinction
Float Shininess
Color WaterColor
Color DeepWaterColor
Vector2 WindDirection
Float ReflectionDisplace
Float FoamIntensity
Float CausticsIntensity
Float UnderWaterFogDistance
Boolean UseRipples
Boolean UseHQShoreline
Boolean UseSpecular
Boolean UseFoam
Boolean UseCaustics
Boolean UseRefraction
Float Radius
Vector3 Center
Boolean SquareArea
Vector2Array Points
Int NumPoints : 0
}
Technique {
VertexShader GLSL310 GLSL300 GLSL150 GLSL120 : Common/MatDefs/Post/Post.vert
FragmentShader GLSL310 GLSL300 GLSL150 GLSL120 : Shaders/WaterPolygon.frag
WorldParameters {
ViewProjectionMatrixInverse
}
Defines {
BOUND_DRAW_BUFFER: BoundDrawBuffer
RESOLVE_MS : NumSamples
RESOLVE_DEPTH_MS : NumSamplesDepth
ENABLE_RIPPLES : UseRipples
ENABLE_HQ_SHORELINE : UseHQShoreline
ENABLE_SPECULAR : UseSpecular
ENABLE_FOAM : UseFoam
ENABLE_CAUSTICS : UseCaustics
ENABLE_REFRACTION : UseRefraction
ENABLE_AREA : Center
SQUARE_AREA : SquareArea
POLYGON_AREA : Points
}
}
}

View File

@@ -1,24 +0,0 @@
# Blender 4.0.2 MTL File: 'Campfire.blend'
# www.blender.org
newmtl Campfire_MAT
Ka 0.500000 0.500000 0.500000
Ks 0.222727 0.222727 0.222727
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 3
map_Kd Campfire_MAT_BaseColor_01.jpg
map_Ns Campfire_MAT_Roughness.jpg
map_refl Campfire_MAT_Metallic.jpg
map_Bump -bm 1.000000 Campfire_MAT_Normal_JL.jpg
newmtl Campfire_fire_MAT
Ns 1000.000000
Ka 0.500000 0.500000 0.500000
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
illum 3
map_Kd Campfire_fire_MAT_BaseColor_Alpha.png
map_d Campfire_fire_MAT_BaseColor_Alpha.png

View File

@@ -0,0 +1,23 @@
#Thu Jun 18 17:47:21 CEST 2026
attachedEmitters.count=0
attachedLight.0=0.00000|0.10000|0.00000|0.80000|1.00000|0.80000|12.00000|50.00000
attachedLights.count=1
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=Höhlenkristall1
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=1.0
scaleY=1.0
scaleZ=1.0
solid=true
tags=
uniformScale=true

View File

@@ -0,0 +1,27 @@
#Sat Jun 20 13:06:13 CEST 2026
attachedEmitters.count=0
attachedLights.count=0
castShadow=true
category=
cullDistance=120.0
interactableOffsetX=0.0
interactableOffsetY=0.6
interactableOffsetZ=0.0
interactableRotY=1.5707964
interactableType=BENCH
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=bank
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=1.0
scaleY=1.0
scaleZ=1.0
solid=true
tags=
uniformScale=true

View File

@@ -0,0 +1,27 @@
#Sat Jun 20 14:30:44 CEST 2026
attachedEmitters.count=0
attachedLights.count=0
castShadow=true
category=
cullDistance=120.0
interactableOffsetX=0.0
interactableOffsetY=0.5
interactableOffsetZ=0.0
interactableRotY=1.5707964
interactableType=BENCH
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=bank1
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=1.0
scaleY=1.0
scaleZ=1.0
solid=false
tags=
uniformScale=true

View File

@@ -1 +0,0 @@
{"IDLE":"stand_up"}

View File

@@ -0,0 +1,20 @@
#Mon Jun 08 22:18:33 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=kaktusfeige
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=2.5
scaleY=2.5
scaleZ=2.5
solid=true
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 10:41:26 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=blutagave
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.3
scaleY=0.3
scaleZ=0.3
solid=false
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 09:59:57 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=erzmoss
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.33
scaleY=0.33
scaleZ=0.33
solid=false
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 10:38:00 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=geisterfarn
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.3
scaleY=0.3
scaleZ=0.3
solid=true
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 10:42:24 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=quelllilie
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.3
scaleY=0.3
scaleZ=0.3
solid=false
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 10:39:27 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=sonnenherz
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.3
scaleY=0.3
scaleZ=0.3
solid=false
tags=
uniformScale=true

View File

@@ -0,0 +1,20 @@
#Tue Jun 09 10:40:05 CEST 2026
castShadow=true
category=
cullDistance=120.0
lod1Distance=30.0
lod1Path=
lod2Distance=80.0
lod2Path=
name=windschiff
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.3
scaleY=0.3
scaleZ=0.3
solid=false
tags=
uniformScale=true

View File

@@ -0,0 +1,42 @@
#import "Common/ShaderLib/GLSLCompat.glsllib"
uniform vec4 m_Diffuse;
uniform sampler2D m_DiffuseMap;
uniform bool m_HasDiffuseMap;
uniform sampler2D m_NormalMap;
uniform bool m_HasNormalMap;
in vec2 texCoord;
in vec3 vNormal;
in vec3 vTangent;
in float vHandedness;
void main() {
vec3 baseColor;
if (m_HasDiffuseMap) {
vec4 tex = texture2D(m_DiffuseMap, texCoord);
if (tex.a < 0.5) discard;
baseColor = tex.rgb * m_Diffuse.rgb;
} else {
vec2 uv = texCoord * 2.0 - 1.0;
if (dot(uv, uv) > 0.95) discard;
baseColor = m_Diffuse.rgb;
}
vec3 N = normalize(vNormal);
if (m_HasNormalMap) {
vec3 T = normalize(vTangent);
vec3 B = normalize(cross(N, T) * vHandedness);
mat3 TBN = mat3(T, B, N);
vec3 nm = texture2D(m_NormalMap, texCoord).rgb * 2.0 - 1.0;
N = normalize(TBN * nm);
}
vec3 sun = normalize(vec3(0.4, 1.0, 0.3));
float diff = max(0.0, dot(N, sun));
// two-sided: underside receives half brightness
diff = max(diff, max(0.0, dot(-N, sun)) * 0.5);
float lit = 0.45 + diff * 0.55;
gl_FragColor = vec4(baseColor * lit, 1.0);
}

View File

@@ -0,0 +1,34 @@
#import "Common/ShaderLib/GLSLCompat.glsllib"
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldMatrix;
uniform float g_Time;
uniform float m_WindStrength;
uniform float m_WindSpeed;
in vec3 inPosition;
in vec3 inNormal;
in vec2 inTexCoord;
in vec4 inColor; // R = wind weight (0=base, 1=tip)
in vec4 inTangent; // xyz=tangent, w=handedness
out vec2 texCoord;
out vec3 vNormal;
out vec3 vTangent;
out float vHandedness;
void main() {
float windW = inColor.r;
float t = g_Time * m_WindSpeed;
vec4 wp = g_WorldMatrix * vec4(inPosition, 1.0);
float phase = wp.x * 0.08 + wp.z * 0.06;
float swayX = sin(t + phase) * windW * m_WindStrength;
float swayZ = cos(t*0.73 + phase) * windW * m_WindStrength * 0.55;
vec3 anim = inPosition + vec3(swayX, 0.0, swayZ);
gl_Position = g_WorldViewProjectionMatrix * vec4(anim, 1.0);
texCoord = inTexCoord;
vNormal = normalize((g_WorldMatrix * vec4(inNormal, 0.0)).xyz);
vTangent = normalize((g_WorldMatrix * vec4(inTangent.xyz, 0.0)).xyz);
vHandedness = inTangent.w;
}

View File

@@ -0,0 +1,85 @@
#ifdef HAS_NORMALMAP
uniform sampler2D m_NormalMap;
#endif
#ifdef HAS_FOAMMAP
uniform sampler2D m_FoamMap;
#endif
#ifdef HAS_DIFFUSEMAP
uniform sampler2D m_DiffuseMap;
#endif
uniform vec4 m_Tint;
uniform float m_FoamAmount;
in vec2 vUV;
in vec2 vTex1;
in vec2 vTex2;
out vec4 outFragColor;
void main() {
// ── Randabstand: 0 = Mitte, 1 = Rand ─────────────────────────────────────
float edgeDist = abs(vUV.x * 2.0 - 1.0);
// ── Tiefengradient ────────────────────────────────────────────────────────
// Ränder heller/transparenter (flaches Ufer), Mitte dunkler (tief)
vec3 baseColor = m_Tint.rgb * (1.0 - edgeDist * 0.45);
float baseAlpha = m_Tint.a * smoothstep(0.0, 0.18, 1.0 - edgeDist);
// ── Dual-Layer Normal-Map: Specular + Wellenhelligkeit ────────────────────
float specular = 0.0;
float ripple = 0.0;
#ifdef HAS_NORMALMAP
vec3 raw1 = texture(m_NormalMap, vTex1).rgb * 2.0 - 1.0;
vec3 raw2 = texture(m_NormalMap, vTex2).rgb * 2.0 - 1.0;
// Tangent-Space → World-Space für horizontales Mesh (T=X, B=Z, N=Y):
// raw.xyz = (tangent-X, tangent-Y, depth) → world = (raw.x, raw.z, raw.y)
vec3 n1 = normalize(vec3(raw1.x, raw1.z, raw1.y));
vec3 n2 = normalize(vec3(raw2.x, raw2.z, raw2.y));
vec3 n = normalize(n1 + n2);
vec3 sunDir = normalize(vec3(0.5, 1.0, 0.3));
specular = pow(max(0.0, dot(n, sunDir)), 8.0);
// Ripple: Bereiche mit starker Oberflächenneigung (Wellenkämme) heller
ripple = (abs(n.x) + abs(n.z)) * 0.30;
#endif
// ── Schaum ────────────────────────────────────────────────────────────────
// Uferschaum wird stärker je näher am Rand; Wasserfälle extra
float foamEdge = smoothstep(0.55, 1.0, edgeDist);
float foamMask = clamp(foamEdge + m_FoamAmount * 0.75, 0.0, 1.0);
#ifdef HAS_FOAMMAP
float foamSample = texture(m_FoamMap, vTex1 * 0.4).r;
foamMask *= foamSample;
#else
// Prozeduraler Fallback wenn keine Schaumtextur geladen
float procFoam = (sin(vTex1.x * 6.283) * 0.5 + 0.5)
* (sin(vTex1.y * 3.141) * 0.5 + 0.5);
foamMask *= procFoam;
#endif
// ── Zusammenführen ────────────────────────────────────────────────────────
// specular-Anteil erhöht (0.55→0.75) damit Glanzlichter deutlich sichtbar sind
vec3 waterColor = baseColor + ripple + vec3(0.55, 0.65, 0.75) * specular;
vec3 finalColor = mix(waterColor, vec3(1.0), foamMask);
float finalAlpha = max(baseAlpha, foamMask * 0.9);
// ── Diffuse-Map: Fluss = Farbmodulation in Fließrichtung, Wasserfall = Gischt ──
#ifdef HAS_DIFFUSEMAP
float d1 = texture(m_DiffuseMap, vTex1 * 0.55).r;
float d2 = texture(m_DiffuseMap, vTex2 * 0.40).r;
float diffuseBlend = max(d1, d2 * 0.6);
// Fluss (FoamAmount=0): Textur moduliert die Wasserfarbe (dunkle/helle Strömungsmuster)
float riverMod = (diffuseBlend - 0.5) * 0.4 * (1.0 - m_FoamAmount);
finalColor = clamp(finalColor + riverMod, 0.0, 1.0);
// Wasserfall (FoamAmount>0): weiße Gischt-Überlagerung
float foamStr = diffuseBlend * m_FoamAmount * 0.85;
finalColor = mix(finalColor, vec3(1.0), foamStr);
finalAlpha = max(finalAlpha, foamStr * 0.9);
#endif
outFragColor = vec4(clamp(finalColor, 0.0, 1.0), finalAlpha);
}

View File

@@ -0,0 +1,23 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform float m_Time;
uniform float m_UVScale;
uniform float m_NormalUVScale;
uniform float m_FlowSpeed;
in vec3 inPosition;
in vec2 inTexCoord;
out vec2 vUV; // raw [0..1] UV für Tiefe / Rand-Logik
out vec2 vTex1; // scrollende Normal-Map-UV (flussabwärts)
out vec2 vTex2; // scrollende Normal-Map-UV (diagonal, gegenläufig)
void main() {
vUV = inTexCoord;
float ns = m_UVScale * m_NormalUVScale; // Normal-Map UV-Dichte (0.5 = 2x größeres Muster)
float t = m_Time * m_FlowSpeed * m_NormalUVScale; // Scroll-Geschwindigkeit skaliert mit
vTex1 = vec2(inTexCoord.x * ns,
inTexCoord.y * ns - t);
vTex2 = vec2(inTexCoord.x * ns * 0.7 - t * 0.25,
inTexCoord.y * ns * 0.7 + t * 0.55);
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}

View File

@@ -1,10 +1,20 @@
uniform vec4 m_Color; uniform vec4 m_Color;
uniform vec3 m_SunDir;
uniform vec4 m_SunColor;
uniform vec4 g_AmbientLightColor;
#ifdef HAS_COLORMAP #ifdef HAS_COLORMAP
uniform sampler2D m_ColorMap; uniform sampler2D m_ColorMap;
#endif #endif
#ifdef HAS_NORMALMAP
uniform sampler2D m_NormalMap;
in vec3 wTangent;
in vec3 wBitangent;
#endif
in vec2 texCoord; in vec2 texCoord;
in vec3 wNormal;
out vec4 outFragColor; out vec4 outFragColor;
void main() { void main() {
@@ -12,7 +22,20 @@ void main() {
#ifdef HAS_COLORMAP #ifdef HAS_COLORMAP
color *= texture(m_ColorMap, texCoord); color *= texture(m_ColorMap, texCoord);
#endif #endif
// Alpha-Discard: transparente Pixel sofort verwerfen, Z-Buffer bleibt sauber
if (color.a < 0.5) discard; if (color.a < 0.5) discard;
vec3 n = normalize(wNormal);
#ifdef HAS_NORMALMAP
vec3 nm = texture(m_NormalMap, texCoord).rgb * 2.0 - 1.0;
mat3 tbn = mat3(normalize(wTangent), normalize(wBitangent), n);
n = normalize(tbn * nm);
#endif
// Beleuchtung: Sonne (two-sided via abs für Grashalme) + Ambient
float diffuse = abs(dot(n, normalize(m_SunDir)));
vec3 lit = g_AmbientLightColor.rgb + m_SunColor.rgb * diffuse;
color.rgb *= lit;
outFragColor = color; outFragColor = color;
} }

View File

@@ -7,8 +7,16 @@ uniform float m_WindStrength;
in vec3 inPosition; in vec3 inPosition;
in vec2 inTexCoord; in vec2 inTexCoord;
in vec3 inNormal;
in vec4 inTangent;
out vec2 texCoord; out vec2 texCoord;
out vec3 wNormal;
#ifdef HAS_NORMALMAP
out vec3 wTangent;
out vec3 wBitangent;
#endif
void main() { void main() {
vec4 pos = vec4(inPosition, 1.0); vec4 pos = vec4(inPosition, 1.0);
@@ -29,5 +37,14 @@ void main() {
} }
texCoord = inTexCoord; texCoord = inTexCoord;
mat3 rot = mat3(g_WorldMatrix);
wNormal = normalize(rot * inNormal);
#ifdef HAS_NORMALMAP
wTangent = normalize(rot * inTangent.xyz);
wBitangent = cross(wNormal, wTangent) * inTangent.w;
#endif
gl_Position = g_WorldViewProjectionMatrix * pos; gl_Position = g_WorldViewProjectionMatrix * pos;
} }

View File

@@ -0,0 +1,34 @@
uniform vec4 g_AmbientLightColor;
uniform vec3 m_SunDir; // Richtung von der Fläche zur Sonne (world-space, normiert)
uniform vec4 m_SunColor; // Sonnenfarbe RGB
in vec4 varColor;
in vec3 varNormal;
out vec4 outFragColor;
void main() {
// Normale für Rück- und Vorderseite korrekt ausrichten
vec3 n = normalize(varNormal);
if (!gl_FrontFacing) n = -n;
vec3 L = normalize(m_SunDir);
// Diffuses Licht
float nDotL = max(dot(n, L), 0.0);
// Subsurface-Scatter-Approximation: etwas Licht scheint durch den Halm
float sss = max(dot(-n, L), 0.0) * 0.25;
float light = nDotL + sss;
vec3 ambient = g_AmbientLightColor.rgb * varColor.rgb;
vec3 diffuse = m_SunColor.rgb * varColor.rgb * light;
// Farbe nicht über die Vertex-Color-Helligkeit hinaus aufhellen
vec3 result = ambient + diffuse;
result = min(result, varColor.rgb * 1.5);
outFragColor = vec4(result, 1.0);
}

View File

@@ -0,0 +1,39 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldMatrix;
uniform float g_Time;
uniform float m_WindSpeed;
uniform float m_WindStrength;
in vec3 inPosition;
in vec3 inNormal;
in vec4 inColor;
in vec2 inTexCoord; // .x = windFactor (0 = Wurzel, 1 = Spitze)
out vec4 varColor;
out vec3 varNormal;
void main() {
vec4 pos = vec4(inPosition, 1.0);
float wf = inTexCoord.x;
if (wf > 0.001) {
// Weltposition als Phasenbasis → jeder Halm schwingt anders
vec2 worldXZ = (g_WorldMatrix * pos).xz;
float t = g_Time * m_WindSpeed;
float sway = sin(t * 2.1 + worldXZ.x * 0.08 + worldXZ.y * 0.06) * 0.6
+ sin(t * 1.4 - worldXZ.x * 0.05 + worldXZ.y * 0.09) * 0.4;
// Quadratische Gewichtung: Spitze biegt sich mehr als Basis
float bend = sway * m_WindStrength * wf * wf;
pos.x += bend;
pos.z += bend * 0.3;
}
varColor = inColor;
// Normal in Weltkoordinaten (WorldMatrix ist für Gras typischerweise Identität)
varNormal = normalize(mat3(g_WorldMatrix) * inNormal);
gl_Position = g_WorldViewProjectionMatrix * pos;
}

View File

@@ -0,0 +1,133 @@
uniform sampler2DArray m_DiffuseArray;
#ifdef DEBUG_DIRECT_TEX
uniform sampler2D m_DebugDirectTex;
#endif
uniform float m_DiffuseScales[12];
uniform sampler2D m_AlphaMap;
#ifdef HAS_ALPHA_1
uniform sampler2D m_AlphaMap_1;
#endif
#ifdef HAS_ALPHA_2
uniform sampler2D m_AlphaMap_2;
#endif
#ifdef HAS_NORMAL_ARRAY
uniform sampler2DArray m_NormalArray;
#endif
#ifdef HAS_LIGHTDIR
uniform vec3 m_LightDir;
#endif
#ifdef HAS_SCENE_LIGHT
uniform vec3 m_SunColor;
uniform vec3 m_AmbientColor;
#endif
in vec2 vSplatUV;
in vec3 vWorldPos;
in vec3 vNormal;
in vec4 vTangent;
out vec4 outColor;
void main() {
vec4 a0 = texture(m_AlphaMap, vSplatUV);
vec4 a1 = vec4(0.0);
vec4 a2 = vec4(0.0);
#ifdef HAS_ALPHA_1
a1 = texture(m_AlphaMap_1, vSplatUV);
#endif
#ifdef HAS_ALPHA_2
a2 = texture(m_AlphaMap_2, vSplatUV);
#endif
// Slot-Mapping:
// Array[0] = Editor-Slot 1 (Basis, immer sichtbar — a0.r ist hardcoded 1.0)
// Array[1] = Editor-Slot 2, alpha = a0.g
// Array[2] = Editor-Slot 3, alpha = a0.b
// Array[3] = Editor-Slot 4, alpha = a0.a
// Array[4] = Editor-Slot 5, alpha = a1.r
// Array[5] = Editor-Slot 6, alpha = a1.g
// Array[6] = Editor-Slot 7, alpha = a1.b
// Array[7] = Editor-Slot 8, alpha = a1.a
// Array[8] = Editor-Slot 9, alpha = a2.r
// Array[9] = Editor-Slot 10, alpha = a2.g
// Array[10] = Editor-Slot 11, alpha = a2.b
// Array[11] = Editor-Slot 12, alpha = a2.a
//
// Blending: sequential mix — jeder Overlay ersetzt den Basis-Layer schrittweise.
// a0.r (Slot 1) wird vom Painting-Tool immer auf 1.0 gesetzt und dient nur als
// "Basis ist belegt"-Marker; er ist kein echter Alpha-Wert.
float overlays[11] = float[](a0.g, a0.b, a0.a,
a1.r, a1.g, a1.b, a1.a,
a2.r, a2.g, a2.b, a2.a);
#ifdef DEBUG_DIRECT_TEX
vec4 directCol = texture(m_DebugDirectTex, vWorldPos.xz / m_DiffuseScales[0]);
outColor = vec4(directCol.rgb, directCol.a);
return;
#endif
// Basis (Slot 1)
vec4 col = texture(m_DiffuseArray, vec3(vWorldPos.xz / m_DiffuseScales[0], 0.0));
#ifdef DEBUG_SLOT0_ONLY
// Debug: nur Slot 0 anzeigen, keine Alpha-Blending-Schleife
outColor = vec4(col.rgb, col.a);
return;
#endif
// Overlays (Slots 2-12) sequentiell darüber mischen
for (int i = 0; i < 11; i++) {
if (overlays[i] > 0.001) {
vec2 uv = vWorldPos.xz / m_DiffuseScales[i + 1];
col = mix(col, texture(m_DiffuseArray, vec3(uv, float(i + 1))), overlays[i]);
}
}
vec3 N = normalize(vNormal);
#ifdef HAS_NORMAL_ARRAY
vec3 T = normalize(vTangent.xyz);
vec3 B = cross(N, T) * vTangent.w;
mat3 TBN = mat3(T, B, N);
// Normal-Map Basis (Slot 1)
vec2 uv0 = vWorldPos.xz / m_DiffuseScales[0];
vec3 nm0 = texture(m_NormalArray, vec3(uv0, 0.0)).rgb * 2.0 - 1.0;
vec3 pertN = TBN * nm0;
// Normal-Maps Overlays (Slots 2-12) sequentiell mischen
for (int i = 0; i < 11; i++) {
if (overlays[i] > 0.001) {
vec2 uv = vWorldPos.xz / m_DiffuseScales[i + 1];
vec3 nm = texture(m_NormalArray, vec3(uv, float(i + 1))).rgb * 2.0 - 1.0;
pertN = mix(pertN, TBN * nm, overlays[i]);
}
}
N = normalize(pertN);
#endif
#ifdef HAS_LIGHTDIR
vec3 lightDir = normalize(m_LightDir);
#else
vec3 lightDir = normalize(vec3(0.6, 1.0, 0.4));
#endif
float diff = max(dot(N, lightDir), 0.0);
#ifdef HAS_SCENE_LIGHT
vec3 light = m_AmbientColor + m_SunColor * diff;
#else
vec3 light = vec3(diff * 0.65 + 0.35);
#endif
const float BRIGHTNESS = 0.80;
#ifdef DEBUG_NO_LIGHT
outColor = vec4(col.rgb * BRIGHTNESS, col.a);
#else
outColor = vec4(col.rgb * light * BRIGHTNESS, col.a);
#endif
}

View File

@@ -0,0 +1,27 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldMatrix;
uniform mat4 g_ViewProjectionMatrix;
in vec3 inPosition;
in vec3 inNormal;
in vec2 inTexCoord;
in vec4 inTangent;
out vec2 vSplatUV;
out vec3 vWorldPos;
out vec3 vNormal;
out vec4 vTangent;
void main() {
vec4 worldPos4 = g_WorldMatrix * vec4(inPosition, 1.0);
mat3 worldMat3 = mat3(g_WorldMatrix);
vec3 worldPos = worldPos4.xyz;
vec3 worldNorm = normalize(worldMat3 * inNormal);
vSplatUV = inTexCoord;
vWorldPos = worldPos;
vNormal = worldNorm;
vTangent = vec4(normalize(worldMat3 * inTangent.xyz), inTangent.w);
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}

Some files were not shown because too many files have changed in this diff Show More