Skip to content

Commit 044afe7

Browse files
authored
Merge pull request #743 from Calinou/add-3d-antialiasing-demo
Add a 3D antialiasing demo
2 parents 5efee67 + 9dbd05a commit 044afe7

39 files changed

+2045
-0
lines changed

3d/antialiasing/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# 3D Anti-Aliasing
2+
3+
This project showcases the various 3D antialiasing techniques supported by Godot.
4+
5+
- **Multisample antialiasing (MSAA):** High quality, high performance cost.
6+
Does not blur the image.
7+
- Does not affect shader-induced aliasing (such as specular aliasing) or alpha
8+
scissor materials, so these will remain aliased.
9+
- **Fast approximate antialiasing (FXAA):** Medium quality, low performance cost.
10+
Slightly blurs the image.
11+
- **Temporal antialiasing (TAA):** High-quality, low performance cost. Slightly
12+
blurs the image (but less so than FXAA).
13+
- Antialiasing quality is worse on fast-moving objects than other methods,
14+
especially at lower framerates since the TAA won't have enough time to
15+
converge on those objects.
16+
- Can introduce ghosting artifacts on moving objects, especially if motion
17+
vectors are not correctly generated from a given material shader.
18+
- **Supersampling (SSAA):** The highest-quality technique, but also the most
19+
expensive. Does not blur the image.
20+
- 200% resolution scale is equivalent to 4× SSAA, as each dimension is
21+
doubled. For example, if running in a 1920×1080 window at 200% render scale,
22+
the 3D framebuffer will be 3840×2160.
23+
- SSAA can be used together with FXAA or TAA to counter the blurring added by
24+
those algorithms, while further improving antialiasing quality.
25+
26+
Godot allows using multiple antialiasing techniques at the same time. This can
27+
be useful to obtain the best possible quality, or to find a better performance
28+
tradeoff.
29+
30+
Language: GDScript
31+
32+
Renderer: Vulkan Clustered
33+
34+
## Screenshots
35+
36+
![Screenshot](screenshots/3d_anti_aliasing.png)
37+
38+
## Licenses
39+
40+
Files in the `polyhaven/` folder are downloaded from <https://polyhaven.com/a/dutch_ship_medium>
41+
and are licensed under CC0 1.0 Universal.

3d/antialiasing/anti_aliasing.gd

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
extends Node
2+
3+
const ROT_SPEED = 0.003
4+
const ZOOM_SPEED = 0.125
5+
const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE
6+
7+
var tester_index = 0
8+
var rot_x = -TAU / 16 # This must be kept in sync with RotationX.
9+
var rot_y = TAU / 8 # This must be kept in sync with CameraHolder.
10+
var camera_distance = 2.0
11+
var base_height = ProjectSettings.get_setting("display/window/size/viewport_height")
12+
13+
@onready var testers = $Testers
14+
@onready var camera_holder = $CameraHolder # Has a position and rotates on Y.
15+
@onready var rotation_x = $CameraHolder/RotationX
16+
@onready var camera = $CameraHolder/RotationX/Camera3D
17+
18+
19+
func _ready():
20+
camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0))
21+
rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0))
22+
update_gui()
23+
24+
25+
func _unhandled_input(event):
26+
if event.is_action_pressed("ui_left"):
27+
_on_previous_pressed()
28+
if event.is_action_pressed("ui_right"):
29+
_on_next_pressed()
30+
31+
if event is InputEventMouseButton:
32+
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
33+
camera_distance -= ZOOM_SPEED
34+
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
35+
camera_distance += ZOOM_SPEED
36+
camera_distance = clamp(camera_distance, 1.5, 6)
37+
38+
if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS:
39+
# Compensate motion speed to be resolution-independent (based on the window height).
40+
var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height
41+
rot_y -= relative_motion.x * ROT_SPEED
42+
rot_x -= relative_motion.y * ROT_SPEED
43+
rot_x = clamp(rot_x, -1.57, 0)
44+
camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0))
45+
rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0))
46+
47+
48+
func _process(delta):
49+
var current_tester = testers.get_child(tester_index)
50+
# This code assumes CameraHolder's X and Y coordinates are already correct.
51+
var current_position = camera_holder.global_transform.origin.z
52+
var target_position = current_tester.global_transform.origin.z
53+
camera_holder.global_transform.origin.z = lerp(current_position, target_position, 3 * delta)
54+
camera.position.z = lerp(camera.position.z, camera_distance, 10 * delta)
55+
56+
57+
func _on_previous_pressed():
58+
tester_index = max(0, tester_index - 1)
59+
update_gui()
60+
61+
62+
func _on_next_pressed():
63+
tester_index = min(tester_index + 1, testers.get_child_count() - 1)
64+
update_gui()
65+
66+
67+
func update_gui():
68+
$TestName.text = str(testers.get_child(tester_index).name).capitalize()
69+
$Previous.disabled = tester_index == 0
70+
$Next.disabled = tester_index == testers.get_child_count() - 1
71+
72+
73+
func _on_fxaa_toggled(button_pressed):
74+
get_viewport().screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA if button_pressed else Viewport.SCREEN_SPACE_AA_DISABLED
75+
76+
77+
func _on_temporal_antialiasing_toggled(button_pressed):
78+
get_viewport().use_taa = button_pressed
79+
80+
81+
func _on_msaa_item_selected(index):
82+
get_viewport().msaa = index
83+
84+
85+
func _on_render_scale_item_selected(index):
86+
match index:
87+
0:
88+
get_viewport().scaling_3d_scale = 0.5
89+
1:
90+
get_viewport().scaling_3d_scale = 0.75
91+
2:
92+
get_viewport().scaling_3d_scale = 1.0
93+
3:
94+
get_viewport().scaling_3d_scale = 1.25
95+
4:
96+
get_viewport().scaling_3d_scale = 1.5
97+
5:
98+
get_viewport().scaling_3d_scale = 1.75
99+
6:
100+
get_viewport().scaling_3d_scale = 2.0

0 commit comments

Comments
 (0)