https://arugl.medium.com/games-in-the-gpu-shaders-a912414b1894 Open in app Sign up Sign in [ ] Write Sign up Sign in [1] Games in the GPU shaders Danil Danil * Follow 11 min read * May 29, 2021 -- Listen Share Screenshot from https://www.shadertoy.com/view/3syXDD This is not a tutorial, I write only about my way of creating logic and some useful tips and code. Useful Shaders and Shadertoy related links and tips in my previous blog post. Content: 1. Useful code for data saving/loading. 2. 2D drawing/creating graphics. 3. Optimization and debugging. 4. The edge of the Games in GPU. 5. Links to my own games in the shaders. 6. Export template. How it works: Shadertoy implementation of "buffer logic" allows read from "buffer previous frame data"(BufferA read self when binded as one of iChannels). Basic logic --in the buffer on Frame 0 init data and on next frames execute game logic reading the previous state of saved data. And Image buffer displays the state of logic using game elements and UI. Creating a game in the GLSL shader is the same as in pure C -- the result is very large linear straightforward logic. Example of the game in the shaders https://www.shadertoy.com/view/ wdS3D3 This example shows how I use 28 pixels to save data (state of map and logic). Pixels, each pixel is vec4(r,g,b,a): 0 -- init game status 1 to 26 -- used to store 10x10 map, 25 pixels*4(r,g,b,a) values=100 27 -- (r,g) player position, (b) direction of player rotation, (a) time of start movement 28 -- (r,g) bullet position, (b) direction of player rotation when bulled launched, (a) time of bullet launch Player and bullet position is tile index where they located now. Timers are used to move player or bullet to the next tile by direction. And Image shader animate movement using timer value. In the tiles stored ID of the tile(water/block/free/etc), and Image shader draw graphics base on tile ID. I use the whole 32-bit value to save a single tile ID, in real use single tile can contain much more information than just a tile ID, and for that case, the unused part of 32-bit data can be used. Look below for functions to store data. Useful code for data saving/loading: To read pixel data always use texelFetch. Shadertoy Buffers is GL_RGBA32F 32 bit per value, 128 bits of data can be saved per "thread"(pixel). GLSL has functions floatBitsToUint and uintBitsToFloat conversion float32 from/to uint32. Large 32bit uint can be stored in a single float. To optimize data -- use and save more than 4 values per pixel(thread). These functions can be used: https://www.shadertoy.com/view/Nls3Rn Description: uint in 0-255 range float in -1.0 to 1.0 range _udata32 is pack/unpack four 8-bit uint to/from 32 bit [0xF1][0xF2][0xF3][0xF4] to/from 0xF1F2F3F4 _float4x8 is four 8-bit floats _float3x10 is three 10-bit floats bits is 8-bit int in range 0-255 presented as bits Usage : When game logic needs a large number of booleans to switch states -- data to save/load can be presented as bits that allow saving 32-booleans per value and 128 booleans per pixel. Same with other types of data, when integers don't need a full 32-bit range they can be packed to a smaller range, same with floats as for example timers-like better to store at least in the 10 bits (because 8-bit has a way too large step that noticeable in smooth-movement that you can see on the preview shader). 2D drawing/creating graphics: Left SDF antialiasing. On the right no antialiasing. https:// www.shadertoy.com/view/ll3BzM Antialiasing: 1. With hardware derivatives: Filterable procedurals -- square patterns. Nonsquare -- concentric rings and isovalues. More information on the Shadertoy Unofficial. Another way can be -- move procedural pattern to its own buffer (BufA) and generate mipmaps for it every frame, and use texture function in the main buffer to create graphics using generated texture from a buffer. 2. With SDF: float px = 1./iResolution.y; float edge = smoothstep(0., px, sdf); Example displayed on the screenshot. 3. Multisampling: Call pixel function many times with shifting pixel position in range of a half pixel. This is very slow, better do not use it in real-time. Anti-Aliasing Compare -- comparison of MSAA methods. Most default Shadertoy MSAA template: (rename original mainImage to mainImage_orig) void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec4 tcol=vec4(0.); const int AA=4; for( int mx=0; mx0)&&((y+=1)<0); First part x>0 will be calculated always, when y+=1 may not be calculated. Do not put complex C-like logic to a single line, the result may be not expected. Always move "fast function" to the left side of the condition. Debug heatmap script https://www.shadertoy.com/view/tllfDM Debugging: I found the most useful way is -- a minimal application that does texture saving to file or frame by frame debugging, I use Shadertoy only to debug WebGL shaders. Maybe can be useful -- this my Debug heatmap script. Display number of function/logic calls per pixel but in most cases its obvious without a script. I have not found useful GLSL emulation on the CPU. Chrome and Mesa software GLSL emulation has way too many bugs, in most cases, it can not even load my shaders. Other emulators for example SPIRV-VM also have way too many bugs and the result of calculation from complex shader is not equal to shader on the GPU result. The way to set up GLSL emulation described there: github.com/danilw/ GPU-my-list-of-bugs. Read Debug section on the page. The edge of the Games in GPU: Error in some GPUs on using a large shader. WebGL: Avoiding compiler crash and Compatibility issues in Shadertoy and webGLSL. OpenGL/Vulkan: Also look at my GPU-my-list-of-bugs. Hardware limitations -- depends on GPU: 1. Loop in the loop in another loop with complex logic on every level. Shaders do have a complexity limit, and when used many loops -- this shader may not work on many low-end GPUs like integrated or mobile GPU. Example bug report of this case in Vulkan. 2. Size of the compiled shader -- also another hardware limitation that depends on GPU. I do not know the exact limits, I think when unrolled code size less than 1000 lines everything should be fine, or SPIR-file size less than 200Kb shader should work everywhere. Example bug report of this case in Vulkan. 3. Frame time -- Windows OS have a limitation of 1-sec frame render time or GPU driver will be rebooted, or blue screen if GPU freeze. On Linux no such limitation, but having a shader that freezes GPU for more than 1 sec is very bad. When you have a very slow shader -- render shader in small tiles, using reading from the previous frame in the buffers or discard if supported. Example shader using discard and for buffers using reading last frame. 4. Various hardware bugs in some cases. Example of such bugs -- bug with memory in shader and bug shader noise. Almost every my complex shader discovers some new GPU-related bugs. To avoid most of the GPU limitations just use the newest and most powerful GPU you can found. Games in the shaders, links: From my shader-game Sgame. My games in the shaders: 1. Sgame (youtube video link) -- my first try of creating a game in the shader, only physics calculated on the CPU. Launch link. Warning: clicking this link may crash your browser. Shader source code. 2. Getting Over...GLSL? --my try using 2D SDF physics in the GPU. Shader that used for GPU physics source link. My other shaders source code. 3. Card game in the single shader -- large linear logic TCG-like game concept with minimal AI-bot. To launch on Shadertoy remove # define NOCOMPILE from Common and press Compile(run). Youtube video of my Card game. Alternative 75Kb exe download, Windows only. 4. GLSL Auto Tetris -- blog post link, read description there. 5. An unfinished game (youtube video link) where I tried to use blend to draw many small elements. Download links in the youtube video description. Shader source code. 6. We need more likes, playable -- very minimal clicker. 7. Game for Cactus Jam -- downlload links listed on Shadertoy page. Other games on the Shadertoy: List of 151 Playable games in Shadertoy! Export template: I use only my own Vulkan-Shadertoy-Launcher (source code there). I do not recommend OpenGL applications because way too many bugs in OpenGL. For other templates for exporting look at my previous blog Into Shadertoy and Shaders useful links and tips (Offline Shadertoy related applications section). Thanks for reading! Games Shadertoy Shaders -- -- Danil Follow Written by Danil 15 Followers GLSL and usual coding Follow Help Status About Careers Blog Privacy Terms Text to speech Teams