Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - Clocktown/Godot-ComputeShader-Image-TextureRect-Example: An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU. · GitHub
Skip to content

Repository files navigation

Godot Compute-Shader Image to TextureRect Example

Many resources about how to use compute shaders in Godot 4.6 are insufficient if what you want to do is have compute shaders output/modify something on the GPU every frame (or physics frame) and have that same resource available to regular nodes or the main renderer.

For example, the heightmap example uses a local rendering device and downloads the texture to the CPU just to reupload that texture to the GPU again.

This is fine if it happens occasionally. It is not fine if we are talking about a simulation that modifies large images or particle data that we want to access in our normal rendering outside of the RenderingDevice API.

The project I have provided here contains a toy example that shows how to do this:

  • Uses RenderingServer.get_rendering_device() so that Resources allocated can be accessed by nodes
  • Uses Texture2DRD to bind a texture created on the RenderingDevice to a standard TextureRect node
  • Has example code that handles a change in width/height of the simulation texture in a deferred manner
  • Shows the correct Usage Bits for the texture such that Sampling (usage as texture via Texture2DRD or directly in a uniform sampler2D) and Image Load/Store are possible (Storage Bit)
  • Shows how to use Push Constants for Shader data that changes frequently
  • Shows how to use image2D to write to an image in a compute shader

This toy example queues a compute shader dispatch in _physics_process such that it executes a stable number of times per second, which is what you usually want for simulations. It would work the same way if you want to run it in _process instead. A push constant is set alternating between 0 and 1 which the shader reacts to by either outputting a horizontal or vertical gradient.

There is no submit() or sync() because this is done automatically behind the scenes for the main rendering device.

The reason all the variables are talking about Sand is because I was going to use this as a baseline to implement a sand simulation, but when I had the basic template running I thought that it would be valuable to share with anyone interested in learning about compute shaders in Godot.

About

An example of how to use a compute shader in Godot 4.6 that writes a texture in every physics step. The texture is bound to a TextureRect without the need of downloading to the CPU and reuploading to the GPU.

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages