Weiter gearbeitet

This commit is contained in:
2026-06-16 07:03:08 +02:00
parent a80269e681
commit a369647e9c
531 changed files with 8327 additions and 1381 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -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 {
@@ -23,6 +27,7 @@ MaterialDef Grass {
Defines {
HAS_COLORMAP : ColorMap
HAS_NORMALMAP : NormalMap
}
}
}

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

@@ -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
}
}
}

View File

@@ -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 {

View File

@@ -1,21 +1,71 @@
MaterialDef Voxel {
MaterialParameters {
Texture2D Tex0
Texture2D Tex1
Texture2D Tex2
Texture2D Tex3
Float TexScale : 4.0
Texture2D TexFlat
Texture2D TexSteep
Texture2D TexCeil
Texture2D NormalMapFlat
Texture2D NormalMapSteep
Texture2D NormalMapCeil
Texture2D DisplacementMapFlat
Texture2D DisplacementMapSteep
Texture2D DisplacementMapCeil
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
NormalMatrix
}
Defines {
HAS_NM_FLAT : NormalMapFlat
HAS_NM_STEEP : NormalMapSteep
HAS_NM_CEIL : NormalMapCeil
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_NM_CEIL : NormalMapCeil
HAS_DISP_FLAT : DisplacementMapFlat
HAS_DISP_STEEP : DisplacementMapSteep
HAS_DISP_CEIL : DisplacementMapCeil
HAS_LIGHTDIR : LightDir
HAS_SCENE_LIGHT : SunColor
}
RenderState {

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

@@ -1,15 +0,0 @@
#Mon Jun 08 11:09:04 CEST 2026
castShadow=true
category=
name=FernPlantV2
pivotOffsetY=0.0
placementOffsetY=0.0
randomScaleMax=1.0
randomScaleMin=1.0
receiveShadow=true
scaleX=0.002
scaleY=0.002
scaleZ=0.002
solid=false
tags=
uniformScale=true

View File

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

View File

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

View File

@@ -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;
}

View File

@@ -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;
}

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);
}

View File

@@ -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);
}

View File

@@ -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
}

View File

