Jump to content

Blogs

Map Loading, Materials, Shaders, and other Details

I have map loading working now. The LoadMap() function has three overloads you can use:: shared_ptr<Map> LoadMap(shared_ptr<World> world, const std::string filename); shared_ptr<Map> LoadMap(shared_ptr<World> world, const std::wstring filename); shared_ptr<Map> LoadMap(shared_ptr<World> world, shared_ptr<Stream> stream); Instead of returning a boolean to indicate success or failure, the LoadMap() function returns a Map object. The Map object gives you a handle to hang onto all the loaded entities so they don't get instantly deleted. When you want to clear the map, you can just set this variable to nullptr/NULL: auto map = LoadMap(world,"Maps/start.map"); map = nullptr; //BOOM!!! The "entities" member of the map object gives you a list of all entities loaded in the map: auto map = LoadMap(world,"Maps/start.map"); for (auto entity : map->entities) { //do something to entity } If you want to clear a map but retain one of the loaded entities, you just set it to a new variable like this. Notice we grab the camera, clear the map, but we still can use the camera: auto map = LoadMap(world,"Maps/start.map"); shared_ptr<Camera> cam; for (auto entity : map->entities) { cam = dynamic_pointer_cast<Camera>(entity); if (cam) break; } map = nullptr; //BOOM!!! cam->SetPosition(1,2,3); //everything is fine Materials and shader assignment has gotten simpler. If no material is assigned, a blank one will be auto-generated in the rendering thread. If a material has no shader assigned, the rendering thread will choose one automatically based on what textures are present. For example, if texture slots one and two are filled then the rendering thread will choose a shader with diffuse and normal maps. In most cases, you don't even need to bother assigning a shader to materials. I might even add separate animation and static shader slots, in which case materials could work for animated or non-animated models, and you wouldn't normally even need to specify the shader. Shaders now support include directives. By using a pragma statement we can indicate to the engine which file to load in, and the syntax won't trigger an error in Visual Studio Code's syntax highlighter: #pragma include Lighting.glsl Shader includes allow us to create many different shaders, while only storing the complicated lighting code in one file that all other shaders include. The #line directive is automatically inserted into the shader source at every line, so that the engine can correctly detect which file and line number any errors originated from. With this all working, I can now load maps side by side in Leadwerks 4 and in the new renderer and get actual performance benchmarks. Here's the first one, showing the example map "02-FPS Controller.map" from the First-Person Shooter game template. In Leadwerks 4, with Intel HD 4000 graphics, we get 71 FPS. (Yes, vertical sync is disabled). And with the new forward renderer we get a massive 400%+ increase in performance: I expect the results will vary a little bit across different hardware, but we can see already that on the low-end hardware the new renderer is a massive improvement. I plan to get a new build of the beta up soon so that you can try your own maps out and test the difference. Physics and scripts are presently disabled, as these systems need additional work to be usable. Oh, and look how much cleaner those shadow edges are!

Josh

Josh

Fun driving in Leadwerks 4.5

Little demo I made about driving in Leadwerks 4.5 with "self-made" vehicle (well the model is not from me) How to make ? -> https://www.leadwerks.com/community/blogs/entry/2216-simple-car-improved/  enjoy!    

Marcousik

Marcousik

Simple Car Improved

Now, I wrote a single script that creates suspension, steer and traction You have to create the chassis, 4 wheels, set this script to each one of the wheels and then paly with the configurable parameters. Enjoy: --[[ Autor Juan Ignacio Odriozola (charrua) Purpose: A script that facilitates the making of a simple car all you need is a chassis and 4 wheels assing this scrip to each wheel and set the object chassis then adjust some of the configurable parameters Parent: chassis entity : wheel 3 joints and 2 auxiliary entities are created the chain is: Parent Slider Pivot Hinge Pivot Hinge chassis -suspensionJoint- suspensionPivot -steerJoint- steerPivot -wheelJoint- wheel suspension uses pin 010 (Y axis) steer uses pin 010 (Y axis) wheel pin (must be set depends of wheel orientation) up/down keys are defaults for forward and backward left/right keys are defaults for steer left/right space key is default for brakes steer velocity and start/end angle must be set suspension lenght must be set wheel friction must be set steerAngle set both limits to +/- steerAngle/2 if no key (left/right) is pressed then, target angle is 0 : straight suspensionLenght set both limits to +/- suspensionLength/2 and target distance is set to 0 suspension strength defaults to 1000 which is too much strenght for a light weight car (20 of mass) and not to much for a 200 car of mass each joint is created with a mass of 1, which should be taking into accoung (so for a 4 wheels car, you have a mass of 8 on the 8 joints). there are so many other parameters that may be adjusted: Spring, Strength, Stiffness ... not too much documented :) ]]-- Script.currspeed = 0 Script.chassis = nil--Entity "chassis" Script.pin = Vec3(0,0,1) --Vec3 "wheel Pin" Script.motorspeed=500--float "max motor speed" Script.velcontrolled=false--bool "velControl" Script.suspensionLength=0.2--float "suspension" Script.steerAngle=90--float "steer angle" Script.steerSpeed=100--float "steer velocity" Script.friction=1--float "wheel friction" Script.steerPivot=nil Script.suspensionPivot=nil Script.steerJoint=nil Script.suspensionJoint=nil Script.wheelJoint=nil function Script:Start() local pos = self.entity:GetPosition(false) --true for global if self.chassis ~= nil then self.suspensionPivot = Pivot:Create() self.suspensionPivot:SetPosition(pos) self.suspensionPivot:SetMass(1) self.suspensionPivot:SetCollisionType(Collision.None) self.steerPivot = Pivot:Create() self.steerPivot:SetPosition(pos) self.steerPivot:SetMass(1) self.steerPivot:SetCollisionType(Collision.None) --joints creation self.suspensionJoint = Joint:Slider(pos.x, pos.y, pos.z, 0, 1, 0, self.chassis, self.suspensionPivot) self.steerJoint = Joint:Hinge(pos.x, pos.y, pos.z, 0, -1, 0, self.suspensionPivot, self.steerPivot) self.wheelJoint = Joint:Hinge(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.steerPivot, self.entity) --suspension self.suspensionJoint:EnableLimits() self.suspensionJoint:SetLimits(-self.suspensionLength/2,self.suspensionLength/2) --steerAngle=0 means no steer self.suspensionJoint:SetTargetAngle(0) --at the middle self.suspensionJoint:SetMotorSpeed(1) -- 1 m/s self.suspensionJoint:SetStrength(100) --defatul is 1000 self.suspensionJoint:EnableMotor() --steer self.steerJoint:EnableLimits() self.steerJoint:SetLimits(-self.steerAngle/2,self.steerAngle/2) --steerAngle=0 means no steer self.steerJoint:SetMotorSpeed(self.steerSpeed) self.steerJoint:EnableMotor() --wheel self.entity:SetFriction(self.friction, self.friction) else Debug:Error("no chassis assigned") end end function Script:setMotorSpeed(speed) if self.velcontrolled then --System:Print("setMotorSpeed: "..speed) self.currspeed = speed if speed~=0 then self.wheelJoint:EnableMotor() end self.wheelJoint:SetMotorSpeed(self.currspeed) end end function Script:UpdateWorld() if self.motorspeed>0 then self.wheelJoint:SetAngle(self.wheelJoint:GetAngle()+100) else self.wheelJoint:SetAngle(self.wheelJoint:GetAngle()-100) end if App.window:KeyDown(Key.Space) then self:setMotorSpeed(0) end if self.velcontrolled then if App.window:KeyDown(Key.Up) then self.currspeed = self.currspeed + 10 if self.currspeed>self.motorspeed then self.currspeed=self.motorspeed end if self.currspeed == 10 then self.wheelJoint:EnableMotor() end self.wheelJoint:SetMotorSpeed(self.currspeed) end if App.window:KeyDown(Key.Down) then self.currspeed = self.currspeed - 10 if self.currspeed<-self.motorspeed then self.currspeed=-self.motorspeed end self.wheelJoint:SetMotorSpeed(self.currspeed) end end if self.steerAngle>0 then local direction=0 if App.window:KeyDown(Key.Left) then direction=-self.steerAngle/2 end if App.window:KeyDown(Key.Right) then direction=self.steerAngle/2 end self.steerJoint:SetAngle(direction) else self.steerJoint:SetAngle(0) end end   In the other maps i was using a box as a floor to which I set the desired friction, testing this new script i use a terrain and have to figure it out how to set the friction to the terrain... Did some searches and ended with: local n for n=0,self.world:CountEntities()-1 do local entity = self.world:GetEntity(n) if entity:GetClassName()=="Terrain" then terrain = entity System:Print("terrain found!") terrain:SetFriction(10,10) break end end insert this in the app.lua (after load map) and then you can play with terrain friction, the video shows how the car behaves with the defaul terrain friction and then whit a friction of 10,10 Always learning something new    A word about some parameters: If you are using a hinge, when you specity speed (SetMotorSpeed) the number means degrees per second. So if you use 3600 as max speed you get 10 revoluions per second. If your tire has, 64cm then d*pi aprox 2 meters per revolution, 10 revolutions per secon aprox 20 meters per second... and if you are lucky 72Km/h If you are using a slider, then speed is un meters per second.  Other parameter which is very important is the hinge/slider "pin" which is a vector that tells the direction of movement of the slider or over which plane de hinges open/close For a common door, we need to use the Y axis, so the pin is 0,1,0 I use this pin for the suspension and for the steer but for this script, you must tell the traction pin, which sould be 1,0,0 or 0,0,1 depending on the orientation of your tires If your tires are not facing X nor Z axis, then you have to do some math to get the proper x,z component of the pin In the script I use a Strenght of 100, instead of the 1000 which is default, my car is light weight : 5 + 4*3 = 17 of Mass chassis has 5, each wheel has 1 and the 2 auxiliary pivots has 1 each one whith a friction of 10 on each tire and with a friction of 10 on the terrain looks ok for me (better than I spected at first).  Juan

Charrua

Charrua

On how to loose half day

I had a window popping up every time i was closing the game.Error below: Debug Assertion Failed! Expression: __acrt_first_block == header At first i thought is something related to me not deleting all pointers or closing the app the wrong way.So i fix that up same error.
More investigating i figure it up that somehow is related to poco libs that i use to connect over tcp.If game exit code was before calling poco there was no exception. More wtf and curses for not being able to work on game and debug this. Finally solution was to rebuild poco with /MTd option, default built was with /MD and was causing incompatibilities seems. Glad i got over this , back to entry development

aiaf

aiaf

Joints

