Orthographic blending

  • Prevent perspective from warping models near the screen edges
  • Has a depth bias for 3D model “sorting” (use small values like 0.00001)
Shader code
shader_type spatial;

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_bias : hint_range(-1.0, 1.0, 0.00001)= 0.0;

vec2 getFov(vec2 vp_size) {
    float aspect = vp_size.x / vp_size.y;
    float fov_y = radians(CameraFOV);
    float fov_x = 2.0 * atan(tan(fov_y * 0.5) * aspect);
    return vec2(fov_x, fov_y);
}

void vertex() {
    if(IN_SHADOW_PASS) {
        POSITION = PROJECTION_MATRIX * MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
    }
    else
    {
        // Clip matrix
        mat4 CLIP_MATRIX = PROJECTION_MATRIX * VIEW_MATRIX;
        mat4 INV_CLIP_MATRIX = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX;

        vec4 camera = INV_VIEW_MATRIX[3];
        vec3 camera_pos = camera.xyz;
        vec3 world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
        vec3 relative_pos = world_pos - camera_pos;
        vec4 clip_pos = CLIP_MATRIX * vec4(relative_pos, 0.0);

        vec2 fov = getFov(VIEWPORT_SIZE);
        vec2 view_size = CameraDistance * tan(fov * 0.5);
        vec3 ortho_vector = VIEW_MATRIX[0].xyz / view_size.x;

        // Apply ortho blending
        float blend_amount = OrthoBlendEnabled ? ortho_blend : 0.0;
        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 = camera + (INV_CLIP_MATRIX * ortho_clip_pos);
        POSITION = CLIP_MATRIX * final_pos;

        // Apply Depth Bias
        const float epsilon = 1e-5;
        float biased_z = POSITION.z + depth_bias * POSITION.w;

    #if CURRENT_RENDERER == RENDERER_COMPATIBILITY
        POSITION.z = clamp(biased_z, -POSITION.w + epsilon, POSITION.w - epsilon);
    #else
        POSITION.z = clamp(biased_z, epsilon, POSITION.w - epsilon);
    #endif
   }
}

void fragment() {
    vec4 tex = texture(albedo_texture, UV);
    ALBEDO = tex.rgb * tint_color;
}
Live Preview
Tags
depth offset, ortho blending, orthogonal
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from lucasteles42

Related shaders

guest

0 Comments
Oldest
Newest Most Voted