This commit is contained in:
Matteo Sonaglioni
2026-03-12 22:41:49 +01:00
parent 6674dcf26f
commit ed40bb6ed4
37 changed files with 24 additions and 995 deletions

View File

@@ -1,29 +0,0 @@
shader_type canvas_item;
render_mode blend_mul;
// Colori esposti nell'Inspector
uniform vec4 color_mattina : source_color = vec4(1.0, 0.9, 0.8, 1.0);
uniform vec4 color_pomeriggio : source_color = vec4(1.0, 0.6, 0.2, 1.0);
uniform vec4 color_notte : source_color = vec4(0.1, 0.1, 0.3, 1.0);
// Parametro fluido: 1.0 = Mattina, 2.0 = Pomeriggio, 3.0 = Notte
uniform float tempo_giorno : hint_range(1.0, 3.0) = 1.0;
void fragment() {
vec4 tex_color = texture(TEXTURE, UV);
vec4 final_tint;
if (tempo_giorno <= 2.0) {
// Transizione tra Mattina (1.0) e Pomeriggio (2.0)
// mix(A, B, t) dove t va da 0 a 1
float t = tempo_giorno - 1.0;
final_tint = mix(color_mattina, color_pomeriggio, t);
} else {
// Transizione tra Pomeriggio (2.0) e Notte (3.0)
float t = tempo_giorno - 2.0;
final_tint = mix(color_pomeriggio, color_notte, t);
}
// Applica il colore finale con blend_mul (moltiplicazione)
COLOR = tex_color * final_tint;
}

View File

@@ -1 +0,0 @@
uid://4n16lkrav6bj

View File

