Browse Source

scene: remove useless subobject classes.

legacy
Sam Hocevar 5 years ago
parent
commit
06edad8755
5 changed files with 264 additions and 325 deletions
  1. +3
    -0
      src/application/application.cpp
  2. +0
    -4
      src/application/egl-app.cpp
  3. +0
    -3
      src/application/sdl-app.cpp
  4. +182
    -308
      src/scene.cpp
  5. +79
    -10
      src/scene.h

+ 3
- 0
src/application/application.cpp View File

@@ -161,6 +161,8 @@ static void AppCallback()

Application::Application(char const *name, ivec2 res, float framerate)
{
ticker::setup(framerate);

auto app_display = new ApplicationDisplay(name, res);
SceneDisplay::Add(app_display);
data = new ApplicationData(name, app_display->resolution(), framerate);
@@ -194,6 +196,7 @@ void Application::ShowPointer(bool show)

Application::~Application()
{
ticker::teardown();
delete data;
}



+ 0
- 4
src/application/egl-app.cpp View File

@@ -248,8 +248,6 @@ EglApp::EglApp(char const *title, ivec2 res, float fps) :
new SdlInput(res.x, res.y, data->screen_size.x, data->screen_size.y);
# endif

/* Initialise everything */
ticker::setup(fps);
Video::Setup((ivec2)data->screen_size);
audio::init();
#else
@@ -285,8 +283,6 @@ EglApp::~EglApp()
XCloseDisplay(data->dpy);
# endif
#endif
ticker::teardown();

delete data;
}



+ 0
- 3
src/application/sdl-app.cpp View File

@@ -176,8 +176,6 @@ SdlApp::SdlApp(char const *title, ivec2 res, float fps) :
ivec2 window_size = res;
ivec2 screen_size = res;

/* Initialise everything */
ticker::setup(fps);
audio::init();

/* Autoreleased objects */
@@ -210,7 +208,6 @@ SdlApp::~SdlApp()
SDL_Quit();
#endif
delete data;
ticker::teardown();
}

} /* namespace lol */


+ 182
- 308
src/scene.cpp View File

@@ -40,19 +40,7 @@ namespace lol

array<Scene*> Scene::g_scenes;

/*
* A quick and dirty Tile structure for 2D blits
*/

struct Tile
{
mat4 m_model;
TileSet *m_tileset;
int m_id;
};

//-----------------------------------------------------------------------------
static array<SceneDisplay*> m_scene_displays;
static array<SceneDisplay*> g_scene_displays;

static inline void gpu_marker(char const *message)
{
@@ -64,35 +52,34 @@ static inline void gpu_marker(char const *message)
#endif
}

/*
* Public SceneDisplay class
*/
//
// Public SceneDisplay class
//

void SceneDisplay::Add(SceneDisplay* display)
{
m_scene_displays << display;
g_scene_displays << display;
}

int SceneDisplay::GetCount()
{
return m_scene_displays.count();
return g_scene_displays.count();
}

SceneDisplay* SceneDisplay::GetDisplay(int index)
{
ASSERT(0 <= index && index < m_scene_displays.count(),
ASSERT(0 <= index && index < g_scene_displays.count(),
"invalid display index %d", index);
return m_scene_displays[index];
return g_scene_displays[index];
}

void SceneDisplay::DestroyAll()
{
for (SceneDisplay* display : m_scene_displays)
for (SceneDisplay* display : g_scene_displays)
delete display;
m_scene_displays.clear();
g_scene_displays.clear();
}

/* ------------------------------------------------ */
void SceneDisplay::Enable()
{
// TODO: PROFILER STUFF
@@ -119,87 +106,9 @@ void PrimitiveRenderer::Render(Scene& scene, std::shared_ptr<PrimitiveSource> pr
* Scene implementation class
*/

class SceneData
{
friend class Scene;

public:
SceneData()
{
/* TODO: FIX THAT */
ASSERT(!(m_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!");
m_mask_id = m_used_id;
m_used_id = m_used_id << 1;
}

private:
/* Mask ID */
/* TODO: Do a mask class that handles more than 64 slots */
static uint64_t m_used_id;
uint64_t m_mask_id = 0;

/* Scene display: if none has been set to the scene,
* the default one created by the app will be used */
SceneDisplay* m_display = nullptr;

/** Render buffers: where to render to. */
std::shared_ptr<Framebuffer> m_renderbuffer[4];

struct postprocess
{
std::shared_ptr<Shader> m_shader[2];
std::shared_ptr<VertexBuffer> m_vbo;
std::shared_ptr<VertexDeclaration> m_vdecl;
ShaderUniform m_buffer_uni[2][3];
ShaderAttrib m_coord[2];
}
m_pp;

/* Sources are shared by all scenes.
* Renderers are scene-dependent. They get the primitive in the identical
* slot to render with the given scene.
* Primitives and renderers will be kept until:
* - Updated by entity
* - Marked Fire&Forget
* - Scene is destroyed */
std::map<uintptr_t, array<std::shared_ptr<PrimitiveRenderer>>> m_prim_renderers;
static std::map<uintptr_t, array<std::shared_ptr<PrimitiveSource>>> m_prim_sources;
static mutex m_prim_mutex;

Camera *m_default_cam;
array<Camera *> m_camera_stack;

/* Old line API <P0, P1, COLOR, TIME, MASK> */
struct line_api
{
//float m_duration, m_segment_size;
//vec4 m_color;
array<vec3, vec3, vec4, float, int, bool, bool> m_lines;
int /*m_mask,*/ m_debug_mask;
std::shared_ptr<Shader> m_shader;
std::shared_ptr<VertexDeclaration> m_vdecl;
}
m_line_api;

/* The old tiles API */
struct tile_api
{
int m_cam;
array<Tile> m_tiles;
array<Tile> m_palettes;
array<Light *> m_lights;

std::shared_ptr<Shader> m_shader;
std::shared_ptr<Shader> m_palette_shader;

std::shared_ptr<VertexDeclaration> m_vdecl;
array<std::shared_ptr<VertexBuffer>> m_bufs;
}
m_tile_api;
};
uint64_t SceneData::m_used_id = 1;
std::map<uintptr_t, array<std::shared_ptr<PrimitiveSource>>> SceneData::m_prim_sources;
mutex SceneData::m_prim_mutex;
uint64_t Scene::g_used_id = 1;
mutex Scene::g_prim_mutex;
std::map<uintptr_t, array<std::shared_ptr<PrimitiveSource>>> Scene::g_prim_sources;

/*
* Public Scene class
@@ -207,45 +116,49 @@ mutex SceneData::m_prim_mutex;
Scene::Scene(ivec2 size)
: m_size(size),
m_wanted_size(size),
data(std::make_unique<SceneData>()),
m_renderer(std::make_shared<Renderer>(size))
{
/* TODO: FIX THAT */
ASSERT(!(g_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!");
m_mask_id = g_used_id;
g_used_id = g_used_id << 1;

for (int i = 0; i < 4; ++i)
data->m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
data->m_pp.m_shader[0] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_blit));
data->m_pp.m_shader[1] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_postprocess));
data->m_pp.m_coord[0] = data->m_pp.m_shader[0]->GetAttribLocation(VertexUsage::Position, 0);
data->m_pp.m_coord[1] = data->m_pp.m_shader[1]->GetAttribLocation(VertexUsage::Position, 0);
data->m_pp.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec2>(VertexUsage::Position));
data->m_pp.m_buffer_uni[0][0] = data->m_pp.m_shader[0]->GetUniformLocation("u_buffer");
data->m_pp.m_buffer_uni[1][0] = data->m_pp.m_shader[1]->GetUniformLocation("u_buffer");
data->m_pp.m_buffer_uni[1][1] = data->m_pp.m_shader[1]->GetUniformLocation("u_prev_buffer");
data->m_pp.m_buffer_uni[1][2] = data->m_pp.m_shader[1]->GetUniformLocation("u_prev_final");
m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
m_pp.m_shader[0] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_blit));
m_pp.m_shader[1] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_postprocess));
m_pp.m_coord[0] = m_pp.m_shader[0]->GetAttribLocation(VertexUsage::Position, 0);
m_pp.m_coord[1] = m_pp.m_shader[1]->GetAttribLocation(VertexUsage::Position, 0);
m_pp.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec2>(VertexUsage::Position));
m_pp.m_buffer_uni[0][0] = m_pp.m_shader[0]->GetUniformLocation("u_buffer");
m_pp.m_buffer_uni[1][0] = m_pp.m_shader[1]->GetUniformLocation("u_buffer");
m_pp.m_buffer_uni[1][1] = m_pp.m_shader[1]->GetUniformLocation("u_prev_buffer");
m_pp.m_buffer_uni[1][2] = m_pp.m_shader[1]->GetUniformLocation("u_prev_final");

array<vec2> quad { vec2( 1.0, 1.0), vec2(-1.0, -1.0), vec2( 1.0, -1.0),
vec2(-1.0, -1.0), vec2( 1.0, 1.0), vec2(-1.0, 1.0), };

data->m_pp.m_vbo = std::make_shared<VertexBuffer>(quad.bytes());
void *vertices = data->m_pp.m_vbo->Lock(0, 0);
m_pp.m_vbo = std::make_shared<VertexBuffer>(quad.bytes());
void *vertices = m_pp.m_vbo->Lock(0, 0);
memcpy(vertices, quad.data(), quad.bytes());
data->m_pp.m_vbo->Unlock();
m_pp.m_vbo->Unlock();

/* Create a default orthographic camera, in case the user doesn’t. */
data->m_default_cam = new Camera();
m_default_cam = new Camera();
mat4 proj = mat4::ortho(0.f, (float)m_size.x, 0.f, (float)m_size.y, -1000.f, 1000.f);
data->m_default_cam->SetProjection(proj);
PushCamera(data->m_default_cam);
m_default_cam->SetProjection(proj);
PushCamera(m_default_cam);

