Rock Generator 2.8.0: Cavity in Vertex-Farben (texturfreier Weg)
Idee kam vom User: die Steine ueber "smart materials" in UE loesen statt ueber gebackene Texturen. Prozedurales Noise/Voronoi im Shader waere zu teuer (laeuft pro Pixel), aber der Kern der Idee traegt - deshalb dieser Weg: Neue Option "Cavity in Vertex-Farben": schreibt Cavity/AO plus optionalen Hoehen-Verlauf in das Farb-Attribut "Cavity" (vertex_color_dirt + eigene Nachbearbeitung fuer Staerke und Verlauf). Das Material braucht damit KEINE Textur: Base Color = Farbton x VertexColor, dazu Kantenlicht und Schattentint. Gegenueber Triplanar sitzen die dunklen Fugen dadurch auf den ECHTEN Kanten des Meshes statt darueberzuschweben - genau das passiert in der Genshin-Referenz. Verifiziert: Attribut wird angelegt, Wertebereich 0.250..0.947 (echter Kontrast), und es ueberlebt den FBX-Roundtrip UNVERAENDERT (gleicher Bereich nach Import). Regler: Cavity-Staerke, Hoehen-Verlauf, Weichzeichnen. Neuer Test tests/test_vertex_cavity.py. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
bl_info = {
|
||||
"name": "Stylized Rock Generator",
|
||||
"author": "D4rkst3r",
|
||||
"version": (2, 7, 0),
|
||||
"version": (2, 8, 0),
|
||||
"blender": (4, 2, 0),
|
||||
"location": "View3D > Sidebar > Rock Gen",
|
||||
"description": (
|
||||
@@ -60,6 +60,7 @@ PRESET_KEYS = (
|
||||
"shading_mode", "autosmooth_angle",
|
||||
"randomize_shape", "noise_scale_max", "displace_strength_max", "nonuniform_scale",
|
||||
"flatten_bottom", "flatten_ratio", "set_origin_bottom", "keep_size",
|
||||
"bake_vertex_cavity", "cavity_strength", "cavity_blur", "cavity_gradient",
|
||||
"use_class_size", "base_size",
|
||||
)
|
||||
|
||||
@@ -453,6 +454,65 @@ def _apply_random_transform(context, obj, settings, rng):
|
||||
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
||||
|
||||
|
||||
def _bake_vertex_cavity(context, obj, settings):
|
||||
"""Cavity + Hoehen-Verlauf in die VERTEX-FARBEN backen.
|
||||
|
||||
Warum: das Material braucht damit KEINE Textur. Base Color = Farbton x
|
||||
Vertex-Farbe, dazu Kantenlicht und Schattentint im Shader - genau der
|
||||
Genshin-Aufbau. Ausserdem sitzen die dunklen Fugen auf den ECHTEN Kanten
|
||||
des Meshes, statt per Triplanar darueberzuschweben.
|
||||
|
||||
Aufloesung haengt an der Vertex-Dichte; fuer flaechige Platten reicht das,
|
||||
fuer feine Struktur nicht (dann Textur nehmen).
|
||||
"""
|
||||
me = obj.data
|
||||
layer = me.color_attributes.get("Cavity")
|
||||
if layer is None:
|
||||
layer = me.color_attributes.new(name="Cavity", type='BYTE_COLOR', domain='CORNER')
|
||||
me.color_attributes.active_color = layer
|
||||
me.color_attributes.render_color_index = me.color_attributes.find("Cavity")
|
||||
|
||||
_deselect_all(context)
|
||||
context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
try:
|
||||
bpy.ops.paint.vertex_color_set(color=(1.0, 1.0, 1.0, 1.0))
|
||||
except RuntimeError:
|
||||
pass
|
||||
try:
|
||||
bpy.ops.paint.vertex_color_dirt(
|
||||
blur_strength=1.0,
|
||||
blur_iterations=settings.cavity_blur,
|
||||
clean_angle=3.14159,
|
||||
dirt_angle=0.0,
|
||||
dirt_only=False,
|
||||
normalize=True,
|
||||
)
|
||||
except RuntimeError as exc:
|
||||
raise RockGenError("Vertex-Cavity fehlgeschlagen: %s" % exc)
|
||||
|
||||
# Staerke regeln + optionaler Hoehen-Verlauf (unten dunkler, wie in der
|
||||
# Referenz). Beides direkt auf den Farbwerten, das ist schnell genug.
|
||||
zs = [v.co.z for v in me.vertices]
|
||||
if not zs:
|
||||
return
|
||||
zmin, zmax = min(zs), max(zs)
|
||||
span = max(zmax - zmin, 1e-6)
|
||||
amt = settings.cavity_strength
|
||||
grad = settings.cavity_gradient
|
||||
data = layer.data
|
||||
for poly in me.polygons:
|
||||
for li in poly.loop_indices:
|
||||
vi = me.loops[li].vertex_index
|
||||
c = data[li].color
|
||||
val = 1.0 - (1.0 - c[0]) * amt # Cavity abschwaechen
|
||||
if grad > 0.0:
|
||||
t = (me.vertices[vi].co.z - zmin) / span
|
||||
val *= (1.0 - grad) + grad * (0.35 + 0.65 * t)
|
||||
val = max(0.0, min(1.0, val))
|
||||
data[li].color = (val, val, val, 1.0)
|
||||
|
||||
|
||||
def _apply_shading(context, obj, settings):
|
||||
"""Setzt den Shading-Look: FLAT (facettiert), SMOOTH oder AUTO (nach Winkel)."""
|
||||
_deselect_all(context)
|
||||
@@ -607,6 +667,8 @@ def make_one_rock(context, settings, index, batch_count=1):
|
||||
_apply_hardsurface(context, obj, settings)
|
||||
_apply_random_transform(context, obj, settings, rng)
|
||||
_apply_shading(context, obj, settings)
|
||||
if settings.bake_vertex_cavity:
|
||||
_bake_vertex_cavity(context, obj, settings)
|
||||
if settings.set_origin_bottom:
|
||||
_set_origin_bottom(context, obj)
|
||||
if settings.assign_material:
|
||||
@@ -730,6 +792,27 @@ class RockGenSettings(PropertyGroup):
|
||||
description="Setzt den Origin auf die Unterseiten-Mitte (sauberes Aufstellen in UE)",
|
||||
)
|
||||
|
||||
# --- Vertex-Cavity (texturfreier Weg) ---
|
||||
bake_vertex_cavity: BoolProperty(
|
||||
name="Cavity in Vertex-Farben", default=False,
|
||||
description=("Backt Cavity/AO in die Vertex-Farben (Attribut 'Cavity'). "
|
||||
"Das Material braucht dann KEINE Textur: Base Color = Farbton "
|
||||
"x Vertex-Farbe, Rest ueber Kantenlicht und Schattentint"),
|
||||
)
|
||||
cavity_strength: FloatProperty(
|
||||
name="Cavity-Staerke", default=0.7, min=0.0, max=1.0,
|
||||
description="0 = alles weiss, 1 = volle Abdunklung in den Vertiefungen",
|
||||
)
|
||||
cavity_blur: IntProperty(
|
||||
name="Weichzeichnen", default=1, min=0, max=5,
|
||||
description="Glaettet den Cavity-Verlauf ueber benachbarte Vertices",
|
||||
)
|
||||
cavity_gradient: FloatProperty(
|
||||
name="Hoehen-Verlauf", default=0.35, min=0.0, max=1.0,
|
||||
description=("Dunkelt den Stein nach unten hin ab (wie in der Referenz). "
|
||||
"0 = aus"),
|
||||
)
|
||||
|
||||
# --- Material ---
|
||||
assign_material: BoolProperty(
|
||||
name="Material zuweisen", default=False,
|
||||
@@ -1567,6 +1650,15 @@ class VIEW3D_PT_rock_generator(Panel):
|
||||
sub.prop(settings, "lod_count")
|
||||
sub.prop(settings, "lod_ratio_step")
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Vertex-Cavity (ohne Textur)")
|
||||
box.prop(settings, "bake_vertex_cavity")
|
||||
sub = box.column(align=True)
|
||||
sub.enabled = settings.bake_vertex_cavity
|
||||
sub.prop(settings, "cavity_strength")
|
||||
sub.prop(settings, "cavity_gradient")
|
||||
sub.prop(settings, "cavity_blur")
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Material")
|
||||
box.prop(settings, "assign_material")
|
||||
|
||||
Reference in New Issue
Block a user