You are browsing as a guest. Sign up (or log in) to start making projects!

nikooo

@nikooo

Joined June 2nd, 2026

  • 7Devlogs
  • 2Projects
  • 0Ships
  • 0Votes
Open comments for this post

5h 18m 46s logged

Wrote a full-length devlog about a core feature of Kolori and its implementation, but it got deleted for being “too long”. Lets try again then, with a piece that only demands a bit of your time.


Kolori offers users three (at the moment) coloring modes: HSL, HSLuv, and custom palette generation. How do these work?

Custom palette generation

Unlike HSL and HSLuv, using a custom palette to color the complex plane is much more simple. Kolori lets the user input four arbitrary RGB colors. We then use Inigo Quilez’s cosine-based formula for procedural palette
generation to determine the color of a pixel. An article of his that describes it is here: https://iquilezles.org/articles/palettes/.

The shader code that does it all:

// From https://iquilezles.org/articles/palettes/
vec4 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d)
{
	return vec4(a + b*cos(TAU * (c*t+d)), 1);
}

Our a, b, c, and d are the colors the user has selected, and t is an input variable to vary. However, one would notice that t is a scalar, while we work in the complex numbers. How would we map the plane onto the real line in order to get a valid t to input into palette? The answer we chose is simple: we take the projection onto the real axis–i.e. just taking the real part of the complex number This is an answer that a user would expect and is pointed out in the user guide. Furthermore, by not choosing ahead of time for the user, we allow the user to exert more control over what they wish to generate.

Wrote a full-length devlog about a core feature of Kolori and its implementation, but it got deleted for being “too long”. Lets try again then, with a piece that only demands a bit of your time.


Kolori offers users three (at the moment) coloring modes: HSL, HSLuv, and custom palette generation. How do these work?

Custom palette generation

Unlike HSL and HSLuv, using a custom palette to color the complex plane is much more simple. Kolori lets the user input four arbitrary RGB colors. We then use Inigo Quilez’s cosine-based formula for procedural palette
generation to determine the color of a pixel. An article of his that describes it is here: https://iquilezles.org/articles/palettes/.

The shader code that does it all:

// From https://iquilezles.org/articles/palettes/
vec4 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d)
{
	return vec4(a + b*cos(TAU * (c*t+d)), 1);
}

Our a, b, c, and d are the colors the user has selected, and t is an input variable to vary. However, one would notice that t is a scalar, while we work in the complex numbers. How would we map the plane onto the real line in order to get a valid t to input into palette? The answer we chose is simple: we take the projection onto the real axis–i.e. just taking the real part of the complex number This is an answer that a user would expect and is pointed out in the user guide. Furthermore, by not choosing ahead of time for the user, we allow the user to exert more control over what they wish to generate.

Replying to @nikooo

0
1
Open comments for this post

12h 21m 35s logged

Was preparing for first our ship, but then discovered that my application was leaking memory–badly. Memory usage would climb by a gigabyte in <2 minutes. Worse than any browser you’ve ever seen.


To start, I use Odin, which has a tracking allocator that lets you see where you didn’t free up memory, or perhaps made bad frees. On program exit, it prints out how many bytes you leaked, and where you made the allocations. I had been using this allocator, and it had not reported anything.

Furthermore, upon, admittedly, a very cursory look into my code, I couldn’t find anything that would’ve caused any leaks either–all allocations were eventually freed: whether that be manually or via Odin’s temporary allocator (a really nice feature of the language). LSan hadn’t pointed out anything, and Valgrind didn’t report anything scary, only ~200KiB of memory usage. I had even patched myself a custom allocator, which would print to stdout whenever an allocation was made with it, and I saw nothing concerning at all. Only small allocations were made which were, again, eventually freed.

My application uses SDL3 for windowing and ImGui for GUI, so perhaps one of those has a memory leak in it? I’m not sure. For such a large library, I doubt that’s the case. Though, when running valgrind with --leak-check=full --show-leak-kinds=all I did keep seeing SDL pop up, but it didn’t report any outright leaks.


Upon researching potential external sources for this memory leak, I found https://github.com/libsdl-org/SDL/issues/15192, which describes my issue exactly. It seems that there is no memory leak in SDL, ImGui, or whatever I’m doing, but instead a driver issue, which is interesting. The example that was given to reproduce the leak is quite minimal, so I wonder how that got past their testing. Furthermore, if this is indeed a driver-level issue, why is it that no other applications running on this device leak memory this egregiously? In any case, the leak is not my fault, and out of my hands.

Was preparing for first our ship, but then discovered that my application was leaking memory–badly. Memory usage would climb by a gigabyte in <2 minutes. Worse than any browser you’ve ever seen.


To start, I use Odin, which has a tracking allocator that lets you see where you didn’t free up memory, or perhaps made bad frees. On program exit, it prints out how many bytes you leaked, and where you made the allocations. I had been using this allocator, and it had not reported anything.

Furthermore, upon, admittedly, a very cursory look into my code, I couldn’t find anything that would’ve caused any leaks either–all allocations were eventually freed: whether that be manually or via Odin’s temporary allocator (a really nice feature of the language). LSan hadn’t pointed out anything, and Valgrind didn’t report anything scary, only ~200KiB of memory usage. I had even patched myself a custom allocator, which would print to stdout whenever an allocation was made with it, and I saw nothing concerning at all. Only small allocations were made which were, again, eventually freed.

My application uses SDL3 for windowing and ImGui for GUI, so perhaps one of those has a memory leak in it? I’m not sure. For such a large library, I doubt that’s the case. Though, when running valgrind with --leak-check=full --show-leak-kinds=all I did keep seeing SDL pop up, but it didn’t report any outright leaks.


Upon researching potential external sources for this memory leak, I found https://github.com/libsdl-org/SDL/issues/15192, which describes my issue exactly. It seems that there is no memory leak in SDL, ImGui, or whatever I’m doing, but instead a driver issue, which is interesting. The example that was given to reproduce the leak is quite minimal, so I wonder how that got past their testing. Furthermore, if this is indeed a driver-level issue, why is it that no other applications running on this device leak memory this egregiously? In any case, the leak is not my fault, and out of my hands.

Replying to @nikooo

0
0
Open comments for this post

3h 50m 52s logged

Learned how cool rubberducking is. I was having a problem fixing a bug with the parser (as described below), and I went to write a devlog about it. As I was describing the bug, I immediately had an idea about how to fix it, and lo and behold, it worked. The original post was going to be as follows:


Fixed a bug where trailing input after the parser successfully completes is not disallowed. This most commonly occurs, as I’ve found, after the use of a comma character. The parser simply does not see it, and instead only parses the expression it sees before it.

Internally, a comma character is used to delimit function arguments, so this kind of behavior is not totally useless. However, for situations like picrel, it just seems strange. doesn’t it?

This usually would be an easy bug to fix. We currently use a recursive descent parser (considering moving to a pratt parser) for parsing mathematical expression. All that honestly would’ve needed to be done was adding a check at the procedure that parses the top level grammar rule: “OK, are we at the end of our input? We should be. If not, return an error.”

(Here, I realized that if we literally call this procedure while parsing function calls, it really isn’t too wise to immediately ask “are we done yet?” if we very much aren’t done yet. I then added the check into a procedure that isn’t called by the parser and we should definitely be done by the time that check is ran.)

Learned how cool rubberducking is. I was having a problem fixing a bug with the parser (as described below), and I went to write a devlog about it. As I was describing the bug, I immediately had an idea about how to fix it, and lo and behold, it worked. The original post was going to be as follows:


Fixed a bug where trailing input after the parser successfully completes is not disallowed. This most commonly occurs, as I’ve found, after the use of a comma character. The parser simply does not see it, and instead only parses the expression it sees before it.

Internally, a comma character is used to delimit function arguments, so this kind of behavior is not totally useless. However, for situations like picrel, it just seems strange. doesn’t it?

This usually would be an easy bug to fix. We currently use a recursive descent parser (considering moving to a pratt parser) for parsing mathematical expression. All that honestly would’ve needed to be done was adding a check at the procedure that parses the top level grammar rule: “OK, are we at the end of our input? We should be. If not, return an error.”

(Here, I realized that if we literally call this procedure while parsing function calls, it really isn’t too wise to immediately ask “are we done yet?” if we very much aren’t done yet. I then added the check into a procedure that isn’t called by the parser and we should definitely be done by the time that check is ran.)

Replying to @nikooo

0
0
Open comments for this post

13h 8m 41s logged

(excuse the amount of time, i’m doing general refactors + debugging as well as working on other features)


Implemented adjusting the gamma correction amount. Normally, with the gamma correction, areas close to zero would appear black, and areas that have large magnitudes would appear white. However, you might not always want this, and instead would prefer only pure hue.

Set the gamma correction amount to zero to reduce the amount that colors’ lightness values are altered. An example is shown where we use this feature to produce a colorful, moving spiral. Note that when gamma correction is not zero, as demonstrated, the effect does not work as well.

(excuse the amount of time, i’m doing general refactors + debugging as well as working on other features)


Implemented adjusting the gamma correction amount. Normally, with the gamma correction, areas close to zero would appear black, and areas that have large magnitudes would appear white. However, you might not always want this, and instead would prefer only pure hue.

Set the gamma correction amount to zero to reduce the amount that colors’ lightness values are altered. An example is shown where we use this feature to produce a colorful, moving spiral. Note that when gamma correction is not zero, as demonstrated, the effect does not work as well.

Replying to @nikooo

0
0
Open comments for this post

32h 48m 5s logged

The project has come a long way (see the 30 hours of work that went into this). We now support:

  • arbitrary function input
  • on-the-fly graphing and error checking
  • a “t” time variable, allowing you to animate graphs
  • being able to speed up, slow down, and pause animations
  • screenshots (not imaged below)
  • zoom in/out
  • panning

As well as being multiplatform for both Linux and Windows (you can go build and run this, right now).

What to expect:

  • the ability to change coloring method (hsl, hsluv, palette generation)
  • the ability to use an image for coloring
  • WASM web builds
  • coordinate inspector to see where exactly in the complex plane you are

Check it out on github: https://github.com/neroist/kolori

The project has come a long way (see the 30 hours of work that went into this). We now support:

  • arbitrary function input
  • on-the-fly graphing and error checking
  • a “t” time variable, allowing you to animate graphs
  • being able to speed up, slow down, and pause animations
  • screenshots (not imaged below)
  • zoom in/out
  • panning

As well as being multiplatform for both Linux and Windows (you can go build and run this, right now).

What to expect:

  • the ability to change coloring method (hsl, hsluv, palette generation)
  • the ability to use an image for coloring
  • WASM web builds
  • coordinate inspector to see where exactly in the complex plane you are

Check it out on github: https://github.com/neroist/kolori

Replying to @nikooo

0
2
Open comments for this post

12h 49m 3s logged

Finally! SDL3 & the GPU shaders are working.

FWIW – this is the graph of f(z)=z, the identity transformation.

I will make a devlog on how these images are generated later.

Finally! SDL3 & the GPU shaders are working.

FWIW – this is the graph of f(z)=z, the identity transformation.

I will make a devlog on how these images are generated later.

Replying to @nikooo

0
2
Open comments for this post

10h 49m 27s logged

Finished the lexer + uploaded git repo to github!

Finished the lexer + uploaded git repo to github!

Replying to @nikooo

0
0

Followers

Loading…