Another month, another weird devblog. They keep coming out later in the month as well, so at some point I’m going to have to correct for that and put up an update after just a couple of weeks of work.
This is a tough one to write: A lot of the last month was spent on wasted time and dead ends, and the work which has been accomplished is largely rather dry and technical, not lending itself especially to pretty screenshots or poetic descriptions. I apologize for this likely extremely boring devblog.
Anyway: Almost immediately after last month’s update, I got tired – real tired. I lost all energy and inclination towards productivity for about a week. Afterwards, I felt pretty great – but, looking back at it now, I’m not sure how much I accomplished in the aftermath either. One of the first things I did after waking up was to write out all of the documentation for the sprite shaders. This was definitely something that needed to be done, but I underestimated how many parts of the project were and remain still in flux. I said the project was almost done last time, and ‘almost done’ it remains, moving towards completion only slightly faster than completion itself moves further away. I keep coming up with new ideas and, since I’m more excited by new ideas than I am by ever finishing anything, overall I’m progressing slowly. Regardless, while it may be frustrating having to keep updating the documentation, it’s at least a less intimidating task than creating the whole thing from scratch.
Meanwhile, I had an idea: Right now the project has a secondary utility script which allows the user to modify shader parameters, so they don’t need to create a new material for each individual GameObject. I realized that I might be able to bypass the necessity of this script by creating a replacement for Unity’s default SpriteRenderer UI. I spent a solid week or so working on this, since Unity really doesn’t make this sort of thing easy to do, before realizing I’d made a huge oversight: UI elements don’t serialize any data, so any changes made would be lost as soon as the scene reloads. Now that I’m thinking about it again, this problem may not be insurmountable… Well, if I find a workaround you can read about it next month, but I at least thought I’d wasted a week.
Surprisingly, this didn’t upset me very much. I’m not entirely sure whether that’s a good thing or a bad thing. On the one hand, I certainly prefer not being angry; on the other I can’t help but feel that this sanguine attitude towards delays and challenges is part of why my projects don’t get finished. I’ve been recently focused on why I have issues with consistency, with weird aversions and anxieties, and exploring various ADHD treatments as possible solutions. I do feel somewhat more aware of what my issues are, feel a bit more comprehensive awareness of what my deal is, but not enough to feel unencumbered by these challenges.
Another major problem I tackled this month was the idea of modifying the vertices of the sprite within the shader to accommodate any special effects which might expand beyond the normal boundaries of the sprite, making them cut off in a rather unattractive manner. In order to do this operation, I needed to have the positions of the vertex pivot in world space along with the matching pivot location on the texture – this ended up creating some kind of interesting and fun algebra challenges, and also required me to implement a new kind of shader, a geometry shader, which contains information about sets of vertices (rather than individual vertices) so I was able to calculate their position relative to each other. This feature is now largely complete, though I could probably make it more efficient, particularly where rotation is concerned – I was having a difficult enough time figuring out what the maximum possible extents of a set of points being rotated through an arc might be that I currently just have it set to the maximum possible extents of the points being rotated around 360°.
After that, I worked on pixel snapping and pixel scaling. This is basically a setting that lets you snap the pixels to boundaries based on the resolution of the screen or texture, so that it is effectively drawn at half resolution or whatever. This is normally a trivial challenge – so much so that I’d probably barely mention it here – but in combination with other features actually becomes surprisingly tricky. The issue is that, while snapping a single texture’s values along pixel boundaries is very easy, snapping a texture which is having its values modified by another texture to pixel boundaries is… not. It required a lot of finagling to get them to basically line up, but after a couple of days I got there – mostly. The result of this is the header image, another experimental fire render, which looks mostly correct but which, if you look closely, also has weird seams where a little bit of pixel edge renders while the rest is transparent. I don’t know what’s causing this, but I’m declaring this feature Good Enough For Now.
I can’t help but notice how many features have gotten added, and how this one-month project has ballooned into a 3-month project. I’ve definitely allowed myself to move too many goal posts, and I now need to decide on a release feature list once and for all. First, I can add the features that are already complete:
- Depth/Shadows (with dithered transparency)
- Blend Modes
- Lighting w/ Normal Mapping (and alternate normal spaces)
- Color Transformation w/ Masking
- Displacement w/ Mapping
- Vertex Transformation w/ Mapping
- Mix-In Texture
- Modifier Sprite
- Vertex expansion for special effects
- Pixel Snap/Scale
Then, a few other features which are mostly complete or which I’m confident can be done quickly and which I can safely commit to finishing before release:
- Blur
- Outline
- Texture rotation
- Texture value curve
- Pre-Made demo effects: Fire (static and particles), Water, Grass, Ripples, ???
And a few other features which I’m excited about enough to want to try but won’t commit to:
- Seamless UI Replacement/Expansion
- Normal Beveling
- Deferred Rendering
Along with a few that I’m definitely not going to bother with yet, but may add in the future:
- Fog support
- Smoothness/Metallic/Emission maps
These, along with anything else that comes up, can wait to be added in until after release.
None of these planned features, except for the pre-made effects, should take very long, so next week will probably have those wrapped up and hopefully give me enough info to decide which of the maybe’s will be included. After that, hopefully one week will be enough to wrap up the documentation and put together a trailer and a store page and finally make this thing real. I will also need to make some resources for actually learning how to use these tools: Tutorials are good, but I think in the short term it will be easier to just have the pre-made effects include little info boxes explaining how they were created. Actual tutorial videos can perhaps be created the week after it goes up on the store, when it’s less of an obstacle and more of an extra.
Hopefully this is the last devblog entirely about sprite shaders. It’s a fun side project, and I think the features I’m adding will be useful for EverEnding and, hopefully, useful to many other game developers as well – but I’m so impatient to get back to the game itself!