Compare commits
29 Commits
1e0789461f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 63aa7aa104 | |||
| 6d061cd621 | |||
| cd350a92fa | |||
| b44d583dc3 | |||
| ba0b80f524 | |||
| 79f9cf12a3 | |||
| 914bf6e673 | |||
| b3b943e588 | |||
| d3c6e8ed77 | |||
| 7a3b2b8733 | |||
| e669e29096 | |||
| 52c1fb1fe8 | |||
| 197a820ef9 | |||
| 7dcf16fddf | |||
| 71ba297657 | |||
| 07a4c6a323 | |||
| c8f1dd9432 | |||
| a369647e9c | |||
| a80269e681 | |||
| fe5dfc19b1 | |||
| edb9cfc946 | |||
| 5e85051716 | |||
| 1297869dfa | |||
| 7faed35287 | |||
| d56f2ea41f | |||
| 875c39ab27 | |||
| ed1bc8f0a3 | |||
| 3e7108954e | |||
| 50f496c864 |
12
.gitignore
vendored
@@ -10,3 +10,15 @@
|
||||
.classpath
|
||||
.settings/
|
||||
bin/
|
||||
|
||||
# Laufzeit-Logs
|
||||
**/logs/
|
||||
|
||||
# Lokale Downloads (nicht ins Repo)
|
||||
downloads/
|
||||
|
||||
# Ingame-Karten-Sessions (vom Editor beim Spielstart erzeugt)
|
||||
run/
|
||||
|
||||
# Spielstände
|
||||
saves/
|
||||
|
||||
98
ANIMATIONEN_BLENDER_WORKFLOW.txt
Normal file
@@ -0,0 +1,98 @@
|
||||
ANIMATIONEN – BLENDER RETARGETING WORKFLOW
|
||||
==========================================
|
||||
|
||||
WARUM DIESER WORKFLOW?
|
||||
----------------------
|
||||
Das Mixamo-Skelett (stand.glb etc.) und das Tripo3D-Skelett (Charakter-Modell) haben
|
||||
unterschiedliche Bone-Orientierungs-Konventionen. Das Runtime-Retargeting in Java kann
|
||||
diesen Mismatch nicht zuverlässig beheben. Lösung: Animationen einmalig in Blender auf
|
||||
das Tripo-Skelett "umrechnen" (baken) und als neue GLBs exportieren.
|
||||
|
||||
Diese Arbeit ist EINMALIG pro Animations-Clip. Danach funktioniert jedes weitere
|
||||
Tripo3D-Modell mit denselben Bone-Namen automatisch über AnimationLibrary.
|
||||
|
||||
|
||||
VORAUSSETZUNGEN
|
||||
---------------
|
||||
- Charakter-Modell als GLB-Datei (die Quelldatei, aus der die .j3o erzeugt wurde)
|
||||
- Mixamo-Animations-GLB (z.B. stand.glb, twohand_idle.glb)
|
||||
- Blender 3.x oder 4.x
|
||||
|
||||
|
||||
WORKFLOW (für jede Animation einmal wiederholen)
|
||||
------------------------------------------------
|
||||
|
||||
Schritt 1: Beide Armatures in Blender laden
|
||||
File → Import → glTF 2.0 → Charakter-Modell .glb (= Custom-Armature)
|
||||
File → Import → glTF 2.0 → stand.glb (= Mixamo-Armature + Animation)
|
||||
|
||||
Schritt 2: Custom-Armature vorbereiten
|
||||
- Custom-Armature selektieren
|
||||
- Pose Mode (Ctrl+Tab)
|
||||
- Alle Bones selektieren (A)
|
||||
|
||||
Schritt 3: Copy-Rotation-Constraints setzen
|
||||
Für jeden Bone in der Custom-Armature:
|
||||
Bone-Properties → Constraints → Add Bone Constraint → Copy Rotation
|
||||
Target: Mixamo-Armature
|
||||
Bone: entsprechender Mixamo-Bone (siehe Mapping unten)
|
||||
|
||||
BONE-MAPPING (Custom → Mixamo):
|
||||
┌─────────────────┬─────────────────────────┐
|
||||
│ Custom │ Mixamo │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Pelvis │ mixamorig:Hips │
|
||||
│ Waist │ mixamorig:Spine │
|
||||
│ Spine01 │ mixamorig:Spine1 │
|
||||
│ Spine02 │ mixamorig:Spine2 │
|
||||
│ NeckTwist01 │ mixamorig:Neck │
|
||||
│ L_Clavicle │ mixamorig:LeftShoulder │
|
||||
│ L_Upperarm │ mixamorig:LeftArm │
|
||||
│ L_Forearm │ mixamorig:LeftForeArm │
|
||||
│ L_Hand │ mixamorig:LeftHand │
|
||||
│ R_Clavicle │ mixamorig:RightShoulder │
|
||||
│ R_Upperarm │ mixamorig:RightArm │
|
||||
│ R_Forearm │ mixamorig:RightForeArm │
|
||||
│ R_Hand │ mixamorig:RightHand │
|
||||
│ L_Thigh │ mixamorig:LeftUpLeg │
|
||||
│ L_Calf │ mixamorig:LeftLeg │
|
||||
│ L_Foot │ mixamorig:LeftFoot │
|
||||
│ R_Thigh │ mixamorig:RightUpLeg │
|
||||
│ R_Calf │ mixamorig:RightLeg │
|
||||
│ R_Foot │ mixamorig:RightFoot │
|
||||
└─────────────────┴─────────────────────────┘
|
||||
|
||||
Schritt 4: Animation baken
|
||||
Pose → Animation → Bake Action
|
||||
✓ Only Selected Bones
|
||||
✓ Visual Keying
|
||||
✓ Clear Constraints
|
||||
Bake Data: Pose
|
||||
|
||||
→ Erzeugt eine neue Action auf dem Custom-Skelett.
|
||||
|
||||
Schritt 5: Exportieren
|
||||
- Mixamo-Armature aus der Szene löschen (X → Delete)
|
||||
- Custom-Armature selektieren
|
||||
- File → Export → glTF 2.0
|
||||
Format: GLB
|
||||
Include: Selected Objects only
|
||||
Animation: ✓ (Export animations)
|
||||
- Speichern als: blight-assets/src/main/resources/animations/stand.glb
|
||||
(überschreibt das alte, fehlerhafte GLB)
|
||||
|
||||
→ Workflow für jede weitere Animation (twohand_idle.glb etc.) wiederholen.
|
||||
|
||||
|
||||
WIE ES DANACH FUNKTIONIERT
|
||||
---------------------------
|
||||
Die neuen GLBs haben das Tripo-Skelett mit den korrekten vorgerechneten Animationen.
|
||||
AnimationLibrary lädt sie beim Start automatisch und verteilt sie per applyAllTo()
|
||||
auf alle Charaktere im Spiel.
|
||||
|
||||
Neue Tripo3D-Charaktere (gleiche Bone-Namen) bekommen alle Animationen automatisch —
|
||||
kein weiteres Blender-Mapping nötig, weil das RetargetingSystem Bind-Pose-Unterschiede
|
||||
(z.B. unterschiedliche Proportionen) selbst korrigiert.
|
||||
|
||||
Neuer Animations-Clip von Mixamo:
|
||||
→ Einmal durch diesen Workflow → GLB in animations/ ablegen → fertig.
|
||||
BIN
assets/imported/animations/alive_again.glb
Normal file
BIN
assets/imported/animations/idle.glb
Normal file
BIN
assets/imported/animations/idle_jump.glb
Normal file
BIN
assets/imported/animations/pickup.glb
Normal file
BIN
assets/imported/animations/running.glb
Normal file
BIN
assets/imported/animations/running_jump.glb
Normal file
BIN
assets/imported/animations/sit_down.glb
Normal file
BIN
assets/imported/animations/sit_down_bench.glb
Normal file
BIN
assets/imported/animations/sitting_bench.glb
Normal file
BIN
assets/imported/animations/sitting_floor.glb
Normal file
BIN
assets/imported/animations/sprinting.glb
Normal file
BIN
assets/imported/animations/stand_up.glb
Normal file
BIN
assets/imported/animations/stand_up_bench.glb
Normal file
BIN
assets/imported/animations/tpose.glb
Normal file
BIN
assets/imported/animations/walking.glb
Normal file
@@ -3,3 +3,12 @@
|
||||
// geteilten Assets (MatDefs, Shaders, Textures) auf dem Classpath zu erhalten.
|
||||
//
|
||||
// Editor-spezifische Assets (Tool-Icons etc.) verbleiben in blight-editor.
|
||||
|
||||
apply plugin: 'java'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java { srcDirs = [] }
|
||||
resources { srcDirs = ['src/main/resources'] }
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 247 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
@@ -1,13 +1,14 @@
|
||||
MaterialDef TreeLeaf {
|
||||
MaterialDef Fern {
|
||||
|
||||
MaterialParameters {
|
||||
Color Diffuse (Color) : 0.18 0.60 0.10 1.0
|
||||
Float WindStrength : 0.30
|
||||
Float WindSpeed : 0.7
|
||||
Texture2D LeafMap
|
||||
Boolean HasLeafMap : false
|
||||
Float WindStrength : 0.15
|
||||
Float WindSpeed : 0.6
|
||||
Texture2D DiffuseMap
|
||||
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 FilterMode
|
||||
Boolean HardwareShadows
|
||||
@@ -15,8 +16,6 @@ MaterialDef TreeLeaf {
|
||||
Texture2D ShadowMap1
|
||||
Texture2D ShadowMap2
|
||||
Texture2D ShadowMap3
|
||||
Texture2D ShadowMap4
|
||||
Texture2D ShadowMap5
|
||||
Float ShadowIntensity : 1.0
|
||||
Vector4 Splits
|
||||
Vector2 FadeInfo
|
||||
@@ -24,18 +23,15 @@ MaterialDef TreeLeaf {
|
||||
Matrix4 LightViewProjectionMatrix1
|
||||
Matrix4 LightViewProjectionMatrix2
|
||||
Matrix4 LightViewProjectionMatrix3
|
||||
Matrix4 LightViewProjectionMatrix4
|
||||
Matrix4 LightViewProjectionMatrix5
|
||||
Vector3 LightPos
|
||||
Vector3 LightDir
|
||||
Float PCFEdge
|
||||
Float ShadowMapSize
|
||||
Boolean BackfaceShadows : false
|
||||
Boolean BackfaceShadows : false
|
||||
}
|
||||
|
||||
Technique {
|
||||
VertexShader GLSL150 : Shaders/Tree.vert
|
||||
FragmentShader GLSL150 : Shaders/TreeLeaf.frag
|
||||
VertexShader GLSL150 : Shaders/Fern.vert
|
||||
FragmentShader GLSL150 : Shaders/Fern.frag
|
||||
|
||||
WorldParameters {
|
||||
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 {
|
||||
VertexShader GLSL150 : Shaders/LeafPreShadow.vert
|
||||
FragmentShader GLSL150 : Shaders/LeafPreShadow.frag
|
||||
@@ -80,4 +60,20 @@ MaterialDef TreeLeaf {
|
||||
ColorWrite Off
|
||||
}
|
||||
}
|
||||
|
||||
Technique PostShadow {
|
||||
VertexShader GLSL150 : Shaders/LeafPostShadow.vert
|
||||
FragmentShader GLSL150 : Shaders/LeafPostShadow.frag
|
||||
|
||||
WorldParameters {
|
||||
WorldViewProjectionMatrix
|
||||
WorldMatrix
|
||||
}
|
||||
|
||||
ForcedRenderState {
|
||||
Blend Modulate
|
||||
FaceCull Off
|
||||
DepthWrite Off
|
||||
}
|
||||
}
|
||||
}
|
||||
25
blight-assets/src/main/resources/MatDefs/FlowingWater.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,11 @@ MaterialDef Grass {
|
||||
MaterialParameters {
|
||||
Color Color (Color) : 1.0 1.0 1.0 1.0
|
||||
Texture2D ColorMap
|
||||
Texture2D NormalMap
|
||||
Float WindSpeed : 0.5
|
||||
Float WindStrength : 0.12
|
||||
Vector3 SunDir : 0.55 0.80 0.35
|
||||
Color SunColor : 1.0 1.0 0.95 1.0
|
||||
}
|
||||
|
||||
Technique {
|
||||
@@ -15,6 +18,7 @@ MaterialDef Grass {
|
||||
WorldViewProjectionMatrix
|
||||
WorldMatrix
|
||||
Time
|
||||
AmbientLightColor
|
||||
}
|
||||
|
||||
RenderState {
|
||||
@@ -22,7 +26,8 @@ MaterialDef Grass {
|
||||
}
|
||||
|
||||
Defines {
|
||||
HAS_COLORMAP : ColorMap
|
||||
HAS_COLORMAP : ColorMap
|
||||
HAS_NORMALMAP : NormalMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
blight-assets/src/main/resources/MatDefs/GrassVertex.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
40
blight-assets/src/main/resources/MatDefs/TerrainArray.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
19
blight-assets/src/main/resources/MatDefs/Topology.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ MaterialDef Tree {
|
||||
Float WindSpeed : 0.5
|
||||
Texture2D BarkMap
|
||||
Boolean HasBarkMap : false
|
||||
Vector3 LightDir
|
||||
Vector3 SunColor
|
||||
Vector3 AmbientColor
|
||||
}
|
||||
|
||||
Technique {
|
||||
@@ -17,5 +20,9 @@ MaterialDef Tree {
|
||||
WorldMatrix
|
||||
Time
|
||||
}
|
||||
|
||||
Defines {
|
||||
HAS_SCENE_LIGHT : SunColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ MaterialDef TreeLeaf {
|
||||
Matrix4 LightViewProjectionMatrix5
|
||||
Vector3 LightPos
|
||||
Vector3 LightDir
|
||||
Vector3 SunColor
|
||||
Vector3 AmbientColor
|
||||
Float PCFEdge
|
||||
Float ShadowMapSize
|
||||
Boolean BackfaceShadows : false
|
||||
@@ -46,6 +48,10 @@ MaterialDef TreeLeaf {
|
||||
RenderState {
|
||||
FaceCull Off
|
||||
}
|
||||
|
||||
Defines {
|
||||
HAS_SCENE_LIGHT : SunColor
|
||||
}
|
||||
}
|
||||
|
||||
Technique PostShadow {
|
||||
|
||||
69
blight-assets/src/main/resources/MatDefs/Voxel.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
80
blight-assets/src/main/resources/MatDefs/WaterPolygon.j3md
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
blight-assets/src/main/resources/Models/Chars/mainchar.j3o
Normal file
BIN
blight-assets/src/main/resources/Models/Chars/silas.j3o
Normal 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
|
||||
@@ -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
|
||||
BIN
blight-assets/src/main/resources/Models/imported/bank1.j3o
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
42
blight-assets/src/main/resources/Shaders/Fern.frag
Normal 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);
|
||||
}
|
||||
34
blight-assets/src/main/resources/Shaders/Fern.vert
Normal 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;
|
||||
}
|
||||
85
blight-assets/src/main/resources/Shaders/FlowingWater.frag
Normal 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);
|
||||
}
|
||||
23
blight-assets/src/main/resources/Shaders/FlowingWater.vert
Normal 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);
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
uniform vec4 m_Color;
|
||||
uniform vec3 m_SunDir;
|
||||
uniform vec4 m_SunColor;
|
||||
uniform vec4 g_AmbientLightColor;
|
||||
|
||||
#ifdef HAS_COLORMAP
|
||||
uniform sampler2D m_ColorMap;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_NORMALMAP
|
||||
uniform sampler2D m_NormalMap;
|
||||
in vec3 wTangent;
|
||||
in vec3 wBitangent;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 wNormal;
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main() {
|
||||
@@ -12,7 +22,20 @@ void main() {
|
||||
#ifdef HAS_COLORMAP
|
||||
color *= texture(m_ColorMap, texCoord);
|
||||
#endif
|
||||
// Alpha-Discard: transparente Pixel sofort verwerfen, Z-Buffer bleibt sauber
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,16 @@ uniform float m_WindStrength;
|
||||
|
||||
in vec3 inPosition;
|
||||
in vec2 inTexCoord;
|
||||
in vec3 inNormal;
|
||||
in vec4 inTangent;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec3 wNormal;
|
||||
|
||||
#ifdef HAS_NORMALMAP
|
||||
out vec3 wTangent;
|
||||
out vec3 wBitangent;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec4 pos = vec4(inPosition, 1.0);
|
||||
@@ -29,5 +37,14 @@ void main() {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
34
blight-assets/src/main/resources/Shaders/GrassVertex.frag
Normal 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);
|
||||
}
|
||||
39
blight-assets/src/main/resources/Shaders/GrassVertex.vert
Normal 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;
|
||||
}
|
||||
133
blight-assets/src/main/resources/Shaders/TerrainArray.frag
Normal 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
|
||||
}
|
||||
27
blight-assets/src/main/resources/Shaders/TerrainArray.vert
Normal 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);
|
||||
}
|
||||
38
blight-assets/src/main/resources/Shaders/Topology.frag
Normal file
@@ -0,0 +1,38 @@
|
||||
uniform float m_Interval;
|
||||
uniform float m_LineWidth;
|
||||
uniform float m_Opacity;
|
||||
|
||||
in float vWorldY;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
// Maps height to a blue→green→yellow→red gradient
|
||||
vec3 heightColor(float t) {
|
||||
t = clamp(t, 0.0, 1.0);
|
||||
vec3 c;
|
||||
if (t < 0.25) {
|
||||
c = mix(vec3(0.0, 0.0, 0.8), vec3(0.0, 0.7, 0.7), t * 4.0);
|
||||
} else if (t < 0.5) {
|
||||
c = mix(vec3(0.0, 0.7, 0.7), vec3(0.2, 0.8, 0.1), (t - 0.25) * 4.0);
|
||||
} else if (t < 0.75) {
|
||||
c = mix(vec3(0.2, 0.8, 0.1), vec3(0.9, 0.8, 0.0), (t - 0.5) * 4.0);
|
||||
} else {
|
||||
c = mix(vec3(0.9, 0.8, 0.0), vec3(0.8, 0.1, 0.0), (t - 0.75) * 4.0);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float minH = -20.0;
|
||||
float maxH = 300.0;
|
||||
float t = (vWorldY - minH) / (maxH - minH);
|
||||
vec3 band = heightColor(t);
|
||||
|
||||
// Contour lines: sharp pulse near each interval boundary
|
||||
float phase = fract(vWorldY / m_Interval);
|
||||
float fw = fwidth(vWorldY / m_Interval);
|
||||
float line = 1.0 - smoothstep(m_LineWidth - fw, m_LineWidth + fw, min(phase, 1.0 - phase));
|
||||
|
||||
vec3 color = mix(band, vec3(0.0), line * 0.75);
|
||||
outColor = vec4(color, m_Opacity);
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||
|
||||
uniform mat4 g_WorldViewProjectionMatrix;
|
||||
uniform mat4 g_WorldMatrix;
|
||||
|
||||
in vec3 inPosition;
|
||||
in vec2 inTexCoord;
|
||||
|
||||
out vec2 texCoord;
|
||||
out float vWorldY;
|
||||
|
||||
void main() {
|
||||
vec4 worldPos = g_WorldMatrix * vec4(inPosition, 1.0);
|
||||
vWorldY = worldPos.y;
|
||||
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
|
||||
texCoord = inTexCoord;
|
||||
}
|
||||
@@ -4,26 +4,35 @@ uniform vec4 m_Diffuse;
|
||||
uniform sampler2D m_BarkMap;
|
||||
uniform bool m_HasBarkMap;
|
||||
|
||||
#ifdef HAS_SCENE_LIGHT
|
||||
uniform vec3 m_LightDir;
|
||||
uniform vec3 m_SunColor;
|
||||
uniform vec3 m_AmbientColor;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 worldNormal;
|
||||
|
||||
void main() {
|
||||
vec3 n = normalize(worldNormal);
|
||||
|
||||
// Sun at ~45° elevation from SE — good contrast on vertical cylinders
|
||||
vec3 sunDir = normalize(vec3(0.6, 0.7, 0.4));
|
||||
vec3 fillDir = normalize(vec3(-0.5, 0.3, -0.4));
|
||||
vec3 rimDir = normalize(vec3(-0.3, 0.5, 0.7));
|
||||
|
||||
float sun = max(dot(n, sunDir), 0.0);
|
||||
float fill = max(dot(n, fillDir), 0.0) * 0.22;
|
||||
float rim = max(dot(n, rimDir), 0.0) * 0.14;
|
||||
float sky = dot(n, vec3(0.0, 1.0, 0.0)) * 0.4 + 0.4; // [0.0, 0.8]
|
||||
float light = sun * 0.75 + fill + rim + sky * 0.09 + 0.05;
|
||||
|
||||
vec3 baseColor = m_HasBarkMap
|
||||
? texture2D(m_BarkMap, texCoord).rgb * m_Diffuse.rgb
|
||||
: m_Diffuse.rgb;
|
||||
|
||||
gl_FragColor = vec4(baseColor * clamp(light, 0.0, 1.0), m_Diffuse.a);
|
||||
#ifdef HAS_SCENE_LIGHT
|
||||
float diff = max(dot(n, normalize(m_LightDir)), 0.0);
|
||||
vec3 light = clamp(m_AmbientColor + m_SunColor * diff, 0.0, 1.0);
|
||||
#else
|
||||
vec3 sunDir = normalize(vec3(0.6, 0.7, 0.4));
|
||||
vec3 fillDir = normalize(vec3(-0.5, 0.3, -0.4));
|
||||
vec3 rimDir = normalize(vec3(-0.3, 0.5, 0.7));
|
||||
float sun = max(dot(n, sunDir), 0.0);
|
||||
float fill = max(dot(n, fillDir), 0.0) * 0.22;
|
||||
float rim = max(dot(n, rimDir), 0.0) * 0.14;
|
||||
float sky = dot(n, vec3(0.0, 1.0, 0.0)) * 0.4 + 0.4;
|
||||
vec3 light = vec3(clamp(sun * 0.75 + fill + rim + sky * 0.09 + 0.05, 0.0, 1.0));
|
||||
#endif
|
||||
|
||||
gl_FragColor = vec4(baseColor * light, m_Diffuse.a);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@ uniform vec4 m_Diffuse;
|
||||
uniform sampler2D m_LeafMap;
|
||||
uniform bool m_HasLeafMap;
|
||||
|
||||
#ifdef HAS_SCENE_LIGHT
|
||||
uniform vec3 m_LightDir;
|
||||
uniform vec3 m_SunColor;
|
||||
uniform vec3 m_AmbientColor;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 worldNormal;
|
||||
|
||||
@@ -15,13 +21,18 @@ void main() {
|
||||
if (tex.a < 0.5) discard;
|
||||
baseColor = tex.rgb * m_Diffuse.rgb;
|
||||
} else {
|
||||
// Fallback: kreisförmiger Clip
|
||||
vec2 uv = texCoord * 2.0 - 1.0;
|
||||
if (dot(uv, uv) > 0.95) discard;
|
||||
float edge = 1.0 - dot(uv, uv);
|
||||
baseColor = m_Diffuse.rgb * (0.7 + 0.3 * edge);
|
||||
}
|
||||
|
||||
// Leaves transmit light — no directional shading, uniform brightness
|
||||
gl_FragColor = vec4(baseColor, 1.0);
|
||||
#ifdef HAS_SCENE_LIGHT
|
||||
// Blätter transmittieren Licht — abs() für doppelseitige Beleuchtung
|
||||
float diff = abs(dot(normalize(worldNormal), normalize(m_LightDir)));
|
||||
vec3 light = clamp(m_AmbientColor + m_SunColor * diff * 0.6, 0.0, 1.0);
|
||||
gl_FragColor = vec4(baseColor * light, 1.0);
|
||||
#else
|
||||
gl_FragColor = vec4(baseColor * 0.8, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
112
blight-assets/src/main/resources/Shaders/Voxel.frag
Normal file
@@ -0,0 +1,112 @@
|
||||
uniform sampler2D m_TexFlat;
|
||||
uniform sampler2D m_TexSteep;
|
||||
uniform float m_TexScale;
|
||||
|
||||
#ifdef HAS_NM_FLAT
|
||||
uniform sampler2D m_NormalMapFlat;
|
||||
#endif
|
||||
#ifdef HAS_NM_STEEP
|
||||
uniform sampler2D m_NormalMapSteep;
|
||||
#endif
|
||||
|
||||
in vec3 vWorldPos;
|
||||
in vec3 vNormal;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
#ifdef HAS_LIGHTDIR
|
||||
uniform vec3 m_LightDir;
|
||||
#endif
|
||||
#ifdef HAS_SCENE_LIGHT
|
||||
uniform vec3 m_SunColor;
|
||||
uniform vec3 m_AmbientColor;
|
||||
#endif
|
||||
|
||||
vec4 triplanar(sampler2D tex, vec2 uvX, vec2 uvY, vec2 uvZ, vec3 bw) {
|
||||
return texture(tex, uvX) * bw.x
|
||||
+ texture(tex, uvY) * bw.y
|
||||
+ texture(tex, uvZ) * bw.z;
|
||||
}
|
||||
|
||||
// Triplanare Normal-Map-Mischung (Whiteout-Blending, world-space Ausgabe).
|
||||
// N = geometrische Weltoberflächen-Normale, bw = triplanare Gewichte.
|
||||
vec3 triplanarNormal(sampler2D nmap, vec2 uvX, vec2 uvY, vec2 uvZ, vec3 bw, vec3 N) {
|
||||
vec3 tnX = texture(nmap, uvX).rgb * 2.0 - 1.0;
|
||||
vec3 tnY = texture(nmap, uvY).rgb * 2.0 - 1.0;
|
||||
vec3 tnZ = texture(nmap, uvZ).rgb * 2.0 - 1.0;
|
||||
|
||||
// Reorientiertes Normal-Mapping (RNM / Whiteout): Tangent → World
|
||||
tnX = vec3(tnX.xy + N.zy, abs(tnX.z) * N.x);
|
||||
tnY = vec3(tnY.xy + N.xz, abs(tnY.z) * N.y);
|
||||
tnZ = vec3(tnZ.xy + N.xy, abs(tnZ.z) * N.z);
|
||||
|
||||
return normalize(tnX.zyx * bw.x + tnY.xzy * bw.y + tnZ.xyz * bw.z);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 bw = pow(abs(vNormal), vec3(4.0));
|
||||
bw /= (bw.x + bw.y + bw.z + 0.001);
|
||||
|
||||
vec2 uvX = vWorldPos.yz / m_TexScale;
|
||||
vec2 uvY = vWorldPos.xz / m_TexScale;
|
||||
vec2 uvZ = vWorldPos.xy / m_TexScale;
|
||||
|
||||
// Flach ab ~11° Gefälle (20% grade, normal.y≈0.98); alles andere Fels.
|
||||
float flatBlend = smoothstep(0.94, 0.99, vNormal.y);
|
||||
float steepBlend = 1.0 - flatBlend;
|
||||
|
||||
// Flat: reines XZ-UV wie das Terrain (uvY = worldPos.xz / texScale), kein Triplanar.
|
||||
// Steep: Triplanar für alle nicht-flachen Flächen inkl. Decken und Tunnelwände.
|
||||
vec4 col = texture(m_TexFlat, uvY) * flatBlend
|
||||
+ triplanar(m_TexSteep, uvX, uvY, uvZ, bw) * steepBlend;
|
||||
|
||||
// Geometrie-Normale für Beleuchtung, ggf. durch Normal-Map ersetzt.
|
||||
vec3 N = normalize(vNormal);
|
||||
|
||||
#if defined(HAS_NM_FLAT) || defined(HAS_NM_STEEP)
|
||||
vec3 pertN = vec3(0.0);
|
||||
float totalBlend = 0.0;
|
||||
#ifdef HAS_NM_FLAT
|
||||
if (flatBlend > 0.001) {
|
||||
vec3 nmFlat = texture(m_NormalMapFlat, uvY).rgb * 2.0 - 1.0;
|
||||
nmFlat = vec3(nmFlat.xy + N.xz, abs(nmFlat.z) * N.y);
|
||||
pertN += normalize(nmFlat.xzy) * flatBlend;
|
||||
totalBlend += flatBlend;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAS_NM_STEEP
|
||||
if (steepBlend > 0.001) {
|
||||
pertN += triplanarNormal(m_NormalMapSteep, uvX, uvY, uvZ, bw, N) * steepBlend;
|
||||
totalBlend += steepBlend;
|
||||
}
|
||||
#endif
|
||||
if (totalBlend > 0.001) {
|
||||
N = normalize(pertN / totalBlend);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Flache Voxel-Flächen Richtung (0,1,0) korrigieren, um Abweichungen der
|
||||
// Marching-Cubes-Normalen auszugleichen und das Terrain-Lighting zu matchen.
|
||||
N = normalize(mix(N, vec3(0.0, 1.0, 0.0), flatBlend));
|
||||
|
||||
#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
|
||||
if (outColor.a < 0.1) discard;
|
||||
}
|
||||
29
blight-assets/src/main/resources/Shaders/Voxel.tsctrl
Normal file
@@ -0,0 +1,29 @@
|
||||
layout(vertices = 3) out;
|
||||
|
||||
in vec3 vWorldPos[];
|
||||
in vec3 vNormal[];
|
||||
|
||||
out vec3 tcWorldPos[];
|
||||
out vec3 tcNormal[];
|
||||
|
||||
uniform float m_TessellationLevel;
|
||||
uniform vec3 g_CameraPosition;
|
||||
|
||||
void main() {
|
||||
tcWorldPos[gl_InvocationID] = vWorldPos[gl_InvocationID];
|
||||
tcNormal[gl_InvocationID] = vNormal[gl_InvocationID];
|
||||
|
||||
if (gl_InvocationID == 0) {
|
||||
vec3 center = (vWorldPos[0] + vWorldPos[1] + vWorldPos[2]) / 3.0;
|
||||
float dist = distance(g_CameraPosition, center);
|
||||
|
||||
// Maximum subdivision close-up, falls to 1 at 64 m
|
||||
float level = mix(m_TessellationLevel, 1.0, clamp(dist / 64.0, 0.0, 1.0));
|
||||
level = max(1.0, level);
|
||||
|
||||
gl_TessLevelOuter[0] = level;
|
||||
gl_TessLevelOuter[1] = level;
|
||||
gl_TessLevelOuter[2] = level;
|
||||
gl_TessLevelInner[0] = level;
|
||||
}
|
||||
}
|
||||
82
blight-assets/src/main/resources/Shaders/Voxel.tseval
Normal file
@@ -0,0 +1,82 @@
|
||||
layout(triangles, equal_spacing, ccw) in;
|
||||
|
||||
in vec3 tcWorldPos[];
|
||||
in vec3 tcNormal[];
|
||||
|
||||
out vec3 vWorldPos;
|
||||
out vec3 vNormal;
|
||||
|
||||
uniform mat4 g_ViewProjectionMatrix;
|
||||
uniform float m_TexScale;
|
||||
uniform float m_DisplacementScale;
|
||||
|
||||
#ifdef HAS_DISP_FLAT
|
||||
uniform sampler2D m_DisplacementMapFlat;
|
||||
#endif
|
||||
#ifdef HAS_DISP_STEEP
|
||||
uniform sampler2D m_DisplacementMapSteep;
|
||||
#endif
|
||||
#ifdef HAS_DISP_CEIL
|
||||
uniform sampler2D m_DisplacementMapCeil;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec3 bc = gl_TessCoord;
|
||||
|
||||
// Interpolate position and normal from patch vertices
|
||||
vec3 pos = bc.x * tcWorldPos[0] + bc.y * tcWorldPos[1] + bc.z * tcWorldPos[2];
|
||||
vec3 nor = normalize(bc.x * tcNormal[0] + bc.y * tcNormal[1] + bc.z * tcNormal[2]);
|
||||
|
||||
// Triplanar blend weights (same as fragment shader)
|
||||
vec3 bw = pow(abs(nor), vec3(4.0));
|
||||
bw /= (bw.x + bw.y + bw.z + 0.001);
|
||||
vec2 uvX = pos.yz / m_TexScale;
|
||||
vec2 uvY = pos.xz / m_TexScale;
|
||||
vec2 uvZ = pos.xy / m_TexScale;
|
||||
|
||||
float flatBlend = smoothstep(0.94, 0.99, nor.y);
|
||||
float ceilBlend = 1.0 - smoothstep(-0.6, -0.3, nor.y);
|
||||
float steepBlend = max(0.0, 1.0 - flatBlend - ceilBlend);
|
||||
|
||||
#if defined(HAS_DISP_FLAT) || defined(HAS_DISP_STEEP) || defined(HAS_DISP_CEIL)
|
||||
float disp = 0.0;
|
||||
float totalW = 0.0;
|
||||
|
||||
#ifdef HAS_DISP_FLAT
|
||||
if (flatBlend > 0.001) {
|
||||
float d = texture(m_DisplacementMapFlat, uvX).r * bw.x
|
||||
+ texture(m_DisplacementMapFlat, uvY).r * bw.y
|
||||
+ texture(m_DisplacementMapFlat, uvZ).r * bw.z;
|
||||
disp += d * flatBlend;
|
||||
totalW += flatBlend;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAS_DISP_STEEP
|
||||
if (steepBlend > 0.001) {
|
||||
float d = texture(m_DisplacementMapSteep, uvX).r * bw.x
|
||||
+ texture(m_DisplacementMapSteep, uvY).r * bw.y
|
||||
+ texture(m_DisplacementMapSteep, uvZ).r * bw.z;
|
||||
disp += d * steepBlend;
|
||||
totalW += steepBlend;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAS_DISP_CEIL
|
||||
if (ceilBlend > 0.001) {
|
||||
float d = texture(m_DisplacementMapCeil, uvX).r * bw.x
|
||||
+ texture(m_DisplacementMapCeil, uvY).r * bw.y
|
||||
+ texture(m_DisplacementMapCeil, uvZ).r * bw.z;
|
||||
disp += d * ceilBlend;
|
||||
totalW += ceilBlend;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (totalW > 0.001) disp /= totalW;
|
||||
|
||||
// 0.5 = neutral (no displacement), 0 = sink, 1 = raise
|
||||
pos += nor * ((disp - 0.5) * m_DisplacementScale);
|
||||
#endif
|
||||
|
||||
vWorldPos = pos;
|
||||
vNormal = nor;
|
||||
gl_Position = g_ViewProjectionMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
15
blight-assets/src/main/resources/Shaders/Voxel.vert
Normal file
@@ -0,0 +1,15 @@
|
||||
uniform mat4 g_WorldViewProjectionMatrix;
|
||||
uniform mat4 g_WorldMatrix;
|
||||
|
||||
in vec3 inPosition;
|
||||
in vec3 inNormal;
|
||||
|
||||
out vec3 vWorldPos;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main() {
|
||||
vec4 worldPos = g_WorldMatrix * vec4(inPosition, 1.0);
|
||||
vWorldPos = worldPos.xyz;
|
||||
vNormal = normalize(mat3(g_WorldMatrix) * inNormal);
|
||||
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
|
||||
}
|
||||
15
blight-assets/src/main/resources/Shaders/VoxelTess.vert
Normal file
@@ -0,0 +1,15 @@
|
||||
uniform mat4 g_WorldViewProjectionMatrix;
|
||||
uniform mat4 g_WorldMatrix;
|
||||
|
||||
in vec3 inPosition;
|
||||
in vec3 inNormal;
|
||||
|
||||
out vec3 vWorldPos;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main() {
|
||||
vec4 wpos = g_WorldMatrix * vec4(inPosition, 1.0);
|
||||
vWorldPos = wpos.xyz;
|
||||
vNormal = normalize(mat3(g_WorldMatrix) * inNormal);
|
||||
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
|
||||
}
|
||||
483
blight-assets/src/main/resources/Shaders/WaterPolygon.frag
Normal file
@@ -0,0 +1,483 @@
|
||||
#import "Common/ShaderLib/GLSLCompat.glsllib"
|
||||
#import "Common/ShaderLib/MultiSample.glsllib"
|
||||
#import "Common/ShaderLib/WaterUtil.glsllib"
|
||||
|
||||
// Water pixel shader
|
||||
// Copyright (C) JMonkeyEngine 3.0
|
||||
// by Remy Bouquet (nehon) for JMonkeyEngine 3.0
|
||||
// original HLSL version by Wojciech Toman 2009
|
||||
|
||||
uniform COLORTEXTURE m_Texture;
|
||||
uniform DEPTHTEXTURE m_DepthTexture;
|
||||
|
||||
|
||||
uniform sampler2D m_HeightMap;
|
||||
uniform sampler2D m_NormalMap;
|
||||
uniform sampler2D m_FoamMap;
|
||||
uniform sampler2D m_CausticsMap;
|
||||
uniform sampler2D m_ReflectionMap;
|
||||
|
||||
uniform mat4 g_ViewProjectionMatrixInverse;
|
||||
uniform mat4 m_TextureProjMatrix;
|
||||
uniform vec3 m_CameraPosition;
|
||||
|
||||
uniform float m_WaterHeight;
|
||||
uniform float m_Time;
|
||||
uniform float m_WaterTransparency;
|
||||
uniform float m_NormalScale;
|
||||
uniform float m_R0;
|
||||
uniform float m_MaxAmplitude;
|
||||
uniform vec3 m_LightDir;
|
||||
uniform vec4 m_LightColor;
|
||||
uniform float m_ShoreHardness;
|
||||
uniform float m_FoamHardness;
|
||||
uniform float m_RefractionStrength;
|
||||
uniform vec3 m_FoamExistence;
|
||||
uniform vec3 m_ColorExtinction;
|
||||
uniform float m_Shininess;
|
||||
uniform vec4 m_WaterColor;
|
||||
uniform vec4 m_DeepWaterColor;
|
||||
uniform vec2 m_WindDirection;
|
||||
uniform float m_SunScale;
|
||||
uniform float m_WaveScale;
|
||||
uniform float m_UnderWaterFogDistance;
|
||||
uniform float m_CausticsIntensity;
|
||||
|
||||
#ifdef ENABLE_AREA
|
||||
uniform vec3 m_Center;
|
||||
uniform float m_Radius;
|
||||
#endif
|
||||
|
||||
#ifdef POLYGON_AREA
|
||||
uniform vec2 m_Points[64];
|
||||
uniform int m_NumPoints;
|
||||
|
||||
bool polygonContains(float px, float pz) {
|
||||
bool inside = false;
|
||||
int j = m_NumPoints - 1;
|
||||
for (int i = 0; i < m_NumPoints; i++) {
|
||||
float xi = m_Points[i].x, zi = m_Points[i].y;
|
||||
float xj = m_Points[j].x, zj = m_Points[j].y;
|
||||
if ((zi > pz) != (zj > pz) &&
|
||||
px < (xj - xi) * (pz - zi) / (zj - zi) + xi)
|
||||
inside = !inside;
|
||||
j = i;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 scale; // = vec2(m_WaveScale, m_WaveScale);
|
||||
float refractionScale; // = m_WaveScale;
|
||||
|
||||
// Modifies 4 sampled normals. Increase first values to have more
|
||||
// smaller "waves" or last to have more bigger "waves"
|
||||
const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0);
|
||||
// Strength of displacement along normal.
|
||||
uniform float m_ReflectionDisplace;
|
||||
// Water transparency along eye vector.
|
||||
const float visibility = 3.0;
|
||||
// foam intensity
|
||||
uniform float m_FoamIntensity ;
|
||||
|
||||
vec2 m_FrustumNearFar; //=vec2(1.0,m_UnderWaterFogDistance);
|
||||
const float LOG2 = 1.442695;
|
||||
|
||||
|
||||
varying vec2 texCoord;
|
||||
|
||||
void setGlobals(){
|
||||
scale = vec2(m_WaveScale, m_WaveScale);
|
||||
refractionScale = m_WaveScale;
|
||||
m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance);
|
||||
}
|
||||
|
||||
mat3 MatrixInverse(in mat3 inMatrix){
|
||||
float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]);
|
||||
mat3 T = transpose(inMatrix);
|
||||
return mat3(cross(T[1], T[2]),
|
||||
cross(T[2], T[0]),
|
||||
cross(T[0], T[1])) / det;
|
||||
}
|
||||
|
||||
|
||||
mat3 computeTangentFrame(in vec3 N, in vec3 P, in vec2 UV) {
|
||||
vec3 dp1 = dFdx(P);
|
||||
vec3 dp2 = dFdy(P);
|
||||
vec2 duv1 = dFdx(UV);
|
||||
vec2 duv2 = dFdy(UV);
|
||||
|
||||
// solve the linear system
|
||||
vec3 dp1xdp2 = cross(dp1, dp2);
|
||||
mat2x3 inverseM = mat2x3(cross(dp2, dp1xdp2), cross(dp1xdp2, dp1));
|
||||
|
||||
vec3 T = inverseM * vec2(duv1.x, duv2.x);
|
||||
vec3 B = inverseM * vec2(duv1.y, duv2.y);
|
||||
|
||||
// construct tangent frame
|
||||
float maxLength = max(length(T), length(B));
|
||||
T = T / maxLength;
|
||||
B = B / maxLength;
|
||||
|
||||
return mat3(T, B, N);
|
||||
}
|
||||
|
||||
float saturate(in float val){
|
||||
return clamp(val,0.0,1.0);
|
||||
}
|
||||
|
||||
vec3 saturate(in vec3 val){
|
||||
return clamp(val,vec3(0.0),vec3(1.0));
|
||||
}
|
||||
|
||||
vec3 getPosition(in float depth, in vec2 uv){
|
||||
vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0;
|
||||
pos = g_ViewProjectionMatrixInverse * pos;
|
||||
return pos.xyz / pos.w;
|
||||
}
|
||||
|
||||
// Function calculating fresnel term.
|
||||
// - normal - normalized normal vector
|
||||
// - eyeVec - normalized eye vector
|
||||
float fresnelTerm(in vec3 normal,in vec3 eyeVec){
|
||||
float angle = 1.0 - max(0.0, dot(normal, eyeVec));
|
||||
float fresnel = angle * angle;
|
||||
fresnel = fresnel * fresnel;
|
||||
fresnel = fresnel * angle;
|
||||
return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength);
|
||||
}
|
||||
|
||||
vec4 underWater(int sampleNum){
|
||||
|
||||
|
||||
float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
|
||||
vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
|
||||
|
||||
vec3 position = getPosition(sceneDepth, texCoord);
|
||||
float level = m_WaterHeight;
|
||||
|
||||
vec3 eyeVec = position - m_CameraPosition;
|
||||
|
||||
// Find intersection with water surface
|
||||
vec3 eyeVecNorm = normalize(eyeVec);
|
||||
float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
|
||||
vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;
|
||||
|
||||
vec2 texC = vec2(0.0);
|
||||
|
||||
float cameraDepth = length(m_CameraPosition - surfacePoint);
|
||||
texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection;
|
||||
float bias = texture2D(m_HeightMap, texC).r;
|
||||
level += bias * m_MaxAmplitude;
|
||||
t = (level - m_CameraPosition.y) / eyeVecNorm.y;
|
||||
surfacePoint = m_CameraPosition + eyeVecNorm * t;
|
||||
eyeVecNorm = normalize(m_CameraPosition - surfacePoint);
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
// Find normal of water surface
|
||||
float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0, 0.0)).r;
|
||||
float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0, 0.0)).r;
|
||||
float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
|
||||
float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0, 1.0)).r;
|
||||
#else
|
||||
// Find normal of water surface
|
||||
float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
|
||||
float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
|
||||
float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
|
||||
float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
|
||||
#endif
|
||||
|
||||
vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
|
||||
vec3 normal = myNormal*-1.0;
|
||||
float fresnel = fresnelTerm(normal, eyeVecNorm);
|
||||
|
||||
vec3 refraction = color2;
|
||||
#ifdef ENABLE_REFRACTION
|
||||
texC = texCoord.xy *sin (fresnel+1.0);
|
||||
texC = clamp(texC,0.0,1.0);
|
||||
refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
|
||||
#endif
|
||||
|
||||
float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
|
||||
refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency), m_WaterColor.rgb* waterCol,m_WaterTransparency);
|
||||
|
||||
vec3 foam = vec3(0.0);
|
||||
#ifdef ENABLE_FOAM
|
||||
texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
|
||||
vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;
|
||||
|
||||
if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
|
||||
foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity * m_FoamIntensity * 0.3 *
|
||||
saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
|
||||
}
|
||||
foam *= m_LightColor.rgb;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
vec3 specular = vec3(0.0);
|
||||
vec3 color ;
|
||||
float fogFactor;
|
||||
|
||||
if(position.y>level){
|
||||
#ifdef ENABLE_SPECULAR
|
||||
if(step(0.9999,sceneDepth)==1.0){
|
||||
vec3 lightDir=normalize(m_LightDir);
|
||||
vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
|
||||
float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
|
||||
specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
|
||||
specular += specular * 25.0 * saturate(m_Shininess - 0.05);
|
||||
specular=specular * m_LightColor.rgb * 100.0;
|
||||
}
|
||||
#endif
|
||||
float fogIntensity= 8.0 * m_WaterTransparency;
|
||||
fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 );
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
color =mix(m_DeepWaterColor.rgb,refraction,fogFactor);
|
||||
specular=specular*fogFactor;
|
||||
color = saturate(color + max(specular, foam ));
|
||||
}else{
|
||||
vec3 caustics = vec3(0.0);
|
||||
#ifdef ENABLE_CAUSTICS
|
||||
vec2 windDirection=m_WindDirection;
|
||||
texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.x) * 0.01;
|
||||
vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.z) * 0.01;
|
||||
caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb;
|
||||
caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity));
|
||||
color=mix(color2,caustics,m_CausticsIntensity);
|
||||
#else
|
||||
color=color2;
|
||||
#endif
|
||||
|
||||
float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x));
|
||||
float fogIntensity= 18.0 * m_WaterTransparency;
|
||||
fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth * fogDepth * LOG2 );
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
color =mix(m_DeepWaterColor.rgb,color,fogFactor);
|
||||
}
|
||||
|
||||
return vec4(color, 1.0);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: This will be called even for single-sampling
|
||||
vec4 main_multiSample(int sampleNum){
|
||||
// If we are underwater let's call the underwater function
|
||||
if(m_WaterHeight >= m_CameraPosition.y){
|
||||
#ifdef ENABLE_AREA
|
||||
if(isOverExtent(m_CameraPosition, m_Center, m_Radius)){
|
||||
return fetchTextureSample(m_Texture, texCoord, sampleNum);
|
||||
}
|
||||
#endif
|
||||
#ifdef POLYGON_AREA
|
||||
if(!polygonContains(m_CameraPosition.x, m_CameraPosition.z)){
|
||||
return fetchTextureSample(m_Texture, texCoord, sampleNum);
|
||||
}
|
||||
#endif
|
||||
return underWater(sampleNum);
|
||||
}
|
||||
|
||||
float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
|
||||
vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb;
|
||||
|
||||
vec3 color = color2;
|
||||
vec3 position = getPosition(sceneDepth, texCoord);
|
||||
|
||||
#ifdef ENABLE_AREA
|
||||
if(isOverExtent(position, m_Center, m_Radius)){
|
||||
return vec4(color2, 1.0);
|
||||
}
|
||||
#endif
|
||||
#ifdef POLYGON_AREA
|
||||
if(!polygonContains(position.x, position.z)){
|
||||
return vec4(color2, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
float level = m_WaterHeight;
|
||||
|
||||
float isAtFarPlane = step(0.99998, sceneDepth);
|
||||
//#ifndef ENABLE_RIPPLES
|
||||
// This optimization won't work on NVIDIA cards if ripples are enabled
|
||||
if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){
|
||||
|
||||
return vec4(color2, 1.0);
|
||||
}
|
||||
//#endif
|
||||
|
||||
vec3 eyeVec = position - m_CameraPosition;
|
||||
float cameraDepth = m_CameraPosition.y - position.y;
|
||||
|
||||
// Find intersection with water surface
|
||||
vec3 eyeVecNorm = normalize(eyeVec);
|
||||
float t = (level - m_CameraPosition.y) / eyeVecNorm.y;
|
||||
vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t;
|
||||
|
||||
vec2 texC = vec2(0.0);
|
||||
int samples = 1;
|
||||
#ifdef ENABLE_HQ_SHORELINE
|
||||
samples = 10;
|
||||
#endif
|
||||
|
||||
float biasFactor = 1.0 / float(samples);
|
||||
for (int i = 0; i < samples; i++){
|
||||
texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection;
|
||||
|
||||
float bias = texture2D(m_HeightMap, texC).r;
|
||||
|
||||
bias *= biasFactor;
|
||||
level += bias * m_MaxAmplitude;
|
||||
t = (level - m_CameraPosition.y) / eyeVecNorm.y;
|
||||
surfacePoint = m_CameraPosition + eyeVecNorm * t;
|
||||
}
|
||||
|
||||
float depth = length(position - surfacePoint);
|
||||
float depth2 = surfacePoint.y - position.y;
|
||||
|
||||
// XXX: HACK ALERT: Increase water depth to infinity if at far plane
|
||||
// Prevents "foam on horizon" issue
|
||||
// For best results, replace the "100.0" below with the
|
||||
// highest value in the m_ColorExtinction vec3
|
||||
depth += isAtFarPlane * 100.0;
|
||||
depth2 += isAtFarPlane * 100.0;
|
||||
|
||||
eyeVecNorm = normalize(m_CameraPosition - surfacePoint);
|
||||
|
||||
#if __VERSION__ >= 130
|
||||
// Find normal of water surface
|
||||
float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0, 0.0)).r;
|
||||
float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0, 0.0)).r;
|
||||
float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r;
|
||||
float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0, 1.0)).r;
|
||||
#else
|
||||
// Find normal of water surface
|
||||
float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r;
|
||||
float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r;
|
||||
float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r;
|
||||
float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r;
|
||||
#endif
|
||||
|
||||
vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude));
|
||||
vec3 normal = vec3(0.0);
|
||||
|
||||
#ifdef ENABLE_RIPPLES
|
||||
texC = surfacePoint.xz * 0.8 + m_WindDirection * m_Time* 1.6;
|
||||
mat3 tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
|
||||
vec3 normal0a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));
|
||||
|
||||
texC = surfacePoint.xz * 0.4 + m_WindDirection * m_Time* 0.8;
|
||||
tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
|
||||
vec3 normal1a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));
|
||||
|
||||
texC = surfacePoint.xz * 0.2 + m_WindDirection * m_Time * 0.4;
|
||||
tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
|
||||
vec3 normal2a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));
|
||||
|
||||
texC = surfacePoint.xz * 0.1 + m_WindDirection * m_Time * 0.2;
|
||||
tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC);
|
||||
vec3 normal3a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0));
|
||||
|
||||
normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w);
|
||||
|
||||
#if __VERSION__ >= 130 && !defined GL_ES
|
||||
// XXX: Here's another way to fix the terrain edge issue,
|
||||
// But it requires GLSL 1.3 and still looks kinda incorrect
|
||||
// around edges
|
||||
normal = isnan(normal.x) ? myNormal : normal;
|
||||
#else
|
||||
// To make the shader 1.2 compatible we use a trick :
|
||||
// we clamp the x value of the normal and compare it to it's former value instead of using isnan.
|
||||
normal = clamp(normal.x,0.0,1.0)!=normal.x ? myNormal : normal;
|
||||
#endif
|
||||
|
||||
#else
|
||||
normal = myNormal;
|
||||
#endif
|
||||
|
||||
vec3 refraction = color2;
|
||||
#ifdef ENABLE_REFRACTION
|
||||
// texC = texCoord.xy+ m_ReflectionDisplace * normal.x;
|
||||
texC = texCoord.xy;
|
||||
texC += sin(m_Time*1.8 + 3.0 * abs(position.y))* (refractionScale * min(depth2, 1.0));
|
||||
texC = clamp(texC,vec2(0.0),vec2(0.999));
|
||||
refraction = fetchTextureSample(m_Texture, texC, sampleNum).rgb;
|
||||
#endif
|
||||
vec3 waterPosition = surfacePoint.xyz;
|
||||
waterPosition.y -= (level - m_WaterHeight);
|
||||
vec4 texCoordProj = m_TextureProjMatrix * vec4(waterPosition, 1.0);
|
||||
|
||||
texCoordProj.x = texCoordProj.x + m_ReflectionDisplace * normal.x;
|
||||
texCoordProj.z = texCoordProj.z + m_ReflectionDisplace * normal.z;
|
||||
texCoordProj /= texCoordProj.w;
|
||||
texCoordProj.y = 1.0 - texCoordProj.y;
|
||||
|
||||
vec3 reflection = texture2D(m_ReflectionMap, texCoordProj.xy).rgb;
|
||||
|
||||
float fresnel = fresnelTerm(normal, eyeVecNorm);
|
||||
|
||||
float depthN = depth * m_WaterTransparency;
|
||||
float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale);
|
||||
refraction = mix(mix(refraction, m_WaterColor.rgb * waterCol, saturate(depthN / visibility)),
|
||||
m_DeepWaterColor.rgb * waterCol, saturate(depth2 / m_ColorExtinction));
|
||||
|
||||
|
||||
vec3 foam = vec3(0.0);
|
||||
#ifdef ENABLE_FOAM
|
||||
texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005;
|
||||
vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005;
|
||||
|
||||
vec4 foam1 = texture2D(m_FoamMap, texC);
|
||||
vec4 foam2 = texture2D(m_FoamMap, texCoord2);
|
||||
|
||||
if(depth2 < m_FoamExistence.x){
|
||||
foam = (foam1.r + foam2).rgb * vec3(m_FoamIntensity);
|
||||
}else if(depth2 < m_FoamExistence.y){
|
||||
foam = mix((foam1 + foam2) * m_FoamIntensity , vec4(0.0),
|
||||
(depth2 - m_FoamExistence.x) / (m_FoamExistence.y - m_FoamExistence.x)).rgb;
|
||||
}
|
||||
|
||||
|
||||
if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){
|
||||
foam += ((foam1 + foam2) * m_FoamIntensity * m_FoamIntensity * 0.3 *
|
||||
saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb;
|
||||
}
|
||||
foam *= m_LightColor.rgb;
|
||||
#endif
|
||||
|
||||
vec3 specular = vec3(0.0);
|
||||
#ifdef ENABLE_SPECULAR
|
||||
vec3 lightDir=normalize(m_LightDir);
|
||||
vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
|
||||
float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5);
|
||||
specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2)));
|
||||
specular += specular * 25.0 * saturate(m_Shininess - 0.05);
|
||||
//foam does not shine
|
||||
specular=specular * m_LightColor.rgb - (5.0 * foam);
|
||||
#endif
|
||||
|
||||
color = mix(refraction, reflection, fresnel);
|
||||
color = mix(refraction, color, saturate(depth * m_ShoreHardness));
|
||||
color = saturate(color + max(specular, foam ));
|
||||
color = mix(refraction, color, saturate(depth* m_FoamHardness));
|
||||
|
||||
|
||||
// XXX: HACK ALERT:
|
||||
// We trick the GeForces to think they have
|
||||
// to calculate the derivatives for all these pixels by using step()!
|
||||
// That way we won't get pixels around the edges of the terrain,
|
||||
// Where the derivatives are undefined
|
||||
return vec4(mix(color, color2, step(level, position.y)), 1.0);
|
||||
}
|
||||
|
||||
void main(){
|
||||
setGlobals();
|
||||
#ifdef RESOLVE_MS
|
||||
vec4 color = vec4(0.0);
|
||||
for (int i = 0; i < m_NumSamples; i++){
|
||||
color += main_multiSample(i);
|
||||
}
|
||||
gl_FragColor = color / float(m_NumSamples);
|
||||
#else
|
||||
gl_FragColor = main_multiSample(0);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/gravel1/Gravel040_1K-PNG_NormalGL.png","displacementMap":"Textures/gravel1/Gravel040_1K-PNG_Displacement.png","roughnessMap":"Textures/gravel1/Gravel040_1K-PNG_Roughness.png","aoMap":"Textures/gravel1/Gravel040_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/gras2/Ground003_1K-PNG_NormalGL.png","displacementMap":"Textures/gras2/Ground003_1K-PNG_Displacement.png","roughnessMap":"Textures/gras2/Ground003_1K-PNG_Roughness.png","aoMap":""}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/leaves2/Ground019_1K-PNG_NormalGL.png","displacementMap":"Textures/leaves2/Ground019_1K-PNG_Displacement.png","roughnessMap":"Textures/leaves2/Ground019_1K-PNG_Roughness.png","aoMap":"Textures/leaves2/Ground019_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/leaves1/Ground023_1K-PNG_NormalGL.png","displacementMap":"Textures/leaves1/Ground023_1K-PNG_Displacement.png","roughnessMap":"Textures/leaves1/Ground023_1K-PNG_Roughness.png","aoMap":"Textures/leaves1/Ground023_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/gras1/Ground037_1K-PNG_NormalGL.png","displacementMap":"Textures/gras1/Ground037_1K-PNG_Displacement.png","roughnessMap":"Textures/gras1/Ground037_1K-PNG_Roughness.png","aoMap":"Textures/gras1/Ground037_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/dirt1/Ground048_1K-PNG_NormalGL.png","displacementMap":"Textures/dirt1/Ground048_1K-PNG_Displacement.png","roughnessMap":"Textures/dirt1/Ground048_1K-PNG_Roughness.png","aoMap":"Textures/dirt1/Ground048_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/sand1/Ground054_1K-PNG_NormalGL.png","displacementMap":"Textures/sand1/Ground054_1K-PNG_Displacement.png","roughnessMap":"Textures/sand1/Ground054_1K-PNG_Roughness.png","aoMap":"Textures/sand1/Ground054_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/sand2/Ground060_1K-PNG_NormalGL.png","displacementMap":"Textures/sand2/Ground060_1K-PNG_Displacement.png","roughnessMap":"Textures/sand2/Ground060_1K-PNG_Roughness.png","aoMap":"Textures/sand2/Ground060_1K-PNG_AmbientOcclusion.png"}
|
||||
@@ -0,0 +1 @@
|
||||
{"normalMap":"Textures/gras3/Ground068_1K-PNG_NormalGL.png","displacementMap":"Textures/gras3/Ground068_1K-PNG_Displacement.png","roughnessMap":"Textures/gras3/Ground068_1K-PNG_Roughness.png","aoMap":"Textures/gras3/Ground068_1K-PNG_AmbientOcclusion.png"}
|
||||