Files
godot-website/article/gsoc-2022-progress-report-1/index.html
2025-06-12 18:44:07 +00:00

23 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Godot Engine"><meta name=description content="This year we have 3 students working on exciting projects as part of the Google Summer of Code. In this progress report they present their work on refactoring the ColorPicker and its UX, making code editors detachable from the main editor window, and improving the GPU lightmapper."><script defer data-domain=godotengine.org src=https://plausible.godot.foundation/js/script.file-downloads.outbound-links.js></script><meta property="og:site_name" content="Godot Engine"><meta property="og:url" content="https://godotengine.org/article/gsoc-2022-progress-report-1/"><meta property="og:type" content="website"><meta property="og:description" content="This year we have 3 students working on exciting projects as part of the Google Summer of Code. In this progress report they present their work on refactoring the ColorPicker and its UX, making code editors detachable from the main editor window, and improving the GPU lightmapper."><meta property="og:image" content="https://godotengine.org/storage/app/uploads/public/62f/3c8/fac/62f3c8fac0406080699461.png"><meta name=twitter:card content="summary_large_image"><meta property="twitter:domain" content="godotengine.org"><meta property="twitter:url" content="https://godotengine.org/article/gsoc-2022-progress-report-1/"><meta property="og:title" content="GSoC 2022 - Progress report #1 Godot Engine"><title>GSoC 2022 - Progress report #1 Godot Engine</title>
<link rel=alternate type=application/rss+xml title="Godot News" href=/rss.xml><link rel=alternate type=application/json title="Godot News" href=/rss.json><link rel=alternate type=application/atom+xml title="Godot News" href=/atom.xml><link rel=icon href=/assets/favicon.png sizes=any><link rel=icon href=/assets/favicon.svg type=image/svg+xml><link rel=stylesheet href=/assets/css/main.css?121><link rel=stylesheet href=/assets/css/header.css?1><link rel=stylesheet href=/assets/css/tobii.min.css><link rel=preload as=font href=/assets/fonts/Montserrat-Italic-VariableFont_wght.woff2 crossorigin><link rel=preload as=font href=/assets/fonts/Montserrat-VariableFont_wght.woff2 crossorigin><link rel=me href=https://mastodon.gamedev.place/@godotengine><input type=checkbox id=nav_toggle_cb><header class="flex column"><div class="container flex align-center"><div id=nav_head><a href=/ id=logo-link><img class=nav-logo src=/assets/logo.svg width=136 height=48 alt="Godot Engine">
<img class="nav-logo dark-logo" src=/assets/logo_dark.svg width=136 height=48 alt="Godot Engine"></a><div class=mobile-links><span class="fund mobile"><a href=https://fund.godotengine.org><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width:13px;fill:#fff;margin-right:4px"><path d="M47.6 300.4 228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6.0 115.2.0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg> Donate</a></span>
<label for=nav_toggle_cb id=nav_toggle_btn><img src=/assets/icons/hamburger.svg width=24 height=24 alt="Main menu"></label></div></div><nav id=nav><ul class=left><li><a href=/features/>Features</a><li><a href=/showcase/>Showcase</a><li><a href=/blog/>Blog</a><li><a href=/community/>Community</a><li><a href=https://godotengine.org/asset-library/asset>Assets</a></ul><ul class=right><li><a href=/download/windows/ class=set-os-download-url>Download</a><li><a href=https://docs.godotengine.org>Docs</a><li><a href=https://docs.godotengine.org/en/stable/contributing/how_to_contribute.html>Contribute</a><li class="fund desktop"><a href=https://fund.godotengine.org><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width:13px;fill:#fff;margin-right:4px;top:1px;position:relative"><path d="M47.6 300.4 228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6.0 115.2.0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg> Donate</a></ul></nav></div></header><main><style>body{background-color:var(--background-color)}h1{margin-bottom:8px;margin-top:32px}:not(pre)>code{background:var(--code-background-color);padding:1px 4px;font-size:.95em;border-radius:3px}pre{background:var(--codeblock-background-color);color:var(--codeblock-color)}pre code{display:block;overflow-x:auto;padding:.5em}.date-big{line-height:2;margin-left:32px}article{background-color:var(--base-color);box-shadow:0 3px 2px rgba(0,0,0,.15)}figure{margin:0}figure img{margin:0}article img,article video{max-width:100%;height:auto;display:block;margin:auto;margin-top:16px;margin-bottom:16px}article h1{margin-top:64px}article h2,article h3,article h4{margin-top:42px}.article-info{display:flex;flex-direction:column;gap:8px}.article-metadata{display:flex;gap:24px;align-items:center;font-family:var(--header-font-family);margin-bottom:12px}@media(max-width:900px){.article-metadata{flex-direction:column;align-items:flex-start;gap:16px}}.article-author{color:var(--base-color-text-subtitle-date);font-weight:700;font-size:18px;flex-grow:1;display:flex;gap:12px;align-items:center}.article-author .avatar{border-radius:100%;margin:0;background:0 0}.article-author .by{color:var(--base-color-text-subtitle)}.article-metadata .date{color:var(--base-color-text-subtitle-date)}.article-metadata .date.post-recent-highlight{color:var(--post-recent-highlight-color);opacity:.8}.article-metadata .date.post-recent-highlight::after{font-size:80%;content:"NEW";border:2px solid var(--post-recent-highlight-color);padding:2px 3px;margin-left:8px}.tag.active{filter:saturate(.75)}@media screen and (min-width:900px){article .content{width:70%;margin:auto}}@media(max-width:900px){body{background-color:var(--base-color)}article{background-color:initial;box-shadow:none}article img:first-child,article video:first-child{max-width:100%}}.blog-navigation{display:grid;grid-template-columns:1fr 1fr;padding-top:30px;padding-bottom:60px}.blog-navigation .next{text-align:right}@media(max-width:900px){.blog-navigation{grid-template-columns:1fr;gap:20px;border-top:1px solid var(--code-background-color)}.blog-navigation .next{text-align:left}}.blog-navigation span{opacity:.6;font-weight:700;margin-bottom:5px;display:block}.blog-navigation a{display:inline-block;text-decoration:none;color:inherit;opacity:.6;transition:opacity .2s}.blog-navigation a:hover{opacity:1}</style><link rel=stylesheet href=/assets/css/highlight.obsidian.min.css><div class=container><article class=padded><div class="content article-container"><figure class=article-cover><img src=/storage/app/uploads/public/62f/3c8/fac/62f3c8fac0406080699461.png title alt=" " class=rounded-lg style=width:100%;height:auto;background-color:initial></figure><div class=article-info><h1>GSoC 2022 - Progress report #1</h1><div class=article-metadata><div class=article-author><span>By: </span><img class=avatar width=25 height=25 src=/assets/images/authors/akien.webp alt="Rémi Verschelde" loading=lazy>
<span class=by>Rémi Verschelde</span></div><span class=date data-post-date="2022-08-10 15:05:19 +0000">10 August 2022</span></div><div class=tags><a href=/blog/progress-report><div class="tag active">Progress Report</div></a></div></div><div class="card card-warning"><p>This article is from <strong>August 2022</strong>, some of its contents might be outdated and no longer accurate.<br>You can find up-to-date information about the engine in the <a href=https://docs.godotengine.org/en/stable/>official documentation</a>.</div><div class=article-body><p>Like in previous years, Godot is participating again in the <a href=https://summerofcode.withgoogle.com/>Google Summer of Code</a> program for its 2022 edition.<p>This year we selected 3 projects, and the 3 students and their mentors have now been working on their projects for two months. We asked them to write a progress report to present what theyre working on and the current status.<p>Here are the 3 projects/students with links to the relevant sections in this post:<ul><li><a href=#colorpicker>Refactor and UX updates of ColorPicker</a> by Vitika Soni (<a href=https://github.com/Vitika9>Vitika9</a>)<li><a href=#multiwindow>Multi window code editors</a> by <a href=https://github.com/trollodel>trollodel</a><li><a href=#gpu-lightmapper>GPU lightmapper enhancements</a> by Priyansh Rathi (<a href=https://github.com/techiepriyansh>techiepriyansh</a>)</ul><p>Theyve all been doing outstanding work so far, and were looking forward to integrating all those changes in the engine!<hr><p><a id=colorpicker></a><h2 id=refactor-and-ux-updates-of-colorpicker>Refactor and UX updates of ColorPicker</h2><ul><li>Project: Refactor and UX updates of ColorPicker<li>Student: Vitika Soni (<a href=https://github.com/Vitika9>Vitika9</a>)<li>Mentors: Rémi Verschelde (<a href=https://github.com/akien-mga>akien-mga</a>) and Tomasz Chabora (<a href=https://github.com/KoBeWi>KoBeWi</a>)<li>Branches: <a href=https://github.com/Vitika9/godot/tree/gsoc-colorpicker><code class="language-plaintext highlighter-rouge">Vitika9/gsoc-colorpicker</code></a>, <a href=https://github.com/Vitika9/godot/tree/gsoc-colorpicker-ux><code class="language-plaintext highlighter-rouge">Vitika9/gsoc-colorpicker-ux</code></a><li>PRs: <a href=https://github.com/godotengine/godot/pull/62075>#62075</a>, <a href=https://github.com/godotengine/godot/pull/62910>#62910</a></ul><h3 id=project-description>Project description</h3><p>RGB, HSV and Raw modes of <code class="language-plaintext highlighter-rouge">ColorPicker</code> were never properly separated, resulting in lots of messy code like this:<div class="language-c++ highlighter-rouge"><div class=highlight><pre class=highlight><code><span class=k>if</span> <span class=p>(</span><span class=n>hsv_mode_enabled</span><span class=p>)</span> <span class=p>{</span>
<span class=n>set_raw_mode</span><span class=p>(</span><span class=nb>false</span><span class=p>);</span>
<span class=n>btn_raw</span><span class=o>-&gt;</span><span class=n>set_disabled</span><span class=p>(</span><span class=nb>true</span><span class=p>);</span>
<span class=p>}</span> <span class=k>else</span> <span class=nf>if</span> <span class=p>(</span><span class=n>raw_mode_enabled</span><span class=p>)</span> <span class=p>{</span>
<span class=n>set_hsv_mode</span><span class=p>(</span><span class=nb>false</span><span class=p>);</span>
<span class=n>btn_hsv</span><span class=o>-&gt;</span><span class=n>set_disabled</span><span class=p>(</span><span class=nb>true</span><span class=p>);</span>
<span class=p>}</span> <span class=k>else</span> <span class=p>{</span>
<span class=n>btn_raw</span><span class=o>-&gt;</span><span class=n>set_disabled</span><span class=p>(</span><span class=nb>false</span><span class=p>);</span>
<span class=n>btn_hsv</span><span class=o>-&gt;</span><span class=n>set_disabled</span><span class=p>(</span><span class=nb>false</span><span class=p>);</span>
<span class=p>}</span>
</code></pre></div></div><p>With OKHSL mode added in <a href=https://github.com/godotengine/godot/pull/59786>#59786</a>, it was necessary to refactor <code class="language-plaintext highlighter-rouge">ColorPicker</code> to make color modes more maintainable and easier to add, which is covered in this project along with updating its UX.<p>This part of the project was complemented and merged in <a href=https://github.com/godotengine/godot/pull/62075>#62075</a>.<h3 id=separation-of-color-modes>Separation of color modes</h3><p>With the guidance of my mentors, I worked on reimplementing color modes with an object-oriented approach by making separate classes for each color mode like <code class="language-plaintext highlighter-rouge">ColorModeRGB</code>, <code class="language-plaintext highlighter-rouge">ColorModeHSV</code>, etc. and made them inherit from newly made <code class="language-plaintext highlighter-rouge">ColorMode</code> abstract class. <code class="language-plaintext highlighter-rouge">ColorMode</code> has the following methods which get called on the selected instance by <code class="language-plaintext highlighter-rouge">ColorPicker</code>:<ul><li><code class="language-plaintext highlighter-rouge">get_name()</code><li><code class="language-plaintext highlighter-rouge">get_slider_count()</code> (useful if we add CMYK in future)<li><code class="language-plaintext highlighter-rouge">get_slider_step()</code><li><code class="language-plaintext highlighter-rouge">get_slider_label(idx)</code><li><code class="language-plaintext highlighter-rouge">get_slider_max(idx)</code><li><code class="language-plaintext highlighter-rouge">get_slider_value(idx)</code> (getting the slider value from color)<li><code class="language-plaintext highlighter-rouge">get_color()</code> (getting the color value from sliders)<li><code class="language-plaintext highlighter-rouge">slider_draw(which)</code> (function for sliders <code class="language-plaintext highlighter-rouge">draw</code> signal)<li><code class="language-plaintext highlighter-rouge">apply_theme()</code><li><code class="language-plaintext highlighter-rouge">get_shape_override()</code> (useful for <code class="language-plaintext highlighter-rouge">ColorModeOKHSL</code> as it needs OKHSL circle as picker shape)</ul><h3 id=ux-updates>UX updates</h3><p>Next to this C++ refactoring, I have been working on improving the UX of ColorPicker. I am taking reference from wireframes provided by Taylor Wright (<a href=https://github.com/redlamp>redlamp</a>) which can be found <a href=https://github.com/godotengine/godot-proposals/issues/4353#issuecomment-1098934700>in godot-proposals#4353</a> and trying to follow this design as close as possible. Below are the changes which I have made so far:<table><thead><tr><th>Before<th>Mode selection<th>Shape selection<th>Preset dragging<th>Recent presets<th>Uncolorized sliders<tbody><tr><td><img width=166 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-before.png><td><img width=155 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-mode-selection.png><td><img width=155 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-shape-selection.png><td><img width=153 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-preset-dragging.png><td><img width=154 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-recent-presets.png><td><img width=156 alt=image src=/storage/app/media/gsoc/2022-1/colorpicker-uncolorized-sliders.png></table><p>This part of the project is still a work-in-progress, check <a href=https://github.com/godotengine/godot/pull/62910>#62910</a> for details.<h3 id=whats-next>Whats next</h3><p>Firstly, I will complete the UX part, then the next goal is to reimplement picker shapes with the same approach as color modes without breaking anything. Also, there are some bugs to be fixed.<p><a id=multiwindow></a><h2 id=multi-window-code-editors>Multi window code editors</h2><ul><li>Project: Allow undocking the Script editor and the Shader editor<li>Student: <a href=https://github.com/trollodel>trollodel</a><li>Mentors: Hugo Locurcio (<a href=https://github.com/Calinou>Calinou</a>), Michael Alexsander (<a href=https://github.com/YeldhamDev>Yeldham</a>)<li>Branch: <a href=https://github.com/trollodel/godot/tree/gsoc_2022_multiwindow><code class="language-plaintext highlighter-rouge">trollodel/gsoc_2022_multiwindow</code></a><li>PR: <a href=https://github.com/godotengine/godot/pull/62378>#62378</a></ul><h3 id=introduction>Introduction</h3><p>Undocking parts of the Godot editor UI is something quite desired in the community. For things like the Script editor, this means you can move it to another screen, move the undocked window to be side-by-side with the main window, or just using <kbd>Alt+Tab</kbd> to change between the main window and the undocked one.<p>In this project, Ill focus to make the Script editor and the Shader editor undockable, and keep the undocked windows after editor restarts.<h3 id=current-progress>Current progress</h3><p>Detaching the Script editor and the Shader editor is done for the most part. Let me show a video demonstration of it.</p><video controls muted>
<source src=/storage/app/media/gsoc/2022-1/multiwindow-showcase.mp4 type=video/mp4></video><p>Along with the basic feature and controls, some integrations were done:<ul><li>When the Script editor is undocked, the last selected Viewport is shown.<li>When the Script button is clicked and the Script editor is undocked, the Script editor window is focused.<li>Undocking the code editors can be done using shortcuts and command palette too.</ul><p><img src=/storage/app/media/gsoc/2022-1/multiwindow-command-palette.png alt="Command palette"><h4 id=window-save-and-restore>Window save and restore</h4><p>Undocking the Script editor (or the Shader editor) on every editor restart and placing it in the second screen can be annoying. For this reason, the window positions, sizes, and other information for the code editors are saved when saving the editor layout and restored when the editor is reopened.<p>The new system can take into account changes in the users screens, like resolution changes or missing screens, and try to put the undocked window into another position. If the recover fails, the windows is attached into the editor window.<h3 id=future>Future</h3><p>The next step is to implement most of the feature available for the code editor to the docks (which are already undockable).<p>After them, I plan to work on the following tasks:<ul><li>Add an icon for the “Make Floating” button.<li>Add a complex UI instead of the simple “Make Floating” action that allows to choose the screen where to place the undocked window.<li>Add some editor settings to configure the behavior.<li>Test the implement features and fix bugs.</ul><p><a id=gpu-lightmapper></a><h2 id=gpu-lightmapper-enhancements>GPU lightmapper enhancements</h2><ul><li>Project: GPU lightmapper enhancements<li>Student: Priyansh Rathi (<a href=https://github.com/techiepriyansh>techiepriyansh</a>)<li>Mentors: Clay John (<a href=https://github.com/clayjohn>clayjohn</a>), Joan Fons Sanchez (<a href=https://github.com/jfons>jfons</a>)<li>PRs:<ul><li><a href=https://github.com/godotengine/godot/pull/61861>Multi Image Atlases</a> (merged)<li><a href=https://github.com/godotengine/godot/pull/62054>Soft Shadows</a> (merged)<li><a href=https://github.com/godotengine/godot/pull/62987>UV2 Texel Density Debug Draw Mode</a></ul></ul><h3 id=introduction-1>Introduction</h3><p>Godot 4.0 announced its new GPU lightmapper back in 2020. Its been two years since then, and a lot of work has gone into it. My project aims to further improve the 4.0 GPU lightmapper by porting some of the essential features from the 3.x CPU lightmapper and adding a new debug draw mode for visualizing the texel density of lightmaps.<h3 id=project-overview-and-progress>Project overview and progress</h3><h4 id=multi-image-atlases>Multi-image atlases</h4><p>Previously every <code class="language-plaintext highlighter-rouge">LightmapGI</code> node used to store its lightmap atlas in a single large image. This meant that the larger scenes might refuse to bake because they dont fit within the size limits of an image. I modified the implementation to allow saving the lightmap atlas as multiple images if it doesnt fit inside a single image.<h4 id=soft-shadows>Soft shadows</h4><p>The general idea behind soft shadows is to take into account the light sources size instead of treating the light source as a point. When one also takes the contribution of light rays from parts of the light source other than its centre, there is a gradual transition from shadowed to fully lit instead of an abrupt change.<p>I added support for soft shadows to the GPU lightmapper by incorporating this idea in the lightmappers raytracing compute shader.<table><thead><tr><th style=text-align:center>No soft shadows<th style=text-align:center>With soft shadows<tbody><tr><td style=text-align:center><img src=/storage/app/media/gsoc/2022-1/gpu-lightmapper-no-soft-shadows.png alt="No soft shadows"><td style=text-align:center><img src=/storage/app/media/gsoc/2022-1/gpu-lightmapper-with-soft-shadows.png alt="With soft shadows"></table><h4 id=debug-draw-mode-for-texel-density>Debug draw mode for texel density</h4><p>This will be a draw mode that previews the texel density of lightmaps (without actually (re)baking them). It will aid users in adjusting the lightmap scale of their objects.<p><strong>How do you show the texel density visually?</strong><p>The idea is to overlay a checkerboard pattern with the same square size (in texels) on the textures of all the meshes. Upon rendering, the checkerboard pattern will appear diminished in the regions with high texel density, and magnified in the regions with low texel density.<p>For this to work, the <code class="language-plaintext highlighter-rouge">lightmap_size</code> of each object would need to be read from the draw modes godot shader. We can conveniently use <a href=/article/godot-40-gets-global-and-instance-shader-uniforms>Godot 4.0s per-instance uniforms</a> to make this work.<p>I have created a crude proof of concept for this. Heres a sneak peek:<table><thead><tr><th>UV2 texel density debug draw mode<tbody><tr><td><img src=/storage/app/media/gsoc/2022-1/gpu-lightmapper-uv2-texel-density-debug.png alt="UV2 texel density debug draw mode"></table><h3 id=next-steps>Next steps</h3><p>My priority would be to complete the texel density debug draw mode PR and get it merged. After that, I would like to take up an experimental task related to rendering.<p><strong>Lastly</strong>, shoutout to my awesome mentors (<a href=https://github.com/clayjohn>clayjohn</a> & <a href=https://github.com/jfons>jfons</a>) for always coming up with ingenious ways to get around my blockers!<hr><p>Thats it for this progress report! Youll hear more about each project once theyre finished at the end of September.<p>A big thankyou to all students for their quality work and creative ideas to implement or improve those features in Godot, and thanks to all the mentors who support them!</div></div></article><div class=blog-navigation><div class=previous><span>Previous</span>
<a rel=prev href=/article/godot-3-5-cant-stop-wont-stop/>Godot 3.5: Can't stop won't stop</a></div><div class=next><span>Next</span>
<a rel=next href=/article/dev-snapshot-godot-4-0-alpha-14/>Dev snapshot: Godot 4.0 alpha 14</a></div></div></div><link rel=stylesheet href=/assets/css/anchor-link.css?1><link rel=stylesheet href=/assets/css/article-cards.css?3><script src=/assets/js/anchor-link.js></script><script>document.addEventListener("DOMContentLoaded",()=>{window.applyAnchorLinks(".article-body"),document.querySelectorAll(".article-cover img, .article-body img").forEach(e=>{if(e.classList.contains("lightbox-ignore"))return;const t=document.createElement("a");t.href=e.src,t.classList.add("lightbox"),t.dataset.group="article",e.parentNode.appendChild(t),t.appendChild(e)})})</script></main><footer class=footer-global><div class=wrapper><div class=columns><div class=col><h2>Godot Engine</h2><ul><li><a class=set-os-download-url href=/download>Download</a><li><a href=https://docs.godotengine.org>Documentation</a><li><a href=/features/>Features</a><li><a href=https://editor.godotengine.org/releases/latest/>Web editor</a><li><a href=/download/archive/>Release archive</a><li><a href=https://github.com/godotengine>Source code</a></ul></div><div class=col><h2>Project</h2><ul><li><a href=/blog/>Blog</a><li><a href=/code-of-conduct/>Code of conduct</a><li><a href=/governance/>Governance</a><li><a href=/teams/>Teams</a><li><a href=/priorities/>Priorities</a><li><a href=/community/>Communities</a></ul></div><div class=col><h2>Resources</h2><ul><li><a href=https://godotengine.org/asset-library/asset>Asset library</a><li><a href=/press/>Press kit</a><li><a href=/showcase/>Showcase</a><li><a href=/education/>Education</a></ul></div><div class=col><h2>Foundation</h2><ul><li><a href=https://godot.foundation/>About</a><li><a href=https://fund.godotengine.org>Donate</a><li><a href=/license/>License</a><li><a href=/privacy-policy/>Privacy policy</a><li><a href=/contact/>Contact us</a></ul></div></div><hr><div class=credits-and-socials><p>© 2007-2025 Juan Linietsky, Ariel Manzur and <a href=https://github.com/godotengine/godot/blob/master/AUTHORS.md target=_blank rel=noopener>contributors</a>. Hosted by the <a href=https://godot.foundation/ target=_blank rel=noopener>Godot Foundation</a>. Website <a href=https://github.com/godotengine/godot-website target=_blank rel=noopener>source code on GitHub</a>.<div class=social><a href=https://github.com/godotengine target=_blank rel=noopener title=GitHub><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</a><a href=https://bsky.app/profile/godotengine.org target=_blank rel=noopener title=Bluesky><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8.0 41.9.0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3.5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9C220.6 589.1 265.1 437.8 288 361.1c22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7C566.9 194 576 75 576 58.4s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8C385.1 81.9 314.1 176.4 288 227.1z"/></svg>
</a><a href=https://mastodon.gamedev.place/@godotengine target=_blank rel=noopener title=Mastodon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5.0.0.0-63.7 28.5-63.7 125.7.0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5.0 01-.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6V190.1c0-49.7-64-51.6-64 6.9v62.5H201V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"/></svg>
</a><a href=https://discord.gg/godotengine target=_blank rel=noopener title=Discord><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M524.5 69.8a1.5 1.5.0 00-.8-.7A485.1 485.1.0 00404.1 32a1.8 1.8.0 00-1.9.9 337.5 337.5.0 00-14.9 30.6 447.8 447.8.0 00-134.4.0 309.5 309.5.0 00-15.1-30.6 1.9 1.9.0 00-1.9-.9A483.7 483.7.0 00116.1 69.1a1.7 1.7.0 00-.8.7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 00.8 1.4A487.7 487.7.0 00176 479.9a1.9 1.9.0 002.1-.7 348.2 348.2.0 0030-48.8 1.9 1.9.0 00-1-2.6 321.2 321.2.0 01-45.9-21.9 1.9 1.9.0 01-.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8.0 011.9-.3c96.2 43.9 200.4 43.9 295.5.0a1.8 1.8.0 011.9.2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9.0 01-.2 3.1 301.4 301.4.0 01-45.9 21.8 1.9 1.9.0 00-1 2.6 391.1 391.1.0 0030 48.8 1.9 1.9.0 002.1.7 486 486 0 00147.2-74.1 1.9 1.9.0 00.8-1.4c12.2-126.7-20.6-236.8-87-334.5zm-302 267.8c-29 0-52.8-26.6-52.8-59.2s23.4-59.3 52.8-59.3c29.7.0 53.3 26.8 52.8 59.2.0 32.7-23.4 59.3-52.8 59.3zm195.4.0c-29 0-52.8-26.6-52.8-59.2s23.3-59.3 52.8-59.3c29.7.0 53.3 26.8 52.8 59.2.0 32.7-23.2 59.3-52.8 59.3z"/></svg>
</a><a href=https://www.reddit.com/r/godot title=Reddit target=_blank rel=noopener><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M0 256C0 114.6 114.6.0 256 0S512 114.6 512 256 397.4 512 256 512H37.1c-13.7.0-20.5-16.5-10.9-26.2L75 437C28.7 390.7.0 326.7.0 256zM349.6 153.6c23.6.0 42.7-19.1 42.7-42.7s-19.1-42.7-42.7-42.7c-20.6.0-37.8 14.6-41.8 34-34.5 3.7-61.4 33-61.4 68.4v.2c-37.5 1.6-71.8 12.3-99 29.1-10.1-7.8-22.8-12.5-36.5-12.5-33 0-59.8 26.8-59.8 59.8.0 24 14.1 44.6 34.4 54.1 2 69.4 77.6 125.2 170.6 125.2s168.7-55.9 170.6-125.3c20.2-9.6 34.1-30.2 34.1-54 0-33-26.8-59.8-59.8-59.8-13.7.0-26.3 4.6-36.4 12.4-27.4-17-62.1-27.7-1e2-29.1v-.2c0-25.4 18.9-46.5 43.4-49.9 4.4 18.8 21.3 32.8 41.5 32.8zM177.1 246.9c16.7.0 29.5 17.6 28.5 39.3s-13.5 29.6-30.3 29.6-31.4-8.8-30.4-30.5S160.3 247 177 247zm190.1 38.3c1 21.7-13.7 30.5-30.4 30.5s-29.3-7.9-30.3-29.6c-1-21.7 11.8-39.3 28.5-39.3s31.2 16.6 32.1 38.3zm-48.1 56.7c-10.3 24.6-34.6 41.9-63 41.9s-52.7-17.3-63-41.9c-1.2-2.9.8-6.2 3.9-6.5 18.4-1.9 38.3-2.9 59.1-2.9s40.7 1 59.1 2.9c3.1.3 5.1 3.6 3.9 6.5z"/></svg>
</a><a href=/rss.xml title=RSS target=_blank rel=noopener><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M64 32C28.7 32 0 60.7.0 96V416c0 35.3 28.7 64 64 64h320c35.3.0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zM96 136c0-13.3 10.7-24 24-24 137 0 248 111 248 248 0 13.3-10.7 24-24 24s-24-10.7-24-24c0-110.5-89.5-2e2-2e2-2e2-13.3.0-24-10.7-24-24zm0 96c0-13.3 10.7-24 24-24 83.9.0 152 68.1 152 152 0 13.3-10.7 24-24 24s-24-10.7-24-24c0-57.4-46.6-104-104-104-13.3.0-24-10.7-24-24zm0 120a32 32 0 1164 0 32 32 0 11-64 0z"/></svg></a></div></div></div></footer><script defer src=/assets/js/localize.js?5></script><script defer src=/assets/js/tobii.min.js></script><script defer src=/assets/js/highlight.min.js?1></script><script defer src=/assets/js/highlight.gdscript.min.js?1></script><script>document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("pre code").forEach(e=>{hljs.highlightBlock(e)}),document.querySelectorAll("[data-post-date]").forEach(e=>{Date.parse(e.dataset.postDate)>Date.now()-1e3*60*60*48&&e.classList.add("post-recent-highlight")}),new Tobii({zoom:!1});const e=document.querySelectorAll(".set-os-download-url");for(let n=0;n<e.length;n++){const s=e[n];let o="download";"version"in s.dataset&&s.dataset.version==="3"&&(o="download/3.x");let t="windows";navigator.platform.indexOf("Mac")!==-1?t="macos":navigator.userAgent.indexOf("Android")!==-1?t="android":navigator.platform.indexOf("Linux")!==-1&&(t="linux"),s.href=`/${o}/${t}/`}})</script>