opengl render state functions

This commit is contained in:
2018-09-29 02:43:35 +07:00
parent 8f585860c1
commit 4da9442a31
7 changed files with 538 additions and 47 deletions

View File

@@ -10,12 +10,113 @@
namespace e2d
{
class texture final : noncopyable {
public:
enum class wrap {
clamp,
repeat,
mirror
};
enum class filter {
linear,
nearest
};
public:
texture();
~texture() noexcept;
void set_wrap(wrap u, wrap v) noexcept;
void set_filter(filter min, filter mag) noexcept;
private:
class internal_state;
std::unique_ptr<internal_state> state_;
};
class render final : public module<render> {
public:
enum class state {
blend,
cull_face,
depth_test,
stencil_test
};
enum class cull_face {
front,
back,
front_back
};
enum class blend_func {
zero,
one,
src_color,
one_minus_src_color,
dst_color,
one_minus_dst_color,
src_alpha,
one_minus_src_alpha,
dst_alpha,
one_minus_dst_alpha,
constant_color,
one_minus_constant_color,
constant_alpha,
one_minus_constant_alpha,
src_alpha_saturate
};
enum class depth_func {
never,
less,
lequal,
greater,
gequal,
equal,
notequal,
always
};
enum class stencil_func {
never,
less,
lequal,
greater,
gequal,
equal,
notequal,
always
};
enum class stencil_op {
keep,
zero,
replace,
incr,
incr_wrap,
decr,
decr_wrap,
invert
};
public:
render();
~render() noexcept;
void clear(bool color, bool depth, bool stencil) noexcept;
void set_view(const m4f& view) noexcept;
void set_projection(const m4f& projection) noexcept;
void set_viewport(f32 x, f32 y, f32 w, f32 h) noexcept;
void enable_state(state state) noexcept;
void disable_state(state state) noexcept;
void set_cull_face(cull_face cull_face) noexcept;
void set_depth_func(depth_func depth_func) noexcept;
void set_depth_mask(bool yesno) noexcept;
void set_stencil_func(stencil_func stencil_func, i32 ref, u32 mask) noexcept;
void set_stencil_mask(u32 mask) noexcept;
void set_stencil_op(stencil_op fail, stencil_op zfail, stencil_op zpass) noexcept;
void set_clear_color(const color& color) noexcept;
void set_color_mask(bool r, bool g, bool b, bool a);
void set_blend_func(blend_func src, blend_func dst) noexcept;
void set_blend_color(const color& color) noexcept;
private:
class state;
std::unique_ptr<state> state_;
class internal_state;
std::unique_ptr<internal_state> state_;
};
}

View File

@@ -8,22 +8,20 @@
using namespace e2d;
int e2d_main() {
input& i = modules::initialize<input>();
debug& d = modules::initialize<debug>();
window& w = modules::initialize<window>(v2u{640, 480}, "Enduro2D", false);
modules::initialize<debug>();
modules::initialize<input>();
modules::initialize<render>();
modules::initialize<window>(v2u{640, 480}, "Enduro2D", false);
d.add_sink<debug_console_sink>();
w.register_event_listener<window_input_source>(i);
w.register_event_listener<window_trace_event_listener>(d);
the<debug>().add_sink<debug_console_sink>();
the<window>().register_event_listener<window_input_source>(the<input>());
d.trace("SAMPLE: window real size: %0", w.real_size())
.trace("SAMPLE: window virtual size: %0", w.virtual_size())
.trace("SAMPLE: window framebuffer size: %0", w.framebuffer_size());
const keyboard& k = i.keyboard();
while ( !w.should_close() && !k.is_key_just_released(keyboard_key::escape) ) {
i.frame_tick();
w.swap_buffers(true);
const keyboard& k = the<input>().keyboard();
while ( !the<window>().should_close() && !k.is_key_just_released(keyboard_key::escape) ) {
the<render>().set_clear_color({1.f, 0.4f, 0.f});
the<render>().clear(true, true, true);
the<input>().frame_tick();
the<window>().swap_buffers(true);
window::frame_tick();
}
return 0;

View File

@@ -9,7 +9,7 @@
#include <enduro2d/core/render.hpp>
#define E2D_RENDER_MODE_NONE 1
#define E2D_RENDER_MODE_OGL 2
#define E2D_RENDER_MODE_OPENGL 2
#ifndef E2D_RENDER_MODE
# if defined(E2D_PLATFORM) && E2D_PLATFORM == E2D_PLATFORM_IOS
@@ -17,7 +17,7 @@
# elif defined(E2D_PLATFORM) && E2D_PLATFORM == E2D_PLATFORM_LINUX
# define E2D_RENDER_MODE E2D_RENDER_MODE_NONE
# elif defined(E2D_PLATFORM) && E2D_PLATFORM == E2D_PLATFORM_MACOSX
# define E2D_RENDER_MODE E2D_RENDER_MODE_OGL
# define E2D_RENDER_MODE E2D_RENDER_MODE_OPENGL
# elif defined(E2D_PLATFORM) && E2D_PLATFORM == E2D_PLATFORM_WINDOWS
# define E2D_RENDER_MODE E2D_RENDER_MODE_NONE
# endif

View File

@@ -10,15 +10,113 @@
namespace e2d
{
class render::state final : private e2d::noncopyable {
//
// texture::internal_state
//
class texture::internal_state final : private e2d::noncopyable {
public:
state() {}
~state() noexcept = default;
internal_state() {}
~internal_state() noexcept = default;
};
//
// render::internal_state
//
class render::internal_state final : private e2d::noncopyable {
public:
internal_state() {}
~internal_state() noexcept = default;
};
//
// texture
//
texture::texture()
: state_(new internal_state()) {}
texture::~texture() noexcept = default;
void texture::set_wrap(wrap u, wrap v) noexcept {
E2D_UNUSED(u, v);
}
void texture::set_filter(filter min, filter mag) noexcept {
E2D_UNUSED(min, mag);
}
//
// render
//
render::render()
: state_(new state()) {}
: state_(new internal_state()) {}
render::~render() noexcept = default;
void render::clear(bool color, bool depth, bool stencil) noexcept {
E2D_UNUSED(color, depth, stencil);
}
void render::set_view(const m4f& view) noexcept {
E2D_UNUSED(view);
}
void render::set_projection(const m4f& projection) noexcept {
E2D_UNUSED(projection);
}
void render::set_viewport(f32 x, f32 y, f32 w, f32 h) noexcept {
E2D_UNUSED(x, y, w, h);
}
void render::enable_state(state state) noexcept {
E2D_UNUSED(state);
}
void render::disable_state(state state) noexcept {
E2D_UNUSED(state);
}
void render::set_cull_face(cull_face cull_face) noexcept {
E2D_UNUSED(cull_face);
}
void render::set_depth_func(depth_func depth_func) noexcept {
E2D_UNUSED(depth_func);
}
void render::set_depth_mask(bool yesno) noexcept {
E2D_UNUSED(yesno);
}
void render::set_stencil_func(stencil_func stencil_func, i32 ref, u32 mask) noexcept {
E2D_UNUSED(stencil_func, ref, mask);
}
void render::set_stencil_mask(u32 mask) noexcept {
E2D_UNUSED(mask);
}
void render::set_stencil_op(stencil_op fail, stencil_op zfail, stencil_op zpass) noexcept {
E2D_UNUSED(fail, zfail, zpass);
}
void render::set_clear_color(const color& color) noexcept {
E2D_UNUSED(color);
}
void render::set_color_mask(bool r, bool g, bool b, bool a) {
E2D_UNUSED(r, g, b, a);
}
void render::set_blend_func(blend_func src, blend_func dst) noexcept {
E2D_UNUSED(src, dst);
}
void render::set_blend_color(const color& color) noexcept {
E2D_UNUSED(color);
}
}
#endif

View File

@@ -1,24 +0,0 @@
/*******************************************************************************
* This file is part of the "Enduro2D"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018 Matvey Cherevko
******************************************************************************/
#include "render.hpp"
#if defined(E2D_RENDER_MODE) && E2D_RENDER_MODE == E2D_RENDER_MODE_OGL
namespace e2d
{
class render::state final : private e2d::noncopyable {
public:
state() {}
~state() noexcept = default;
};
render::render()
: state_(new state()) {}
render::~render() noexcept = default;
}
#endif

View File

@@ -0,0 +1,318 @@
/*******************************************************************************
* This file is part of the "Enduro2D"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018 Matvey Cherevko
******************************************************************************/
#include "render.hpp"
#if defined(E2D_RENDER_MODE) && E2D_RENDER_MODE == E2D_RENDER_MODE_OPENGL
#if defined(E2D_PLATFORM) && E2D_PLATFORM == E2D_PLATFORM_MACOSX
# include <OpenGL/gl.h>
#endif
namespace
{
using namespace e2d;
GLenum convert_wrap(texture::wrap w) noexcept {
#define DEFINE_CASE(x,y) case texture::wrap::x: return y;
switch ( w ) {
DEFINE_CASE(clamp, GL_CLAMP_TO_EDGE);
DEFINE_CASE(repeat, GL_REPEAT);
DEFINE_CASE(mirror, GL_MIRRORED_REPEAT);
default:
E2D_ASSERT_MSG(false, "unexpected texture wrap");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_filter(texture::filter f) noexcept {
#define DEFINE_CASE(x,y) case texture::filter::x: return y;
switch ( f ) {
DEFINE_CASE(linear, GL_LINEAR);
DEFINE_CASE(nearest, GL_NEAREST);
default:
E2D_ASSERT_MSG(false, "unexpected texture filter");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_state(render::state s) noexcept {
#define DEFINE_CASE(x,y) case render::state::x: return y;
switch ( s ) {
DEFINE_CASE(blend, GL_BLEND);
DEFINE_CASE(cull_face, GL_CULL_FACE);
DEFINE_CASE(depth_test, GL_DEPTH_TEST);
DEFINE_CASE(stencil_test, GL_STENCIL_TEST);
default:
E2D_ASSERT_MSG(false, "unexpected render state");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_cull_face(render::cull_face cf) noexcept {
#define DEFINE_CASE(x,y) case render::cull_face::x: return y;
switch ( cf ) {
DEFINE_CASE(front, GL_FRONT);
DEFINE_CASE(back, GL_BACK);
DEFINE_CASE(front_back, GL_FRONT_AND_BACK);
default:
E2D_ASSERT_MSG(false, "unexpected render cull face");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_blend_func(render::blend_func bf) noexcept {
#define DEFINE_CASE(x,y) case render::blend_func::x: return y;
switch ( bf ) {
DEFINE_CASE(zero, GL_ZERO);
DEFINE_CASE(one, GL_ONE);
DEFINE_CASE(src_color, GL_SRC_COLOR);
DEFINE_CASE(one_minus_src_color, GL_ONE_MINUS_SRC_COLOR);
DEFINE_CASE(dst_color, GL_DST_COLOR);
DEFINE_CASE(one_minus_dst_color, GL_ONE_MINUS_DST_COLOR);
DEFINE_CASE(src_alpha, GL_SRC_ALPHA);
DEFINE_CASE(one_minus_src_alpha, GL_ONE_MINUS_SRC_ALPHA);
DEFINE_CASE(dst_alpha, GL_DST_ALPHA);
DEFINE_CASE(one_minus_dst_alpha, GL_ONE_MINUS_DST_ALPHA);
DEFINE_CASE(constant_color, GL_CONSTANT_COLOR);
DEFINE_CASE(one_minus_constant_color, GL_ONE_MINUS_CONSTANT_COLOR);
DEFINE_CASE(constant_alpha, GL_CONSTANT_ALPHA);
DEFINE_CASE(one_minus_constant_alpha, GL_ONE_MINUS_CONSTANT_ALPHA);
DEFINE_CASE(src_alpha_saturate, GL_SRC_ALPHA_SATURATE);
default:
E2D_ASSERT_MSG(false, "unexpected render blend func");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_depth_func(render::depth_func df) noexcept {
#define DEFINE_CASE(x,y) case render::depth_func::x: return y;
switch ( df ) {
DEFINE_CASE(never, GL_NEVER);
DEFINE_CASE(less, GL_LESS);
DEFINE_CASE(lequal, GL_LEQUAL);
DEFINE_CASE(greater, GL_GREATER);
DEFINE_CASE(gequal, GL_GEQUAL);
DEFINE_CASE(equal, GL_EQUAL);
DEFINE_CASE(notequal, GL_NOTEQUAL);
DEFINE_CASE(always, GL_ALWAYS);
default:
E2D_ASSERT_MSG(false, "unexpected render depth func");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_stencil_func(render::stencil_func sf) noexcept {
#define DEFINE_CASE(x,y) case render::stencil_func::x: return y;
switch ( sf ) {
DEFINE_CASE(never, GL_NEVER);
DEFINE_CASE(less, GL_LESS);
DEFINE_CASE(lequal, GL_LEQUAL);
DEFINE_CASE(greater, GL_GREATER);
DEFINE_CASE(gequal, GL_GEQUAL);
DEFINE_CASE(equal, GL_EQUAL);
DEFINE_CASE(notequal, GL_NOTEQUAL);
DEFINE_CASE(always, GL_ALWAYS);
default:
E2D_ASSERT_MSG(false, "unexpected render stencil func");
return 0;
}
#undef DEFINE_CASE
}
GLenum convert_stencil_op(render::stencil_op so) noexcept {
#define DEFINE_CASE(x,y) case render::stencil_op::x: return y;
switch ( so ) {
DEFINE_CASE(keep, GL_KEEP);
DEFINE_CASE(zero, GL_ZERO);
DEFINE_CASE(replace, GL_REPLACE);
DEFINE_CASE(incr, GL_INCR);
DEFINE_CASE(incr_wrap, GL_INCR_WRAP);
DEFINE_CASE(decr, GL_DECR);
DEFINE_CASE(decr_wrap, GL_DECR_WRAP);
DEFINE_CASE(invert, GL_INVERT);
default:
E2D_ASSERT_MSG(false, "unexpected render stencil op");
return 0;
}
#undef DEFINE_CASE
}
}
namespace e2d
{
//
// texture::internal_state
//
class texture::internal_state final : private e2d::noncopyable {
public:
internal_state() {}
~internal_state() noexcept = default;
};
//
// render::internal_state
//
class render::internal_state final : private e2d::noncopyable {
public:
std::mutex mutex;
m4f view;
m4f projection;
public:
internal_state() {}
~internal_state() noexcept = default;
};
//
// texture
//
texture::texture()
: state_(new internal_state()) {}
texture::~texture() noexcept = default;
void texture::set_wrap(wrap u, wrap v) noexcept {
E2D_UNUSED(convert_wrap(u), convert_wrap(v));
}
void texture::set_filter(filter min, filter mag) noexcept {
E2D_UNUSED(convert_filter(min), convert_filter(mag));
}
//
// render
//
render::render()
: state_(new internal_state()) {}
render::~render() noexcept = default;
void render::clear(bool color, bool depth, bool stencil) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
GLbitfield mask = 0;
if ( color ) {
mask |= GL_COLOR_BUFFER_BIT;
}
if ( depth ) {
mask |= GL_DEPTH_BUFFER_BIT;
}
if ( stencil ) {
mask |= GL_STENCIL_BUFFER_BIT;
}
glClear(mask);
}
void render::set_view(const m4f& view) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
state_->view = view;
}
void render::set_projection(const m4f& projection) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
state_->projection = projection;
}
void render::set_viewport(f32 x, f32 y, f32 w, f32 h) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glViewport(
math::numeric_cast<GLint>(x),
math::numeric_cast<GLint>(y),
math::numeric_cast<GLsizei>(w),
math::numeric_cast<GLsizei>(h));
}
void render::enable_state(state state) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glEnable(convert_state(state));
}
void render::disable_state(state state) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glDisable(convert_state(state));
}
void render::set_cull_face(cull_face cull_face) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glCullFace(convert_cull_face(cull_face));
}
void render::set_depth_func(depth_func depth_func) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glDepthFunc(convert_depth_func(depth_func));
}
void render::set_depth_mask(bool yesno) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glDepthMask(yesno ? GL_TRUE : GL_FALSE);
}
void render::set_stencil_func(
stencil_func stencil_func, i32 ref, u32 mask) noexcept
{
std::lock_guard<std::mutex> guard(state_->mutex);
glStencilFunc(
convert_stencil_func(stencil_func),
math::numeric_cast<GLint>(ref),
math::numeric_cast<GLuint>(mask));
}
void render::set_stencil_mask(u32 mask) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glStencilMask(math::numeric_cast<GLuint>(mask));
}
void render::set_stencil_op(
stencil_op fail, stencil_op zfail, stencil_op zpass) noexcept
{
std::lock_guard<std::mutex> guard(state_->mutex);
glStencilOp(
convert_stencil_op(fail),
convert_stencil_op(zfail),
convert_stencil_op(zpass));
}
void render::set_clear_color(const color& color) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glClearColor(
math::numeric_cast<GLclampf>(color.r),
math::numeric_cast<GLclampf>(color.g),
math::numeric_cast<GLclampf>(color.b),
math::numeric_cast<GLclampf>(color.a));
}
void render::set_color_mask(bool r, bool g, bool b, bool a) {
std::lock_guard<std::mutex> guard(state_->mutex);
glColorMask(
r ? GL_TRUE : GL_FALSE,
g ? GL_TRUE : GL_FALSE,
b ? GL_TRUE : GL_FALSE,
a ? GL_TRUE : GL_FALSE);
}
void render::set_blend_func(blend_func src, blend_func dst) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glBlendFunc(convert_blend_func(src), convert_blend_func(dst));
}
void render::set_blend_color(const color& color) noexcept {
std::lock_guard<std::mutex> guard(state_->mutex);
glBlendColor(
math::numeric_cast<GLclampf>(color.r),
math::numeric_cast<GLclampf>(color.g),
math::numeric_cast<GLclampf>(color.b),
math::numeric_cast<GLclampf>(color.a));
}
}
#endif

View File

@@ -319,7 +319,7 @@ namespace e2d
}
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
v2i real_size = fullscreen