I'm trying to create a grass shader that, when provided with a mesh (a simple quad from multimesh) and texture, will display that texture always facing the camera. That part isn't too hard to do.
However, I also want to transfer lighting from the terrain onto the grass. To do this, I've been giving the grass the same normal as the terrain and then applying the same lighting function as is on the terrain shader. This works great when the grass has not been billboarded. However, once it has, it looses all lighting except for shadows. I suspect this has something to do with the transformations applied to the normal when I modify the model view matrix, but I haven't been able to fix it.
Shader code: (ignore the weird stuff I'm doing with UVs)
shader_type spatial;
render_mode ambient_light_disabled;
uniform vec4 ambientColor:hint_color = vec4(0);
//uniform vec4 albedo:hint_color = vec4(0);
//uniform vec4 tipColor:hint_color = vec4(0);
uniform sampler2D grassTexture:hint_albedo;
const vec3 UP = vec3(0,1,0);
void vertex() {
// billboard sprite
//MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);
// billboard y only
//MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), CAMERA_MATRIX[2].xyz)),0.0),vec4(0.0, 1.0, 0.0, 0.0),vec4(normalize(cross(CAMERA_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))),0.0),WORLD_MATRIX[3]);
// all taken from https://github.com/godotengine/godot/blob/0d9aecd96760ad85930cced7a40c0e6c3c19f3dc/scene/resources/material.cpp
NORMAL = UP;
vec3 vertex = VERTEX;
// negative to fix some weird issue with mesh being inverted
vertex.xz *= -INSTANCE_CUSTOM.x;
vertex.y *= INSTANCE_CUSTOM.y;
UV = UV2;
UV2 = INSTANCE_CUSTOM.w > 200.0 ? vec2(0.0, UV2.y) : vec2(1.0, UV2.y);
VERTEX = vertex;
}
void fragment() {
ALBEDO = texture(grassTexture, UV).rgb;
//ALPHA_SCISSOR = texture(grassTexture, UV).a > 0.1 ? 5.0 : 0.0;
}
// overthought toon shader
void light() {
float lDot = dot(NORMAL, LIGHT) * ATTENUATION.x;
float lightIntensity = UV2.x == 1.0 ? (lDot > 0.15 ? 1.0 : (lDot > 0.02 ? 0.5 : 0.0)) : 0.5;
vec3 light = lightIntensity * LIGHT_COLOR;
DIFFUSE_LIGHT += length(light) > 0.0 ? (ALBEDO * LIGHT_COLOR * (ambientColor.rgb + light)) : (length(DIFFUSE_LIGHT) == 0.0 ? ALBEDO * ambientColor.rgb : vec3(0.0));
}
Shaded terrain works well:

Shaded grass works well without billboarding:

It all comes crashing down when the billboarding is enabled:
