Need advice/tutorials transitioning to modern OpenGL(3.3+), preferably SDL2-based.

closed account (Ezyq4iN6)
I have been using SDL2 and started tinkering around with OpenGL tutorials on the web a while back. It has come to my attention that most of them are outdated, and that the code I have learned is obsolete. From what I can tell I need to move to OpenGL 3.3+ to be using the "modern" OpenGL code.

I have looked around for modern tutorials, and most ask me to download other libraries (GLEW, GLFW, GLAD, Vulkan, etc.). First, can I not simply do OpenGL with SDL2 like I did in the past? Second, if it is good to get an additional library or libraries, which one(s) is/are considered to be the best to work with? I'm making simple 2D games, experimenting with 3D, and also making small math/physics sims if that helps. Since I know SDL2 and use if for user input and sound I would like to keep working with it, but if someone has a better combo suggestion for OpenGL/Vulkan with input/sound support, then I am open to that.

I will post my current OpenGL code below. If transitioning any of the parts is simple, please let me know and I'll modify them to meet the newer standards. Please keep in mind that I'm new to coding, so my structure probably isn't great. It draws a triangle and a quadrilateral (square) and rotates them both. As my code is too long, I'll post the mygl.cpp in a followup.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

// main.cpp
#include "mygl.hpp"
#include <ctime>
#include <chrono>

int main(int argc, char *argv[])
{

  std::vector <MG_Vertex> triangle =
  {
    {0.0f, 1.0f, 0.0f},
    {-1.0f, -1.0f, 0.0f},
    {1.0f, -1.0f, 0.0f}
  };

  std::vector <MG_Vertex> quadrilateral =
  {
    {-1.0f, 1.0f, 0.0f},
    {1.0f, 1.0f, 0.0f},
    {1.0f, -1.0f, 0.0f},
    {-1.0f, -1.0f, 0.0f}
  };

  double theta = 0.0;
  double fps_max = 60.0;

	try
	{
	  My_GL display;

      while (!display.check_input())
      {
        LARGE_INTEGER frame_start, frame_stop, frame_diff;
        QueryPerformanceCounter(&frame_start);

        std::vector <MG_Vertex> quad1(quadrilateral.size());

        for (unsigned int i = 0; i < quadrilateral.size(); i++)
        {
          quad1[i].x = quadrilateral[i].x * cos(theta) - quadrilateral[i].y * sin(theta);
          quad1[i].y = quadrilateral[i].y * cos(theta) + quadrilateral[i].x * sin(theta);
        }

        display.MG_Clear_Screen();
        display.MG_Reset_Matrix();

	    display.MG_Move_Matrix((const MG_Vertex){-1.5f, 0.0f, -6.0f});
        display.MG_Save_Matrix();
        display.MG_Rotate_Matrix(theta * (180 / M_PI), (const MG_Vertex){0.0f, 0.0f, 1.0f});
        display.MG_Pick_Color(MG_Color::MG_GREEN);
        display.MG_Draw_Triangle(triangle);
        display.MG_Restore_Matrix();

        display.MG_Move_Matrix((const MG_Vertex){3.0f, 0.0f, 0.0f});
        display.MG_Pick_Color(MG_Color::MG_WHITE);
        display.MG_Draw_Quadrilateral(quad1);

        display.MG_Draw_Screen();

        QueryPerformanceCounter(&frame_stop);
        frame_diff.QuadPart = frame_stop.QuadPart - frame_start.QuadPart;
        double frame_adjust = fps_max * (double)frame_diff.QuadPart / 1000000.0;

        theta += (M_PI / 180.0) * frame_adjust;
        if (theta >= (2 * M_PI))
          theta = theta - (2 * M_PI);
      }
	}
	catch (int x)
	{
      if (x == 10)
      {
        std::cout << "Exiting program due to error(s).\n";
        return 0;
      }
	}

	return 0;
}

// mygl.hpp
#ifndef MYGL_HPP
#define MYGL_HPP

#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <vector>

#include <SDL.h>
#include <SDL_opengl.h>

enum MG_Color {MG_BLACK, MG_BLUE, MG_GREEN, MG_CYAN, MG_RED, MG_MAGENTA,
               MG_YELLOW, MG_WHITE, MG_BRIGHT_BLACK, MG_BRIGHT_BLUE,
               MG_BRIGHT_GREEN, MG_BRIGHT_CYAN, MG_BRIGHT_RED,
               MG_BRIGHT_MAGENTA, MG_BRIGHT_YELLOW, MG_BRIGHT_WHITE};

