mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-14 16:09:06 +07:00
render state to separate structures
This commit is contained in:
@@ -177,8 +177,9 @@ namespace e2d
|
||||
sampler_2d,
|
||||
sampler_cube
|
||||
};
|
||||
|
||||
enum class attribute_type : u8 {
|
||||
f,
|
||||
floating_point,
|
||||
|
||||
v2f,
|
||||
v3f,
|
||||
@@ -214,6 +215,7 @@ namespace e2d
|
||||
repeat,
|
||||
mirror
|
||||
};
|
||||
|
||||
enum class filter : u8 {
|
||||
linear,
|
||||
nearest
|
||||
@@ -291,20 +293,46 @@ namespace e2d
|
||||
|
||||
class render final : public module<render> {
|
||||
public:
|
||||
enum class state : u8 {
|
||||
blend,
|
||||
cull_face,
|
||||
depth_test,
|
||||
stencil_test
|
||||
enum class topology : u8 {
|
||||
triangles,
|
||||
triangles_fan,
|
||||
triangles_strip
|
||||
};
|
||||
|
||||
enum class cull_face : u8 {
|
||||
front,
|
||||
enum class stencil_op : u8 {
|
||||
keep,
|
||||
zero,
|
||||
replace,
|
||||
incr,
|
||||
incr_wrap,
|
||||
decr,
|
||||
decr_wrap,
|
||||
invert
|
||||
};
|
||||
|
||||
enum class compare_func : u8 {
|
||||
never,
|
||||
less,
|
||||
lequal,
|
||||
greater,
|
||||
gequal,
|
||||
equal,
|
||||
notequal,
|
||||
always
|
||||
};
|
||||
|
||||
enum class culling_mode : u8 {
|
||||
cw,
|
||||
ccw
|
||||
};
|
||||
|
||||
enum class culling_face : u8 {
|
||||
back,
|
||||
front_back
|
||||
front,
|
||||
back_and_front
|
||||
};
|
||||
|
||||
enum class blend_func : u8 {
|
||||
enum class blending_factor : u8 {
|
||||
zero,
|
||||
one,
|
||||
src_color,
|
||||
@@ -322,49 +350,112 @@ namespace e2d
|
||||
src_alpha_saturate
|
||||
};
|
||||
|
||||
enum class blend_equation : u8 {
|
||||
enum class blending_equation : u8 {
|
||||
add,
|
||||
subtract,
|
||||
reverse_subtract
|
||||
};
|
||||
|
||||
enum class depth_func : u8 {
|
||||
never,
|
||||
less,
|
||||
lequal,
|
||||
greater,
|
||||
gequal,
|
||||
equal,
|
||||
notequal,
|
||||
always
|
||||
enum class blending_color_mask : u8 {
|
||||
none = 0,
|
||||
|
||||
r = (u8(1) << u8(0)),
|
||||
g = (u8(1) << u8(1)),
|
||||
b = (u8(1) << u8(2)),
|
||||
a = (u8(1) << u8(3)),
|
||||
|
||||
rg = r | g,
|
||||
rb = r | b,
|
||||
ra = r | a,
|
||||
gb = g | b,
|
||||
ga = g | a,
|
||||
ba = b | a,
|
||||
|
||||
rgb = r | g | b,
|
||||
rga = r | g | a,
|
||||
rba = r | b | a,
|
||||
gba = g | b | a,
|
||||
|
||||
rgba = r | g | b | a
|
||||
};
|
||||
|
||||
enum class stencil_func : u8 {
|
||||
never,
|
||||
less,
|
||||
lequal,
|
||||
greater,
|
||||
gequal,
|
||||
equal,
|
||||
notequal,
|
||||
always
|
||||
class depth_state {
|
||||
public:
|
||||
depth_state& range(f32 near, f32 far) noexcept;
|
||||
depth_state& write(bool enable) noexcept;
|
||||
depth_state& func(compare_func func) noexcept;
|
||||
private:
|
||||
friend class render;
|
||||
f32 near_ = 0.0f;
|
||||
f32 far_ = 1.0f;
|
||||
bool write_ = true;
|
||||
compare_func func_ = compare_func::less;
|
||||
u8 _pad[2] = {0};
|
||||
};
|
||||
|
||||
enum class stencil_op : u8 {
|
||||
keep,
|
||||
zero,
|
||||
replace,
|
||||
incr,
|
||||
incr_wrap,
|
||||
decr,
|
||||
decr_wrap,
|
||||
invert
|
||||
class render_state {
|
||||
public:
|
||||
render_state& culling(bool enable) noexcept;
|
||||
render_state& blending(bool enable) noexcept;
|
||||
render_state& depth_test(bool enable) noexcept;
|
||||
render_state& stencil_test(bool enable) noexcept;
|
||||
private:
|
||||
friend class render;
|
||||
bool culling_ = false;
|
||||
bool blending_ = false;
|
||||
bool depth_test_ = false;
|
||||
bool stencil_test_ = false;
|
||||
};
|
||||
|
||||
enum class topology : u8 {
|
||||
triangles,
|
||||
triangles_fan,
|
||||
triangles_strip
|
||||
class stencil_state {
|
||||
public:
|
||||
stencil_state& write(u8 mask) noexcept;
|
||||
stencil_state& func(compare_func func, u8 ref, u8 mask) noexcept;
|
||||
stencil_state& op(stencil_op sfail, stencil_op zfail, stencil_op pass) noexcept;
|
||||
private:
|
||||
friend class render;
|
||||
u8 write_ = 1;
|
||||
u8 ref_ = 0;
|
||||
u8 read_ = 1;
|
||||
stencil_op pass_ = stencil_op::keep;
|
||||
stencil_op sfail_ = stencil_op::keep;
|
||||
stencil_op zfail_ = stencil_op::keep;
|
||||
compare_func func_ = compare_func::always;
|
||||
u8 _pad[1] = {0};
|
||||
};
|
||||
|
||||
class culling_state {
|
||||
public:
|
||||
culling_state& mode(culling_mode mode) noexcept;
|
||||
culling_state& face(culling_face face) noexcept;
|
||||
private:
|
||||
friend class render;
|
||||
culling_mode mode_ = culling_mode::ccw;
|
||||
culling_face face_ = culling_face::back;
|
||||
u8 _pad[2] = {0};
|
||||
};
|
||||
|
||||
class blending_state {
|
||||
public:
|
||||
blending_state& constant_color(const color& c) noexcept;
|
||||
blending_state& factor(blending_factor src, blending_factor dst) noexcept;
|
||||
blending_state& rgb_factor(blending_factor src, blending_factor dst) noexcept;
|
||||
blending_state& alpha_factor(blending_factor src, blending_factor dst) noexcept;
|
||||
blending_state& equation(blending_equation equation) noexcept;
|
||||
blending_state& rgb_equation(blending_equation equation) noexcept;
|
||||
blending_state& alpha_equation(blending_equation equation) noexcept;
|
||||
blending_state& color_mask(blending_color_mask mask) noexcept;
|
||||
private:
|
||||
friend class render;
|
||||
color constant_color_ = color::clear();
|
||||
blending_factor src_rgb_factor_ = blending_factor::one;
|
||||
blending_factor dst_rgb_factor_ = blending_factor::zero;
|
||||
blending_equation rgb_equation_ = blending_equation::add;
|
||||
blending_factor src_alpha_factor_ = blending_factor::one;
|
||||
blending_factor dst_alpha_factor_ = blending_factor::zero;
|
||||
blending_equation alpha_equation_ = blending_equation::add;
|
||||
blending_color_mask color_mask_ = blending_color_mask::rgba;
|
||||
u8 _pad[1] = {0};
|
||||
};
|
||||
public:
|
||||
render(debug& d, window& w);
|
||||
@@ -392,42 +483,26 @@ namespace e2d
|
||||
const vertex_declaration& decl,
|
||||
vertex_buffer::usage usage);
|
||||
|
||||
void clear(
|
||||
bool color,
|
||||
bool depth,
|
||||
bool stencil) noexcept;
|
||||
|
||||
void draw(
|
||||
topology tp,
|
||||
const shader_ptr& ps,
|
||||
const index_buffer_ptr& ib,
|
||||
const vertex_buffer_ptr& vb) noexcept;
|
||||
|
||||
void set_model(const m4f& model) noexcept;
|
||||
void set_view(const m4f& view) noexcept;
|
||||
void set_projection(const m4f& projection) noexcept;
|
||||
void set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept;
|
||||
render& clear_depth_buffer(f32 value) noexcept;
|
||||
render& clear_stencil_buffer(u8 value) noexcept;
|
||||
render& clear_color_buffer(const color& value) noexcept;
|
||||
|
||||
void enable_state(state state) noexcept;
|
||||
void disable_state(state state) noexcept;
|
||||
render& set_model(const m4f& model) noexcept;
|
||||
render& set_view(const m4f& view) noexcept;
|
||||
render& set_projection(const m4f& projection) noexcept;
|
||||
render& set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept;
|
||||
|
||||
void set_blend_func(blend_func src, blend_func dst) noexcept;
|
||||
void set_blend_color(const color& color) noexcept;
|
||||
void set_blend_equation(blend_equation blend_equation) 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_clear_depth(f32 value) noexcept;
|
||||
|
||||
void set_stencil_func(stencil_func stencil_func, u32 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_stencil(u32 value) noexcept;
|
||||
|
||||
void set_clear_color(const color& color) noexcept;
|
||||
void set_color_mask(bool r, bool g, bool b, bool a);
|
||||
render& set_depth_state(const depth_state& ds) noexcept;
|
||||
render& set_render_state(const render_state& rs) noexcept;
|
||||
render& set_stencil_state(const stencil_state& ss) noexcept;
|
||||
render& set_culling_state(const culling_state& cs) noexcept;
|
||||
render& set_blending_state(const blending_state& bs) noexcept;
|
||||
private:
|
||||
class internal_state;
|
||||
std::unique_ptr<internal_state> state_;
|
||||
|
||||
@@ -84,13 +84,16 @@ int e2d_main() {
|
||||
|
||||
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, 1.f});
|
||||
the<render>().clear(true, true, true);
|
||||
|
||||
f32 t = (time::now_ms() - begin_time).cast_to<f32>().value;
|
||||
ps->set_uniform("u_time", t);
|
||||
{
|
||||
the<render>().draw(render::topology::triangles, ps, ib, vb);
|
||||
f32 t = (time::now_ms() - begin_time).cast_to<f32>().value;
|
||||
ps->set_uniform("u_time", t);
|
||||
}
|
||||
{
|
||||
the<render>()
|
||||
.clear_depth_buffer(1.f)
|
||||
.clear_stencil_buffer(0)
|
||||
.clear_color_buffer({1.f, 0.4f, 0.f, 1.f})
|
||||
.draw(render::topology::triangles, ps, ib, vb);
|
||||
}
|
||||
the<window>().swap_buffers(true);
|
||||
the<input>().frame_tick();
|
||||
|
||||
@@ -229,4 +229,133 @@ namespace e2d
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
//
|
||||
// depth_state
|
||||
//
|
||||
|
||||
render::depth_state& render::depth_state::range(f32 near, f32 far) noexcept {
|
||||
near_ = near;
|
||||
far_ = far;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::depth_state& render::depth_state::write(bool enable) noexcept {
|
||||
write_ = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::depth_state& render::depth_state::func(compare_func func) noexcept {
|
||||
func_ = func;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// render_state
|
||||
//
|
||||
|
||||
render::render_state& render::render_state::culling(bool enable) noexcept {
|
||||
culling_ = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::render_state& render::render_state::blending(bool enable) noexcept {
|
||||
blending_ = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::render_state& render::render_state::depth_test(bool enable) noexcept {
|
||||
depth_test_ = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::render_state& render::render_state::stencil_test(bool enable) noexcept {
|
||||
stencil_test_ = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// stencil_state
|
||||
//
|
||||
|
||||
render::stencil_state& render::stencil_state::write(u8 mask) noexcept {
|
||||
write_ = mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::stencil_state& render::stencil_state::func(compare_func func, u8 ref, u8 mask) noexcept {
|
||||
func_ = func;
|
||||
ref_ = ref;
|
||||
read_ = mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::stencil_state& render::stencil_state::op(stencil_op sfail, stencil_op zfail, stencil_op pass) noexcept {
|
||||
sfail_ = sfail;
|
||||
zfail_ = zfail;
|
||||
pass_ = pass;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// culling_state
|
||||
//
|
||||
|
||||
render::culling_state& render::culling_state::mode(culling_mode mode) noexcept {
|
||||
mode_ = mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::culling_state& render::culling_state::face(culling_face face) noexcept {
|
||||
face_ = face;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// blending_state
|
||||
//
|
||||
|
||||
render::blending_state& render::blending_state::constant_color(const color& c) noexcept {
|
||||
constant_color_ = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::factor(blending_factor src, blending_factor dst) noexcept {
|
||||
rgb_factor(src, dst);
|
||||
alpha_factor(src, dst);
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::rgb_factor(blending_factor src, blending_factor dst) noexcept {
|
||||
src_rgb_factor_ = src;
|
||||
dst_rgb_factor_ = dst;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::alpha_factor(blending_factor src, blending_factor dst) noexcept {
|
||||
src_alpha_factor_ = src;
|
||||
dst_alpha_factor_ = dst;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::equation(blending_equation equation) noexcept {
|
||||
rgb_equation(equation);
|
||||
alpha_equation(equation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::rgb_equation(blending_equation equation) noexcept {
|
||||
rgb_equation_ = equation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::alpha_equation(blending_equation equation) noexcept {
|
||||
alpha_equation_ = equation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
render::blending_state& render::blending_state::color_mask(blending_color_mask mask) noexcept {
|
||||
color_mask_ = mask;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace e2d
|
||||
public:
|
||||
vertex_declaration decl_;
|
||||
public:
|
||||
internal_state(const vertex_declaration& decl)
|
||||
explicit internal_state(const vertex_declaration& decl) noexcept
|
||||
: decl_(decl){}
|
||||
~internal_state() noexcept = default;
|
||||
};
|
||||
@@ -29,7 +29,7 @@ namespace e2d
|
||||
|
||||
class texture::internal_state final : private e2d::noncopyable {
|
||||
public:
|
||||
internal_state() {}
|
||||
internal_state() noexcept = default;
|
||||
~internal_state() noexcept = default;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace e2d
|
||||
|
||||
class index_buffer::internal_state final : private e2d::noncopyable {
|
||||
public:
|
||||
internal_state() {}
|
||||
internal_state() noexcept = default;
|
||||
~internal_state() noexcept = default;
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace e2d
|
||||
|
||||
class vertex_buffer::internal_state final : private e2d::noncopyable {
|
||||
public:
|
||||
internal_state() {}
|
||||
internal_state() noexcept = default;
|
||||
~internal_state() noexcept = default;
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace e2d
|
||||
debug& debug_;
|
||||
window& window_;
|
||||
public:
|
||||
internal_state(debug& debug, window& window)
|
||||
internal_state(debug& debug, window& window) noexcept
|
||||
: debug_(debug)
|
||||
, window_(window) {}
|
||||
~internal_state() noexcept = default;
|
||||
@@ -165,8 +165,19 @@ namespace e2d
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void render::clear(bool color, bool depth, bool stencil) noexcept {
|
||||
E2D_UNUSED(color, depth, stencil);
|
||||
render& render::clear_depth_buffer(f32 value) noexcept {
|
||||
E2D_UNUSED(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
render& render::clear_stencil_buffer(u8 value) noexcept {
|
||||
E2D_UNUSED(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
render& render::clear_color_buffer(const color& value) noexcept {
|
||||
E2D_UNUSED(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::draw(
|
||||
@@ -178,80 +189,49 @@ namespace e2d
|
||||
E2D_UNUSED(tp, ps, ib, vb);
|
||||
}
|
||||
|
||||
void render::set_model(const m4f& model) noexcept {
|
||||
render& render::set_model(const m4f& model) noexcept {
|
||||
E2D_UNUSED(model);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_view(const m4f& view) noexcept {
|
||||
render& render::set_view(const m4f& view) noexcept {
|
||||
E2D_UNUSED(view);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_projection(const m4f& projection) noexcept {
|
||||
render& render::set_projection(const m4f& projection) noexcept {
|
||||
E2D_UNUSED(projection);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept {
|
||||
render& render::set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept {
|
||||
E2D_UNUSED(x, y, w, h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::enable_state(state state) noexcept {
|
||||
E2D_UNUSED(state);
|
||||
render& render::set_depth_state(const depth_state& ds) noexcept {
|
||||
E2D_UNUSED(ds);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::disable_state(state state) noexcept {
|
||||
E2D_UNUSED(state);
|
||||
render& render::set_render_state(const render_state& rs) noexcept {
|
||||
E2D_UNUSED(rs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_blend_func(blend_func src, blend_func dst) noexcept {
|
||||
E2D_UNUSED(src, dst);
|
||||
render& render::set_stencil_state(const stencil_state& ss) noexcept {
|
||||
E2D_UNUSED(ss);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_blend_color(const color& color) noexcept {
|
||||
E2D_UNUSED(color);
|
||||
render& render::set_culling_state(const culling_state& cs) noexcept {
|
||||
E2D_UNUSED(cs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_blend_equation(blend_equation blend_equation) noexcept {
|
||||
E2D_UNUSED(blend_equation);
|
||||
}
|
||||
|
||||
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_clear_depth(f32 value) noexcept {
|
||||
E2D_UNUSED(value);
|
||||
}
|
||||
|
||||
void render::set_stencil_func(stencil_func stencil_func, u32 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_stencil(u32 value) noexcept {
|
||||
E2D_UNUSED(value);
|
||||
}
|
||||
|
||||
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);
|
||||
render& render::set_blending_state(const blending_state& bs) noexcept {
|
||||
E2D_UNUSED(bs);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace
|
||||
GLint convert_attribute_type(shader::attribute_type at) noexcept {
|
||||
#define DEFINE_CASE(x,y) case shader::attribute_type::x: return y;
|
||||
switch ( at ) {
|
||||
DEFINE_CASE(f, GL_FLOAT);
|
||||
DEFINE_CASE(floating_point, GL_FLOAT);
|
||||
|
||||
DEFINE_CASE(v2f, GL_FLOAT_VEC2);
|
||||
DEFINE_CASE(v3f, GL_FLOAT_VEC3);
|
||||
@@ -140,35 +140,82 @@ namespace
|
||||
#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);
|
||||
GLenum convert_topology(render::topology t) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::topology::x: return y;
|
||||
switch ( t ) {
|
||||
DEFINE_CASE(triangles, GL_TRIANGLES);
|
||||
DEFINE_CASE(triangles_fan, GL_TRIANGLE_FAN);
|
||||
DEFINE_CASE(triangles_strip, GL_TRIANGLE_STRIP);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected render state");
|
||||
E2D_ASSERT_MSG(false, "unexpected render topology");
|
||||
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;
|
||||
GLenum convert_stencil_op(render::stencil_op sa) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::stencil_op::x: return y;
|
||||
switch ( sa ) {
|
||||
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
|
||||
}
|
||||
|
||||
GLenum convert_compare_func(render::compare_func cf) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::compare_func::x: return y;
|
||||
switch ( cf ) {
|
||||
DEFINE_CASE(front, GL_FRONT);
|
||||
DEFINE_CASE(back, GL_BACK);
|
||||
DEFINE_CASE(front_back, GL_FRONT_AND_BACK);
|
||||
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 cull face");
|
||||
E2D_ASSERT_MSG(false, "unexpected render compare func");
|
||||
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;
|
||||
GLenum convert_culling_mode(render::culling_mode cm) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::culling_mode::x: return y;
|
||||
switch ( cm ) {
|
||||
DEFINE_CASE(cw, GL_CW);
|
||||
DEFINE_CASE(ccw, GL_CCW);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected render culling mode");
|
||||
return 0;
|
||||
}
|
||||
#undef DEFINE_CASE
|
||||
}
|
||||
|
||||
GLenum convert_culling_face(render::culling_face cf) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::culling_face::x: return y;
|
||||
switch ( cf ) {
|
||||
DEFINE_CASE(back, GL_BACK);
|
||||
DEFINE_CASE(front, GL_FRONT);
|
||||
DEFINE_CASE(back_and_front, GL_FRONT_AND_BACK);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected render culling face");
|
||||
return 0;
|
||||
}
|
||||
#undef DEFINE_CASE
|
||||
}
|
||||
|
||||
GLenum convert_blending_factor(render::blending_factor bf) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::blending_factor::x: return y;
|
||||
switch ( bf ) {
|
||||
DEFINE_CASE(zero, GL_ZERO);
|
||||
DEFINE_CASE(one, GL_ONE);
|
||||
@@ -186,87 +233,20 @@ namespace
|
||||
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");
|
||||
E2D_ASSERT_MSG(false, "unexpected render blending factor");
|
||||
return 0;
|
||||
}
|
||||
#undef DEFINE_CASE
|
||||
}
|
||||
|
||||
GLenum convert_blend_equation(render::blend_equation bf) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::blend_equation::x: return y;
|
||||
switch ( bf ) {
|
||||
GLenum convert_blending_equation(render::blending_equation be) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::blending_equation::x: return y;
|
||||
switch ( be ) {
|
||||
DEFINE_CASE(add, GL_FUNC_ADD);
|
||||
DEFINE_CASE(subtract, GL_FUNC_SUBTRACT);
|
||||
DEFINE_CASE(reverse_subtract, GL_FUNC_REVERSE_SUBTRACT);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected render blend equation");
|
||||
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
|
||||
}
|
||||
|
||||
GLenum convert_topology(render::topology t) noexcept {
|
||||
#define DEFINE_CASE(x,y) case render::topology::x: return y;
|
||||
switch ( t ) {
|
||||
DEFINE_CASE(triangles, GL_TRIANGLES);
|
||||
DEFINE_CASE(triangles_fan, GL_TRIANGLE_FAN);
|
||||
DEFINE_CASE(triangles_strip, GL_TRIANGLE_STRIP);
|
||||
default:
|
||||
E2D_ASSERT_MSG(false, "unexpected topology");
|
||||
E2D_ASSERT_MSG(false, "unexpected render blending equation");
|
||||
return 0;
|
||||
}
|
||||
#undef DEFINE_CASE
|
||||
@@ -337,6 +317,14 @@ namespace
|
||||
*loc = glGetAttribLocation(program, name);
|
||||
}
|
||||
|
||||
void gl_enable_or_disable(GLenum cap, bool enable) noexcept {
|
||||
if ( enable ) {
|
||||
glEnable(cap);
|
||||
} else {
|
||||
glDisable(cap);
|
||||
}
|
||||
}
|
||||
|
||||
#define GL_FLUSH_ERRORS(dbg)\
|
||||
for ( GLenum err = glGetError(); err != GL_NO_ERROR; err = glGetError() ) {\
|
||||
E2D_ASSERT_MSG(false, "RENDER: GL_FLUSH_ERRORS()");\
|
||||
@@ -719,7 +707,6 @@ namespace
|
||||
program, location, ai.name));
|
||||
location += math::numeric_cast<GLuint>(ai.rows);
|
||||
}
|
||||
//TODO(BlackMat): add attribute type checks
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -796,6 +783,11 @@ namespace
|
||||
location += rows;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename E >
|
||||
constexpr std::underlying_type_t<E> enum_to_number(E e) noexcept {
|
||||
return static_cast<std::underlying_type_t<E>>(e);
|
||||
}
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
@@ -1161,20 +1153,6 @@ namespace e2d
|
||||
state_->debug_, std::move(id), vertices.size(), decl, usage));
|
||||
}
|
||||
|
||||
void render::clear(bool color, bool depth, bool stencil) noexcept {
|
||||
GLbitfield mask = 0;
|
||||
if ( color ) {
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if ( depth ) {
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
if ( stencil ) {
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
GL_CHECK_CODE(state_->debug_, glClear(mask));
|
||||
}
|
||||
|
||||
void render::draw(
|
||||
topology tp,
|
||||
const shader_ptr& ps,
|
||||
@@ -1202,112 +1180,119 @@ namespace e2d
|
||||
GL_CHECK_CODE(state_->debug_, glUseProgram(0));
|
||||
}
|
||||
|
||||
void render::set_model(const m4f& model) noexcept {
|
||||
render& render::clear_depth_buffer(f32 value) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glClearDepth(
|
||||
math::numeric_cast<GLclampd>(math::saturate(value))));
|
||||
GL_CHECK_CODE(state_->debug_, glClear(GL_DEPTH_BUFFER_BIT));
|
||||
return *this;
|
||||
}
|
||||
|
||||
render& render::clear_stencil_buffer(u8 value) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glClearStencil(
|
||||
math::numeric_cast<GLint>(value)));
|
||||
GL_CHECK_CODE(state_->debug_, glClear(GL_STENCIL_BUFFER_BIT));
|
||||
return *this;
|
||||
}
|
||||
|
||||
render& render::clear_color_buffer(const color& value) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glClearColor(
|
||||
math::numeric_cast<GLclampf>(math::saturate(value.r)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(value.g)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(value.b)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(value.a))));
|
||||
GL_CHECK_CODE(state_->debug_, glClear(GL_COLOR_BUFFER_BIT));
|
||||
return *this;
|
||||
}
|
||||
|
||||
render& render::set_model(const m4f& model) noexcept {
|
||||
state_->model_ = model;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_view(const m4f& view) noexcept {
|
||||
render& render::set_view(const m4f& view) noexcept {
|
||||
state_->view_ = view;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_projection(const m4f& projection) noexcept {
|
||||
render& render::set_projection(const m4f& projection) noexcept {
|
||||
state_->projection_ = projection;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept {
|
||||
render& render::set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glViewport(
|
||||
math::numeric_cast<GLint>(x),
|
||||
math::numeric_cast<GLint>(y),
|
||||
math::numeric_cast<GLsizei>(w),
|
||||
math::numeric_cast<GLsizei>(h)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::enable_state(state state) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glEnable(convert_state(state)));
|
||||
}
|
||||
|
||||
void render::disable_state(state state) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glDisable(convert_state(state)));
|
||||
}
|
||||
|
||||
void render::set_blend_func(blend_func src, blend_func dst) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glBlendFunc(
|
||||
convert_blend_func(src), convert_blend_func(dst)));
|
||||
}
|
||||
|
||||
void render::set_blend_color(const color& color) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, 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)));
|
||||
}
|
||||
|
||||
void render::set_blend_equation(blend_equation blend_equation) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glBlendEquation(
|
||||
convert_blend_equation(blend_equation)));
|
||||
}
|
||||
|
||||
void render::set_cull_face(cull_face cull_face) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glCullFace(
|
||||
convert_cull_face(cull_face)));
|
||||
}
|
||||
|
||||
void render::set_depth_func(depth_func depth_func) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glDepthFunc(
|
||||
convert_depth_func(depth_func)));
|
||||
}
|
||||
|
||||
void render::set_depth_mask(bool yesno) noexcept {
|
||||
render& render::set_depth_state(const depth_state& ds) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glDepthRange(
|
||||
math::numeric_cast<GLclampd>(math::saturate(ds.near_)),
|
||||
math::numeric_cast<GLclampd>(math::saturate(ds.far_))));
|
||||
GL_CHECK_CODE(state_->debug_, glDepthMask(
|
||||
yesno ? GL_TRUE : GL_FALSE));
|
||||
ds.write_ ? GL_TRUE : GL_FALSE));
|
||||
GL_CHECK_CODE(state_->debug_, glDepthFunc(
|
||||
convert_compare_func(ds.func_)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_clear_depth(f32 value) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glClearDepth(
|
||||
math::numeric_cast<GLclampd>(value)));
|
||||
render& render::set_render_state(const render_state& bs) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, gl_enable_or_disable(
|
||||
GL_CULL_FACE, bs.culling_));
|
||||
GL_CHECK_CODE(state_->debug_, gl_enable_or_disable(
|
||||
GL_BLEND, bs.blending_));
|
||||
GL_CHECK_CODE(state_->debug_, gl_enable_or_disable(
|
||||
GL_DEPTH_TEST, bs.depth_test_));
|
||||
GL_CHECK_CODE(state_->debug_, gl_enable_or_disable(
|
||||
GL_STENCIL_TEST, bs.stencil_test_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_stencil_func(stencil_func stencil_func, u32 ref, u32 mask) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glStencilFunc(
|
||||
convert_stencil_func(stencil_func),
|
||||
math::numeric_cast<GLint>(ref),
|
||||
math::numeric_cast<GLuint>(mask)));
|
||||
}
|
||||
|
||||
void render::set_stencil_mask(u32 mask) noexcept {
|
||||
render& render::set_stencil_state(const stencil_state& ss) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glStencilMask(
|
||||
math::numeric_cast<GLuint>(mask)));
|
||||
}
|
||||
|
||||
void render::set_stencil_op(
|
||||
stencil_op fail, stencil_op zfail, stencil_op zpass) noexcept
|
||||
{
|
||||
math::numeric_cast<GLuint>(ss.write_)));
|
||||
GL_CHECK_CODE(state_->debug_, glStencilFunc(
|
||||
convert_compare_func(ss.func_),
|
||||
math::numeric_cast<GLint>(ss.ref_),
|
||||
math::numeric_cast<GLuint>(ss.read_)));
|
||||
GL_CHECK_CODE(state_->debug_, glStencilOp(
|
||||
convert_stencil_op(fail),
|
||||
convert_stencil_op(zfail),
|
||||
convert_stencil_op(zpass)));
|
||||
convert_stencil_op(ss.sfail_),
|
||||
convert_stencil_op(ss.zfail_),
|
||||
convert_stencil_op(ss.pass_)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_clear_stencil(u32 value) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glClearStencil(
|
||||
math::numeric_cast<GLint>(value)));
|
||||
render& render::set_culling_state(const culling_state& cs) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glFrontFace(
|
||||
convert_culling_mode(cs.mode_)));
|
||||
GL_CHECK_CODE(state_->debug_, glCullFace(
|
||||
convert_culling_face(cs.face_)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render::set_clear_color(const color& color) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, 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) {
|
||||
render& render::set_blending_state(const blending_state& bs) noexcept {
|
||||
GL_CHECK_CODE(state_->debug_, glBlendColor(
|
||||
math::numeric_cast<GLclampf>(math::saturate(bs.constant_color_.r)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(bs.constant_color_.g)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(bs.constant_color_.b)),
|
||||
math::numeric_cast<GLclampf>(math::saturate(bs.constant_color_.a))));
|
||||
GL_CHECK_CODE(state_->debug_, glBlendFuncSeparate(
|
||||
convert_blending_factor(bs.src_rgb_factor_),
|
||||
convert_blending_factor(bs.dst_rgb_factor_),
|
||||
convert_blending_factor(bs.src_alpha_factor_),
|
||||
convert_blending_factor(bs.dst_alpha_factor_)));
|
||||
GL_CHECK_CODE(state_->debug_, glBlendEquationSeparate(
|
||||
convert_blending_equation(bs.rgb_equation_),
|
||||
convert_blending_equation(bs.alpha_equation_)));
|
||||
GL_CHECK_CODE(state_->debug_, glColorMask(
|
||||
r ? GL_TRUE : GL_FALSE,
|
||||
g ? GL_TRUE : GL_FALSE,
|
||||
b ? GL_TRUE : GL_FALSE,
|
||||
a ? GL_TRUE : GL_FALSE));
|
||||
(enum_to_number(bs.color_mask_) & enum_to_number(blending_color_mask::r)) != 0,
|
||||
(enum_to_number(bs.color_mask_) & enum_to_number(blending_color_mask::g)) != 0,
|
||||
(enum_to_number(bs.color_mask_) & enum_to_number(blending_color_mask::b)) != 0,
|
||||
(enum_to_number(bs.color_mask_) & enum_to_number(blending_color_mask::a)) != 0));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -278,15 +278,13 @@ namespace e2d
|
||||
str title;
|
||||
bool fullscreen = false;
|
||||
bool cursor_hidden = false;
|
||||
char _pad[6];
|
||||
public:
|
||||
state(const v2u& size, str_view title, bool fullscreen)
|
||||
state(const v2u& size, str_view ntitle, bool nfullscreen)
|
||||
: shared_state(glfw_state::get_shared_state())
|
||||
, window(open_window_(size, make_utf8(title), fullscreen))
|
||||
, window(open_window_(size, make_utf8(ntitle), nfullscreen))
|
||||
, virtual_size(size)
|
||||
, title(title)
|
||||
, fullscreen(fullscreen)
|
||||
, cursor_hidden(false)
|
||||
, title(ntitle)
|
||||
, fullscreen(nfullscreen)
|
||||
{
|
||||
if ( !window ) {
|
||||
throw bad_window_operation();
|
||||
@@ -341,6 +339,9 @@ namespace e2d
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
|
||||
#if defined(E2D_BUILD_MODE) && E2D_BUILD_MODE == E2D_BUILD_MODE_DEBUG
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||
#endif
|
||||
v2i real_size = fullscreen
|
||||
? make_vec2(video_mode->width, video_mode->height)
|
||||
: virtual_size.cast_to<i32>();
|
||||
|
||||
Reference in New Issue
Block a user