1"use strict";(globalThis.webpackChunkmi_sitio=globalThis.webpackChunkmi_sitio||[]).push([[4507],{2019(e,n,r){r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>s,toc:()=>o});var s=r(4494),i=r(4848),d=r(8453);const t={slug:"brakeza3d-0-26-10",title:"Brakeza3D 0.26.10 released!",authors:["eduardo"],tags:["brakeza3d","release","community"]},a=void 0,l={authorsImageUrls:[void 0]},o=[{value:"\u2728 What's New",id:"-whats-new",level:2},{value:"Rendering Performance Overhaul",id:"rendering-performance-overhaul",level:3},{value:"Emissive Materials",id:"emissive-materials",level:3},{value:"New Audio Backend: miniaudio",id:"new-audio-backend-miniaudio",level:3},{value:"Faster Async Loading",id:"faster-async-loading",level:3},{value:"UI System Upgrades",id:"ui-system-upgrades",level:3},{value:"Pathfinding \u2014 Path Costs",id:"pathfinding--path-costs",level:3},{value:"Command-Line Parameters & Automation",id:"command-line-parameters--automation",level:3},{value:"Scripting API Additions",id:"scripting-api-additions",level:3},{value:"Profiler \u2014 Render Detail",id:"profiler--render-detail",level:3},{value:"Editor & Platform",id:"editor--platform",level:3},{value:"Bug Fixes",id:"bug-fixes",level:3},{value:"Documentation",id:"documentation",level:3}];function c(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",hr:"hr",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,d.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Brakeza3D ",(0,i.jsx)(n.strong,{children:"0.26.10"})," is here! This release is all about ",(0,i.jsx)(n.strong,{children:"performance and polish"}),": a reworked renderer\r\nwith instancing and shared GPU geometry, emissive materials, a brand-new audio backend, faster async\r\nloading, a much more capable UI system, path costs for pathfinding, and command-line parameters for\r\nautomated runs."]}),"\n",(0,i.jsxs)(n.p,{children:["Download for ",(0,i.jsx)(n.strong,{children:"Linux"})," and ",(0,i.jsx)(n.strong,{children:"Windows"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/rzeronte/brakeza3d/releases/tag/0.26.10",children:"https://github.com/rzeronte/brakeza3d/releases/tag/0.26.10"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://brakeza.com/downloads",children:"https://brakeza.com/downloads"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"-whats-new",children:"\u2728 What's New"}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"rendering-performance-overhaul",children:"Rendering Performance Overhaul"}),"\n",(0,i.jsx)(n.p,{children:"The deferred renderer has been profiled and optimized end to end. Scenes with many copies of the same\r\nmodel are now dramatically cheaper."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Shared GPU geometry"})," \u2014 every ",(0,i.jsx)(n.code,{children:"Mesh3D"})," / ",(0,i.jsx)(n.code,{children:"Mesh3DAnimation"})," created from the same model file shares\r\nits vertex buffers, with deduplicated index buffers"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Instancing"})," \u2014 an opaque render queue groups objects by model and draws them instanced in the\r\nG-Buffer, shadow and picking passes. Animated models too: bones are skinned in the vertex shader from\r\na bone-matrix texture buffer"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Shadow caster culling"})," \u2014 each light only renders the casters inside its own frustum"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"State caches"})," \u2014 FBO/program bind cache and a shared GL render-state cache remove redundant state\r\nchanges; projection and view travel in a single ",(0,i.jsx)(n.code,{children:"CameraBlock"})," uniform buffer"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"emissive-materials",children:"Emissive Materials"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Mesh3D"})," objects can now ",(0,i.jsx)(n.strong,{children:"glow"})," with their own color, ignoring scene lighting: screens, neon signs,\r\nlamps, magic effects. Emission is off by default and adds no cost to scenes that do not use it."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-lua",children:'local sign = Brakeza:getObjectByName("neon_sign")\r\nsign:setEmissionEnabled(true)\r\nsign:setEmissionIntensity(0.8) -- 0 = lit normally, 1 = full self
1-illumination\n'})}),"\n",(0,i.jsx)(n.p,{children:"Available in the object inspector, saved in scene files and fully scriptable."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"new-audio-backend-miniaudio",children:"New Audio Backend: miniaudio"}),"\n",(0,i.jsxs)(n.p,{children:["SDL2_mixer has been replaced by ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"https://miniaud.io",children:"miniaudio"})}),", bundled as a single header \u2014\r\none dependency less to install on Linux."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Same Lua API as before (",(0,i.jsx)(n.code,{children:"playSound"}),", channels, ",(0,i.jsx)(n.code,{children:"Sound3D"}),", ambience volume...)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"WAV, MP3 and FLAC"})," support, also for positional ",(0,i.jsx)(n.code,{children:"Sound3D"})," sources"]}),"\n",(0,i.jsxs)(n.li,{children:["New ",(0,i.jsx)(n.code,{children:"setChannelPitch(channel, pitch)"})," for engine RPM, Doppler and similar effects"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"faster-async-loading",children:"Faster Async Loading"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Per-file load locks in the resource caches: the same file is never loaded twice in parallel"}),"\n",(0,i.jsx)(n.li,{children:"The compute thread pool is sized from the CPU core count"}),"\n",(0,i.jsx)(n.li,{children:"Deferrable jobs: work that has to wait no longer blocks a worker thread"}),"\n",(0,i.jsx)(n.li,{children:"Animated billboards get their own texture cache"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Brakeza:getPendingJobsCount()"})," and ",(0,i.jsx)(n.code,{children:"Brakeza:cancelPendingJobs()"})," to drive loading screens and\r\nclean restarts; ",(0,i.jsx)(n.code,{children:"Components:Render():PreloadImage2D(path)"})," warms up images before they are shown"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"ui-system-upgrades",children:"UI System Upgrades"}),"\n",(0,i.jsx)(n.p,{children:"The widget system takes a big step forward:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Feature"}),(0,i.jsx)(n.th,{children:"Detail"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Fonts per widget and per element"}),(0,i.jsxs)(n.td,{children:["Any ",(0,i.jsx)(n.code,{children:".ttf"})," / ",(0,i.jsx)(n.code,{children:".otf"}),"; nested widgets inherit the parent's font"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Word-wrapped text"}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"wrap"}),", ",(0,i.jsx)(n.code,{children:"w"}),", ",(0,i.jsx)(n.code,{children:"maxLines"})," and ",(0,i.jsx)(n.code,{children:"lineSpacing"})," on text elements"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"9-slice backgrounds"}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"bgSlice"}),": frames whose corners keep their size when the panel is resized"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Scrollable lists"}),(0,i.jsxs)(n.td,{children:["New ",(0,i.jsx)(n.code,{children:"scroll"})," element type"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Pagers on top"}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"arrayPagerTop"})," places a long list's pager above it"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"Resolution-aware text"}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"setUIDesignResolution(w, h)"})," and per-widget ",(0,i.jsx)(n.code,{children:"refHeight"})," scale text with the window"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"New Lua helpers"}),(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"getWidgetSize"}),", ",(0,i.jsx)(n.code,{children:"invalidateWidget"}),", ",(0,i.jsx)(n.code,{children:"invalidateAllWidgets"}),", ",(0,i.jsx)(n.code,{children:"isUIScrollHovered"})]})]})]})]}),"\n",(0,i.jsx)(n.p,{children:"The UI Manager editor window gained the matching controls (font pickers, grouped sections...)."}),"\n",(0,i.jsx)(n.p,{children:"Related rendering helpers:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"drawFillSubmesh(obj, submesh, r, g, b, a)"})," \u2014 translucent highlight over a single submesh"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"TextWriter:measureTextWidthAtlas(text, scale)"})," \u2014 measure batched atlas text to center or align it;\r\natlas text now honors its tint color and blends correctly"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"pathfinding--path-costs",children:"Pathfinding \u2014 Path Costs"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Grid3D"})," cells can now have a ",(0,i.jsx)(n.strong,{children:"traversal cost"}),". A* prefers cheaper cells, so units can favour\r\nsidewalks over roads or avoid dangerous areas without blocking them:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-lua",children:'local grid = mesh:getGrid3D()\r\ngrid:fillCostFromImage("../assets/nav/roads.png", 128, 4.0) -- roads cost 4\r\ngrid:setCellsCost({ 10, 12, 11, 12 }, 10.0) -- a temporary danger zone\r\nprint(grid:getCellCost(10, 12))\n'})}),"\n",(0,i.jsx)(n.p,{children:"Grid world coordinates are now derived from the grid bounds."}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"command-line-parameters--automation",children:"Command-Line Parameters & Automation"}),"\n",(0,i.jsx)(n.p,{children:"Projects can declare their own parameters and receive them from the command line \u2014 ideal for test\r\nscenarios, CI and benchmarks:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> brakeza3d.exe -p MyGame.json --set level=forest --set godMode=true --exit-after 300\n"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"--set key=value"})," \u2014 passed to the project, declared in its ",(0,i.jsx)(n.code,{children:"cli_params"})," (name, type, default)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"--exit-after N"})," \u2014 safety watchdog for headless runs"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Brakeza:getCliParam(name)"})," reads a parameter with its declared type"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Brakeza:requestExit(code)"})," closes the app with a process exit code"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"scripting-api-additions",children:"Scripting API Additions"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"API"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"Brakeza:getDeltaTimeMS()"})}),(0,i.jsxs)(n.td,{children:["Frame time in milliseconds (",(0,i.jsx)(n.code,{children:"getDeltaTimeMicro()"})," now really returns microseconds)"]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"Brakeza:getImage3DAnimationByName()"})}),(0,i.jsx)(n.td,{children:"Typed access to animated billboards"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"BillboardAnimation:setTowardsCamera / setSize / setRenderFB"})}),(0,i.jsx)(n.td,{children:"Flat ground sprites, runtime resizing, render layer"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsxs)(n.td,{children:[(0,i.jsx)(n.code,{children:"Mesh3D:getModelFile()"})," / ",(0,i.jsx)(n.code,{children:"getDiffuseTextureFile(i)"})]}),(0,i.jsx)(n.td,{children:"Inspect the model and per-submesh textures"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"Input:isMouseInWindow()"})}),(0,i.jsx)(n.td,{children:"Know when the cursor leaves the window"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"ParticlesContext.PARTICLE_SIZE_SCALE"})}),(0,i.jsx)(n.td,{children:"Particle size multiplier"})]})]})]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"profiler--render-detail",children:"Profiler \u2014 Render Detail"}),"\n",(0,i.jsxs)(n.p,{children:["The Profiler adds exact per-frame ",(0,i.jsx)(n.strong,{children:"draw call and triangle counters"}),", CPU and real ",(0,i.jsx)(n.strong,{children:"GPU time per\r\nrender pass"})," (GPU queries are optional, zero overhead when off), rolling history with median/P95/P99,\r\nand ",(0,i.jsx)(n.strong,{children:"CSV export"})," to compare a scene before and after an optimization."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"editor--platform",children:"Editor & Platform"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Scene badge in the project panel"}),"\n",(0,i.jsx)(n.li,{children:"Windows: the application icon is embedded in the executable (taskbar icon from the first frame)"}),"\n",(0,i.jsxs)(n.li,{children:["New minimal ",(0,i.jsx)(n.strong,{children:"UITest"})," demo scene (",(0,i.jsx)(n.code,{children:"UIWidgetsDemo.lua"}),") showing a plain widget, a nested widget and an\r\narray with the sample widgets in ",(0,i.jsx)(n.code,{children:"assets/ui/"})]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"bug-fixes",children:"Bug Fixes"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Texture unit helpers only handled units 0\u20135 (higher units were bound onto the previous one)"}),"\n",(0,i.jsxs)(n.li,{children:["UI widget editor now saves ",(0,i.jsx)(n.code,{children:"arrayPrefix"})]}),"\n",(0,i.jsx)(n.li,{children:"Black scene after a window resize (VAO name reuse in ground decals)"}),"\n",(0,i.jsx)(n.li,{children:"VRAM leak when destroying custom code shaders"}),"\n",(0,i.jsx)(n.li,{children:"Outline fill pass inheriting instancing flags"}),"\n",(0,i.jsx)(n.li,{children:"Editor grid disappearing"}),"\n",(0,i.jsx)(n.li,{children:"Two use-after-free crashes"}),"\n",(0,i.jsx)(n.li,{children:"Camera up vector computed from its own rotation"}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h3,{id:"documentation",children:"Documentation"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"UI Widgets"})," \u2014 new dedicated page: JSON format, element types, buttons, nested widgets, lists and\r\npagination, scroll areas, 9-slice backgrounds, text scaling and the UI Manager editor"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"3D Objects"})," \u2014 Mesh3D model/texture methods, emission, shared geometry and instancing, animated billboards"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Grid3D"})," \u2014 movement costs"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Scripting introduction"})," \u2014 command-line parameters (",(0,i.jsx)(n.code,{children:"--set"}),", ",(0,i.jsx)(n.code,{children:"cli_params"}),", ",(0,i.jsx)(n.code,{children:"--exit-after"}),"),\r\n",(0,i.jsx)(n.code,{children:"requestExit"}),", async loading helpers"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Sound"})," \u2014 miniaudio backend, supported formats, ",(0,i.jsx)(n.code,{children:"setChannelPitch"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Text System"})," \u2014 custom fonts with the glyph atlas, batched text and ",(0,i.jsx)(n.code,{children:"measureTextWidthAtlas"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Editor"})," \u2014 Profiler counters, GPU timing and CSV export"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Download and Install"})," \u2014 build from source updated: new Windows libraries package for 0.26.10\r\n(no SDL2_mixer, exact MinGW build it needs) and the FFmpeg development packages on Linux"]}),"\n"]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.p,{children:"Thanks for testing Brakeza3D and sharing feedback \u2764\ufe0f"})]})}function h(e={}){const{wrapper:n}={...(0,d.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},4494(e){e.exports=JSON.parse('{"permalink":"/blog/brakeza3d-0-26-10","source":"@site/blog/2026-10-04-launch-0.26.10-release.md","title":"Brakeza3D 0.26.10 released!","description":"Brakeza3D 0.26.10 is here! This release is all about performance and polish: a reworked renderer","date":"2026-10-04T00:00:00.000Z","tags":[{"inline":true,"label":"brakeza3d","permalink":"/blog/tags/brakeza-3-d"},{"inline":true,"label":"release","permalink":"/blog/tags/release"},{"inline":true,"label":"community","permalink":"/blog/tags/community"}],"readingTime":4.98,"hasTruncateMarker":true,"authors":[{"name":"Eduardo","title":"Lead Developer @ Brakeza3D","url":"https://github.com/rzeronte","imageURL":"https://github.com/rzeronte.png","key":"eduardo","page":null}],"frontMatter":{"slug":"brakeza3d-0-26-10","title":"Brakeza3D 0.26.10 released!","authors":["eduardo"],"tags":["brakeza3d","release","community"]},"unlisted":false,"nextItem":{"title":"Brakeza3D 0.26.8 released!","permalink":"/blog/brakeza3d-0-26-8"}}')},8453(e,n,r){r.d(n,{R:()=>t,x:()=>a});var s=r(6540);const i={},d=s.createContext(i);function t(e){const n=s.useContext(d);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),s.createElement(d.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.