Updates to sfchat and procedural shader

And suddenly it's been nearly two months since my last post... It's not that I've been doing nothing, I just haven't actually accomplished anything to any real end. I have updated a few things, however, so I shall go ahead and share them:

sfchat
I've done a small amount of work recently on my server/client chat class for SFML. Nothing extraordinary, I've added the option for coloured text and updated the internal dynamic memory handling with smart pointers. It doesn't warrant a new release as there are still some bugs when using coloured text, but the updates are available by checking out the latest version of the source on the Github project page.

Oh yes, smart pointers. They're awesome. I won't go too into detail as there are plenty of resources out there to explain their use; but I will say this: std::unique_ptr should be your default go-to when allocating from the heap. If you don't know why then do some research, it'll make your life much easier in the long run. I'm certainly glad I made the effort.

The procedural shader
Subject of two of my previous posts, I have had some questions as to why the light source appears to rotate with any sprite which uses the shader. The reason for this is that when applying the shader to an individual sprite rather than he whole screen is that it's being applied to the sprite's texture, not the texture of the quad representing the world space. Crucially this means that when a sprite is rotated, along with its texture, the texture coordinates are rotated too, with the effect of bringing the light with it. To demonstrate the effect consider the following images:




The first image looks fine as the sprite is not rotated at all, but in the second image the rotated sprite has been lit on the wrong side, as if the light source has been rotated with it. To fix this we need to rotate the light coordinates in the opposite direction about the origin of the sprite. The first thing, then, is to convert the origin of the light source vector to the sprite's local space. As the sprite's position is also in world space this is as straightforward as:

lightPos -= sprite.getPosition();

Next, the tricky bit: rotating the coordinates. You could use traditional trigonometry to calculate the required angles - but this can get a bit unweildy in code, even when wrapped in its own function. Fortunately SFML offers an alternative solution with its sf::tranform class. sf::transform supplies a 3x3 matrix which allows easy calculation of transformations in position, scale and rotation - in fact it is used by default in SFML by every object derived from sf::transformable, including sprites and shapes. The math behind a 3x3 transform may blow your mind, but in practice it is very easy to use the sf::transform class to convert coordinates between world and local systems (which is what we're doing here). First we need to create an instance:

sf::transform tf;

then rotate it:

tf.rotate(-sprite.getRotation());

Once it has been rotated it can be used to rotate any given point about that point's origin. As our light position is now originating from the sprite position it will now rotate about the sprite:

tf.transformPoint(lightPos);

Now when we feed the transformed light coordinate into the shader the lighting will render correctly.


An alternative, of course, would be to use a vertex shader to supply the correct coordinates to the procedural shader which would have the benefit of moving the processing for this step from the CPU to the GPU. If I ever feel that I need the gain in performance then I'll look into it and no doubt post here - but for now this does the job.

Comments

Popular Posts