Skip to content

Instantly share code, notes, and snippets.

@PranavSK
Last active October 9, 2020 11:43
Show Gist options
  • Save PranavSK/191dd40331561277a512f87df3d70bea to your computer and use it in GitHub Desktop.
Save PranavSK/191dd40331561277a512f87df3d70bea to your computer and use it in GitHub Desktop.
tool
extends ShaderMaterial
class_name StylizedMaterial
"""
"""
enum BlendMode {MIX, ADD, SUB, MUL}
enum DepthDrawMode {OPAQUE_ONLY, ALWAYS, DISABLED, ALPHA_OPAQUE_PREPASS}
enum CullMode {BACK, FRONT, DISABLED}
enum CelPrimaryMode {NONE, SINGLE, MULTI}
export(BlendMode) var blend_mode: int = BlendMode.MIX setget set_blend_mode, get_blend_mode
export(DepthDrawMode) var depth_draw_mode: int = DepthDrawMode.OPAQUE_ONLY setget set_depth_draw_mode, get_depth_draw_mode
export(CullMode) var cull_mode: int = CullMode.BACK setget set_cull_mode, get_cull_mode
export var recieve_shadows: = true setget enable_recieve_shadows, is_recieve_shadows_enabled
export var ambient_light: = false setget enable_ambient_light, is_ambient_light_enabled
export(CelPrimaryMode) var cel_shading_mode: int = CelPrimaryMode.NONE setget set_cel_shading_mode, get_cel_shading_mode
export var extra_cel: = false setget enable_extra_cel, is_extra_cel_enabled
export var specular: = false setget enable_specular, is_specular_enabled
export var rim: = false setget enable_rim, is_rim_enabled
export var height_gradient: = false setget enable_height_gradient, is_height_gradient_enabled
# Additional params
export var vertex_color: = false setget enable_vertex_color, is_vertex_color_enabled
var _is_shader_updating: = false
func set_blend_mode(value):
blend_mode = value;
_queue_shader_update()
func get_blend_mode():
return blend_mode
func set_depth_draw_mode(value):
depth_draw_mode = value
_queue_shader_update()
func get_depth_draw_mode():
return depth_draw_mode
func set_cull_mode(value):
cull_mode = value
_queue_shader_update()
func get_cull_mode():
return cull_mode
func enable_recieve_shadows(value):
recieve_shadows = value
_queue_shader_update()
func is_recieve_shadows_enabled():
return recieve_shadows
func enable_ambient_light(value):
ambient_light = value
_queue_shader_update()
func is_ambient_light_enabled():
return ambient_light
func set_cel_shading_mode(value):
cel_shading_mode = value
_queue_shader_update()
func get_cel_shading_mode():
return cel_shading_mode
func enable_extra_cel(value):
extra_cel = value
_queue_shader_update()
func is_extra_cel_enabled():
return extra_cel
func enable_specular(value):
specular = value
_queue_shader_update()
func is_specular_enabled():
return specular
func enable_rim(value):
rim = value
_queue_shader_update()
func is_rim_enabled():
return rim
func enable_height_gradient(value):
height_gradient = value
_queue_shader_update()
func is_height_gradient_enabled():
return height_gradient
func enable_vertex_color(value):
vertex_color = value
_queue_shader_update()
func is_vertex_color_enabled():
return vertex_color
func _queue_shader_update():
if not _is_shader_updating:
call_deferred("_generate_shader_code")
# _generate_shader_code()
_is_shader_updating = true
func _generate_shader_code():
print_debug("Updating Shader")
if not shader:
shader = Shader.new()
shader.code = ""
shader.code += "shader_type spatial;"
shader.code += "\nrender_mode "
match blend_mode:
BlendMode.MIX: shader.code += "blend_mix"
BlendMode.ADD: shader.code += "blend_add"
BlendMode.SUB: shader.code += "blend_sub"
BlendMode.MUL: shader.code += "blend_mul"
match depth_draw_mode:
DepthDrawMode.OPAQUE_ONLY: shader.code += ",depth_draw_opaque"
DepthDrawMode.ALWAYS: shader.code += ",depth_draw_always"
DepthDrawMode.DISABLED: shader.code += ",depth_draw_never"
DepthDrawMode.ALPHA_OPAQUE_PREPASS: shader.code += ",depth_draw_alpha_prepass"
match cull_mode:
CullMode.BACK: shader.code += ",cull_back"
CullMode.FRONT: shader.code += ",cull_front"
CullMode.DISABLED: shader.code += ",cull_disabled"
if cel_shading_mode == CelPrimaryMode.NONE:
shader.code += ",unshaded"
if not recieve_shadows:
shader.code += ",shadows_disabled";
if not ambient_light:
shader.code += ",ambient_light_disabled"
shader.code += ";\n"
shader.code += "uniform vec4 color_primary: hint_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
shader.code += "uniform sampler2D texture_primary: hint_albedo;\n"
if not cel_shading_mode == CelPrimaryMode.NONE:
if cel_shading_mode == CelPrimaryMode.SINGLE:
shader.code += "uniform vec4 color_shaded: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform float self_shading_size: hint_range(0.0, 1.0) = 0.5;\n"
shader.code += "uniform float shadow_edge_size: hint_range(0.0, 0.5) = 0.05;\n"
shader.code += "uniform float flatness: hint_range(0.0, 1.0) = 1.0;\n"
elif cel_shading_mode == CelPrimaryMode.MULTI:
shader.code += "uniform vec4 color_shaded: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform sampler2D cel_step_texture: hint_white;\n"
if extra_cel:
shader.code += "uniform vec4 extra_color_shaded: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform float extra_self_shading_size: hint_range(0.0, 1.0) = 0.6;\n"
shader.code += "uniform float extra_shadow_edge_size: hint_range(0.0, 0.5) = 0.05;\n"
shader.code += "uniform float extra_flatness: hint_range(0.0, 1.0) = 1.0;\n"
if specular:
shader.code += "uniform vec4 specular_color: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform float specular_size: hint_range(0.0, 1.0) = 0.1;\n"
shader.code += "uniform float specular_edge_smoothness: hint_range(0.0, 1.0) = 0.0;\n"
if rim:
shader.code += "uniform vec4 rim_color: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform float rim_light_align: hint_range(0.0, 1.0) = 0;\n"
shader.code += "uniform float rim_size: hint_range(0.0, 1.0) = 0.5;\n"
shader.code += "uniform float rim_edge_smoothness: hint_range(0.0, 1.0) = 0.5;\n"
if height_gradient:
shader.code += "uniform vec4 height_gradient_color: hint_color = vec4(0.86, 0.86, 0.86, 1.0);\n"
shader.code += "uniform vec2 height_gradient_center = vec2(0.0, 0.0);\n"
shader.code += "uniform float height_gradient_size = 10.0;\n"
shader.code += "uniform float height_gradient_angle: hint_range(0.0, 360.0) = 0.0;\n"
shader.code += "float cel_transition(float ndotl, float p_self_shading_size, float p_shadow_edge_size, float p_flatness) {\n"
shader.code += "\tfloat angle_diff = clamp((ndotl * 0.5 + 0.5) - p_self_shading_size, 0.0, 1.0);\n"
shader.code += "\tfloat angle_diff_transition = smoothstep(0.0, p_shadow_edge_size, angle_diff);\n"
shader.code += "\treturn mix(angle_diff, angle_diff_transition, p_flatness);\n"
shader.code += "}\n"
if cel_shading_mode == CelPrimaryMode.SINGLE:
shader.code += "float cel_transition_primary(float ndotl) {\n"
shader.code += "\treturn cel_transition(ndotl, self_shading_size, shadow_edge_size, flatness);\n"
shader.code += "}\n"
elif cel_shading_mode == CelPrimaryMode.MULTI:
shader.code += "float cel_transition_texture(float ndotl, sampler2D step_texture) {\n"
shader.code += "\tfloat angle_diff = clamp((ndotl * 0.5 + 0.5), 0.0, 1.0);\n"
shader.code += "\treturn texture(step_texture, vec2(angle_diff, 0.5)).r;\n"
shader.code += "}\n"
if extra_cel:
shader.code += "float cel_transition_extra(float ndotl){\n"
shader.code += "\treturn cel_transition(ndotl, extra_self_shading_size, extra_shadow_edge_size, extra_flatness);\n"
shader.code += "}\n"
if height_gradient:
shader.code += "varying vec3 world_pos;\n"
shader.code += "\n"
shader.code += "void vertex() {\n"
shader.code += "\tvec4 world = WORLD_MATRIX * vec4(VERTEX, 1.0);\n"
shader.code += "\tworld_pos = world.xyz / world.w;\n"
shader.code += "}\n"
shader.code += "void fragment(){\n"
shader.code += "\tvec4 primary = texture(texture_primary, UV) * color_primary;\n"
if vertex_color:
shader.code += "\tprimary *= COLOR;\n"
shader.code += "\tALBEDO = primary.rgb;\n//\tALPHA = primary.a;\n"
shader.code += "}\n"
if not cel_shading_mode == CelPrimaryMode.NONE:
shader.code += "void light(){\n"
shader.code += "\tvec4 color = color_primary;\n"
shader.code += "\tfloat ndotl = dot(NORMAL, LIGHT);\n"
if cel_shading_mode == CelPrimaryMode.SINGLE:
shader.code += "\tfloat cel_transition = cel_transition_primary(ndotl);\n"
elif cel_shading_mode == CelPrimaryMode.MULTI:
shader.code += "\tfloat cel_transition = cel_transition_texture(ndotl, cel_step_texture);\n"
shader.code += "\tcolor = mix(color_shaded, color, cel_transition);\n"
if extra_cel:
shader.code += "\tfloat extra_cel_transition = cel_transition_extra(ndotl);\n"
shader.code += "\tcolor = mix(extra_color_shaded, color, extra_cel_transition);\n"
if height_gradient:
shader.code += "\tfloat angle_radians = radians(height_gradient_angle / 180.0);\n"
shader.code += "\tfloat pos_grad_rotated = (world_pos.x - height_gradient_center.x) * sin(angle_radians) + (world_pos.y - height_gradient_center.y) * cos(angle_radians);\n"
shader.code += "\tfloat gradient_top = height_gradient_center.y + height_gradient_size * 0.5;\n"
shader.code += "\tfloat gradient_factor = clamp((gradient_top - pos_grad_rotated) / height_gradient_size, 0.0, 1.0);\n"
shader.code += "\tcolor = mix(height_gradient_color, color, gradient_factor);\n"
if rim:
shader.code += "\tfloat rim = 1.0 - dot(VIEW, NORMAL);\n"
shader.code += "\tfloat rim_spread = 1.0 - rim_size - ndotl * rim_light_align;\n"
shader.code += "\tfloat rim_transition = smoothstep(rim_spread - rim_edge_smoothness * 0.5, rim_spread + rim_edge_smoothness * 0.5, rim);\n"
shader.code += "\tcolor = mix(color, rim_color, rim_transition);\n"
if specular:
shader.code += "\tvec3 half_vector = normalize(VIEW + LIGHT);\n"
shader.code += "\tfloat ndoth = dot(NORMAL, half_vector) * 0.5 + 0.5;\n"
shader.code += "\tfloat specular = clamp(pow(ndoth, 100.0 * (1.0 - specular_size) * (1.0 - specular_size)), 0.0, 1.0);\n"
shader.code += "\tfloat specular_transition = smoothstep(0.5 - specular_edge_smoothness * 0.1, 0.5 + specular_edge_smoothness * 0.1, specular);\n"
shader.code += "\tSPECULAR_LIGHT = mix(vec4(0.0,0.0,0.0,1.0), specular_color, specular_transition).rgb * ALBEDO;\n"
shader.code += "\tDIFFUSE_LIGHT += color.rgb * ALBEDO;\n"
shader.code += "//\tALPHA = color.a;\n"
shader.code +="}\n"
_is_shader_updating = false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment