• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By fleissi
      Hey guys!

      I'm new here and I recently started developing my own rendering engine. It's open source, based on OpenGL/DirectX and C++.
      The full source code is hosted on github:
      https://github.com/fleissna/flyEngine

      I would appreciate if people with experience in game development / engine desgin could take a look at my source code. I'm looking for honest, constructive criticism on how to improve the engine.
      I'm currently writing my master's thesis in computer science and in the recent year I've gone through all the basics about graphics programming, learned DirectX and OpenGL, read some articles on Nvidia GPU Gems, read books and integrated some of this stuff step by step into the engine.

      I know about the basics, but I feel like there is some missing link that I didn't get yet to merge all those little pieces together.

      Features I have so far:
      - Dynamic shader generation based on material properties
      - Dynamic sorting of meshes to be renderd based on shader and material
      - Rendering large amounts of static meshes
      - Hierarchical culling (detail + view frustum)
      - Limited support for dynamic (i.e. moving) meshes
      - Normal, Parallax and Relief Mapping implementations
      - Wind animations based on vertex displacement
      - A very basic integration of the Bullet physics engine
      - Procedural Grass generation
      - Some post processing effects (Depth of Field, Light Volumes, Screen Space Reflections, God Rays)
      - Caching mechanisms for textures, shaders, materials and meshes

      Features I would like to have:
      - Global illumination methods
      - Scalable physics
      - Occlusion culling
      - A nice procedural terrain generator
      - Scripting
      - Level Editing
      - Sound system
      - Optimization techniques

      Books I have so far:
      - Real-Time Rendering Third Edition
      - 3D Game Programming with DirectX 11
      - Vulkan Cookbook (not started yet)

      I hope you guys can take a look at my source code and if you're really motivated, feel free to contribute :-)
      There are some videos on youtube that demonstrate some of the features:
      Procedural grass on the GPU
      Procedural Terrain Engine
      Quadtree detail and view frustum culling

      The long term goal is to turn this into a commercial game engine. I'm aware that this is a very ambitious goal, but I'm sure it's possible if you work hard for it.

      Bye,

      Phil
    • By tj8146
      I have attached my project in a .zip file if you wish to run it for yourself.
      I am making a simple 2d top-down game and I am trying to run my code to see if my window creation is working and to see if my timer is also working with it. Every time I run it though I get errors. And when I fix those errors, more come, then the same errors keep appearing. I end up just going round in circles.  Is there anyone who could help with this? 
       
      Errors when I build my code:
      1>Renderer.cpp 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2039: 'string': is not a member of 'std' 1>c:\program files (x86)\windows kits\10\include\10.0.16299.0\ucrt\stddef.h(18): note: see declaration of 'std' 1>c:\users\documents\opengl\game\game\renderer.h(15): error C2061: syntax error: identifier 'string' 1>c:\users\documents\opengl\game\game\renderer.cpp(28): error C2511: 'bool Game::Rendering::initialize(int,int,bool,std::string)': overloaded member function not found in 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.h(9): note: see declaration of 'Game::Rendering' 1>c:\users\documents\opengl\game\game\renderer.cpp(35): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(36): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>c:\users\documents\opengl\game\game\renderer.cpp(43): error C2597: illegal reference to non-static member 'Game::Rendering::window' 1>Done building project "Game.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========  
       
      Renderer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Renderer.h" #include "Timer.h" #include <iostream> namespace Game { GLFWwindow* window; /* Initialize the library */ Rendering::Rendering() { mClock = new Clock; } Rendering::~Rendering() { shutdown(); } bool Rendering::initialize(uint width, uint height, bool fullscreen, std::string window_title) { if (!glfwInit()) { return -1; } /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); glViewport(0, 0, (GLsizei)width, (GLsizei)height); glOrtho(0, (GLsizei)width, (GLsizei)height, 0, 1, -1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glfwSwapInterval(1); glEnable(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_TEXTURE_2D); glLoadIdentity(); return true; } bool Rendering::render() { /* Loop until the user closes the window */ if (!glfwWindowShouldClose(window)) return false; /* Render here */ mClock->reset(); glfwPollEvents(); if (mClock->step()) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glfwSwapBuffers(window); mClock->update(); } return true; } void Rendering::shutdown() { glfwDestroyWindow(window); glfwTerminate(); } GLFWwindow* Rendering::getCurrentWindow() { return window; } } Renderer.h
      #pragma once namespace Game { class Clock; class Rendering { public: Rendering(); ~Rendering(); bool initialize(uint width, uint height, bool fullscreen, std::string window_title = "Rendering window"); void shutdown(); bool render(); GLFWwindow* getCurrentWindow(); private: GLFWwindow * window; Clock* mClock; }; } Timer.cpp
      #include <GL/glew.h> #include <GLFW/glfw3.h> #include <time.h> #include "Timer.h" namespace Game { Clock::Clock() : mTicksPerSecond(50), mSkipTics(1000 / mTicksPerSecond), mMaxFrameSkip(10), mLoops(0) { mLastTick = tick(); } Clock::~Clock() { } bool Clock::step() { if (tick() > mLastTick && mLoops < mMaxFrameSkip) return true; return false; } void Clock::reset() { mLoops = 0; } void Clock::update() { mLastTick += mSkipTics; mLoops++; } clock_t Clock::tick() { return clock(); } } TImer.h
      #pragma once #include "Common.h" namespace Game { class Clock { public: Clock(); ~Clock(); void update(); bool step(); void reset(); clock_t tick(); private: uint mTicksPerSecond; ufloat mSkipTics; uint mMaxFrameSkip; uint mLoops; uint mLastTick; }; } Common.h
      #pragma once #include <cstdio> #include <cstdlib> #include <ctime> #include <cstring> #include <cmath> #include <iostream> namespace Game { typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef float ufloat; }  
      Game.zip
    • By Ty Typhoon
      Before read everything i am honest:
      Payment after release you get your percentage lifetime for that project.
       
      Second:
      i dont need your inspirations, ideas, music or designs.
      My head is full with that.
      I need workers who i can trust.
       
       
       
      Please let us talk in discord.
      I got a lot of stuff planned, there is much work to do.
       
      But first my team and me try to start with a small mini game and we need maybe exactly you.
      Planned for more than pc, like ps4, xbox one and mobile - so its very important to us to hopefully welcome a programmer.
       
      The mini game will be part of the planned big game. There will be never before seen guns and gameplay, you will get deeper info if youre a safe part of the team.
       
      I need:
      Programmers
      Animators
      Zbrush pros
       
      Join here please:
      https://discord.gg/YtjE3sV
       
      You find me here:
      Joerg Federmann Composing#2898
       
       
    • By Ty Typhoon
      I like to build my A - Team now.
       
      I need loyal people who can trust and believe in a dream.
      If you got time and no need for direct pay please contact me now.
       
      We cant pay now, you will recieve a lifetime percentage if the released game will give earnings. 
      If I get the best people together for a team, everything should be possible.
       
       
      What i need:
      - Programmer c++
      - Unity / Unreal - we must check whats possible, please share your experience with me.
      - Sculpter, 3D Artist
      - Animator
      - Marketing / Promotion 
       
       
      What i do:
      - Studio Owner
      - Director
      - Recruit exactly you
      - Sounddesign
      - Main theme composing
      - Vocals
      - Game design
      - Gun, swords, shields and weapon design
      - Character, plants and animal design
       
       
      Please dont ask about the Name of the Game, about Designs or Screenshots.
      The game will be defintitly affected about our and your skills if you join the team.
       
       
      Planned for the big Game:
      - 1st person shooter
      - online multiplayer
      - character manipulation
      - complete big open world with like lifetime actions and reactions
      - gunstore with many items to buy
      - many upgrades for players
      - specials like mini games
       
      So if you are interested in joining a team with a nearly complete game idea, contact me now and tell me what you can do.
       
      discord:
      joerg federmann composing#2898
       
       
    • By codelyoko373
      I wasn't sure if this would be the right place for a topic like this so sorry if it isn't.
      I'm currently working on a project for Uni using FreeGLUT to make a simple solar system simulation. I've got to the point where I've implemented all the planets and have used a Scene Graph to link them all together. The issue I'm having with now though is basically the planets and moons orbit correctly at their own orbit speeds.
      I'm not really experienced with using matrices for stuff like this so It's likely why I can't figure out how exactly to get it working. This is where I'm applying the transformation matrices, as well as pushing and popping them. This is within the Render function that every planet including the sun and moons will have and run.
      if (tag != "Sun") { glRotatef(orbitAngle, orbitRotation.X, orbitRotation.Y, orbitRotation.Z); } glPushMatrix(); glTranslatef(position.X, position.Y, position.Z); glRotatef(rotationAngle, rotation.X, rotation.Y, rotation.Z); glScalef(scale.X, scale.Y, scale.Z); glDrawElements(GL_TRIANGLES, mesh->indiceCount, GL_UNSIGNED_SHORT, mesh->indices); if (tag != "Sun") { glPopMatrix(); } The "If(tag != "Sun")" parts are my attempts are getting the planets to orbit correctly though it likely isn't the way I'm meant to be doing it. So I was wondering if someone would be able to help me? As I really don't have an idea on what I would do to get it working. Using the if statement is truthfully the closest I've got to it working but there are still weird effects like the planets orbiting faster then they should depending on the number of planets actually be updated/rendered.
  • Advertisement
  • Advertisement
Sign in to follow this  

C++ What can't a namespace do that a singleton does?

Recommended Posts

Not asking about singletons here (nor advocating). With that clarified:

If we assume someone wants a global + unique object, why isn't a namespace always the preferred approach in C++, over implementing a singleton class?

I've only seen the namespace approach encouraged when there aren't statics being shared. Eg; from Google's style guidelines:

"Rather than creating classes only to group static member functions which do not share static data, use namespaces instead."

But why not have non-member functions that share static data, declared in an unnamed namespace? And why isn't this generally suggested as a better alternative to writing a singleton class in C++?

Edited by Defend

Share this post


Link to post
Share on other sites
Advertisement

This the functional equivalent to having a static variable with a bunch of functions to act on it, which is what you might do in C, and in fact that sort of thing is everywhere in a lot of C codebases.

If anything, the singleton-as-object approach seems marginally better because you can take the type, and therefore pass it into functions as an argument, which lets you more easily refactor later.  Not that either is a terribly great choice.

Share this post


Link to post
Share on other sites

I'm guessing the reason you don't see them is because you don't see many varieties of code.

6 hours ago, Defend said:

I've only seen the namespace approach encouraged when there aren't statics being shared.

This is because static objects are almost always the wrong choice.

That's not referring to static constants, where the compiler will typically use the value directly to simplify the executed code.  Outside of that use, a static value or a global value is nearly always a bug or design defect.  Usually in the handful of cases where they are useful they still are not ideal from a conceptual standpoint, but instead they are an informed decision where the developers decide the advantage in their specific situation is worth the added cognitive effort of adding the shared state.

 

6 hours ago, Defend said:

If we assume someone wants a global + unique object, why isn't a namespace always the preferred approach in C++, over implementing a singleton class?

I've never heard an argument that it wasn't, apart from the fact that globals and shared state tend to be 'evil'.

A globally accessed pointer, or perhaps a restricted access pointer with static linkage, can work fine with this scenario, assuming rules are followed to ensure consistency and access through safe patterns.

Imagine a logging framework providing a bunch of functions that take an optional logger. It can have a pointer to an instance that is the default instance, and that default instance can be swapped out. Then a set of freestanding functions can call that instance.

Thus you have functions that exist on an object allowing you to use your own: mylog->Info("This happened (%d)",thing.id);

And you have the namespace-wrapped versions using the default:  logger::Info("This happened (%d)",thing.id);  That version can use a namespace-constrained pointer, perhaps logger::defaultInstance or something, and the free-floating Info function could pass the call directly on to the defaultInstance version if the pointer is valid.

This in turn makes the tradeoff as mentioned above, the implementer decided the convenience was more important that the extra hidden dependency and the burden of ensuring validity of that hidden dependency.  There must be assurances that the defaultInstance pointer has a sane value and is only swapped out at well-defined times.

7 hours ago, Defend said:

And why isn't this generally suggested as a better alternative to writing a singleton class in C++?

Because you still have a static variable, you still have a shared mutable state.  That should be avoided in general, so it makes for a bad suggestion.  It is less bad that other bad practices, but that doesn't make it a good practice.

Shared mutable state brings with it a host of issues.  It can change behind your back, at any time, for reasons you cannot predict.  The risk can be reduced through human-enforced rules about how and when it is used, what the values must be at certain times, but ultimately there can be no enforcement.  In any non-trivial application this will eventually bite you as someone somewhere changes the value.

In addition to being unable to create more than one, the Singleton pattern also frequently invokes shared mutable state among its assorted issues. Since this isn't supposed to be people bashing on Singletons since we all know the pattern is seriously flawed, that's probably enough there.

Share this post


Link to post
Share on other sites

They're equivalent so it doesn't really matter what you pick. Global functions that share hidden static state of extremely common in C. I guess singletons are more common in C++ as they're OOish. 

Fighting for a better singleton is like hoping to step in a better dog turd though... :D

Share this post


Link to post
Share on other sites

Frob, I too haven't heard an argument that the namespace  approach is worse (or not) than the class approach, but that's because it is practically impossible to find discussion on that particular question at all. Any search (I can find anyway) related to 'how to singleton'  and C++ produces the class approach. Any search with the word 'singleton' at all results in replies all too keen to launch into thoughts on the pattern and/or globals. I don't disagree with them at all, but they drown the focus on any related specific questions such as this one.

Thank you all though for confirming for me that I'm not just missing something obvious in C++. I think Hodgman's suspicion is a good one. Seraph, your comment  was something I hadn't thought of so that feels like I've finally I found some closure! Many thanks. :D 

Share this post


Link to post
Share on other sites
1 hour ago, Defend said:

 

I can think of a way in which using a singleton might be better than a namespace.  Imagine you have a system that you're going to make into a singleton (or namespace).  With a namespace anyone can access anything at any time.  But, now imagine that I want to verify that this system only gets accessed from my main thread.  With a singleton I can have a GetSystem() function that returns the pointer to the system, but I can also add code in there to verify that it's being called from the main thread.   Considering that engines often use singletons for things like a rendering manager, and you also often want that only accessible from a single thread, this would benefit for the singleton pattern.

Share this post


Link to post
Share on other sites

Let's look at what the C++ standard library does, since it was developed by experts over many years and had extreme use testing over decades in real-world scenarios.

The C++ standard library offers singletons (ie. hidden variables of static storage duration accessed only by static member functions like std::locale::global()).

The C++ standard library offers "global" variables (ie. visible variables of static storage duration at namespace level) and associated namespace-level functions (eg. std::cout) to operate on them.

The choice of which is used is based on two criteria.  The first is ease of use.  The standard IO streams are used frequently, are well-known, and there's no point beating about the bush they're "global variables."  Imagine if they were "singletons" instead.

std::cout.get_instance() << "Hello World!" << std::cout::endl();

My guess is printf() using its hidden globals and complete type erasure would still be the only in-use method of output if that were the case.

The second, and probably more important, is the strictly-specified lifetime requirements of the "global variables" in the library.  They need to exist before any user code is called and can not get destroyed until after the last user code has executed.  It turns out that's a little bit easier to do with 1970s-era linkage machinery if you use global variables instead of a C++ function (although not with any modern linkers).

Share this post


Link to post
Share on other sites

As mentioned by @SeraphLance, the type-based implementation allows code to easily opt-out of depending on global state, ignore the "baked-in" multiplicity of the type's implementation, and accept precisely the number of instances it wants as dependencies. You can also do this without classes, but in the absence of an aggregating agent such an interface would be awkward and cumbersome (AOS vs SOA). A class will also allow you to utilize other type-driven language functionality like templates and overload resolution, although I doubt this is actually useful or advantageous when it comes to singletons. Perhaps a singleton class is also easier to refactor in the future, but once again still begs the question of why you'd start with one in the first place.

Otherwise, there's nothing functional that you can do with one approach that you can't do with the other. Likewise, there aren't any pitfalls that you would avoid by using one approach over the other.

It's also worth mentioning that namespaces aren't really relevant to the subject, as they're just tools for labeling and organizing code.

Share this post


Link to post
Share on other sites
21 hours ago, Defend said:

Any search (I can find anyway) related to 'how to singleton'  and C++ produces the class approach

Because that's what a singleton is, by definition -- a class that can only be instantiated once. If you don't have a class then it's not a singleton.

Of course though this is functionally equivalent to a bunch of global functions that share some hidden global state... which pre-dates the word "singleton" by decades. The word "singleton" was invented to specifically describe the pattern of using a class to implement the idea of global functions with hidden global state.

The "singleton" pattern is a very specific way of implementing hidden global state. Not every implementation of hidden global state is a singleton.

Share this post


Link to post
Share on other sites
23 hours ago, Defend said:

Frob, I too haven't heard an argument that the namespace  approach is worse (or not) than the class approach, but that's because it is practically impossible to find discussion on that particular question at all

That is because as others point out, it is syntactic sugar over the same issue.

The issue is mutable shared states.  Mixing mutable shared state in any sufficiently large system is going to face issues with it.  Two threads are going to modify it, or unrelated systems will fight over it, or similar. They introduce hidden coupling, introduce hidden dependencies, complicate or break tools like dependency injection, block extension, and cause many other issues.

The Singleton pattern (which means there can be only one) is that issue and more. In addition to shared mutable state it also creates unrealistic and improbable demands that a single instance is the only one that will ever be wanted, that no code will ever want to replace it, or extend the behavior, or replace the behavior, or provide either alternate or missing behavior, or many other conditions besides.  It is well-covered as being "evil".

 

As for the shared mutable states in C and C++, there are a few that cannot be removed. They are holdovers from decades ago (probably long before you were born) when parallel processing was rare. There are the global streams (stdin, stdout, stderr) and their associated global locale; they have c++ class equivalents but they remain the three streams.  These cannot be designed out of the language nor is there a good way to remove them universally, so they are here to stay.

Some shared mutable states remain because removing them would break too much code, but they have alternates for new code to use. There are strerror(), strtok(), and asctime() functions that all have static buffers internally. There are a few oldcharacter conversion functions between multibyte and wide characters that have shared state, such as wctomb(), mbtowc(), wcsrtomb(), and mbsrtowc(). There are some math functions like the gamma() family and rand() family that rely on internal state.  All of these have alternate versions available that do not rely on shared mutable state.

And a few historically were shared but have been corrected, such as the errno codes from system libraries. In some cases there were rather extensive system library changes to support it, but the change was still made.  

 

There are some on hardware as well.  Floating point control is often fought-over between libraries.  Setting the precision, denormalization options, error handling, and floating point exception resolution are commonly troublesome.  Floating point rounding modes (even/nearest, up, down, and toward zero) can also lead to some 'gotcha' bugs. 

23 hours ago, Defend said:

Thank you all though for confirming for me that I'm not just missing something obvious in C++.

This is common to all languages. You can mask it in various ways, including hiding in namespaces or wrapping on functions that modify hidden variables, but ultimately the underlying problem remains.  

Even in functional languages, where there is tremendous effort made by the language designers to avoid stateful conditions in general, can still occasionally be stung by unintended shared mutable state.

As programs get larger and systems grow they will nearly always have some mutable shared states since there are times when the engineering effort required to avoid it is greater than the project is willing to bear, but that should be weighed as an intentional choice to implement the shared state, and mitigated through policies such as ensuring modification only happens at specific times, or by specific systems, or in specific manners. 

These rules can be put in place in many ways, including having functions that modify a static variable that is kept out of visible scope (such as within an anonymous namespace or as a static variable within a file) but they remain an implementation of a shared mutable state.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement