generated from krampus/template-godot4
Using subviewport texture for gunk mask
Some checks failed
linting & formatting / build (push) Failing after 3s
Some checks failed
linting & formatting / build (push) Failing after 3s
This commit is contained in:
parent
b0078c1bab
commit
0fee0a155f
@ -1,12 +1,11 @@
|
|||||||
[gd_scene load_steps=24 format=3 uid="uid://16ds4fvv72xk"]
|
[gd_scene load_steps=23 format=3 uid="uid://16ds4fvv72xk"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://src/world/gunk_body.gd" id="1_csc4b"]
|
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="1_a67lu"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="1_h436a"]
|
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="1_h436a"]
|
||||||
[ext_resource type="ArrayMesh" uid="uid://lvats6ptrcxt" path="res://assets/props/icosahedron/icosahedron.obj" id="1_kvwui"]
|
[ext_resource type="ArrayMesh" uid="uid://lvats6ptrcxt" path="res://assets/props/icosahedron/icosahedron.obj" id="1_kvwui"]
|
||||||
[ext_resource type="Shader" path="res://src/shaders/gunk.gdshader" id="2_utxkh"]
|
[ext_resource type="Shader" path="res://src/shaders/gunk.gdshader" id="2_utxkh"]
|
||||||
[ext_resource type="Material" uid="uid://byyjoruj8mwe0" path="res://levels/sandbox/debug_gunk_mat.tres" id="3_o7v4k"]
|
[ext_resource type="Material" uid="uid://byyjoruj8mwe0" path="res://levels/sandbox/debug_gunk_mat.tres" id="3_o7v4k"]
|
||||||
[ext_resource type="ArrayMesh" uid="uid://e6syamfwiitk" path="res://assets/props/monkey/monkey.obj" id="4_o55bf"]
|
[ext_resource type="ArrayMesh" uid="uid://e6syamfwiitk" path="res://assets/props/monkey/monkey.obj" id="4_o55bf"]
|
||||||
[ext_resource type="Script" path="res://levels/sandbox/debug_draw.gd" id="7_r3enw"]
|
|
||||||
|
|
||||||
[sub_resource type="Environment" id="Environment_cc548"]
|
[sub_resource type="Environment" id="Environment_cc548"]
|
||||||
background_mode = 1
|
background_mode = 1
|
||||||
@ -114,9 +113,8 @@ mesh = SubResource("CylinderMesh_a1koa")
|
|||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Cylinder"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Cylinder"]
|
||||||
shape = SubResource("CylinderShape3D_uo57d")
|
shape = SubResource("CylinderShape3D_uo57d")
|
||||||
|
|
||||||
[node name="Icosahedron" type="StaticBody3D" parent="Geometry"]
|
[node name="Icosahedron" parent="Geometry" instance=ExtResource("1_a67lu")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.35498, 1.13294, -2.81423)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.35498, 1.13294, -2.81423)
|
||||||
script = ExtResource("1_csc4b")
|
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Geometry/Icosahedron"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="Geometry/Icosahedron"]
|
||||||
mesh = ExtResource("1_kvwui")
|
mesh = ExtResource("1_kvwui")
|
||||||
@ -126,27 +124,15 @@ surface_material_override/0 = ExtResource("3_o7v4k")
|
|||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Icosahedron"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Icosahedron"]
|
||||||
shape = SubResource("ConcavePolygonShape3D_nxc47")
|
shape = SubResource("ConcavePolygonShape3D_nxc47")
|
||||||
|
|
||||||
[node name="Monkey" type="StaticBody3D" parent="Geometry"]
|
[node name="Monkey" parent="Geometry" instance=ExtResource("1_a67lu")]
|
||||||
transform = Transform3D(-0.616239, 0, 0.787559, 0, 1, 0, -0.787559, 0, -0.616239, -2.22512, 1.41158, 2.88581)
|
transform = Transform3D(-0.616239, 0, 0.787559, 0, 1, 0, -0.787559, 0, -0.616239, -2.22512, 1.41158, 2.88581)
|
||||||
script = ExtResource("1_csc4b")
|
|
||||||
|
|
||||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="Geometry/Monkey"]
|
[node name="MeshInstance3D" type="MeshInstance3D" parent="Geometry/Monkey"]
|
||||||
mesh = ExtResource("4_o55bf")
|
mesh = ExtResource("4_o55bf")
|
||||||
|
skeleton = NodePath("")
|
||||||
surface_material_override/0 = SubResource("StandardMaterial3D_7cwtv")
|
surface_material_override/0 = SubResource("StandardMaterial3D_7cwtv")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Monkey"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Geometry/Monkey"]
|
||||||
shape = SubResource("ConcavePolygonShape3D_hvf6a")
|
shape = SubResource("ConcavePolygonShape3D_hvf6a")
|
||||||
|
|
||||||
[node name="Player" parent="." instance=ExtResource("1_h436a")]
|
[node name="Player" parent="." instance=ExtResource("1_h436a")]
|
||||||
|
|
||||||
[node name="DebugDraw" type="Control" parent="."]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
visible = false
|
|
||||||
layout_mode = 3
|
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
mouse_filter = 2
|
|
||||||
script = ExtResource("7_r3enw")
|
|
||||||
|
@ -7,7 +7,7 @@ const JUMP_FORCE := 4.5
|
|||||||
const GROUND_FRICTION := 0.3
|
const GROUND_FRICTION := 0.3
|
||||||
const AIR_FRICTION := 0.03
|
const AIR_FRICTION := 0.03
|
||||||
|
|
||||||
const SPRAY_RADIUS := 15
|
const SPRAY_RADIUS := 8
|
||||||
|
|
||||||
var gravity: Vector3 = (
|
var gravity: Vector3 = (
|
||||||
ProjectSettings.get_setting("physics/3d/default_gravity")
|
ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||||
|
@ -13,8 +13,6 @@ uniform highp sampler2D gunk_normal_map;
|
|||||||
|
|
||||||
|
|
||||||
void fragment() {
|
void fragment() {
|
||||||
float mask = texture(gunk_mask, UV).r;
|
|
||||||
if(mask < 0.1) {
|
|
||||||
float value = texture(gunk_noise, UV).r;
|
float value = texture(gunk_noise, UV).r;
|
||||||
vec4 color = mix(color_1, color_2, value);
|
vec4 color = mix(color_1, color_2, value);
|
||||||
float roughness_mix = value * roughness;
|
float roughness_mix = value * roughness;
|
||||||
@ -23,8 +21,5 @@ void fragment() {
|
|||||||
ROUGHNESS = roughness_mix;
|
ROUGHNESS = roughness_mix;
|
||||||
SPECULAR = 0.5 * inversesqrt(specular_contribution);
|
SPECULAR = 0.5 * inversesqrt(specular_contribution);
|
||||||
NORMAL_MAP = texture(gunk_normal_map, UV).xyz;
|
NORMAL_MAP = texture(gunk_normal_map, UV).xyz;
|
||||||
ALPHA = 1.0;
|
ALPHA = 1.0 - texture(gunk_mask, UV).r;
|
||||||
} else {
|
|
||||||
ALPHA = 0.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
22
src/world/gunk_body/draw_controller.gd
Normal file
22
src/world/gunk_body/draw_controller.gd
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
class_name DrawController extends Control
|
||||||
|
|
||||||
|
var _draw_queue: Array[Callable] = []
|
||||||
|
|
||||||
|
var _dirty := true
|
||||||
|
|
||||||
|
|
||||||
|
func queue_draw(op: Callable) -> void:
|
||||||
|
_draw_queue.push_back(op)
|
||||||
|
_dirty = true
|
||||||
|
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
while _draw_queue:
|
||||||
|
var op: Callable = _draw_queue.pop_front()
|
||||||
|
op.call()
|
||||||
|
|
||||||
|
|
||||||
|
func _process(_delta: float) -> void:
|
||||||
|
if _dirty:
|
||||||
|
queue_redraw()
|
||||||
|
_dirty = false
|
@ -1,34 +1,24 @@
|
|||||||
class_name GunkBody extends StaticBody3D
|
class_name GunkBody extends StaticBody3D
|
||||||
## StaticBody3D with an associated "gunkable" mesh.
|
## StaticBody3D with an associated "gunkable" mesh.
|
||||||
|
|
||||||
const MASK_DIM := 512
|
|
||||||
const FACE_EPSILON := 0.4
|
const FACE_EPSILON := 0.4
|
||||||
const MASK_COLOR := Color.RED
|
const MASK_COLOR := Color.RED
|
||||||
|
|
||||||
@export var mask_image: Image
|
|
||||||
|
|
||||||
var meshtool := MeshDataTool.new()
|
var meshtool := MeshDataTool.new()
|
||||||
|
|
||||||
@onready var mesh_instance: MeshInstance3D = $MeshInstance3D
|
@onready var mesh_instance: MeshInstance3D = $MeshInstance3D
|
||||||
@onready var mesh: ArrayMesh = mesh_instance.mesh
|
@onready var mesh: ArrayMesh = mesh_instance.mesh
|
||||||
@onready var gunk_mat: ShaderMaterial = mesh_instance.get_surface_override_material(0).next_pass
|
@onready var gunk_mat: ShaderMaterial = mesh_instance.get_surface_override_material(0).next_pass
|
||||||
|
|
||||||
@onready var debug_draw: DebugDraw = %DebugDraw
|
@onready var mask_viewport: SubViewport = %MaskViewport
|
||||||
|
@onready var mask_control: DrawController = %MaskControl
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if not mask_image:
|
gunk_mat.set_shader_parameter("gunk_mask", mask_viewport.get_texture())
|
||||||
mask_image = Image.create_empty(MASK_DIM, MASK_DIM, false, Image.FORMAT_L8)
|
|
||||||
_update_gunk_material()
|
|
||||||
|
|
||||||
meshtool.create_from_surface(mesh, 0)
|
meshtool.create_from_surface(mesh, 0)
|
||||||
|
|
||||||
|
|
||||||
## Must be called internally whenever `mask_image` is updated
|
|
||||||
func _update_gunk_material() -> void:
|
|
||||||
gunk_mat.set_shader_parameter("gunk_mask", ImageTexture.create_from_image(mask_image))
|
|
||||||
|
|
||||||
|
|
||||||
## Transform cartesian coordinates to barycentric wrt the given triangle
|
## Transform cartesian coordinates to barycentric wrt the given triangle
|
||||||
func _barycentric(p: Vector3, a: Vector3, b: Vector3, c: Vector3) -> Vector3:
|
func _barycentric(p: Vector3, a: Vector3, b: Vector3, c: Vector3) -> Vector3:
|
||||||
var v0 := b - a
|
var v0 := b - a
|
||||||
@ -83,14 +73,10 @@ func _get_uv(point: Vector3, normal: Vector3) -> Vector2:
|
|||||||
|
|
||||||
## Paint a rectangle on the mask at a given point & normal on the mesh.
|
## Paint a rectangle on the mask at a given point & normal on the mesh.
|
||||||
func paint_mask(point: Vector3, normal: Vector3, radius: int) -> void:
|
func paint_mask(point: Vector3, normal: Vector3, radius: int) -> void:
|
||||||
# debug_draw.draw_vector(normal, point)
|
|
||||||
var local_point := point * global_transform
|
var local_point := point * global_transform
|
||||||
var local_normal := normal * global_basis
|
var local_normal := normal * global_basis
|
||||||
var uv := _get_uv(local_point, local_normal)
|
var uv := _get_uv(local_point, local_normal)
|
||||||
if uv == Vector2.INF:
|
if uv == Vector2.INF:
|
||||||
return
|
return
|
||||||
var px_center: Vector2i = Vector2i(uv * Vector2(mask_image.get_size()))
|
var px_center: Vector2 = uv * mask_control.size
|
||||||
var rect := Rect2i(px_center.x - radius, px_center.y - radius, 2 * radius, 2 * radius)
|
mask_control.queue_draw(func() -> void: mask_control.draw_circle(px_center, radius, MASK_COLOR))
|
||||||
mask_image.fill_rect(rect, MASK_COLOR)
|
|
||||||
# TODO: can we call this once after all painting in a single frame is finished?
|
|
||||||
_update_gunk_material()
|
|
26
src/world/gunk_body/gunk_body.tscn
Normal file
26
src/world/gunk_body/gunk_body.tscn
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://c2omlx4ptrc01"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://src/world/gunk_body/gunk_body.gd" id="1_qqbpr"]
|
||||||
|
[ext_resource type="Script" path="res://src/world/gunk_body/draw_controller.gd" id="2_kkcjw"]
|
||||||
|
|
||||||
|
[node name="GunkBody" type="StaticBody3D"]
|
||||||
|
script = ExtResource("1_qqbpr")
|
||||||
|
|
||||||
|
[node name="MaskViewport" type="SubViewport" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
handle_input_locally = false
|
||||||
|
msaa_2d = 3
|
||||||
|
canvas_item_default_texture_filter = 0
|
||||||
|
size = Vector2i(1024, 1024)
|
||||||
|
render_target_clear_mode = 1
|
||||||
|
render_target_update_mode = 4
|
||||||
|
|
||||||
|
[node name="MaskControl" type="Control" parent="MaskViewport"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("2_kkcjw")
|
Loading…
x
Reference in New Issue
Block a user