struct MG_Color_Format
{
  GLfloat red;
  GLfloat green;
  GLfloat blue;
  GLfloat alpha;
};

struct MG_Vertex
{
  GLfloat x;
  GLfloat y;
  GLfloat z;
};

constexpr int SCREEN_WIDTH = 800;
constexpr int SCREEN_HEIGHT = 600;
constexpr char WINDOW_TITLE[] = "Very basic SDL2 OpenGL application";

constexpr GLfloat aspect = (GLfloat) SCREEN_WIDTH / (GLfloat) SCREEN_HEIGHT;
constexpr GLdouble fovY = 45.0f;
constexpr GLdouble zNear = 0.1f;
constexpr GLdouble zFar = 100.0f;
constexpr GLdouble fH = tan(fovY / 360 * M_PI) * zNear;
constexpr GLdouble fW = fH * aspect;

constexpr int OPENGL_MAJOR_VERSION = 2;
constexpr int OPENGL_MINOR_VERSION = 1;

constexpr SDL_GLprofile OPENGL_PROFILE = SDL_GLprofile::SDL_GL_CONTEXT_PROFILE_CORE;

constexpr GLclampf BG_CLEAR_RED = 0.33f;
constexpr GLclampf BG_CLEAR_GREEN = 0.33f;
constexpr GLclampf BG_CLEAR_BLUE = 0.33f;
constexpr GLclampf BG_CLEAR_ALPHA = 0.0f;

class My_GL
{
  SDL_Window* displayWindow;
  SDL_GLContext context;
  SDL_Event e;

  MG_Color_Format MG_16[16] =
  {
    {0.0f, 0.0f, 0.0f, 1.0f},     // BLACK
    {0.0f, 0.0f, 0.67f, 1.0f},    // BLUE
    {0.0f, 0.67f, 0.0f, 1.0f},    // GREEN
    {0.0f, 0.67f, 0.67f, 1.0f},   // CYAN
    {0.67f, 0.0f, 0.0f, 1.0f},    // RED
    {0.67f, 0.0f, 0.67f, 1.0f},   // MAGENTA
    {0.67f, 0.67f, 0.0f, 1.0f},   // YELLOW
    {0.67f, 0.67f, 0.67f, 1.0f},  // WHITE
    {0.33f, 0.33f, 0.33f, 1.0f},  // BRIGHT BLACK
    {0.33f, 0.33f, 1.0f, 1.0f},   // BRIGHT BLUE
    {0.33f, 1.0f, 0.33f, 1.0f},   // BRIGHT GREEN
    {0.33f, 1.0f, 1.0f, 1.0f},    // BRIGHT CYAN
    {1.0f, 0.33f, 0.33f, 1.0f},   // BRIGHT RED
    {1.0f, 0.33f, 1.0f, 1.0f},    // BRIGHT MAGENTA
    {1.0f, 1.0f, 0.33f, 1.0f},    // BRIGHT YELLOW
    {1.0f, 1.0f, 1.0f, 1.0f}      // BRIGHT WHITE
  };

  public:
    My_GL();
    ~My_GL();

    void MG_Clear_Screen();
    void MG_Pick_Color(unsigned int color);
    void MG_Draw_Triangle(const std::vector<MG_Vertex> & triangle);
    void MG_Draw_Quadrilateral(const std::vector<MG_Vertex> & quadrilateral);
    void MG_Reset_Matrix();
    void MG_Move_Matrix(MG_Vertex move_matrix);
    void MG_Rotate_Matrix(const GLfloat angle, const MG_Vertex move_matrix);
    void MG_Save_Matrix();
    void MG_Restore_Matrix();
    void MG_Draw_Screen();
    void MG_Delay(unsigned int wait_time);
    bool check_input();
};

#endif
closed account (Ezyq4iN6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// mygl.cpp

#include "mygl.hpp"

My_GL::My_GL()
{
  if (SDL_Init(SDL_INIT_VIDEO) < 0)
  {
    std::cerr << "ERROR: Could not initialize SDL2 because "
              << SDL_GetError() << std::endl;
	  throw 10;
  }
  else
  {
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, OPENGL_PROFILE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR_VERSION);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR_VERSION);

    displayWindow = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED,
                                     SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
                                     SCREEN_HEIGHT, SDL_WINDOW_OPENGL);

    if (displayWindow == nullptr)
    {
      std::cerr << "ERROR: Could not create the window."
                << SDL_GetError() << std::endl;
      throw 10;
    }
    else
    {
      context = SDL_GL_CreateContext(displayWindow);
      if (context == nullptr)
      {
        std::cerr << "ERROR: Cannot create OpenGL context."
                  << SDL_GetError() << std::endl;
        throw 10;
      }
      else
      {
        const unsigned char *version = glGetString(GL_VERSION);

        if (version == nullptr)
        {
          std::cerr << "ERROR: OpenGL configuration issue."
                    << SDL_GetError() << std::endl;
          throw 10;
        }
        else
        {
          SDL_GL_MakeCurrent(displayWindow, context);

          glShadeModel(GL_SMOOTH);
          glClearColor(BG_CLEAR_RED, BG_CLEAR_GREEN, BG_CLEAR_BLUE, BG_CLEAR_ALPHA);
          glClearDepth(1.0f);
          glEnable(GL_DEPTH_TEST);
          glDepthFunc(GL_LEQUAL);
          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
          glViewport(0, 0, (GLsizei) SCREEN_WIDTH, (GLsizei) SCREEN_HEIGHT);
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          glFrustum(-fW, fW, -fH, fH, zNear, zFar);
          glMatrixMode(GL_MODELVIEW);
          glLoadIdentity();
        }
      }
    }
  }
}

My_GL::~My_GL()
{
  SDL_GL_DeleteContext(context);
  SDL_DestroyWindow(displayWindow);
  SDL_Quit();
}

void My_GL::MG_Clear_Screen()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void My_GL::MG_Pick_Color(unsigned int color)
{
  glColor4f(MG_16[color].red, MG_16[color].green,
            MG_16[color].blue, MG_16[color].alpha);
}

void My_GL::MG_Draw_Triangle(const std::vector<MG_Vertex> & triangle)
{
	glBegin(GL_TRIANGLES);
	glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z);
	glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z);
	glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z);
	glEnd();
}

void My_GL::MG_Draw_Quadrilateral(const std::vector<MG_Vertex> & quadrilateral)
{
	glBegin(GL_QUADS);
	glVertex3f(quadrilateral[0].x, quadrilateral[0].y, quadrilateral[0].z);
	glVertex3f(quadrilateral[1].x, quadrilateral[1].y, quadrilateral[1].z);
	glVertex3f(quadrilateral[2].x, quadrilateral[2].y, quadrilateral[2].z);
	glVertex3f(quadrilateral[3].x, quadrilateral[3].y, quadrilateral[3].z);
	glEnd();
}

void My_GL::MG_Reset_Matrix()
{
  glLoadIdentity();
}

void My_GL::MG_Move_Matrix(MG_Vertex move_matrix)
{
  glTranslatef(move_matrix.x, move_matrix.y, move_matrix.z);
}

void My_GL::MG_Save_Matrix()
{
  glPushMatrix();
}

void My_GL::MG_Rotate_Matrix(const GLfloat angle, const MG_Vertex move_matrix)
{
  glRotatef(angle, move_matrix.x, move_matrix.y, move_matrix.z);
}

void My_GL::MG_Restore_Matrix()
{
  glPopMatrix();
}

void My_GL::MG_Draw_Screen()
{
  SDL_GL_SwapWindow(displayWindow);
}

void My_GL::MG_Delay(unsigned int wait_time)
{
  SDL_Delay(wait_time);
}

bool My_GL::check_input()
{

  while (SDL_PollEvent(&e))
  {
    switch(e.type)
    {
      case SDL_QUIT:
        return true;
        break;
      case SDL_KEYDOWN:
        switch(e.key.keysym.sym)
        {
          case SDLK_ESCAPE:
            return true;
            break;
          default:
            break;
        }
      default:
        break;
    }
  }
  return false;
}
@opisop,

If you're doing this just to learn how to make a graphics engine, then what I offer here may not apply.

First, I preface with a self introduction for relevance. I've been there, years ago. I've been a developer since the 80's. Games, game engines, physics engines, audio engines, CAD plugins and video and film post production are among the targets I've addressed in my career. I'm not a particularly high end authority on all matters of these subjects (I leave much to the PhD's from which I take research), but I do know it well and I've followed it a long while.