Recently i posted a simple car made with joints without too much explanations... so What is a joint? This video shows joints in action. At the end, the stand alone executable and the complete project.   The following text and figure is from the "ode-latest-userguide", figures are also form the JV-ODE documentation: In real life a joint is something like a hinge, that is used to connect two objects. It is a relationship that is enforced between two bodies so that they can only have certain positions and orientations relative to each other. This relationship is called a constraint,  the words joint and constraint are often used interchangeably. The figure shows three different constraint types. The first is a ball and socket joint that constraints the “ball” of one body to be in the same location as the “socket” of another body.  The second is a hinge joint that constraints the two parts of the hinge to be in the same location and to line up along the hinge axle.  The third is a slider joint that constraints the “piston” and “socket” to line up, and additionally constraints the two bodies to have the same orientation. Each time the integrator takes a step all the joints are allowed to apply constraint forces to the bodies they affect. These forces are calculated such that the bodies move in such a way to preserve all the joint relationships. Each joint has a number of parameters controlling its geometry. An example is the position of the balland- socket point for a ball-and-socket joint. The functions to set joint parameters all take global coordinates, not body-relative coordinates. A consequence of this is that the rigid bodies that a joint connects must be positioned correctly before the joint is attached. Figure: types of joints   The "Integrator step" is the part of the physics engine that does all the calculations.
Based on the current state, force applied, constrain parameters, collisions etc... recalculates the next position and rotation of every affected physical obejct.
Leadwerks then, does the render of the objects acordingly to it's new positions, or that is what is supposed to do... (Josh should correct me if I'm wrong). A joint normally is placed between two objects, one is called Parent and the other Child. The child should be NULL, and in this case
the joint is between one body and the world or scene. In the case of a door, you need a Door and a Frame, the Frame should be the Parent body, the Door the child body.
In real life you have to decide where the Hinge (or more than one) will be placed and use some screws to attach both parts of the hinge to the frame and the door. In software, things are practically the same In other words, we have to have 3 things clear:
    Who is the parent and where it should be positioned and oriented.
    Who is the child and where it should be poitioned and oriented.
    Which type of joint you need, where it should be positioned and oriented. Normally we create and place the two bodies first and then, at joint creation we say where the joint will be and how it should be oriented, who the parent is and who child is, if any. After that, joints normally has some other properties that should be adjusted, used, controlled, limited, enabled... etc, depending on the joint type. Joints have two "limits": If the joint is a Hinge, the limits are the Start Angle and End Angle "the door should turn".
If the joint is a Slider, the limits are the Start Position and End Position the piston should extend.
If the joint is a Ball, the limits are the cone angle and twist or torsion... keep reading Joints (hinge and slider) should have a "motor" if not, as a normal door, we need external forces to "open the door", if we place a door on a frame attached with hinges and the door has no lock at all, then
the wind should open/close it, or some body that collides with the door should move it. As we use a hinge, the door do not fall, do not take an upward motion, the motion is well known and 
constrainded tho the clasic movement we all know.
But if, for instance we have a "motorized door" then the open/close operation is started in some way (press of a button?) and a motor does the job. Normally it stops automatically, because there are end-run switches or the like installed and working for us.
A sofware motorized joint is exactly that, we set where we want the joint go (setTargetAngle), and start a motor (enableMotor). Ball Joint A ball is used when we need a "cone" movement freedom, think that you have a rope attached at the roof of your room and you hang a box on it.
If the rope is made of a rigid material, the box should made a pendulum movement not so large and probably the box orientations should not change too much.
How much we let the rope to move is dictated by the first limit and how much the object attached should change orientation (twist/torsion) is dictated by the second limit. A rope is a nice looking example, all you have to do is place N cubes (shape is not important) and place ball joints in the middle of each pair.
You may have the first box joined to the world (attached to a fixed 3d position) and then a link of bodies and ball joints:
    Joint N has body N as parent and body N+1 as child Leadwerks came with a simple ball.lua script: function Script:Start()     local pos = self.entity:GetPosition(true)     self.joint = Joint:Ball(pos.x, pos.y, pos.z, self.entity, self.entity:GetParent())     self.joint:SetFriction(10)     self.entity:SetDamping(0,0) end If you have a chain of parented objetcts, then you  may set this script and you have a rope build with a few clicks of your mouse on the editor.
Procedure:
    Create some boxes, set prop collision and a mass not zero (1 perhaps), place then in a vertical row somewhat separated.
    In the editor drag the second box to the first, the third to the second building a hierachy (parent/child relationship)
    Select all (one by one with ctrl click on each box) and then apply the ball script. Voila! You have a rope with no limits: cone angle is the maximum the engine lets you to be and the same for torsion.
    Collide the rope with some object or, place the boxes horizontally (instead of vetically) and let gravity do it's job.
    
