initial import, >900commits predate this

This commit is contained in:
2020-09-29 13:47:50 +02:00
commit e74154ccee
352 changed files with 108120 additions and 0 deletions

View File

@ -0,0 +1,203 @@
cmake_minimum_required(VERSION 3.2)
project(opengl_renderer CXX)
add_library(opengl_renderer_s
src/mm/opengl/render_task.hpp
src/mm/services/opengl_renderer.hpp
src/mm/services/opengl_renderer.cpp
src/mm/opengl/camera_3d.hpp
src/mm/opengl/camera_3d.cpp
)
target_include_directories(opengl_renderer_s PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
add_definitions(-DGLM_ENABLE_EXPERIMENTAL)
target_link_libraries(opengl_renderer_s
engine
logger
opengl_primitives
sdl_service
)
if(EMSCRIPTEN)
set_target_properties(opengl_renderer_s PROPERTIES COMPILE_FLAGS "-s USE_SDL=2")
set_target_properties(opengl_renderer_s PROPERTIES LINK_FLAGS "-s USE_SDL=2")
endif()
############# imgui render task ###########
add_library(imgui_render_task
src/mm/opengl/render_tasks/imgui.hpp
src/mm/opengl/render_tasks/imgui.cpp
)
target_include_directories(imgui_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
#add_definitions(-DGLM_ENABLE_EXPERIMENTAL)
target_link_libraries(imgui_render_task
opengl_renderer_s
imgui
icon_font_cpp_headers
)
############# simple rect render task ###########
add_library(simple_rect_render_task
src/mm/opengl/render_tasks/simple_rect.hpp
src/mm/opengl/render_tasks/simple_rect.cpp
)
target_include_directories(simple_rect_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(simple_rect_render_task
opengl_renderer_s
common_components
engine
)
############# simple sprite render task ###########
add_library(simple_sprite_render_task
src/mm/opengl/render_tasks/simple_sprite.hpp
src/mm/opengl/render_tasks/simple_sprite.cpp
)
target_include_directories(simple_sprite_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(simple_sprite_render_task
opengl_renderer_s
common_components
engine
)
############# simple spritesheet render task ###########
add_library(simple_spritesheet_render_task
src/mm/opengl/render_tasks/simple_spritesheet.hpp
src/mm/opengl/render_tasks/spritesheet_renderable.hpp
src/mm/opengl/render_tasks/simple_spritesheet.cpp
)
target_include_directories(simple_spritesheet_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(simple_spritesheet_render_task
opengl_renderer_s
common_components
engine
)
############# batched spritesheet render task ###########
add_library(batched_spritesheet_render_task
src/mm/opengl/render_tasks/batched_spritesheet.hpp
src/mm/opengl/render_tasks/spritesheet_renderable.hpp # dup?
src/mm/opengl/render_tasks/batched_spritesheet.cpp
)
target_include_directories(batched_spritesheet_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(batched_spritesheet_render_task
opengl_renderer_s
common_components
engine
)
############# clear render task ###########
add_library(clear_render_task
src/mm/opengl/render_tasks/clear.hpp
src/mm/opengl/render_tasks/clear.cpp
)
target_include_directories(clear_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(clear_render_task
opengl_renderer_s
engine
)
############# blit fb render task ###########
add_library(blit_fb_render_task
src/mm/opengl/render_tasks/blit_fb.hpp
src/mm/opengl/render_tasks/blit_fb.cpp
)
target_include_directories(blit_fb_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(blit_fb_render_task
opengl_renderer_s
engine
)
############# copy to fb render task ###########
add_library(copy_to_fb_render_task
src/mm/opengl/render_tasks/copy_to_fb.hpp
src/mm/opengl/render_tasks/copy_to_fb.cpp
)
target_include_directories(copy_to_fb_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(copy_to_fb_render_task
opengl_renderer_s
engine
)
############# blur render task ###########
add_library(blur_render_task
src/mm/opengl/render_tasks/blur.hpp
src/mm/opengl/render_tasks/blur.cpp
)
target_include_directories(blur_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(blur_render_task
opengl_renderer_s
engine
)
############# tilemap renderer ###########
add_library(tilemap_render_task
src/mm/opengl/render_tasks/tilemap.hpp
src/mm/opengl/render_tasks/tilemap_renderable.hpp
src/mm/opengl/render_tasks/tilemap.cpp
)
target_include_directories(tilemap_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(tilemap_render_task
opengl_renderer_s
engine
common_components
)
############# fast sky render task ###########
add_library(fast_sky_render_task
src/mm/opengl/render_tasks/fast_sky_render_task.hpp
src/mm/opengl/render_tasks/fast_sky_render_task.cpp
)
target_include_directories(fast_sky_render_task PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(fast_sky_render_task
opengl_renderer_s
engine
)
########################
if (BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,182 @@
#include "./camera_3d.hpp"
#include <glm/gtc/matrix_transform.hpp>
namespace MM::OpenGL {
Camera3D::Camera3D(void) {
updateView();
}
void Camera3D::setOrthographic(void) {
ortho = true;
_projection = glm::ortho(
-horizontalViewPortSize / 2,
horizontalViewPortSize / 2,
-horizontalViewPortSize / (screenRatio * 2),
horizontalViewPortSize / (screenRatio * 2),
nearPlane,
farPlane
);
}
void Camera3D::setPerspective(void) {
ortho = false;
_projection = glm::perspective(fov, screenRatio, nearPlane, farPlane);
}
void Camera3D::updateView(void) {
roll = glm::mod(roll, 2*glm::pi<float>());
if (ortho) {
_view = glm::mat4(1);
_view = glm::rotate(_view, roll, glm::vec3{0.f, 0.f, 1.f});
auto tmp_trans = glm::mat4(1);
tmp_trans[3] = glm::vec4(-translation.x, -translation.y, 0.f, 1.f);
_view = _view * tmp_trans;
//_view[3] = glm::vec4(-translation.x, -translation.y, 0.f, 1.f);
////_view[3] = glm::vec4(-translation.x, -translation.y, 1.0f, 1.f);
//_view = glm::translate(_view, glm::vec3{-translation.x, -translation.y, -1.f});
//_view = glm::inverse(_view);
_view[2][2] = -1.f;
// TODO: please fix me
} else {
pitch = glm::clamp(pitch, -(glm::pi<float>()/2 - 0.00001f), glm::pi<float>()/2 - 0.00001f);
yaw = glm::mod(yaw, 2*glm::pi<float>());
glm::vec3 front {0,0,0};
{ // TODO: optimize
// if y up/down
front.x += up.y * glm::cos(pitch) * glm::cos(-yaw); // TODO: y is yaw inverted??
front.y += up.y * glm::sin(pitch);
front.z += up.y * glm::cos(pitch) * glm::sin(-yaw);
// if z up/down
front.x += up.z * glm::cos(pitch) * glm::cos(yaw);
front.y += up.z * glm::cos(pitch) * glm::sin(yaw);
front.z += up.z * glm::sin(pitch);
}
front = glm::normalize(front);
_view = glm::lookAt(translation, translation + front, up);
}
}
glm::mat4 Camera3D::getViewProjection() const {
return _projection * _view;
}
glm::mat4 Camera3D::getView() const {
return _view;
}
glm::mat4 Camera3D::getProjection() const {
return _projection;
}
std::array<glm::vec4, 6> Camera3D::getFrustumPlanes(void) const {
std::array<glm::vec4, 6> planes;
glm::mat4 wvp = getViewProjection();
// see:
// https://stackoverflow.com/questions/11770262/glm-calculating-the-frustum-from-the-projection-matrix
// http://web.archive.org/web/20120531231005/http://crazyjoke.free.fr/doc/3D/plane%20extraction.pdf
#ifdef LEFT_HANDED
// left handed
{
// Left clipping plane
planes[0].x = wvp[0][3] + wvp[0][0];
planes[0].y = wvp[1][3] + wvp[1][0];
planes[0].z = wvp[2][3] + wvp[2][0];
planes[0].w = wvp[3][3] + wvp[3][0];
// Right clipping plane
planes[1].x = wvp[0][3] - wvp[0][0];
planes[1].y = wvp[1][3] - wvp[1][0];
planes[1].z = wvp[2][3] - wvp[2][0];
planes[1].w = wvp[3][3] - wvp[3][0];
// Top clipping
planes[2].x = wvp[0][3] - wvp[0][1];
planes[2].y = wvp[1][3] - wvp[1][1];
planes[2].z = wvp[2][3] - wvp[2][1];
planes[2].w = wvp[3][3] - wvp[3][1];
// Bottom clipping plane
planes[3].x = wvp[0][3] + wvp[0][1];
planes[3].y = wvp[1][3] + wvp[1][1];
planes[3].z = wvp[2][3] + wvp[2][1];
planes[3].w = wvp[3][3] + wvp[3][1];
// Near clipping plane
planes[4].x = wvp[0][2];
planes[4].y = wvp[1][2];
planes[4].z = wvp[2][2];
planes[4].w = wvp[3][2];
// Far clipping
planes[5].x = wvp[0][3] - wvp[0][2];
planes[5].y = wvp[1][3] - wvp[1][2];
planes[5].z = wvp[2][3] - wvp[2][2];
planes[5].w = wvp[3][3] - wvp[3][2];
}
#else
// right handed
{
// Left clipping plane
planes[0].x = wvp[0][3] + wvp[0][0];
planes[0].y = wvp[1][3] + wvp[1][0];
planes[0].z = wvp[2][3] + wvp[2][0];
planes[0].w = wvp[3][3] + wvp[3][0];
// Right clipping plane
planes[1].x = wvp[0][3] - wvp[0][0];
planes[1].y = wvp[1][3] - wvp[1][0];
planes[1].z = wvp[2][3] - wvp[2][0];
planes[1].w = wvp[3][3] - wvp[3][0];
// Top clipping plane
planes[2].x = wvp[0][3] - wvp[0][1];
planes[2].y = wvp[1][3] - wvp[1][1];
planes[2].z = wvp[2][3] - wvp[2][1];
planes[2].w = wvp[3][3] - wvp[3][1];
// Bottom clipping plane
planes[3].x = wvp[0][3] + wvp[0][1];
planes[3].y = wvp[1][3] + wvp[1][1];
planes[3].z = wvp[2][3] + wvp[2][1];
planes[3].w = wvp[3][3] + wvp[3][1];
// Near clipping plane
planes[4].x = wvp[0][3] + wvp[0][2];
planes[4].y = wvp[1][3] + wvp[1][2];
planes[4].z = wvp[2][3] + wvp[2][2];
planes[4].w = wvp[3][3] + wvp[3][2];
// Far clipping plane
planes[5].x = wvp[0][3] - wvp[0][2];
planes[5].y = wvp[1][3] - wvp[1][2];
planes[5].z = wvp[2][3] - wvp[2][2];
planes[5].w = wvp[3][3] - wvp[3][2];
}
#endif
// normalize
for (size_t i = 0; i < 6; i++) {
planes[i] = glm::normalize(planes[i]);
//planes[i] /= glm::length(glm::vec3(planes[i]));
}
return planes;
}
} // MM::Rendering

View File

@ -0,0 +1,54 @@
#pragma once
#include <glm/mat4x4.hpp>
#include <glm/gtc/constants.hpp>
#include <array>
namespace MM::OpenGL {
class Camera3D {
private:
glm::mat4 _view{1}, _projection{1};
public:
glm::vec3 translation {0.f, 0.f, 0.f};
float screenRatio {16.f / 9.f};
float nearPlane {0.1f};
float farPlane {1000.f};
// for orth and pers
float roll {0.f}; // in rad
bool ortho {true};
// for orthogonal
float horizontalViewPortSize {100.f}; // 100 meters
// for perspective (right handed, z up)
float fov {glm::half_pi<float>()}; // in rad
float yaw {0.f}; // in rad
float pitch {0.f}; // in rad
glm::vec3 up {0.f, 0.f, 1.f}; // normalize!
public:
Camera3D(void);
// call this if ortho and horizontalViewPortSize or screenRatio changes
void setOrthographic(void);
// call this if not ortho and fov or screenRation changes
void setPerspective(void);
// call this after changing translation
void updateView(void);
glm::mat4 getViewProjection(void) const;
glm::mat4 getView(void) const;
glm::mat4 getProjection(void) const;
// call updateView beforehand, does not cache
std::array<glm::vec4, 6> getFrustumPlanes(void) const;
};
} // MM::OpenGL

View File

@ -0,0 +1,32 @@
#pragma once
#include <vector>
// fwd
namespace MM {
class Engine;
namespace Services {
class OpenGLRenderer;
}
}
#ifdef MM_OPENGL_3_GLES
#define GLSL_VERSION_STRING "#version 300 es\n"
#else
#define GLSL_VERSION_STRING "#version 330 core\n"
#endif
namespace MM::OpenGL {
class RenderTask {
public:
virtual ~RenderTask(void) = default;
virtual void render(Services::OpenGLRenderer& rs, Engine& engine) = 0;
// a place to reload/compile shaders etc.
//virtual void reload(void) {} // TODO: remove
//virtual std::vector<const char*> getShaderPaths(void) {return {};} // TODO: remove
};
}

View File

@ -0,0 +1,244 @@
#include "./batched_spritesheet.hpp"
#include <memory>
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include "./spritesheet_renderable.hpp"
#include <mm/services/opengl_renderer.hpp>
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
namespace MM::OpenGL::RenderTasks {
BatchedSpriteSheet::BatchedSpriteSheet(Engine& engine) {
default_cam.setOrthographic();
default_cam.updateView();
float vertices[] = {
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
gl_inst_buffer = std::make_unique<MM::OpenGL::InstanceBuffer<gl_instance_data>>();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
BatchedSpriteSheet::~BatchedSpriteSheet(void) {
}
void BatchedSpriteSheet::render(Services::OpenGLRenderer& rs, Engine& engine) {
ZoneScopedN("MM::OpenGL::RenderTasks::BatchedSpriteSheet::render");
auto* scene_ss = engine.tryService<MM::Services::SceneServiceInterface>();
// no scene
if (scene_ss == nullptr) {
return;
}
auto& scene = scene_ss->getScene();
struct sp_data {
SpriteSheet sp;
struct instance_data {
MM::Components::Transform2D* trans = nullptr;
glm::vec4* color = nullptr;
uint32_t tile_index = 0;
};
std::vector<instance_data> instances;
};
// HACK: assume same sp for same texture
std::unordered_map<MM::OpenGL::Texture::handle, sp_data> batch_map;
auto view = scene.view<Components::Transform2D, SpriteSheetRenderable>();
view.each([&](auto e, Components::Transform2D& t, SpriteSheetRenderable& spr) {
// if off screen, early out
if (false) { // TODO:
return;
}
assert(spr.sp.tex); // debug
// first insert
if (!batch_map.count(spr.sp.tex)) {
auto& sp_ent = batch_map[spr.sp.tex];
sp_ent.sp = spr.sp;
}
auto* tmp_col_ptr = &default_color;
if (scene.has<Components::Color>(e)) {
tmp_col_ptr = &scene.get<Components::Color>(e).color;
}
auto& tmp_new_ent = batch_map[spr.sp.tex].instances.emplace_back();
tmp_new_ent.trans = &t;
tmp_new_ent.tile_index = spr.tile_index;
tmp_new_ent.color = tmp_col_ptr;
});
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto* cam = scene.try_ctx<Camera3D>();
if (!cam) {
cam = &default_cam;
}
auto vp = cam->getViewProjection();
_shader->setUniformMat4f("_VP", vp);
for (auto& sp_ent : batch_map) {
TracyGpuZone("MM::OpenGL::RenderTasks::BatchedSpriteSheet::render::sprite_entry");
sp_ent.second.sp.tex->bind(0);
_shader->setUniform2ui("_tileCount", sp_ent.second.sp.tile_count.x, sp_ent.second.sp.tile_count.y);
auto* inst_memory = gl_inst_buffer->map(sp_ent.second.instances.size(), GL_DYNAMIC_DRAW);
for (auto& inst : sp_ent.second.instances) {
inst_memory->pos_trans = inst.trans->getTransform4(inst.trans->position.y/10.f + 500.f);
inst_memory->color = *inst.color;
inst_memory->tile_index = inst.tile_index;
inst_memory++;
}
gl_inst_buffer->unmap();
static_assert(std::is_standard_layout<gl_instance_data>::value); // check if offsetof() is usable
// mat4, oof
// attptr 1-4
for (size_t i = 0; i < 4; i++) {
glVertexAttribPointer(
1 + i,
4,
GL_FLOAT, GL_FALSE,
sizeof(gl_instance_data),
(void*) (offsetof(gl_instance_data, pos_trans) + sizeof(glm::mat4::row_type) * i)
);
glVertexAttribDivisor(1 + i, 1);
glEnableVertexAttribArray(1 + i);
}
glVertexAttribIPointer(5, 1, GL_UNSIGNED_INT, sizeof(gl_instance_data), (void*) offsetof(gl_instance_data, tile_index));
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(5);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(gl_instance_data), (void*) offsetof(gl_instance_data, color));
glVertexAttribDivisor(6, 1);
glEnableVertexAttribArray(6);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, sp_ent.second.instances.size());
}
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void BatchedSpriteSheet::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 _VP;
uniform uvec2 _tileCount;
layout(location = 0) in vec2 _vertexPosition;
layout(location = 1) in mat4 _pos_trans;
layout(location = 5) in uint _atlasIndex;
layout(location = 6) in vec4 _color;
out vec2 _tex_pos;
out vec4 _tex_color;
void main() {
// fwd
_tex_color = _color;
// position
gl_Position = _VP * _pos_trans * vec4(_vertexPosition, 0, 1);
// uv
uint row = _atlasIndex / _tileCount.x;
uint column = _atlasIndex % _tileCount.x;
_tex_pos.x = (float(column) + 0.5 + _vertexPosition.x) / float(_tileCount.x);
_tex_pos.y = 1.0 - (float(row) + 0.5 - _vertexPosition.y) / float(_tileCount.y);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D _tex0;
in vec2 _tex_pos;
in vec4 _tex_color;
out vec4 _out_color;
void main() {
vec4 tmp_col = texture(_tex0, _tex_pos) * _tex_color;
if (tmp_col.a == 0.0) {
discard;
}
_out_color = tmp_col;
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,58 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
#include <mm/opengl/camera_3d.hpp>
//#include <glm/fwd.hpp>
#include <glm/vec4.hpp>
#include <mm/opengl/instance_buffer.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class BatchedSpriteSheet : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
struct gl_instance_data {
glm::mat4 pos_trans;
glm::vec4 color;
uint32_t tile_index;
};
std::unique_ptr<MM::OpenGL::InstanceBuffer<gl_instance_data>> gl_inst_buffer;
public:
glm::vec4 default_color {1.f, 1.f, 1.f, 1.f};
OpenGL::Camera3D default_cam;
BatchedSpriteSheet(Engine& engine);
~BatchedSpriteSheet(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/batched_spritesheet_render_task/vert.glsl";
const char* fragmentPath = "shader/batched_spritesheet_render_task/frag.glsl";
std::string target_fbo = "display";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,40 @@
#include "./blit_fb.hpp"
#include <mm/services/sdl_service.hpp>
#include <tracy/Tracy.hpp>
namespace MM::OpenGL::RenderTasks {
BlitFB::BlitFB(Engine& engine) {
// assuming fbo textures are the size of the window buffer
auto [x, y] = engine.getService<MM::Services::SDLService>().getWindowSize();
srcX1 = x;
srcY1 = y;
dstX1 = x;
dstY1 = y;
}
BlitFB::~BlitFB(void) {
}
void BlitFB::render(Services::OpenGLRenderer& rs, Engine&) {
ZoneScopedN("MM::OpenGL::RenderTasks::BlitFB::render");
rs.targets[read_fbo]->bind(FrameBufferObject::R);
rs.targets[write_fbo]->bind(FrameBufferObject::W);
glBlitFramebuffer(
srcX0, srcY0,
srcX1, srcY1,
dstX0, dstY0,
dstX1, dstY1,
mask,
filter
);
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,36 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
namespace MM::OpenGL::RenderTasks {
class BlitFB : public RenderTask {
public:
BlitFB(Engine& engine);
~BlitFB(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
std::string read_fbo = "game_view";
std::string write_fbo = "display";
// blit params
GLint srcX0 = 0;
GLint srcY0 = 0;
GLint srcX1 = 0; // u will want to set this
GLint srcY1 = 0; // u will want to set this
GLint dstX0 = 0;
GLint dstY0 = 0;
GLint dstX1 = 0; // u will want to set this
GLint dstY1 = 0; // u will want to set this
GLbitfield mask = GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;
GLenum filter = GL_NEAREST;
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,135 @@
#include "./blur.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/opengl/texture.hpp>
#include <tracy/Tracy.hpp>
namespace MM::OpenGL::RenderTasks {
Blur::Blur(Engine& engine) {
float vertices[] = {
-1.f, 1.f,
-1.f, -1.f,
1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
Blur::~Blur(void) {
}
void Blur::render(Services::OpenGLRenderer& rs, Engine&) {
ZoneScopedN("MM::OpenGL::RenderTasks::Blur::render");
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glDisable(GL_DEPTH_TEST);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
rs.targets[src_fbo]->bind(FrameBufferObject::W);
{
_shader->setUniform1i("horizontal", 1);
rs.targets[src_fbo]->_texAttachments.front()->bind(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
rs.targets[target_fbo]->bind(FrameBufferObject::W);
{
_shader->setUniform1i("horizontal", 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
rs.targets[src_fbo]->clear(0.f, 0.f, 0.f, 1.f);
}
void Blur::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 _vertexPosition;
out vec2 _tex;
void main() {
gl_Position = vec4(_vertexPosition, 0, 1);
_tex = vec2(_vertexPosition.x * 0.5 + 0.5, _vertexPosition.y * 0.5 + 0.5);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D tex0;
in vec2 _tex;
uniform bool horizontal;
const float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
out vec4 _out_color;
void main() {
vec2 tex_offset = vec2(1.0) / vec2(textureSize(tex0, 0)); // gets size of single texel
vec3 result = texture(tex0, _tex).rgb * weight[0]; // current fragment's contribution
if (horizontal) {
for (int i = 1; i < 5; i++) {
result += texture(tex0, _tex + vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i];
result += texture(tex0, _tex - vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i];
}
} else {
for (int i = 1; i < 5; i++) {
result += texture(tex0, _tex + vec2(0.0, tex_offset.y * float(i))).rgb * weight[i];
result += texture(tex0, _tex - vec2(0.0, tex_offset.y * float(i))).rgb * weight[i];
}
}
_out_color = vec4(result, 1.0);
//float brightness = dot(gl_FragColor.rgb, vec3(0.2126, 0.7152, 0.0722));
//if (brightness > 1.0)
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,39 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class Blur : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
Blur(Engine& engine);
~Blur(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/blur_render_task/vert.glsl";
const char* fragmentPath = "shader/blur_render_task/frag.glsl";
std::string target_fbo = "blur_out";
std::string src_fbo = "blur_in";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,19 @@
#include "./clear.hpp"
//#include <tracy/Tracy.hpp>
namespace MM::OpenGL::RenderTasks {
Clear::Clear(Engine&) {
}
Clear::~Clear(void) {
}
void Clear::render(Services::OpenGLRenderer& rs, Engine&) {
//ZoneScopedN("MM::OpenGL::RenderTasks::Clear::render");
rs.targets[target_fbo]->clear(r,g,b,a,mask);
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,26 @@
#pragma once
#include <mm/services/opengl_renderer.hpp>
namespace MM::OpenGL::RenderTasks {
class Clear : public RenderTask {
public:
Clear(Engine& engine);
~Clear(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
std::string target_fbo = "display";
float r = 0.f;
float g = 0.f;
float b = 0.f;
float a = 1.f;
GLbitfield mask = GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,110 @@
#include "./copy_to_fb.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/opengl/texture.hpp>
#include <tracy/Tracy.hpp>
namespace MM::OpenGL::RenderTasks {
CopyToFB::CopyToFB(Engine& engine) {
float vertices[] = {
-1.f, 1.f,
-1.f, -1.f,
1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
CopyToFB::~CopyToFB(void) {
}
void CopyToFB::render(Services::OpenGLRenderer& rs, Engine&) {
ZoneScopedN("MM::OpenGL::RenderTasks::CopyToFB::render");
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glDisable(GL_DEPTH_TEST);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto& rm = MM::ResourceManager<MM::OpenGL::Texture>::ref();
auto tex = rm.get(entt::hashed_string::value(src_tex.c_str()));
tex->bind(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void CopyToFB::reloadShaders(MM::Engine& engine) {
auto tmp_shader = Shader::createF(engine, vertexPath, fragmentPath);
if (tmp_shader) {
_shader = tmp_shader;
}
}
void CopyToFB::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 _vertexPosition;
out vec2 _tex;
void main() {
gl_Position = vec4(_vertexPosition, 0, 1);
_tex = vec2(_vertexPosition.x * 0.5 + 0.5, _vertexPosition.y * 0.5 + 0.5);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D tex0;
in vec2 _tex;
out vec4 _out_color;
void main() {
_out_color = texture(tex0, _tex);
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,41 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class CopyToFB : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
CopyToFB(Engine& engine);
~CopyToFB(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/copy_to_fb_render_task/vert.glsl";
const char* fragmentPath = "shader/copy_to_fb_render_task/frag.glsl";
std::string target_fbo = "display";
std::string src_tex = "game_view";
void reloadShaders(Engine& engine);
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,231 @@
#include "./fast_sky_render_task.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/opengl/camera_3d.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
namespace MM::OpenGL::RenderTasks {
FastSky::FastSky(MM::Engine& engine) {
setupShaderFiles();
_shader = MM::OpenGL::Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
float vertices[] = {
-1.f, 1.f,
-1.f, -1.f,
1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f,
};
_vertexBuffer = std::make_unique<MM::OpenGL::Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<MM::OpenGL::VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
}
FastSky::~FastSky(void) {
}
void FastSky::render(MM::Services::OpenGLRenderer& rs, MM::Engine& engine) {
ZoneScopedN("MM::OpenGL::RenderTasks::FastSky::render");
rs.targets[target_fbo]->bind(MM::OpenGL::FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glDepthFunc(GL_LESS);
glDisable(GL_BLEND); // i hate my life
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
{
auto& cam = scene.ctx<MM::OpenGL::Camera3D>();
MM::OpenGL::Camera3D tmp_cam = cam;
// create cam with y up, bc shader says so
tmp_cam.up = {0, 1, 0};
tmp_cam.updateView();
_shader->setUniformMat4f("V", tmp_cam.getView());
_shader->setUniformMat4f("P", cam.getProjection());
}
{
auto* ctx_ptr = scene.try_ctx<FastSkyContext>();
if (!ctx_ptr) {
ctx_ptr = &_default_context;
}
_shader->setUniform1f("time", ctx_ptr->time);
_shader->setUniform1f("cirrus", ctx_ptr->cirrus);
_shader->setUniform1f("cumulus", ctx_ptr->cumulus);
_shader->setUniform3f("fsun", ctx_ptr->fsun);
}
//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLES, 0, 6);
_shader->unbind();
}
void FastSky::reloadShaders(MM::Engine& engine) {
auto tmp_shader = MM::OpenGL::Shader::createF(engine, vertexPath, fragmentPath);
if (tmp_shader) {
_shader = tmp_shader;
}
}
// the shaders are based on https://github.com/shff/opengl_sky/
// with the following LICENSE:
// MIT License
//Copyright (c) 2019 Silvio Henrique Ferreira
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
void FastSky::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 vertex_pos;
out vec3 pos;
uniform mat4 P;
uniform mat4 V;
void main() {
vec4 tmp_pos = vec4(vertex_pos, 1.0, 1.0);
gl_Position = tmp_pos;
pos = transpose(mat3(V)) * (inverse(P) * tmp_pos).xyz;
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec3 pos;
uniform vec3 fsun;
out vec4 color;
uniform float time;
uniform float cirrus;
uniform float cumulus;
const float Br = 0.0025;
const float Bm = 0.0003;
const float g = 0.9800;
const vec3 nitrogen = vec3(0.650, 0.570, 0.475);
const vec3 Kr = Br / pow(nitrogen, vec3(4.0));
const vec3 Km = Bm / pow(nitrogen, vec3(0.84));
float hash(float n) {
return fract(sin(n) * 43758.5453123);
}
float noise(vec3 x) {
vec3 f = fract(x);
float n = dot(floor(x), vec3(1.0, 157.0, 113.0));
return mix(mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
mix(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
}
const mat3 m = mat3(0.0, 1.60, 1.20, -1.6, 0.72, -0.96, -1.2, -0.96, 1.28);
float fbm(vec3 p) {
float f = 0.0;
f += noise(p) / 2.0; p = m * p * 1.1;
f += noise(p) / 4.0; p = m * p * 1.2;
f += noise(p) / 6.0; p = m * p * 1.3;
f += noise(p) / 12.0; p = m * p * 1.4;
f += noise(p) / 24.0;
return f;
}
void main() {
if (pos.y < 0.0) {
discard;
//return;
}
// Atmosphere Scattering
float mu = dot(normalize(pos), normalize(fsun));
vec3 extinction = mix(exp(-exp(-((pos.y + fsun.y * 4.0) * (exp(-pos.y * 16.0) + 0.1) / 80.0) / Br) * (exp(-pos.y * 16.0) + 0.1) * Kr / Br) * exp(-pos.y * exp(-pos.y * 8.0 ) * 4.0) * exp(-pos.y * 2.0) * 4.0, vec3(1.0 - exp(fsun.y)) * 0.2, -fsun.y * 0.2 + 0.5);
color.rgb = 3.0 / (8.0 * 3.14) * (1.0 + mu * mu) * (Kr + Km * (1.0 - g * g) / (2.0 + g * g) / pow(1.0 + g * g - 2.0 * g * mu, 1.5)) / (Br + Bm) * extinction;
// Cirrus Clouds
float density = smoothstep(1.0 - cirrus, 1.0, fbm(pos.xyz / pos.y * 2.0 + time * 0.05)) * 0.3;
color.rgb = mix(color.rgb, extinction * 4.0, density * max(pos.y, 0.0));
// Cumulus Clouds
for (int i = 0; i < 3; i++) {
float density = smoothstep(1.0 - cumulus, 1.0, fbm((0.7 + float(i) * 0.01) * pos.xyz / pos.y + time * 0.3));
color.rgb = mix(color.rgb, extinction * density * 5.0, min(density, 1.0) * max(pos.y, 0.0));
}
// Dithering Noise
color.rgb += noise(pos * 1000.0) * 0.01; // needed?
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,53 @@
#pragma once
#include <mm/services/opengl_renderer.hpp>
#include <glm/vec3.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
namespace RenderTasks {
struct FastSkyContext {
float time = 0.f;
float cirrus = 0.4f;
float cumulus = 0.8f;
glm::vec3 fsun {0,0,1};
};
class FastSky : public MM::OpenGL::RenderTask {
private:
std::shared_ptr<MM::OpenGL::Shader> _shader;
std::unique_ptr<MM::OpenGL::Buffer> _vertexBuffer;
std::unique_ptr<MM::OpenGL::VertexArrayObject> _vao;
FastSkyContext _default_context;
public:
FastSky(MM::Engine& engine);
~FastSky(void);
void render(MM::Services::OpenGLRenderer& rs, MM::Engine& engine) override;
public:
const char* vertexPath = "shader/fast_sky_render_task/vert.glsl";
const char* fragmentPath = "shader/fast_sky_render_task/frag.glsl";
std::string target_fbo = "display";
void reloadShaders(MM::Engine& engine);
private:
void setupShaderFiles(void);
};
} // RenderTasks
} // MM::OpenGL

View File

@ -0,0 +1,38 @@
#include <mm/opengl/render_tasks/imgui.hpp> // bc imgui.hpp is overused
#include <mm/engine.hpp>
#include <imgui/imgui.h>
#include <imgui_impl_opengl3.h>
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
namespace MM::OpenGL::RenderTasks {
ImGuiRT::ImGuiRT(Engine&) {
assert(ImGui::GetCurrentContext());
}
ImGuiRT::~ImGuiRT(void) {
}
void ImGuiRT::render(Services::OpenGLRenderer& rs, Engine&) {
ZoneScopedN("MM::OpenGL::RenderTasks::ImGuiRT::render");
TracyGpuZone("MM::OpenGL::RenderTasks::ImGuiRT::render");
rs.targets["display"]->bind(FrameBufferObject::W);
// render
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,18 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
namespace MM::OpenGL::RenderTasks {
// RT to avoid name collisons
class ImGuiRT : public RenderTask {
public:
ImGuiRT(Engine& engine);
~ImGuiRT(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,134 @@
#include "./simple_rect.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include <tracy/Tracy.hpp>
#include <mm/logger.hpp>
#define LOG_SRR(x) LOG("SimpleRectRenderTask", x)
namespace MM::OpenGL::RenderTasks {
SimpleRect::SimpleRect(Engine& engine) {
default_cam.setOrthographic();
default_cam.updateView();
float vertices[] = {
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
SimpleRect::~SimpleRect(void) {
}
void SimpleRect::render(Services::OpenGLRenderer& rs, Engine& engine) {
ZoneScopedN("MM::OpenGL::RenderTasks::SimpleRect::render");
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
//_shader->setUniform4f("_color", default_color);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
Camera3D* cam = scene.try_ctx<Camera3D>();
if (!cam) {
cam = &default_cam;
}
auto vp = cam->getViewProjection();
auto view = scene.view<MM::Components::Transform2D>();
for (auto& e : view) {
auto& t = view.get(e);
_shader->setUniformMat4f("_WVP", vp * t.getTransform4(t.position.y/10.f + 500.f));
if (scene.has<Components::Color>(e)) {
_shader->setUniform4f("_color", scene.get<Components::Color>(e).color);
} else {
_shader->setUniform4f("_color", default_color);
}
glDrawArrays(GL_TRIANGLES, 0, 6);
}
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void SimpleRect::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 _vertexPosition;
uniform mat4 _WVP;
void main() {
gl_Position = _WVP * vec4(_vertexPosition, 0, 1);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 _color;
out vec4 _out_color;
void main() {
_out_color = _color;
//gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,47 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
#include <mm/opengl/camera_3d.hpp>
//#include <glm/fwd.hpp>
#include <glm/vec4.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class SimpleRect : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
glm::vec4 default_color {1,1,1,1};
Camera3D default_cam;
SimpleRect(Engine& engine);
~SimpleRect(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/simple_rect_render_task/vert.glsl";
const char* fragmentPath = "shader/simple_rect_render_task/frag.glsl";
std::string target_fbo = "display";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,153 @@
#include "./simple_sprite.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/opengl/components/texture.hpp>
#include <mm/components/color.hpp>
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
namespace MM::OpenGL::RenderTasks {
SimpleSprite::SimpleSprite(Engine& engine) {
default_cam.setOrthographic();
default_cam.updateView();
float vertices[] = {
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
SimpleSprite::~SimpleSprite(void) {
}
void SimpleSprite::render(Services::OpenGLRenderer& rs, Engine& engine) {
ZoneScopedN("MM::OpenGL::RenderTasks::SimpleSprite::render");
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
auto* cam = scene.try_ctx<Camera3D>();
if (!cam) {
cam = &default_cam;
}
auto vp = cam->getViewProjection();
auto view = scene.view<Components::Transform2D, Components::OpenGL::Texture>();
view.each([&](auto e, Components::Transform2D& t, Components::OpenGL::Texture& tex) {
assert(tex.tex); // debug
tex.tex->bind(0);
_shader->setUniformMat4f("_WVP", vp * t.getTransform4(t.position.y/10.f + 500.f));
if (scene.has<Components::Color>(e)) {
_shader->setUniform4f("_color", scene.get<Components::Color>(e).color);
} else {
_shader->setUniform4f("_color", default_color);
}
glDrawArrays(GL_TRIANGLES, 0, 6);
});
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void SimpleSprite::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 _vertexPosition;
uniform mat4 _WVP;
out vec2 _tex_pos;
void main() {
gl_Position = _WVP * vec4(_vertexPosition, 0, 1);
_tex_pos = vec2(_vertexPosition.x + 0.5, _vertexPosition.y + 0.5);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 _color;
uniform sampler2D _tex0;
in vec2 _tex_pos;
out vec4 _out_color;
void main() {
vec4 tmp_col = texture(_tex0, _tex_pos) * _color;
if (tmp_col.a == 0.0) {
discard;
}
//gl_FragColor = tmp_col;
_out_color = tmp_col;
//gl_FragColor = texture(_tex0, _tex_pos) * _color;
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,47 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
#include <mm/opengl/camera_3d.hpp>
//#include <glm/fwd.hpp>
#include <glm/vec4.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class SimpleSprite : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
glm::vec4 default_color {1,1,1,1};
Camera3D default_cam;
SimpleSprite(Engine& engine);
~SimpleSprite(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/simple_sprite_render_task/vert.glsl";
const char* fragmentPath = "shader/simple_sprite_render_task/frag.glsl";
std::string target_fbo = "display";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,178 @@
#include "./simple_spritesheet.hpp"
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include "./spritesheet_renderable.hpp"
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
#include <mm/logger.hpp>
#define LOG_SSSR(x) LOG("SimpleSpriteSheetRenderTask", x)
namespace MM::OpenGL::RenderTasks {
SimpleSpriteSheet::SimpleSpriteSheet(Engine& engine) {
default_cam.setOrthographic();
default_cam.updateView();
float vertices[] = {
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
};
_vertexBuffer = std::make_unique<Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
if (!scene.try_ctx<Camera3D>()) {
LOG_SSSR("warn: scene has no Camera!");
}
}
SimpleSpriteSheet::~SimpleSpriteSheet(void) {
}
void SimpleSpriteSheet::render(Services::OpenGLRenderer& rs, Engine& engine) {
ZoneScopedN("MM::OpenGL::RenderTasks::SimpleSpriteSheet::render");
rs.targets[target_fbo]->bind(FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
auto* cam = scene.try_ctx<Camera3D>();
if (!cam) {
cam = &default_cam;
}
auto vp = cam->getViewProjection();
auto view = scene.view<Components::Transform2D, SpriteSheetRenderable>();
view.each([&](auto e, Components::Transform2D& t, SpriteSheetRenderable& spr) {
assert(spr.sp.tex); // debug
TracyGpuZone("MM::OpenGL::Renderers::SimpleSpriteSheetRenderer::render.each");
spr.sp.tex->bind(0);
_shader->setUniformMat4f("_WVP", vp * t.getTransform4(t.position.y/10.f + 500.f));
_shader->setUniform2ui("_tileCount", spr.sp.tile_count.x, spr.sp.tile_count.y);
_shader->setUniform1ui("_atlasIndex", spr.tile_index);
if (scene.has<Components::Color>(e)) {
_shader->setUniform4f("_color", scene.get<Components::Color>(e).color);
} else {
_shader->setUniform4f("_color", default_color);
}
glDrawArrays(GL_TRIANGLES, 0, 6);
});
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void SimpleSpriteSheet::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
in vec2 _vertexPosition;
uniform mat4 _WVP;
uniform uvec2 _tileCount;
uniform uint _atlasIndex;
out vec2 _tex_pos;
void main() {
// position
gl_Position = _WVP * vec4(_vertexPosition, 0, 1);
// uv
uint row = _atlasIndex / _tileCount.x;
uint column = _atlasIndex % _tileCount.x;
_tex_pos.x = (float(column) + 0.5 + _vertexPosition.x) / float(_tileCount.x);
_tex_pos.y = 1.0 - (float(row) + 0.5 - _vertexPosition.y) / float(_tileCount.y);
//_tex_pos = vec2(_vertexPosition.x + 0.5, _vertexPosition.y + 0.5);
})")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 _color;
uniform sampler2D _tex0;
in vec2 _tex_pos;
out vec4 _out_color;
void main() {
vec4 tmp_col = texture(_tex0, _tex_pos) * _color;
if (tmp_col.a == 0.0) {
discard;
}
//gl_FragColor = tmp_col;
_out_color = tmp_col;
//gl_FragColor = texture(_tex0, _tex_pos) * _color;
})")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,47 @@
#pragma once
#include "../render_task.hpp"
#include <mm/services/opengl_renderer.hpp>
#include <mm/opengl/camera_3d.hpp>
//#include <glm/fwd.hpp>
#include <glm/vec4.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class SimpleSpriteSheet : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
glm::vec4 default_color {1.f, 1.f, 1.f, 1.f};
Camera3D default_cam;
SimpleSpriteSheet(Engine& engine);
~SimpleSpriteSheet(void);
void render(Services::OpenGLRenderer& rs, Engine& engine) override;
public:
const char* vertexPath = "shader/simple_spritesheet_render_task/vert.glsl";
const char* fragmentPath = "shader/simple_spritesheet_render_task/frag.glsl";
std::string target_fbo = "display";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,12 @@
#include <mm/opengl/spritesheet.hpp>
namespace MM::OpenGL {
struct SpriteSheetRenderable {
SpriteSheet sp;
uint32_t tile_index = 0;
};
} // MM::OpenGL

View File

@ -0,0 +1,193 @@
#include <mm/opengl/render_tasks/tilemap.hpp>
#include <mm/opengl/shader.hpp>
#include <mm/opengl/buffer.hpp>
#include <mm/opengl/vertex_array_object.hpp>
#include <mm/fs_const_archiver.hpp>
#include <mm/engine.hpp>
#include <mm/services/scene_service_interface.hpp>
#include <entt/entity/registry.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/opengl/components/texture.hpp>
#include <mm/components/color.hpp>
#include <mm/opengl/camera_3d.hpp>
#include "./tilemap_renderable.hpp"
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#define TracyGpuZone(...)
#endif
#include <mm/logger.hpp>
#define LOG_SSR(x) LOG("TilemapRenderTask", x)
namespace MM::OpenGL::RenderTasks {
Tilemap::Tilemap(MM::Engine& engine) {
float vertices[] = {
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
};
_vertexBuffer = std::make_unique<MM::OpenGL::Buffer>(vertices, 2 * 6 * sizeof(float), GL_STATIC_DRAW);
_vao = std::make_unique<MM::OpenGL::VertexArrayObject>();
_vao->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(1); // Tilemap::Tile::pos
glEnableVertexAttribArray(2); // Tilemap::Tile::atlas_index
//glEnableVertexAttribArray(3); // Tilemap::Tile::color
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_vao->unbind();
setupShaderFiles();
_shader = MM::OpenGL::Shader::createF(engine, vertexPath, fragmentPath);
assert(_shader != nullptr);
}
Tilemap::~Tilemap(void) {
}
void Tilemap::render(MM::Services::OpenGLRenderer& rs, MM::Engine& engine) {
ZoneScopedN("MM::OpenGL::Renderers::TilemapRenderer::render");
rs.targets[target_fbo]->bind(MM::OpenGL::FrameBufferObject::W);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
_shader->bind();
_vertexBuffer->bind(GL_ARRAY_BUFFER);
_vao->bind();
auto& scene = engine.tryService<Services::SceneServiceInterface>()->getScene();
MM::OpenGL::Camera3D& cam = scene.ctx<MM::OpenGL::Camera3D>();
auto vp = cam.getViewProjection();
auto view = scene.view<MM::Components::Transform2D, OpenGL::TilemapRenderable>();
view.each([&](auto, MM::Components::Transform2D& t, OpenGL::TilemapRenderable& tilemap) {
_shader->setUniformMat4f("_WVP", vp * t.getTransform4(tilemap.z + 500.f));
// for each sprite layer
for (auto& sp_layer : tilemap.sprite_layer) {
assert(sp_layer.sprite_sheet.tex); // debug
assert(sp_layer.map_buffer);
assert(sp_layer.map_buffer->getSize());
sp_layer.sprite_sheet.tex->bind(0);
_shader->setUniform2ui("_tileCount", sp_layer.sprite_sheet.tile_count.x, sp_layer.sprite_sheet.tile_count.y);
// renderj
{
TracyGpuZone("MM::OpenGL::Renderers::TilemapRenderer::render.each_tilemap.each_sprite_layer");
sp_layer.map_buffer->bind();
OpenGL::TilemapRenderable::Tile::setupGLBindings();
glVertexAttribDivisor(1, 1);
glVertexAttribDivisor(2, 1);
//glVertexAttribDivisor(3, 1);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, sp_layer.map_buffer->getSize());
}
}
});
_vao->unbind();
_vertexBuffer->unbind(GL_ARRAY_BUFFER);
_shader->unbind();
}
void Tilemap::setupShaderFiles(void) {
FS_CONST_MOUNT_FILE(vertexPath,
GLSL_VERSION_STRING
R"(
uniform mat4 _WVP;
uniform uvec2 _tileCount;
layout(location = 0) in vec2 _vertexPosition;
layout(location = 1) in vec2 _tPos;
layout(location = 2) in uint _atlasIndex;
//layout(location = 3) in vec3 _tColor;
//out vec4 _color;
out vec2 _tex_pos;
void main() {
//gl_Position = vec4(_WVP * vec3(_vertexPosition, 1), 1);
//mat3 tmp = mat3(_WVP[0], _WVP[1], vec3(_WVP[2][0] * _tPos.x, _WVP[2][1] * _tPos.y, _WVP[2][2]));
//gl_Position = vec4(tmp * vec3(_vertexPosition, 1), 1);
mat4 tmp = mat4(1.0);
tmp[3] = vec4(_tPos.x, -_tPos.y, -_tPos.y / 10.f, 1);
gl_Position = (_WVP * tmp) * vec4(_vertexPosition, 0, 1);
//_color = vec4(_tColor, 1.0);
uint row = _atlasIndex / _tileCount.x;
uint column = _atlasIndex % _tileCount.x;
//_tex_pos = vec2(_vertexPosition.x + 0.5, _vertexPosition.y + 0.5);
//_tex_pos.x = _vertexPosition.x + 0.5;
_tex_pos.x = (float(column) + 0.5 + _vertexPosition.x) / float(_tileCount.x);
_tex_pos.y = 1.0 - (float(row) + 0.5 - _vertexPosition.y) / float(_tileCount.y);
//_tex_pos.y = _vertexPosition.y + 0.5;
}
)")
FS_CONST_MOUNT_FILE(fragmentPath,
GLSL_VERSION_STRING
R"(
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D _tex0;
//in vec4 _color;
in vec2 _tex_pos;
out vec4 _out_color;
void main() {
vec4 tmp_col = texture(_tex0, _tex_pos);
if (tmp_col.a == 0.0) {
discard;
}
//gl_FragColor = tmp_col;
_out_color = tmp_col;
//gl_FragColor = texture(_tex0, _tex_pos);
//gl_FragColor = texture(_tex0, _tex_pos) * _color;
//gl_FragColor = vec4(_tex_pos.x, _tex_pos.y, 0, 1);
}
)")
}
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,41 @@
#pragma once
#include <mm/opengl/render_task.hpp>
#include <mm/services/opengl_renderer.hpp>
//#include <glm/fwd.hpp>
#include <glm/vec4.hpp>
// fwd
namespace MM::OpenGL {
class Shader;
class Buffer;
class VertexArrayObject;
}
namespace MM::OpenGL::RenderTasks {
class Tilemap : public RenderTask {
private:
std::shared_ptr<Shader> _shader;
std::unique_ptr<Buffer> _vertexBuffer;
std::unique_ptr<VertexArrayObject> _vao;
public:
Tilemap(MM::Engine& engine);
~Tilemap(void);
void render(MM::Services::OpenGLRenderer& rs, MM::Engine& engine) override;
public:
const char* vertexPath = "shader/tilemap_render_task/vert.glsl";
const char* fragmentPath = "shader/tilemap_render_task/frag.glsl";
std::string target_fbo = "display";
private:
void setupShaderFiles(void);
};
} // MM::OpenGL::RenderTasks

View File

@ -0,0 +1,49 @@
#pragma once
#include <mm/opengl/texture.hpp>
#include <mm/opengl/instance_buffer.hpp>
#include <mm/opengl/spritesheet.hpp>
#include <cstring>
#include <string>
#include <vector>
namespace MM::OpenGL {
struct TilemapRenderable {
struct Tile {
float pos[2];
uint32_t sprite_sheet_index;
//float color[3] = {1.f, 1.f, 1.f};
static void setupGLBindings(void) {
static_assert(std::is_standard_layout<Tile>::value); // check if offsetof() is usable
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Tile), (void*) offsetof(Tile, pos));
glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, sizeof(Tile), (void*) offsetof(Tile, sprite_sheet_index));
//glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Tile), (void*) offsetof(Tile, color));
}
} /*__attribute__((packed))*/;
struct SpriteLayer {
MM::OpenGL::SpriteSheet sprite_sheet;
std::vector<Tile> map; // TODO: move this to tilemap
std::shared_ptr<MM::OpenGL::InstanceBuffer<Tile>> map_buffer = std::make_shared<MM::OpenGL::InstanceBuffer<Tile>>();
void syncMapBuffer(void) {
auto* arr = map_buffer->map(map.size(), GL_STATIC_DRAW);
std::memcpy(arr, map.data(), map.size() * sizeof(Tile));
map_buffer->unmap();
}
};
std::vector<SpriteLayer> sprite_layer;
float z = 0.f;
};
} // MM::OpenGL

View File

@ -0,0 +1,18 @@
unsigned char default_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x00,
0x78, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xed, 0x96, 0xb1, 0x11, 0x80,
0x30, 0x0c, 0x03, 0x65, 0x46, 0x33, 0x25, 0x6b, 0xa4, 0x0d, 0xc3, 0x24,
0x2d, 0x3b, 0x50, 0x51, 0xe2, 0xd5, 0xc2, 0x06, 0x72, 0x87, 0x1b, 0xb9,
0xfd, 0x3b, 0xdf, 0x9f, 0x0a, 0xd9, 0x36, 0xd0, 0x16, 0xc8, 0x74, 0x1c,
0x0c, 0x63, 0xf7, 0x49, 0x79, 0x44, 0x50, 0xbe, 0x51, 0xfa, 0xc3, 0x48,
0x40, 0x02, 0x12, 0xb0, 0x85, 0x9b, 0xf6, 0xc0, 0xc4, 0x43, 0x17, 0x9c,
0xb8, 0x28, 0x77, 0x77, 0xca, 0xcb, 0x13, 0x90, 0x80, 0x04, 0x24, 0x60,
0xee, 0x4e, 0x7b, 0x20, 0xbb, 0xe7, 0x03, 0x8d, 0xf2, 0xec, 0x9f, 0x28,
0x4f, 0x40, 0x02, 0x12, 0x90, 0x80, 0x01, 0xa0, 0x3d, 0x90, 0xdd, 0xf3,
0x37, 0x3a, 0xe5, 0xd9, 0x3f, 0x51, 0x9e, 0x80, 0x04, 0x24, 0x20, 0x81,
0x0f, 0x49, 0xf4, 0x16, 0xa3, 0xb7, 0xbf, 0xe8, 0xa6, 0x00, 0x00, 0x00,
0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int default_png_len = 177;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,175 @@
#include "./opengl_renderer.hpp"
#include <memory>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/opengl/fbo_builder.hpp>
#include <mm/opengl/frame_buffer_object.hpp>
#include <mm/resource_manager.hpp>
#include <mm/opengl/texture_loader.hpp>
#include "../opengl/res/default_texture.h" // data
#include "../opengl/res/errig_texture.h" // data
#include <tracy/Tracy.hpp>
#ifndef MM_OPENGL_3_GLES
#include <tracy/TracyOpenGL.hpp>
#else
#define TracyGpuContext
#define TracyGpuCollect
#endif
//#define LOGRS_SDL(x) LOGRS(std::string(SDL_GetError()) + x)
#include <mm/logger.hpp>
#define LOG_CRIT(...) __LOG_CRIT( "OpenGLRenderer", __VA_ARGS__)
#define LOG_ERROR(...) __LOG_ERROR("OpenGLRenderer", __VA_ARGS__)
#define LOG_WARN(...) __LOG_WARN( "OpenGLRenderer", __VA_ARGS__)
#define LOG_INFO(...) __LOG_INFO( "OpenGLRenderer", __VA_ARGS__)
#define LOG_DEBUG(...) __LOG_DEBUG("OpenGLRenderer", __VA_ARGS__)
#define LOG_TRACE(...) __LOG_TRACE("OpenGLRenderer", __VA_ARGS__)
namespace MM::Services {
OpenGLRenderer::OpenGLRenderer(void) {
MM::Logger::initSectionLogger("OpenGL");
MM::Logger::initSectionLogger("OpenGLRenderer");
}
OpenGLRenderer::~OpenGLRenderer(void) {
}
bool OpenGLRenderer::enable(Engine& engine) {
if (!engine.tryService<SDLService>()) {
LOG_ERROR("OpenGLRenderer requires SDLService");
return false;
}
auto& sdl_s = engine.getService<SDLService>();
if (!sdl_s.win) {
if (!sdl_s.createGLWindow("MushMachine (OpenGLRenderer)", 800, 600)) {
LOG_ERROR("couldn't create window with gl context");
return false;
}
} else if (!sdl_s.gl_context) {
if (!sdl_s.createGLContext()) {
LOG_ERROR("couldn't create gl context");
return false;
}
}
// "creating" display fbo
{
targets["display"].reset(new OpenGL::FrameBufferObject);
targets["display"]->_fboID = 0;
targets["display"]->_resize = false; // its done for us
}
_render_handle = engine.addUpdate([this](Engine& e){ this->render(e); });
if (_render_handle.expired()) {
LOG_ERROR("couldn't add update function!");
return false;
}
{
auto tmp_lock = _render_handle.lock();
tmp_lock->priority = -10;
tmp_lock->name = "render";
}
_sdl_event_handle = sdl_s.addEventHandler([this, &engine](const SDL_Event& e) -> bool {
if (e.type == SDL_WINDOWEVENT) {
if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
auto& sdl_s = engine.getService<MM::Services::SDLService>();
auto new_window_size = sdl_s.getWindowSize();
glViewport(0, 0, new_window_size.first, new_window_size.second);
// TODO: recreate fbos, dirvers seem to have problems otherwise
//std::vector<std::pair<std::string,std::shared_ptr<MM::OpenGL::FrameBufferObject>>> new_fbos;
for (auto& map_entry : targets) {
if (map_entry.second->_resize) {
auto& fbo = map_entry.second;
float new_width = fbo->_resize_factor_width * new_window_size.first;
float new_height = fbo->_resize_factor_height * new_window_size.second;
for (auto& tex : fbo->_texAttachments) {
if (tex->height == new_height && tex->width == new_width) {
continue;
}
tex->resize(static_cast<int32_t>(new_width), static_cast<int32_t>(new_height));
}
//auto new_fbo = std::make_shared<MM::OpenGL::FrameBufferObject>();
//auto new_fbo = OpenGL::FBOBuilder::start().
//new_fbos.emplace_back(map_entry.first, new_fbo);
}
}
//if (!new_fbos.empty()) {
//}
}
}
return false;
});
if (!_sdl_event_handle) {
LOG_ERROR("couldn't add sdl event function!");
return false;
}
{ // default texures
auto& rm_t = MM::ResourceManager<MM::OpenGL::Texture>::ref();
if (!rm_t.contains("default"_hs)) {
if (!rm_t.load<MM::OpenGL::TextureLoaderConstBuffer>("default", default_png, default_png_len)) {
LOG_WARN("couldn't load 'default' texture!");
}
}
if (!rm_t.contains("errig"_hs)) {
if (!rm_t.load<MM::OpenGL::TextureLoaderConstBuffer>("errig", errig_jpg, errig_jpg_len)) {
LOG_WARN("couldn't load 'errig' texture!");
}
}
}
return true;
}
void OpenGLRenderer::disable(Engine& engine) {
if (!_render_handle.expired()) {
engine.removeUpdate(_render_handle);
_render_handle.reset();
}
// TODO: do we need this??
targets.clear();
render_tasks.clear();
// TODO: reallly?
MM::ResourceManager<MM::OpenGL::Texture>::ref().clear();
}
void OpenGLRenderer::render(Engine& engine) {
ZoneScopedN("MM::Services::OpenGLRenderer::render");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//targets["display"]->bind(FrameBufferObject::RW);
//glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
targets["display"]->clear(0.1f, 0.1f, 0.1f, 1.0f, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
for (auto& r : render_tasks) {
r->render(*this, engine);
}
SDL_GL_SwapWindow(engine.getService<SDLService>().win);
TracyGpuCollect;
}
} // namespace MM::Services

View File

@ -0,0 +1,45 @@
#pragma once
#include <mm/engine.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/opengl/frame_buffer_object.hpp>
#include <mm/opengl/render_task.hpp>
#include <vector>
#include <unordered_map>
namespace MM::Services {
class OpenGLRenderer : public Service {
public:
OpenGLRenderer(void);
~OpenGLRenderer(void);
public:
std::vector<std::unique_ptr<OpenGL::RenderTask>> render_tasks;
std::unordered_map<std::string, std::shared_ptr<MM::OpenGL::FrameBufferObject>> targets;
// add rendertask helper
// TODO: forward args
template<typename RT_T>
RT_T& addRenderTask(::MM::Engine& engine) {
return *(RT_T*)render_tasks.emplace_back(std::make_unique<RT_T>(engine)).get();
}
private:
Engine::FunctionDataHandle _render_handle;
SDLService::EventHandlerHandle _sdl_event_handle = nullptr;
public:
bool enable(Engine& engine) override;
void disable(Engine& engine) override;
const char* name(void) override { return "OpenGLRendererService"; }
private:
void render(Engine& engine);
};
} // namespace MM::Services

View File

@ -0,0 +1,154 @@
add_executable(opengl_renderer_s_test ./opengl_renderer_s_test.cpp)
target_include_directories(opengl_renderer_s_test PRIVATE ".")
target_link_libraries(opengl_renderer_s_test
opengl_renderer_s
gtest_main
)
add_test(NAME opengl_renderer_s_test COMMAND opengl_renderer_s_test)
#################
add_executable(imgui_render_task_test imgui_render_task_test.cpp)
target_include_directories(imgui_render_task_test PRIVATE ".")
target_link_libraries(imgui_render_task_test
opengl_renderer_s
imgui_service
imgui_render_task
gtest_main
)
add_test(NAME imgui_render_task_test COMMAND imgui_render_task_test)
################# simple rect render task
add_executable(simple_rect_render_task_test simple_rect_render_task_test.cpp)
target_include_directories(simple_rect_render_task_test PRIVATE ".")
target_link_libraries(simple_rect_render_task_test
opengl_renderer_s
simple_scene
simple_rect_render_task
simple_velocity_system
gtest_main
)
add_test(NAME simple_rect_render_task_test COMMAND simple_rect_render_task_test)
################# simple sprite render task
add_executable(simple_sprite_render_task_test simple_sprite_render_task_test.cpp)
target_include_directories(simple_sprite_render_task_test PRIVATE ".")
target_link_libraries(simple_sprite_render_task_test
opengl_renderer_s
simple_scene
simple_sprite_render_task
simple_velocity_system
gtest_main
)
add_test(NAME simple_sprite_render_task_test COMMAND simple_sprite_render_task_test)
################# simple spritesheet render task
add_executable(simple_spritesheet_render_task_test simple_spritesheet_render_task_test.cpp)
target_include_directories(simple_spritesheet_render_task_test PRIVATE ".")
target_link_libraries(simple_spritesheet_render_task_test
opengl_renderer_s
simple_scene
simple_spritesheet_render_task
#simple_velocity_system
gtest_main
)
add_test(NAME simple_spritesheet_render_task_test COMMAND simple_spritesheet_render_task_test)
################# batched spritesheet render task
add_executable(batched_spritesheet_render_task_test batched_spritesheet_render_task_test.cpp)
target_include_directories(batched_spritesheet_render_task_test PRIVATE ".")
target_link_libraries(batched_spritesheet_render_task_test
opengl_renderer_s
simple_scene
batched_spritesheet_render_task
#simple_velocity_system
gtest_main
)
add_test(NAME batched_spritesheet_render_task_test COMMAND batched_spritesheet_render_task_test)
#################
add_executable(blur_render_task_test blur_render_task_test.cpp)
target_include_directories(blur_render_task_test PRIVATE ".")
target_link_libraries(blur_render_task_test
opengl_renderer_s
simple_scene
simple_rect_render_task
blur_render_task
imgui_service
imgui_render_task
simple_velocity_system
gtest_main
)
add_test(NAME blur_render_task_test COMMAND blur_render_task_test)
################# tilemap render task
add_executable(tilemap_render_task_test tilemap_render_task_test.cpp)
target_include_directories(tilemap_render_task_test PRIVATE ".")
target_link_libraries(tilemap_render_task_test
opengl_renderer_s
simple_scene
imgui_service
tilemap_render_task
gtest_main
)
add_test(NAME tilemap_render_task_test COMMAND tilemap_render_task_test)
################# fast sky render task
add_executable(fast_sky_render_task_test fast_sky_render_task_test.cpp)
target_include_directories(fast_sky_render_task_test PRIVATE ".")
target_link_libraries(fast_sky_render_task_test
opengl_renderer_s
simple_scene
#imgui_service
fast_sky_render_task
fast_sky_sun_system
gtest_main
)
add_test(NAME fast_sky_render_task_test COMMAND fast_sky_render_task_test)

View File

@ -0,0 +1,111 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/texture_loader.hpp>
#include <mm/opengl/render_tasks/batched_spritesheet.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include <mm/opengl/render_tasks/spritesheet_renderable.hpp>
#include <physfs.h>
#include "res/textures.zip.h"
const char* argv0;
TEST(batched_spritesheet_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("batched_spritesheet_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(argv0, "batched_spritesheet_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
ASSERT_TRUE(PHYSFS_mountMemory(textures_zip, textures_zip_len, NULL, "", NULL, 0));
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
auto& cam = scene.set<MM::OpenGL::Camera3D>();
cam.horizontalViewPortSize = 5;
cam.setOrthographic();
cam.updateView();
rs.addRenderTask<MM::OpenGL::RenderTasks::BatchedSpriteSheet>(engine);
float accu = 0.f;
MM::AddSystemToScene(scene, [&accu](auto& scene, float delta) {
accu += delta;
if (accu >= 1.f/10) {
accu -= 1.f/10;
scene.template view<MM::OpenGL::SpriteSheetRenderable>()
.each([](auto, auto& spr) {
spr.tile_index = (spr.tile_index+spr.sp.tile_count.x) % (spr.sp.tile_count.x*spr.sp.tile_count.y);
}
);
}
});
auto& rm_t = MM::ResourceManager<MM::OpenGL::Texture>::ref();
ASSERT_TRUE(rm_t.load<MM::OpenGL::TextureLoaderFile>("anim_run", engine, "/textures/animation_running-1_ea_0.3.png"));
ASSERT_TRUE(rm_t.load<MM::OpenGL::TextureLoaderFile>("anim_idle", engine, "/textures/animation_standing-1_ea_0.1.png"));
{
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = -1.f;
t.scale.x = 1.5f;
t.scale.y = 2.f;
auto& spr = scene.emplace<MM::OpenGL::SpriteSheetRenderable>(e);
spr.sp.tex = rm_t.get("anim_run"_hs);
spr.sp.tile_count.x = 8;
spr.sp.tile_count.y = 8;
spr.tile_index = 2;
}
{
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = 1.f;
t.scale.x = 1.5f;
t.scale.y = 2.f;
auto& spr = scene.emplace<MM::OpenGL::SpriteSheetRenderable>(e);
spr.sp.tex = rm_t.get("anim_idle"_hs);
spr.sp.tile_count.x = 8;
spr.sp.tile_count.y = 4;
spr.tile_index = 0;
}
engine.run();
}
int main(int argc, char** argv) {
argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,120 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <mm/services/imgui_s.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/render_tasks/simple_rect.hpp>
#include <mm/opengl/render_tasks/blur.hpp>
#include <mm/opengl/render_tasks/imgui.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include <mm/systems/simple_velocity_system2d.hpp>
#include <mm/opengl/fbo_builder.hpp>
#include <imgui/imgui.h>
#include <random>
const char* argv0;
TEST(blur_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("blur_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(argv0, "blur_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
engine.addService<MM::Services::ImGuiService>();
ASSERT_TRUE(engine.enableService<MM::Services::ImGuiService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
rs.addRenderTask<MM::OpenGL::RenderTasks::SimpleRect>(engine).target_fbo = "game_view";
MM::OpenGL::RenderTasks::SimpleRect* bsrr_rend_ptr = &rs.addRenderTask<MM::OpenGL::RenderTasks::SimpleRect>(engine);
bsrr_rend_ptr->target_fbo = "blur_in";
MM::OpenGL::RenderTasks::Blur* blur_rend_ptr = &rs.addRenderTask<MM::OpenGL::RenderTasks::Blur>(engine);
blur_rend_ptr->target_fbo = "display";
rs.addRenderTask<MM::OpenGL::RenderTasks::ImGuiRT>(engine);
{
auto [w, h] = sdl_ss.getWindowSize();
rs.targets["game_view"] = MM::OpenGL::FBOBuilder::start()
.attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE))
.finish();
rs.targets["blur_in"] = MM::OpenGL::FBOBuilder::start()
.attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE))
.finish();
rs.targets["blur_out"] = MM::OpenGL::FBOBuilder::start()
.attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE))
.finish();
}
// setup v system
MM::AddSystemToScene(scene, MM::Systems::SimpleVelocity);
std::mt19937 mt(42);
for (int i = 0; i < 10; i++) {
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = i * 9.f - 40;
t.scale = {5,5};
auto& v = scene.emplace<MM::Components::Velocity2D>(e);
v.rotation = i * 0.3f;
if (mt() % 2) {
auto& col = scene.emplace<MM::Components::Color>(e);
auto rc = [&mt]() -> float {
return (mt() % 1001) / 1000.f ;
};
col.color = {rc(),rc(),rc(),1};
}
}
engine.addUpdate(
[&](MM::Engine&) {
ImGui::ColorEdit4("rect_col", &bsrr_rend_ptr->default_color[0]);
}
);
engine.run();
}
int main(int argc, char** argv) {
argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,59 @@
#include "mm/opengl/camera_3d.hpp"
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/render_tasks/fast_sky_render_task.hpp>
#include <mm/systems/fast_sky_sun_system.hpp>
const char* argv0;
TEST(fast_sky_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("fast_sky_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(argv0, "fast_sky_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
rs.addRenderTask<MM::OpenGL::RenderTasks::FastSky>(engine);
MM::AddSystemToScene(scene, MM::Systems::FastSkySun);
auto& cam = scene.set<MM::OpenGL::Camera3D>();
cam.setPerspective();
cam.updateView();
scene.set<MM::OpenGL::RenderTasks::FastSkyContext>();
engine.run();
}
int main(int argc, char** argv) {
argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,46 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <mm/services/imgui_s.hpp>
#include <mm/opengl/render_tasks/imgui.hpp>
#include <imgui/imgui.h>
TEST(imgui_render_task, demowindow) {
MM::Engine engine;
engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
// needs a open window (and opengl context) which the OpenGLRenderer creates in this case
engine.addService<MM::Services::ImGuiService>();
ASSERT_TRUE(engine.enableService<MM::Services::ImGuiService>());
rs.addRenderTask<MM::OpenGL::RenderTasks::ImGuiRT>(engine);
auto handle = engine.addUpdate([](MM::Engine&) {
ImGui::ShowDemoWindow();
}
);
{
auto tmp_lock = handle.lock();
tmp_lock->priority = 0;
tmp_lock->name = "imgui demo window";
}
engine.run();
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,26 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/opengl_renderer.hpp>
TEST(opengl_renderer_s, basic) {
MM::Engine engine;
engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
engine.update();
}
int main(int argc, char** argv) {
//argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/render_tasks/simple_rect.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include <mm/systems/simple_velocity_system2d.hpp>
#include <random>
const char* argv0;
TEST(simple_rect_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("simple_rect_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(argv0, "simple_rect_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
rs.addRenderTask<MM::OpenGL::RenderTasks::SimpleRect>(engine);
// setup v system
MM::AddSystemToScene(scene, MM::Systems::SimpleVelocity);
std::mt19937 mt(42);
for (int y = 0; y < 10; y++) {
for (int i = 0; i < 10; i++) {
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = i * 9.f - 40;
t.position.y = -y * 6.f + 25;
t.scale = {5,5};
auto& v = scene.emplace<MM::Components::Velocity2D>(e);
v.rotation = i * 0.3f;
if (mt() % 2) {
auto& col = scene.emplace<MM::Components::Color>(e);
auto rc = [&mt]() -> float {
return (mt() % 1001) / 1000.f ;
};
col.color = {rc(),rc(),rc(),1};
}
}
}
engine.run();
}
int main(int argc, char** argv) {
argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,88 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/render_tasks/simple_sprite.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/opengl/components/texture.hpp>
#include <mm/components/color.hpp>
#include <mm/systems/simple_velocity_system2d.hpp>
#include <random>
const char* argv0;
TEST(simple_sprite_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("simple_sprite_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(argv0, "simple_sprite_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
rs.addRenderTask<MM::OpenGL::RenderTasks::SimpleSprite>(engine);
// setup v system
MM::AddSystemToScene(scene, MM::Systems::SimpleVelocity);
auto& rm_t = MM::ResourceManager<MM::OpenGL::Texture>::ref();
std::mt19937 mt(42);
for (int y = 0; y < 10; y++) {
for (int i = 0; i < 10; i++) {
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = i * 9.f - 40;
t.position.y = -y * 6.f + 25;
t.scale = {5,5};
auto& v = scene.emplace<MM::Components::Velocity2D>(e);
v.rotation = i * 0.3f;
auto& tex = scene.emplace<MM::Components::OpenGL::Texture>(e);
tex.tex = rm_t.get("errig"_hs);
if (mt() % 2) {
auto& col = scene.emplace<MM::Components::Color>(e);
auto rc = [&mt]() -> float {
return (mt() % 1001) / 1000.f ;
};
col.color = {rc(),rc(),rc(),1};
}
}
}
engine.run();
}
int main(int argc, char** argv) {
argv0 = argv[0];
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,101 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/texture_loader.hpp>
#include <mm/opengl/render_tasks/simple_spritesheet.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/components/color.hpp>
#include <mm/opengl/render_tasks/spritesheet_renderable.hpp>
#include <physfs.h>
#include "res/textures.zip.h"
TEST(simple_spritesheet_render_task, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("simple_spritesheet_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
engine.addService<MM::Services::FilesystemService>(nullptr, "simple_spritesheet_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
ASSERT_TRUE(PHYSFS_mountMemory(textures_zip, textures_zip_len, NULL, "", NULL, 0));
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
auto& cam = scene.set<MM::OpenGL::Camera3D>();
cam.horizontalViewPortSize = 5;
cam.setOrthographic();
cam.updateView();
rs.addRenderTask<MM::OpenGL::RenderTasks::SimpleSpriteSheet>(engine);
float accu = 0.f;
MM::AddSystemToScene(scene, [&accu](auto& scene, float delta) {
accu += delta;
if (accu >= 1.f/10) {
accu -= 1.f/10;
scene.template view<MM::OpenGL::SpriteSheetRenderable>()
.each([](auto, auto& spr) {
spr.tile_index = (spr.tile_index+spr.sp.tile_count.x) % (spr.sp.tile_count.x*spr.sp.tile_count.y);
}
);
}
});
auto& rm_t = MM::ResourceManager<MM::OpenGL::Texture>::ref();
ASSERT_TRUE(rm_t.load<MM::OpenGL::TextureLoaderFile>("anim_run", engine, "/textures/animation_running-1_ea_0.3.png"));
ASSERT_TRUE(rm_t.load<MM::OpenGL::TextureLoaderFile>("anim_idle", engine, "/textures/animation_standing-1_ea_0.1.png"));
{
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = -1.f;
t.scale.x = 1.5f;
t.scale.y = 2.f;
auto& spr = scene.emplace<MM::OpenGL::SpriteSheetRenderable>(e);
spr.sp.tex = rm_t.get("anim_run"_hs);
spr.sp.tile_count.x = 8;
spr.sp.tile_count.y = 8;
spr.tile_index = 2;
}
{
auto e = scene.create();
auto& t = scene.emplace<MM::Components::Transform2D>(e);
t.position.x = 1.f;
t.scale.x = 1.5f;
t.scale.y = 2.f;
auto& spr = scene.emplace<MM::OpenGL::SpriteSheetRenderable>(e);
spr.sp.tex = rm_t.get("anim_idle"_hs);
spr.sp.tile_count.x = 8;
spr.sp.tile_count.y = 4;
spr.tile_index = 0;
}
engine.run();
}

View File

@ -0,0 +1,97 @@
#include <gtest/gtest.h>
#include <mm/engine.hpp>
#include <mm/services/filesystem.hpp>
#include <mm/services/sdl_service.hpp>
#include <mm/services/simple_scene.hpp>
#include <mm/services/opengl_renderer.hpp>
#include <entt/entity/registry.hpp>
#include <mm/opengl/camera_3d.hpp>
#include <mm/opengl/render_tasks/tilemap.hpp>
#include <mm/opengl/render_tasks/tilemap_renderable.hpp>
#include <mm/components/transform2d.hpp>
#include <mm/opengl/texture_loader.hpp>
TEST(tilemap_render_task_test, it) {
MM::Engine engine;
auto& sdl_ss = engine.addService<MM::Services::SDLService>();
ASSERT_TRUE(engine.enableService<MM::Services::SDLService>());
sdl_ss.createGLWindow("tilemap_render_task_test", 1280, 720);
engine.addService<MM::Services::SimpleSceneService>();
ASSERT_TRUE(engine.enableService<MM::Services::SimpleSceneService>());
bool provide_ret = engine.provide<MM::Services::SceneServiceInterface, MM::Services::SimpleSceneService>();
ASSERT_TRUE(provide_ret);
auto& scene = engine.tryService<MM::Services::SceneServiceInterface>()->getScene();
auto& cam = scene.set<MM::OpenGL::Camera3D>();
cam.translation = {2.f, -2.f, 0.f};
cam.horizontalViewPortSize = 20.f;
cam.setOrthographic();
cam.updateView();
engine.addService<MM::Services::FilesystemService>(nullptr, "tilemap_render_task_test");
ASSERT_TRUE(engine.enableService<MM::Services::FilesystemService>());
auto& rs = engine.addService<MM::Services::OpenGLRenderer>();
ASSERT_TRUE(engine.enableService<MM::Services::OpenGLRenderer>());
rs.addRenderTask<MM::OpenGL::RenderTasks::Tilemap>(engine);
auto& rm_t = MM::ResourceManager<MM::OpenGL::Texture>::ref();
{
auto e = scene.create();
scene.emplace<MM::Components::Transform2D>(e);
auto& tm = scene.emplace<MM::OpenGL::TilemapRenderable>(e);
auto& slayer = tm.sprite_layer.emplace_back();
// fill sprite sheet
{
slayer.sprite_sheet.tile_count.x = 1;
slayer.sprite_sheet.tile_count.y = 1;
//slayer.sprite_sheet.tex = rm_t.get("default"_hs);
slayer.sprite_sheet.tex = rm_t.get("errig"_hs);
}
// fill tiles
{
std::vector<uint32_t> temp_map {
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 1, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1,
};
uint32_t width = 5;
uint32_t height = 5;
for (uint32_t y = 0; y < height; y++) {
for (uint32_t x = 0; x < width; x++) {
if (temp_map[y*width + x] != 0) {
auto& tile = slayer.map.emplace_back();
tile.pos[0] = x;
tile.pos[1] = y;
tile.sprite_sheet_index = temp_map[y*width + x] - 1;
}
}
}
slayer.syncMapBuffer(); // send to opengl
}
}
engine.run();
}