I have no experience writing shaders, but it seems to be more flexible than using the VisualShader system, being able to pass values between the vertex and fragment shaders. I figure it's better to learn to write them instead of manipulate prebuilt blocks. I have a very basic problem currently, where I'm trying to set the albedo based on the VERTEX.y position. I know using the VIEW_MATRIX is how to solve my problem, but I don't know how to use this:
vec3 n_out6p0 = (vec4(NORMAL, 1.0) * VIEW_MATRIX).xyz;
in the following:
if (VERTEX.y > 0.5) {
albedo_out = rock_albedo;
}
Here's the full shader code:
shader_type spatial;
uniform sampler2D grass_texture;
uniform sampler2D dirt_texture;
uniform sampler2D rock_texture;
uniform sampler2D sand_texture;
uniform float min_rock_slope: hint_range(0.0, 1.0, 0.1) = 0.8;
uniform float max_grass_slope: hint_range(0.0, 1.0, 0.1) = 0.9;
varying float normal_y;
void vertex() {
normal_y = NORMAL.y;
}
void fragment() {
vec3 n_out6p0 = (vec4(NORMAL, 1.0) * VIEW_MATRIX).xyz;
// Vector3Constant:7
vec3 y_axis = vec3(0.000000, 1.000000, 0.000000);
// DotProduct:8
float n_out8p0 = dot(n_out6p0, y_axis);
// UVFunc:3
vec2 n_in3p1 = vec2(8.00000, 8.00000);
vec2 n_in3p2 = vec2(0.00000, 0.00000);
vec2 n_out3p0 = (UV - n_in3p2) * n_in3p1 + n_in3p2;
// Albedo Values
vec3 grass_albedo = texture(grass_texture, UV * 4.0).xyz;
vec3 dirt_albedo = texture(dirt_texture, UV * 4.0).xyz;
vec3 rock_albedo = texture(rock_texture, UV * 4.0).xyz;
vec3 sand_albedo = texture(sand_texture, UV * 4.0).xyz;
// Weights
float rock_grass_weight = normal_y;
vec3 albedo_out;
rock_grass_weight = max(min_rock_slope, rock_grass_weight);
rock_grass_weight = min(max_grass_slope, rock_grass_weight);
rock_grass_weight -= min_rock_slope;
rock_grass_weight /= max_grass_slope - min_rock_slope;
albedo_out = mix(rock_albedo, grass_albedo, rock_grass_weight);
if (VERTEX.y > 0.5) {
albedo_out = rock_albedo;
}
// Output:0
ALBEDO = albedo_out;
}