At least you mentioned Vulkan, as that is the only genuine modern example. At this point OpenGL ES 3.3 is no longer "modern". The line between the old style and the modern style is found where OpenGL ends and Vulkan begins, or where Metal (on Apple) begins, or where DX11 ends and DX12 begins (on Windows/XBox).

OpenGL from 2.0 through 4.x are incremental, though sometimes dramatic, advancements all along the same basic lines (as is all DX prior to 12). The numbering for OpenGL and OpenGL ES differ beyond 2.0, in that some of what is in OpenGL ES 3.3 is from some version of OpenGL 4+.

I mention that because this has always been a moving target, and unless you're making a game engine you probably shoudn't focus upon it.

CAN one use SLD2 and just code to OpenGL (ES)? Sure, but it is no longer really that simple. It's not just that the OpenGL advanced, but the GPU's advanced into such a fractured state that you must inquire from a long list of capabilities to adapt code to that particular GPU implementing OpenGL at whatever version.

This subject, of modern GAME development, breaks down into two basic parts: game engines and game applications. You indicate you're making game applications and hope to directly implement graphics in OpenGL. No matter what version of OpenGL you choose, THAT is the old style of game application development. It is no longer really practical to implement OpenGL in an application.

You'll get lots of argument about that, but such arguments have no choice but to completely ignore what really happened (and is still happening). The "modern" style, embodied in Vulkan, Metal and DX12, is to remove the old "client/server" model of graphics programming. When SGI originally invented the concept (and launched OpenGL), the graphics unit was a physically separate computer connected to the main application computer via a cable. That might as well be over the Internet, though, obviously, that became a card installed in the PC, or a separate GPU chip in a console or phone.

What Vulkan and the other modern API's do now is to bring the GPU much closer to the CPU's memory, so they can share. That was never possible before - we had to ship all data over the bus into the GPU's memory before it could be used. Unfortunately, for application developers, that means an entirely new dimension of theory involving the same basic notions required for threading to coordinate (synchronize) the two engine's access to memory.

For Apple products Vulkan is denied. Instead one must either use Metal, or MoltenVK (which adapts Vulkan code to use Metal on Apple).

You could choose a lowest common denominator, like OpenGL (ES) of a sufficiently high version, but that doesn't actually solve the problem, it forces you into an old style model that does the best it can for 2014. It will not age well beyond 2020. Where you intend to create a game you'll get stuck in a maze of compatibility issues in the graphics code, killing productivity and delaying your ability to release.

All objectives related to efficiency and size evaporate in modern hardware. In theory it may seem that you'd have a smaller, lighter product. In reality that depends ENTIRELY on how good you are at making a game engine. No matter how light an efficient you can make OpenGL ES 3.3 code, Vulkan and other modern API's fundamentally offer so much more efficiency and performance that you OpenGL code may not be able to compete. That's a moving target, and plenty of examples exist which claim to "prove" Vulkan isn't much faster, but that's because Vulkan is new (as are the others), and efficient use of the new style isn't fully implemented.

For game application developers there really is no choice at this point. Some are stubborn about it, but reality will have it's way with us. Graphics API's vary so widely at this point that user expectations simply won't be met going forward.

Beyond that, what is done with even the recent OpenGL (or DX11) API's is rather advanced. Lighting, materials, special effects, post processing - everything is advancing to such a point that users expect features that would absorb the vast majority of your programming work.