@@ -1,54 +1,125 @@
uniform sampler2D m_Tex0;
uniform sampler2D m_Tex1;
uniform sampler2D m_Tex2;
uniform sampler2D m_Tex3;
uniform sampler2D m_TexFlat;
uniform sampler2D m_TexSteep;
uniform sampler2D m_TexCeil;
uniform float m_TexScale;
#ifdef HAS_NM_FLAT
uniform sampler2D m_NormalMapFlat;
#endif
#ifdef HAS_NM_STEEP
uniform sampler2D m_NormalMapSteep;
#endif
#ifdef HAS_NM_CEIL
uniform sampler2D m_NormalMapCeil;
#endif
in vec3 vWorldPos;
in vec3 vNormal;
in vec4 vMatWeights;
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 blendWeights = abs(vNormal);
blendWeights = max(blendWeights - 0.2, 0.0);
blendWeights /= (blendWeights.x + blendWeights.y + blendWeights.z + 0.001);
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;
vec4 col = vec4(0.0);
// Flach ab ~11° Gefälle (20% grade, normal.y≈0.98); Fels darunter.
float flatBlend = smoothstep(0.94, 0.99, vNormal.y);
float ceilBlend = 1.0 - smoothstep(-0.6, -0.3, vNormal.y);
float steepBlend = max(0.0, 1.0 - flatBlend - ceilBlend);
float w0 = vMatWeights.r;
if (w0 > 0.001) {
col += w0 * (texture(m_Tex0, uvX) * blendWeights.x
+ texture(m_Tex0, uvY) * blendWeights.y
+ texture(m_Tex0, uvZ) * blendWeights.z);
}
float w1 = vMatWeights.g;
if (w1 > 0.001) {
col += w1 * (texture(m_Tex1, uvX) * blendWeights.x
+ texture(m_Tex1, uvY) * blendWeights.y
+ texture(m_Tex1, uvZ) * blendWeights.z);
}
float w2 = vMatWeights.b;
if (w2 > 0.001) {
col += w2 * (texture(m_Tex2, uvX) * blendWeights.x
+ texture(m_Tex2, uvY) * blendWeights.y
+ texture(m_Tex2, uvZ) * blendWeights.z);
}
float w3 = vMatWeights.a;
if (w3 > 0.001) {
col += w3 * (texture(m_Tex3, uvX) * blendWeights.x
+ texture(m_Tex3, uvY) * blendWeights.y
+ texture(m_Tex3, uvZ) * blendWeights.z);
}
// Flat: reines XZ-UV wie das Terrain (uvY = worldPos.xz / texScale), kein Triplanar.
// Steep/Ceil: Triplanar bleibt, da es dort keine eindeutige Projektion gibt.
vec4 col = texture(m_TexFlat, uvY) * flatBlend
+ triplanar(m_TexSteep, uvX, uvY, uvZ, bw) * steepBlend
+ triplanar(m_TexCeil, uvX, uvY, uvZ, bw) * ceilBlend;
vec3 lightDir = normalize(vec3(0.5, 1.0, 0.3));
float diff = max(dot(vNormal, lightDir), 0.0) * 0.7 + 0.3;
// Geometrie-Normale für Beleuchtung, ggf. durch Normal-Map ersetzt.
vec3 N = normalize(vNormal);
outColor = vec4(col.rgb * diff, col.a);
#if defined(HAS_NM_FLAT) || defined(HAS_NM_STEEP) || defined(HAS_NM_CEIL)
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;
// Y-Projektion RNM (identisch mit triplanarNormal Y-Achse bei bw.y=1)
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
#ifdef HAS_NM_CEIL
if (ceilBlend > 0.001) {
pertN += triplanarNormal(m_NormalMapCeil, uvX, uvY, uvZ, bw, N) * ceilBlend;
totalBlend += ceilBlend;
}
#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;
}

View 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;
}
}

View 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);
}

View File

@@ -1,19 +1,15 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldMatrix;
uniform mat3 g_NormalMatrix;
in vec3 inPosition;
in vec3 inNormal;
in vec4 inColor; // material blend weights (r=tex0, g=tex1, b=tex2, a=tex3)
out vec3 vWorldPos;
out vec3 vNormal;
out vec4 vMatWeights;
void main() {
vec4 worldPos = g_WorldMatrix * vec4(inPosition, 1.0);
vWorldPos = worldPos.xyz;
vNormal = normalize(g_NormalMatrix * inNormal);
vMatWeights = inColor;
vNormal = normalize(mat3(g_WorldMatrix) * inNormal);
gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}

View 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);
}

View File

@@ -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"}

View File

@@ -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":""}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -0,0 +1 @@
{"normalMap":"Textures/dirt2/Ground079S_1K-PNG_NormalGL.png","displacementMap":"Textures/dirt2/Ground079S_1K-PNG_Displacement.png","roughnessMap":"Textures/dirt2/Ground079S_1K-PNG_Roughness.png","aoMap":"Textures/dirt2/Ground079S_1K-PNG_AmbientOcclusion.png"}

View File

@@ -0,0 +1 @@
{"normalMap":"Textures/rock2/Rock030_1K-PNG_NormalGL.png","displacementMap":"Textures/rock2/Rock030_1K-PNG_Displacement.png","roughnessMap":"Textures/rock2/Rock030_1K-PNG_Roughness.png","aoMap":"Textures/rock2/Rock030_1K-PNG_AmbientOcclusion.png"}

View File

@@ -0,0 +1 @@
{"normalMap":"Textures/rock1/Rock033_1K-PNG_NormalGL.png","displacementMap":"Textures/rock1/Rock033_1K-PNG_Displacement.png","roughnessMap":"Textures/rock1/Rock033_1K-PNG_Roughness.png","aoMap":"Textures/rock1/Rock033_1K-PNG_AmbientOcclusion.png"}

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