Giter VIP home page Giter VIP logo

sparky's Introduction

Sparky Game Engine

Sparky

Build status

Sparky is a cross-platform, high performance game engine currently in development. This readme will be updated with more info eventually.

Join the Slack channel (#sparky)

sparky's People

Contributors

crisspl avatar ilohama avatar jannisj1 avatar klukule avatar tgsm avatar thechernoproj avatar tstr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sparky's Issues

Order of Transformation stack

I was using the engine to make a demo when I came accross a problem.
I had a map object that contained tile objects that each could contain a single entity.
I then used the transformation stack in map to position the tiles and in tiles to position the entity.

However when I wanted to rotate the entity on the spot I was unable to since it rotated around the origin point, aka the point the sprite would be in before the translation of the map and the tile.

A fix for this is changing

                m_TransformationStack.push_back(m_TransformationStack.back() * matrix);

to

                m_TransformationStack.push_back(matrix * m_TransformationStack.back());

in renderer2d.h

Multiple post effects passes

At the moment, only the last PostEffectsPass in PostEffects' m_Passes is actually rendered.
To fix this you could change this:

target->Bind();
API::SetActiveTexture(GL_TEXTURE0);
source->GetTexture()->Bind();

quad->Bind();
indices->Bind();

for (PostEffectsPass* pass : m_Passes)
    pass->RenderPass(target);

indices->Unbind();
quad->Unbind();

to this:

target->Bind();
API::SetActiveTexture(GL_TEXTURE0);
source->GetTexture()->Bind();

quad->Bind();
indices->Bind();

m_Passes[0]->RenderPass(target);

target->GetTexture()->Bind();

for (uint i = 1; i < m_Passes.size(); i++)
    m_Passes[i]->RenderPass(target);

indices->Unbind();
quad->Unbind();

Can not re-enable the shader program.

To re-enable the shader you would have to re create the shader again which I believe is bad and hurts CPU and GPU performance.

EDIT: I should mention I copied the code directly from here. "Stealing" as you stated.

bgfx as rendering api

Have you heard of bgfx lib ?
It provides opengl, opengl es, webgl, directx (9, 11, 12) and metal support.
I thinck it would be awesome to use this lib in sparky engine
Check out examples here

Linux user!

Hello!
I'm a Elementary Os freya(Ubuntu 14.04) user and I'd like to contribute to sparky but I cant since I dont have the possibility to load the engine into CodeBlocks(and VS does not work on Linux).My point is that many users may have different OSs than Windows and we cant use sparky.This needs to be fixed.
So I think the best option would be to make sparky work with CodeBlocks because that ide works cross platform.

ImageLoad free dib data

We create a FIBITMAP *dib pointer and check if there is data but we do not free the data through a delete dib. I don't know much about FreeImage but i don't thing our BYTE* result is pointing to the same data.

Fragment shader color.

Looking at it with a fresh eye I realised why it is done the way it is, so you can mark this closed. (don't code or analize code when you are tired :) )

I've heared that the if(...) is very costly in the fragment shaderand now you have this.

if (fs_in.tid > 0.0)
{
int tid = int(fs_in.tid - 0.5);
texColor = texture(textures[tid], fs_in.uv);
}
color = texColor * intensity;

You should have a static white color as an unsigned int as the default color attribute and if the Sprite is not textured you would change it in the submit method, else it is not needed because you would basically multiply the textured color with 1.

So you could have s'thing like this in the shader instead of the if(...)

color = fs_in.color * texColor * intensity;

Raw string literals should be used

In C++11 we have raw string literals, I think it would be better to use them in shader factory. You don't need to put quotes and the newline character at every line. Example:
const char * mystr = R"ESCAPE_SEQUENCE(
This string has every
newline and spacing
in it.
)ESCAPE_SEQUENCE";

Note, that an escape sequence is not required, this is also just fine:
R"( ... )";

Mat4 columns

Shouldn't this

vec4 getColumn(int index)
        {
            index *= 4;
            return vec4(elements[index], elements[index + 1], elements[index + 2], elements[index + 3]);
        }

be this instead?

vec4 getColumn(int index)
        {
            return columns[index];
        }

(mat4.h)

Group needs a destructor!

Renderable2Ds that are added to layer are deleted in the destructor of layer but those who are added to groups are not deleted by any other function. I think it would be bad not to delete them. ;)

Direct3D not working!

Sparky fails to init Direct3D:
"Ausnahme ausgelöst bei 0x0FA11D42 (SPCore.dll) in Sandbox.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000."
(sorry for having vs is german)
This happens in DXContext.cpp. The D3D11CreateDevice method does not create a device, so when the ID3D11Device* dev pointer is used I get a NullpointerException (or whatever you call this in c++).

Texture glitch.

Adding sprite and label in same layer causes sprite to glitch. I didn't saw this bug on your videos, but I think it's not problem only for me. I tried on your code too.

glitch

OpenAL

Hey, I had a probleme with sparky..... At start, I've tried to take your OpenAL.dll from your github (the good one) and just run sparky (audio). I had an error (code : 0xc00007b). Then I get to the OpenAL website and I installed the SDK (like you). It fixed the problem but i'm worried about people that use Sparky... I think we have to test Sparky on multiple desktops without this OpenAL SDK installed to confirm that issue.

More over, I insist that i've the same code as you, your Sparky Engine like tuto's one.
To be sure, I pulled the code from commit Ep.23, compiled it and run it.... same error like before.

Have a nice dayy~~

Input handling should be mindful of a key's previous state

The engine only shows us the current state of a key on a given frame. That is, on this frame is a key held or idle. This is limiting for cases where the previous state of a key also needs to be taken into account. For instance, for a semi automatic weapon in a game where the weapon shoots once every time you click the left mouse button you would need to have code like this to get it to work:

bool ready = true;
/*...*/
if(window.isMouseButtonPressed(GLFW_MOUSE_BUTTON_1)){
    if(ready){
        weapon.fire();
        ready = false;
    }
}else{
    ready = true;
}

We need a housekeeping bool to ensure our weapon fires on only the first frame a key is pressed. This is tedious to do for every case where we need this behavior and is prone to bugs. We should instead compare the previous and current states of each key/mouse button to see if a key has been pressed, held, released, or idle on the given frame and store that state for every key. So the code above turns into:

if(window.getMouseButtonState(GLFW_MOUSE_BUTTON_1) == BUTTON_PRESSED){
    weapon.fire();
}

Another case where we want something like an ability that powers up as a key is held and then activated when the key is released would go from this:

bool held = false;
/*...*/
if(window.isKeyPressed(GLFW_KEY_DOWN)){
    held = true;
    power.charge(dt);
}else if(held){
    power.activate();
    power.reset();
    held = false;
}

To this:

if(window.getKeyState(GLFW_KEY_DOWN) == KEY_HELD){
    power.charge(dt);
}else if(window.getKeyState(GLFW_KEY_DOWN) == KEY_RELEASED)){
    power.activate();
    power.reset();
}

Batch renderer submit optimization

So the batch renderer's submit(...) function takes a lot of time, mainly because of the matrix multiplications. With a little trick I was able to cut down the time (60% to 50%). Here's what I did:

Maths::vec3f _tpos = *m_TransformationBack * position;

m_Buffer->Position = _tpos;
m_Buffer->TexCoord = texCoords[0];
m_Buffer->TexID = ts;
m_Buffer->Color = c;
m_Buffer++;

_tpos.y += size.y;

m_Buffer->Position = _tpos;
m_Buffer->TexCoord = texCoords[1];
m_Buffer->TexID = ts;
m_Buffer->Color = c;
m_Buffer++;

_tpos.x += size.x;

m_Buffer->Position = _tpos;
m_Buffer->TexCoord = texCoords[2];
m_Buffer->TexID = ts;
m_Buffer->Color = c;
m_Buffer++;

_tpos.y -= size.y;

m_Buffer->Position = _tpos;
m_Buffer->TexCoord = texCoords[3];
m_Buffer->TexID = ts;
m_Buffer->Color = c;
m_Buffer++;

So I'm saving the position, multyply it only once with the matrix, and then keep working with that. Because I don't have a very good computer, without this optimization I got around 3025 FPS. With this I've got almost 3300.

Unable to render 2 or more labels in the same layer

If I try to render 2 or more labels with different fonts in the same layer just one gets rendered properly, the other is full of random letters, like if the renderer was trying to render both with just one texture.

Again, it only happens if you want to render more than one label in the same layer and with different fonts, if you use the same fonts, all works fine.

That's all I know :)

It gives me en error.

When I want to show the Debug Menu, its is not showing!
Maybe its just me, or its an bug!

WebGL Mac Texture Issues

Sparky WebGL on Mac OS X has fatal issues with textures on all browsers. This results in a black screen on both Safari and Firefox, and severe artifacting as well as colour problems on Chrome.

Whilst Safari and Chrome report no issues in the Javascript console, Firefox logs "Error: WebGL: texImage2D: width must be >= 0". Investigate.

Default shader doesn't work with my AMD card

After about an hour of changing the shader with eatplayhate, we finally found out that my good old AMD Radeon 6670 HD doesn't work if you try to get the texture from the array if you use a variable as the index.
So we had to use the shader you wrote for SPARKY_WEB (which has a lot of if statements to check which texture to use) and add +0.5f on lines 154,163 and 210 in BatchRenderer2D.

BatchRenderer2D Optimization

As we saw in one of your livestream, when you render your sprites with a max texture per drawcall of 2 you had an insane 93 drawcalls while you only had a total of 8 different textures.
The reason is that your sprites are not sorted.
So this advice will work both with static and dynamic buffer renderers, batched or unbatched.
The idea is this:

When you submit a renderable via void submit(const Renderable2D* renderable), you don't do anything except populate a vector with the info of that submit (meaning you save a pointer to the renderable and a copy of the transformation matrix).

Then when you flush, that is where you do all the work.
But before you do, the first thing is you need to sort the vector.
Here you just need to sort by the texture id. that way, whatever order you submit your sprites in, if you have a max texture of 2 and 8 textures, you will have 4 draw calls max.

This becomes even more important when you can have different shaders per renderable. you then sort first by shader, second by material then by mesh.

Then you need to track the state of the opengl pipeline and you only call glUseProgram when you change shader, then for each shader, you only set the material uniforms when you change material etc. All that is quite simple to implement and is necessary to drastically reduce the number of drawcalls.

Oh and in general you shouldn't unbind things unless you absolutely know it is necessary.
This is to avoid things like:
glBind (something)
glBind(0) --> unnecessary api call
glBind(somethingElse)

Lua support?

Hey!

As we all know Lua is a great scripting language and since the project it is made in C++ the dev time could take longer than in Java for example.So I think Lua will come in handy!

Edit 1: Will we ever see android support ?
Edit 2: Cmake for non windows users?

m_Buffers in vertexarray never filled

Files: vertexarray.h and vertexarray.cpp

Seems like std::vector<Buffer*> m_Buffers; is defined, however there is no logic that adds buffers to the vector. Therefore making the loop in VertexArray::~VertexArray() and std::vector<Buffer*>vector unnecessary.

optimization of batch renderer

Hi!
I don't know if this is the correct section or if I should post this under pull request. So forgive me if it's in the wrong section.

I'm looking the youtube videos therefore I'm a little behind. So delete this comment if it's out of date.

I saw that your batch renderer is calculating vertex postions every submit. This is quite inefficient.

My suggestion is a rectangle class/struct that precalculate all vertecies on the constructor call of a sprite. This works as long as the size of a sprite doesn't change. I was able to achieve about a 8-10% higher fps rate then before.

My example:
Rect header (I put it into math):

struct Rect
{
    vec3 topLeftPositon;
    vec3 topRightPositon;
    vec3 bottomLeftPositon;
    vec3 bottomRightPositon;

    enum Alignment
    {
        BottomLeft,
        BottomRight,
        TopLeft,
        TopRight,
        CenteredLeft,
        CenteredRight,
        BottomCentered,
        TopCentered,
        Centered
    };

    Rect(Alignment alignment = Alignment::BottomLeft);
    Rect(float x, float y, float width, float height, Alignment alignment = Alignment::BottomLeft);

    inline const vec3& GetTopLeftPositon() const { return topLeftPositon; }
    inline const vec3& GetTopRightPositon() const { return topRightPositon; }
    inline const vec3& GetBottomLeftPositon() const { return bottomLeftPositon; }
    inline const vec3& GetBottomRightPositon() const { return bottomRightPositon; }
};

Rect cpp implementation:

Rect::Rect(Alignment alignment)
    : Rect(1, 1, 1, 1, alignment)
{

}
Rect::Rect(float x, float y, float width, float height, Alignment alignment)
{
    float halfWidth = 0.5f + width;
    float halfHeight = 0.5f * height;

    switch (alignment)
    {
    case Alignment::BottomLeft:
        topLeftPositon = vec3(x, y + height, 0);
        topRightPositon = vec3(x + width, y + height, 0);
        bottomLeftPositon = vec3(x, y, 0);
        bottomRightPositon = vec3(x + width, y, 0);
        break;
    case Alignment::BottomCentered:
        topLeftPositon = vec3(x - halfWidth, y + height, 0);
        topRightPositon = vec3(x + halfWidth, y + height, 0);
        bottomLeftPositon = vec3(x - halfWidth, y, 0);
        bottomRightPositon = vec3(x + halfWidth, y, 0);
        break;
    case Alignment::BottomRight:
        topLeftPositon = vec3(x - width, y + height, 0);
        topRightPositon = vec3(x, y + height, 0);
        bottomLeftPositon = vec3(x - width, y, 0);
        bottomRightPositon = vec3(x, y, 0);
        break;
    case Alignment::CenteredLeft:
        topLeftPositon = vec3(x, y + halfHeight, 0);
        topRightPositon = vec3(x + width, y + halfHeight, 0);
        bottomLeftPositon = vec3(x, y - halfHeight, 0);
        bottomRightPositon = vec3(x + width, y - halfHeight, 0);
        break;
    case Alignment::Centered:
        topLeftPositon = vec3(x - halfWidth, y + halfHeight, 0);
        topRightPositon = vec3(x + halfWidth, y + halfHeight, 0);
        bottomLeftPositon = vec3(x - halfWidth, y - halfHeight, 0);
        bottomRightPositon = vec3(x + halfWidth, y - halfHeight, 0);
        break;
    case Alignment::CenteredRight:
        topLeftPositon = vec3(x - width, y + halfHeight, 0);
        topRightPositon = vec3(x, y + halfHeight, 0);
        bottomLeftPositon = vec3(x - width, y - halfHeight, 0);
        bottomRightPositon = vec3(x, y - halfHeight, 0);
        break;
    case Alignment::TopLeft:
        topLeftPositon = vec3(x, y, 0);
        topRightPositon = vec3(x + width, y, 0);
        bottomLeftPositon = vec3(x, y - height, 0);
        bottomRightPositon = vec3(x + width, y - height, 0);
        break;
    case Alignment::TopCentered:
        topLeftPositon = vec3(x - halfWidth, y, 0);
        topRightPositon = vec3(x + halfWidth, y, 0);
        bottomLeftPositon = vec3(x - halfWidth, y - height, 0);
        bottomRightPositon = vec3(x + halfWidth, y - height, 0);
        break;
    case Alignment::TopRight:
        topLeftPositon = vec3(x - width, y, 0);
        topRightPositon = vec3(x, y, 0);
        bottomLeftPositon = vec3(x - width, y - height, 0);
        bottomRightPositon = vec3(x, y - height, 0);
        break;
    default:
        topLeftPositon = vec3(x, y + height, 0);
        topRightPositon = vec3(x + width, y + height, 0);
        bottomLeftPositon = vec3(x, y, 0);
        bottomRightPositon = vec3(x + width, y, 0);
        break;
    }
}

A sprite has a rect member and in the constructor this rect is generated.
So the batch renderer submit function looks like this (I commented out the old code):

void BatchRenderer2D::Submit(const Renderable2D* renderable)
{
    //const vec3& position = renderable->GetPosition();
    //const vec2& size = renderable->GetSize();
    const vec4& color = renderable->GetColor();

    int r = color.x * 255.0f;
    int g = color.y * 255.0f;
    int b = color.z * 255.0f;
    int a = color.w * 255.0f;
    unsigned int col = a << 24 | b << 16 | g << 8 | r;

    const Rect* rect = ((Sprite*)renderable)->GetRect();

    //buffer->vertex = position;
    buffer->vertex = rect->GetBottomLeftPositon();
    buffer->color = col;
    buffer++;

    //buffer->vertex = vec3(position.x, position.y + size.y, position.z);
    buffer->vertex = rect->GetTopLeftPositon();
    buffer->color = col;
    buffer++;

    //buffer->vertex = vec3(position.x + size.x, position.y + size.y, position.z);
    buffer->vertex = rect->GetTopRightPositon();
    buffer->color = col;
    buffer++;

    //buffer->vertex = vec3(position.x + size.x, position.y, position.z);
    buffer->vertex = rect->GetBottomRightPositon();
    buffer->color = col;
    buffer++;

    indexCount += 6;
}

I hope this is useful for you.

Change GLFW window resize callback

Hello,

inside Window::init() you call glfwSetWindowSizeCallback to use glViewport in the callback.

In GLFW's documentation they say why you shouldn't use that function:

"Do not pass the window size to glViewport or other pixel-based OpenGL calls. The window size is in screen coordinates, not pixels. Use the framebuffer size, which is in pixels, for pixel-based calls."

So you should change glfwSetWindowSizeCallback to glfwSetFramebufferSizeCallback, which will be correct.

Rotate matrix is incorrect

Hi,

There is incorrect main diagonal in rotate matrix. You matrix

        float r = toRadians(angle);
        float c = cos(r);
        float s = sin(r);
        float omc = 1.0f - c;

        float x = axis.x;
        float y = axis.y;
        float z = axis.z;

        result.elements[0 + 0 * 4] = x * omc + c;
        result.elements[1 + 0 * 4] = y * x * omc + z * s;
        result.elements[2 + 0 * 4] = x * z * omc - y * s;

        result.elements[0 + 1 * 4] = x * y * omc - z * s;
        result.elements[1 + 1 * 4] = y * omc + c;
        result.elements[2 + 1 * 4] = y * z * omc + x * s;

        result.elements[0 + 2 * 4] = x * z * omc + y * s;
        result.elements[1 + 2 * 4] = y * z * omc - x * s;
        result.elements[2 + 2 * 4] = z * omc + c;

And could be implemented as marix (see below)

incorrect_rotate_matrix

So in main diagonal you should multiply (1 - cos a) on sqaure of the coordinate of the vector.. See below pic.

correct_rotate_matrix

Probably fix it (w/o optimization and etc.)

        result.elements[0 + 0 * 4] = x * x * omc + c; // fixed
        result.elements[1 + 0 * 4] = y * x * omc + z * s;
        result.elements[2 + 0 * 4] = x * z * omc - y * s;

        result.elements[0 + 1 * 4] = x * y * omc - z * s;
        result.elements[1 + 1 * 4] = y * y * omc + c; // fixed
        result.elements[2 + 1 * 4] = y * z * omc + x * s;

        result.elements[0 + 2 * 4] = x * z * omc + y * s;
        result.elements[1 + 2 * 4] = y * z * omc - x * s;
        result.elements[2 + 2 * 4] = z * z * omc + c; // fixed

Failed to create GLFW Window

i watched the EP1 video and did exactly the same and i checked my code 3 times

and iam getting this error (in the cmd) "Failed to create GLFW Window"

here's my windows.h

pragma once

include

include <GLFW/glfw3.h>

namespace DFQEngine {
namespace graphics {

    class Window
    {
    private:
        const char *m_Title;
        int m_Width, m_Height;
        GLFWwindow *m_Window;
        bool m_Closed;
    public:
        Window(const char *name, int width, int height);
        ~Window();
        bool closed() const;
        void update() const;
    private:
        bool init();
    };

}

}

and here's my windows.cpp

include "window.h"

namespace DFQEngine { namespace graphics {

Window::Window(const char *title, int width, int height)
{
    m_Title = title;
    m_Width = width;
    m_Height = height;
    if (!init())
        glfwTerminate();
}

Window::~Window()
{
    glfwTerminate();
}

bool Window::init()
{
    if (!glfwInit())
    {
        std::cout << "Failed to initialize GLFW!" << std::endl;
        return false;
    }
    m_Window = glfwCreateWindow(m_Width, m_Height, m_Title, NULL, NULL);
    if (!m_Window)
    {
        std::cout << "Failed to create GLFW window!" << std::endl;
        return false;
    }
    glfwMakeContextCurrent(m_Window);
    return true;
}

bool Window::closed() const
{
    return glfwWindowShouldClose(m_Window) == 1;
}

void Window::update() const
{
    glfwPollEvents();
    glfwSwapBuffers(m_Window);
}

} }

and my main.cpp

include

include "src/graphics/window.h"

int main()
{
using namespace DFQEngine;
using namespace graphics;

Window test("$engine", 800, 600);

while (!test.closed())
{
    test.update();
}

system("PAUSE");
return 0;

}

Assert error when closing app during lesson 11 : Layers

I have everything working fine with no compile errors, but when I close the app with the 'x' button in the top right corner I will get an Assertion Error and the break will be at the delete mShader; statement in the Layer Destructor. Any clues as to why I might be getting this?

Mat4 Multiplication Bug

Mat4 multiplication doesn't work correctly. Change to:

    mat4& mat4::multiply(const mat4& other)
    {
        float data[16];
        for (int y = 0; y < 4; y++)
        {
            for (int x = 0; x < 4; x++)
            {
                float sum = 0.0f;
                for (int e = 0; e < 4; e++)
                {
                    sum += elements[x + e * 4] * other.elements[e + y * 4];
                }
                data[x + y * 4] = sum;
            }
        }

        memcpy(elements, data, 16 * 4);

        return *this;
    }

Delete textures

Please put
glDeleteTextures(1, &m_TID);
into the the destructor of Texture.
Thank you.

Double include of Batch Rendered 2D

Including batchrenderer2d.h 2 times in main.cpp on line 11 and 12

#include "src/graphics/batchrenderer2d.h"
#include "src/graphics/batchrenderer2D.h"

Improving Readability and Smart Memory Management

More of an enhancement than an issue...

Sparky/Sparky-core/src/graphics/layers/layer.h

In this file you have a vector of pointers called renderables.

However, it could be called Renderables renderables by a typedef and using unique_ptr.

//std::vector<Renderable2D*> m_Renderables;
typedef std::vector<std::unique_ptr<Renderable2D>> Renderables;
Renderables m_Renderables;
//or even better!
typedef std::map<std::string, std::unique_ptr<Renderable2D>> RenderableMap;
RenderableMap m_RenderableMap;
//now one can access these by name and remove them by name!

This will make it easier to read, and show a good way to handle memory through the use of smart pointers. As standard pointers are dangerous, it is probably better to change the objects that can be changed to unique_ptr as well.

Render API CreateVertexBuffers()

inline void CreateVertexArrays(uint size, uint* arrays)
{
    GLCall(glGenVertexArrays(size, arrays));
}

inline void CreateVertexBuffers(uint size, uint* buffers)
{
    GLCall(glGenVertexArrays(size, buffers));
}

These are doing exactly the same. Didn't you want to write glGenBuffers on the second one?

Orthographics matrix issue and vector inconsistency

Hi Cherno,
Thanks for great series and sorry for my bad English. I'm actually at episode 6. But after I watched episode 5(.5) think that I found one issue and one inconsistency in your code which can be "weird" for begginers.

[1]
Issue in mat4.cpp in orthographic method.
In all your branches you have:

mat4 mat4::orthographic(float left, float right, float bottom, float top, float near, float far)
{
    mat4 result(1.0f);

    result.elements[0 + 0 * 4] = 2.0f / (right - left);

    result.elements[1 + 1 * 4] = 2.0f / (top - bottom);

    result.elements[2 + 2 * 4] = 2.0f / (near - far);

    result.elements[0 + 3 * 4] = (left + right) / (left - right);
    result.elements[1 + 3 * 4] = (bottom + top) / (bottom - top);
    result.elements[2 + 3 * 4] = (far + near) / (far - near);

    return result;
}

The problem is, I think, in line:

 result.elements[2 + 3 * 4] = (far + near) / (far - near);

Because "original" is

result.elements[2 + 3 * 4] = - (far + near) / (far - near);

So your line should be:

 result.elements[2 + 3 * 4] = (far + near) / (near - far);

[2]
There is inconsistency in your code. I know - it is because of union which works only with PODs.

vec2 and vec3 have void parameter constuctor defined to fill these vectors with zeroes.
vec4 have this constructor set as "= default". So your struct variables are uninitialized.

So if you have:

sparky::maths::vec2 a;
sparky::maths::vec3 b;
float aa = a.x;
float bb = b.x;

Than aa and bb is zeroes.
But if you try this (in VS 2015 RC in my case):

sparky::maths::vec4 c;
float cc = c.x;

You will get compile time error:

Severity Code Description
Error C4700 uninitialized local variable 'c' used

Of course you can still get c filled with zeroes. For example like this:

sparky::maths::vec4 c{};
or
sparky::maths::vec4 c = sparky::maths::vec4();

To fix this you can set constructors of vec2 and vec3 to "= default" as well or instead of union use casting or... whatever - it is totally up to you.

Thanks, and have a nice day,
CdTCzech

OpenGL Error 1281 (Invalid value) Fix

Hi,

In void BatchRenderer2D::flush() at line 247 you are calling glDrawElements(GL_TRIANGLES, m_IndexCount, GL_UNSIGNED_INT, NULL); however the m_IndexCount is never initialized, and so it causes glGetError() to report a 1281 Invalid value in the first iteration. To fix this you simply initialize the value to zero in the constructor.

Hope this helps.

FPS Camera mouse recapture after pressing Esc failed

To reproduce the bug:

  • run the program
  • once the scene is loaded, press c to enter FPS camera
  • free mouse pointer pressing Esc
  • click into the window

The result is that nothing happens, it should recapture the mouse, as explained in the previous devlog.

Deleting shader!

When you load the vertex and fragment shader you try to delete them but they never(Until you close the window) are going to be deleted because they need to be detached first from the program.

Source: Stackoverflow

Flexable Emscripten bat

TL;DR : Made a auto cpp adding batch file.

Not sure if you are going to keep using a batch file but since I was having a look at emscripten with SDL2 and got sick of adding the cpp files every time I made a new one I decided to make the batch file that I was working with slightly better.

This allowed me to quickly adapt it to the sparky engine. while testing it on my machine tho it was saying something about the bc files not matching so I couldn't see if it worked. (it should work just as if you had wrote them unless i buggered up somehow)
EDIT: fixed for folders with spaces.
EDIT2: Updated to reflect changes in ep 26 ?

@echo off
SETLOCAL enabledelayedexpansion enableextensions

CALL:Setup
:: ::::::::::::::::::::: :::::::::::::::::::::
:: Automatically add all Sparky base files. 
:: ::::::::::::::::::::: :::::::::::::::::::::
CALL:SearchForSourceFiles ..\Sparky-core\src
SET "SparkyFiles=%returnString%"

:: ::::::::::::::::::::: :::::::::::::::::::::
:: Get Game files.  
:: ::::::::::::::::::::: :::::::::::::::::::::
CALL:SearchForSourceFiles ..\Sparky-core\examples
SET "GameFiles=%returnString%"

:: ::::::::::::::::::::: :::::::::::::::::::::
:: Compile everything. 
:: ::::::::::::::::::::: :::::::::::::::::::::
CALL:Compile

goto:eof




:: ::::::::::::::::::::: :::::::::::::::::::::
:: Setup needed variables
:: ::::::::::::::::::::: :::::::::::::::::::::
:Setup
:: Grab parent directory
pushd "%~dp0%"
pushd ..
SET parentFolder=%cd%
popd
popd

:: ::::::::::::::::::::: :::::::::::::::::::::
:: Settings for emscripten
:: ::::::::::::::::::::: :::::::::::::::::::::
SET returnString=
SET AddedJavaScript= --post-js SoundManager.js 
SET MemoryFileGen= --memory-init-file 0
SET OptimizationLevel= -O3
SET EmbedFolders= res
SET LibraryBinFiles= freetype.bc freeimage.bc
SET OutputName= Web\sparky.html


goto:eof

:: ::::::::::::::::::::: :::::::::::::::::::::
:: Find all .cpp files, trim them for the 
:: | right paths and concatinate them. 
:: | @Param <string> folder location
:: | @Return <string> returnString
:: ::::::::::::::::::::: :::::::::::::::::::::
:SearchForSourceFiles
SETLOCAL
SET FolderLocation=%1
SET FoundFiles=
SET REPLACETEXT=..
FOR /F "delims=" %%i in ('dir /b /s "%FolderLocation%\*.cpp"') DO ( 
    SET "string=%%i"
    SET modFilePath=!string:%parentFolder%=%REPLACETEXT%!
    SET "FoundFiles=!FoundFiles! !modFilePath!"
)
ENDLOCAL & SET returnString=%FoundFiles%
goto:eof


:: ::::::::::::::::::::: :::::::::::::::::::::
:: Combine all files found in locations  
:: ::::::::::::::::::::: :::::::::::::::::::::
:Compile
call emcc -std=c++11 -I"../Dependencies/Freeimage/include" %SparkyFiles% %GameFiles% %LibraryBinFiles% -s USE_GLFW=3 -s FULL_ES3=1 %EmbedFolders% %AddedJavaScript% %MemoryFileGen% %OptimizationLevel% -o %OutputName% & PAUSE
goto:eof

GLSL dynamic indexing

In GLSL standards dynamic indexing of arrays is not allowed, so basicly textures[tid] won't work everywhere. Even on a few modern cards this could be an issue, but on older ones definetly. A switch statement could resolve this (but will also drain performance):
switch (tid)
{
case 0: .... textures[0] ... break;
....
}

Perspective matrix seems incorrect

There seems to be a missing assignment for the last element in the matrix.

mat4 mat4::perspective(float fov, float aspectRatio, float near, float far)
    {
        mat4 result(1.0f);

        float q = 1.0f / tan(toRadians(0.5f * fov));
        float a = q / aspectRatio;

        float b = (near + far) / (near - far);
        float c = (2.0f * near * far) / (near - far);

        result.elements[0 + 0 * 4] = a;
        result.elements[1 + 1 * 4] = q;
        result.elements[2 + 2 * 4] = b;
        result.elements[3 + 2 * 4] = -1.0f;
        result.elements[2 + 3 * 4] = c;

        return result;
    }

I believe the 15th element should be 0.
source = http://www.songho.ca/opengl/gl_projectionmatrix.html

So, fix would be adding

result.elements[3+3*4]=0;

Multiple Windows

I am currently evaluating your drawing engine for a work project. One of my requirements is to be able to open/close multiple windows. Looking at the implementation this looks fairly trivial, but I don't have a very full understanding of the entire engine. Let me know what you think!

Robert

Small Transformation Stack optimization

Instead of using vector's back() in push methoh in renderer2d, you could do:

    void push(const maths::mat4& matrix, bool override = false)
    {
        if (override) {
            m_TransformationStack.push_back(matrix);
        } else {
            maths::mat4* result = m_TransformationBack * matrix;
            m_TransformationStack.push_back(result);
            m_TransformationBack = result;
        }
    }

I haven't tested it, but it should be a bit faster

Universal Timer

Decided to quickly remove the windows dependency for the timer class.
Only downfall is it requires Cx11(if someone needs earlier porting it with boost shouldnt be too hard)

#pragma once

#include <chrono>

namespace sparky {

    class Timer
    {
    private:
        typedef std::chrono::high_resolution_clock hrClock;
        typedef std::chrono::duration<float, std::milli> milliseconds_type;
        std::chrono::time_point<hrClock> m_Start;
    public:
        Timer()
        {
            reset();
        }

        void reset()
        {
            m_Start = hrClock::now();
        }

        float elapsed()
        {
            return std::chrono::duration_cast<milliseconds_type>(hrClock::now() - m_Start).count() / 1000.0f;
        }

    };

}

[Sparky-core] Steady timer instead of system timer.

In your utils/Timer.h you should use std::chrono::steady_clock instead of std::chrono::high_resolution_clock.
The high_resolution_clock depends on the systems time which means that when you change your time, the clock will behave akwardly. So you can set your systems time to the future and your game will go insane.

To fix this issue just use the std::chrono::steady_clock which is based on your systems internal time counter.

Optional:
I would call the class a StopWatch rather than a timer.

Here's the way i implemented it:

template<typename Res>
class StopWatch
{
private:
    std::chrono::steady_clock::time_point m_start;

public:
    StopWatch()
    {
        restart();
    }

    long getElapsedTime()
    {
        return (long)std::chrono::duration_cast<Res>(std::chrono::steady_clock::duration(std::chrono::steady_clock::now() - m_start)).count();
    }

    void restart()
    {
        m_start = std::chrono::steady_clock::now();
    }
};

typedef StopWatch<std::chrono::nanoseconds> StopWatchNs;
typedef StopWatch<std::chrono::microseconds> StopWatchUs;
typedef StopWatch<std::chrono::milliseconds> StopWatchMs;
typedef StopWatch<std::chrono::seconds> StopWatchS;
typedef StopWatch<std::chrono::minutes> StopWatchM;
typedef StopWatch<std::chrono::hours> StopWatchH;

Sparky Tools

Tools for the engine should commence development. Probably on a different repository. Address this.

Audio play and loop

There's another issue (not sure that's important, because this is for Game but....). Let's try to play a sound and try to loop the same sound (with play() function and loop() function on the same sound).... The loop() stop at the end of play().

Have a nice day~~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.