- Prevent perspective from warping models near the screen edges
- Has a depth offset for 3D model “sorting”
Shader code
shader_type spatial;
render_mode skip_vertex_transform;
global uniform float CameraDistance = 5.4;
global uniform float CameraFOV = 32.0;
global uniform bool OrthoBlendEnabled = true;
uniform vec3 tint_color : source_color = vec3(1);
uniform sampler2D albedo_texture : source_color;
uniform float ortho_blend : hint_range(0.0, 1.0) = 0.7;
uniform float depth_offset = 0.0;
vec2 get_fov(vec2 vpSize) {
float aspect = vpSize.x / vpSize.y;
float fov_y = radians(CameraFOV);
float fov_x = 2.0 * atan(tan(fov_y * 0.5) * aspect);
return vec2(fov_x, fov_y);
}
vec4 get_ortho_vector(mat4 viewMtx, vec2 fov) {
vec2 size = CameraDistance * tan(fov * 0.5);
mat4 ortho_matrix = mat4(
vec4(1.0 / size.x, 0.0, 0.0, 0.0),
vec4(0.0, 1.0 / size.y, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
) * viewMtx;
return vec4(
ortho_matrix[0][0],
ortho_matrix[1][0],
ortho_matrix[2][0],
ortho_matrix[3][0]
);
}
void vertex() {
NORMAL = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
BINORMAL = normalize((MODELVIEW_MATRIX * vec4(BINORMAL, 0.0)).xyz);
TANGENT = normalize((MODELVIEW_MATRIX * vec4(TANGENT, 0.0)).xyz);
mat4 CLIP_MATRIX = PROJECTION_MATRIX * VIEW_MATRIX;
mat4 INV_CLIP_MATRIX = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX;
vec3 local_pos = VERTEX;
vec4 world_pos = MODEL_MATRIX * vec4(local_pos, 1.0);
vec4 camera_pos = INV_VIEW_MATRIX[3];
vec4 relative_pos = world_pos - camera_pos;
vec4 clip_pos = CLIP_MATRIX * relative_pos;
// Reconstruct FOV
vec2 fov = get_fov(VIEWPORT_SIZE);
vec4 ortho_vector = get_ortho_vector(VIEW_MATRIX, fov);
float blend_amount = OrthoBlendEnabled ? ortho_blend : 0.0;
// Apply ortho blending
float ortho_value = dot(ortho_vector, relative_pos) * clip_pos.w;
vec4 ortho_clip_pos = vec4(mix(clip_pos.x, ortho_value, blend_amount), clip_pos.yzw);
vec4 final_pos = INV_CLIP_MATRIX * ortho_clip_pos;
final_pos += camera_pos;
// Apply depth offset
vec4 camera_direction = normalize(camera_pos - world_pos);
vec4 depth_pos_offset = camera_direction * depth_offset;
final_pos += depth_pos_offset;
POSITION = CLIP_MATRIX * final_pos;
}
void fragment() {
vec4 tex = texture(albedo_texture, UV);
ALBEDO = tex.xyz * tint_color;
}
Live Preview
Tags
depth offset,
ortho blending,
orthogonal