@@ -1,113 +0,0 @@
shader_type spatial;
render_mode specular_disabled, ambient_light_disabled;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_nearest;
uniform sampler2D NORMAL_TEXTURE : hint_normal_roughness_texture, filter_nearest;
uniform float lightIntensity = 1.25;
uniform float lineAlpha = 0.7;
uniform bool useLighting = true;
uniform float lineHighlight = 0.2;
uniform float lineShadow = 0.55;
varying vec2 screenUV;
varying float lineMask;
float GetLinearDepth(vec2 sUV, sampler2D depthTexture, mat4 invProjectionMat, float mask){
// Raw depth to linear depth code from:
// https://docs.godotengine.org/en/latest/tutorials/shaders/advanced_postprocessing.html
float depth = texture(depthTexture, sUV).x * mask;
vec3 ndc = vec3(sUV * 2.0 - 1.0, depth);
vec4 view = invProjectionMat * vec4(ndc, 1.0);
view.xyz /= view.w;
return -view.z;
}
vec3 GetNormal(vec2 uv, sampler2D normalTexture, float mask){
vec3 normal = texture(normalTexture, uv).rgb;
normal = normal * 2.0 - 1.0 * mask;
return normal;
}
float NormalEdgeIndicator(vec3 normalEdgeBias, vec3 normal, vec3 neighborNormal, float depthDifference){
//From Kody King: https://threejs.org/examples/webgl_postprocessing_pixel.html
float normalDifference = dot(normal - neighborNormal, normalEdgeBias);
float normalIndicator = clamp(smoothstep(-.01, .01, normalDifference), 0.0, 1.0);
float depthIndicator = clamp(sign(depthDifference * .25 + .0025), 0.0, 1.0);
return (1.0 - dot(normal, neighborNormal)) * depthIndicator * normalIndicator;
}
void vertex(){
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
}
void fragment() {
vec2 texelSize = 1.0 / VIEWPORT_SIZE.xy;
screenUV = SCREEN_UV;
// UV offsets
vec2 UVOffsets[4];
UVOffsets[0] = SCREEN_UV + vec2(0.0, -1.0) * texelSize;
UVOffsets[1] = SCREEN_UV + vec2(0.0, 1.0) * texelSize;
UVOffsets[2] = SCREEN_UV + vec2(1.0, 0.0) * texelSize;
UVOffsets[3] = SCREEN_UV + vec2(-1.0, 0.0) * texelSize;
// Using alpha channel (screen roughness) to mask objects to not receive outlines
float outlineMask = texture(NORMAL_TEXTURE, SCREEN_UV).a;
outlineMask = ceil(outlineMask); // Objects with Roughness = 0 will not have and outline
// Edge detection with Depth
float depthDifference = 0.0;
float invDepthDifference = 0.5;
float depth = GetLinearDepth(SCREEN_UV, DEPTH_TEXTURE, INV_PROJECTION_MATRIX, outlineMask);
for (int i = 0; i < UVOffsets.length(); i++){
float dOff = GetLinearDepth(UVOffsets[i],DEPTH_TEXTURE, INV_PROJECTION_MATRIX, outlineMask);
depthDifference += clamp(dOff - depth, 0.0, 1.0);
invDepthDifference += depth - dOff;
}
invDepthDifference = clamp(invDepthDifference, 0.0, 1.0);
invDepthDifference = clamp(smoothstep(0.9, 0.9, invDepthDifference) * 10.0 , 0.0, 1.0);
depthDifference = smoothstep(0.25, 0.3, depthDifference);
// Edge detection with Normals
float normalDifference = 0.;
vec3 normalEdgeBias = vec3(1.0, 1.0, 1.0);
vec3 normal = GetNormal(SCREEN_UV, NORMAL_TEXTURE, outlineMask);
for (int i = 0; i < UVOffsets.length(); i++){
vec3 nOff = GetNormal(UVOffsets[i],NORMAL_TEXTURE, outlineMask);
normalDifference += NormalEdgeIndicator(normalEdgeBias, normal, nOff, depthDifference);
}
normalDifference = smoothstep(0.2, 0.2, normalDifference);
normalDifference = clamp(normalDifference - invDepthDifference, 0.0, 1.0);
ALBEDO = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
lineMask = clamp(0.1, lineAlpha, (depthDifference + normalDifference * 5.0));
if (!useLighting){
ALBEDO += clamp((normalDifference - depthDifference), 0.0, 1.0) * lineHighlight;
ALBEDO -= ALBEDO * depthDifference * lineShadow;
}
}
void light (){
if (useLighting){
vec4 normal = texture(NORMAL_TEXTURE, screenUV);
normal = normal * 2.0 - 1.0;
// Calculate light direction
float dotNL = dot(normal.rgb, LIGHT);
dotNL = pow(dotNL, 2.5);
dotNL = clamp(dotNL, 0.0, 1.0);
if(LIGHT_IS_DIRECTIONAL)
DIFFUSE_LIGHT += mix(vec3(1.0), dotNL * LIGHT_COLOR * lightIntensity, lineMask);
}
else
DIFFUSE_LIGHT = vec3(1.0);
}

View File

@@ -1 +0,0 @@
uid://vfm72f8fcvup

View File

@@ -1,113 +0,0 @@
shader_type spatial;
render_mode specular_disabled, ambient_light_disabled;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_nearest;
uniform sampler2D NORMAL_TEXTURE : hint_normal_roughness_texture, filter_nearest;
uniform float lightIntensity = 1.25;
uniform float lineAlpha = 0.7;
uniform bool useLighting = true;
uniform float lineHighlight = 0.2;
uniform float lineShadow = 0.55;
varying vec2 screenUV;
varying float lineMask;
float GetLinearDepth(vec2 sUV, sampler2D depthTexture, mat4 invProjectionMat, float mask){
// Raw depth to linear depth code from:
// https://docs.godotengine.org/en/latest/tutorials/shaders/advanced_postprocessing.html
float depth = texture(depthTexture, sUV).x * mask;
vec3 ndc = vec3(sUV * 2.0 - 1.0, depth);
vec4 view = invProjectionMat * vec4(ndc, 1.0);
view.xyz /= view.w;
return -view.z;
}
vec3 GetNormal(vec2 uv, sampler2D normalTexture, float mask){
vec3 normal = texture(normalTexture, uv).rgb;
normal = normal * 2.0 - 1.0 * mask;
return normal;
}
float NormalEdgeIndicator(vec3 normalEdgeBias, vec3 normal, vec3 neighborNormal, float depthDifference){
//From Kody King: https://threejs.org/examples/webgl_postprocessing_pixel.html
float normalDifference = dot(normal - neighborNormal, normalEdgeBias);
float normalIndicator = clamp(smoothstep(-.01, .01, normalDifference), 0.0, 1.0);
float depthIndicator = clamp(sign(depthDifference * .25 + .0025), 0.0, 1.0);
return (1.0 - dot(normal, neighborNormal)) * depthIndicator * normalIndicator;
}
void vertex(){
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
}
void fragment() {
vec2 texelSize = 1.0 / VIEWPORT_SIZE.xy;
screenUV = SCREEN_UV;
// UV offsets
vec2 UVOffsets[4];
UVOffsets[0] = SCREEN_UV + vec2(0.0, -1.0) * texelSize;
UVOffsets[1] = SCREEN_UV + vec2(0.0, 1.0) * texelSize;
UVOffsets[2] = SCREEN_UV + vec2(1.0, 0.0) * texelSize;
UVOffsets[3] = SCREEN_UV + vec2(-1.0, 0.0) * texelSize;
// Using alpha channel (screen roughness) to mask objects to not receive outlines
float outlineMask = texture(NORMAL_TEXTURE, SCREEN_UV).a;
outlineMask = ceil(outlineMask); // Objects with Roughness = 0 will not have and outline
// Edge detection with Depth
float depthDifference = 0.0;
float invDepthDifference = 0.5;
float depth = GetLinearDepth(SCREEN_UV, DEPTH_TEXTURE, INV_PROJECTION_MATRIX, outlineMask);
for (int i = 0; i < UVOffsets.length(); i++){
float dOff = GetLinearDepth(UVOffsets[i],DEPTH_TEXTURE, INV_PROJECTION_MATRIX, outlineMask);
depthDifference += clamp(dOff - depth, 0.0, 1.0);
invDepthDifference += depth - dOff;
}
invDepthDifference = clamp(invDepthDifference, 0.0, 1.0);
invDepthDifference = clamp(smoothstep(0.9, 0.9, invDepthDifference) * 10.0 , 0.0, 1.0);
depthDifference = smoothstep(0.25, 0.3, depthDifference);
// Edge detection with Normals
float normalDifference = 0.;
vec3 normalEdgeBias = vec3(1.0, 1.0, 1.0);
vec3 normal = GetNormal(SCREEN_UV, NORMAL_TEXTURE, outlineMask);
for (int i = 0; i < UVOffsets.length(); i++){
vec3 nOff = GetNormal(UVOffsets[i],NORMAL_TEXTURE, outlineMask);
normalDifference += NormalEdgeIndicator(normalEdgeBias, normal, nOff, depthDifference);
}
normalDifference = smoothstep(0.2, 0.2, normalDifference);
normalDifference = clamp(normalDifference - invDepthDifference, 0.0, 1.0);
ALBEDO = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
lineMask = clamp(0.1, lineAlpha, (depthDifference + normalDifference * 5.0));
if (!useLighting){
ALBEDO += clamp((normalDifference - depthDifference), 0.0, 1.0) * lineHighlight;
ALBEDO -= ALBEDO * depthDifference * lineShadow;
}
}
void light (){
if (useLighting){
vec4 normal = texture(NORMAL_TEXTURE, screenUV);
normal = normal * 2.0 - 1.0;
// Calculate light direction
float dotNL = dot(normal.rgb, LIGHT);
dotNL = pow(dotNL, 2.5);
dotNL = clamp(dotNL, 0.0, 1.0);
if(LIGHT_IS_DIRECTIONAL)
DIFFUSE_LIGHT += mix(vec3(1.0), dotNL * LIGHT_COLOR * lightIntensity, lineMask);
}
else
DIFFUSE_LIGHT = vec3(1.0);
}

View File

@@ -1 +0,0 @@
uid://bj20y6cydpck6

View File

