error("\069\120\097\109\112\108\101 \110\111\116 \105\109\112\108\101\109\101\110\116\101\100\033")local Q=require("\102\102\105")local z=require("\114\097\121\108\105\098")local p=768 local U=48 Q.cdef("  \116\121\112\101\100\101\102 \115\116\114\117\099\116 \071\111\108\085\112\100\097\116\101\067\109\100 \123\n    \117\110\115\105\103\110\101\100 \105\110\116 \120\059\n    \117\110\115\105\103\110\101\100 \105\110\116 \121\059\n    \117\110\115\105\103\110\101\100 \105\110\116 \119\059\n    \117\110\115\105\103\110\101\100 \105\110\116 \101\110\097\098\108\101\100\059\n  \125 \071\111\108\085\112\100\097\116\101\067\109\100\059\n")Q.cdef(string.format("  \116\121\112\101\100\101\102 \115\116\114\117\099\116 \071\111\108\085\112\100\097\116\101\083\083\066\079 \123\n    \117\110\115\105\103\110\101\100 \105\110\116 \099\111\117\110\116\059\n    \071\111\108\085\112\100\097\116\101\067\109\100 \099\111\109\109\097\110\100\115\091\037\100\093\059\n  \125 \071\111\108\085\112\100\097\116\101\083\083\066\079\059\n",U))z.InitWindow(p,p,"\114\097\121\108\105\098 \091\114\108\103\108\093 \101\120\097\109\112\108\101 - \099\111\109\112\117\116\101 \115\104\097\100\101\114 - \103\097\109\101 \111\102 \108\105\102\101")local j=z.Vector2(p,p)local W=8 local K=z.LoadFileText("\101\120\097\109\112\108\101\115\047\114\101\115\111\117\114\099\101\115\047\103\108\115\108\052\051\048\047\103\111\108\046\103\108\115\108")local m=z.rlCompileShader(K,z.RL_COMPUTE_SHADER)local h=z.rlLoadComputeShaderProgram(m)z.UnloadFileText(K)local b=z.LoadShader(nil,"\101\120\097\109\112\108\101\115\047\114\101\115\111\117\114\099\101\115\047\103\108\115\108\052\051\048\047\103\111\108\095\114\101\110\100\101\114\046\103\108\115\108")local t=z.GetShaderLocation(b,"\114\101\115\111\108\117\116\105\111\110")local c=z.LoadFileText("\101\120\097\109\112\108\101\115\047\114\101\115\111\117\114\099\101\115\047\103\108\115\108\052\051\048\047\103\111\108\095\116\114\097\110\115\102\101\114\116\046\103\108\115\108")local k=z.rlCompileShader(c,z.RL_COMPUTE_SHADER)local i=z.rlLoadComputeShaderProgram(k)z.UnloadFileText(c)local f=Q.sizeof("\105\110\116\091\063\093",p*p)local O=z.rlLoadShaderBuffer(f,nil,z.RL_DYNAMIC_COPY)local N=z.rlLoadShaderBuffer(f,nil,z.RL_DYNAMIC_COPY)local x=Q.new("\115\116\114\117\099\116 \071\111\108\085\112\100\097\116\101\083\083\066\079")x.count=0 local A=Q.sizeof("\115\116\114\117\099\116 \071\111\108\085\112\100\097\116\101\083\083\066\079")local B=z.rlLoadShaderBuffer(A,nil,z.RL_DYNAMIC_COPY)local n=z.GenImageColor(p,p,z.WHITE)local q=z.LoadTextureFromImage(n)z.UnloadImage(n)while not z.WindowShouldClose()do W=math.floor(W+z.GetMouseWheelMove())if(z.IsMouseButtonDown(z.MOUSE_BUTTON_LEFT)or z.IsMouseButtonDown(z.MOUSE_BUTTON_RIGHT))and x.count<U then x.commands[x.count].x=z.GetMouseX()-W/2 x.commands[x.count].y=z.GetMouseY()-W/2 x.commands[x.count].w=W x.commands[x.count].enabled=z.IsMouseButtonDown(z.MOUSE_BUTTON_LEFT)x.count=x.count+1 elseif x.count>0 then z.rlUpdateShaderBuffer(B,x,A,0)z.rlEnableShader(i)z.rlBindShaderBuffer(O,1)z.rlBindShaderBuffer(B,3)z.rlComputeShaderDispatch(x.count,1,1)z.rlDisableShader()x.count=0 else z.rlEnableShader(h)z.rlBindShaderBuffer(O,1)z.rlBindShaderBuffer(N,2)z.rlComputeShaderDispatch(p/8,p/8,1)z.rlDisableShader()O,N=N,O end z.rlBindShaderBuffer(O,1)z.SetShaderValue(b,t,j,z.SHADER_UNIFORM_VEC2)z.BeginDrawing()z.ClearBackground(z.BLANK)z.BeginShaderMode(b)z.DrawTexture(q,0,0,z.WHITE)z.EndShaderMode()z.DrawRectangleLines(z.GetMouseX()-W/2,z.GetMouseY()-W/2,W,W,z.RED)z.DrawText("\085\115\101 \077\111\117\115\101 \119\104\101\101\108 \116\111 \105\110\099\114\101\097\115\101\047\100\101\099\114\101\097\115\101 \098\114\117\115\104 \115\105\122\101",10,10,20,z.WHITE)z.DrawFPS(z.GetScreenWidth()-100,10)z.EndDrawing()end z.rlUnloadShaderBuffer(O)z.rlUnloadShaderBuffer(N)z.rlUnloadShaderBuffer(B)z.rlUnloadShaderProgram(i)z.rlUnloadShaderProgram(h)z.UnloadTexture(q)z.UnloadShader(b)z.CloseWindow()
error("Example not implemented!")

