Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by Josh

  1. I found another optimization that I think will pretty much eliminate slowdown when shadows are redrawn.

  2. Two and a half months later, we have shadow maps working:
  3. I’m not sure, I will have to experiment with it.
  4. @gamecreator If you are asking about shadows on vegetation, there is no vegetation system currently, so that problem is solved. Variance shadow maps don't work without all objects casting shadows so I think this will be in there.
  5. I love watching these videos.
  6. Shadow maps are now supported in the new Vulkan renderer, for point, spot, and box lights! Our new forward renderer eliminates all the problems that deferred renderers have with transparency, so shadows and lighting works great with transparent surfaces. Transparent objects even receive lighting from their back face automatically! There is some shadow acne, which I am not going to leave alone right now because I want to try some ideas to eliminate it completely, so you never have to adjust offsets or other settings. I also want to take another look at variance shadow maps, as these can produce much better results than depthmap shadows. I also noticed some seams in the edges of point light shadows. Another interesting thing to note is that the new renderer handles light and shadows with orthographic projection really well. A new parameter has also been added to the JSON material loader. You can add a scale factor inside the normalTexture block to make normal maps appear bumpier. The default value is 1.0: "normalTexture": { "file": "./glass_dot3.tex", "scale": 2.0 } Also, the Context class has been renamed to "Framebuffer". Use CreateFramebuffer() instead of CreateContext().

    1. gamecreator


      Congrats on the progress!  Looking forward to some screenshots.

    2. Josh
  8. Okay, I now have all the Vulkan knowledge I need to finish the renderer.

  9. Josh

    Trials and Tribulations

    Width and height of the framebuffer during rendering were set to zero. I'm back on track.
  10. After about four days of trying to get render-to-texture working in Vulkan, I have everything working except...it doesn't work. No errors, no clue what is wrong, but the renderer is not even clearing the depth attachment, which is why the texture read shown here is flat red. There's not much else to say right now. I will keep trying to find the magic combination of cryptic obscure settings it takes to make Vulkan do what I want. This is very hard stuff, but once I have it working I think that gives me all the functionality I need to finish the Vulkan renderer. Post-processing effects are just another render-to-texture problem. Now, the Vulkan renderer is much more strict than OpenGL, and I think the way post-processing will work is with a an automatically created blur texture and a single post-process shader. It's very wasteful to render a bunch of different passes for each effect, so instead I think we will just have some different effects files and a shader that can include whatever effects you want. In fact, the post-process pass can probably be done as a third Vulkan subpass which would be very efficient.
  11. I would say this is almost definitely the problem. I used to use some apps like this, but it can be very dangerous to mess around with your Windows theme with unofficial stuff. Once I tried to install some unofficial WinXP theme and the whole thing turned every element in the UI pure black. My computer started and ran but was impossible to use at all because everything was black. XD I had to reformat.
  12. Reinstalling does not affect your projects but I doubt that would change anything. This sounds like a windows problem. You could delete your config file, but I think the problem lies with your windows updates or drivers.
  13. Woot, looks like I have render-to-texture working in Vulkan.

    1. Josh


      Nevermind, there is like 20 more steps!

  14. Happy American Independence Day. Most-Patriotic-Games-Duke-Nukem.jpg.opti

  15. Now that we have lights working in our clustered forward Vulkan renderer (same great technique the latest DOOM games are using) I am starting to implement shadow maps. The first issue that came up was managing render-to-texture when the texture might still be in use rendering the previous frame. At first I thought multiple shadowmaps would be needed per light, like a double-buffering system, but that would double the number of shadow textures and video memory. Instead, I created a simple object pool which stores spare shadowmaps that can be swapped around and used as they are needed. It turns out I already have pretty much all the code I need because Vulkan's swapchain creation works exactly the same way, by rendering to a series of images. I worked through the code slowly and came up with this by the end of the day, which runs successfully without throwing any validation errors: bool RenderBuffer::Initialize(shared_ptr<RenderContext> context, const int width, const int height, const int depth, const int colorcomponents, const bool depthcomponent, const int samples) { this->device = GameEngine::Get()->renderingthreadmanager->instance; int totalcomponents = colorcomponents; if (depthcomponent) totalcomponents++; std::fill(colortexture.begin(), colortexture.end(), nullptr); depthtexture = nullptr; //Create color images for (int i = 0; i < colorcomponents; ++i) { colortexture[i] = make_shared<RenderTexture>(); colortexture[i]->Initialize(VK_IMAGE_TYPE_2D, device->chaininfo.imageFormat, width, height, 1, 0, false, -1,-1,-1,-1,1, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); colorimages[i] = colortexture[i]->vkimage; } //Create depth image if (depthcomponent) { depthtexture = make_shared<RenderTexture>(); depthtexture->Initialize(VK_IMAGE_TYPE_2D, device->depthformat, width, height, 1, samples, false, -1, -1, -1, -1, 1, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); } //Create image views imageviews.resize(totalcomponents); VkImageViewCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.subresourceRange.baseMipLevel = 0; createInfo.subresourceRange.levelCount = 1; createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.layerCount = 1; // Create color image views for (size_t i = 0; i < colorcomponents; i++) { createInfo.image = colorimages[i]; createInfo.format = device->chaininfo.imageFormat; createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; VkAssert(vkCreateImageView(device->device, &createInfo, nullptr, &imageviews[i])); } //Create depth image view if (depthcomponent) { createInfo.image = depthtexture->vkimage; createInfo.format = depthtexture->format; createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; VkAssert(vkCreateImageView(device->device, &createInfo, nullptr, &imageviews[colorcomponents])); } //Create framebuffer VkFramebufferCreateInfo framebufferInfo = {}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = device->renderpass->pass; framebufferInfo.attachmentCount = 2; framebufferInfo.pAttachments = imageviews.data(); framebufferInfo.width = width; framebufferInfo.height = height; framebufferInfo.layers = 1; VkAssert(vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer)); return true; } The blog cover image isn't the Vulkan renderer, I just found a random image of Leadwerks shadows.
  16. I think this will be easy to do in a top-down game.
  17. Josh

    Asset Workflow Test

    It looks like in the above shot each floor tile could be 1.28 meters wide (the stairs are 2.56 meters wide). That means two tiles high would be enough for the character to walk under. It looks very close to that right now. But if you are more particular about the size then I can understand how that would be difficult to settle.
  18. I have an idea for a directional light shadow method that replaces cascaded shadow maps and allows sun shadows in the distance with no range limit.

    1. Show previous comments  2 more
    2. Josh


      @gamecreator I don't ever look at code, I just read technical papers. Stuff that has visual diagrams is best.

    3. gamecreator


      Why not look at code?  I feel like you might be missing out on stuff that is faster and/or more optimized than what you could think up sometimes.  I do appreciate that your method makes the engines as much yours as possible though (and maybe that's the point).

    4. Josh


      @gamecreator Anything complex is big and takes a long time to read and understand, and I am pretty good at understanding the best way to manage data in an algorithm. At least that works best for me with graphics. That Doom 2016 analysis for example was very helpful.

  19. Josh

    Coroutine Sequences

    @Rick The whole thing is very interesting because you are programming a "flow" of events instead of a frame-by-frame slice. Maybe a sequence can be created that has two sub-sequences. Something like "bake the chicken and pour the wine" and then dinner is ready when both sequences are complete. I am also thinking about a sub-sequence. If your AI is going to a destination point, but they see a powerup on their way there that they want, it makes sense to create a subtask "go get the powerup" and then resume what they were doing. If a peasant is collecting wood and is attacked by an orc, he should fight the enemy and then go back to collecting wood. He would not start the process over, he would go back to the point he left off. I can think of how to draw that on paper with lines but I don't know yet what the commands would look like.
  20. Josh

    Asset Workflow Test

    Why would you use an odd number like 192? Why not use a pow2 number like 256 or 128? if you do this then it becomes very easy to line up geometry with textures details, like cutting a window out in the right place inside the outline of a window frame drawn on the wall.
  21. Josh

    Coroutine Sequences

    Looks like I broke the Lua binding code: https://github.com/ThePhD/sol2/issues/836 I will continue this later. It can be done in some Lua code if need be.
  22. Josh

    Asset Workflow Test

    I am interested to hear more about this issue. I do not think I understand what you mean. The UV mapping on CSGs should be perfect.
  23. Josh

    Asset Workflow Test

    There is a resize tool in the model editor that might be useful. the motion looks very natural, especially the jumping. It really looks like a little person is in there running around.
  24. Josh

    Coroutine Sequences

    I am experimenting with a system for creating a sequence of actions using Lua coroutines. This allows you to define a bunch of behavior at startup and let the game just run without having to keep track of a lot of states. You can add coroutines to entities and they will be executed in order. The first one will complete, and then the next one will start. A channel parameter allows you to have separate stacks of commands so you can have multiple sequences running on the same object. For example, you might have one channel that controls entity colors while another channel is controlling position. function Script:Start() local MotionChannel = 0 local ColorChannel = 1 local turnspeed = 1 local colorspeed = 3 --Rotate back and forth at 1 degree / second self:AddCoroutine(MotionChannel, ChangeRotation, 0, 45, 0, turnspeed) self:AddCoroutine(MotionChannel, ChangeRotation, 0, -45, 0, turnspeed) self:LoopCourtines(MotionChannel)--keeps the loop going instead of just running once --Flash red and black every 3 seconds self:AddCoroutine(ColorChannel, ChangeColor, 1, 0 , 0, 1, colorspeed) self:AddCoroutine(ColorChannel, ChangeColor, 0, 0, 0, 1, colorspeed) self:LoopCourtines(ColorChannel)--keeps the loop going instead of just running once end There's no Update() function! Where do the coroutine functions come from? These can be in the script itself, or they can be general-use functions loaded from another script. For example, you can see an example of a MoveToPoint() coroutine function in this thread. The same script could be created using an Update function but it would involve a lot of stored states. I started to write it out actually for this blog, but then I said "ah screw it, I don't want to write all that" so you will have to use your imagination. Now if you can imagine a game like the original Warcraft, you might have a script function like this that is called when the player assigns a peasant to collect wood: function Script:CollectWood() self:ClearCoroutines(0) self:AddCoroutine(0, self.GoToForestAndFindATree) self:AddCoroutine(0, self.ChopDownTree) self:AddCoroutine(0, self.GoToCastle) self:AddCoroutine(0, self.Wait, 6000) self.AddCoroutine(0, self.DepositWood, 100) self:LoopCoroutines(0) end I wonder if there is some way to create a sub-loop so if the NPC gets distracted they carry out some actions then return to the sequence they were in before, at the same point in the sequence. Of course this would work really well for cutscenes or any other type of one-time sequence of events.
  • Create New...