data->m_tile_api.m_cam = -1;
data->m_tile_api.m_shader = 0;
data->m_tile_api.m_palette_shader = 0;
data->m_tile_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec3>(VertexUsage::Position),
VertexStream<vec2>(VertexUsage::TexCoord));
m_tile_api.m_cam = -1;
m_tile_api.m_shader = 0;
m_tile_api.m_palette_shader = 0;
m_tile_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec3>(VertexUsage::Position),
VertexStream<vec2>(VertexUsage::TexCoord));

data->m_line_api.m_shader = 0;
data->m_line_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));
m_line_api.m_shader = 0;
m_line_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));

data->m_line_api.m_debug_mask = 1;
m_line_api.m_debug_mask = 1;
}

void Scene::resize(ivec2 size)
@@ -253,10 +166,9 @@ void Scene::resize(ivec2 size)
m_wanted_size = size;
}

//-----------------------------------------------------------------------------
Scene::~Scene()
{
PopCamera(data->m_default_cam);
PopCamera(m_default_cam);

/* FIXME: this must be done while the GL context is still active.
* Change the code architecture to make sure of that. */
@@ -265,7 +177,6 @@ Scene::~Scene()
Reset();
}

//-----------------------------------------------------------------------------
void Scene::AddNew(ivec2 size)
{
Scene::g_scenes << new Scene(size);
@@ -288,13 +199,11 @@ int Scene::GetCount()
return g_scenes.count();
}

//-----------------------------------------------------------------------------
bool Scene::IsReady(int index)
{
return 0 <= index && index < g_scenes.count() && !!g_scenes[index];
}

//-----------------------------------------------------------------------------
Scene& Scene::GetScene(int index)
{
ASSERT(0 <= index && index < g_scenes.count() && !!g_scenes[index],
@@ -302,51 +211,40 @@ Scene& Scene::GetScene(int index)
return *g_scenes[index];
}

//-----------------------------------------------------------------------------
void Scene::Link(Entity* entity)
{
entity->m_scene_mask |= data->m_mask_id;
entity->m_scene_mask |= m_mask_id;
}

//-----------------------------------------------------------------------------
bool Scene::IsRelevant(Entity* entity)
{
return !!(entity->m_scene_mask & data->m_mask_id);
return !!(entity->m_scene_mask & m_mask_id);
}

//-----------------------------------------------------------------------------
Camera* Scene::GetCamera(int cam_idx)
{
ASSERT(!!data, "Trying to access a non-ready scene");

return (0 <= cam_idx && cam_idx < data->m_camera_stack.count()) ?
data->m_camera_stack[cam_idx] :
data->m_camera_stack.last();
return (0 <= cam_idx && cam_idx < m_camera_stack.count()) ?
m_camera_stack[cam_idx] :
m_camera_stack.last();
}

//-----------------------------------------------------------------------------
int Scene::PushCamera(Camera *cam)
{
ASSERT(!!data, "Trying to access a non-ready scene");

Ticker::Ref(cam);
data->m_camera_stack.push(cam);
return (int)data->m_camera_stack.count() - 1;
m_camera_stack.push(cam);
return (int)m_camera_stack.count() - 1;
}

//-----------------------------------------------------------------------------
void Scene::PopCamera(Camera *cam)
{
ASSERT(!!data, "Trying to access a non-ready scene");

/* Parse from the end because that’s probably where we’ll find
* our camera first. */
for (int i = data->m_camera_stack.count(); i--;)
for (int i = m_camera_stack.count(); i--;)
{
if (data->m_camera_stack[i] == cam)
if (m_camera_stack[i] == cam)
{
Ticker::Unref(cam);
data->m_camera_stack.remove(i);
m_camera_stack.remove(i);
return;
}
}
@@ -354,52 +252,49 @@ void Scene::PopCamera(Camera *cam)
ASSERT(false, "trying to pop a nonexistent camera from the scene");
}

//-----------------------------------------------------------------------------
void Scene::SetTileCam(int cam_idx)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_tile_api.m_cam = cam_idx;
m_tile_api.m_cam = cam_idx;
}

//-----------------------------------------------------------------------------
void Scene::Reset()
{
ASSERT(!!data, "Trying to access a non-ready scene");

/* New scenegraph: Release fire&forget primitives */
for (uintptr_t key : keys(data->m_prim_renderers))
for (uintptr_t key : keys(m_prim_renderers))
{
for (int idx = 0; idx < data->m_prim_renderers[key].count(); ++idx)
if (data->m_prim_renderers[key][idx]->m_fire_and_forget)
for (int idx = 0; idx < m_prim_renderers[key].count(); ++idx)
if (m_prim_renderers[key][idx]->m_fire_and_forget)
ReleasePrimitiveRenderer(idx--, key);
}

data->m_tile_api.m_bufs.clear();
data->m_tile_api.m_lights.clear();
m_tile_api.m_bufs.clear();
m_tile_api.m_lights.clear();
}

//---- Primitive source stuff -------------------------------------------------
//
// Primitive source stuff
//

int Scene::HasPrimitiveSource(uintptr_t key)
{
int count;
SceneData::m_prim_mutex.lock();
g_prim_mutex.lock();
{
count = SceneData::m_prim_sources[key].count();
count = g_prim_sources[key].count();
}
SceneData::m_prim_mutex.unlock();
g_prim_mutex.unlock();
return count;
}

int Scene::AddPrimitiveSource(uintptr_t key, std::shared_ptr<PrimitiveSource> source)
{
int count;
SceneData::m_prim_mutex.lock();
g_prim_mutex.lock();
{
count = SceneData::m_prim_sources[key].count();
SceneData::m_prim_sources[key].push(source);
count = g_prim_sources[key].count();
g_prim_sources[key].push(source);
}
SceneData::m_prim_mutex.unlock();
g_prim_mutex.unlock();
return count;
}

@@ -411,27 +306,27 @@ void Scene::SetPrimitiveSource(int index, uintptr_t key, std::shared_ptr<Primiti
// Keep reference to old source until AFTER we release the lock
std::shared_ptr<PrimitiveSource> old;

SceneData::m_prim_mutex.lock();
g_prim_mutex.lock();
{
if (index < SceneData::m_prim_sources[key].count())
old = SceneData::m_prim_sources[key][index];
if (index < g_prim_sources[key].count())
old = g_prim_sources[key][index];
else
SceneData::m_prim_sources[key].resize(index + 1);
SceneData::m_prim_sources[key][index] = source;
g_prim_sources[key].resize(index + 1);
g_prim_sources[key][index] = source;
}
SceneData::m_prim_mutex.unlock();
g_prim_mutex.unlock();
}

void Scene::ReleasePrimitiveSource(int index, uintptr_t key)
{
std::shared_ptr<PrimitiveSource> old;
SceneData::m_prim_mutex.lock();
g_prim_mutex.lock();
{
ASSERT(0 <= index && index < SceneData::m_prim_sources[key].count());
old = SceneData::m_prim_sources[key][index];
SceneData::m_prim_sources[key].remove(index);
ASSERT(0 <= index && index < g_prim_sources[key].count());
old = g_prim_sources[key][index];
g_prim_sources[key].remove(index);
}
SceneData::m_prim_mutex.unlock();
g_prim_mutex.unlock();
}

void Scene::ReleaseAllPrimitiveSources(uintptr_t key)
@@ -439,26 +334,29 @@ void Scene::ReleaseAllPrimitiveSources(uintptr_t key)
// Delete oldies AFTER having released the lock
array<std::shared_ptr<PrimitiveSource>> oldies;

SceneData::m_prim_mutex.lock();
g_prim_mutex.lock();
{
oldies.reserve(SceneData::m_prim_sources[key].count());
for (auto source : SceneData::m_prim_sources[key])
oldies.reserve(g_prim_sources[key].count());
for (auto source : g_prim_sources[key])
oldies << source;
SceneData::m_prim_sources[key].clear();
g_prim_sources[key].clear();
}
SceneData::m_prim_mutex.unlock();
g_prim_mutex.unlock();
}

//---- Primitive renderer stuff -----------------------------------------------
//
// Primitive renderer stuff
//

int Scene::HasPrimitiveRenderer(uintptr_t key)
{
return data->m_prim_renderers[key].count();
return m_prim_renderers[key].count();
}

void Scene::AddPrimitiveRenderer(uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
{
renderer->m_fire_and_forget = true;
data->m_prim_renderers[key].push(renderer);
m_prim_renderers[key].push(renderer);
}

void Scene::SetPrimitiveRenderer(int index, uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
@@ -466,24 +364,23 @@ void Scene::SetPrimitiveRenderer(int index, uintptr_t key, std::shared_ptr<Primi
ASSERT(renderer);
ASSERT(index >= 0);

if (index >= data->m_prim_renderers[key].count())
data->m_prim_renderers[key].resize(index + 1);
data->m_prim_renderers[key][index] = renderer;
if (index >= m_prim_renderers[key].count())
m_prim_renderers[key].resize(index + 1);
m_prim_renderers[key][index] = renderer;
}

void Scene::ReleasePrimitiveRenderer(int index, uintptr_t key)
{
ASSERT(0 <= index && index < data->m_prim_renderers[key].count());
ASSERT(0 <= index && index < m_prim_renderers[key].count());

data->m_prim_renderers[key].remove(index);
m_prim_renderers[key].remove(index);
}

void Scene::ReleaseAllPrimitiveRenderers(uintptr_t key)
{
data->m_prim_renderers[key].clear();
m_prim_renderers[key].clear();
}

//-----------------------------------------------------------------------------
void Scene::AddTile(TileSet *tileset, int id, vec3 pos, vec2 scale, float radians)
{
ASSERT(id < tileset->GetTileCount());
@@ -508,62 +405,48 @@ void Scene::AddTile(TileSet *tileset, int id, mat4 model)
t.m_id = id;

if (tileset->GetPalette())
data->m_tile_api.m_palettes.push(t);
m_tile_api.m_palettes.push(t);
else
data->m_tile_api.m_tiles.push(t);
m_tile_api.m_tiles.push(t);
}

//-----------------------------------------------------------------------------
void Scene::AddLine(vec3 a, vec3 b, vec4 color)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_lines.push(a, b, color, -1.f, 0xFFFFFFFF, false, false);
m_line_api.m_lines.push(a, b, color, -1.f, 0xFFFFFFFF, false, false);
}

//-----------------------------------------------------------------------------
void Scene::AddLine(vec3 a, vec3 b, vec4 color, float duration, int mask)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_lines.push(a, b, color, duration, mask, false, false);
m_line_api.m_lines.push(a, b, color, duration, mask, false, false);
}

//-----------------------------------------------------------------------------
void Scene::AddLight(Light *l)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_tile_api.m_lights.push(l);
m_tile_api.m_lights.push(l);
}

//-----------------------------------------------------------------------------
array<Light *> const &Scene::GetLights()
{
ASSERT(!!data, "Trying to access a non-ready scene");

return data->m_tile_api.m_lights;
return m_tile_api.m_lights;
}

//-----------------------------------------------------------------------------
void Scene::SetDisplay(SceneDisplay* display)
{
data->m_display = display;
m_display = display;
}

//-----------------------------------------------------------------------------
void Scene::EnableDisplay()
{
// If no display has been set, use the default one
if (!data->m_display)
if (!m_display)
SetDisplay(SceneDisplay::GetDisplay());
data->m_display->Enable();
m_display->Enable();
}

void Scene::DisableDisplay()
{
ASSERT(data->m_display);
data->m_display->Disable();
ASSERT(m_display);
m_display->Disable();
}

static bool do_pp = true;
@@ -577,16 +460,16 @@ void Scene::pre_render(float)
{
m_size = m_wanted_size;
for (int i = 0; i < 4; ++i)
data->m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);

mat4 proj = mat4::ortho(0.f, (float)m_size.x, 0.f, (float)m_size.y, -1000.f, 1000.f);
data->m_default_cam->SetProjection(proj);
m_default_cam->SetProjection(proj);
}

/* First render into the offline buffer */
if (do_pp)
{
data->m_renderbuffer[0]->Bind();
m_renderbuffer[0]->Bind();
}

{
@@ -618,11 +501,11 @@ void Scene::post_render(float)

if (do_pp)
{
data->m_renderbuffer[0]->Unbind();
m_renderbuffer[0]->Unbind();

gpu_marker("PostProcess");

data->m_renderbuffer[3]->Bind();
m_renderbuffer[3]->Bind();

render_context rc(m_renderer);
rc.clear_color(vec4(0.f, 0.f, 0.f, 1.f));
@@ -630,23 +513,23 @@ void Scene::post_render(float)
m_renderer->Clear(ClearMask::Color | ClearMask::Depth);

/* Execute post process */
data->m_pp.m_shader[1]->Bind();
data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][0], data->m_renderbuffer[0]->GetTextureUniform(), 0);
data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][1], data->m_renderbuffer[1]->GetTextureUniform(), 1);
data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][2], data->m_renderbuffer[2]->GetTextureUniform(), 2);
data->m_pp.m_vdecl->SetStream(data->m_pp.m_vbo, data->m_pp.m_coord[1]);
data->m_pp.m_vdecl->Bind();
data->m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
data->m_pp.m_vdecl->Unbind();
data->m_pp.m_shader[1]->Unbind();
data->m_renderbuffer[3]->Unbind();
m_pp.m_shader[1]->Bind();
m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][0], m_renderbuffer[0]->GetTextureUniform(), 0);
m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][1], m_renderbuffer[1]->GetTextureUniform(), 1);
m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][2], m_renderbuffer[2]->GetTextureUniform(), 2);
m_pp.m_vdecl->SetStream(m_pp.m_vbo, m_pp.m_coord[1]);
m_pp.m_vdecl->Bind();
m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
m_pp.m_vdecl->Unbind();
m_pp.m_shader[1]->Unbind();
m_renderbuffer[3]->Unbind();
}

if (do_pp)
{
gpu_marker("Blit frame");

data->m_pp.m_shader[0]->Bind();
m_pp.m_shader[0]->Bind();

render_context rc(m_renderer);
rc.clear_color(vec4(0.f, 0.f, 0.f, 1.f));
@@ -654,57 +537,51 @@ void Scene::post_render(float)
m_renderer->Clear(ClearMask::Color | ClearMask::Depth);

/* Blit final image to screen */
data->m_pp.m_shader[0]->SetUniform(data->m_pp.m_buffer_uni[0][0], data->m_renderbuffer[3]->GetTextureUniform(), 3);
data->m_pp.m_vdecl->SetStream(data->m_pp.m_vbo, data->m_pp.m_coord[0]);
data->m_pp.m_vdecl->Bind();
data->m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
data->m_pp.m_vdecl->Unbind();
data->m_pp.m_shader[0]->Unbind();
m_pp.m_shader[0]->SetUniform(m_pp.m_buffer_uni[0][0], m_renderbuffer[3]->GetTextureUniform(), 3);
m_pp.m_vdecl->SetStream(m_pp.m_vbo, m_pp.m_coord[0]);
m_pp.m_vdecl->Bind();
m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
m_pp.m_vdecl->Unbind();
m_pp.m_shader[0]->Unbind();
}

if (do_pp)
{
/* Swap back buffers */
std::swap(data->m_renderbuffer[0], data->m_renderbuffer[1]);
std::swap(data->m_renderbuffer[2], data->m_renderbuffer[3]);
std::swap(m_renderbuffer[0], m_renderbuffer[1]);
std::swap(m_renderbuffer[2], m_renderbuffer[3]);
}

gpu_marker("End Render");
}

//-----------------------------------------------------------------------------
void Scene::render_primitives()
{
ASSERT(!!data, "Trying to access a non-ready scene");

/* FIXME: Temp fix for mesh having no render context*/
render_context rc(m_renderer);
rc.cull_mode(CullMode::Clockwise);
rc.depth_func(DepthFunc::LessOrEqual);

/* new scenegraph */
for (uintptr_t key : keys(data->m_prim_renderers))
for (uintptr_t key : keys(m_prim_renderers))
{
for (int idx = 0; idx < data->m_prim_renderers[key].count(); ++idx)
for (int idx = 0; idx < m_prim_renderers[key].count(); ++idx)
{
/* TODO: Not sure if thread compliant */
std::shared_ptr<PrimitiveSource> source;
if (idx < SceneData::m_prim_sources[key].count())
source = SceneData::m_prim_sources[key][idx];
data->m_prim_renderers[key][idx]->Render(*this, source);
if (idx < g_prim_sources[key].count())
source = g_prim_sources[key][idx];
m_prim_renderers[key][idx]->Render(*this, source);
}
}
}

//-----------------------------------------------------------------------------
void Scene::render_tiles() // XXX: rename to Blit()
{
ASSERT(!!data, "Trying to access a non-ready scene");

render_context rc(m_renderer);

/* Early test if nothing needs to be rendered */
if (!data->m_tile_api.m_tiles.count() && !data->m_tile_api.m_palettes.count())
if (!m_tile_api.m_tiles.count() && !m_tile_api.m_palettes.count())
return;

/* FIXME: we disable culling for now because we don’t have a reliable
@@ -720,15 +597,15 @@ void Scene::render_tiles() // XXX: rename to Blit()
glEnable(GL_TEXTURE_2D);
#endif

if (!data->m_tile_api.m_shader)
data->m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_tile));
if (!data->m_tile_api.m_palette_shader && data->m_tile_api.m_palettes.count())
data->m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_palette));
if (!m_tile_api.m_shader)
m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_tile));
if (!m_tile_api.m_palette_shader && m_tile_api.m_palettes.count())
m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_palette));

for (int p = 0; p < 2; p++)
{
auto shader = (p == 0) ? data->m_tile_api.m_shader : data->m_tile_api.m_palette_shader;
auto &tiles = (p == 0) ? data->m_tile_api.m_tiles : data->m_tile_api.m_palettes;
auto shader = (p == 0) ? m_tile_api.m_shader : m_tile_api.m_palette_shader;
auto &tiles = (p == 0) ? m_tile_api.m_tiles : m_tile_api.m_palettes;

if (tiles.count() == 0)
continue;
@@ -741,14 +618,14 @@ void Scene::render_tiles() // XXX: rename to Blit()
shader->Bind();

uni_mat = shader->GetUniformLocation("u_projection");
shader->SetUniform(uni_mat, GetCamera(data->m_tile_api.m_cam)->GetProjection());
shader->SetUniform(uni_mat, GetCamera(m_tile_api.m_cam)->GetProjection());
uni_mat = shader->GetUniformLocation("u_view");
shader->SetUniform(uni_mat, GetCamera(data->m_tile_api.m_cam)->GetView());
shader->SetUniform(uni_mat, GetCamera(m_tile_api.m_cam)->GetView());
uni_mat = shader->GetUniformLocation("u_model");
shader->SetUniform(uni_mat, mat4(1.f));

uni_tex = shader->GetUniformLocation("u_texture");
uni_pal = data->m_tile_api.m_palette_shader ? data->m_tile_api.m_palette_shader->GetUniformLocation("u_palette") : ShaderUniform();
uni_pal = m_tile_api.m_palette_shader ? m_tile_api.m_palette_shader->GetUniformLocation("u_palette") : ShaderUniform();
uni_texsize = shader->GetUniformLocation("u_texsize");

for (int buf = 0, i = 0, n; i < tiles.count(); i = n, buf += 2)
@@ -764,8 +641,8 @@ void Scene::render_tiles() // XXX: rename to Blit()
auto vb2 = std::make_shared<VertexBuffer>(6 * (n - i) * sizeof(vec2));
vec2 *texture = (vec2 *)vb2->Lock(0, 0);

data->m_tile_api.m_bufs.push(vb1);
data->m_tile_api.m_bufs.push(vb2);
m_tile_api.m_bufs.push(vb1);
m_tile_api.m_bufs.push(vb2);

for (int j = i; j < n; j++)
{
@@ -795,13 +672,13 @@ void Scene::render_tiles() // XXX: rename to Blit()
(vec2)tiles[i].m_tileset->GetTextureSize());

/* Bind vertex and texture coordinate buffers */
data->m_tile_api.m_vdecl->Bind();
data->m_tile_api.m_vdecl->SetStream(vb1, attr_pos);
data->m_tile_api.m_vdecl->SetStream(vb2, attr_tex);
m_tile_api.m_vdecl->Bind();
m_tile_api.m_vdecl->SetStream(vb1, attr_pos);
m_tile_api.m_vdecl->SetStream(vb2, attr_tex);

/* Draw arrays */
data->m_tile_api.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
data->m_tile_api.m_vdecl->Unbind();
m_tile_api.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
m_tile_api.m_vdecl->Unbind();
tiles[i].m_tileset->Unbind();
}

@@ -809,7 +686,7 @@ void Scene::render_tiles() // XXX: rename to Blit()

shader->Unbind();

if (!data->m_tile_api.m_palette_shader)
if (!m_tile_api.m_palette_shader)
break;
}

@@ -818,16 +695,13 @@ void Scene::render_tiles() // XXX: rename to Blit()
#endif
}

//-----------------------------------------------------------------------------
// FIXME: get rid of the delta time argument
// XXX: rename to Blit()
void Scene::render_lines(float seconds)
{
ASSERT(!!data, "Trying to access a non-ready scene");

render_context rc(m_renderer);

if (!data->m_line_api.m_lines.count())
if (!m_line_api.m_lines.count())
return;

rc.depth_func(DepthFunc::LessOrEqual);
@@ -835,10 +709,10 @@ void Scene::render_lines(float seconds)
rc.blend_equation(BlendEquation::Add, BlendEquation::Max);
rc.alpha_func(AlphaFunc::GreaterOrEqual, 0.01f);

int linecount = (int)data->m_line_api.m_lines.count();
int linecount = (int)m_line_api.m_lines.count();

if (!data->m_line_api.m_shader)
data->m_line_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_line));
if (!m_line_api.m_shader)
m_line_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_line));

array<vec4, vec4, vec4, vec4> buff;
buff.resize(linecount);
@@ -846,18 +720,18 @@ void Scene::render_lines(float seconds)
mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView());
for (int i = 0; i < linecount; i++)
{
if (data->m_line_api.m_lines[i].m5 & data->m_line_api.m_debug_mask)
if (m_line_api.m_lines[i].m5 & m_line_api.m_debug_mask)
{
buff[real_linecount].m1 = vec4(data->m_line_api.m_lines[i].m1, (float)data->m_line_api.m_lines[i].m6);
buff[real_linecount].m2 = data->m_line_api.m_lines[i].m3;
buff[real_linecount].m3 = vec4(data->m_line_api.m_lines[i].m2, (float)data->m_line_api.m_lines[i].m7);
buff[real_linecount].m4 = data->m_line_api.m_lines[i].m3;
buff[real_linecount].m1 = vec4(m_line_api.m_lines[i].m1, (float)m_line_api.m_lines[i].m6);
buff[real_linecount].m2 = m_line_api.m_lines[i].m3;
buff[real_linecount].m3 = vec4(m_line_api.m_lines[i].m2, (float)m_line_api.m_lines[i].m7);
buff[real_linecount].m4 = m_line_api.m_lines[i].m3;
real_linecount++;
}
data->m_line_api.m_lines[i].m4 -= seconds;
if (data->m_line_api.m_lines[i].m4 < 0.f)
m_line_api.m_lines[i].m4 -= seconds;
if (m_line_api.m_lines[i].m4 < 0.f)
{
data->m_line_api.m_lines.remove_swap(i--);
m_line_api.m_lines.remove_swap(i--);
linecount--;
}
}
@@ -866,27 +740,27 @@ void Scene::render_lines(float seconds)
memcpy(vertex, buff.data(), buff.bytes());
vb->Unlock();

data->m_line_api.m_shader->Bind();
m_line_api.m_shader->Bind();

ShaderUniform uni_mat, uni_tex;
ShaderAttrib attr_pos, attr_col;
attr_pos = data->m_line_api.m_shader->GetAttribLocation(VertexUsage::Position, 0);
attr_col = data->m_line_api.m_shader->GetAttribLocation(VertexUsage::Color, 0);
attr_pos = m_line_api.m_shader->GetAttribLocation(VertexUsage::Position, 0);
attr_col = m_line_api.m_shader->GetAttribLocation(VertexUsage::Color, 0);

data->m_line_api.m_shader->Bind();
m_line_api.m_shader->Bind();

uni_mat = data->m_line_api.m_shader->GetUniformLocation("u_projection");
data->m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetProjection());
uni_mat = data->m_line_api.m_shader->GetUniformLocation("u_view");
data->m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetView());
uni_mat = m_line_api.m_shader->GetUniformLocation("u_projection");
m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetProjection());
uni_mat = m_line_api.m_shader->GetUniformLocation("u_view");
m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetView());

data->m_line_api.m_vdecl->Bind();
data->m_line_api.m_vdecl->SetStream(vb, attr_pos, attr_col);
data->m_line_api.m_vdecl->DrawElements(MeshPrimitive::Lines, 0, 2 * real_linecount);
data->m_line_api.m_vdecl->Unbind();
data->m_line_api.m_shader->Unbind();
m_line_api.m_vdecl->Bind();
m_line_api.m_vdecl->SetStream(vb, attr_pos, attr_col);
m_line_api.m_vdecl->DrawElements(MeshPrimitive::Lines, 0, 2 * real_linecount);
m_line_api.m_vdecl->Unbind();
m_line_api.m_shader->Unbind();

//data->m_line_api.m_lines.clear();
//m_line_api.m_lines.clear();
}

} /* namespace lol */


+ 79
- 10
src/scene.h View File

@@ -45,6 +45,17 @@ public:
private:
};

/*
* A quick and dirty Tile structure for 2D blits
*/

struct Tile
{
mat4 m_model;
TileSet *m_tileset;
int m_id;
};

class PrimitiveRenderer
{
friend class Scene;
@@ -58,9 +69,6 @@ private:
bool m_fire_and_forget = false;
};

//-----------------------------------------------------------------------------
class SceneDisplayData;

class SceneDisplay
{
friend class Scene;
@@ -88,14 +96,8 @@ public:
//protected:
virtual void Enable();
virtual void Disable();

private:
SceneDisplayData *data;
};

//-----------------------------------------------------------------------------
class SceneData;

class Scene
{
friend class Video;
@@ -264,8 +266,75 @@ private:

ivec2 m_size, m_wanted_size;

std::unique_ptr<SceneData> data;
std::shared_ptr<Renderer> m_renderer;

//
// The old SceneData stuff
//

/* Mask ID */
/* TODO: Do a mask class that handles more than 64 slots */
static uint64_t g_used_id;
uint64_t m_mask_id = 0;

/* Scene display: if none has been set to the scene,
* the default one created by the app will be used */
SceneDisplay* m_display = nullptr;

/** Render buffers: where to render to. */
std::shared_ptr<Framebuffer> m_renderbuffer[4];

struct postprocess
{
std::shared_ptr<Shader> m_shader[2];
std::shared_ptr<VertexBuffer> m_vbo;
std::shared_ptr<VertexDeclaration> m_vdecl;
ShaderUniform m_buffer_uni[2][3];
ShaderAttrib m_coord[2];
}
m_pp;

/* Sources are shared by all scenes.
* Renderers are scene-dependent. They get the primitive in the identical
* slot to render with the given scene.
* Primitives and renderers will be kept until:
* - Updated by entity
* - Marked Fire&Forget
* - Scene is destroyed */
std::map<uintptr_t, array<std::shared_ptr<PrimitiveRenderer>>> m_prim_renderers;
static std::map<uintptr_t, array<std::shared_ptr<PrimitiveSource>>> g_prim_sources;
static mutex g_prim_mutex;

Camera *m_default_cam;
array<Camera *> m_camera_stack;

/* Old line API <P0, P1, COLOR, TIME, MASK> */
struct line_api
{
//float m_duration, m_segment_size;
//vec4 m_color;
array<vec3, vec3, vec4, float, int, bool, bool> m_lines;
int /*m_mask,*/ m_debug_mask;
std::shared_ptr<Shader> m_shader;
std::shared_ptr<VertexDeclaration> m_vdecl;
}
m_line_api;

/* The old tiles API */
struct tile_api
{
int m_cam;
array<Tile> m_tiles;
array<Tile> m_palettes;
array<Light *> m_lights;

std::shared_ptr<Shader> m_shader;
std::shared_ptr<Shader> m_palette_shader;

std::shared_ptr<VertexDeclaration> m_vdecl;
array<std::shared_ptr<VertexBuffer>> m_bufs;
}
m_tile_api;
};

} /* namespace lol */


Loading…
Cancel
Save