Compare that to a modern game engine. You create artwork, fashion materials, select special effects, write some "script" code (in C# or C++ - sometimes simple, could be as advanced as you want), and you have a game application that can target anything from a phone to a console in every API available now, and likely assuming future developments rather rapidly.

There are traps. Some game engines focus on high end graphics and can't really produce something a phone can display without draining the battery in 5 minutes.

Few modern game application development projects use a "code only" engine at this point. SDL2 is one of those. There are many. Games have been released using them, and there's no problem with that, but there's a net loss of productivity.

Physics is it's own issue. In some game engines you can fashion an object, attach a physics component to that in a graphical editor and suddenly it's reacting to physics as you'd expect. You can attach scripts to tune the physics properties.

In a code only approach, however, you have to deal with the fact that the physics engine has it's own models, it's own materials, independent of the rendering engine. They're tied together, sure, but serialization is independent until you unify them. That's already handled in a modern "full featured" game engine.

Seriously, you're on a path that does not end in a game you could sell anytime soon. If you're doing this just to learn the subject of how game engines work, or how to write them - you're in the right area but maybe SDL2 isn't quite modern enough.

I understand. I'm first and foremost a developer/programmer/engineer. I resisted this simple fact for a long while myself.

The main game engines for modern development are among names like Lumberyard, CryEngine, UE4 and Unity (not really in that order). Lumberyard is Amazon's re-write of CryEngine.

Each have very different licenses, an CryEngine does not do mobile (probably never will).

Lumberyard has been retrofitted to target mobile, but the results aren't all that efficient.

UE4 also targets mobile, but you really must limit all modest devices and target high end mobile.

Unity has a specialized light weight rendering option aimed straight at lower end mobile, with other higher end renderers which compete against UE4 well.

Before you commit more time you owe it to yourself to download and experiment with these before you continue. Of the set, Unity is the simplest to learn and offers the widest target audience. While it focuses on C# script, you can (and I do) write C++ as native modules. There's even an open source tool to virtually eliminate all C#, writing almost entirely in C++ (not my approach, I just write native modules).

I would recommend starting with Unity, then check into UE4. UE4's editor requires a higher end GPU whereas Unity can work reasonably on an integrated GPU.

If you goal is to make a game or games, you really don't want to use the old style approach of a "code only" engine solution. I don't know of any that are as "current" with modern API's.

If you're more focused on learning how to write game engines then I'm entirely off course here.





Modern OpenGL has a different setup than the "immediate mode" deprecated OpenGL. It would be best to first program the "hello world" of OpenGL 3.3+, which in itself will be a sizable challenge for a first-time learner. And once you understand the basics of how that pipeline works, then try to re-make your existing program in modern OpenGL.

I personally haven't used SDL, but here's what I found just by searchengining 'sdl with opengl 4':
https://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php
https://bcmpinc.wordpress.com/2015/08/18/creating-an-opengl-4-5-context-using-sdl2-and-glad/

Seems to be close to what you're looking for.

Note that I highly suggest this site for modern OpenGL tutorials: http://www.opengl-tutorial.org/

Yes, it uses GLFW as its windowing library in the first tutorial, but you can skip this if you can get it set up with SDL instead. After the first tutorial, it's pretty much windowing-library-agnostic, and only focuses on the OpenGL part of the code.

Tutorial #2 is the "hello world" (first triangle) tutorial.
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/

________________________________________________

Edit: And also, having reading part of Niccolo's post, just want to say that some good points were made.

I'll paste again an important sentence:
Seriously, you're on a path that does not end in a game you could sell anytime soon.

I want to stress this. It's not to discourage you from programming this, it's just that if your end goal is having fun making an actual game, and not an engine, you need to realize that programming the actual gameplay and logic of the game is hard enough by itself. By also trying to make all the physics and graphics-rendering yourself, you're looking at potentially years before you have something that looks decent.

If you want to trudge through all that and learn something from it, then by all means do that. But if you have actual gameplay ideas that you're excited about and want to bring to life, I would first try to see if you can make it in an existing game engine.
Last edited on
closed account (Ezyq4iN6)
@Niccolo
Thanks for your long, in-depth answer. I'm not looking to write game engines, because I can accept that it would take an army of elite programmers to make something competitive these. I just want to be able to create simple games or simulations of math or physics models and have a graphic interface for them. After all, I am only one person working alone.

Unity looks great and really appeals to me, but my efforts to download and experiment with it over the past years has been very frustrating. I was never able to complete even the most basic tutorials for it, and finally gave up and switched to pure coding. Are their any tutorials that you would recommend, and has it gotten any easier? Is it meant only for people with lots of programming experience and/or advanced engineering/programming degrees?

I have read about Vulkan, though I didn't realize that it was already being switched to from OpenGL. It looks interesting, but very difficult. I think your advice about using an existing engine would be the best choice if I can find one that I can figure out. I know C# some, but am more familiar with C/C++, so I'm glad you said that Unity can support that. Maybe I'll give it another try.

@Ganado
Thanks for the links. I'll check out some of those tutorials on the second link, since the first one only seems to have that one tutorial and the second one has a big collection of them. I'm glad to head that the OpenGL code should be able to be used with SDL. Not that I wouldn't switch to GLFW, I just like some of the non-graphics abilities of SDL, that's all.
@opisop,

Unity has become a lot easier. There are much better walk thru's and "game in 2 hour" tutorials that can get you rolling fairly quickly. Start with just a rolling ball on a floor, then add a few cubes and learn to shoot the ball from the camera to knock the blocks around. After that, you're in....

Your goal aligned with something I needed recently. I've been volunteering to teach robotics programming to a club at the local high school where my son attended (just graduated). I'll be teaching again through the summer and next year.

In order to give the students a sense of the contest they were building to compete in, it's strategy and the suitability of their designs, I decided to make a game in Unity that simulated the bots and the contest (running bots around in a 12ft square "field", shooting 3 inch "ping pong" balls and lifting plastic objects.

For this, Unity had to be able to simulate the physics of the robot sufficiently to represent the bot they would build, and the strategy of playing the game in under 2 minute scrimmages.

I got it to work in about 3 weeks. I had already had the kids design the bot's in CAD, so I transported those CAD models into something Unity could read, textured it in metal and plastic, applied physics relationships for the arm/wheels/motor drive, took some time to get the physics of the 2 ounce balls right, fashioned a few "tricks" to get the grab of the robot's claw right, and the kids were playing matches and testing their design that month.

The app runs on Windows/Linux/MAC/iOS/Android.

As to Vulkan's difficulty - it is a bit more than what it takes to write C++ using threads, but loosely related to the same notions with lots of little details.

Since there's a counterpart of similar difficulty and density on DX12 and Metal, it becomes a curious study best left to the game engine designers, unless one intends to become one.

Bottom line, you could have 6 games running in less time than it might take to get one in SDL2, where multiple target platforms is of any interest.

We didn't even get to the issues of input (touch/mouse/joystick/gamepad/gyro/accelorometer/VR headset).

Last edited on
closed account (Ezyq4iN6)
@opisop

I'm glad to hear that about Unity. Even though I have some programming experience, I guess I'm not used to working in an environment with so many different options. I get lost easily, which is one of the reasons I had to stop using Visual Studio in exchange for using IDE's with simple interfaces, like Code::Blocks, and even simply notepad and compiling it in a console window.

Robotics is great. I took some courses in that and really enjoyed it. I never got to use CAD though, but it's probably just as well because I can imagine you need to be an artist to design all those intricate models. Speaking of which, do you need a high-degree of art skills to be able to use Unity? I have heard some programmers joking about it being a game design program tailored to artists.

Also, it sounds like you had to program your own physics into Unity. Does it not come with a lot of options for physics?

Do you have to tweak it a lot to get it to run on multiple platforms, or is it as easy as selecting the platform to output for?

The most that I have programmed (with SDL) so far are very simply games like pong, breakout, minesweeper, tetris, and space invaders, so I'd be even happy to create something of that level with Unity.
Well, first I have a frank response about IDE's. I'll try to attenuate. Unity installs Visual Studio on Windows to write C# code. I can't imagine working outside of an IDE, and I come from a time when there were no IDE's. Vi and makefiles on UNIX in '81, or worse, line oriented BASIC and a really manual approach to assembler/machine code on 6502 based "personal" computers in the late 70's (there were no assemblers for some of those machines, we actually coded the numeric instructions). IDE's save a lot of time. I'm not sure I can relate to being lost in Visual Studio, but then I've used it since before Windows '95 (and a lot of others along the way). All of us rebelled at VS 2010 (it was a shock over the change). You really don't need to know all of it (I don't). I use the project explorer, various debug windows, and, of course, project properties, all the time. Much of the other stuff is of little interest to me, but the integrated debugger, the code analyzer, the project definition and the multi-monitor support is key to my own work. Then, too, I'm accustomed to applications that range from AutoCAD to 3DS Max, Photoshop and Illustrator (the latter is what most people actually need to use but don't really know exists), Fusion, Inventor....I lose track of how many. At any one moment I may be running 3 or 4 operating systems at once (in virtual machines). I realize it may sound rude, but I just can't relate here, so I have little to offer to but to explore and reorient.

CAD, especially for engineering, isn't really an artistic act any more than drafting or graphing with compass and straight edge would be. In the case of these robots the parts are from a standardized set of metal components, and the manufacturer offers a library of pre-built "artwork" sufficiently detailed to 3D print the parts or otherwise fabricate them if one had metal fabrication equipment (one of my long standing clients is a sheet metal/machining manufacturer).

Unity doesn't require art skills so much, at least by itself. Factually, the editor is built with the game engine. You are literally running a game built as a game editor (this has become fairly standard in recent years, true of UE4 for example). If you can play a game, you can use the editor. It doesn't draw 3D art (beyond the standard primitives like boxes, spheres, etc). For models or artwork beyond simple primitives one uses DCC tools (digital content creation) like 3DS Max, Blender, Maya, etc.

One could argue that all game engines seek to give artists the power to turn artwork into games, so I suppose the viewpoint is valid. From a more practical perspective, however, that's exactly what you want - to reduce the work of detailed linear algebra into something conceptually related to loading a robot or character and fitting it to the game. That's true of "code only" solutions to a significant extent anyway. Ogre3D, which is a rendering engine that can be a game engine when fitted with physics and other components, is focused on loading and texturing models.

In any 3D game, part of the real work is the materials. Materials are key to the look of the game, from highlights and simple textures to glass or water, smoke or fire, materials are key. They're also an entire study, somewhat steeped in programming shaders for the GPU in a C like language (depending on the API). A game engine can reduce that work to selecting a texture and setting values in a PBR style (physically based rendering).

If a programmer approaches the subject of game development without acknowledging the issues of creating realistic materials, the result will be an 80's or 90's style "pastel" color and look. For anything this side of the 21st century it takes more knowledge of image processing and materials theory. For example, are you familiar with phong and blinn shading? These are old, simple techniques, and the very beginning of shader theory, but it works its way into reflections, refractions, translucence, and a wide range of techniques used to "paint" the look of the product. Without it the result is a bit like comparing a drawing made with crayons or colored pencils to that of an oil painting. So, indeed, modern game development usually involves some awareness of these concepts so as to give one control. Where that technical work has been done for you (saving YEARS of development study and time), I suppose a programmer would think it is just artists' work and not programming. They just say that as if it were a bad thing.

Put another way, the more you know about modeling tools and photoshop, about textures shaders, the better the look of the product.

Unity uses the PhysX engine. It exposes that in a pre-defined manner, simplifying the work involved. A simple sphere will not react to physics by just creating a sphere. To make it react as a physics object, one attaches a "rigid body" and a "collider" to the sphere. Now it can react to being hit, and will move according gravity and collision with other objects. The addition of those two physics attachments is as simple as a few selections in the editor. Then, one adjusts the "bounciness" of the material, the mass of the object and it's surface friction. I had the issue of taking what is basically a 3 inch ping pong ball which bounces on a hard floor nearly endlessly (like a ping pong ball does), but make it react to the padded foam floor of the field. That took a bit of tweaking, and to make it realistic I conducted experiments with the actual ball and those foam tiles to get the bounce effect to match closely, improving the fidelity of the physics simulation. You don't have to know PhysX to use physics in Unity, they expose it rather simply. I choose, however, to run the PhysX engine from source in C++, which is much more work, but gives me "the rest of the engine's features Unity doesn't expose (and most don't really need).

For the most part targeting other platforms is fairly simple (almost just a build and test). However, there are some minor adjustments one makes to fit to widely differing platforms, from resolution to user interface concepts. The hardest (longest) part of that effort is to install the tools for each platform. To build for iOS you need a MAC. To build for Android you need the Android SDK and NDK installed. Unity as some automated setup tools (makes Windows targets trivial), but configuring for Android building is it's own thing anyway. If you know how to build for Android, you know it's a bit of work even with Android Studio (especially the NDK).

To learn Unity, stick with the host OS installation for a while until you know Unity well enough to decide if you're going to continue before spending the effort to build for other platforms.

I've not made 2D games in decades, so I can't really say all that much, but there's a 2D specialization of physics and modeling in Unity aimed squarely at 2D game work.
closed account (Ezyq4iN6)
Thank you for taking so much time to explain all of these things to me. I must admit I am finding that my computer classes weren't as strong as most, so I sometimes seem to have strange ways of doing things. Most of the programs I have written are only comprised of simple classes, functions, and basic math. Concepts like version control, unit testing, algorithms and data structures, etc. are new to me. So I can only guess that for what I was programming, simpler IDEs like Dev-C++ and Code::Blocks were easier for me to understand and get up and running. VS and Eclipse always seemed much more daunting.

After reading the rest of what you have written, I'm going to have to do some serious thinking before continuing with game development. I had a lot of ideas about what I wanted to do (what person doesn't), but from what it sounds like I probably need to get a lot more experience and read a lot more before going forward. I'm sure Unity is a great program to use, but from what I have seen, it's a bit above my pay grade for right now.
Topic archived. No new replies allowed.