-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
de27fa1
commit 8598453
Showing
39 changed files
with
2,045 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# 3D Anti-Aliasing | ||
|
||
This project showcases the various 3D antialiasing techniques supported by Godot. | ||
|
||
- **Multisample antialiasing (MSAA):** High quality, high performance cost. | ||
Does not blur the image. | ||
- Does not affect shader-induced aliasing (such as specular aliasing) or alpha | ||
scissor materials, so these will remain aliased. | ||
- **Fast approximate antialiasing (FXAA):** Medium quality, low performance cost. | ||
Slightly blurs the image. | ||
- **Temporal antialiasing (TAA):** High-quality, low performance cost. Slightly | ||
blurs the image (but less so than FXAA). | ||
- Antialiasing quality is worse on fast-moving objects than other methods, | ||
especially at lower framerates since the TAA won't have enough time to | ||
converge on those objects. | ||
- Can introduce ghosting artifacts on moving objects, especially if motion | ||
vectors are not correctly generated from a given material shader. | ||
- **Supersampling (SSAA):** The highest-quality technique, but also the most | ||
expensive. Does not blur the image. | ||
- 200% resolution scale is equivalent to 4× SSAA, as each dimension is | ||
doubled. For example, if running in a 1920×1080 window at 200% render scale, | ||
the 3D framebuffer will be 3840×2160. | ||
- SSAA can be used together with FXAA or TAA to counter the blurring added by | ||
those algorithms, while further improving antialiasing quality. | ||
|
||
Godot allows using multiple antialiasing techniques at the same time. This can | ||
be useful to obtain the best possible quality, or to find a better performance | ||
tradeoff. | ||
|
||
Language: GDScript | ||
|
||
Renderer: Vulkan Clustered | ||
|
||
## Screenshots | ||
|
||
![Screenshot](screenshots/3d_anti_aliasing.png) | ||
|
||
## Licenses | ||
|
||
Files in the `polyhaven/` folder are downloaded from <https://polyhaven.com/a/dutch_ship_medium> | ||
and are licensed under CC0 1.0 Universal. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
extends Node | ||
|
||
const ROT_SPEED = 0.003 | ||
const ZOOM_SPEED = 0.125 | ||
const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE | ||
|
||
var tester_index = 0 | ||
var rot_x = -TAU / 16 # This must be kept in sync with RotationX. | ||
var rot_y = TAU / 8 # This must be kept in sync with CameraHolder. | ||
var camera_distance = 2.0 | ||
var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") | ||
|
||
@onready var testers = $Testers | ||
@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. | ||
@onready var rotation_x = $CameraHolder/RotationX | ||
@onready var camera = $CameraHolder/RotationX/Camera3D | ||
|
||
|
||
func _ready(): | ||
camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) | ||
rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) | ||
update_gui() | ||
|
||
|
||
func _unhandled_input(event): | ||
if event.is_action_pressed("ui_left"): | ||
_on_previous_pressed() | ||
if event.is_action_pressed("ui_right"): | ||
_on_next_pressed() | ||
|
||
if event is InputEventMouseButton: | ||
if event.button_index == MOUSE_BUTTON_WHEEL_UP: | ||
camera_distance -= ZOOM_SPEED | ||
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN: | ||
camera_distance += ZOOM_SPEED | ||
camera_distance = clamp(camera_distance, 1.5, 6) | ||
|
||
if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: | ||
# Compensate motion speed to be resolution-independent (based on the window height). | ||
var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height | ||
rot_y -= relative_motion.x * ROT_SPEED | ||
rot_x -= relative_motion.y * ROT_SPEED | ||
rot_x = clamp(rot_x, -1.57, 0) | ||
camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) | ||
rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) | ||
|
||
|
||
func _process(delta): | ||
var current_tester = testers.get_child(tester_index) | ||
# This code assumes CameraHolder's X and Y coordinates are already correct. | ||
var current_position = camera_holder.global_transform.origin.z | ||
var target_position = current_tester.global_transform.origin.z | ||
camera_holder.global_transform.origin.z = lerp(current_position, target_position, 3 * delta) | ||
camera.position.z = lerp(camera.position.z, camera_distance, 10 * delta) | ||
|
||
|
||
func _on_previous_pressed(): | ||
tester_index = max(0, tester_index - 1) | ||
update_gui() | ||
|
||
|
||
func _on_next_pressed(): | ||
tester_index = min(tester_index + 1, testers.get_child_count() - 1) | ||
update_gui() | ||
|
||
|
||
func update_gui(): | ||
$TestName.text = str(testers.get_child(tester_index).name).capitalize() | ||
$Previous.disabled = tester_index == 0 | ||
$Next.disabled = tester_index == testers.get_child_count() - 1 | ||
|
||
|
||
func _on_fxaa_toggled(button_pressed): | ||
get_viewport().screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA if button_pressed else Viewport.SCREEN_SPACE_AA_DISABLED | ||
|
||
|
||
func _on_temporal_antialiasing_toggled(button_pressed): | ||
get_viewport().use_taa = button_pressed | ||
|
||
|
||
func _on_msaa_item_selected(index): | ||
get_viewport().msaa = index | ||
|
||
|
||
func _on_render_scale_item_selected(index): | ||
match index: | ||
0: | ||
get_viewport().scaling_3d_scale = 0.5 | ||
1: | ||
get_viewport().scaling_3d_scale = 0.75 | ||
2: | ||
get_viewport().scaling_3d_scale = 1.0 | ||
3: | ||
get_viewport().scaling_3d_scale = 1.25 | ||
4: | ||
get_viewport().scaling_3d_scale = 1.5 | ||
5: | ||
get_viewport().scaling_3d_scale = 1.75 | ||
6: | ||
get_viewport().scaling_3d_scale = 2.0 |
Oops, something went wrong.