update
This commit is contained in:
@@ -1,113 +1,38 @@
|
||||
extends RefCounted
|
||||
## Materialien aus Regeln, ohne eine einzige Datei. Je Stoff ein Eintrag:
|
||||
## Farbverlauf, Rauschart, Reliefstärke, Rauheit, Maßstab. Daraus baut
|
||||
## `mach()` ein StandardMaterial3D mit drei zur Laufzeit erzeugten Texturen:
|
||||
## Farbe (Rauschen durch einen Farbverlauf), Relief (dasselbe Rauschen als
|
||||
## Normalenkarte) und Rauheit. Das Relief ist der Unterschied zwischen
|
||||
## "gemustertes Plastik" und Filz, Holz, Messing.
|
||||
##
|
||||
## Materialien für den Low-Poly-Look: eine flache Farbe, matt, kein Muster,
|
||||
## kein Relief. Was "Holz" von "Filz" unterscheidet, ist die Farbe und die
|
||||
## Form - nicht eine Textur. Die Palette ist pastellig und satt, wie Knete.
|
||||
## Kein class_name: den Klassencache baut nur der Editor, headless fehlt er.
|
||||
|
||||
const STOFFE := {
|
||||
"filz": {
|
||||
# Feiner Flaum, kaum Relief, ganz matt. Grobes, glänzendes Relief sah
|
||||
# nach nassem Moos aus.
|
||||
"farben": [Color(0.06, 0.18, 0.11), Color(0.08, 0.23, 0.14), Color(0.10, 0.26, 0.16)],
|
||||
"art": FastNoiseLite.TYPE_SIMPLEX_SMOOTH, "freq": 0.35, "oktaven": 3,
|
||||
"relief": 0.12, "rauheit": [0.96, 1.0], "metall": 0.0, "uv": Vector3(14, 14, 1),
|
||||
"glanz": 0.05,
|
||||
},
|
||||
"holz": {
|
||||
"farben": [Color(0.20, 0.12, 0.06), Color(0.36, 0.23, 0.11), Color(0.46, 0.31, 0.16)],
|
||||
"art": FastNoiseLite.TYPE_SIMPLEX, "freq": 0.03, "oktaven": 5, "warp": 25.0,
|
||||
"relief": 0.6, "rauheit": [0.45, 0.75], "metall": 0.0,
|
||||
# stark gestreckt: aus dem Rauschen wird Maserung
|
||||
"uv": Vector3(1.0, 9.0, 1.0),
|
||||
},
|
||||
"holz_dunkel": {
|
||||
"farben": [Color(0.14, 0.06, 0.04), Color(0.30, 0.12, 0.07), Color(0.40, 0.18, 0.10)],
|
||||
"art": FastNoiseLite.TYPE_SIMPLEX, "freq": 0.03, "oktaven": 5, "warp": 25.0,
|
||||
"relief": 0.5, "rauheit": [0.4, 0.7], "metall": 0.0, "uv": Vector3(1.0, 7.0, 1.0),
|
||||
},
|
||||
"messing": {
|
||||
"farben": [Color(0.55, 0.40, 0.14), Color(0.80, 0.62, 0.26), Color(0.95, 0.80, 0.42)],
|
||||
"art": FastNoiseLite.TYPE_CELLULAR, "freq": 0.12, "oktaven": 2,
|
||||
"relief": 0.25, "rauheit": [0.2, 0.5], "metall": 0.9, "uv": Vector3(3, 3, 1),
|
||||
},
|
||||
"knochen": {
|
||||
# Farbe kommt von den Vertexfarben (Körper hell, Augen dunkel); hier
|
||||
# nur feine Dellen und eine warme, leicht fettige Oberfläche.
|
||||
"farben": [], "art": FastNoiseLite.TYPE_SIMPLEX_SMOOTH, "freq": 0.25, "oktaven": 3,
|
||||
"relief": 0.2, "rauheit": [0.45, 0.65], "metall": 0.0, "uv": Vector3(4, 4, 1),
|
||||
},
|
||||
const FARBEN := {
|
||||
"filz": Color(0.33, 0.70, 0.42),
|
||||
"filz_dunkel": Color(0.26, 0.60, 0.36),
|
||||
"holz": Color(0.86, 0.68, 0.46),
|
||||
"holz_dunkel": Color(0.76, 0.42, 0.30),
|
||||
"holz_rand": Color(0.60, 0.40, 0.26),
|
||||
"messing": Color(0.96, 0.80, 0.36),
|
||||
"knochen": Color(0.99, 0.96, 0.90),
|
||||
"boden": Color(0.90, 0.84, 0.72),
|
||||
"glas": Color(1.0, 0.92, 0.55),
|
||||
}
|
||||
|
||||
static var _fertig: Dictionary = {} ## name -> StandardMaterial3D, einmal gebaut
|
||||
static var _fertig: Dictionary = {}
|
||||
|
||||
|
||||
static func _rauschen(r: Dictionary, seed: int) -> FastNoiseLite:
|
||||
var n := FastNoiseLite.new()
|
||||
n.seed = seed
|
||||
n.noise_type = r.art
|
||||
n.frequency = r.freq
|
||||
n.fractal_octaves = r.oktaven
|
||||
if r.has("warp"):
|
||||
n.domain_warp_enabled = true
|
||||
n.domain_warp_amplitude = r.warp
|
||||
return n
|
||||
|
||||
|
||||
static func _textur(n: FastNoiseLite, groesse: int) -> NoiseTexture2D:
|
||||
var t := NoiseTexture2D.new()
|
||||
t.noise = n
|
||||
t.width = groesse
|
||||
t.height = groesse
|
||||
t.seamless = true
|
||||
t.generate_mipmaps = true
|
||||
return t
|
||||
|
||||
|
||||
## Baut das Material nach Regel `name`. Gleiche Regel, gleiches Material:
|
||||
## alle Becher teilen eine Instanz, so bleibt es ein Renderobjekt je Stoff.
|
||||
## Ein Stoff, eine Instanz: gleiche Farbe teilt das Material.
|
||||
static func mach(name: String) -> StandardMaterial3D:
|
||||
if _fertig.has(name):
|
||||
return _fertig[name]
|
||||
var r: Dictionary = STOFFE[name]
|
||||
var m := StandardMaterial3D.new()
|
||||
var basis := _rauschen(r, name.hash() % 1000)
|
||||
|
||||
if not r.farben.is_empty():
|
||||
var verlauf := Gradient.new()
|
||||
var farben: Array = r.farben
|
||||
verlauf.offsets = PackedFloat32Array([0.0, 0.5, 1.0])
|
||||
verlauf.colors = PackedColorArray([farben[0], farben[1], farben[2]])
|
||||
var farbe := _textur(basis, 256)
|
||||
farbe.color_ramp = verlauf
|
||||
m.albedo_texture = farbe
|
||||
else:
|
||||
m.vertex_color_use_as_albedo = true
|
||||
|
||||
var relief := _textur(basis, 256)
|
||||
relief.as_normal_map = true
|
||||
relief.bump_strength = float(r.relief) * 8.0
|
||||
m.normal_enabled = true
|
||||
m.normal_texture = relief
|
||||
m.normal_scale = 1.0
|
||||
|
||||
# Rauheit schwankt mit dem Rauschen zwischen den zwei Werten.
|
||||
var rau := _textur(_rauschen(r, name.hash() % 1000 + 7), 128)
|
||||
m.roughness_texture = rau
|
||||
m.roughness_texture_channel = BaseMaterial3D.TEXTURE_CHANNEL_RED
|
||||
m.roughness = float(r.rauheit[1])
|
||||
m.metallic = float(r.metall)
|
||||
m.metallic_specular = float(r.get("glanz", 0.5 if r.metall > 0.5 else 0.3))
|
||||
m.uv1_scale = r.uv
|
||||
m.texture_filter = BaseMaterial3D.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC
|
||||
m.albedo_color = FARBEN[name]
|
||||
m.roughness = 0.85
|
||||
m.metallic = 0.0
|
||||
# Fast kein Glanzpunkt: Knete glänzt nicht, sie leuchtet vom Licht her.
|
||||
m.metallic_specular = 0.15
|
||||
_fertig[name] = m
|
||||
return m
|
||||
|
||||
|
||||
## Eigene Instanz, wenn ein Objekt Farbe oder Leuchten ändern muss.
|
||||
static func eigene(name: String) -> StandardMaterial3D:
|
||||
return mach(name).duplicate()
|
||||
|
||||
@@ -116,6 +41,10 @@ static func filz() -> StandardMaterial3D:
|
||||
return mach("filz")
|
||||
|
||||
|
||||
static func filz_dunkel() -> StandardMaterial3D:
|
||||
return mach("filz_dunkel")
|
||||
|
||||
|
||||
static func holz() -> StandardMaterial3D:
|
||||
return mach("holz")
|
||||
|
||||
@@ -124,22 +53,36 @@ static func holz_dunkel() -> StandardMaterial3D:
|
||||
return mach("holz_dunkel")
|
||||
|
||||
|
||||
static func boden() -> StandardMaterial3D:
|
||||
return mach("boden")
|
||||
|
||||
|
||||
static func messing(emission := 0.0) -> StandardMaterial3D:
|
||||
if emission <= 0.0:
|
||||
return mach("messing")
|
||||
var m := eigene("messing")
|
||||
if emission > 0.0:
|
||||
m.emission_enabled = true
|
||||
m.emission = Color(1.0, 0.75, 0.30)
|
||||
m.emission_energy_multiplier = emission
|
||||
m.emission_enabled = true
|
||||
m.emission = Color(1.0, 0.80, 0.35)
|
||||
m.emission_energy_multiplier = emission
|
||||
return m
|
||||
|
||||
|
||||
## Würfel: Farbe kommt aus den Vertexfarben (Körper hell, Augen dunkel).
|
||||
static func knochen() -> StandardMaterial3D:
|
||||
return mach("knochen")
|
||||
if _fertig.has("knochen"):
|
||||
return _fertig["knochen"]
|
||||
var m := StandardMaterial3D.new()
|
||||
m.vertex_color_use_as_albedo = true
|
||||
m.roughness = 0.8
|
||||
m.metallic_specular = 0.15
|
||||
_fertig["knochen"] = m
|
||||
return m
|
||||
|
||||
|
||||
## Zonenrand: Holz, das leuchten kann, wenn der Platz dran ist.
|
||||
## Zonenrand: dunkleres Holz als die Becher, damit sich beides trennt; kann
|
||||
## leuchten, wenn der Platz dran ist.
|
||||
static func rand() -> StandardMaterial3D:
|
||||
var m := eigene("holz")
|
||||
var m := eigene("holz_rand")
|
||||
m.emission = Color(1.0, 0.78, 0.30)
|
||||
m.emission_enabled = false
|
||||
return m
|
||||
|
||||
Reference in New Issue
Block a user