Skip to content

Instantly share code, notes, and snippets.

@t-mw
Last active May 4, 2020 17:52
Show Gist options
  • Save t-mw/0b78167372ed97e7c78e3f3844f3ae75 to your computer and use it in GitHub Desktop.
Save t-mw/0b78167372ed97e7c78e3f3844f3ae75 to your computer and use it in GitHub Desktop.
Godot Engine AtlasTexture billboard shader
# NB: assumes an orthogonal camera and quad mesh geometry
fn _process(_delta) {
# set this to an instance of AtlasTexture
var atlas_tex = ...
# set this to an instance of Material
var material = ...
# optionally center the sprite around a point relative to the top-left corner
var center = Vector2(0, 0)
# hook this up to the camera size
var camera_size = 30
var atlas_size = atlas_tex.get_atlas().get_size()
var margin = atlas_tex.get_margin()
var margin_origin = margin.position
var region = atlas_tex.get_region()
var region_origin = region.position
var region_size = region.size
material.set_shader_param("camera_size", camera_size)
material.set_shader_param("inv_atlas_size", Vector2(1.0, 1.0) / atlas_size)
material.set_shader_param("offset", Vector2(margin_origin.x - center.x, -(margin_origin.y - center.y)))
material.set_shader_param("region_origin", region_origin)
material.set_shader_param("region_size", region_size)
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx,unshaded,skip_vertex_transform;
uniform vec4 albedo : hint_color;
uniform sampler2D texture_albedo : hint_albedo;
uniform float specular;
uniform float metallic;
uniform float roughness : hint_range(0,1);
uniform float camera_size;
uniform vec2 inv_atlas_size;
uniform vec2 offset;
uniform vec2 region_origin;
uniform vec2 region_size;
void vertex() {
// NB: assumes camera keep_aspect == height.
// assign a constant to world_units_per_px to keep the sprite size
// fixed relative to the 3D world, rather than fixed 1:1 with the viewport.
float world_units_per_px = camera_size / VIEWPORT_SIZE.y;
// billboard quad
MODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);
// scale quad to region size
MODELVIEW_MATRIX[0][0] *= region_size.x * world_units_per_px;
MODELVIEW_MATRIX[1][1] *= region_size.y * world_units_per_px;
VERTEX = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
NORMAL = (MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz;
// anchor top-left of quad to node origin
VERTEX.xy += vec2(region_size.x / 2.0, -region_size.y / 2.0) * world_units_per_px;
// offset by margin
VERTEX.xy += offset * world_units_per_px;
// adjust uvs for atlas region
vec2 uv_offset = region_origin * inv_atlas_size;
vec2 uv_scale = region_size * inv_atlas_size;
UV = UV * uv_scale + uv_offset;
}
void fragment() {
vec2 base_uv = UV;
vec4 albedo_tex = texture(texture_albedo,base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
METALLIC = metallic;
ROUGHNESS = roughness;
SPECULAR = specular;
ALPHA = albedo.a * albedo_tex.a;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment