Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Ant

Pages: [1] 2
1
Network / Re: Nonblocking Tcp Socket Status is Never sf::Socket::Done
« on: August 21, 2021, 06:53:10 pm »
I experimented with this again, and I didn't find anything new. I decided to simply interpret NotReady as a successful return code primarily because:

SocketImpl::getErrorStatus maps Status::NotReady to WSAEWOULDBLOCK and WSAEALREADY.

According to windows-sockets-error-codes:
WSAEALREADY
A nonblocking connect call is in progress on the specified socket.
This is fine. I can work around this particular code by checking if I already sent a request or not.

WSAEWOULDBLOCK
It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.
Seeing that it is normal for Windows to report that error code for nonblocking sockets, I think it would be fine to treat a normal code as a success especially since I never seen it return anything else in a successful case.

I'm going to take a break on this. When I look into this again, the next thing I'll look into is the FD_CONNECT notification. The document points me to use the select function:
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select

I recall that SFML already implements a SocketSelector. Admittedly I haven't researched the SocketSelector extensively. Perhaps I've been using nonblocking sockets incorrectly, and I was suppose to use the socket selector this whole time. It's something I'll look into.

2
Network / Re: Nonblocking Tcp Socket Status is Never sf::Socket::Done
« on: August 20, 2021, 04:53:41 am »
Update:
on the client, Windows is returning WSAEWOULDBLOCK, and SocketImpl::getErrorStatus maps to that error to Socket::NotReady.

According to https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
WSAEWOULDBLOCK is:
Resource temporarily unavailable.
    This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.

If I ignore this specific error message (using a break on that specific case), and if I start the server before the client, the applications proceed as expected. Starting the client before the server is ready would cause it to fail.

I closely followed what parameters are we passing into the win socket methods (in particular creation, blocking, and connect), and I haven't found anything suspicious when following along SFML's code and MS's documentation.

I found a few posts that may be related to win sockets, but I haven't quite comprehend it yet.
https://forums.codeguru.com/showthread.php?317429-Why-do-I-get-WSAEWOULDBLOCK-when-calling-recv()
https://stackoverflow.com/questions/14010285/wsaewouldblock-handling

I've also read that winapi returns WSAEWOULDBLOCK when there is nothing to read from the socket. However I tested against this by having the server populate a packet and sending it immediately after successfully accepting the connection.


Another thing that puzzles me is that I'm not seeing this bug in my actual application. I created this minimal case to investigate a different bug where I'm getting multiple callbacks from one packet. However this particular bug only occurs on the Hello World programs. The only thing that comes to mind is the complexity between the two applications. The real application essentially has a continuous loop that does a host of other things every frame. I was hoping to simulate this using thread sleep. I've attempted at higher intervals, too (up to 5 seconds).

This quote from one of the SO posts lead me to suspect that it's related to the infinite while loop.
It is a performance optimization. You can speculatively try to send synchronously (which is very fast). And only if it fails you are supposed to schedule an asynchronous IO

I'll take another look at the forum posts to see if something clicks in my head.

3
Network / Nonblocking Tcp Socket Status is Never sf::Socket::Done
« on: August 19, 2021, 09:56:30 am »
I'm running into problems with nonblocking Tcp sockets where the client is unable to receive the sf::Socket::Done status despite that the server accepting the connection. After the server accepts the connection, the client's socket status becomes NotReady.

Server minimal example:
#include <chrono>
#include <iostream>
#include <SFML/Network.hpp>
#include <thread>

int main()
{
        std::cout << "Starting server\n";

        unsigned long updateRate = 30;

        sf::TcpListener listen;
        listen.setBlocking(false);
        if (listen.listen(2011) != sf::Socket::Done)
        {
                std::cout << "Failed to listen at port 2011\n";
                return -1;
        }

        std::cout << "Listening on port 2011\n";

        sf::TcpSocket client;
        client.setBlocking(false);
        while (true)
        {
                if (listen.accept(client) == sf::Socket::Done)
                {
                        break;
                }

                //simulate work
                std::this_thread::sleep_for(std::chrono::milliseconds(updateRate));
        }

        std::cout << "Connected... waiting for packet\n";
        sf::Packet packet;
        while (true)
        {
                sf::Socket::Status status = client.receive(packet);
                if (status == sf::Socket::Done)
                {
                        int num;
                        packet >> num;
                        std::cout << "Received data. " << num << " \n";
                        break; //TODO: loop a couple times to check if receiving multiple data.
                }
               
                //Simulate work
                std::this_thread::sleep_for(std::chrono::milliseconds(updateRate));
        }

        std::cout << "Disconnecting server.\n";
        client.disconnect();
        return 0;
}

Server output:
Starting server
Listening on port 2011
Connected... waiting for packet
 


Client minimal example:
#include <chrono>
#include <iostream>
#include <SFML/Network.hpp>
#include <thread>

int main()
{
        std::cout << "Starting client\n";

        unsigned long updateRate = 30;
        sf::TcpSocket client;
        client.setBlocking(false);

        while (true)
        {
                sf::Socket::Status status = client.connect(sf::IpAddress("127.0.0.1"), 2011);
                if (status == sf::Socket::Done)
                {
                        break;
                }

                //Simulate work
                std::this_thread::sleep_for(std::chrono::milliseconds(updateRate));
        }

        std::cout << "Connected... sending packet\n";
        sf::Packet packet;
        while (true)
        {
                int num = 456;
                packet << num;

                sf::Socket::Status status = client.send(packet);
                if (status == sf::Socket::Done)
                {
                        std::cout << "Sent data. " << num << " \n";
                        break;
                }
               
                //Simulate work
                std::this_thread::sleep_for(std::chrono::milliseconds(updateRate));
        }

        std::cout << "Disconnecting client.\n";
        client.disconnect();
        return 0;
}

Client output:
Starting client

When I set the client's socket to blocking (server remains unblocking), then it proceeds as expected.
Server output
Starting server
Listening on port 2011
Connected... waiting for packet
Received data. 456
Disconnecting server.

Client output
Starting client
Connected... sending packet
Sent data. 456
Disconnecting client.

This is tested on Windows 10.
I'm using SFML version 2.5.1.

I will continue looking into this, and I'll post anything I identified in my investigation.

4
Window / Re: Hitching and Crashing with multiple sf::Window handles
« on: June 09, 2020, 12:42:59 am »
Update

I've updated my drivers and did a full restart on my machine. That seem to solve my issue. The test is now very smooth!

Though I'm curious. If it was a driver/OS issue, I don't understand why other applications were not hitching. When playing resource intensive games like GW2, that game seems to run smoothly but yet my simple sprite render test hitches.

I've also did some experimenting this morning. Although it's no where near as prevalent as before I was able to cause a few hitches when running other programs like Process Explorer. But it's no where as bad as it was. Before it was hitting 150+ ms every 2-5 seconds. During my experiments this morning, it would hit 60-75 ms once every few minutes (only when Process Explorer's system monitor was running). When running a blank desktop, I never got it to hit that break point.

I guess I can close this ticket out since it may appear negligible. I have lingering worries when I do decide to upscale my project to include a physics engine and render more Entities. I have a feeling the hitching would come back, and it'll be more difficult to debug and fix once the project becomes even more complicated.

5
Window / Re: Hitching and Crashing with multiple sf::Window handles
« on: June 08, 2020, 12:49:12 am »
Quote
You should really be focusing on one thing at a time.
I agree. My main focus is to figure out how to fix the hitches. My investigation lead me to many irrelevant things such as the setActive.

Quote
What's more likely the cause is some faulty input device driver.
That's a fantastic idea! I'll check my hardware and their drivers tonight.

Quote
Measuring and breaking after it happens is fine to detect that issue, but if you really want to figure out what's going on, you should use a profiler. It's still tricky to capture it, but it may give you an insight where it spends a lot of time.
I'll have to research more about this. I'm not familiar with using a profiler.


Quote
As for your multiple sf::Window handles. What do you mean with multiple sf::Window handles? What's a handle for you?
A handle to me is similar to Window API HWND. But instead of void*, I'm treating sf::Window as the object that interfaces with the OS.
In my case, I really have multiple sf::Window instances. One thread use to have three window handles, and another thread is responsible for 2. Now I'm down to a single sf::Window instance that resides in a separate thread.

Quote
Don't forget that you can process events only in the thread that created the window.
Yeah I read that from somewhere. Probably from the docs or from another help forum. The good news is that the thread is very isolated from everything else. The thread creates its own copy of the engine. It imports its own textures and fonts. It creates its own sf::Window, poll handlers, input handlers, tick groups, etc...

Threads are only allowed to communicate through ThreadedComponents, but there aren't any instantiated in this test. The only exception is the shutdown signal, and maybe a few static variables for mutex locks.

Quote
Also remember that writing multi-threaded code introduces a lot of complexity and with it a lot of hard to understand and hard to debug problems. Don't do it unless you have a good reason and enough experience.
Yeah. Race conditions really scare me. I plan to write multi-threaded code for heavy processing that could be extracted from the main thread. I only moved this test to a separate thread to see if having too many sf::Window instances on the same thread is problematic.

6
Window / Re: Hitching and Crashing with multiple sf::Window handles
« on: June 07, 2020, 10:52:01 pm »
Update

I've disabled nearly everything from the main thread. It's essentially ticking an empty loop. It doesn't create any windows nor does it create any RenderTextures.

This allowed my second thread to create window handles.

I've also minimized that thread to display a blank window. It only has a mouse pointer in a blank screen.

Some things I observed from this.
1. I'm still reaching 100-175 ms on an empty pollEvents loop.
2. Moving tests to a separate thread will not fix my hitching problem.
3. Calling setActive(false) to everything doesn't seem to do anything. The window handles are still rendering a sprite even when I set its active to false. In fact, I'm setting it to be inactive every poll event.
        std::vector<sf::Event> events;
        if (Resource != nullptr)
        {
                const std::lock_guard<std::mutex> lock(WindowResourceMutex);
                Resource->setActive(false);

                Stopwatch pollEventStopwatch(TXT("windowStopwatch"), false);

                sf::Event sfEvent;
                while (Resource->pollEvent(OUT sfEvent))
                {
                        //Do stuff in loop.
                        events.push_back(sfEvent);
                }

                FLOAT elapsedTime = pollEventStopwatch.GetElapsedTime();
                if (elapsedTime > 50)
                {
                        int breakHere = 0; //Hitting this breakpoint
                }
        }
        //Registered callbacks will handle events, but those are outside the scope of stopwatch, and the events vector is empty.
 

I started to suspect the hitches could be related to cache misses, but when I debugged the entire tick cycle, I'm only hitting 50+ ms on the system tick group.

        //Update all TickGroups and their registered TickComponents
        for (TickGroup* tickGroup : TickGroups)
        {
                Stopwatch tickGroupStopwatch(TXT("TickGroupStopwatch"), false);
                tickGroup->TickRegisteredComponents(deltaSec);
                FLOAT elapsedTime = tickGroupStopwatch.GetElapsedTime();
                if (elapsedTime > 50 && !IsMainEngine())
                {
                        int breakHere = 0; //<---- I'm hitting this break point from time-to-time on the System tick group.
                }
        }
 

In this test, there are numerous tick groups: Debug, Render, Gui, etc...
None of those tick groups are triggering that break point. Only the System tick group is hitting that break point. And there is only one registered TickComponent in that group and that is for handling the window poll events, which is also pasted above.


I've ran the Hello World SFML project, and I'm not hitting that break point. That program seems to run smoothly.
int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setOrigin(100.f, 100.f);
    shape.setPosition(100.f, 100.f);
    shape.setFillColor(sf::Color::Green);

    while (window.isOpen())
    {
                std::clock_t c_start = std::clock();
                auto t_start = std::chrono::high_resolution_clock::now();
                std::vector<sf::Event> evnts;

        sf::Event event;
        while (window.pollEvent(event))
        {
                        evnts.push_back(event);
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(shape);
        window.display();

                std::clock_t c_end = std::clock();
                auto t_end = std::chrono::high_resolution_clock::now();
                double elapsedTime = 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC;
                if (elapsedTime > 50)
                {
                        int breakHere = 0; //<----- I am NOT hitting this breakpoint
                }
    }

    return 0;
}
 

7
Window / Hitching and Crashing with multiple sf::Window handles
« on: June 05, 2020, 11:17:58 pm »
I've been experiencing hitches with sf::Window::pollEvents function. Most of the time, the application can run smoothly (over 100 fps). But every few seconds, the app hitches on this function.

    Stopwatch pollEventsStopwatch;

    int counter = 0;

    sf::Event sfEvent;
    while (Resource != nullptr && Resource->pollEvent(sfEvent))
    {
        counter++;

        //Do stuff in this loop, but this loop is never iterating since there aren't any events.
    }

    FLOAT elapsedTime = pollEventsStopwatch.GetElapsedTime();
    if (elapsedTime > 50)
    {
        int breakHere = 0; //<----  I'm hitting this breakpoint since elapsed time is usually above 150 milliseconds even when counter is 0.
    }
 

I've been struggling with this for awhile. The best theory I have is maybe because there many window handles in this application. The application I have is basically runs multiple unit tests so it pops up about five windows on a thread. And to test this theory, I closed all but one of the windows. And it seems to never hit that break point when it's down to one window handle.

I tried moving one of the tests to its own thread, but by doing so, I'm running into a new issue where creating a new window handle on the separate thread causes an infinite recursion crash.

//Other stuff here. Let me know if you want me to post the full context of this function.

PrimaryWindow = Window::CreateObject();
PrimaryWindow->SetResource(new sf::RenderWindow(sf::VideoMode(800, 600), PROJECT_NAME)); //<---- crashes here
 

Callstack crash:
....
        sfml-window-d-2.dll!`anonymous namespace'::getInternalContext() Line 159        C++
        sfml-window-d-2.dll!sf::priv::GlContext::ensureContext() Line 217       C++
        sfml-window-d-2.dll!sf::GlResource::GlResource() Line 61        C++
        sfml-window-d-2.dll!sf::Context::Context() Line 61      C++
        sfml-window-d-2.dll!`anonymous namespace'::getInternalContext() Line 159        C++
        sfml-window-d-2.dll!sf::priv::GlContext::ensureContext() Line 217       C++
        sfml-window-d-2.dll!sf::GlResource::GlResource() Line 61        C++
        sfml-window-d-2.dll!sf::Context::Context() Line 61      C++
        sfml-window-d-2.dll!`anonymous namespace'::getInternalContext() Line 159        C++
        sfml-window-d-2.dll!sf::priv::GlContext::ensureContext() Line 217       C++
        sfml-window-d-2.dll!sf::GlResource::GlResource() Line 61        C++
        sfml-window-d-2.dll!sf::Context::Context() Line 61      C++
....
 

While reading through docs and forums, I learned about sf::Window::setActive. Although I call setActive(true) during the draw/render stage, it did not seem to make a difference. Then I started calling setActive(false) everywhere (after creating sf::RenderWindow, before render calls, before pollEvents, etc...). I know that's not the right way of doing things, but I was hoping it would at least 'lock' the windows instead of crashing whenever I create a window handle on a different thread.

I've did this for sf::RenderTextures, too. And I'm still crashing whenever I create a window handler on the other thread.


And here I am currently stuck. I'm running SFML version 2.4.0. I suppose I can upgrade it to a later version in case there was a bug fix for this.


Questions I have are:
1. Any idea why polling events sometimes take over 150 milliseconds even though there aren't any events?

2. When do I need to call setActive on a window handle? Can it only be activated before calling clear, draw, display functions? Or do I need to activate the window handles when polling events, too? I presume the same should be done for sf::RenderTextures, too.

3. Any idea what could be causing the infinite recursion crash? If the windows are self contained in their own threads, is it possible to handle windows and render textures in multiple threads if setActive is called appropriately?

8
Graphics / Re: Transformation Order Problem
« on: June 16, 2018, 07:41:39 pm »
Although the transform allows me to customize the order.  In the end, I realized that the best solution is simply to set the position to a different value.

If I were to adjust the scale before setting the origin, that would hurt the purpose behind setting the origin in the first place (scale relative to the origin and rotate about the origin).

9
Graphics / Transformation Order Problem
« on: June 16, 2018, 03:33:47 am »
I apologies for the long winded topic.  I got stuck on a problem for a few days, and I think what would help me is to write the situation somewhere to straighten my thoughts.


The problem is that I misinterpreted the origin attribute for transformable objects.

I interpreted that the origin was the spot where whenever you call setPosition, the origin will be placed at that pixel location.
By default, it's the top left corner.  Setting the origin would shift the rendered object.  This would allow the dev to easily center a sprite over a specified position.
Scale and rotation by seems to work fine, too.  It rotates about the origin, and it scales relative to the origin.


My issue is introduced when I tried to apply all three transforms for a test game (Solitaire).
I'm setting a card's origin to the middle to allow it to spin around its center.
I'm setting the center's position equal to the center of a specific spot.
Lastly, the sprite is scaled by 50%.  Here I'm expecting the card's borders to squeeze closer to the origin equally.

Although the card gets smaller, the position is 'shifted' from desired location.  I've attached a screenshot to help visualize the scenario.  I've also disabled spinning to simplify the problem.
Looking at the 9 of spades, there's a card outline to the top left of it.  That's the desired location.
CardSize.X = 90
Pivot = CardSize * 0.5  (Pivot.X = 90/2 => 45)
Position.X = 8 + Pivot   (53) <--- The intention is to place the center of the card at the center of the outline.
Size = 0.5
Result Position of top left corner of card (X-axis) = 31     ((-Pivot.X*0.5) + Position.X)  <-- The 0.5 is coming from size
Expected Position of top left corner of card (X-axis) = 8   (-Pivot.X + Position.X)

The easiest solution is to simply adjust the position, but that would weaken my internal usage behind origin where the origin is always at the location where setPosition is specified.
My objective is that when I call SetPosition on an object, the origin of that object is found at that location regardless of scale and rotation.

I've considered a handful of hacky solutions, but I'm too embarrassed to bring them up.

-----------------------------------

Edit:  I sat on my post for a few hours before publishing it.  Writing it down did help me understand the problem.  It's an order of operation error.  It's applying origin shift, scaling, then translating when I need to scale, shift it, then translate it.

For the example above (looking at left border X coordinate of sprite):
Actual:
Absolute Pos = 0
Apply Origin Shift (45)
Absolute Pos = -45
Apply scaling (0.5)
Absolute Pos = -22.5
Apply translation (53)
Absolute Pos = 31

Needed:
Absolute Pos = 0
Apply scale (0.5)
Absolute Pos = 0   <--- but the card is half size
Apply translation (53)
Absolute Pos = 53
Apply Origin Shift (45)
Absolute Pos = 8

Perhaps changing my setPosition setOrigin setSize calls with using a sf::Transform object may help resolve my issue.  I'll give this a try, and I'll post again.  I decided to make this post anyways in case others are running into similar problems.

10
System / Re: basic_string<Unsigned Char> to basic_string<char> for UTF-8
« on: January 24, 2017, 07:50:12 am »
There's functionality in utf-8 library that's missing from SFML.

The find_invalid function determines if the string of bytes is formatted correctly in UTF-8.  This is helpful for unit testing.  This is also helpful when checking if a file is encoded in utf-8 or not.

I also liked the ability to go backwards in the iterator (since some functions may be searching from right to left).  This required a few utilities such as determining if the current byte is starting a new character or not.

11
System / Re: basic_string<Unsigned Char> to basic_string<char> for UTF-8
« on: January 23, 2017, 08:27:35 am »
Sorry about the late reply.  I come to realize that I didn't conduct enough research to continue on with that task.

The following week, I've done some reading.  Here are a few things I've messed up on when making the first post.

  • Firstly, I was reading the strings incorrectly.  I've learned that there's a neat trick in Visual Studio's watcher window to interpret the byte array differently.  For example, when you append a ",s8" to the variable name in the watcher window, it'll read it as a UTF-8 string.  Other format specifiers can be found here:  https://msdn.microsoft.com/en-us/library/75w45ekt.aspx
  • I found out that the standard library doesn't fully support Unicode strings.  For example, if the UTF-8 string contains a character that possesses more than 1 byte, the std library would treat that character as 2 or more characters.
The following weeks, I was implementing a bidirectional string iterator that will jump across one or more bytes based on the size of the current character.  I've used the utf8 library for validation and conversions.  The useful library can be found here:  http://utfcpp.sourceforge.net/

Although this was a pleasant learning experience, rewriting many of the string libraries and their associated unit tests were not so pleasant.  In the end, I'm glad I took on this task!

Sorry for bumping this topic.  But I wanted to bring closure to this, and to share my experience for future readers.


12
System / basic_string<Unsigned Char> to basic_string<char> for UTF-8
« on: January 07, 2017, 07:13:58 am »
Ever since Microsoft announced that they added support Unicode literals in Visual Studio 2015, I've been slowly replacing my wide strings with UTF-8 basic strings.
https://msdn.microsoft.com/en-us/library/hh409293.aspx

I ran into an issue with std::basic_string<unsigned char>
With std::basic_string<unsigned char> (instead of  std::basic_string<char>) I lose some functionality to interact with std.  For example, I can't do this:
std::basic_string<unsigned char> something;
std::cout << something << std::endl; //error here
 

The sf::String::toUtf8 function returns std::basic_string<Uint8> which is results to std::basic_string<unsigned char>

Here's an example of an issue I'm running into:
void LogIt (const std::string& log)
{
        std::cout << log;
        OutputDebugString(log.c_str());
}

void LogIt (const std::basic_string<unsigned char>& log)
{
        //Need to convert basic_string<sf::Uint8> to string<char>
}

void DoStringTest ()
{
        //Value of string copied from:  http://en.cppreference.com/w/cpp/locale/wstring_convert/from_bytes
        std::string utf8String = u8"z\u00df\u6c34\U0001d10b \n";
        std::string normalString = "z\u00df\u6c34\U0001d10b \n"; //invalid chars and compiler warnings
        std::basic_string<char> utf8Basic = u8"z\u00df\u6c34\U0001d10b \n";
        std::basic_string<char> normalBasic = "z\u00df\u6c34\U0001d10b \n"; //invalid chars and compiler warnings

        sf::String sfString = utf8String;
        //std::string something = sfString.toUtf8(); //error
        std::basic_string<sf::Uint8> fromSF = sfString.toUtf8();

        LogIt(utf8String); //produces "zÃ...." The remaining characters cannot be displayed in this forum post.
        LogIt(utf8Basic); //produces "zÃ...." The remaining characters cannot be displayed in this forum post.
        LogIt(sfString); //produces "zÃ...." The remaining characters cannot be displayed in this forum post.
        LogIt(fromSF); //Goes to overloaded function with param std::basic_string<unsigned char>
}
 
Compiled in Microsoft Visual Studio 2015 Update 1
Using SFML version 2.4.0.

I'm not sure if I should have created a feature request to have that function return a std::basic_string<char> instead, or I should look at this problem at a different angle.

Thanks for your help.

13
SFML website / Re: Custom Avatar Is Not Accepted
« on: December 18, 2016, 10:02:29 pm »
Uploading to Imgur was the solution.  I think you're right about the https comment.

Thanks for your help!

14
SFML website / Custom Avatar Is Not Accepted
« on: December 18, 2016, 11:20:34 am »
I've been trying to change my avatar to use an image from my Dropbox account.  However when I hit 'Change Profile' button in the profile settings I receive a 'Your profile has been updated successfully.' message at the top, but the avatar radio button reset back to 'No Avatar'.

I've tried the following resolutions in jpg:
596x357
512x512
128x128
32x32


What are the rules for a custom avatar via URL?
Is there a min/max size?
Is there an enforced aspect ratio?

Thanks for your help in advance.

15
Feature requests / Check if Shader Parameter Exists
« on: July 08, 2016, 10:12:45 am »
I think having the capability to check which uniform(s) exists on a Shader may help reduce the amount of micromanagement.  For example, I can create a wrapper of sf::Shader, and that wrapper can check for specific uniform names and act accordingly.  If the uniform named 'GlobalTime' or 'DeltaTime' exists on shader, I can have the shader wrapper automatically update those variables every frame.  It gets trickier when I need to associate a texture mask that's based on the current animation frame.  Having this functionality implemented in a wrapper class may reduce the need of external objects updating every shader they instanced.

I'm requesting for a bool CheckParamExists function defined in the sf::Shader class.

Pages: [1] 2
anything