Jump to content

Josh

Staff
  • Content Count

    15,992
  • Joined

  • Last visited

Everything posted by Josh

  1. An update is available for the Leadwerks 5 beta. Shadow updating is fixed so the lights no longer turn black during the update whenever a shadow changes. We're now using multiview to draw all six faces of a cube shadow map in one single pass! Point light shadow updates are something that used to be a considerable bottleneck in Leadwerks 4, and their performance impact is now very insignificant. Thanks to Sascha Williams for his excellent Vulkan examples. Joints are finished, a new upvector joint is added to lock the Y axis to a vector, all collision shape types are now supported, and body mass centers are fixed for rigid body physics will work correctly.
  2. I got single-pass cube shadowmap rendering working. Very fast!

  3. Josh

    Some Changes...

    It won't be called Turbo. Something else.
  4. Josh

    Some Changes...

    @Thirsty Panther Thank you for the comments. Regarding game content, what I have seen is that DLCs sell extremely well but it is very hard to get people to buy things through a new store. It even seems like people are more loyal to stores online than they are to the actual brick and mortar store they will shop at! So in the future I will probably focus on official DLC-type model packs and just try to improve the quality and amount of content offered of those, since they actually do sell well. I plan to release paid updates every 12-18 months. I don't plan on ever going back and building a new foundation for our technology, and from here on out I want continuous forward progression, not any rewrites. I definitely want to keep giving game developers what they want, because you guys give all the useful feedback. Without that, I can't build good software.
  5. Josh

    Some Changes...

    Leadwerks 3 / 4 was aimed at beginners who were completely new to game development. Since we were the first game engine on Steam, this made a lot of sense at the time, and the decision resulted in a successful outcome. However, in the next engine we are taking a different approach. (This is a direct result of Steam Direct.) Enterprise is a new market I am pursuing, and we have a lot of interest from aerospace and defense VR developers. The fact that I am American also helps here. There are special features these customers need that aren't necessarily needed by game developers, but I think you will like some of the possibilities this unlocks. For game developers, I have been moving back to an approach more like Leadwerks 2 where we focus on extreme high-end PC game technology, so that comes down to graphical quality and performance. I think most people here will be pretty happy with that direction. We're going to sell on Steam, Humble Store, Amazon, Microsoft store, Mac App Store, and direct from our website. Less importance will be attached to Steam, as they are just one more storefront we sell through. We're not going to use Steam Workshop. For pricing of the non-enterprise version, I am thinking $59.99 / $99.99 standard / pro with a monthly subscription option at $4.99 / $9.99. This is actually cheaper than the pricing of Leadwerks, but I think keeping things under $100 is better for the consumer market. The paid beta subscription is going to end before the end of the year, and it will be replaced with an open beta. The reason I did this was because I wanted a very small group of people testing the early betas (really more of an alpha), and I wanted to test out our subscriptions system. During that time we found and fixed a couple of small issues, so this was a good idea. A big thanks to all who participated and bought me many espressos. ☕ Finally, we are not going to call Leadwerks 5 "Turbo Game Engine". The name just isn't sticking for me, and I don't think we can get rid of the :"retro" connotations it has. My new technology has developed quite a lot since then, and speed is not the only advantage it brings to the table. I do have a new name in mind, but I am not ready to announce it yet. Until then, I will refer to the new engine as "Leadwerks 5 beta".
  6. Did you run the installer yourself?
  7. Happy Halloween!

    1. gamecreator

      gamecreator

      To you too Josh.

  8. No, but you could rescale the model, create the physics shape, save it, then reimport the model to restore the original scale.
  9. Josh

    Joint Class Finished

    I was thinking about having the Enable functions accept a Boolean because it makes for fewer commands and sometimes the programming is a little easier. Enable(false) would disable it. Enable(true) or Enable() would enable it. Any thoughts on this?
  10. Josh

    Joint Class Finished

    One small change is all the "motor" functions have been renamed to "actuator" which is a little more accurate.
  11. I'm happy to say the physics joint class in the new engine is completed. I made all the members that are not meant to be accessed private. One interesting part is the parent and child public members, which are constant pointers to private members. This should result in a read-only member in C++. A sol property is used to expose this to Lua in a read-only manner. The upvector joint will align an object's Y axis to any vector you set, but still allow rotation around the axis. This is perfect for making 2D games with physics. You can just set the axis to point along the Z world axis, and you will have 2D physics locked to the XY plane. class Joint : public SharedObject { std::list<shared_ptr<Joint> >::iterator bodylink[2]; Mat4 entitymatrix[2]; bool uselimits; Vec2 limits; Vec3 origin; PhysicsJoint* physicsjoint; bool motorenabled; bool limitsenabled; float angle; float motorspeed; float motorpower; float stiffness; float spring; Vec2 friction; Mat4 targetmatrix; shared_ptr<Entity> parent_; shared_ptr<Entity> child_; public: Joint(); virtual ~Joint(); const shared_ptr<Entity>& parent; const shared_ptr<Entity>& child; virtual void Break(); virtual void SetSpring(const float relaxation, const float spring, const float damper); virtual float GetSpring(); virtual void SetLimits(const float limits0, const float limits1); virtual Vec2 GetLimits(); virtual void SetStiffness(const float stiffness); virtual float GetStiffness(); virtual void SetMotorSpeed(const float speed); virtual void SetMotorPower(const float power); virtual float GetMotorPower(); virtual float GetMotorSpeed(); virtual void EnableLimits(); virtual void EnableMotor(const bool enabled); virtual void DisableLimits(); virtual void DisableMotor(); virtual bool LimitsEnabled(); virtual bool MotorEnabled(); virtual void SetFriction(const float angularfriction, const float linearfriction); virtual Vec2 GetFriction(); virtual void SetTargetPosition(const Vec3& pos, const float blend = 1.0f); virtual void SetTargetPosition(const float x, const float y, const float z, const float blend = 1.0f); virtual void SetTargetRotation(const Quat& rotation, const float blend = 1.0f); virtual void SetTargetRotation(const Vec3& rotation, const float blend = 1.0f); virtual void SetTargetRotation(const float pitch, const float yaw, const float roll, const float blend = 1.0f); virtual void SetTarget(const float target); virtual void SetTarget(const Mat4& target); friend shared_ptr<Joint> CreateUpVectorJoint(const Vec3&, shared_ptr<Entity>); friend shared_ptr<Joint> CreateKinematicJoint(const float, const float, const float, shared_ptr<Entity>); friend shared_ptr<Joint> CreateSliderJoint(const float, const float, const float, const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>); friend shared_ptr<Joint> CreateBallAndSocketJoint(const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>); friend shared_ptr<Joint> CreateHingeJoint(const float, const float, const float, const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>); }; extern shared_ptr<Joint> CreateUpVectorJoint(const Vec3& pin, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateUpVectorJoint(const float pinx, const float piny, const float pinz, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateKinematicJoint(const Vec3& pos, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateKinematicJoint(const float posx, const float posy, const float posz, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateSliderJoint(const Vec3& pos, const Vec3& pin, shared_ptr<Entity> parent, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateSliderJoint(const float x, const float y, const float z, const float px, const float py, const float pz, shared_ptr<Entity> child, shared_ptr<Entity> parent); extern shared_ptr<Joint> CreateBallAndSocketJoint(const Vec3& pos, shared_ptr<Entity> parent, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateBallAndSocketJoint(const float posx, const float posy, const float posz, shared_ptr<Entity> child, shared_ptr<Entity> parent); extern shared_ptr<Joint> CreateHingeJoint(const Vec3& pos, const Vec3& pin, shared_ptr<Entity> parent, shared_ptr<Entity> child); extern shared_ptr<Joint> CreateHingeJoint(const float x, const float y, const float z, const float pinx, const float piny, const float pinz, shared_ptr<Entity> child, shared_ptr<Entity> parent); And this is what the Lua binding code looks like: L->new_usertype<Joint> ( "Joint", sol::base_classes, sol::bases<SharedObject>(), sol::meta_function::index, &SharedObject::dynamic_get, sol::meta_function::new_index, &SharedObject::dynamic_set, "parent", sol::property([](Joint& j) { return j.parent; }), "child", sol::property([](Joint& j) { return j.child; }), "Break", &Joint::Break, "SetSpring", &Joint::SetSpring, "GetSpring", &Joint::GetSpring, "SetLimits", &Joint::SetLimits, "GetLimits", &Joint::GetLimits, "EnableLimits", &Joint::EnableLimits, "DisableLimits", &Joint::DisableLimits, "LimitsEnabled", &Joint::LimitsEnabled, "EnableMotor", &Joint::EnableMotor, "DisableMotor", &Joint::DisableMotor, "MotorEnabled", &Joint::MotorEnabled, "SetFriction", &Joint::SetFriction, "GetFriction", &Joint::GetFriction, "SetStiffness", &Joint::SetStiffness, "GetStiffness", &Joint::GetStiffness, "SetMotorSpeed", &Joint::SetMotorSpeed, "GetMotorSpeed", &Joint::GetMotorSpeed, "SetMotorPower", &Joint::SetMotorPower, "GetMotorPower", &Joint::GetMotorPower, "SetTargetRotation", sol::overload( sol::resolve<void(const Vec3&, const float)>(&Joint::SetTargetRotation), sol::resolve<void(const Quat&, const float)>(&Joint::SetTargetRotation), sol::resolve<void(const float, const float, const float, const float)>(&Joint::SetTargetRotation) ), "SetTargetPosition", sol::overload( sol::resolve<void(const Vec3&, const float)>(&Joint::SetTargetPosition), sol::resolve<void(const float, const float, const float, const float)>(&Joint::SetTargetPosition) ), "SetTarget", sol::overload( sol::resolve<void(const float)>(&Joint::SetTarget), sol::resolve<void(const Mat4&)>(&Joint::SetTarget) ) ); L->set_function("CreateHingeJoint", sol::overload( sol::resolve<shared_ptr<Joint>(const Vec3&, const Vec3&, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateHingeJoint), sol::resolve<shared_ptr<Joint>(const float, const float, const float, const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateHingeJoint) )); L->set_function("CreateSliderJoint", sol::overload( sol::resolve<shared_ptr<Joint>(const Vec3&, const Vec3&, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateSliderJoint), sol::resolve<shared_ptr<Joint>(const float, const float, const float, const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateSliderJoint) )); L->set_function("CreateBallAndSocketJoint", sol::overload( sol::resolve<shared_ptr<Joint>(const Vec3&, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateBallAndSocketJoint), sol::resolve<shared_ptr<Joint>(const float, const float, const float, shared_ptr<Entity>, shared_ptr<Entity>)>(&CreateBallAndSocketJoint) )); L->set_function("CreateKinematicJoint", sol::overload( sol::resolve<shared_ptr<Joint>(const Vec3&, shared_ptr<Entity>)>(&CreateKinematicJoint), sol::resolve<shared_ptr<Joint>(const float, const float, const float, shared_ptr<Entity>)>(&CreateKinematicJoint) )); L->set_function("CreateUpVectorJoint", sol::overload( sol::resolve<shared_ptr<Joint>(const Vec3&, shared_ptr<Entity>)>(&CreateUpVectorJoint), sol::resolve<shared_ptr<Joint>(const float, const float, const float, shared_ptr<Entity>)>(&CreateUpVectorJoint) )); A big thanks goes out to the developers of sol and Newton Dynamics for providing excellent technology for me to build on.
  12. For big numbers of entities, yes, but if it's just a list of 20 objects this would likely be slower. Anyways, we are all talking about optimizing something that does not need to be optimized, because it is not the cause of his problem.
  13. Running this code only 20 times should not make a big difference. You should eliminate other things like the bullet actually firing so you can see if that is actually the cause.
  14. There is nothing I see there that would cause any slowdown in C++ or even in Lua, with 20 enemies.
  15. Josh

    GLTF Loading Speed

    There's a discussion here about using GLTF as standalone material files: https://github.com/KhronosGroup/glTF/issues/1420 There is really no concept of these existing at all, so I am interested in pursuing this approach.
  16. Josh

    GLTF Loading Speed

    Another option is to compile the raycast code as a separate library in release mode and pull that into the project so that the fast code with no debugging is always being used.
  17. Josh

    GLTF Loader Update

    The following changes have been made to the GLTF model loader: Correctly loaded rotations and orientations. Mesh collision caching for faster loading. Supports transforms with negative scale and correct face orientation. Support for adjustable alpha cutoff value. Support for KHR_materials_unlit extension (full bright materials). This model from SketchFab was useful for testing because it uses so many features of the GLTF format: https://sketchfab.com/3d-models/ftm-0970f30574d047b1976ba0aa6f2ef855 This scene uses alpha masking, transparency, and the full-bright extension, since it already includes lightmaps. The cartoon outline you see on the edges is actually mesh-based. Update is available now for beta subscribers. At this point, if you find a GLTF file that does not load correctly, or if there is an extension you would like to see support added for, I would like to hear it. I'm also proposing standalone GLTF material files here: https://github.com/KhronosGroup/glTF/issues/1420
  18. GLTF loader is finished except for animation.

  19. Josh

    GLTF Loading Speed

    And another option is to modify the Blender GLTF exporter to add the raycast data into exported files. Not really a fan of making this a requirement though. https://github.com/KhronosGroup/glTF-Blender-IO
  20. Josh

    GLTF Loading Speed

    Another possibility would be to add new GLTF extensions that embed the raycast structure in the file, but that adds an extra step in the workflow of resaving the GLTF.
  21. Josh

    GLTF Loading Speed

    There are two aspects of GLTF files that have non-optimal loading speed. First, the vertex data is not stored in the same exact layout and format as our vertex structure. I found the difference in performance for this was pretty small, even for large models, so I was willing to let it go. Tangents can take a bit longer to build, but those are usually included in the model if they are needed. The second issue is the triangle tree structure which is used for raycasting (the pick commands). I found the difference in debug mode was really significant when using a large (two million poly) mesh. Here are the numbers. The big concern is building the pick tree in debug mode, which takes two minutes using this model. GLTF Loading Speed (milliseconds) Release Mode Vertices only: 1249 Vertices + build tangents: 1276 Vertices + build collision: 5563 Debug Mode Vertices only: 3758 Vertices + build tangents: 12453 Vertices + build collision: 120,000 I was able to improve this speed significantly by saving vertex and pick tree data to a cache file after processing. Release Mode Cached data: 1233 Debug Mode Cached data: 2707 This is sort of a halfway step between using GLTF natively and converting to our faster-loading GMF2 file format. I like the idea of keeping all files in easily-accessible formats like DDS and GLTF, but there are some big questions. Where and how should the mesh cache files be stored? A published game will not necessarily have write access for files in its own install folder, so any files written should be in the user Documents or AppData folders. How should the GLTF file be identified? By checksum? By full file path? The full file path will change when the game is installed on another computer. Should the mesh cache files be shipped with the game, or generated the first time it is run? Do we even need to worry about caching when release mode is used? It seems like only debug mode has a significant performance problem, so maybe this should be something that only gets used during development?j I need to think about this.
  22. I put some hours into the GLTF loader and I now have models loading reliably. Very nice to use with models from Sketchfab!

  23. If you have a wall / floor / ceiling combo available I could start playing with it. I need to start making some nicer screenshots.
×
×
  • Create New...