Created a new outline shader.

Instead of changing the albedo of a mesh depending on it's normal
vector at a particular pixel, a new mesh is now created within the
shader that is a slightly expanded version of the original mesh, with
front face culling as to not draw over the original.

This makes the highlighting of certain objects, e.g. cards, more
consistent.
This commit is contained in:
drwhut 2022-09-12 15:03:34 +01:00
parent bbd87b3448
commit 63c6048b16
4 changed files with 29 additions and 77 deletions

View File

@ -421,7 +421,7 @@ puppet func ss(basis0: Basis, basis1: Basis) -> void:
# color: The color of the outline.
func set_outline_color(color: Color) -> void:
if _outline_material:
_outline_material.set_shader_param("Color", color)
_outline_material.set_shader_param("OutlineColor", color)
else:
push_error("Outline material has not been created!")
@ -453,11 +453,11 @@ remotesync func set_translation(new_translation: Vector3) -> void:
# Add the outline material to all mesh instances in this piece.
func setup_outline_material():
var outline_shader = preload("res://Shaders/OutlineShader.tres")
var outline_shader = preload("res://Shaders/OutlineShader.shader")
_outline_material = ShaderMaterial.new()
_outline_material.shader = outline_shader
_outline_material.set_shader_param("Color", Color.transparent)
_outline_material.set_shader_param("OutlineColor", Color.transparent)
for mesh_instance in get_mesh_instances():
if mesh_instance is MeshInstance:

View File

@ -435,11 +435,11 @@ remotesync func set_piece_order(_order: Array) -> void:
# Add the outline material to the outline mesh instance.
func setup_outline_material():
var outline_shader = preload("res://Shaders/OutlineShader.tres")
var outline_shader = preload("res://Shaders/OutlineShader.shader")
_outline_material = ShaderMaterial.new()
_outline_material.shader = outline_shader
_outline_material.set_shader_param("Color", Color.transparent)
_outline_material.set_shader_param("OutlineColor", Color.transparent)
get_outline_mesh_instance().set_surface_material(0, _outline_material)

View File

@ -0,0 +1,24 @@
// This shader is based off code uploaded by axilirate on Godot Shaders (CC0):
// https://godotshaders.com/shader/pixel-perfect-outline-shader/
shader_type spatial;
render_mode cull_front, unshaded;
uniform vec4 OutlineColor: hint_color;
uniform float OutlineWidth = 1.0;
void vertex() {
vec4 clip_position = PROJECTION_MATRIX * (MODELVIEW_MATRIX * vec4(VERTEX, 1.0));
vec3 clip_normal = mat3(PROJECTION_MATRIX) * (mat3(MODELVIEW_MATRIX) * NORMAL);
vec2 offset = normalize(clip_normal.xy) / VIEWPORT_SIZE * clip_position.w * OutlineWidth * 2.0;
clip_position.xy += offset;
POSITION = clip_position;
}
void fragment() {
ALBEDO = OutlineColor.rgb;
ALPHA = OutlineColor.a;
}

View File

@ -1,72 +0,0 @@
[gd_resource type="VisualShader" load_steps=6 format=2]
[sub_resource type="VisualShaderNodeFresnel" id=1]
default_input_values = [ 2, false, 3, 3.0 ]
[sub_resource type="VisualShaderNodeColorUniform" id=2]
uniform_name = "Color"
[sub_resource type="VisualShaderNodeScalarOp" id=3]
operator = 2
[sub_resource type="VisualShaderNodeInput" id=4]
input_name = "normal"
[sub_resource type="VisualShaderNodeInput" id=5]
input_name = "view"
[resource]
code = "shader_type spatial;
render_mode specular_schlick_ggx;
uniform vec4 Color : hint_color;
void vertex() {
// Output:0
}
void fragment() {
// ColorUniform:3
vec3 n_out3p0 = Color.rgb;
float n_out3p1 = Color.a;
// Input:5
vec3 n_out5p0 = NORMAL;
// Input:6
vec3 n_out6p0 = VIEW;
// Fresnel:2
float n_in2p3 = 3.00000;
float n_out2p0 = pow(1.0 - clamp(dot(n_out5p0, n_out6p0), 0.0, 1.0), n_in2p3);
// ScalarOp:4
float n_out4p0 = n_out3p1 * n_out2p0;
// Output:0
ALBEDO = n_out3p0;
ALPHA = n_out4p0;
EMISSION = n_out3p0;
}
void light() {
// Output:0
}
"
graph_offset = Vector2( -481, 115 )
nodes/fragment/2/node = SubResource( 1 )
nodes/fragment/2/position = Vector2( -40, 340 )
nodes/fragment/3/node = SubResource( 2 )
nodes/fragment/3/position = Vector2( -40, 160 )
nodes/fragment/4/node = SubResource( 3 )
nodes/fragment/4/position = Vector2( 200, 300 )
nodes/fragment/5/node = SubResource( 4 )
nodes/fragment/5/position = Vector2( -240, 320 )
nodes/fragment/6/node = SubResource( 5 )
nodes/fragment/6/position = Vector2( -240, 380 )
nodes/fragment/connections = PoolIntArray( 3, 0, 0, 0, 2, 0, 4, 1, 3, 1, 4, 0, 4, 0, 0, 1, 5, 0, 2, 0, 6, 0, 2, 1, 3, 0, 0, 5 )