render state to separate structures

This commit is contained in:
2018-10-09 08:06:03 +07:00
parent df9cb24dd8
commit 5144413881
6 changed files with 498 additions and 325 deletions

View File

@@ -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_;

View File

@@ -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);
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();

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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>();