@@ -1,66 +0,0 @@
shader_type spatial;
render_mode specular_disabled;
// --- TEXTURE E COLORE BASE ---
uniform sampler2D albedo_texture : source_color, filter_nearest_mipmap;
uniform vec4 color_tint : source_color = vec4(1.0);
// --- CORREZIONE IMMAGINE ---
uniform float saturation : hint_range(0.0, 2.0) = 1.0;
uniform float brightness : hint_range(0.0, 2.0) = 1.0;
// --- LUCE E OMBRA ---
uniform float light_steps = 4.0; // Gradini di luce
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.5; // Quanto è scura l'ombra (0=nera)
// *** NUOVO PARAMETRO ***
// Colore con cui tingere le ombre. Default: Grigio-Bluastro (Cool shadows)
uniform vec4 shadow_tint : source_color = vec4(0.6, 0.6, 0.7, 1.0);
void vertex() {
// Vuoto per prop statici
}
void fragment() {
vec4 tex_color = texture(albedo_texture, UV);
vec3 base_rgb = tex_color.rgb * color_tint.rgb;
// --- SATURAZIONE ---
float luminance = dot(base_rgb, vec3(0.299, 0.587, 0.114));
vec3 saturated_color = mix(vec3(luminance), base_rgb, saturation);
// --- LUMINOSITA' ---
ALBEDO = saturated_color * brightness;
ROUGHNESS = 1.0;
SPECULAR = 0.0;
}
void light() {
// --- CEL SHADING ---
float NdotL = dot(NORMAL, LIGHT);
float light_amount = clamp(NdotL, 0.0, 1.0);
// Gradini
light_amount = ceil(light_amount * light_steps) / light_steps;
// Ombre proiettate (attenuazione)
float shadow = ATTENUATION;
shadow = ceil(shadow * light_steps) / light_steps;
// Calcolo quanta luce totale riceve il pixel (0.0 = ombra totale, 1.0 = luce piena)
float final_light_factor = light_amount * shadow;
// --- IL TRUCCO DEL HUE SHIFT ---
// Invece di moltiplicare solo per la luce, facciamo un mix tra:
// A) Colore in Ombra (Albedo * Tinta Ombra * Intensità minima)
// B) Colore Illuminato (Albedo * Colore Luce)
vec3 lit_color = ALBEDO * LIGHT_COLOR;
vec3 shadowed_color = ALBEDO * shadow_tint.rgb * shadow_intensity; // L'ombra si colora!
// Mischiamo i due stati in base alla luce ricevuta
vec3 final_color = mix(shadowed_color, lit_color, final_light_factor);
DIFFUSE_LIGHT += final_color / PI;
}

View File

@@ -1 +0,0 @@
uid://c8b30c87lfclb

View File

@@ -1,19 +0,0 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://da8erd0d83kog"]
[ext_resource type="Shader" uid="uid://c0dy1aqj1b4q3" path="res://Shaders/trunk_shader.gdshader" id="1_bjiey"]
[ext_resource type="Texture2D" uid="uid://cdlgd0h5qeb7k" path="res://Assets/Textures/Palette_train.png" id="2_e8nia"]
[resource]
render_priority = 0
shader = ExtResource("1_bjiey")
shader_parameter/albedo_color = Color(1, 1, 1, 1)
shader_parameter/albedo_texture = ExtResource("2_e8nia")
shader_parameter/use_texture = true
shader_parameter/uv_scale = Vector2(1, 1)
shader_parameter/light_direction = Vector3(0.5, 1, 0.5)
shader_parameter/light_steps = 4.0
shader_parameter/step_softness = 0.1
shader_parameter/shadow_color = Color(0.4, 0.4, 0.6, 1)
shader_parameter/shadow_offset = 0.0
shader_parameter/emission_color = Color(1, 1, 1, 1)
shader_parameter/emission_energy = 0.0

View File

