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 }