I made another ball script: ballEnhaced: Script.parent = nil--Entity "Parent" Script.child = nil--Entity "Child" Script.useLimits=false--bool "Use limits" Script.coneAngle = 45--Float "Cone Angle" Script.torsion = 45--Float "Torsion" Script.hide = true--bool "Hide entity" function Script:Start()     local pos = self.entity:GetPosition(true)     if self.parent~=nil then         self.joint = Joint:Ball(pos.x, pos.y, pos.z, self.parent, self.child)         self.joint:SetLimits(self.coneAngle, self.torsion)         if self.useLimits then             self.joint:EnableLimits()             System:Print("limits:"..self.coneAngle..", "..self.torsion)         end         if self.hide then             self.entity:Hide()         end     end end if using this script, you have to create a pivot or box (collision type: none, and no mass) and tell the script ho the parent is and ho the child is, if no child, then the parent body
will be attached to the environement, fixed at this 3d point. In the map included in this blog there are two ropes, one made with the leadwerks ball.lua and one with the ballEnhaced.lua script, in this script you may tell how to constrain 
the ball cone anlgle and trosion. Look the video, and you will see the difference on how the cubes behave when hitted by the car. A rope suspension bridge should be made with both ends attached to the world and a double chain of joints... doing two unions between each part of the brige.
It's nice so see the car passing over it! The attached video shows at first the car passing over the bridge... the mass of the car is very little, if not, the joints get broken.. as always there are some other things to consider. Hinje Joint
As I used a hinge for some explanation, i guess there is not to much to say here, I use some hinges for doors in the map attached and also used them for the steer and wheels of the car.
One door have a motor and the other not, so the second one moves as the car collides it.  I wrote two scripts: hingeEnhaced.lua Script.parent = nil --entity "parent" Script.child = nil --entity "hild" Script.hide = true--bool "Hide entity" Script.pin = Vec3(0,0,1) --Vec3 "Hinge Pin" Script.limitsenabled=false--bool "Enable limits" Script.limits = Vec2(-45,45) --Vec2 "Limits" Script.friction = 0--float "Friction" function Script:Start()     local pos = self.entity:GetPosition(true)     if self.parent~=nil then         self.joint = Joint:Hinge(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.parent, self.child)         if self.limitsenabled then self.joint:EnableLimits() end         self.joint:SetLimits(self.limits.x,self.limits.y)         self.joint:SetFriction(self.friction)         self.entity:SetDamping(0,0)         if self.hide then             self.entity:Hide()         end     end end As in the case of a ball joint, with this script you may set parent, child and limits hingeMotorized.lua Script.parent = nil --entity "parent" Script.child = nil --entity "hild" Script.hide = true--bool "Hide entity" Script.pin = Vec3(0,0,1) --Vec3 "Hinge Pin" Script.limitsenabled=false--bool "Enable limits" Script.limits = Vec2(-45,45) --Vec2 "Limits" Script.tOpenClose = 15 --Int "Open/Close time" Script.movespeed = 60 --Int "Speed" Script.startTime = 0 Script.action = 1    --1 open, 0 close function Script:Start()     local pos = self.entity:GetPosition(true)     if self.parent~=nil then         self.joint = Joint:Hinge(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.parent, self.child)         if self.limitsenabled then self.joint:EnableLimits() end         self.joint:SetLimits(self.limits.x,self.limits.y)         self.joint:SetTargetAngle(self.limits.x)         self.joint:EnableMotor()         self.startTime = Time:GetCurrent()         self.joint:SetMotorSpeed(self.movespeed)         if self.hide then             self.entity:Hide()         end     end end function Script:UpdatePhysics()     local time_ = Time:GetCurrent()     if time_ - self.startTime > self.tOpenClose*1000 then                  self.action = 1-self.action    --toggle action         if self.action == 1 then             self.joint:SetTargetAngle(self.limits.x)         else             self.joint:SetTargetAngle(self.limits.y)         end         self.startTime = Time:GetCurrent()     end end This scripts creates the joint, then set a target angle, enables the motor and apply a velocity, so the "door" starts going to the first limit.
After the tOpenClose time, the variable action is toggled and based on it the TargetAngle will be first limit or second limit, in this way, the door continously open and then close
after tOpenClose time
Slider Joint
For a slider joint, in this map i wrote one script: sliderMotorized.lua Script.child = nil --entity "hild" Script.hide = true--bool "Hide entity" Script.pin = Vec3(0,0,1) --Vec3 "Hinge Pin" ScrScript.parent = nil --entity "parent" ipt.limitsenabled=false--bool "Enable limits" Script.limits = Vec2(-45,45) --Vec2 "Limits" Script.tOpenClose = 15 --Int "Open/Close time" Script.movespeed = 60 --Int "Speed" Script.startTime = 0 Script.action = 1    --1 open, 0 close function Script:Start()     local pos = self.entity:GetPosition(true)     if self.parent~=nil then         self.joint = Joint:Slider(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.parent, self.child)         if self.limitsenabled then self.joint:EnableLimits() end         self.joint:SetLimits(self.limits.x,self.limits.y)         self.joint:SetTargetAngle(self.limits.x)         self.joint:EnableMotor()         self.startTime = Time:GetCurrent()         self.joint:SetMotorSpeed(self.movespeed)         if self.hide then             self.entity:Hide()         end     end end function Script:UpdatePhysics()     local time_ = Time:GetCurrent()     if time_ - self.startTime > self.tOpenClose*1000 then                  self.action = 1-self.action    --toggle action         if self.action == 1 then             self.joint:SetTargetAngle(self.limits.x)         else             self.joint:SetTargetAngle(self.limits.y)         end         self.startTime = Time:GetCurrent()     end end This script is 99% the same as the hingeMotorized.lua, the only difference is that a slider joint is created instead of a hinge joint.
Note that the limis are not angles, they are offsets from the initial position of the plataform. Stand alone executable: jointsworldDistro.zip Project: jointsworldProject.zip Enjoy Juan

Charrua

Charrua

This is what YOUR feedback reveals!

Hi guys! Just wanted to share the first video of the DevTalk series with you, where I keep you up to date about the development, upcoming features etc. It also is a very cool way to communicate with you, so make sure to subscribe and comment to tell me your ideas. I am working very, very hard and there is a lot of awesome stuff coming soon, so stay tuned! Markus from Phodex Games! Give Feeback for Bladequest!
My Youtube Channel!
Your Games Wishlist so I can craft a game to your needs!

Simple Car