local ffi = require("ffi")

local rl = require("raylib")

-- IMPORTANT: This must match gol*.glsl GOL_WIDTH constant.
-- This must be a multiple of 16 (check golLogic compute dispatch).
local GOL_WIDTH = 768

-- Maximum amount of queued draw commands (squares draw from mouse down events).
local MAX_BUFFERED_TRANSFERTS = 48

ffi.cdef([[
  typedef struct GolUpdateCmd {
    unsigned int x;
    unsigned int y;
    unsigned int w;
    unsigned int enabled;
  } GolUpdateCmd;
]])

ffi.cdef(string.format(
  [[
  typedef struct GolUpdateSSBO {
    unsigned int count;
    GolUpdateCmd commands[%d];
  } GolUpdateSSBO;
]],
  MAX_BUFFERED_TRANSFERTS
))

rl.InitWindow(GOL_WIDTH, GOL_WIDTH, "raylib [rlgl] example - compute shader - game of life")

local resolution = rl.Vector2(GOL_WIDTH, GOL_WIDTH)
local brushSize = 8

-- Game of Life logic compute shader
local golLogicCode = rl.LoadFileText("examples/resources/glsl430/gol.glsl")
local golLogicShader = rl.rlCompileShader(golLogicCode, rl.RL_COMPUTE_SHADER)
local golLogicProgram = rl.rlLoadComputeShaderProgram(golLogicShader)
rl.UnloadFileText(golLogicCode)

-- Game of Life rendering compute shader
local golRenderShader = rl.LoadShader(nil, "examples/resources/glsl430/gol_render.glsl")
local resUniformLoc = rl.GetShaderLocation(golRenderShader, "resolution")

local golTransfertCode = rl.LoadFileText("examples/resources/glsl430/gol_transfert.glsl")
local golTransfertShader = rl.rlCompileShader(golTransfertCode, rl.RL_COMPUTE_SHADER)
local golTransfertProgram = rl.rlLoadComputeShaderProgram(golTransfertShader)
rl.UnloadFileText(golTransfertCode)

local ssboSize = ffi.sizeof("int[?]", GOL_WIDTH * GOL_WIDTH)
local ssboA = rl.rlLoadShaderBuffer(ssboSize, nil, rl.RL_DYNAMIC_COPY)
local ssboB = rl.rlLoadShaderBuffer(ssboSize, nil, rl.RL_DYNAMIC_COPY)

