Converted receptor ring to mesh with shader. WIP: Bezel changes
This commit is contained in:
parent
ec8f1f2d53
commit
204aa83461
1
Bezel.gd
1
Bezel.gd
|
@ -8,7 +8,6 @@ func arc_point_list(center: Vector2, radius: float, angle_from:=0.0, angle_to:=3
|
|||
var point_list = PoolVector2Array()
|
||||
for i in range(points):
|
||||
var angle = deg2rad(angle_from + i * (angle_to - angle_from) / (points-1))
|
||||
# point_list.push_back(center + Vector2(cos(angle), sin(angle)) * radius)
|
||||
point_list.push_back(center + polar2cartesian(radius, angle))
|
||||
return point_list
|
||||
|
||||
|
|
2
Menu.gd
2
Menu.gd
|
@ -443,6 +443,8 @@ func finished_song(song_key, score_data):
|
|||
|
||||
|
||||
func _input(event):
|
||||
if !visible:
|
||||
return
|
||||
if event is InputEventScreenTouch:
|
||||
if event.pressed:
|
||||
var pos = event.position - get_global_transform_with_canvas().get_origin()
|
||||
|
|
91
Receptors.gd
91
Receptors.gd
|
@ -1,9 +1,9 @@
|
|||
#tool
|
||||
extends Node2D
|
||||
extends MeshInstance2D
|
||||
|
||||
var ring_px := 4
|
||||
var receptor_px := 24
|
||||
var shadow_px := 5
|
||||
var ring_px := 4 # Analogous to diameter
|
||||
var receptor_px := 24 # Diameter
|
||||
var shadow_px := 8 # Outer edge, analogous to radius
|
||||
var shadow_color := Color.black
|
||||
var center := Vector2(0.0, 0.0)
|
||||
|
||||
|
@ -28,8 +28,11 @@ func make_ring_mesh(inner_vertices: int, thickness: float, radius: float, skew:=
|
|||
# Outer polygon side-length = inner side-length / sin(inside angle/2)
|
||||
# inside angle for a polygon is pi-tau/n. We already precalculated tau/n for other purposes.
|
||||
var r2 = (radius + thickness*0.5)/sin((PI-angle_increment)/2)
|
||||
var UV_r1 = r1/radius
|
||||
var UV_r2 = r2/radius
|
||||
|
||||
var vertex_list = PoolVector2Array()
|
||||
var UV_list = PoolVector2Array()
|
||||
var inner_list = PoolVector2Array()
|
||||
var outer_list = PoolVector2Array()
|
||||
for i in inner_vertices:
|
||||
|
@ -39,12 +42,16 @@ func make_ring_mesh(inner_vertices: int, thickness: float, radius: float, skew:=
|
|||
vertex_list.push_back(polar2cartesian(r2, angle_o))
|
||||
inner_list.push_back(vertex_list[-2])
|
||||
outer_list.push_back(vertex_list[-1])
|
||||
UV_list.push_back(polar2cartesian(UV_r1, angle_i))
|
||||
UV_list.push_back(polar2cartesian(UV_r2, angle_o))
|
||||
if repeat_start:
|
||||
vertex_list.push_back(vertex_list[0])
|
||||
vertex_list.push_back(vertex_list[1])
|
||||
inner_list.push_back(vertex_list[0])
|
||||
outer_list.push_back(vertex_list[1])
|
||||
return [vertex_list, inner_list, outer_list]
|
||||
UV_list.push_back(UV_list[0])
|
||||
UV_list.push_back(UV_list[1])
|
||||
return [vertex_list, inner_list, outer_list, UV_list]
|
||||
|
||||
func triangle_area(a: Vector2, b: Vector2, c: Vector2) -> float:
|
||||
return 0.5 * abs((a.x-c.x)*(b.y-a.y) - (a.x-b.x)*(c.y-a.y))
|
||||
|
@ -58,7 +65,6 @@ func arc_point_list(center: Vector2, radius: float, angle_from:=0.0, angle_to:=3
|
|||
var point_list = PoolVector2Array()
|
||||
for i in range(points):
|
||||
var angle = deg2rad(angle_from + i * (angle_to - angle_from) / (points-1))
|
||||
# point_list.push_back(center + Vector2(cos(angle), sin(angle)) * radius)
|
||||
point_list.push_back(center + polar2cartesian(radius, angle))
|
||||
return point_list
|
||||
|
||||
|
@ -67,42 +73,79 @@ func draw_old(circles:=true, shadows:=true): # Receptor ring
|
|||
var receptor_centers := arc_point_list(center, GameTheme.receptor_ring_radius, Rules.FIRST_COLUMN_ANGLE_DEG, Rules.FIRST_COLUMN_ANGLE_DEG+360.0-Rules.COLS_ANGLE_DEG, Rules.COLS)
|
||||
|
||||
if shadows:
|
||||
#draw_polyline(receptor_circle, shadow_color, ring_px + shadow_px, true)
|
||||
draw_polyline(receptor_circle, Color.darkblue, ring_px + shadow_px, true)
|
||||
draw_polyline(receptor_circle, shadow_color, ring_px + shadow_px/2, true)
|
||||
if circles:
|
||||
for i in range(len(receptor_centers)):
|
||||
# draw_circle(receptor_centers[i], (receptor_px + shadow_px)/2, shadow_color)
|
||||
draw_circle(receptor_centers[i], (receptor_px + shadow_px)/2, Color.darkblue)
|
||||
draw_circle(receptor_centers[i], receptor_px/2 + shadow_px, shadow_color)
|
||||
|
||||
draw_polyline(receptor_circle, GameTheme.receptor_color, ring_px, true)
|
||||
if circles:
|
||||
for i in range(len(receptor_centers)):
|
||||
draw_circle(receptor_centers[i], receptor_px/2, GameTheme.receptor_color)
|
||||
|
||||
|
||||
func _draw():
|
||||
draw_old(true, true)
|
||||
var mesh_v = $VerticesSlider.value
|
||||
var skew = $SkewSlider.value
|
||||
var dbg_color = Color.red
|
||||
var ring_thickness = receptor_px + shadow_px
|
||||
var ring_vertices = make_ring_mesh(mesh_v, ring_thickness, GameTheme.receptor_ring_radius, skew)
|
||||
var estimated_area = circumscribe_polygon_area(GameTheme.receptor_ring_radius+ring_thickness*0.5, mesh_v) - inscribe_polygon_area(GameTheme.receptor_ring_radius-ring_thickness*0.5, mesh_v)
|
||||
var ideal_ring_area = PI * (pow(GameTheme.receptor_ring_radius+(receptor_px+shadow_px)/2, 2) - pow(GameTheme.receptor_ring_radius-(receptor_px+shadow_px)/2, 2))
|
||||
|
||||
func draw_tris():
|
||||
var dbg_color = Color(1.0, 0.0, 0.0, 1.0)
|
||||
draw_polyline(ring_vertices[0], dbg_color)
|
||||
draw_polyline(ring_vertices[1], dbg_color)
|
||||
draw_polyline(ring_vertices[2], dbg_color)
|
||||
|
||||
var ring_vertices
|
||||
func update_ring_mesh():
|
||||
var mesh_v = $VerticesSlider.value
|
||||
var skew = $SkewSlider.value
|
||||
var ring_thickness = receptor_px + shadow_px*2
|
||||
ring_vertices = make_ring_mesh(mesh_v, ring_thickness, GameTheme.receptor_ring_radius, skew)
|
||||
var temp_mesh = ArrayMesh.new()
|
||||
var mesh_arrays = []
|
||||
mesh_arrays.resize(Mesh.ARRAY_MAX)
|
||||
mesh_arrays[Mesh.ARRAY_VERTEX] = ring_vertices[0]
|
||||
mesh_arrays[Mesh.ARRAY_TEX_UV] = ring_vertices[3]
|
||||
# mesh_arrays[Mesh.ARRAY_COLOR] = colors
|
||||
temp_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, mesh_arrays)
|
||||
mesh = temp_mesh
|
||||
|
||||
|
||||
func _draw():
|
||||
# draw_old(true, true)
|
||||
# draw_tris()
|
||||
var mesh_v = $VerticesSlider.value
|
||||
var skew = $SkewSlider.value
|
||||
var ring_thickness = receptor_px + shadow_px*2
|
||||
var estimated_area = circumscribe_polygon_area(GameTheme.receptor_ring_radius+ring_thickness*0.5, mesh_v) - inscribe_polygon_area(GameTheme.receptor_ring_radius-ring_thickness*0.5, mesh_v)
|
||||
var ideal_ring_area = PI * (pow(GameTheme.receptor_ring_radius+receptor_px/2+shadow_px, 2) - pow(GameTheme.receptor_ring_radius-receptor_px/2-shadow_px, 2))
|
||||
|
||||
# var l = len(ring_vertices)
|
||||
# for i in l:
|
||||
## estimated_area += triangle_area(ring_vertices[i], ring_vertices[(i+1)%l], ring_vertices[(i+2)%l])
|
||||
var quad_area = 4*pow(GameTheme.receptor_ring_radius+(receptor_px+shadow_px)/2, 2)
|
||||
# estimated_area += triangle_area(ring_vertices[i], ring_vertices[(i+1)%l], ring_vertices[(i+2)%l])
|
||||
var quad_area = 4*pow(GameTheme.receptor_ring_radius+receptor_px/2+shadow_px, 2)
|
||||
var fps = Performance.get_monitor(Performance.TIME_FPS)
|
||||
$"/root/main/InputHandler".text = "Vertices: %d*2 Skew: %.3f\nArea: %.0f\n(%.0f%% ideal ring)\n(%.0f%% quad)\nFPS: %.0f"%[mesh_v, skew, estimated_area, 100.0*estimated_area/ideal_ring_area, 100.0*estimated_area/quad_area, fps]
|
||||
# ._draw()
|
||||
|
||||
material.set_shader_param("dot_radius", 0.5*receptor_px/GameTheme.receptor_ring_radius)
|
||||
material.set_shader_param("line_thickness", 0.5*ring_px/GameTheme.receptor_ring_radius)
|
||||
material.set_shader_param("shadow_thickness", shadow_px/GameTheme.receptor_ring_radius)
|
||||
material.set_shader_param("shadow_thickness_taper", -0.75)
|
||||
material.set_shader_param("px", 0.5/GameTheme.receptor_ring_radius)
|
||||
|
||||
func update_ring_mesh_1arg(arg1):
|
||||
# Hack because signals can't discard arguments when connected to smaller slots :(
|
||||
update_ring_mesh()
|
||||
|
||||
func _ready():
|
||||
var receptor_array_image := Image.new()
|
||||
receptor_array_image.create(8, 8, false, Image.FORMAT_RH)
|
||||
receptor_array_image.lock()
|
||||
for i in Rules.COLS:
|
||||
receptor_array_image.set_pixel(i%8, i/8, Color(GameTheme.RADIAL_COL_ANGLES[i], 0.0, 0.0))
|
||||
receptor_array_image.unlock()
|
||||
var receptor_data_tex = ImageTexture.new()
|
||||
receptor_data_tex.create_from_image(receptor_array_image, 0)
|
||||
set_texture(receptor_data_tex)
|
||||
material.set_shader_param("num_receptors", Rules.COLS)
|
||||
|
||||
update_ring_mesh()
|
||||
$VerticesSlider.connect("value_changed", self, "update_ring_mesh_1arg")
|
||||
$SkewSlider.connect("value_changed", self, "update_ring_mesh_1arg")
|
||||
$"/root".connect("size_changed", self, "update")
|
||||
|
||||
func _process(delta):
|
||||
|
|
74
main.tscn
74
main.tscn
|
@ -1,22 +1,35 @@
|
|||
[gd_scene load_steps=17 format=2]
|
||||
[gd_scene load_steps=19 format=2]
|
||||
|
||||
[ext_resource path="res://main.gd" type="Script" id=1]
|
||||
[ext_resource path="res://video.gd" type="Script" id=2]
|
||||
[ext_resource path="res://ScreenFilter.gd" type="Script" id=3]
|
||||
[ext_resource path="res://Receptors.gd" type="Script" id=4]
|
||||
[ext_resource path="res://NoteHandler.gd" type="Script" id=5]
|
||||
[ext_resource path="res://assets/text-4k.png" type="Texture" id=6]
|
||||
[ext_resource path="res://shaders/notelines.shader" type="Shader" id=7]
|
||||
[ext_resource path="res://shaders/notemesh.shader" type="Shader" id=8]
|
||||
[ext_resource path="res://Menu.gd" type="Script" id=9]
|
||||
[ext_resource path="res://shaders/scoretext.tres" type="Material" id=10]
|
||||
[ext_resource path="res://ScoreText.gd" type="Script" id=11]
|
||||
[ext_resource path="res://Bezel.gd" type="Script" id=12]
|
||||
[ext_resource path="res://assets/NotoSans.tres" type="DynamicFont" id=13]
|
||||
[ext_resource path="res://InputHandler.gd" type="Script" id=14]
|
||||
[ext_resource path="res://shaders/receptors.shader" type="Shader" id=4]
|
||||
[ext_resource path="res://Receptors.gd" type="Script" id=5]
|
||||
[ext_resource path="res://NoteHandler.gd" type="Script" id=6]
|
||||
[ext_resource path="res://assets/text-4k.png" type="Texture" id=7]
|
||||
[ext_resource path="res://shaders/notelines.shader" type="Shader" id=8]
|
||||
[ext_resource path="res://shaders/notemesh.shader" type="Shader" id=9]
|
||||
[ext_resource path="res://Menu.gd" type="Script" id=10]
|
||||
[ext_resource path="res://shaders/scoretext.tres" type="Material" id=11]
|
||||
[ext_resource path="res://ScoreText.gd" type="Script" id=12]
|
||||
[ext_resource path="res://Bezel.gd" type="Script" id=13]
|
||||
[ext_resource path="res://assets/NotoSans.tres" type="DynamicFont" id=14]
|
||||
[ext_resource path="res://InputHandler.gd" type="Script" id=15]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=1]
|
||||
shader = ExtResource( 7 )
|
||||
[sub_resource type="ShaderMaterial" id=4]
|
||||
shader = ExtResource( 4 )
|
||||
shader_param/num_receptors = 8
|
||||
shader_param/line_color = Plane( 0, 0, 1, 1 )
|
||||
shader_param/dot_color = Plane( 0, 0, 1, 1 )
|
||||
shader_param/shadow_color = Plane( 0, 0, 0, 1 )
|
||||
shader_param/line_thickness = 0.006
|
||||
shader_param/dot_radius = 0.033
|
||||
shader_param/shadow_thickness = 0.01
|
||||
shader_param/shadow_thickness_taper = 0.33
|
||||
shader_param/px = 0.002
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=2]
|
||||
shader = ExtResource( 8 )
|
||||
shader_param/line_color = Plane( 0.8, 0.8, 1, 0.8 )
|
||||
shader_param/line_color_double = Plane( 1, 1, 0.6, 0.9 )
|
||||
shader_param/dot_color = Plane( 1, 1, 1, 0.8 )
|
||||
|
@ -27,8 +40,8 @@ shader_param/dot_thickness = 0.033
|
|||
shader_param/dot_fullbright_thickness = 0.013
|
||||
shader_param/max_angle = 1.0708
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=2]
|
||||
shader = ExtResource( 8 )
|
||||
[sub_resource type="ShaderMaterial" id=3]
|
||||
shader = ExtResource( 9 )
|
||||
shader_param/bps = null
|
||||
shader_param/star_color = null
|
||||
shader_param/held_color = null
|
||||
|
@ -63,9 +76,11 @@ __meta__ = {
|
|||
script = ExtResource( 3 )
|
||||
|
||||
[node name="Receptors" type="MeshInstance2D" parent="."]
|
||||
script = ExtResource( 4 )
|
||||
material = SubResource( 4 )
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="SkewSlider" type="HSlider" parent="Receptors"]
|
||||
visible = false
|
||||
margin_left = -200.0
|
||||
margin_top = -30.0
|
||||
margin_right = 200.0
|
||||
|
@ -80,6 +95,7 @@ tick_count = 3
|
|||
ticks_on_borders = true
|
||||
|
||||
[node name="VerticesSlider" type="HSlider" parent="Receptors"]
|
||||
visible = false
|
||||
margin_left = -200.0
|
||||
margin_top = -100.0
|
||||
margin_right = 200.0
|
||||
|
@ -88,40 +104,40 @@ min_value = 3.0
|
|||
max_value = 72.0
|
||||
value = 36.0
|
||||
tick_count = 2
|
||||
ticks_on_borders = true
|
||||
|
||||
[node name="NoteHandler" type="Node2D" parent="."]
|
||||
script = ExtResource( 5 )
|
||||
script = ExtResource( 6 )
|
||||
|
||||
[node name="SlideTrailHandler" type="Node2D" parent="NoteHandler"]
|
||||
|
||||
[node name="JudgeText" type="MeshInstance2D" parent="NoteHandler"]
|
||||
texture = ExtResource( 6 )
|
||||
texture = ExtResource( 7 )
|
||||
|
||||
[node name="notelines" type="MeshInstance2D" parent="NoteHandler"]
|
||||
material = SubResource( 1 )
|
||||
|
||||
[node name="meshinstance" type="MeshInstance2D" parent="NoteHandler"]
|
||||
material = SubResource( 2 )
|
||||
|
||||
[node name="meshinstance" type="MeshInstance2D" parent="NoteHandler"]
|
||||
material = SubResource( 3 )
|
||||
|
||||
[node name="Menu" type="Node2D" parent="."]
|
||||
visible = false
|
||||
script = ExtResource( 9 )
|
||||
script = ExtResource( 10 )
|
||||
|
||||
[node name="ScoreText" type="Node2D" parent="Menu"]
|
||||
material = ExtResource( 10 )
|
||||
script = ExtResource( 11 )
|
||||
material = ExtResource( 11 )
|
||||
script = ExtResource( 12 )
|
||||
|
||||
[node name="Bezel" type="Node2D" parent="."]
|
||||
script = ExtResource( 12 )
|
||||
script = ExtResource( 13 )
|
||||
|
||||
[node name="InputHandler" type="Label" parent="."]
|
||||
margin_left = -540.0
|
||||
margin_top = -540.0
|
||||
margin_right = 540.0
|
||||
margin_bottom = 540.0
|
||||
custom_fonts/font = ExtResource( 13 )
|
||||
custom_fonts/font = ExtResource( 14 )
|
||||
text = "Fingers on the screen:"
|
||||
script = ExtResource( 14 )
|
||||
script = ExtResource( 15 )
|
||||
__meta__ = {
|
||||
"_edit_lock_": true
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
shader_type canvas_item;
|
||||
render_mode blend_premul_alpha;
|
||||
|
||||
uniform int num_receptors = 8;
|
||||
uniform vec4 line_color = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
uniform vec4 dot_color = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
uniform vec4 shadow_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
//uniform float bps = 1.0;
|
||||
uniform float line_thickness = 0.006;
|
||||
uniform float dot_radius = 0.033;
|
||||
uniform float shadow_thickness = 0.01;
|
||||
uniform float shadow_thickness_taper = 0.33;
|
||||
uniform float px = 0.002; // Represents 1px in UV space, for AA purposes
|
||||
|
||||
//void vertex() {
|
||||
//}
|
||||
|
||||
float angle_diff(float a, float b) {
|
||||
float d = mod((a - b), 6.28318);
|
||||
if (d > 3.14159) d = 6.28318 - d;
|
||||
return d;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
if (COLOR.rgba != vec4(1.0, 0.0, 0.0, 1.0)) {
|
||||
COLOR.rgba = vec4(0.0);
|
||||
lowp float dist = distance(UV, vec2(0.0));
|
||||
lowp float angle = atan(-UV.y, UV.x);
|
||||
float line_alpha = 0.0;
|
||||
float dot_alpha = 0.0;
|
||||
float shadow_alpha = 0.0;
|
||||
float px2 = px/2.0;
|
||||
|
||||
float diff = abs(dist - 1.0);
|
||||
float d2 = diff - line_thickness;
|
||||
if (d2 < -px2){
|
||||
line_alpha = 1.0;
|
||||
} else if (d2 < shadow_thickness){
|
||||
if (d2 < px2)
|
||||
line_alpha = 1.0 - (d2 + px2)/px;
|
||||
shadow_alpha = 1.0 - min((d2 - shadow_thickness*shadow_thickness_taper)/(shadow_thickness*(1.0-shadow_thickness_taper)), 1.0);
|
||||
}
|
||||
|
||||
// Iterate over all the receptors and check distance to them
|
||||
for (int i=0; i<num_receptors; i++){
|
||||
lowp float rads = texelFetch(TEXTURE, ivec2(i%8, i/8), 0).x;
|
||||
|
||||
// Check for dot distance
|
||||
vec2 uv = vec2(cos(rads), -sin(rads));
|
||||
float dist2 = distance(UV, uv);
|
||||
float diff2 = dist2 - dot_radius;
|
||||
if (diff2 < -px2){
|
||||
dot_alpha = 1.0;
|
||||
} else if (diff2 < shadow_thickness){
|
||||
if (diff2 < px2)
|
||||
dot_alpha = 1.0 - (diff2 + px2)/px;
|
||||
shadow_alpha = max(shadow_alpha, 1.0-min((diff2 - shadow_thickness*shadow_thickness_taper)/(shadow_thickness*(1.0-shadow_thickness_taper)), 1.0));
|
||||
}
|
||||
}
|
||||
line_alpha = max(line_alpha - dot_alpha, 0.0);
|
||||
|
||||
COLOR.rgb = (dot_color.rgb*dot_alpha) + (line_color.rgb*line_alpha) + (shadow_color.rgb*shadow_alpha);
|
||||
COLOR.a = dot_alpha + line_alpha*(1.0-dot_alpha);
|
||||
COLOR.a = COLOR.a + shadow_alpha*(1.0-COLOR.a);
|
||||
COLOR.a = clamp(COLOR.a, 0.0, 1.0); }
|
||||
}
|
Loading…
Reference in New Issue