Nothing Special   »   [go: up one dir, main page]

Sobel Outline

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 2

//Use this shader only in next pass of another material, else it doesn’t work

shader_type spatial;
//render_mode unshaded; // in case we want that

//Enable Transparent Materials://


//Ensure that the materials of the objects in front of your shader are set to be
transparent.
//You can do this by adjusting the material's properties in the Inspector panel.
// Set the material's "Flags" property to "Transparent" or "Transparent and
Unshaded".

//Rendering Order://
//Ensure that objects with your shader are rendered after the objects
//they need to be visible through.

//cull_disabled disables backface culling


//depth_draw_opaque ensures that the object is drawn regardless of the depth
//blend_add specifies the blending mode.
//you might want to use different blend modes such as Alpha, Add, or Screen.
render_mode cull_disabled, depth_test_disabled, blend_add;

uniform sampler2D tiling_texture: filter_nearest; // filter nearest is used to keep


a sharp, pixelated look
uniform float tiling_scale = 2.0;
const float DEFAULT_SCALE = 8.0;

uniform sampler2D SCREEN_TEXTURE: hint_screen_texture, filter_linear;


//The normal-roughness texture can be used to read the normals and roughness of
objects
//rendered in the depth prepass. The normal is stored in the .xyz channels
//(mapped to the 0-1 range) while the roughness is stored in the .w channel.
uniform sampler2D NORMAL_TEXTURE: hint_normal_roughness_texture, filter_linear;

// an outline_threshold of 0 means there's no limit so everything will become an


edge
// as it grows the edge will become thinner
uniform float outline_threshold = 0.2;
uniform vec3 outline_color: source_color = vec3(0.0, 0.0, 0.0);
uniform vec3 emmission_color: source_color = vec3(0.0, 0.0, 0.0);
uniform float emmission_power = 3;
//kernel Gy
const mat3 sobel_y = mat3(
vec3(1.0, 0.0, -1.0),
vec3(2.0, 0.0, -2.0),
vec3(1.0, 0.0, -1.0)
);
//kernel Gx
const mat3 sobel_x = mat3(
vec3(1.0, 2.0, 1.0),
vec3(0.0, 0.0, 0.0),
vec3(-1.0, -2.0, -1.0)
);

bool is_edge(in vec2 uv, in vec3 normal, in vec2 offset) {


vec3 n = texture(NORMAL_TEXTURE, uv + vec2(0.0, -offset.y)).rgb;
vec3 s = texture(NORMAL_TEXTURE, uv + vec2(0.0, offset.y)).rgb;
vec3 e = texture(NORMAL_TEXTURE, uv + vec2(offset.x, 0.0)).rgb;
vec3 w = texture(NORMAL_TEXTURE, uv + vec2(-offset.x, 0.0)).rgb;
vec3 nw = texture(NORMAL_TEXTURE, uv + vec2(-offset.x, -offset.y)).rgb;
vec3 ne = texture(NORMAL_TEXTURE, uv + vec2(offset.x, -offset.y)).rgb;
vec3 sw = texture(NORMAL_TEXTURE, uv + vec2(-offset.x, offset.y)).rgb;
vec3 se = texture(NORMAL_TEXTURE, uv + vec2(offset.x, offset.y)).rgb;

mat3 surrounding_pixels = mat3(


vec3(length(nw-normal), length(n-normal), length(ne-normal)),
vec3(length(w-normal), length(normal-normal), length(e-normal)),
vec3(length(sw-normal), length(s-normal), length(se-normal))
);

float edge_x = dot(sobel_x[0], surrounding_pixels[0]) + dot(sobel_x[1],


surrounding_pixels[1]) + dot(sobel_x[2], surrounding_pixels[2]);
float edge_y = dot(sobel_y[0], surrounding_pixels[0]) + dot(sobel_y[1],
surrounding_pixels[1]) + dot(sobel_y[2], surrounding_pixels[2]);

float edge = sqrt(pow(edge_x, 2.0)+pow(edge_y, 2.0));

return edge > outline_threshold;


}

void fragment() {
vec2 uv2 = FRAGCOORD.xy;// Fragment coordinate, pixel adjusted.
vec2 uv = SCREEN_UV; // Screen UV coordinate for current pixel.

vec2 tiling_uv = uv2 / (DEFAULT_SCALE * tiling_scale * -1.0);


vec4 texture_result = texture(tiling_texture, tiling_uv);

vec3 screen_color = texture(SCREEN_TEXTURE, uv).rgb;


vec3 screen_normal = texture(NORMAL_TEXTURE, uv).rgb;
screen_normal = screen_normal * 2.0 - 1.0;
vec2 offset = 1.0 / VIEWPORT_SIZE;

if (is_edge(uv, screen_normal, offset)) {


ALBEDO = outline_color;
//There's no alpha in this texture that's why this uses any other
channel since it's black & white
// you can change this if the image is not black and white or if it
does have an alpha
// We clamp the result so the transparency works as expected
ALPHA = clamp(texture_result.r,0.0,1.0);// we clamp to get perfect
transparency
EMISSION = emmission_color * emmission_power;

} else {
ALBEDO = screen_color;
}
}

You might also like