A project written entirely from scratch in C(23) with OpenGL. Experience real-time ray marching beauties rendered with signed distance functions. Demos are available in the repository if you don’t want/can’t run it yourself.
A project written entirely from scratch in C(23) with OpenGL. Experience real-time ray marching beauties rendered with signed distance functions. Demos are available in the repository if you don’t want/can’t run it yourself.
For more info about the changes, feel free to read the devlogs that I have posted since the last ship:) Here I have written a simple overview of the changes done.
Since the last ship, I have added a very beautiful shader that renders the Mandelbulb 3D fractal. I also added some utilities, such as a memory leak checker script, make targets, in-app scene switching and frame rate indepedence. I also implemented a bunch of bugfixes, regarding memory, logic issues and such.
A huge feature, that could possibly keep pushing the shaders forward, is my custom GLSL preprocessor. For now it supports the @include directive, which, as you can guess, includes a shader file. It handles recursive includes, so you can include a file with had something included.
This devlog essentially covers some small updates that finished up pre-release v0.2 (and v0.2.1 but that was a tiny bugfix).
I spent a lot of time researching online about README quirks and such, and I believe I made a very pretty README that I can be proud of. It features an animated title, lots of shields, new entries, a table of contents and a gif right there on the top of the README. (See attachment).
Instead of having to change the source code directly to check out the different scenes yourself, you can now simply press ‘,’ or ‘.’ to switch between different scenes right in the app.
The v0.2 pre-release didn’t compile on Windows due to a few issues:
<windows.h> lib declaring/defining really GENERIC symbols, such as ERROR, CreateWindow() and such. I had to #undef the ERROR macro and rename my window functions to be able to include this lib.r as a file open mode rather than rb on Windows causes CRLF (\r\n) to be converted automatically into \n, which then causes my program to crash as the file size wasn’t matching.Log in to leave a comment
🔥 cskartikey marked your project as well cooked! As a prize for your nicely cooked project, look out for a bonus prize in the mail :)
This devlog I made another beautiful shader. This time it is the Mandelbulb, which is a 3D infinite fractal. It serves as an analogue to the famous Mandelbrot fractal, as they showcase similar patterns at various scales. The colouring of the fractal uses Orbit trap, which gets the color based on how close an iterative function, used to create the fractal, approaches some shape. I think mine might be a bit wrong, but the colours are really cool nonetheless, so I just kept it this way on this nice pink (even though I aimed for magma-like colours lol).
I also changed a bit of the internals of the shaders, as, to get the Orbit trap data out of my shader functions, I had to make a structure for it. I made sure not to influence the previous two shaders, though, so they should behave exactly the same.
Of course, with a new shader come new DEMO entries. Check out the demos here :)
In the provided attachments you can see the fractal from various positions.
Log in to leave a comment
I followed up on the previous devlog by restructuring the shader directory. Now it’s divided into folders (see attachment 1) where each of them contain/do a specific function. I had to re-write a bunch of the code to fit this new scheme, and I also had to add recursive include support in my custom preprocessor. Attachment 2 shows the updated shader for the Menger Sponge, where you can see the custom includes. I also did some minor bugfixes and such across the codebase. Next devlog should finally be more shader stuff:)
Log in to leave a comment
I have some neat plans for future shaders, but I recognized that they would use the same functions like some other shaders. That’s why I decided to write a custom GLSL preprocessor. In this devlog I added support for the include directive, which, as the name suggests, lets you include other GLSL files. It simply replaces the directive call with source code that you wanted included. I ran into quite a bit of trouble with memory corruption and such, and that’s why it took quite a while to get this working.
What I really like is that I made it nice and extensible, so when I need a new directive, I just add a few variables and a function to handle the directive and it all should work like a charm:) Expect some pretty shader stuff next devlog, though.
In the image, on the left, you can see the source code of the shader after my custom preprocessor ran. On the right you can see the contents of test.glsl, which used the include directive, and below that the contents of functions.glsl, which is the file that was included.
Log in to leave a comment
When I was testing my app, I found out that there may be memory leaks within my code. I then ran valgrind (a cli tool that displays memory leaks amongst other things) and found quite a range of issues. I fixed all of them, and I also wrote a script (checkMemoryLeaks.sh) that compiles the project, runs valgrind on it, saves the output of valgrind to a file, parses the file to find issues with the project files and neatly outputs the lines in the valgrind log occured. I used that output to validate that the program shouldn’t contain any more memory leaks caused by me. The script outputs some detailed info thats coloured for clarity.
The image shows the output of my script after valgrind has finished running. The remaining memory leaks are not my fault; I checked each one of them in the valgrind log file and found that the stack trace leads to functions out of my reach.
Log in to leave a comment
The first pre-release of this shader project. It’s built from scratch using C(23) and GLSL, which I’m proud of. I tried to minimize external dependencies, so, for example, I’m only using core stuff such as GLFW. Other stuff, such as the math behind matrices or vectors, was implemented by me.
Currently there are two ray marching shaders in this project; a Menger Sponge one, and a sphere one. The Menger Sponge one allows you to render a Menger Sponge of any desired stage (if your GPU can handle it, that is). The sphere ray marching shader allows you to render a uniquely coloured sphere with diffused lighting, whose scene contains a light source to see the diffused lighting in action. Both of the scenes have a 3D first person camera available, which you can move by using the keys WASD and moving your mouse.
If you can’t/don’t wanna run the project, you can check out the demos (link) to see how the project looks.
To finish up the first pre-release of the project, that being version v0.1, I created a file named DEMO.md (link). It contains various images and clips that showcase the shaders in this project. I also finally filled up the changelog (link) with thorough descriptions of each version of the project (you can check out the commit history to see the tags with version that associate it with commits). I also renamed the project from raymarch to raych, as I thought the original name was too vague. I updated the Makefile to be able to package an archive with the binary within. I also added Windows support, via the UCRT64 shell.
Log in to leave a comment
As I mentioned in my previous devlog, I wanted to add a 3d camera; which I did in this one. I had to implement a bunch of vector and matrix mathematical functions to be able to have a 3d camera. I am far too tired to set up video recording on my system, so I provided a photo of the Menger sponge from an angle that I could get only by moving my camera.
Log in to leave a comment
Finally some fun, shader stuff, eh? I, first, created a very simple camera system, which allows you to move on the X and Z axis. It’s a very simple implementation, without any transformation or rotation matrices. That is the plan in the future. You bind the camera movement to a shader struct inside the main while loop, which then lets you change the shader’s camera position, and in the shape render function, it gets passed as a uniform to the fragment shader. After getting that done, I worked on implementing an infinite (in theory) 3d fractal named Menger sponge, which I was able to do after learning up on shader concepts and math from some very helpful online resources. I was able to create a function inside the fragment shader that lets me render a Menger sponge of desired stage (see images, where the stage is 5). In the future I’d really like to make the Menger sponge infinite, so you would just fly in Menger sponges forever.
Log in to leave a comment
And for the cherry on top of the up-’n-coming v0.0.1 (pre)release, some actual ray marching shaders. I draw a quad covering the whole viewport and then apply shading in the fragment shader to draw a deformed sphere with simple diffused lighting and curious colors. I spiced it up a bit by passing time to the shader so it glows periodically (based on sin()). In the future I reckon its entirely possible to make the camera movable and light not hardcoded.
PS: For the curious, v0.0.1 update will be out when I add windows compatibility.
Log in to leave a comment
Another OpenGL thing that I implemented this devlog is some basic shape rendering. I added nice functions for rendering a triangle and rectangle to the screen. It’s kinda inefficient but I tried to focus on first having something work and then improving it later if necessary. Data is passed to the functions via a structure that contains the position info and the shape’s color.
Log in to leave a comment
First of the things required for rendering are shaders, and this devlog/commit I added a simple shader abstraction layer. The file, for now, it exposes a simple CreateShader(..) function which takes in paths to vertex and fragment shaders, and returns a structure which, as of right now, contains just the program ID. I also fixed the odd bug, which was simply caused by not initializing (malloc-ing) some internal variables. It all should work correctly now.
Log in to leave a comment
Another core thing to tackle before the fun shader stuff. I added a dedicated logger, which is just a few functions to neatly display logs, and two macros to wrap them for convenience. Curiously, I have encountered a peculiar bug which I can’t seem to find the root of. the LOG(...) macro segfaults if I use it in the main render loop, but nowhere else. In this case, the LOG_RAW(...) macro doesn’t. Also sometimes internal char* buffers for color and label fail (see the screenshot) and I simply have no idea why, as always happens with one specific LOG and no other ones.
Log in to leave a comment
In the first hour (and some minutes) of this project I simply set up my repository, which includes, but is not limited to, the directory structure, Makefile, README contents, the GPLv3 license and wrote some window abstraction code. That means, at this point in time, I can open a window. The project currently only runs on GNU/Linux, but in the future, I plan to support Windows operating systems as well.
Log in to leave a comment