Thu Feb 13 09:04:14 PM CET 2025
Broken
"You still think I'm too optimistic, don't you?" Shallan said.
"It's not your fault", Kaladin said. "I'd rather be like you. I'd rather not have lived the life I have. I wish that the world was only full of people like you, Shallan Davar."
"People who don't understand pain."
"Oh, all people understand pain." Kaladin said. "That's not what I'm talking about. It's ..."
"The sorrow", Shallan said softly, "of watching a life crumble? Of struggling to grab it and hold on, but feeling hope become stringy sinew and blood beneath your fingers as everything collapse?"
"Yes."
"The sensation -- it's not the sorrow, but something deeper -- of being broken. Of being crushed so often, and so hatefully, that emotion becomes something you can only wish for. If only you could cry, because then you'd feel something. Instead, you feel nothing, Just... haze and smoke inside. Like you're already dead."
He stopped in the chasm.
She turned and looked to him. "The crushing guilt", she said, "of being powerless. Of wishing they'd hurt you instead of those around you. Of screaming and scrambling and hating as those you love are ruined, popped like a boil. And you have to watch their joy seeping away while you can't do anything. They break the ones you love, and not you. And you plead. Can't you just beat me instead?"
"Yes", he whispered.
Shallan nodded, holding his eyes. "Yes. It would be nice if nobody in the world knew of those things, Kaladin Stormblessed. I agree. With everything I have."
He saw it in her eyes. The anguish, the frustration. The terrible nothing that clawed inside and sought to smother her. She knew. It was there, inside. She had been broken.
Then she smiled. Oh, storms. She smiled anyway.
Sun Feb 9 05:02:41 PM CET 2025
I am offend! Very offend! No apologize! Boots!
Rock would definitely have a fit.
Tue Jan 28 07:01:59 PM CET 2025
Cooking Mung bean sweet soup
Instead of boiling it for nearly an hour (without presoak, didn't even think about that), just boil it and leave it there for like half an hour, with lid on to keep the heat. The beans are quite soft after, so just cook it to boil again for just a little bit longer and it's done.
Soaking first with cold water probably works too, but probably takes longer time too. At least this way it's almost the same time as before but we save electricity.
Mon Jan 27 09:38:37 PM CET 2025
The Way of Kings
"When we are young", Jasnah said, "we want simple answers. There is no greater indication of youth, perhaps, than desire for everything to be as it should. As it has ever been."
Shallan frowned, still watching the men by the tavern over her shoulder.
"The older we grow", Jasnah said, "the more we question. We begin to as why. And yet, we still want the answers to be simple. We assume that the people around us -- adults, leaders -- will have those answers. Whatever they give often satisfies us."
(Not in the book)
As we grow even older, we stop asking questions. And doesn't care what the answers are for the remaining questions. We've reached peak maturity. Then we die.
Fri Jan 10 08:01:35 PM CET 2025
Damn it! Damn it! Damn it!
Shop Cat sold both Ping and Wisp on second mission. It's dream come true. But Internationale got herself killed anyway. And Decker already got knocked out first mission. Dang it, line of sight is hard. Expert Plus is too plus, I mean hard!
Sat Dec 21 10:58:12 AM CET 2024
You know you play too much Yakuza's karaoke game...
When you start a new game (Infinite Wealth) and got 100 on the first try. Granted, The Future I Dreamed Of is a rather easy one (and probably my very first 100 ever) but still...
That damned Machine Gun Kiss is still hard as f*. First try 85 plus though so not as bad. Second try 90 plus.
PS. And you know you play way too much Karaoke when by the end game you have four songs at 100 points, Hands 98 and the rest 99.
Wed Dec 18 10:28:12 PM CET 2024
I like .md2 format already
It's used for model and animation in Quake II. It was intimidating at first, but it turns out dead simple.
Basically you have a list of vertices and their normals. One per frame because it's quite hard to share vertices when your model moves around. Then you have a list of texture coordinates. These of course can be shared. Then you have a number of frames, each contains a list of indexes of vertices and texture coordinates so you can start drawing triangles.
And that's pretty much it! There's a section for more optimized drawing, using both triangle strips and fans to save draw commands. But since D3D10+ stops supporting triangle fans (and therefore SDL3 GPU does not either), this is no-go.
We probably can still optimize if we want though, by detecting duplicate vertices (with attributes) then draw with index instead. Not sure how much saving that is. But it sure is interesting to find out.
Doing all this made me wonder if I actually applied texture back in glBomb because the models are just red most of the time. Turns out the texture is there, but mild because the whole thing is zoomed out. And then we keep flashing red, not sure why. For flashy? The next version won't be so flashy, and perhaps will have shadow!
Tue Dec 17 11:18:50 PM CET 2024
Quake 2 "md2" format
Finally got over lighting (the simplest one) and started to look at rendering something nicer than a cube. Finally looked at cone3dmd2.cc in glBomb.
I don't think I ever looked inside this code before? MD2 looks more like gif because it stores multiple "frames", complete vertices for each frame. I suppose it's easier to animate this way (than dealing with skeleton animation, which is a completely different beast). But it also means the naive plan to move to the modern gltf format is not going to work out well because ...
Ah but gltf does seem to support animation, so perhaps simply converting md2 to gltf would do the trick? Oii who cares. Just render it with md2 first. Convert it to gltf and do it again!
PS. Moving again?
Sun Dec 15 05:11:44 PM CET 2024
Misunderstanding fragment shader
Let's say we draw a triangle (will I ever draw anything more than a triangle?), we have vertex attributes for 3 vertices of course and the vertex shader produces three vertices. Then some information from the vertex shader (most likely UV texture coordinates) are passed along to the fragment shader.
Here I actually thought the fragment shader was run three times, once per vertex, and all other pixels are "interpolated" somehow.
Which is rather limited in what a fragment shader can do. The reality, it seems, is that the fragment shader would be run for all rasterized pixels (i.e. the entire triangle after mapped to window space) and it's given coordinate for each pixel in gl_FragCoord. And we could do whatever with it.
This just means we essentially have a canvas to draw on. Except that we draw all pixels in parallel, so there can't be any dependencies between pixels in the drawing code.
The remaining question is, how come 3 vertext shader outputs are "attached" to a zillion fragment shaders (one per pixel)? It seems all vertex output would be interpolated. How it's done can be controlled via interpolation qualifiers.
Fri Dec 13 05:13:01 PM CET 2024
I SDL3_GPU now!
Still trying to avoid going back to the lighting lesson in OpenGL. So after Vulkan, let's try Vulkan again, but this time less painful with SDL3's GPU abstraction.
It's not bad. But to be fair, nothing can be bad after the Vulkan experience. Some concept stays, like pipeline creation. Buffer management is SDL's business, but you still have to say where the buffer should be and whether CPU or GPU can access it.
Data transfer is also more explicit like Vulkan. Create a buffer that CPU can see, map it, copy data to it, setup a copy pass to send commands to copy it to a GPU buffer. Doing this in Vulkan is more involved because you also have to explicitly transition the destination buffer.
After that it looks slightly more OpenGL in the rendering loop, probably because it's greatly simplified. You have to bind the pipeline of course. Then instead of binding descriptor sets(?) you can just bind the vertex buffers (haven't touched texture, or uniform buffers yet). Then draw and submit.
The core code looks rather short and sweet
SDL_GPUCommandBuffer* cmdBuf = SDL_AcquireGPUCommandBuffer(device);
SDL_AcquireGPUSwapchainTexture(cmdBuf, window, &swapchainTexture, nullptr, nullptr);
SDL_BeginGPURenderPass(cmdBuf, &colorTargetInfo, 1, nullptr);
SDL_BindGPUGraphicsPipeline(renderPass, pipeline);
SDL_BindGPUVertexBuffers(renderPass, 0, &binding, 1);
SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0);
SDL_EndGPURenderPass(renderPass);
SDL_SubmitGPUCommandBuffer(cmdBuf);
Since we're not going to reuse command buffers (and other stuff), fencing seems less important. SDL will just have to handle all that. Though if you have multiple command buffers with some dependency, then yeah fences will become important.
Doesn't look like SDL3 has pipeline cache yet, which is another pain point (and strong point?) of Vulkan.
Overall not bad. 200 lines for a triangle. Though I still need to try out uniform / storage buffers, texture and compute shader. Wonder why geometry shader is not here, perhaps compute shader can take care of it.