Here there is a way of making a simple car based on hinges This is not a tutorial, is just simply a stating point for the ones that want/like to play arround physics and hinges... I included the entire project and the distribution executable to test the scripts so, you have as I say a starting point and just that, hpe it helps someone This is the editor view and the initial placement of the parts needed Basically I made 3 scripts physicsProperties.lua wheel.lua steer.lua First you have to create and place the car body or chassis, 4 wheels and 6 auxiliary pivots/ or any brush you like (a cube is fine) for the hinges 4 of the auxiliary entities are for the wheels hinges and 2 for the wheels steer. Place the wheel hinge and steer centered with the wheel. After that you may set some script parameters: Wheel scritp: Basically, the position of the entity script holder is used to create a hinge between the "parent" and the "child" you choose (in the picture above: between the auxiliary entity SteerFL and the WheelFL) If vel control is checked then, a motor is enabled for that hinge and keys Up/Down are used to increase/decrease speed If vel control is not cheched, no motor is enabled and the wheel is free to run Be carefull whit the Hinge Pin, which dictates the axis over which the wheel will rotate, in this case I used X axis, but if you use other pieces direction/alignement you should adjust this values.   Steer script: The steer hinge is used to turn the wheel to handle car heading, so the pin is the Y axis Limits and Motor are needed to control the steer Limits is for how much the steer will turn right/left using the default keys left/right arrow When you press left or ritght key, the right limit will be set as the hinge angle and the hinge will try to reach this angle at the "steer speed", the same, but whit the left limit happen if you press the left key.   physicsProperties just let you adjust the friction of the wheels and or the floor Script.sfrict=0--float "static friction" Script.kfrict=0--float "kinetic friction" function Script:Start() System:Print("phy properties start") self.entity:SetFriction(self.sfrict, self.kfrict) end so simple, and in the editor it looks: Here is a hand drawing of how scripts, objects, parent/child are connected       Here is the wheel script Script.currspeed = 0 Script.parent = nil--Entity "Parent" Script.child = nil--Entity "Child" Script.pin = Vec3(0,0,1) --Vec3 "Hinge Pin" Script.motorspeed=500--float "Motor speed" Script.velcontrolled=false--bool "velControl" function Script:Start() System:Print("wheel start") self.entity:Hide() local pos = self.entity:GetPosition(false) --true for global if self.child ~= nil then if self.parent ~= nil then self.joint = Joint:Hinge(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.child, self.parent) else Debug:Error("no parent assigned") end else Debug:Error("no child assigned") end end function Script:setMotorSpeed(speed) if self.velcontrolled then System:Print("setMotorSpeed: "..speed) self.currspeed = speed if speed~=0 then self.joint:EnableMotor() end self.joint:SetMotorSpeed(self.currspeed) end end function Script:UpdateWorld() if self.motorspeed>0 then self.joint:SetAngle(self.joint:GetAngle()+100) else self.joint:SetAngle(self.joint:GetAngle()-100) end if App.window:KeyDown(Key.Space) then self:setMotorSpeed(0) end if self.velcontrolled then if App.window:KeyDown(Key.Up) then self.currspeed = self.currspeed + 10 if self.currspeed>self.motorspeed then self.currspeed=self.motorspeed end if self.currspeed == 10 then self.joint:EnableMotor() end self.joint:SetMotorSpeed(self.currspeed) end if App.window:KeyDown(Key.Down) then self.currspeed = self.currspeed - 10 if self.currspeed<-self.motorspeed then self.currspeed=-self.motorspeed end self.joint:SetMotorSpeed(self.currspeed) end end end Here is the steer scritp Script.parent = nil--Entity "Parent" Script.child = nil--Entity "Child" Script.pin = Vec3(0,1,0) --Vec3 "Hinge Pin" Script.useLimits=false--bool "use limits" Script.limits = Vec2(-45,45) --Vec2 "Limits" Script.useMotor=flase--bool "use motor" Script.motorspeed=50--float "Steer speed" function Script:Start() System:Print("steer start") if self.child == nil then Debug:Error("No child assigned.") end if self.parent == nil then Debug:Error("No parent assigned.") end self.entity:Hide() local pos = self.entity:GetPosition() self.joint = Joint:Hinge(pos.x, pos.y, pos.z, self.pin.x, self.pin.y, self.pin.z, self.child, self.parent) if self.useLimits then self.joint:EnableLimits() self.joint:SetLimits(self.limits.x,self.limits.y) end if self.useMotor then self.joint:SetMotorSpeed(self.motorspeed) self.joint:EnableMotor() end end function Script:UpdateWorld() local direction=0 if App.window:KeyDown(Key.Left) then direction=self.limits.x end if App.window:KeyDown(Key.Right) then direction=self.limits.y end self.joint:SetAngle(direction) end   here the distro: simpleCarDistro.zip here the project: simpleCar.zip and here a video...   enjoy   Juan

Charrua

Charrua

Clustered Forward Rendering - Fun with Light Types

By modifying the spotlight cone attenuation equation I created an area light, with shadow. And here is a working box light The difference here is the box light uses orthographic projection and doesn't have any fading on the edges, since these are only meant to shine into windows. If I scale the box light up and place it up in the sky, it kind of looks like a directional light. And it kind of is, expect a directional light would either use 3-4 different box lights set at radiating distances from the camera position (cascaded shadow maps) or maybe something different. We have a system now that can handle a large number of different lights so I can really arrange a bunch of box lights in any way I want to cover the ground and give good usage of the available texels. Here I have created three box lights which are lighting the entire courtyard with good resolution. My idea is to create something like the image on the right. It may not look more efficient, but in reality the majority of pixels in cascaded shadow maps are wasted space because the FOV is typically between 70-90 degrees and the stages have to be square. This would also allow the directional light to act more like a point or spot light. Only areas of the scene that move have to be updated instead of drawing the whole scene three extra times every frame. This would also allow the engine to skip areas that don't have any shadow casters in them, like a big empty terrain (when terrain shadows are disabled at least). Spot, and area lights are just the same basic formula of a 2D shadowmap rendered from a point in space with some direction. I am trying to make a generic texture coordinate calculation by multiplying the global pixel position by the shadow map projection matrix times the inverse light matrix, but so far everything I have tried is failing. If I can get that working, then the light calculation in the shader will only have two possible light types, one for pointlights which use a cube shadowmap lookup, and another branch for lights that use a 2D shadowmap.

Josh

Josh

How to Request a Payout from Leadwerks Marketplace

Some of you are earning money selling your game assets in Leadwerks Marketplace. This quick article will show you how to request a payout from the store for money you have earned. First, you need to be signed into your Leadwerks account. Click the drop-down user menu in the upper right corner of the website header and click on the link that says "Account Balance". On the next page you can see your account balance. As long as it is $20 or more you can withdraw the balance into your PayPal account by hitting the "Withdraw Funds" button. Now just enter your PayPal email address and press the "Withdraw" button. After that the withdrawal will be deducted from your balance and the withdrawal request will show in your account history. Shortly after that you will receive the funds in your PayPal account. You can sell your game assets in Leadwerks Marketplace and earn a 70% commission on each transaction.

Josh

Josh

Clustered Forward Rendering - Multiple Light Types

I added spotlights to the forward clustered renderer. It's nothing too special, but it does demonstrate multiple light types working within a single pass. I've got all the cluster data and the light index list packed into one texture buffer now. GPU data needs to be aligned to 16 bytes because everything is built around vec4 data. Consequently, some of the code that handles this stuff is really complicated. Here's a sample of some of the code that packs all this data into an array. for (auto it = occupiedcells.begin(); it != occupiedcells.end(); it++) { pos = it->first; visibilityset->lightgrid[pos.z + pos.y * visibilityset->lightgridsize.x + pos.x * visibilityset->lightgridsize.y * visibilityset->lightgridsize.x] = visibilityset->lightgrid.size() / 4 + 1; Assert((visibilityset->lightgrid.size() % 4) == 0); for (int n = 0; n < 4; ++n) { visibilityset->lightgrid.push_back(it->second.lights[n].size()); } for (int n = 0; n < 4; ++n) { if (!it->second.lights[n].empty()) { visibilityset->lightgrid.insert(visibilityset->lightgrid.end(), it->second.lights[n].begin(), it->second.lights[n].end()); //Add padding to make data aligned to 16 bytes int remainder = 4 - (it->second.lights[n].size() % 4); for (int i = 0; i < remainder; ++i) { visibilityset->lightgrid.push_back(0); } Assert((visibilityset->lightgrid.size() % 4) == 0); } } } And the shader is just as tricky: //------------------------------------------------------------------------------------------ // Point Lights //------------------------------------------------------------------------------------------ countlights = lightcount[0]; int lightgroups = countlights / 4; if (lightgroups * 4 < countlights) lightgroups++; int renderedlights = 0; for (n = 0; n < lightgroups; ++n) { lightindices = texelFetch(texture11, lightlistpos + n); for (i = 0; i < 4; ++i) { if (renderedlights == countlights) break; renderedlights++; lightindex = lightindices[n]; ... I plan to add boxlights next. These use orthographic projection (unlike spotlights, which us perspective) and they have a boundary defined by a bounding box, with no edge softening. They have one purpose, and one purpose only. You can place them over windows for indoor scenes, so you can have light coming in a straight line, without using an expensive directional light. (The developer who made the screenshot below used spotlights, which is why the sunlight is spreading out slightly.) I am considering doing away with cascaded shadow maps entirely and using an array of box lights that automatically rearrange around the camera, or a combination of static and per-object shadows. I hope to find another breakthrough with the directional lights and do something really special. For some reason I keep thinking about the outdoor scenery in the game RAGE and while I don't think id's M-M-MEGATEXTURES!!! are the answer, CSM seem like an incredibly inefficient way to distribute texels and I hope to come up with something better. Other stuff I am considering Colored shadows (that are easy to use). Volumetric lights either using a light mesh, similar to the way lights work in the deferred renderer, or maybe a full-screen post-processing effect that traces a ray out per pixel and calculates lighting at each step. Area lights (easy to add, but there are a lot of possibilities to decide on). These might be totally unnecessary if the GI system is able to do this, so I'm not sure. IES lighting profiles. I really want to find a way to render realistic light refraction, but I can't think of any way to do it other than ray-tracing: It is possible the voxel GI system might be able to handle something of this nature, but I think the resolution will be pretty low. We'll see. So I think what I will do is add the boxlights, shader includes, diffuse and normal maps, bug test everything, make sure map loading works, and then upload a new build so that subscribers can try out their own maps in the beta and see what the speed difference is.

Josh

Josh

Multiple Shadows

Texture arrays are a feature that allow you to pack multiple textures into a single one, as long as they all use the same format and size. In reality, this is just a convenience feature that packs all the textures into a single 3D texture. It allows things like cubemap lookups with a 3D texture, but the implementation is sort of inconsistent. In reality it would be much better if we were just given 1000 texture units to use. However, these can be used to pack all scene shadow maps into a single texture so that they can be rendered in a single pass with the clustered forward renderer. The results are great and speed is very fast. However, there are some limitations. I said early on that my top priority with the design of the new renderer is speed. That means I will make decisions that favor speed over other flexibility, and here is a situation where we will see that in action. All scene shadow maps need to be packed into a single array texture of fixed size, which means there is a hard upper limit on total shadow-casting lights in the world. I've also discovered that my beautiful variance shadow maps use a ton of memory. At maximum quality they use an RGBA 32-bit floating point format, so that means a single 1024x1024 cubemap consumes 96 megabytes! (A standard shadow map at the same resolution uses 24 megabytes VRAM). Because all shadows are packed into a single texture, the driver can't even page the data in and out of video memory. If you don't have enough VRAM, you will get an OUT_OF_MEMORY error. So anticipating and handling this issue will be important. Hopefully I can just use appropriate defaults. I think I can cut the size of the VSMs down to 25%, but without the beautiful shadow scattering effect. Because the textures all have to be the same size, it is also impossible to set just one light to use higher resolution settings. If you want speed, I have to build more constraints into the engine. This is the kind of thing I was talking about. I want great graphics and the absolute fastest performance, so that is what Ia m doing. Okay, so with all that information and disclaimers out of the way, I give you the first shot showing multiple lights being rendered with shadows in a single pass in our new forward renderer. Here are three lights: And here I lowered the shadow map resolution and added 50 randomly placed lights. There are some artifacts and glitches, but it's still a pretty cool shot. All running in real-time, in a single pass: Keep in mind this is all before any indirect lighting has been added. The future looks bright!

Josh

Josh

Multisampled Shadowmaps

Because variance shadow maps allow us to store pre-blurred shadow maps it also allows us to take advantage of multipled textures. MSAA is a technique that renders extra pixels around the target pixel and averages the results. This can help bring out fine lines that are smaller than a pixel onscreen, and it also greatly reduces jagged edges. I wanted to see how well this would work for rendering shadow maps, and to see if I could reduce the ragged edge appearance that shadow maps are sometimes prone to. Below is the shadow rendered at 1024x1024 with no multisampling and a 3x3 blur: Using a 4X MSAA texture eliminates the appearance of jagged edges in the shadow: Here they are side by side: This is very exciting stuff because we are challenging some of the long-held limitations of real-time graphics.  

Josh

Josh

Entry progress

Making a multiplayer game about territory conquest, like a board game. The winner will have the most territory. Something like risk but no dice rolls and more simple.   So far i have: A socket server (written in go).This has the territories stored in db. Text communication protocol (using json). For example this is a register packet:  {"t":0, "p":{"name":"test"}} Game client that can select territories (using c++ poco network libraries) Sqlite3 for game data , i really like this wrapper (makes things less verbose): https://github.com/SqliteModernCpp/sqlite_modern_cpp   Working on implementing game play server side. Here is main menu trying to be in line with retro theme

aiaf

aiaf

Realistic Penumbras

Shadows with a constant softness along their edges have always bugged me. Real shadows look like this. Notice the shadow becomes software the further away it gets from the door frame. Here is a mockup of roughly what that shadow looks like with a constant softness around it. It looks so fake! How does this effect happen? There's not really any such thing as a light that all emits from a single point. The closest thing would be a very small bulb, but that still has volume. Because of this, shadows have a soft edge around them that gets less sharp the further away from the occluding object they are. I think some of this also has to do with photons hitting the edge of the object and scattering a bit as they go past it. The edge of the photon catches on the object and knocks it off course. We have some customers who need very realistic renderings, ideally as close to a photo as possible, and I wanted to see if I could create this behavior with our variance shadow maps. Here are the results: The shadows are sharp when they start being cast and become more blurry as light is scattered. Here's another shot. The shadows actually look real instead of just being blobby silhouettes. This is really turning out great!

Josh

Josh

Variance Shadow Maps

After a couple days of work I got point light shadows working in the new clustered forward renderer. This time around I wanted to see if I could get a more natural look for shadow edges, as well as reduve or eliminate shadow acne. Shadow acne is an effect that occurs when the resolution of the shadow map is too low, and incorrect depth comparisons start being made with the lit pixels: By default, any shadow mapping alogirthm will look like this, because not every pixel onscreen has an exact match in the shadow map when the depth comparison is made: We can add an offset to the shadow depth value to eliminate this artifact: \ However, this can push the shadow back too far, and it's hard to come up with values that cover all cases. This is especially problematic with point lights that are placed very close to a wall. This is why the editor allows you to adjust the light range of each light, on an individual basis. I came across a techniqe called variance shadow mapping. I've seen this paper years ago, but never took the time to implement it because it just wasn't a big priority. This works by writing the depth and depth squared values into a GL_RG texture (I use 32-bit floating points). The resulting image is then blurred and the variance of the values can be calculated from the average squared depth stored in the green channel. Then we use Chebyshev's inequality to get an average shadow value: So it turns out, statistics is actually good for something useful after all. Here are the results: The shadow edges are actually soft, without any graininess or pixelation. There is a black border on the edge of the cubemap faces, but I think this is caused by my calculated cubemap face not matching the one the hardware uses to perform the texture lookup, so I think it can be fixed. As an added bonus, this eliminates the need for a shadow offset. Shadow acne is completely gone, even in the scene below with a light that is extremely close to the floor. The banding you are seeing is added in the JPEG compression and it not visible in the original render. Finally, because the texture filtering is so smooth, shadowmaps look much higher resolution than with PCF filtering. By increasing the light range, I can light the entire scene, and it looks great just using a 1024x1024 cube shadow map. VSMs are also quite fast because they only require a single texture lookup in the final pass. So we get better image quality, and probably slightly faster speed. Taking extra time to pay attention to small details like this is going to make your games look great soon!

Josh

Josh

Celebrating the success of Bladequest!

I decided to do a small party, eating some delicious food, celebrating the success of Bladequest - The First Chapter. It had over 450 downloads over within only 7 days and counting, I had the first few sales and Josh is supporting me bringing the game on steam. This is really awesome, thank you soo much, you make it possible for me to live my dream and make me feel the fire deep in my hearth, which gives me the power and motivation to bring my upcoming games on a new exciting quality level! I will soon start a Devlog kind of series on YouTube, where I introduce cool new features and content waiting for you in my next project, so you can give direct feedback and together we can make it awesome :D! Stay cool! Markus from Phodex Games! Grab the Game here! Give Feeback for Bladequest!
My Youtube Channel!
Your Games Wishlist so I can craft a game to your needs!

About the day night cycle

Hey I know you can use for this the nice shader of Shadmar, but now if you want to try something else, This is somewhat like you can obtain if you use a big light sphere rounding around the player. I speed up the cycle quicker for the video to see all the day/night. I used the directional light rotation for the shadows, the color of the sky-sphere for the colorourfull effect and the color of the directional light for the luminosity, getting the no shadow night light. Clouds/rain has been hidden to see better. Here is a demo:  

Marcousik

Marcousik

Rainy weather in forest - performance test LE 4.3

I'm happy with this because I spent a long time in testing how to make rain without slowing the game too much. I wanted the rain to have "splash" effect on the ground and to stop correctly as the player could stay under a roof or hides under a big stone etc etc.. I got big problems with collision testing and very low performances when using the shaped vegetation tool. Now that's fine, because I do not use the collision anymore, saving much performances. Here is a little demo:   Here is a bit longer one with 2 rainfalls:   Hope you enjoy !

Marcousik

Marcousik

Clustered Forward Rendering Victory

I got the remaining glitches worked out, and the deal is that clustered forward rendering works great. It has more flexibility than deferred rendering and it performs a lot faster. This means we can use a better materials and lighting system, and at the same time have faster performance, which is great for VR especially. The video below shows a scene with 50 lights working with fast forward rendering One of the last things I added was switching from a fixed grid size of 16x16x16 to an arbitrary layout that can be set at any time. Right now I have it set to 16x8x64, but I will have to experiment to see what the optimum dimensions are. There are a lot of things to add (like shadows!) but I have zero concern about everything else working. The hard part is done, and I can see that this technique works great.

Josh

Josh

Awesome Redesign & Update & Steam!

Doesn’t the new design of Bladequest look awesome? To celebrate it I just released Bladequest - TFC 1.4.0, including the new design and a voice over for the intro and outro screen, spoken by myself, introducing the project. I think this adds a more personal touch to the game. What do you think about it? The game is now also available on gamejolt, running very good there! Bladequest was downloaded over 100 times within 3 days, thats awesome! To celebrate that I started a sale for the GOLD Edition. Get it 67% OFF! Thanks to Josh Bladequest is also coming to Steam soon! I am very excited to continue development and deliever more content and better quality. Enjoy the update and have a great time! Markus from Phodex Games! Give Feeback for Bladequest!
My Youtube Channel!
Your Games Wishlist so I can craft a game to your needs!

Clustered Forward Rendering Progress

In order to get the camera frustum space dividing up correctly, I first implemented a tiled forward renderer, which just divides the screen up into a 2D grid. After working out the math with this, I was then able to add the third dimension and make an actual volumetric data structure to hold the lighting information. It took a lot of trial and error, but I finally got it working. This screenshot shows the way the camera frustum is divided up into a cubic grid of 16x16x16 cells. Red and green show the XY position, while the blue component displays the depth: And here you can see the depth by itself, enhanced for visibility: I also added dithering to help hide light banding that can appear in gradients. Click on the image below to view it properly: I still have some bugs to resolve, but the technique basically works. I have no complete performance benchmarks yet to share but I think this approach is a lot faster than deferred rendering. It also allows much more flexible lighting, so it will work well with the advanced lighting system I have planned.

Josh

Josh

Clustered Forward Rendering - First Performance Metrics

I was able to partially implement clustered forward rendering. At this time, I have not divided the camera frustum up into cells and I am just handing a single point light to the fragment shader, but instead of a naive implementation that would just upload the values in a shader uniform, I am going through the route of sending light IDs in a buffer. I first tried texture buffers because they have a large maximum size and I already have a GPUMemBlock class that makes them easy to work with. Because the GPU likes things to be aligned to 16 bytes, I am treating the buffer as an array of ivec4s, which makes the code a little trickier, thus we have a loop within a loop with some conditional breaks: vec4 CalculateLighting(in vec3 position, in vec3 normal) { vec4 lighting = vec4(0.0f); int n,i,lightindex,countlights[3]; vec4 lightcolor; ivec4 lightindices; mat4 lightmatrix; vec2 lightrange; vec3 lightdir; float l,falloff; //Get light list offset int lightlistpos = 0;//texelFetch(texture12, sampleCoord, 0).x; //Point Lights countlights[0] = texelFetch(texture11, lightlistpos).x; for (n = 0; n <= countlights[0] / 4; ++n) { lightindices = texelFetch(texture11, lightlistpos + n); for (i = 0; i < 4; ++i) { if (n == 0 && i == 0) continue; //skip first slot since that contains the light count if (n * 4 + i > countlights[0]) break; //break if we go out of bounds of the light list lightindex = lightindices[1]; lightmatrix[3] = texelFetch(texture15, lightindex * 4 + 3); vec3 lightdir = position - lightmatrix[3].xyz; float l = length(lightdir); falloff = max(0.0f,-dot(normal,lightdir/l)); if (falloff <= 0.0f) continue; lightrange = texelFetch(texture15, lightindex * 4 + 4).xy; falloff *= max(0.0f, 1.0f - l / lightrange.y); if (falloff <= 0.0f) continue; lightmatrix[0] = texelFetch(texture15, lightindex * 4); lightmatrix[1] = texelFetch(texture15, lightindex * 4 + 1); lightmatrix[2] = texelFetch(texture15, lightindex * 4 + 2); lightcolor = vec4(lightmatrix[0].w,lightmatrix[1].w,lightmatrix[2].w,1.0f); lighting += lightcolor * falloff; } } return lighting; } I am testing with Intel graphics in order to get a better idea of where the bottlenecks are. My GEForce 1080 just chews through this without blinking an eye, so the slower hardware is actually helpful in tuning performance. I was dismayed at first when I saw my framerate drop from 700 to 200+. I created a simple scene in Leadwerks 4 with one point light and no shadows, and the performance was quite a bit worse on this hardware, so it looks like I am actually doing well. Here are the numbers: Turbo (uniform buffer): 220 FPS Turbo (texture buffer): 290 FPS Leadwerks 4: 90 FPS Of course a discrete card will run much better. The depth pre-pass has a very slight beneficial effect in this scene, and as more lights and geometry are added, I expect the performance savings will become much greater. Post-processing effects like bloom require a texture with the scene rendered to it, so this system will still need to render to a single color texture when these effects are in use. The low quality settings, however, will render straight to the back buffer and thus provide a much better fallback for low-end hardware. Here we can see the same shader working with lots of lights. To get good performance out of this, the camera frustum needs to be divided up into cells with a list of relevant lights for each cell. There are two more benefits to this approach. Context multisample antialiasing can be used when rendering straight to the back buffer. Of course, we can do the same with deferred rendering and multisample textures now, so that is not that big of a deal. What IS a big deal is the fact that transparency with shadows will work 100%, no problems. All the weird tricks and hacks we have tried to use to achieve this all go away. (The below image is one such hack that uses dithering combined with MSAA to provide 50% transparency...sort of.) Everything else aside, our first tests reveal more than a 3X increase in performance over the lighting approach that Leadwerks 4 uses. Things look fantastic!

Josh

Josh

Taking Care of Business

This is about financial stuff, and it's not really your job to care about that, but I still think this is cool and wanted to share it with you. People are buying stuff on our website, and although the level of sales is much lower than Steam it has been growing. Unlike Steam, sales through our website are not dependent on a third party and cannot be endangered by flooded marketplaces, strange decisions, and other random events. Every customer I checked who used a credit card has kept it on file for further purchases. The credit card number isn't actually stored on our server, and I never see it. Instead, PayPal stores the number and we store a token that can only be used for purchases through this domain, so it is impossible for a hacker to steal your credit card from our site. I feel better doing things this way because it's much safer for everyone. Anyways, having a customer who has the ability to buy anything they want on your site at a moment's notice is a very good thing. You give them a good product and they can easily buy it, if it is something they want. This is what I hoped to see by introducing these features to the site, so it is nice to see it working. Thank you for your support! I will work hard to bring you more great software.

Josh

Josh

×