@@ -1,104 +0,0 @@
[gd_resource type="VisualShader" format=3 uid="uid://dktuskj3gem52"]
[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_don5s"]
default_input_values = [0, Quaternion(0, 0, 0, 0), 1, Quaternion(0, 0, 0, 0)]
op_type = 2
operator = 2
[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_rvu6f"]
default_input_values = [0, Quaternion(0, 0, 0, 0), 1, Quaternion(11133, 12, 12321211, 0)]
op_type = 2
operator = 5
[sub_resource type="VisualShaderNodeVec4Constant" id="VisualShaderNodeVec4Constant_d4ljy"]
constant = Quaternion(1.25, 1.25, 1.25, 1.25)
[sub_resource type="VisualShaderNodeFloatConstant" id="VisualShaderNodeFloatConstant_cc8xj"]
constant = 0.8
[sub_resource type="VisualShaderNodeFloatConstant" id="VisualShaderNodeFloatConstant_lhbqr"]
[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_k2ihi"]
parameter_name = "sColorParameter"
default_value_enabled = true
default_value = Color(0, 0.26666668, 0.53333336, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ttifq"]
noise_type = 0
fractal_type = 3
fractal_octaves = 10
fractal_lacunarity = 1.555
fractal_gain = 1.445
fractal_weighted_strength = 1.0
cellular_jitter = 0.0
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_6ruds"]
width = 1500
height = 1500
noise = SubResource("FastNoiseLite_ttifq")
seamless = true
[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_v5yg7"]
texture = SubResource("NoiseTexture2D_6ruds")
[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_mxguh"]
output_port_for_preview = 0
default_input_values = [0, Quaternion(0, 0, 0, 0), 1, Quaternion(0, 0, 0, 0)]
op_type = 2
[sub_resource type="VisualShaderNodeUVFunc" id="VisualShaderNodeUVFunc_jmfs5"]
default_input_values = [1, Vector2(0.02, 0.02), 2, Vector2(0, 0)]
[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_kiici"]
input_name = "time"
[sub_resource type="FastNoiseLite" id="FastNoiseLite_nj26y"]
noise_type = 2
seed = 1
fractal_type = 0
cellular_distance_function = 1
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_8egqe"]
width = 1500
height = 1500
noise = SubResource("FastNoiseLite_nj26y")
seamless = true
[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_x3kgx"]
texture = SubResource("NoiseTexture2D_8egqe")
[sub_resource type="VisualShaderNodeUVFunc" id="VisualShaderNodeUVFunc_4sw7m"]
default_input_values = [1, Vector2(-0.02, -0.02), 2, Vector2(0, 0)]
[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_itkh5"]
input_name = "time"
[resource]
nodes/fragment/0/position = Vector2(680, 200)
nodes/fragment/2/node = SubResource("VisualShaderNodeColorParameter_k2ihi")
nodes/fragment/2/position = Vector2(-400, 80)
nodes/fragment/3/node = SubResource("VisualShaderNodeTexture_v5yg7")
nodes/fragment/3/position = Vector2(-640, 360)
nodes/fragment/4/node = SubResource("VisualShaderNodeVectorOp_mxguh")
nodes/fragment/4/position = Vector2(80, 140)
nodes/fragment/5/node = SubResource("VisualShaderNodeUVFunc_jmfs5")
nodes/fragment/5/position = Vector2(-920, 460)
nodes/fragment/6/node = SubResource("VisualShaderNodeInput_kiici")
nodes/fragment/6/position = Vector2(-1260, 560)
nodes/fragment/7/node = SubResource("VisualShaderNodeTexture_x3kgx")
nodes/fragment/7/position = Vector2(-640, 720)
nodes/fragment/8/node = SubResource("VisualShaderNodeUVFunc_4sw7m")
nodes/fragment/8/position = Vector2(-920, 780)
nodes/fragment/9/node = SubResource("VisualShaderNodeInput_itkh5")
nodes/fragment/9/position = Vector2(-1260, 880)
nodes/fragment/10/node = SubResource("VisualShaderNodeVectorOp_don5s")
nodes/fragment/10/position = Vector2(-420, 560)
nodes/fragment/11/node = SubResource("VisualShaderNodeVectorOp_rvu6f")
nodes/fragment/11/position = Vector2(-200, 560)
nodes/fragment/12/node = SubResource("VisualShaderNodeVec4Constant_d4ljy")
nodes/fragment/12/position = Vector2(-200, 740)
nodes/fragment/13/node = SubResource("VisualShaderNodeFloatConstant_cc8xj")
nodes/fragment/13/position = Vector2(440, 300)
nodes/fragment/14/node = SubResource("VisualShaderNodeFloatConstant_lhbqr")
nodes/fragment/14/position = Vector2(440, 400)
nodes/fragment/connections = PackedInt32Array(2, 0, 4, 0, 5, 0, 3, 0, 6, 0, 5, 2, 8, 0, 7, 0, 9, 0, 8, 2, 3, 0, 10, 0, 10, 0, 11, 0, 12, 0, 11, 1, 11, 0, 4, 1, 3, 0, 0, 0)

View File

@@ -1,24 +0,0 @@
shader_type spatial;
render_mode specular_disabled;
uniform vec4 ground_color : source_color;
uniform float outline_mask = 1.0;
varying vec4 world_pos;
void vertex() {
world_pos = MODEL_MATRIX * vec4(VERTEX, 1.0);
}
void fragment() {
ALBEDO = ground_color.rgb;
SPECULAR = 0.0;
ROUGHNESS = outline_mask;
}
void light() {
float light = clamp(dot(NORMAL, LIGHT), 0.0, 1.0);
DIFFUSE_LIGHT += light * (LIGHT_COLOR / PI) * ATTENUATION;
}

View File

@@ -1 +0,0 @@
uid://bifltg3r6fjhh

View File

@@ -1,96 +0,0 @@
shader_type spatial;
// Unshaded è essenziale per avere colori piatti e puliti
render_mode specular_disabled, cull_disabled, unshaded;
// --- GLOBAL UNIFORMS (Vento) ---
global uniform float wind_scale;
global uniform float wind_speed;
global uniform float wind_strength;
global uniform vec3 wind_direction;
global uniform sampler2D wind_noise : filter_linear_mipmap;
// --- PARAMETRI ESTETICI ---
uniform bool billboard_enabled = true; // <--- PULSANTE ON/OFF BILLBOARD
uniform bool wind_enabled = true; // <--- PULSANTE ON/OFF VENTO
uniform vec4 base_color : source_color = vec4(0.2, 0.6, 0.3, 1.0);
uniform sampler2D alpha_texture : source_color, filter_nearest;
uniform float leaves_scale = 1.0;
uniform float rotation_degrees = 0.0;
uniform vec2 texture_offset = vec2(0.0, 0.0);
// --- CONTROLLO GRADIENTE E RANDOM ---
uniform float height_min = 0.0;
uniform float height_max = 5.0;
uniform float shadow_intensity : hint_range(0.0, 1.0) = 0.5;
uniform float highlight_intensity : hint_range(0.0, 1.0) = 0.3;
uniform float light_steps : hint_range(1.0, 10.0) = 4.0;
uniform float random_mix : hint_range(0.0, 1.0) = 0.3;
varying vec3 v_final_color;
float hash(vec3 p) {
p = fract(p * 0.1031);
p += dot(p, p.yzx + 33.33);
return fract((p.x + p.y) * p.z);
}
void vertex() {
vec3 instance_pos = MODEL_MATRIX[3].xyz;
// --- LOGICA VENTO ---
float total_angle = radians(rotation_degrees);
if (wind_enabled) {
float time = TIME * wind_speed;
vec2 noise_uv = (instance_pos.xz * wind_scale) + (time * wind_direction.xz * 0.5);
float noise_val = textureLod(wind_noise, noise_uv, 2.0).r;
float sway = sin(time + (noise_val * 10.0));
total_angle += (sway * wind_strength);
}
// --- CALCOLO COLORE ---
float h_factor = clamp((instance_pos.y - height_min) / (height_max - height_min), 0.0, 1.0);
float leaf_rand = hash(instance_pos);
float combined_factor = mix(h_factor, leaf_rand, random_mix);
combined_factor = ceil(combined_factor * light_steps) / light_steps;
vec3 dark_color = base_color.rgb * (1.0 - shadow_intensity);
vec3 light_color = base_color.rgb + (vec3(1.0) - base_color.rgb) * highlight_intensity;
v_final_color = mix(dark_color, light_color, combined_factor);
// --- LOGICA TRASFORMAZIONE (BILLBOARD vs STANDARD) ---
if (billboard_enabled) {
// Logica Billboard: guarda sempre la camera
vec3 view_pos_origin = (VIEW_MATRIX * vec4(instance_pos, 1.0)).xyz;
vec2 offset = (UV - 0.5) * leaves_scale;
float c = cos(total_angle);
float s = sin(total_angle);
vec2 rotated_offset = vec2(offset.x * c - offset.y * s, offset.x * s + offset.y * c);
vec3 final_pos = view_pos_origin + vec3(rotated_offset.x, rotated_offset.y, 0.0);
MODELVIEW_MATRIX = mat4(1.0);
MODELVIEW_MATRIX[3].xyz = final_pos;
VERTEX = vec3(0.0);
} else {
// Logica Standard: usa la rotazione e posizione della mesh
// Applichiamo comunque la rotazione extra e lo scale se desiderato
float c = cos(total_angle);
float s = sin(total_angle);
// Modifichiamo il vertice locale prima della trasformazione world
vec2 local_v = (VERTEX.xy) * leaves_scale;
VERTEX.x = local_v.x * c - local_v.y * s;
VERTEX.y = local_v.x * s + local_v.y * c;
// La MODELVIEW_MATRIX rimane quella di default fornita da Godot
}
}
void fragment() {
vec2 shifted_uv = UV + texture_offset;
vec4 tex = texture(alpha_texture, shifted_uv);
ALBEDO = v_final_color;
ALPHA = tex.r;
ALPHA_SCISSOR_THRESHOLD = 0.5;
}

View File

@@ -1 +0,0 @@
uid://cvgukw0n6aw74

View File

@@ -1,50 +0,0 @@
shader_type spatial;
render_mode unshaded;
group_uniforms Albedo_Settings;
uniform vec4 albedo_color : source_color = vec4(1.0);
uniform sampler2D albedo_texture : source_color, filter_nearest;
uniform bool use_texture = true;
uniform vec2 uv_scale = vec2(1.0, 1.0);
group_uniforms Toon_Lighting;
uniform vec3 light_direction = vec3(0.5, 1.0, 0.5);
uniform float light_steps : hint_range(1.0, 10.0, 1.0) = 3.0;
uniform float step_softness : hint_range(0.01, 1.0) = 0.1;
uniform vec4 shadow_color : source_color = vec4(0.4, 0.4, 0.6, 1.0);
uniform float shadow_offset : hint_range(-1.0, 1.0) = 0.0;
group_uniforms Emission_Settings;
uniform vec4 emission_color : source_color = vec4(0.0, 0.0, 0.0, 1.0); // Nero di default
uniform float emission_energy : hint_range(0.0, 16.0) = 0.0; // A 0 l'emissione è spenta
void fragment() {
// 1. Albedo
vec4 tex = texture(albedo_texture, UV * uv_scale);
vec3 base_color = albedo_color.rgb;
if (use_texture) base_color *= tex.rgb;
// 2. Luce (World Space Fix)
vec3 world_light_dir = normalize(light_direction);
vec3 view_light_dir = (VIEW_MATRIX * vec4(world_light_dir, 0.0)).xyz;
float n_dot_l = dot(NORMAL, normalize(view_light_dir));
// 3. Toon Stepping
float intensity = clamp(n_dot_l + shadow_offset, 0.0, 1.0);
float raw_step = intensity * light_steps;
float lower_step = floor(raw_step);
float fract_step = fract(raw_step);
float lerp_step = smoothstep(0.5 - step_softness, 0.5 + step_softness, fract_step);
float stepped_intensity = (lower_step + lerp_step) / light_steps;
// 4. Mixing base
vec3 light_part = base_color * 1.2;
vec3 shaded_part = base_color * shadow_color.rgb;
vec3 final_rgb = mix(shaded_part, light_part, clamp(stepped_intensity, 0.0, 1.0));
ALBEDO = final_rgb;
// 5. Emission
// Moltiplica il colore per l'energia impostata dall'utente
EMISSION = emission_color.rgb * emission_energy;
}

View File

@@ -1 +0,0 @@
uid://n2fjgynfljhx