I'm trying to create a shader to render dots on the screen. While these dots are positioned in 3D space, I want to scale them so that they always appear to be 5 pixels in diameter, regardless of how far away from the camera they are.
I started trying to use the StandardMaterial3d and its billboard setting, but it didn't have anything to scale my quads so they always looked the same size in the viewport. So I converted it into a Shader script and started editing it. I came up with something that works with a perspective camera, but fails with an orthgraphic camera. When using an orthographic camera the points scale properly when you're close to them, but then snap to far too large when you get a modest distance away from them. I'm also not sure why the perspective camera correction is failing for the orthgraphic camera as I think it ought to work for both modes.
Is there perhaps another way to go about this? I want to draw my quads with their point textures so that they appear the same size on the screen no matter how far from the camera they are.
// NOTE: Shader automatically converted from Godot Engine 4.1.stable's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float point_size : hint_range(0,128);
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;
uniform float point_radius = 10.0;
void vertex() {
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);
vec4 origin_view = MODELVIEW_MATRIX * vec4(0.0, 0.0, 0.0, 1.0);
vec4 origin_clip = PROJECTION_MATRIX * origin_view;
origin_clip /= origin_clip.w;
vec4 offset_clip = origin_clip + vec4(0.0, point_radius / VIEWPORT_SIZE.y, 0.0, 0.0);
vec4 offset_model = inverse(MODELVIEW_MATRIX) * INV_PROJECTION_MATRIX * offset_clip;
offset_model /= offset_model.w;
float scale = length(offset_model.xyz - origin_view.xyz);
if (PROJECTION_MATRIX[2][3] == 0.0) {
//Orthogonal
scale *= .0001;
}
mat4 scale_mat = mat4(vec4(scale, 0.0, 0.0, 0.0), vec4(0.0, scale, 0.0, 0.0), vec4(0.0, 0.0, scale, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
MODELVIEW_MATRIX = MODELVIEW_MATRIX * scale_mat;
UV=UV*uv1_scale.xy+uv1_offset.xy;
MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
}
void fragment() {
vec2 base_uv = UV;
vec4 albedo_tex = texture(texture_albedo,base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
SPECULAR = specular;
}