Jump to content

Josh

Staff
  • Posts

    23,506
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh

    Articles
    2020 was the most intellectually challenging year in my career. Many major advancements were invented, and 2021 will see those items refined, polished, and turned into a usable software product. Here is a partial list of things I created:
    Streaming hierarchal planet-scale terrain system with user-defined deformation and texture projection. Vulkan post-processing stack and transparency with refraction. Vulkan render-to-texture. Major progress on voxel ray tracing. Porting/rewrite of Leadwerks GUI with Implementation in 3D, rendered to texture, and using system drawing. Plugin system for loading and saving textures, models, packages, and processing image and mesh data. Lua debugger with integration in Visual Studio Code. Pixmap class for loading, modifying, compressing, and saving texture data. Vulkan particle system with physics. Implemented new documentation system. Lua and C++ state serialization system with JSON. C++ entity component system and preprocessor. (You don't know anything about this yet.) Not only was this a year of massive technical innovation, but it was also the year when my efforts were put to the test to see if my idea of delivering a massive performance increase for VR was actually possible, or if I was in fact, as some people from the Linux community have called me, "unbelievably delusional". Fortunately, it turned out that I was right, and an as-of-yet-unreleased side-by-side benchmark showing our performance against another major engine proves we offer significantly better performance for VR and general 3D graphics. More on this later...
    Additionally, I authored a paper on VR graphics optimization for a major modeling and simulation conference (which was unfortunately canceled but the paper will be published at a later time). This was another major test because I had to put my beliefs, which I mostly gain from personal experience, into a more quantifiable defensible scientific format. Writing this paper was actually one of the hardest things I have ever done in my life. (I would like to thank Eric Lengyel of Terathon Software for providing feedback on the final paper, as well as my colleagues in other interesting industries.)
    I'm actually kind of floored looking at this list. That is a massive block of work, and there's a lot of really heavy-hitting items. I've never produced such a big volume of output before. I'm expecting 2021 to be less about groundbreaking research and more about turning these technologies into usable polished products, to bring you the benefits all these inventions offer.
  2. Josh
    An update is available on the beta branch. This adds the Window::Center style back into the new refactored Window class, and adds a missing header file in the Professional Edition.
     
    If you'd like to try out a basic implementation of the new GUI, download and extract the attached scripts:
    Scripts.zip
     
    This code will create a GUI on the rendering context. It simply consists of a solid background filling the screen and a textless button.

    --Initialize Steamworks (optional) Steamworks:Initialize() --Set the application title title="test" --Create a window local windowstyle = window.Titlebar + window.Resizable if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle) --window:HideMouse() --Create the graphics context context=Context:Create(window,0) if context==nil then return end --Create a world world=World:Create() world:SetLightQuality((System:GetProperty("lightquality","1"))) --Load a map local mapfile = System:GetProperty("map","Maps/start.map") if Map:Load(mapfile)==false then return end --Create a GUI local gui = GUI:Create(context) gui:GetBase():SetScript("Scripts/GUI/Panel.lua") local widget = Widget:Create(20,20,75,30,gui:GetBase()) widget:SetScript("Scripts/GUI/Button.lua") while window:KeyDown(Key.Escape)==false do --If window has been closed, end the program if window:Closed() then break end --Handle map change if changemapname~=nil then --Clear all entities world:Clear() --Load the next map Time:Pause() if Map:Load("Maps/"..changemapname..".map")==false then return end Time:Resume() changemapname = nil end --Update the app timing Time:Update() --Update the world world:Update() --Render the world world:Render() --Render statistics context:SetBlendMode(Blend.Alpha) if DEBUG then context:SetColor(1,0,0,1) context:DrawText("Debug Mode",2,2) context:SetColor(1,1,1,1) context:DrawStats(2,22) context:SetBlendMode(Blend.Solid) else --Toggle statistics on and off if (window:KeyHit(Key.F11)) then showstats = not showstats end if showstats then context:SetColor(1,1,1,1) context:DrawText("FPS: "..Math:Round(Time:UPS()),2,2) end end --Refresh the screen context:Sync(true) end
     
    This code will create the same GUI directly on the window, with no rendering context initialized, using the native OS drawing commands:

    --Initialize Steamworks (optional) Steamworks:Initialize() --Set the application title title="test" --Create a window local windowstyle = window.Titlebar + window.Resizable if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle) --window:HideMouse() --Create a GUI local gui = GUI:Create(window) gui:GetBase():SetScript("Scripts/GUI/Panel.lua") local widget = Widget:Create(20,20,75,30,gui:GetBase()) widget:SetScript("Scripts/GUI/Button.lua") while window:KeyDown(Key.Escape)==false do --If window has been closed, end the program if window:Closed() then break end end
     
    The second example isn't really useful for games, but it will allow me to build a cross-platform UI for our own tools, and create an official GUI for in-game use, all in one step.
  3. Josh
    The beta branch on Steam has received an update with some important changes.
    A new project template called "Tutorial Samples" has been added, which includes the files you need to complete the new tutorials found here.
    A new script, Main.lua, has been introduced to take over the main entry point of your program. As explained in detail here, this will have no effect on your existing projects.
    The screenshot publish feature is fixed.
    Flowgraph arguments no longer require the EnableLegacyFeatures setting to be enabled.
    A sweet new welcome page has been designed.

     
    (Build 621802 was updated to 626936.)
  4. Josh
    A new build is available on the beta branch:
    Fixed animation bug found by tumira
    Multiple animations will now be a bit faster.
    Fixed probes not rendering bug found by reepblue

     
    If all is good this will go out on the stable branch this Sunday.
     
    The beta testers have done a great job. Thanks for your help!
  5. Josh
    A new beta is available with the following changes:
    Script prefixes are now changed to lowercase entity:Update(), entity:Start(), etc., as well as widget:Draw(), etc. This is because Entity() and Widget() are going to be functions to cast an object to that type. Sprites are now created on a sprite layer object. A sprite layer is created in a world and added to a camera. This allows control over what camera sees what set of sprites. See the examples for details. GUI system is partially working. Resizing the window won't reposition items correctly. Only four widget types are supported, panel, button, hyperlink, and label. Example in the FPSGame demo. The game menu system is packed into an entity script and works really nicely. Widget scripts are a little harder to develop now since they use a system of persistent objects, but performance is very much better than LE4. An interesting detail is that you get free interpolation of position and color at a rate of 60 hz. A lot of work was done to improve the Lua binding system. See details here. Error reporting and handling is much improved. No work was done on sound. No work has been done to the multicam demo, which some people had trouble with. Actors crashing / Lua stack error bug fixed. Changed .bat files to use release version of EXE instead of debug. New commands EmitEvent() and GetEvent(). If the returned event type is EVENT_NONE, there is no event. EVENT_QUIT can be emitted anywhere in the program to signal the main loop to exit. Typical usage is like this: while window:Closed() == false do while true do local event = GetEvent() if event.id == EVENT_QUIT then return end if event.id == EVENT_NONE then break end if event.id == EVENT_WINDOW_CLOSE and Window(event.source) == window then return end--you don't need this when Window:Closed() is being checked for already end world:Update() world:Render(framebuffer) end  
  6. Josh
    I've added display pages to the games database, so you can now fill in more information about your game, receive comments, post a video, and add additional images if you wish:
    http://www.leadwerks.com/werkspace/page/games/_/rogue-system-r17
     
    In the future I will add a file upload option so you can distribute your games here if you want to. Some games in the Downloads section have received a pretty high number of downloads, even though they were hidden away and weren't promoted at all:
    http://www.leadwerks.com/werkspace/files/category/19-games/
     
    I took the liberty of filling in some values for the different titles, but you can now modify your entry as you see fit. I know of 50 different games in development, so I hope to consolidate these and not have a separation between casual and more long-term titles, since I am a fan of both.
  7. Josh
    This is my opinion of Windows 7. When I tried Vista, I immediately disliked it, but used it for eight months. At the end of that period I still disliked it for all the same reasons.
     

     
    Source
  8. Josh
    An update is available for beta testers.
    What's new:
    GLTF animations now work! New example included. Any models from Sketchfab should work. Added Camera::SetGamma, GetGamma. Gamma is 1.0 by default, use 2.2 for dark scenes. Fixed bug that was creating extra bones. This is why the animation example was running slow in previous versions. Fixed bug where metalness was being read from wrong channel in metal-roughness map. Metal = R, roughness = G. Texture definitions in JSON materials are changed, but the old scheme is left in for compatibility. Textures are now an array:
    { "material": { "color": [ 1, 1, 1, 1 ], "emission": [ 0, 0, 0 ], "metallic": 0.75, "roughness": 0.5, "textures": [ { "slot": "BASE", "file": "./wall_01_D.tex" }, { "slot": "NORMAL", "file": "./wall_01_N.tex" } ] } } The slot value can be an integer from 0-31 or one of these strings:
    BASE NORMAL METALLIC_ROUGHNESS DISPLACEMENT EMISSION BRDF Bugs:
    FPS example menu freezes. Close window to exit instead. Looping animations are not randomized so the animation example will show characters that appear identical even though they are separate skeletons animating independently. Unskinned GLTF animation is not yet supported (requires bone attachments feature)
  9. Josh

    Articles
    I have not used the engine outside the editor in a while, but I needed to for performance testing, so now I am back to real-time rendering. During the development of the GI system I broke most of the light types, so I had to spend a couple of days getting those to work again. While doing this, I decided to resolve some longstanding issues I have put off.
    First, the PBR lighting will use a default gradient in place of the skybox, if no reflection map is set for the world. This is based off the ambient light level, so it will blend in with any scene. You can disable this by setting a black skybox, but this will give some acceptable default reflectance when an empty scene is created and it prevents unlit areas from looking completely flat:

    Shadow acne will be a thing of the past. I found that using vkCmdSetDepthBias to use the hardware depth bias feature does a great job of eliminating shadow acne. This shot shows a light that is extremely close to the floor, yet no artifacts are visible:

    Of course the new strip lights are can be used for dramatic effects:

    My new video project1.mp4 I have not yet implemented shadows for directional lights. I was hoping this whole time I would come up with a brilliant idea that would make cascaded shadow maps obsolete, but that's the one are I haven't found any great new innovative technique to use.
    Box lights are another new type of light, and can be used to simulate directional lights coming into a window, for levels that are mostly indoors.
    The realtime GI system has been very popular. I am rolling around an idea to increase the quality and performance of the system, with the flip side of that being increased latency. But looking around at the world, the general global illumination never really changes suddenly all at once, so I think it is worth trying. The whole point of Ultra Engine is that it should run very fast, so if I can make the GI system favor performance, hopefully to where it has no impact at all on framerate, I think that is more consistent with our goals.
  10. Josh
    Leadwerks Engine 4.5 will add ZIP files to the list of file formats you can import into the editor.  This isn't really anything special except that it works in a very specific way.  Source art files will be extracted first, followed by final game-ready formats (mdl and tex), followed by .meta files, which contain thumbnails and conversion settings for each file.  The resulting behavior is that you can import a zip file of game assets, with source art files, and the files will be copied in a way so that no reconversion of the files is triggered, because the time stamps are sequenced in the correct order.
    It's the little things. 
  11. Josh
    An update is available on the beta branch. This will improve rendering speed of uncollapsed brushes in-game. You may also see a speed increase in the editor when viewing maps with lots of CSG brushes. You can read about this in detail in this thread.
     
    Lunarovich's suggestion here has also been implemented.
     
    I also tweaked a few stock prefabs and the FPS example map. The crates and boxes will now all use the dynamic shadow setting, and the red cage light prefab is set to only cast static shadows now. This prevents a lot of excessive shadow rendering in the big elevator room, since each point light requires six passes. You can see in the screenshot below the monsters aren't casting shadows from the red light on the right, but they are casting a shadow from the big overhead spotlight. It looks good and the performance is a lot more consistent now.
     

     
    Don't forget we are scheduling a Google Hangout Saturday the 5th at 1:00 PM PST to review the release of Leadwerks Game Launcher.
  12. Josh
    Over the recent months the Leadwerks Workshop Store has experienced a noticeable increase in sales, correlating to an increased number of products offered. Although Workshop Store sales are quite a bit lower than DLC sales, the Workshop Store is more scaleable because it allows third parties to submit a greater variety of products.
     
    We're also able to send out payments to Russia and other regions that other stores and websites may have trouble sending payments to, because our transaction system is built on Steam.
     

     
    I am meeting with Valve in October to make my recommendations on how we can maximize sales through this system for third-party authors. In the meantime, you can submit your items to the Workshop now:
    http://www.leadwerks.com/werkspace/page/tutorials/_/workshop-r11
  13. Josh
    An update is available for beta testers.
    All Lua errors should now display the error message and open the script file and go to the correct line the error occurs on.
    The voxel raytracing system is now accessible. To enable it, just call Camera:SetGIMode(true).
    At this time, only a single voxel grid with dimensions of 32 meters, centered at the origin is in use. The voxel grid will only be generated once, at the time the SetGIMode() method is called. Only the models that have already been loaded will be included when the voxel grid is built. Building takes several seconds in debug mode but less than one second in release. Raytraced GI and reflections do not take into account material properties yet, so there is no need to adjust PBR material settings at this time. Skyboxes and voxels are not currently combined. Only one or the other is shown. Performance is much faster than Nvidia RTX but still has a lot of room for improvement. If it is too slow for you right now, use a smaller window resolution. It will get faster as I work on it more. The raytracing stuff makes such a huge difference that I wanted to get a first draft out to the testers as quickly as possible. I am very curious to see what you are able to do with it.
  14. Josh
    I found and fixed the cause of the cubemap seams in variance shadow maps so we now have nice soft seamless shadows.

    I also changed the engine so that point lights use six 2D textures instead of a separate cubemap texture array. This means that all light types are sharing one big 2D array texture, and it frees up one texture slot. I am not sure if I want to have a hard limit on number of shadow-casting lights in the scene, or if I want to implement a system that moves lights in and out of a fixed number of shadowmap slots.
  15. Josh
    You can now try out the new Workshop Browser by opting into the beta branch. This makes it simpler to install Workshop items, and allows you to browser, install, and uninstall items without having to switch to the Steam window.
     

  16. Josh
    The beta branch now contains an update that adds C++11 support for GCC on Linux. To use this you must enable C++11 support in the compiler settings in Code::Blocks. Select the Settings > Compiler and Debugger... menu item and then check the box indicated below.
     

     
    All new projects created from the Leadwerks templates will work correctly out-of-the-box.
     
    Your existing projects need a couple of new libraries added to them. The easiest way to do this is to open the CBP project file in a text editor. Find two chunks of text that look like this:

    <Linker> <Add library="$(LeadwerksPath)/Library/Linux/Debug/Leadwerks.a" /> <Add library="dl" /> <Add library="openal" /> <Add library="GL" /> <Add library="GLU" /> <Add library="$(LeadwerksPath)/Library/Linux/libluajit.a" /> <Add library="../../libsteam_api.so" /> <Add library="X11" /> <Add library="Xext" /> <Add library="pthread" /> </Linker>
     
    Add these two libraries to the list. Remember, this will occur twice in the file.

    <Add library="Xrender" /> <Add library="Xft" />
     
    Save the project file and you're ready to use C++11 features with Leadwerks on Linux.
  17. Josh
    We now accept popular cryptocurrencies in our store and Marketplace through Coinbase Commerce. That's right, you can now buy software like Ultra App Kit using Bitcoin, Ethereum, Litecoin, Dai, or Bitcoin Cash (if you can figure it out!). Right now it's a novelty, but it's worth trying. Maybe by 2022 it will be your only option?

    Sadly, Dogecoin is not one of the currently supported coins. Soon?
  18. Josh
    The beta branch contains a small update which affects the SoldierAI and Projectile scripts. The SoldierAI script now has a modifiable field that lets you choose a prefab for the projectile his weapon fires. The default value is "Prefabs\Projectiles\tracer.pfb" so your existing instances of these objects will be unaffected.
     
    By making the projectile prefab a modifiable value, we can use different types of projectiles with this script. For example, a medieval archer could fire arrows by creating a new prefab using a model of an arrow with the projectile script attached to it. Other types of weapons can be set up like energy weapons or rocket launchers. For example, you could create a "chicken gun" by selecting a prefab for the projectile that used a chicken model with the MonsterAI script attached to it.
  19. Josh
    It took a few hours to add scrolling to the textfield widget. Now when the caret moves beyond the bounds of the box, text will slide over to keep the caret visible. This really isn't much different from a full text editor. The script is available now on the beta branch on Steam and presently weights in at 381 lines of Lua code.
     


     
    The Draw function is pretty short and easy to understand. I think most people will customize the appearance of these widgets more than the behavior:

    function Script:Draw(x,y,width,height) local gui = self.widget:GetGUI() local pos = self.widget:GetPosition(true) local sz = self.widget:GetSize(true) local scale = gui:GetScale() local item = self.widget:GetSelectedItem() local text = self.widget:GetText() self:UpdateOffset() --Draw the widget background gui:SetColor(0.2,0.2,0.2) gui:DrawRect(pos.x,pos.y,sz.width,sz.height,0) --Draw the widget outline if self.hovered==true then gui:SetColor(51/255/4,151/255/4,1/4) else gui:SetColor(0,0,0) end gui:DrawRect(pos.x,pos.y,sz.width,sz.height,1) --Draw text selection background if self.sellen~=0 then local n local x = gui:GetScale()*self.textindent local px = x local fragment = self:GetSelectedText() local w = gui:GetTextWidth(fragment) local c1 = math.min(self.caretposition,self.caretposition+self.sellen) local c2 = math.max(self.caretposition,self.caretposition+self.sellen) local prefix = String:Left(text,c1) px = px + gui:GetTextWidth(prefix) gui:SetColor(0.4,0.4,0.4) gui:DrawRect(pos.x + px + self.offsetx, pos.y+2*scale,w,sz.height-4*scale,0) end --Draw text gui:SetColor(0.75,0.75,0.75) if text~="" then gui:DrawText(text,scale * self.textindent + pos.x+self.offsetx,pos.y,math.max(sz.width,sz.width-self.offsetx),sz.height,Text.Left+Text.VCenter) end --Draw the caret if self.cursorblinkmode then if self.focused then local x = self:GetCaretCoord() gui:DrawLine(pos.x + x + self.offsetx,pos.y+2*scale,pos.x + x + self.offsetx,pos.y + sz.height-4*scale) end end end
  20. Josh

    Articles
    My initial implementation of mesh voxelization for ray tracing used this code. It was good for testing, but has some problems:
    It's slow, using an unnecessary and expensive x * y * z loop No support for per-voxel color based on a texture lookup There are mathematical mistakes that cause inaccuracy, and the math has to be perfect My solution addresses these problems and only uses an x * y loop to generate the voxels. It does this by identifying the major (largest magnitude) axis of the triangle normal and using the other two axes for the X and Y axis, then finding the Z position of the triangle at each grid point along the surface.
    In previous screenshots, you could see some black faces that were caused by geometry that lies outside the bounds of the voxel geometry. Some of this was caused because I was voxelizing the mesh in local space and then transforming the resulting voxels to world space. That doesn't work, because the voxel position can end up rounding off to a different coordinate than the triangle it's supposed to enclosed. The best solution is to have a low-res LOD model that is used to generate the voxel data. (It's important to make sure the voxel geometry still contains the full-resolution model.)
    In the shot below you can see every single surface has a voxel to retrieve the color from. There are no texture lookups being performed in this shot, just colored voxels that were generated by reading the image pixel at each voxel position and then stored in a GPU buffer.

    This means we can safely calculate which lights are visible at each voxel and store those light IDs in a texture to be retrieved instead of performing a shadowmap lookup. It also means we can calculate global illumination at each voxel, store it in a texture, and just do a single texture lookup to grab the GI lighting when the actual model is rendered, instead of calculating GI each frame.
    Onwards and upwards!
  21. Josh
    An update is available that adds the new refraction effect. It's very easy to create a refractive transparent material:
    auto mtl = CreateMaterial(); mtl->SetTransparent(true); mtl->SetRefraction(0.02); The default FPS example shows some nice refraction, with two overlapping layers of glass, with lighting on all layers. It looks great with some of @TWahl's PBR materials.

    If you want to control the strength of the refraction effect on a per-pixel basis add an alpha channel to your normal map.
    I've configured the launch.json for Visual Studio Code so that the current selected file is passed to the program in the command line. By default, game executable will run the "Scripts/Main.lua" file. If however, the current selected Lua file in the VSCode IDE is a file located in "Scripts/Examples" the executable will launch that one instead. This design allows you to quickly run a different script without overwriting Main.lua, but won't accidentally run a different script if you are working on something else.

    The whole integration with Visual Studio Code has gotten really nice.

    A new option "frameBufferColorFormat" is added to the Config/settings.json file to control the default color format for texture buffers .I have it set to 37 (VK_FORMAT_R8G8B8A8_UNORM) but you can set it to 91 (VK_R16G16B16A16_UNORM) for high-def color, but you probably won't see anything without an additional tone mapping post-processing effect.
    Slow performance in the example game has been fixed. There are a few things going on here. Physics weren't actually the problem, it was the Lua debugger. The biggest problem was an empty Update() function that all the barrels had in their script. Now, this should not really be a problem, but I suspect the routine in vscode-debugger.lua that finds the matching chunk name is slow and can be optimized quite a lot. I did not want to make any additional changes to it right now, but in the future I think this can be further improved. But anyways, the FPS example will be nice and snappy now and runs normally.
    Application shut down will be much faster now, as I did some work to clean up the way the engine cleans itself up upon termination.
  22. Josh
    I like how a sequence of decisions can lead in one overriding direction. It's very fun.
    The FPS weapons and zombie packs were released because I felt there needed to be a little more built-in gameplay available to users.
     
    The Steam Community Choice sale resulted in a large number of new users, most of whom are completely new to game development.
     
    The Winter Games tournament resulted in ten new games that were fun and very creative.
     
    This finally gave me the ammo I needed to launch the standalone game player on Steam. All the videos and screenshots look great, so for Steam users it's a no-brainer to vote yes. This will be awesome because you'll be able to get thousands of players very easily who will give you feedback on your game and become your fan base, when you're ready to move on to Kickstarter or Greenlight.

     
    This came about because it was decided that "gameplay" was the most important factor we needed to focus on. And now we are seeing the result of that, and it is very good. I'm pretty darn proud of what you guys have made, and I am very happy with the direction we're going in.
  23. Josh
    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.
×
×
  • Create New...