paniq [Lexaloffle Blog Feed] Megacolors <p> <table><tr><td> <a href="/bbs/?pid=56729#p"> <img src="/bbs/thumbs/pico56728.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=56729#p"> Untitled</a><br><br> by <a href="/bbs/?uid=9107"> paniq</a> <br><br><br> <a href="/bbs/?pid=56729#p"> [Click to Play]</a> </td></tr></table> </p> <p>I was wondering if it would be possible to use structured temporal dithering to fake more than 16 colors, and it is indeed possible!</p> <p>at 60hz, 1:2 mixes look fairly natural, but 1:4 mixes are a little too noisy.</p> Sun, 16 Sep 2018 08:25:45 UTC gradient palettes <p>I've been designing some gradient palettes for various materials and wanted to share them here for inspiration.</p> <img style="margin-bottom:16px" border=0 src="" width=602 height=628 alt="" /> <p>got anymore ideas what to do? It seems especially blue leaves very little options...</p> Mon, 18 May 2015 02:43:52 UTC Feature request: x-mirror in map editor <p>While experimenting with translating some &quot;Zelda - Link From The Past&quot; tiles into pico, I noticed that a lot of sprites save memory by mirroring the left half to the right one.</p> <p>While the API allows drawing sprites mirrored along the x-axis, the map editor only permits one tile direction.</p> <p>Would it be possible to add the ability to mirror sprites to the map editor as well?</p> Mon, 18 May 2015 01:46:42 UTC Ideas for a GPU implementation <p>I've been thinking about how PICO-8 could provide very primitive 3D software rasterization capabilities that remain within the spirit of the system. These are just goofy ideas, please feel free to bury them if they're too far outside the project scope, but I had to at least write it down once.</p> <p>In any case, it should be possible to implement nearly all of the features below in a cartridge.</p> <p>Following things need to be implemented in order for this to work:</p> <ul> <li>Mesh ROM</li> <li>Mesh editor</li> <li>API functions</li> <li>Z-buffer</li> </ul> <p>Mesh ROM specs:</p> <ul> <li>128 meshes (or less? animated meshes are considered here)</li> <li>per mesh: 16 vertices, 16 quads (96 bytes)</li> <li>index of 8x8 sprite to use as texture / colormap</li> <li>Vertex format: 3x(0..7) position</li> <li>Quad format: 4x(0..15) vertex index, 2x2x(0..7) uv rect (x1,y1,x2,y2)<br /> 0 = no quad</li> </ul> <p>The editor would get a new page with an editing view (64x64) that supports two modes: mesh editing and uv editing.</p> <p>mesh editing:</p> <ul> <li>The view supports free (orthogonal) rotation to preview the result and select obstructed vertices/faces. </li> <li>An extra label displays the index of the selected vertex or face.</li> <li>A toggle switches the view mode: textured / wireframe.</li> <li>left-double-click creates a new vertex. </li> <li>left-click selects a vertex or a face (depending on proximity of cursor to edge of face). </li> <li>right-click on a vertex begins to build a face; 4 vertices of which at least 3 are unique need to be right-clicked in succession to complete the face; right-clicks that don't hit vertices are ignored. a left-click will abort. If the 4 vertices already comprise a face, the operation has no effect.</li> <li>left-drag moves the vertex or face (all vertices of the face) along the orthogonal plane that's best facing the camera (dot product of view normal and plane normal closest to -1). That way no explicit orthogonal view is necessary. If a vertex is moved onto the position of another vertex, the vertex will be reset to its original position. That way, overlapping vertices are avoided.</li> <li>right-drag orbits the camera around the center, and implicitly selects the plane along which vertices and faces will be moved when editing.</li> <li>DELKEY removes the selected vertex or face. face removal does not remove vertices.</li> <li>the mesh can be copied/pasted to other slots in order to facilitate the creation of animations.</li> </ul> <p>uv editing (allowed when a face is selected):</p> <ul> <li>The view shows the default 8x8 texture for this mesh, with a rectangle indicating the region that the active face will be mapped to. If only three vertices of the face are unique, the face will be a triangle (x1,y1 - x1,y2 - x2,y1).</li> <li>Per default, the face is mapped to the entire texture.</li> <li>x1,y1 are rounded to the upper left edge of the texel, x2,y2 are rounded to the lower right edge. That way, a single texel can color the entire quad.</li> <li>An extra panel allows selecting the default texture this mesh will use.</li> <li>left-drag draws a new rectangular bounding box for the quad. A simple left-click selects a single pixel as the quads texture.</li> </ul> <p>The API gets 6 new functions:</p> <p>clsz()</p> <ul> <li>clears the z-buffer to 0 (see Z-buffer notes further below)</li> </ul> <p>zget(x,y)<br /> zset(x,y,z)</p> <ul> <li>get or set the z-value of a z-buffer pixel.</li> </ul> <p>camera3d(&lt;x&gt;, &lt;y&gt;, &lt;z&gt;, &lt;m00&gt;, &lt;m01&gt;, &lt;m02&gt;, &lt;m10&gt;, &lt;m11&gt;, &lt;m12&gt;, &lt;m20&gt;, &lt;m21&gt;, &lt;m22&gt;, [&lt;orthogonal&gt;])</p> <ul> <li>configures the camera (view) matrix for subsequent mesh drawing calls.</li> <li>x y z: origin of camera</li> <li>m00-m22: orientation of camera as a 3x3 matrix; (1,0,0,0,1,0,0,0,1) would describe an identity matrix.</li> <li>orthogonal: if true, an orthogonal projection will be applied instead of the default perspective projection, which is analog to an infinite far plane projection matrix.</li> </ul> <p>model(&lt;x&gt;, &lt;y&gt;, &lt;z&gt;, &lt;m00&gt;, &lt;m01&gt;, &lt;m02&gt;, &lt;m10&gt;, &lt;m11&gt;, &lt;m12&gt;, &lt;m20&gt;, &lt;m21&gt;, &lt;m22&gt;)</p> <ul> <li>configures the model matrix for subsequent mesh drawing calls</li> <li>x y z: origin of model</li> <li>m00-m22: orientation of model as a 3x3 matrix; (1,0,0,0,1,0,0,0,1) would describe an identity matrix.</li> </ul> <p>mesh(&lt;mesh index&gt;, [&lt;texture&gt;], [&lt;flags&gt;], [&lt;face mask&gt;], [&lt;mesh 2&gt;, &lt;blend&gt;])</p> <ul> <li>rasterizes the triangles of a mesh with model, camera, projection transformations applied.</li> <li>mesh index: the index of the mesh to rasterize (0..128).</li> <li>texture: index of the sprite to use as the meshes texture (0..128). If omitted or nil, the default texture will be used. If texture is -1, the mesh will be rendered as wireframe.</li> <li>flags: Sets various render flags: bit 0 = read &amp; test depth; bit 1 = write color; bit 2 = write depth; bit 3 = cull backfaces. The default flags are 0xF.</li> <li>face mask: a set of 16 bitflags, indicating which faces should be rasterized/skipped. If omitted, all faces will be rasterized (face mask = 0xFFFF)</li> <li>mesh 2, blend: if specified, blends the vertices between this mesh and another by factor &lt;blend&gt; (0 = 100% mesh A, 0.5 = 50% mesh A, 50% mesh B, 1 = 100% mesh B). This way,<br /> smooth keyframed animations can be rendered.</li> </ul> <p>Z-buffer:</p> <p>To facilitate order-independent rasterization (depth culling), a 128x128 Z-buffer must be available. The minimum required precision is unclear, but I assume half-float or 16bit precision is needed at least (= 32k). The Z-buffer ranges from 0 to 1, where 0 is infinitely far away and 1 is the near plane. This configuration is appropriate when transforming triangles with an infinite far plane projection matrix. In this entire setup, the near plane is fixed to a system default, e.g. 0.1 or 1.</p> <p>Here is exemplary GLSL code that describes how to do the projection transform:</p> <p>// transform a vector v by an infinite projection matrix so<br /> // that z is projected to the range 1..0 after the vertex shader.<br /> // aspect is usually vec2(1, w/h) or vec2(h/w, 1)<br /> vec4 projection_transform(vec2 aspect, float near, vec4 v) {<br /> return vec4(v.xy<em>aspect, v.w</em>near, v.z);<br /> }</p> <p>// do the inverse of projection_transform(), with baked-in divide by w<br /> vec4 inverse_projection_transform(vec2 aspect, float near, vec4 v) {<br /> float w = near / v.z;<br /> return vec4(v.xy<em>w/aspect, v.w</em>w, 1);<br /> }</p> Sun, 17 May 2015 04:06:36 UTC HSL2RGB example <p> <table><tr><td> <a href="/bbs/?pid=10717#p"> <img src="/bbs/thumbs/pico10716.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=10717#p"> HSL2RGB example 1.0</a><br><br> by <a href="/bbs/?uid=9107"> paniq</a> <br><br><br> <a href="/bbs/?pid=10717#p"> [Click to Play]</a> </td></tr></table> </p> <p>An approach to dither the colors of the HSL colorspace with the 16 built-in colors. I settled for a randomized dither. You can download the source by clicking on the icon &amp; saving the png.</p> Sat, 16 May 2015 17:49:05 UTC 3D Cube <p> <table><tr><td> <a href="/bbs/?pid=10705#p"> <img src="/bbs/thumbs/pico10704.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=10705#p"> 3D Cube 1.0</a><br><br> by <a href="/bbs/?uid=9107"> paniq</a> <br><br><br> <a href="/bbs/?pid=10705#p"> [Click to Play]</a> </td></tr></table> </p> <p>A very simple 3D rasterizer that renders a rotating flat shaded cube.</p> Sat, 16 May 2015 00:29:19 UTC Duangle 2015 Intro <p> <table><tr><td> <a href="/bbs/?pid=10699#p"> <img src="/bbs/thumbs/pico10782.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=10699#p"> Duangle 1.11</a><br><br> by <a href="/bbs/?uid=9107"> paniq</a> <br><br><br> <a href="/bbs/?pid=10699#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is kind of a parody of old amiga cracktros from a parallel universe, where duangle is a demoscene group, and so are all the people in the greetings!</p> <p>1.1: added new greetings</p> Fri, 15 May 2015 19:34:31 UTC Demovibez <p> <table><tr><td> <a href="/bbs/?pid=10684#p"> <img src="/bbs/thumbs/pico10683.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=10684#p"> Demovibez 1.0</a><br><br> by <a href="/bbs/?uid=9107"> paniq</a> <br><br><br> <a href="/bbs/?pid=10684#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is my first cartridge, a tiny self-running intro with music that does a dithered sinus effect. This started as a fullscreen effect but I had to reduce the amount of pixels to fit the CPU limit.</p> <p>ph34r!</p> Fri, 15 May 2015 13:11:42 UTC PICO-8 first impressions <p>So I finally had some time to play with Pico-8 yesterday, and wrote two tiny cartridges, and instead of spamming zep on Twitter I thought it would be more useful to post my thoughts here, in order of appearance.</p> <ol> <li> <p>Jelpi is a pretty impressive demo, i love everything about this handheld console that never existed :D</p> </li> <li> <p>There should be a version of the manual that looks like a 90's devkit manual black &amp; white hardcopy, with a serious layout like the devkit cost $10k. But this is a bootlegged copy of the manual, so it got xerox smudges, is not fully level and is obviously copied right out of a bound book, and right on the first page it says stuff like &quot;FOR YOUR EYES ONLY. YOU ARE CONTRACTUALLY BOUND TO NOT DISCLOSE ANY INFO&quot; etc. On the second page there's a pompous introductory text from the company founder that flaunts the pico-8's luxurious capabilities, telling you how you can be proud to be able to develop for this console and how it's lightyears ahead of the competition. The manual is not even a full copy, it seems like it's just the most important pages copied out; the pages are numbered like 110-112, 351, 430, with paragraphs that make reference to appendixes that don't exist (&quot;see Appendix E for chipset layout&quot;).</p> </li> <li> <p>It's obvious that this pico-8 firmware is the devkit, which starts with a prompt. I imagine a &quot;consumer device&quot; would boot right into the cartridges. :-)</p> </li> <li> <p>First I thought Lua's numeric type had been downgraded to signed short, but then I realized it's actually fixed point 16bit for both integer and fractional part. Very cool.</p> </li> <li> <p>I'd remove all references to Lua and give this language a different name, e.g. Picoscript or Picolua; otherwise I'd just expect everything to work the same way; it's sufficiently different, i think. Considering how all the commands are named, PicoBASIC seems most fitting.</p> </li> <li> <p>I thought that it would be more useful to arrange the palette in a way that makes the 4-bits more significant (e.g. LRGB), similar to how the default <a href="">EGA</a> color palette is arranged. In EGA, bit 3 effectively changes brightness (sort of) without altering hue, that allows for very easy lighting tricks. The numeric bits correspond to RGB, so you can fake additive light effects with simple bit twiddling. Here, i'd ultimately do it with a lookup table; I guess it's too late to change it anyway.</p> </li> <li> <p>I missed a few important math functions, in order of importance: sqrt(x), atan(y,x), exp(x), log(x)</p> </li> <li> <p>The very first thing I attempted to write was a simple per-pixel fullscreen effect, and I ended up with a CPU usage of &gt; x4. I have absolutely no clue which operations are how expensive, and it would help tremendously to have some sort of clock cycle table that shows which operations eat how much time. Do graphics and sound run on separate chips like with the SNES? I hope yes.</p> </li> <li> <p>The sequencer and tracker lack a copy function. It seems also despite the game controller correctly recognizing my german keyboard, the note editor does not take keys by scancode, and so Y and Z are swapped there. I can imagine french keyboards have it even worse.</p> </li> <li> <p>I missed file system operations for file rename and deletion.</p> </li> <li> <p>There's no quicksave shortcut, which made me very nervous. Ctrl+S has no effect. I hoped &quot;save&quot; without arguments would save the module to the last saved file but it had no effect either. I'm a &quot;I need to save every 3 minutes&quot; kind of dude, so that got annoying very quick.</p> </li> <li> <p>It would be cool to be able to load two cartridges, so one can act as an editor for the other one, so people can write alternative editors; The idea being here that the built-in editor could be implemented as a separate cartridge that makes no use of secret system functions.</p> </li> <li>It would be useful to have primitive support for keyboard and mouse peripherals, like the editor has. Maybe as a special &quot;devkit&quot; mode that won't work on &quot;consumer devices&quot;.</li> </ol> <p>I'll also shortly post the first cartridges I did.</p> <p>Cheers</p> Fri, 15 May 2015 12:58:47 UTC