local transfertBuffer = ffi.new("struct GolUpdateSSBO")
transfertBuffer.count = 0

local transfertBufferSize = ffi.sizeof("struct GolUpdateSSBO")

local transfertSSBO = rl.rlLoadShaderBuffer(transfertBufferSize, nil, rl.RL_DYNAMIC_COPY)

-- Create a white texture of the size of the window to update
-- each pixel of the window using the fragment shader
local whiteImage = rl.GenImageColor(GOL_WIDTH, GOL_WIDTH, rl.WHITE)
local whiteTex = rl.LoadTextureFromImage(whiteImage)
rl.UnloadImage(whiteImage)

while not rl.WindowShouldClose() do
  brushSize = math.floor(brushSize + rl.GetMouseWheelMove())

  if
    (rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT) or rl.IsMouseButtonDown(rl.MOUSE_BUTTON_RIGHT))
    and (transfertBuffer.count < MAX_BUFFERED_TRANSFERTS)
  then
    -- Buffer a new command
    transfertBuffer.commands[transfertBuffer.count].x = rl.GetMouseX() - brushSize / 2
    transfertBuffer.commands[transfertBuffer.count].y = rl.GetMouseY() - brushSize / 2
    transfertBuffer.commands[transfertBuffer.count].w = brushSize
    transfertBuffer.commands[transfertBuffer.count].enabled = rl.IsMouseButtonDown(rl.MOUSE_BUTTON_LEFT)
    transfertBuffer.count = transfertBuffer.count + 1
  elseif transfertBuffer.count > 0 then
    -- Process transfert buffer

    -- Send SSBO buffer to GPU
    rl.rlUpdateShaderBuffer(transfertSSBO, transfertBuffer, transfertBufferSize, 0)

    -- Process ssbo command
    rl.rlEnableShader(golTransfertProgram)
    rl.rlBindShaderBuffer(ssboA, 1)
    rl.rlBindShaderBuffer(transfertSSBO, 3)
    rl.rlComputeShaderDispatch(transfertBuffer.count, 1, 1) -- each GPU unit will process a command
    rl.rlDisableShader()

    transfertBuffer.count = 0
  else
    -- Process game of life logic
    rl.rlEnableShader(golLogicProgram)
    rl.rlBindShaderBuffer(ssboA, 1)
    rl.rlBindShaderBuffer(ssboB, 2)
    rl.rlComputeShaderDispatch(GOL_WIDTH / 8, GOL_WIDTH / 8, 1)
    rl.rlDisableShader()

    ssboA, ssboB = ssboB, ssboA
  end

  rl.rlBindShaderBuffer(ssboA, 1)
  rl.SetShaderValue(golRenderShader, resUniformLoc, resolution, rl.SHADER_UNIFORM_VEC2)

  rl.BeginDrawing()

  rl.ClearBackground(rl.BLANK)

  rl.BeginShaderMode(golRenderShader)
  rl.DrawTexture(whiteTex, 0, 0, rl.WHITE)
  rl.EndShaderMode()

  rl.DrawRectangleLines(rl.GetMouseX() - brushSize / 2, rl.GetMouseY() - brushSize / 2, brushSize, brushSize, rl.RED)

  rl.DrawText("Use Mouse wheel to increase/decrease brush size", 10, 10, 20, rl.WHITE)
  rl.DrawFPS(rl.GetScreenWidth() - 100, 10)

  rl.EndDrawing()
end

rl.rlUnloadShaderBuffer(ssboA)
rl.rlUnloadShaderBuffer(ssboB)
rl.rlUnloadShaderBuffer(transfertSSBO)

-- Unload compute shader programs
rl.rlUnloadShaderProgram(golTransfertProgram)
rl.rlUnloadShaderProgram(golLogicProgram)

rl.UnloadTexture(whiteTex) -- Unload white texture
rl.UnloadShader(golRenderShader) -- Unload rendering fragment shader

rl.CloseWindow() -- Close window and OpenGL context
