mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 08:15:38 +07:00
render target first impl
This commit is contained in:
@@ -17,6 +17,8 @@ namespace e2d
|
|||||||
class texture;
|
class texture;
|
||||||
class index_buffer;
|
class index_buffer;
|
||||||
class vertex_buffer;
|
class vertex_buffer;
|
||||||
|
class render_target;
|
||||||
|
class pixel_declaration;
|
||||||
class index_declaration;
|
class index_declaration;
|
||||||
class vertex_declaration;
|
class vertex_declaration;
|
||||||
|
|
||||||
@@ -24,6 +26,50 @@ namespace e2d
|
|||||||
using texture_ptr = std::shared_ptr<texture>;
|
using texture_ptr = std::shared_ptr<texture>;
|
||||||
using index_buffer_ptr = std::shared_ptr<index_buffer>;
|
using index_buffer_ptr = std::shared_ptr<index_buffer>;
|
||||||
using vertex_buffer_ptr = std::shared_ptr<vertex_buffer>;
|
using vertex_buffer_ptr = std::shared_ptr<vertex_buffer>;
|
||||||
|
using render_target_ptr = std::shared_ptr<render_target>;
|
||||||
|
|
||||||
|
//
|
||||||
|
// pixel_declaration
|
||||||
|
//
|
||||||
|
|
||||||
|
class pixel_declaration final {
|
||||||
|
public:
|
||||||
|
enum class pixel_type : u8 {
|
||||||
|
rgba8,
|
||||||
|
depth24_stencil8,
|
||||||
|
|
||||||
|
dxt1,
|
||||||
|
dxt3,
|
||||||
|
dxt5,
|
||||||
|
|
||||||
|
rgb_pvrtc2,
|
||||||
|
rgb_pvrtc4,
|
||||||
|
|
||||||
|
rgba_pvrtc2,
|
||||||
|
rgba_pvrtc4
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
pixel_declaration() = default;
|
||||||
|
~pixel_declaration() noexcept = default;
|
||||||
|
|
||||||
|
pixel_declaration(const pixel_declaration&) noexcept = default;
|
||||||
|
pixel_declaration& operator=(const pixel_declaration&) noexcept = default;
|
||||||
|
|
||||||
|
pixel_declaration(pixel_type type) noexcept;
|
||||||
|
|
||||||
|
pixel_type type() const noexcept;
|
||||||
|
bool is_compressed() const noexcept;
|
||||||
|
std::size_t bits_per_pixel() const noexcept;
|
||||||
|
private:
|
||||||
|
pixel_type type_ = pixel_type::rgba8;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(
|
||||||
|
const pixel_declaration& l,
|
||||||
|
const pixel_declaration& r) noexcept;
|
||||||
|
bool operator!=(
|
||||||
|
const pixel_declaration& l,
|
||||||
|
const pixel_declaration& r) noexcept;
|
||||||
|
|
||||||
//
|
//
|
||||||
// index_declaration
|
// index_declaration
|
||||||
@@ -35,19 +81,6 @@ namespace e2d
|
|||||||
unsigned_byte,
|
unsigned_byte,
|
||||||
unsigned_short
|
unsigned_short
|
||||||
};
|
};
|
||||||
|
|
||||||
class index_info final {
|
|
||||||
public:
|
|
||||||
index_type type = index_type::unsigned_short;
|
|
||||||
public:
|
|
||||||
index_info() = default;
|
|
||||||
~index_info() noexcept = default;
|
|
||||||
|
|
||||||
index_info(const index_info&) noexcept = default;
|
|
||||||
index_info& operator=(const index_info&) noexcept = default;
|
|
||||||
|
|
||||||
explicit index_info(index_type type) noexcept;
|
|
||||||
};
|
|
||||||
public:
|
public:
|
||||||
index_declaration() = default;
|
index_declaration() = default;
|
||||||
~index_declaration() noexcept = default;
|
~index_declaration() noexcept = default;
|
||||||
@@ -55,12 +88,12 @@ namespace e2d
|
|||||||
index_declaration(const index_declaration&) noexcept = default;
|
index_declaration(const index_declaration&) noexcept = default;
|
||||||
index_declaration& operator=(const index_declaration&) noexcept = default;
|
index_declaration& operator=(const index_declaration&) noexcept = default;
|
||||||
|
|
||||||
explicit index_declaration(index_type index_type) noexcept;
|
index_declaration(index_type type) noexcept;
|
||||||
|
|
||||||
const index_info& index() const noexcept;
|
index_type type() const noexcept;
|
||||||
std::size_t index_size() const noexcept;
|
std::size_t bytes_per_index() const noexcept;
|
||||||
private:
|
private:
|
||||||
index_info index_;
|
index_type type_ = index_type::unsigned_short;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(
|
bool operator==(
|
||||||
@@ -69,12 +102,6 @@ namespace e2d
|
|||||||
bool operator!=(
|
bool operator!=(
|
||||||
const index_declaration& l,
|
const index_declaration& l,
|
||||||
const index_declaration& r) noexcept;
|
const index_declaration& r) noexcept;
|
||||||
bool operator==(
|
|
||||||
const index_declaration::index_info& l,
|
|
||||||
const index_declaration::index_info& r) noexcept;
|
|
||||||
bool operator!=(
|
|
||||||
const index_declaration::index_info& l,
|
|
||||||
const index_declaration::index_info& r) noexcept;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// vertex_declaration
|
// vertex_declaration
|
||||||
@@ -138,12 +165,12 @@ namespace e2d
|
|||||||
|
|
||||||
const attribute_info& attribute(std::size_t i) const noexcept;
|
const attribute_info& attribute(std::size_t i) const noexcept;
|
||||||
std::size_t attribute_count() const noexcept;
|
std::size_t attribute_count() const noexcept;
|
||||||
std::size_t vertex_size() const noexcept;
|
std::size_t bytes_per_vertex() const noexcept;
|
||||||
private:
|
private:
|
||||||
constexpr static std::size_t max_attribute_count = 8;
|
constexpr static std::size_t max_attribute_count = 8;
|
||||||
array<attribute_info, max_attribute_count> attributes_;
|
array<attribute_info, max_attribute_count> attributes_;
|
||||||
std::size_t attribute_count_ = 0;
|
std::size_t attribute_count_ = 0;
|
||||||
std::size_t vertex_size_ = 0;
|
std::size_t bytes_per_vertex_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(
|
bool operator==(
|
||||||
@@ -187,8 +214,9 @@ namespace e2d
|
|||||||
public:
|
public:
|
||||||
explicit texture(internal_state_uptr);
|
explicit texture(internal_state_uptr);
|
||||||
~texture() noexcept;
|
~texture() noexcept;
|
||||||
|
public:
|
||||||
const v2u& size() const noexcept;
|
const v2u& size() const noexcept;
|
||||||
image_data_format format() const noexcept;
|
const pixel_declaration& decl() const noexcept;
|
||||||
private:
|
private:
|
||||||
internal_state_uptr state_;
|
internal_state_uptr state_;
|
||||||
};
|
};
|
||||||
@@ -211,10 +239,11 @@ namespace e2d
|
|||||||
public:
|
public:
|
||||||
explicit index_buffer(internal_state_uptr);
|
explicit index_buffer(internal_state_uptr);
|
||||||
~index_buffer() noexcept;
|
~index_buffer() noexcept;
|
||||||
|
public:
|
||||||
void update(const buffer& indices, std::size_t offset) noexcept;
|
void update(const buffer& indices, std::size_t offset) noexcept;
|
||||||
const index_declaration& decl() const noexcept;
|
|
||||||
std::size_t buffer_size() const noexcept;
|
std::size_t buffer_size() const noexcept;
|
||||||
std::size_t index_count() const noexcept;
|
std::size_t index_count() const noexcept;
|
||||||
|
const index_declaration& decl() const noexcept;
|
||||||
private:
|
private:
|
||||||
internal_state_uptr state_;
|
internal_state_uptr state_;
|
||||||
};
|
};
|
||||||
@@ -229,7 +258,7 @@ namespace e2d
|
|||||||
using internal_state_uptr = std::unique_ptr<internal_state>;
|
using internal_state_uptr = std::unique_ptr<internal_state>;
|
||||||
const internal_state& state() const noexcept;
|
const internal_state& state() const noexcept;
|
||||||
public:
|
public:
|
||||||
enum class usage : u8{
|
enum class usage : u8 {
|
||||||
static_draw,
|
static_draw,
|
||||||
stream_draw,
|
stream_draw,
|
||||||
dynamic_draw
|
dynamic_draw
|
||||||
@@ -237,10 +266,37 @@ namespace e2d
|
|||||||
public:
|
public:
|
||||||
explicit vertex_buffer(internal_state_uptr);
|
explicit vertex_buffer(internal_state_uptr);
|
||||||
~vertex_buffer() noexcept;
|
~vertex_buffer() noexcept;
|
||||||
|
public:
|
||||||
void update(const buffer& vertices, std::size_t offset) noexcept;
|
void update(const buffer& vertices, std::size_t offset) noexcept;
|
||||||
const vertex_declaration& decl() const noexcept;
|
|
||||||
std::size_t buffer_size() const noexcept;
|
std::size_t buffer_size() const noexcept;
|
||||||
std::size_t vertex_count() const noexcept;
|
std::size_t vertex_count() const noexcept;
|
||||||
|
const vertex_declaration& decl() const noexcept;
|
||||||
|
private:
|
||||||
|
internal_state_uptr state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// render target
|
||||||
|
//
|
||||||
|
|
||||||
|
class render_target final : noncopyable {
|
||||||
|
public:
|
||||||
|
class internal_state;
|
||||||
|
using internal_state_uptr = std::unique_ptr<internal_state>;
|
||||||
|
const internal_state& state() const noexcept;
|
||||||
|
public:
|
||||||
|
enum class type : u8 {
|
||||||
|
color = (1 << 0),
|
||||||
|
depth = (1 << 1),
|
||||||
|
color_and_depth = color | depth
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
explicit render_target(internal_state_uptr);
|
||||||
|
~render_target() noexcept;
|
||||||
|
public:
|
||||||
|
const v2u& size() const noexcept;
|
||||||
|
const texture_ptr& color() const noexcept;
|
||||||
|
const texture_ptr& depth() const noexcept;
|
||||||
private:
|
private:
|
||||||
internal_state_uptr state_;
|
internal_state_uptr state_;
|
||||||
};
|
};
|
||||||
@@ -285,9 +341,9 @@ namespace e2d
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class culling_face : u8 {
|
enum class culling_face : u8 {
|
||||||
back,
|
back = (1 << 0),
|
||||||
front,
|
front = (1 << 1),
|
||||||
back_and_front
|
back_and_front = back | front
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class blending_factor : u8 {
|
enum class blending_factor : u8 {
|
||||||
@@ -647,6 +703,10 @@ namespace e2d
|
|||||||
texture_ptr create_texture(
|
texture_ptr create_texture(
|
||||||
const input_stream_uptr& image_stream);
|
const input_stream_uptr& image_stream);
|
||||||
|
|
||||||
|
texture_ptr create_texture(
|
||||||
|
const v2u& size,
|
||||||
|
const pixel_declaration& decl);
|
||||||
|
|
||||||
index_buffer_ptr create_index_buffer(
|
index_buffer_ptr create_index_buffer(
|
||||||
const buffer& indices,
|
const buffer& indices,
|
||||||
const index_declaration& decl,
|
const index_declaration& decl,
|
||||||
@@ -657,6 +717,10 @@ namespace e2d
|
|||||||
const vertex_declaration& decl,
|
const vertex_declaration& decl,
|
||||||
vertex_buffer::usage usage);
|
vertex_buffer::usage usage);
|
||||||
|
|
||||||
|
render_target_ptr create_render_target(
|
||||||
|
const v2u& size,
|
||||||
|
render_target::type type);
|
||||||
|
|
||||||
void draw(
|
void draw(
|
||||||
const material& mat,
|
const material& mat,
|
||||||
const geometry& geo);
|
const geometry& geo);
|
||||||
@@ -670,6 +734,7 @@ namespace e2d
|
|||||||
render& clear_stencil_buffer(u8 value) noexcept;
|
render& clear_stencil_buffer(u8 value) noexcept;
|
||||||
render& clear_color_buffer(const color& value) noexcept;
|
render& clear_color_buffer(const color& value) noexcept;
|
||||||
render& set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept;
|
render& set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept;
|
||||||
|
render& set_render_target(const render_target_ptr& rt) noexcept;
|
||||||
private:
|
private:
|
||||||
class internal_state;
|
class internal_state;
|
||||||
std::unique_ptr<internal_state> state_;
|
std::unique_ptr<internal_state> state_;
|
||||||
|
|||||||
@@ -45,3 +45,4 @@ endfunction(add_e2d_sample)
|
|||||||
|
|
||||||
add_e2d_sample(00)
|
add_e2d_sample(00)
|
||||||
add_e2d_sample(01)
|
add_e2d_sample(01)
|
||||||
|
add_e2d_sample(02)
|
||||||
|
|||||||
@@ -9,44 +9,46 @@ using namespace e2d;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const char* vs_source_cstr =
|
const char* vs_source_cstr = R"glsl(
|
||||||
"#version 120 \n"
|
#version 120
|
||||||
" \n"
|
|
||||||
"attribute vec3 a_position; \n"
|
|
||||||
"attribute vec2 a_uv; \n"
|
|
||||||
"attribute vec4 a_color; \n"
|
|
||||||
" \n"
|
|
||||||
"uniform float u_time; \n"
|
|
||||||
"uniform mat4 u_MVP; \n"
|
|
||||||
" \n"
|
|
||||||
"varying vec4 v_color; \n"
|
|
||||||
"varying vec2 v_uv; \n"
|
|
||||||
" \n"
|
|
||||||
"void main(){ \n"
|
|
||||||
" v_color = a_color; \n"
|
|
||||||
" v_uv = a_uv; \n"
|
|
||||||
" \n"
|
|
||||||
" float s = 0.7 + 0.3 * (cos(u_time * 0.003) + 1); \n"
|
|
||||||
" gl_Position = vec4(a_position * s, 1.0) * u_MVP; \n"
|
|
||||||
"} \n";
|
|
||||||
|
|
||||||
const char* fs_source_cstr =
|
attribute vec3 a_position;
|
||||||
"#version 120 \n"
|
attribute vec2 a_uv;
|
||||||
" \n"
|
attribute vec4 a_color;
|
||||||
"uniform float u_time; \n"
|
|
||||||
"uniform sampler2D u_texture1; \n"
|
uniform float u_time;
|
||||||
"uniform sampler2D u_texture2; \n"
|
uniform mat4 u_MVP;
|
||||||
"varying vec4 v_color; \n"
|
|
||||||
"varying vec2 v_uv; \n"
|
varying vec4 v_color;
|
||||||
" \n"
|
varying vec2 v_uv;
|
||||||
"void main(){ \n"
|
|
||||||
" vec2 uv = vec2(v_uv.s, 1.0 - v_uv.t); \n"
|
void main(){
|
||||||
" if ( u_time > 2000 ) { \n"
|
v_color = a_color;
|
||||||
" gl_FragColor = v_color * texture2D(u_texture2, uv); \n"
|
v_uv = a_uv;
|
||||||
" } else { \n"
|
|
||||||
" gl_FragColor = v_color * texture2D(u_texture1, uv); \n"
|
float s = 0.7 + 0.3 * (cos(u_time * 0.003) + 1);
|
||||||
" } \n"
|
gl_Position = vec4(a_position * s, 1.0) * u_MVP;
|
||||||
"} \n";
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
const char* fs_source_cstr = R"glsl(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform float u_time;
|
||||||
|
uniform sampler2D u_texture1;
|
||||||
|
uniform sampler2D u_texture2;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_uv;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 uv = vec2(v_uv.s, 1.0 - v_uv.t);
|
||||||
|
if ( u_time > 2000 ) {
|
||||||
|
gl_FragColor = v_color * texture2D(u_texture2, uv);
|
||||||
|
} else {
|
||||||
|
gl_FragColor = v_color * texture2D(u_texture1, uv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
struct vertex1 {
|
struct vertex1 {
|
||||||
v3f position;
|
v3f position;
|
||||||
@@ -124,7 +126,7 @@ int e2d_main() {
|
|||||||
const auto indices = generate_quad_indices();
|
const auto indices = generate_quad_indices();
|
||||||
const auto index_buffer = the<render>().create_index_buffer(
|
const auto index_buffer = the<render>().create_index_buffer(
|
||||||
buffer(indices.data(), indices.size() * sizeof(indices[0])),
|
buffer(indices.data(), indices.size() * sizeof(indices[0])),
|
||||||
index_declaration(index_declaration::index_type::unsigned_byte),
|
index_declaration::index_type::unsigned_byte,
|
||||||
index_buffer::usage::static_draw);
|
index_buffer::usage::static_draw);
|
||||||
|
|
||||||
const auto vertices1 = generate_quad_vertices(texture1->size());
|
const auto vertices1 = generate_quad_vertices(texture1->size());
|
||||||
|
|||||||
@@ -9,36 +9,38 @@ using namespace e2d;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const char* vs_source_cstr =
|
const char* vs_source_cstr = R"glsl(
|
||||||
"#version 120 \n"
|
#version 120
|
||||||
" \n"
|
|
||||||
"attribute vec3 a_position; \n"
|
|
||||||
"attribute vec2 a_uv; \n"
|
|
||||||
"attribute vec4 a_color; \n"
|
|
||||||
" \n"
|
|
||||||
"uniform mat4 u_MVP; \n"
|
|
||||||
" \n"
|
|
||||||
"varying vec4 v_color; \n"
|
|
||||||
"varying vec2 v_uv; \n"
|
|
||||||
" \n"
|
|
||||||
"void main(){ \n"
|
|
||||||
" v_color = a_color; \n"
|
|
||||||
" v_uv = a_uv; \n"
|
|
||||||
" \n"
|
|
||||||
" gl_Position = vec4(a_position, 1.0) * u_MVP; \n"
|
|
||||||
"} \n";
|
|
||||||
|
|
||||||
const char* fs_source_cstr =
|
attribute vec3 a_position;
|
||||||
"#version 120 \n"
|
attribute vec2 a_uv;
|
||||||
" \n"
|
attribute vec4 a_color;
|
||||||
"uniform sampler2D u_texture; \n"
|
|
||||||
"varying vec4 v_color; \n"
|
uniform mat4 u_MVP;
|
||||||
"varying vec2 v_uv; \n"
|
|
||||||
" \n"
|
varying vec4 v_color;
|
||||||
"void main(){ \n"
|
varying vec2 v_uv;
|
||||||
" vec2 uv = vec2(v_uv.s, 1.0 - v_uv.t); \n"
|
|
||||||
" gl_FragColor = v_color * texture2D(u_texture, uv); \n"
|
void main(){
|
||||||
"} \n";
|
v_color = a_color;
|
||||||
|
v_uv = a_uv;
|
||||||
|
|
||||||
|
gl_Position = vec4(a_position, 1.0) * u_MVP;
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
const char* fs_source_cstr = R"glsl(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
varying vec4 v_color;
|
||||||
|
varying vec2 v_uv;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 uv = vec2(v_uv.s, 1.0 - v_uv.t);
|
||||||
|
gl_FragColor = v_color * texture2D(u_texture, uv);
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
struct vertex1 {
|
struct vertex1 {
|
||||||
v3f position;
|
v3f position;
|
||||||
@@ -182,7 +184,7 @@ int e2d_main() {
|
|||||||
const auto indices = generate_cube_indices();
|
const auto indices = generate_cube_indices();
|
||||||
const auto index_buffer = the<render>().create_index_buffer(
|
const auto index_buffer = the<render>().create_index_buffer(
|
||||||
buffer(indices.data(), indices.size() * sizeof(indices[0])),
|
buffer(indices.data(), indices.size() * sizeof(indices[0])),
|
||||||
index_declaration(index_declaration::index_type::unsigned_byte),
|
index_declaration::index_type::unsigned_byte,
|
||||||
index_buffer::usage::static_draw);
|
index_buffer::usage::static_draw);
|
||||||
|
|
||||||
const auto vertices1 = generate_cube_vertices(make_vec3(1.f));
|
const auto vertices1 = generate_cube_vertices(make_vec3(1.f));
|
||||||
|
|||||||
243
samples/sources/sample_02/sample_02.cpp
Normal file
243
samples/sources/sample_02/sample_02.cpp
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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 "../common.hpp"
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const char* vs_source_cstr = R"glsl(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
attribute vec3 a_position;
|
||||||
|
attribute vec2 a_uv;
|
||||||
|
|
||||||
|
uniform mat4 u_MVP;
|
||||||
|
|
||||||
|
varying vec2 v_uv;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
v_uv = a_uv;
|
||||||
|
|
||||||
|
gl_Position = vec4(a_position, 1.0) * u_MVP;
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
const char* fs_source_cstr = R"glsl(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
varying vec2 v_uv;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 uv = vec2(v_uv.s, 1.0 - v_uv.t);
|
||||||
|
gl_FragColor = texture2D(u_texture, uv);
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
struct vertex {
|
||||||
|
v3f position;
|
||||||
|
v2hu uv;
|
||||||
|
static vertex_declaration decl() noexcept {
|
||||||
|
return vertex_declaration()
|
||||||
|
.add_attribute<v3f>("a_position")
|
||||||
|
.add_attribute<v2hu>("a_uv");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
array<u8,36> generate_cube_indices() noexcept {
|
||||||
|
return {
|
||||||
|
0, 1, 2,
|
||||||
|
2, 3, 0,
|
||||||
|
|
||||||
|
4, 5, 6,
|
||||||
|
6, 7, 4,
|
||||||
|
|
||||||
|
8, 9, 10,
|
||||||
|
10, 11, 8,
|
||||||
|
|
||||||
|
12, 13, 14,
|
||||||
|
14, 15, 12,
|
||||||
|
|
||||||
|
16, 17, 18,
|
||||||
|
18, 19, 16,
|
||||||
|
|
||||||
|
20, 21, 22,
|
||||||
|
22, 23, 20};
|
||||||
|
}
|
||||||
|
|
||||||
|
array<vertex,24> generate_cube_vertices(const v3f& size) noexcept {
|
||||||
|
f32 x = size.x * 0.5f;
|
||||||
|
f32 y = size.y * 0.5f;
|
||||||
|
f32 z = size.z * 0.5f;
|
||||||
|
return {
|
||||||
|
vertex{{-x, -y, -z}, {0, 1}},
|
||||||
|
vertex{{ x, -y, -z}, {1, 1}},
|
||||||
|
vertex{{ x, y, -z}, {1, 0}},
|
||||||
|
vertex{{-x, y, -z}, {0, 0}},
|
||||||
|
|
||||||
|
vertex{{-x, -y, z}, {0, 1}},
|
||||||
|
vertex{{ x, -y, z}, {1, 1}},
|
||||||
|
vertex{{ x, -y, -z}, {1, 0}},
|
||||||
|
vertex{{-x, -y, -z}, {0, 0}},
|
||||||
|
|
||||||
|
vertex{{ x, -y, z}, {0, 1}},
|
||||||
|
vertex{{-x, -y, z}, {1, 1}},
|
||||||
|
vertex{{-x, y, z}, {1, 0}},
|
||||||
|
vertex{{ x, y, z}, {0, 0}},
|
||||||
|
|
||||||
|
vertex{{-x, y, -z}, {0, 1}},
|
||||||
|
vertex{{ x, y, -z}, {1, 1}},
|
||||||
|
vertex{{ x, y, z}, {1, 0}},
|
||||||
|
vertex{{-x, y, z}, {0, 0}},
|
||||||
|
|
||||||
|
vertex{{ x, -y, -z}, {0, 1}},
|
||||||
|
vertex{{ x, -y, z}, {1, 1}},
|
||||||
|
vertex{{ x, y, z}, {1, 0}},
|
||||||
|
vertex{{ x, y, -z}, {0, 0}},
|
||||||
|
|
||||||
|
vertex{{-x, -y, z}, {0, 1}},
|
||||||
|
vertex{{-x, -y, -z}, {1, 1}},
|
||||||
|
vertex{{-x, y, -z}, {1, 0}},
|
||||||
|
vertex{{-x, y, z}, {0, 0}}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int e2d_main() {
|
||||||
|
{
|
||||||
|
modules::initialize<vfs>()
|
||||||
|
.register_scheme<filesystem_file_source>("file");
|
||||||
|
modules::initialize<debug>()
|
||||||
|
.register_sink<debug_console_sink>();
|
||||||
|
modules::initialize<input>();
|
||||||
|
modules::initialize<window>(v2u{640, 480}, "Enduro2D", false)
|
||||||
|
.register_event_listener<window_input_source>(the<input>());
|
||||||
|
modules::initialize<render>(the<debug>(), the<window>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
str resources;
|
||||||
|
filesystem::extract_predef_path(resources, filesystem::predef_path::resources);
|
||||||
|
the<vfs>().register_scheme_alias(
|
||||||
|
"resources",
|
||||||
|
url{"file", resources});
|
||||||
|
the<vfs>().register_scheme<archive_file_source>(
|
||||||
|
"piratepack",
|
||||||
|
the<vfs>().open(url("resources://bin/kenney_piratepack.zip")));
|
||||||
|
the<vfs>().register_scheme_alias("ships", url("piratepack://PNG/Retina/Ships"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto texture = the<render>().create_texture(
|
||||||
|
the<vfs>().open(url("ships://ship (3).png")));
|
||||||
|
|
||||||
|
const auto shader = the<render>().create_shader(
|
||||||
|
make_memory_stream(buffer(vs_source_cstr, std::strlen(vs_source_cstr))),
|
||||||
|
make_memory_stream(buffer(fs_source_cstr, std::strlen(fs_source_cstr))));
|
||||||
|
|
||||||
|
const auto indices = generate_cube_indices();
|
||||||
|
const auto index_buffer = the<render>().create_index_buffer(
|
||||||
|
buffer(indices.data(), indices.size() * sizeof(indices[0])),
|
||||||
|
index_declaration::index_type::unsigned_byte,
|
||||||
|
index_buffer::usage::static_draw);
|
||||||
|
|
||||||
|
const auto vertices = generate_cube_vertices(make_vec3(1.f));
|
||||||
|
const auto vertex_buffer = the<render>().create_vertex_buffer(
|
||||||
|
buffer(vertices.data(), vertices.size() * sizeof(vertices[0])),
|
||||||
|
vertex::decl(),
|
||||||
|
vertex_buffer::usage::static_draw);
|
||||||
|
|
||||||
|
if ( !texture || !shader || !index_buffer || !vertex_buffer ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto material = render::material()
|
||||||
|
.add_pass(render::pass_state()
|
||||||
|
.states(render::state_block()
|
||||||
|
.capabilities(render::capabilities_state()
|
||||||
|
.blending(true)
|
||||||
|
.culling(true)
|
||||||
|
.depth_test(true))
|
||||||
|
.blending(render::blending_state()
|
||||||
|
.src_factor(render::blending_factor::src_alpha)
|
||||||
|
.dst_factor(render::blending_factor::one_minus_src_alpha))
|
||||||
|
.culling(render::culling_state()
|
||||||
|
.mode(render::culling_mode::ccw)
|
||||||
|
.face(render::culling_face::back)))
|
||||||
|
.shader(shader))
|
||||||
|
.properties(render::property_block()
|
||||||
|
.sampler("u_texture", render::sampler_state()
|
||||||
|
.texture(texture)
|
||||||
|
.min_filter(render::sampler_min_filter::linear)
|
||||||
|
.mag_filter(render::sampler_mag_filter::linear)));
|
||||||
|
|
||||||
|
auto geometry = render::geometry()
|
||||||
|
.indices(index_buffer)
|
||||||
|
.add_vertices(vertex_buffer);
|
||||||
|
|
||||||
|
const auto begin_game_time = time::now_ms();
|
||||||
|
const auto framebuffer_size = the<window>().real_size().cast_to<f32>();
|
||||||
|
const auto projection = math::make_perspective_lh_matrix4(
|
||||||
|
make_deg(45.f),
|
||||||
|
framebuffer_size.x / framebuffer_size.y,
|
||||||
|
0.1f,
|
||||||
|
100.f);
|
||||||
|
|
||||||
|
const auto rt = the<render>().create_render_target(
|
||||||
|
the<window>().real_size() / 10u,
|
||||||
|
render_target::type::color_and_depth);
|
||||||
|
|
||||||
|
const keyboard& k = the<input>().keyboard();
|
||||||
|
while ( !the<window>().should_close() && !k.is_key_just_released(keyboard_key::escape) ) {
|
||||||
|
const auto game_time = (time::now_ms() - begin_game_time).cast_to<f32>().value;
|
||||||
|
|
||||||
|
const auto MVP =
|
||||||
|
math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 1.f, 0.f, 0.f) *
|
||||||
|
math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 1.f, 0.f) *
|
||||||
|
math::make_rotation_matrix4(make_rad(game_time) * 0.001f, 0.f, 0.f, 1.f) *
|
||||||
|
math::make_translation_matrix4(0.f, 0.f, 0.f) *
|
||||||
|
math::make_loot_at_lh_matrix4({0.f,0.f,-2.f}, v3f::zero(), v3f::unit_y()) *
|
||||||
|
projection;
|
||||||
|
|
||||||
|
material.properties()
|
||||||
|
.property("u_time", game_time)
|
||||||
|
.property("u_MVP", MVP);
|
||||||
|
|
||||||
|
material.properties()
|
||||||
|
.sampler("u_texture", render::sampler_state()
|
||||||
|
.texture(texture)
|
||||||
|
.min_filter(render::sampler_min_filter::linear)
|
||||||
|
.mag_filter(render::sampler_mag_filter::linear));
|
||||||
|
|
||||||
|
the<render>()
|
||||||
|
.set_render_target(rt)
|
||||||
|
.set_viewport(0, 0, rt->size().x, rt->size().y)
|
||||||
|
.clear_depth_buffer(1.f)
|
||||||
|
.clear_stencil_buffer(0)
|
||||||
|
.clear_color_buffer({0.f, 0.4f, 0.f, 1.f})
|
||||||
|
.draw(material, geometry);
|
||||||
|
|
||||||
|
material.properties()
|
||||||
|
.sampler("u_texture", render::sampler_state()
|
||||||
|
.texture(rt->color())
|
||||||
|
.min_filter(render::sampler_min_filter::linear)
|
||||||
|
.mag_filter(render::sampler_mag_filter::linear));
|
||||||
|
|
||||||
|
the<render>()
|
||||||
|
.set_render_target(nullptr)
|
||||||
|
.set_viewport(0, 0, the<window>().real_size().x, the<window>().real_size().y)
|
||||||
|
.clear_depth_buffer(1.f)
|
||||||
|
.clear_stencil_buffer(0)
|
||||||
|
.clear_color_buffer({1.f, 0.4f, 0.f, 1.f})
|
||||||
|
.draw(material, geometry);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(time::to_chrono(make_milliseconds(10)));
|
||||||
|
|
||||||
|
the<window>().swap_buffers(true);
|
||||||
|
the<input>().frame_tick();
|
||||||
|
window::poll_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -10,6 +10,37 @@ namespace
|
|||||||
{
|
{
|
||||||
using namespace e2d;
|
using namespace e2d;
|
||||||
|
|
||||||
|
struct pixel_type_description {
|
||||||
|
u32 minimal_size;
|
||||||
|
u32 bits_per_pixel;
|
||||||
|
pixel_declaration::pixel_type type;
|
||||||
|
bool compressed;
|
||||||
|
bool must_be_square;
|
||||||
|
bool must_be_power_of_two;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pixel_type_description pixel_type_descriptions[] = {
|
||||||
|
{1, 32, pixel_declaration::pixel_type::rgba8, false, false, false},
|
||||||
|
{1, 32, pixel_declaration::pixel_type::depth24_stencil8, false, false, false},
|
||||||
|
|
||||||
|
{4, 4, pixel_declaration::pixel_type::dxt1, true, false, true},
|
||||||
|
{4, 8, pixel_declaration::pixel_type::dxt3, true, false, true},
|
||||||
|
{4, 8, pixel_declaration::pixel_type::dxt5, true, false, true},
|
||||||
|
|
||||||
|
{8, 2, pixel_declaration::pixel_type::rgb_pvrtc2, true, true, true},
|
||||||
|
{8, 4, pixel_declaration::pixel_type::rgb_pvrtc4, true, true, true},
|
||||||
|
{8, 2, pixel_declaration::pixel_type::rgba_pvrtc2, true, true, true},
|
||||||
|
{8, 4, pixel_declaration::pixel_type::rgba_pvrtc4, true, true, true}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pixel_type_description& get_pixel_type_description(pixel_declaration::pixel_type type) noexcept {
|
||||||
|
const std::size_t index = math::numeric_cast<std::size_t>(math::enum_to_number(type));
|
||||||
|
E2D_ASSERT(index < E2D_COUNTOF(pixel_type_descriptions));
|
||||||
|
const pixel_type_description& desc = pixel_type_descriptions[index];
|
||||||
|
E2D_ASSERT(desc.type == type);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t index_element_size(index_declaration::index_type it) noexcept {
|
std::size_t index_element_size(index_declaration::index_type it) noexcept {
|
||||||
#define DEFINE_CASE(x,y) case index_declaration::index_type::x: return y;
|
#define DEFINE_CASE(x,y) case index_declaration::index_type::x: return y;
|
||||||
switch ( it ) {
|
switch ( it ) {
|
||||||
@@ -41,50 +72,55 @@ namespace
|
|||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// index_declaration::index_info
|
// pixel_declaration
|
||||||
//
|
//
|
||||||
|
|
||||||
index_declaration::index_info::index_info(index_type ntype) noexcept
|
pixel_declaration::pixel_declaration(pixel_type type) noexcept
|
||||||
: type(ntype) {}
|
: type_(type) {}
|
||||||
|
|
||||||
|
pixel_declaration::pixel_type pixel_declaration::type() const noexcept {
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pixel_declaration::is_compressed() const noexcept {
|
||||||
|
return get_pixel_type_description(type_).compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t pixel_declaration::bits_per_pixel() const noexcept {
|
||||||
|
return get_pixel_type_description(type_).bits_per_pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const pixel_declaration& l, const pixel_declaration& r) noexcept {
|
||||||
|
return l.type() == r.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const pixel_declaration& l, const pixel_declaration& r) noexcept {
|
||||||
|
return !(l == r);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// index_declaration
|
// index_declaration
|
||||||
//
|
//
|
||||||
|
|
||||||
index_declaration::index_declaration(index_type type) noexcept
|
index_declaration::index_declaration(index_type type) noexcept
|
||||||
: index_(type) {}
|
: type_(type) {}
|
||||||
|
|
||||||
const index_declaration::index_info& index_declaration::index() const noexcept {
|
index_declaration::index_type index_declaration::type() const noexcept {
|
||||||
return index_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t index_declaration::index_size() const noexcept {
|
std::size_t index_declaration::bytes_per_index() const noexcept {
|
||||||
return index_element_size(index_.type);
|
return index_element_size(type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const index_declaration& l, const index_declaration& r) noexcept {
|
bool operator==(const index_declaration& l, const index_declaration& r) noexcept {
|
||||||
return l.index_size() == r.index_size()
|
return l.type() == r.type();
|
||||||
&& l.index() == r.index();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const index_declaration& l, const index_declaration& r) noexcept {
|
bool operator!=(const index_declaration& l, const index_declaration& r) noexcept {
|
||||||
return !(l == r);
|
return !(l == r);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(
|
|
||||||
const index_declaration::index_info& l,
|
|
||||||
const index_declaration::index_info& r) noexcept
|
|
||||||
{
|
|
||||||
return l.type == r.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(
|
|
||||||
const index_declaration::index_info& l,
|
|
||||||
const index_declaration::index_info& r) noexcept
|
|
||||||
{
|
|
||||||
return !(l == r);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// vertex_declaration::attribute_info
|
// vertex_declaration::attribute_info
|
||||||
//
|
//
|
||||||
@@ -118,7 +154,7 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
|
|
||||||
vertex_declaration& vertex_declaration::skip_bytes(std::size_t bytes) noexcept {
|
vertex_declaration& vertex_declaration::skip_bytes(std::size_t bytes) noexcept {
|
||||||
vertex_size_ += bytes;
|
bytes_per_vertex_ += bytes;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +166,7 @@ namespace e2d
|
|||||||
bool normalized) noexcept
|
bool normalized) noexcept
|
||||||
{
|
{
|
||||||
E2D_ASSERT(attribute_count_ < attributes_.size());
|
E2D_ASSERT(attribute_count_ < attributes_.size());
|
||||||
const std::size_t stride = vertex_size_;
|
const std::size_t stride = bytes_per_vertex_;
|
||||||
attributes_[attribute_count_] = attribute_info(
|
attributes_[attribute_count_] = attribute_info(
|
||||||
stride,
|
stride,
|
||||||
name,
|
name,
|
||||||
@@ -138,7 +174,7 @@ namespace e2d
|
|||||||
columns,
|
columns,
|
||||||
type,
|
type,
|
||||||
normalized);
|
normalized);
|
||||||
vertex_size_ += attribute_element_size(type) * rows * columns;
|
bytes_per_vertex_ += attribute_element_size(type) * rows * columns;
|
||||||
++attribute_count_;
|
++attribute_count_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -152,12 +188,12 @@ namespace e2d
|
|||||||
return attribute_count_;
|
return attribute_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t vertex_declaration::vertex_size() const noexcept {
|
std::size_t vertex_declaration::bytes_per_vertex() const noexcept {
|
||||||
return vertex_size_;
|
return bytes_per_vertex_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const vertex_declaration& l, const vertex_declaration& r) noexcept {
|
bool operator==(const vertex_declaration& l, const vertex_declaration& r) noexcept {
|
||||||
if ( l.vertex_size() != r.vertex_size() ) {
|
if ( l.bytes_per_vertex() != r.bytes_per_vertex() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( l.attribute_count() != r.attribute_count() ) {
|
if ( l.attribute_count() != r.attribute_count() ) {
|
||||||
@@ -695,6 +731,11 @@ namespace e2d
|
|||||||
return pass_count_;
|
return pass_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render::material& render::material::properties(const property_block& properties) noexcept {
|
||||||
|
properties_ = properties;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
render::pass_state& render::material::pass(std::size_t index) noexcept {
|
render::pass_state& render::material::pass(std::size_t index) noexcept {
|
||||||
return passes_[index];
|
return passes_[index];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,16 @@ namespace e2d
|
|||||||
~internal_state() noexcept = default;
|
~internal_state() noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// render_target::internal_state
|
||||||
|
//
|
||||||
|
|
||||||
|
class render_target::internal_state final : private e2d::noncopyable {
|
||||||
|
public:
|
||||||
|
internal_state() noexcept = default;
|
||||||
|
~internal_state() noexcept = default;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// render::internal_state
|
// render::internal_state
|
||||||
//
|
//
|
||||||
@@ -94,8 +104,9 @@ namespace e2d
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
image_data_format texture::format() const noexcept {
|
const pixel_declaration& texture::decl() const noexcept {
|
||||||
return image_data_format::rgba8;
|
static pixel_declaration decl;
|
||||||
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -122,6 +133,29 @@ namespace e2d
|
|||||||
: state_(std::move(state)) {}
|
: state_(std::move(state)) {}
|
||||||
vertex_buffer::~vertex_buffer() noexcept = default;
|
vertex_buffer::~vertex_buffer() noexcept = default;
|
||||||
|
|
||||||
|
//
|
||||||
|
// render_target
|
||||||
|
//
|
||||||
|
|
||||||
|
render_target::render_target(internal_state_uptr state)
|
||||||
|
: state_(std::move(state)) {}
|
||||||
|
render_target::~render_target() noexcept = default;
|
||||||
|
|
||||||
|
const v2u& render_target::size() const noexcept {
|
||||||
|
static v2u size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::color() const noexcept {
|
||||||
|
static texture_ptr color;
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::depth() const noexcept {
|
||||||
|
static texture_ptr depth;
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// render
|
// render
|
||||||
//
|
//
|
||||||
@@ -148,6 +182,11 @@ namespace e2d
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
texture_ptr render::create_texture(const v2u& size, const pixel_declaration& decl) {
|
||||||
|
E2D_UNUSED(size, decl);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
index_buffer_ptr render::create_index_buffer(
|
index_buffer_ptr render::create_index_buffer(
|
||||||
const buffer& indices,
|
const buffer& indices,
|
||||||
const index_declaration& decl,
|
const index_declaration& decl,
|
||||||
@@ -166,6 +205,11 @@ namespace e2d
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_target_ptr render::create_render_target(const v2u& size, render_target::type type) {
|
||||||
|
E2D_UNUSED(size, type);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void render::draw(
|
void render::draw(
|
||||||
const material& mat,
|
const material& mat,
|
||||||
const geometry& geo)
|
const geometry& geo)
|
||||||
@@ -200,6 +244,11 @@ namespace e2d
|
|||||||
E2D_UNUSED(x, y, w, h);
|
E2D_UNUSED(x, y, w, h);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render& render::set_render_target(const render_target_ptr& rt) noexcept {
|
||||||
|
E2D_UNUSED(rt);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ namespace
|
|||||||
math::numeric_cast<GLint>(vai.columns),
|
math::numeric_cast<GLint>(vai.columns),
|
||||||
convert_attribute_type(vai.type),
|
convert_attribute_type(vai.type),
|
||||||
vai.normalized ? GL_TRUE : GL_FALSE,
|
vai.normalized ? GL_TRUE : GL_FALSE,
|
||||||
math::numeric_cast<GLsizei>(decl.vertex_size()),
|
math::numeric_cast<GLsizei>(decl.bytes_per_vertex()),
|
||||||
reinterpret_cast<const GLvoid*>(vai.stride + row * vai.row_size())));
|
reinterpret_cast<const GLvoid*>(vai.stride + row * vai.row_size())));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -225,7 +225,7 @@ namespace
|
|||||||
GL_CHECK_CODE(debug, glDrawElements(
|
GL_CHECK_CODE(debug, glDrawElements(
|
||||||
convert_topology(tp),
|
convert_topology(tp),
|
||||||
math::numeric_cast<GLsizei>(ib->index_count()),
|
math::numeric_cast<GLsizei>(ib->index_count()),
|
||||||
convert_index_type(decl.index().type),
|
convert_index_type(decl.type()),
|
||||||
nullptr));
|
nullptr));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -321,8 +321,8 @@ namespace e2d
|
|||||||
return state_->size();
|
return state_->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
image_data_format texture::format() const noexcept {
|
const pixel_declaration& texture::decl() const noexcept {
|
||||||
return state_->format();
|
return state_->decl();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -340,9 +340,9 @@ namespace e2d
|
|||||||
index_buffer::~index_buffer() noexcept = default;
|
index_buffer::~index_buffer() noexcept = default;
|
||||||
|
|
||||||
void index_buffer::update(const buffer& indices, std::size_t offset) noexcept {
|
void index_buffer::update(const buffer& indices, std::size_t offset) noexcept {
|
||||||
const std::size_t buffer_offset = offset * state_->decl().index_size();
|
const std::size_t buffer_offset = offset * state_->decl().bytes_per_index();
|
||||||
E2D_ASSERT(indices.size() + buffer_offset <= state_->size());
|
E2D_ASSERT(indices.size() + buffer_offset <= state_->size());
|
||||||
E2D_ASSERT(indices.size() % state_->decl().index_size() == 0);
|
E2D_ASSERT(indices.size() % state_->decl().bytes_per_index() == 0);
|
||||||
opengl::with_gl_bind_buffer(state_->dbg(), state_->id(),
|
opengl::with_gl_bind_buffer(state_->dbg(), state_->id(),
|
||||||
[this, &indices, &buffer_offset]() noexcept {
|
[this, &indices, &buffer_offset]() noexcept {
|
||||||
GL_CHECK_CODE(state_->dbg(), glBufferSubData(
|
GL_CHECK_CODE(state_->dbg(), glBufferSubData(
|
||||||
@@ -353,17 +353,17 @@ namespace e2d
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const index_declaration& index_buffer::decl() const noexcept {
|
|
||||||
return state_->decl();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t index_buffer::buffer_size() const noexcept {
|
std::size_t index_buffer::buffer_size() const noexcept {
|
||||||
return state_->size();
|
return state_->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t index_buffer::index_count() const noexcept {
|
std::size_t index_buffer::index_count() const noexcept {
|
||||||
E2D_ASSERT(state_->size() % state_->decl().index_size() == 0);
|
E2D_ASSERT(state_->size() % state_->decl().bytes_per_index() == 0);
|
||||||
return state_->size() / state_->decl().index_size();
|
return state_->size() / state_->decl().bytes_per_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
const index_declaration& index_buffer::decl() const noexcept {
|
||||||
|
return state_->decl();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -381,9 +381,9 @@ namespace e2d
|
|||||||
vertex_buffer::~vertex_buffer() noexcept = default;
|
vertex_buffer::~vertex_buffer() noexcept = default;
|
||||||
|
|
||||||
void vertex_buffer::update(const buffer& vertices, std::size_t offset) noexcept {
|
void vertex_buffer::update(const buffer& vertices, std::size_t offset) noexcept {
|
||||||
const std::size_t buffer_offset = offset * state_->decl().vertex_size();
|
const std::size_t buffer_offset = offset * state_->decl().bytes_per_vertex();
|
||||||
E2D_ASSERT(vertices.size() + buffer_offset <= state_->size());
|
E2D_ASSERT(vertices.size() + buffer_offset <= state_->size());
|
||||||
E2D_ASSERT(vertices.size() % state_->decl().vertex_size() == 0);
|
E2D_ASSERT(vertices.size() % state_->decl().bytes_per_vertex() == 0);
|
||||||
opengl::with_gl_bind_buffer(state_->dbg(), state_->id(),
|
opengl::with_gl_bind_buffer(state_->dbg(), state_->id(),
|
||||||
[this, &vertices, &buffer_offset]() noexcept {
|
[this, &vertices, &buffer_offset]() noexcept {
|
||||||
GL_CHECK_CODE(state_->dbg(), glBufferSubData(
|
GL_CHECK_CODE(state_->dbg(), glBufferSubData(
|
||||||
@@ -394,17 +394,43 @@ namespace e2d
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const vertex_declaration& vertex_buffer::decl() const noexcept {
|
|
||||||
return state_->decl();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t vertex_buffer::buffer_size() const noexcept {
|
std::size_t vertex_buffer::buffer_size() const noexcept {
|
||||||
return state_->size();
|
return state_->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t vertex_buffer::vertex_count() const noexcept {
|
std::size_t vertex_buffer::vertex_count() const noexcept {
|
||||||
E2D_ASSERT(state_->size() % state_->decl().vertex_size() == 0);
|
E2D_ASSERT(state_->size() % state_->decl().bytes_per_vertex() == 0);
|
||||||
return state_->size() / state_->decl().vertex_size();
|
return state_->size() / state_->decl().bytes_per_vertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
const vertex_declaration& vertex_buffer::decl() const noexcept {
|
||||||
|
return state_->decl();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// render_target
|
||||||
|
//
|
||||||
|
|
||||||
|
const render_target::internal_state& render_target::state() const noexcept {
|
||||||
|
return *state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_target::render_target(internal_state_uptr state)
|
||||||
|
: state_(std::move(state)) {
|
||||||
|
E2D_ASSERT(state_);
|
||||||
|
}
|
||||||
|
render_target::~render_target() noexcept = default;
|
||||||
|
|
||||||
|
const v2u& render_target::size() const noexcept {
|
||||||
|
return state_->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::color() const noexcept {
|
||||||
|
return state_->color();
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::depth() const noexcept {
|
||||||
|
return state_->depth();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -448,17 +474,54 @@ namespace e2d
|
|||||||
state_->dbg(), std::move(ps)));
|
state_->dbg(), std::move(ps)));
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_ptr render::create_texture(const image& image) {
|
texture_ptr render::create_texture(
|
||||||
gl_texture_id id = gl_compile_texture(state_->dbg(), image);
|
const image& image)
|
||||||
|
{
|
||||||
|
gl_texture_id id = gl_texture_id::create(
|
||||||
|
state_->dbg(), GL_TEXTURE_2D);
|
||||||
if ( id.empty() ) {
|
if ( id.empty() ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create texture: %0",
|
||||||
|
"failed to create texture id");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
const pixel_declaration decl =
|
||||||
|
convert_image_data_format_to_pixel_declaration(image.format());
|
||||||
|
with_gl_bind_texture(state_->dbg(), id, [this, &id, &image, &decl]() noexcept {
|
||||||
|
if ( decl.is_compressed() ) {
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glCompressedTexImage2D(
|
||||||
|
id.target(),
|
||||||
|
0,
|
||||||
|
convert_pixel_type_to_compressed_format(decl.type()),
|
||||||
|
math::numeric_cast<GLsizei>(image.size().x),
|
||||||
|
math::numeric_cast<GLsizei>(image.size().y),
|
||||||
|
0,
|
||||||
|
math::numeric_cast<GLsizei>(image.data().size()),
|
||||||
|
image.data().data()));
|
||||||
|
} else {
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glTexImage2D(
|
||||||
|
id.target(),
|
||||||
|
0,
|
||||||
|
convert_pixel_type_to_internal_format(decl.type()),
|
||||||
|
math::numeric_cast<GLsizei>(image.size().x),
|
||||||
|
math::numeric_cast<GLsizei>(image.size().y),
|
||||||
|
0,
|
||||||
|
convert_image_data_format_to_external_format(image.format()),
|
||||||
|
convert_image_data_format_to_external_data_type(image.format()),
|
||||||
|
image.data().data()));
|
||||||
|
}
|
||||||
|
#if !defined(GL_ES_VERSION_2_0)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
return std::make_shared<texture>(
|
return std::make_shared<texture>(
|
||||||
std::make_unique<texture::internal_state>(
|
std::make_unique<texture::internal_state>(
|
||||||
state_->dbg(), std::move(id), image.size(), image.format()));
|
state_->dbg(), std::move(id), image.size(), decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_ptr render::create_texture(const input_stream_uptr& image_stream) {
|
texture_ptr render::create_texture(
|
||||||
|
const input_stream_uptr& image_stream)
|
||||||
|
{
|
||||||
image image;
|
image image;
|
||||||
if ( !images::try_load_image(image, image_stream) ) {
|
if ( !images::try_load_image(image, image_stream) ) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -466,13 +529,59 @@ namespace e2d
|
|||||||
return create_texture(image);
|
return create_texture(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
texture_ptr render::create_texture(
|
||||||
|
const v2u& size,
|
||||||
|
const pixel_declaration& decl)
|
||||||
|
{
|
||||||
|
gl_texture_id id = gl_texture_id::create(
|
||||||
|
state_->dbg(), GL_TEXTURE_2D);
|
||||||
|
if ( id.empty() ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create texture: %0",
|
||||||
|
"failed to create texture id");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
with_gl_bind_texture(state_->dbg(), id, [this, &id, &size, &decl]() noexcept {
|
||||||
|
if ( decl.is_compressed() ) {
|
||||||
|
buffer empty_data(decl.bits_per_pixel() * size.x * size.y / 8);
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glCompressedTexImage2D(
|
||||||
|
id.target(),
|
||||||
|
0,
|
||||||
|
convert_pixel_type_to_compressed_format(decl.type()),
|
||||||
|
math::numeric_cast<GLsizei>(size.x),
|
||||||
|
math::numeric_cast<GLsizei>(size.y),
|
||||||
|
0,
|
||||||
|
math::numeric_cast<GLsizei>(empty_data.size()),
|
||||||
|
empty_data.data()));
|
||||||
|
} else {
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glTexImage2D(
|
||||||
|
id.target(),
|
||||||
|
0,
|
||||||
|
convert_pixel_type_to_internal_format(decl.type()),
|
||||||
|
math::numeric_cast<GLsizei>(size.x),
|
||||||
|
math::numeric_cast<GLsizei>(size.y),
|
||||||
|
0,
|
||||||
|
convert_pixel_type_to_external_format(decl.type()),
|
||||||
|
convert_pixel_type_to_external_data_type(decl.type()),
|
||||||
|
nullptr));
|
||||||
|
}
|
||||||
|
#if !defined(GL_ES_VERSION_2_0)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
return std::make_shared<texture>(
|
||||||
|
std::make_unique<texture::internal_state>(
|
||||||
|
state_->dbg(), std::move(id), size, decl));
|
||||||
|
}
|
||||||
|
|
||||||
index_buffer_ptr render::create_index_buffer(
|
index_buffer_ptr render::create_index_buffer(
|
||||||
const buffer& indices,
|
const buffer& indices,
|
||||||
const index_declaration& decl,
|
const index_declaration& decl,
|
||||||
index_buffer::usage usage)
|
index_buffer::usage usage)
|
||||||
{
|
{
|
||||||
E2D_ASSERT(indices.size() % decl.index_size() == 0);
|
E2D_ASSERT(indices.size() % decl.bytes_per_index() == 0);
|
||||||
gl_buffer_id id = gl_compile_index_buffer(state_->dbg(), indices, usage);
|
gl_buffer_id id = gl_compile_index_buffer(
|
||||||
|
state_->dbg(), indices, usage);
|
||||||
if ( id.empty() ) {
|
if ( id.empty() ) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -486,8 +595,9 @@ namespace e2d
|
|||||||
const vertex_declaration& decl,
|
const vertex_declaration& decl,
|
||||||
vertex_buffer::usage usage)
|
vertex_buffer::usage usage)
|
||||||
{
|
{
|
||||||
E2D_ASSERT(vertices.size() % decl.vertex_size() == 0);
|
E2D_ASSERT(vertices.size() % decl.bytes_per_vertex() == 0);
|
||||||
gl_buffer_id id = gl_compile_vertex_buffer(state_->dbg(), vertices, usage);
|
gl_buffer_id id = gl_compile_vertex_buffer(
|
||||||
|
state_->dbg(), vertices, usage);
|
||||||
if ( id.empty() ) {
|
if ( id.empty() ) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -496,6 +606,83 @@ namespace e2d
|
|||||||
state_->dbg(), std::move(id), vertices.size(), decl));
|
state_->dbg(), std::move(id), vertices.size(), decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_target_ptr render::create_render_target(
|
||||||
|
const v2u& size,
|
||||||
|
render_target::type type)
|
||||||
|
{
|
||||||
|
gl_framebuffer_id id = gl_framebuffer_id::create(
|
||||||
|
state_->dbg(), GL_FRAMEBUFFER);
|
||||||
|
if ( id.empty() ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
"failed to create framebuffer id");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool need_color = math::enum_to_number(type) & math::enum_to_number(render_target::type::color);
|
||||||
|
bool need_depth = math::enum_to_number(type) & math::enum_to_number(render_target::type::depth);
|
||||||
|
|
||||||
|
texture_ptr color;
|
||||||
|
texture_ptr depth;
|
||||||
|
|
||||||
|
gl_renderbuffer_id color_rb(state_->dbg());
|
||||||
|
gl_renderbuffer_id depth_rb(state_->dbg());
|
||||||
|
|
||||||
|
if ( need_color ) {
|
||||||
|
color = create_texture(size, pixel_declaration::pixel_type::rgba8);
|
||||||
|
if ( !color ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
"failed to create color texture");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
gl_attach_texture(state_->dbg(), id, color->state().id(), GL_COLOR_ATTACHMENT0);
|
||||||
|
} else {
|
||||||
|
color_rb = gl_compile_renderbuffer(state_->dbg(), size, GL_RGBA8);
|
||||||
|
if ( color_rb.empty() ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
"failed to create color renderbuffer");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
gl_attach_renderbuffer(state_->dbg(), id, color_rb, GL_COLOR_ATTACHMENT0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( need_depth ) {
|
||||||
|
depth = create_texture(size, pixel_declaration::pixel_type::depth24_stencil8);
|
||||||
|
if ( !depth ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
"failed to create depth texture");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
gl_attach_texture(state_->dbg(), id, depth->state().id(), GL_DEPTH_ATTACHMENT);
|
||||||
|
gl_attach_texture(state_->dbg(), id, depth->state().id(), GL_STENCIL_ATTACHMENT);
|
||||||
|
} else {
|
||||||
|
depth_rb = gl_compile_renderbuffer(state_->dbg(), size, GL_DEPTH24_STENCIL8);
|
||||||
|
if ( depth_rb.empty() ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
"failed to create depth renderbuffer");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
gl_attach_renderbuffer(state_->dbg(), id, depth_rb, GL_DEPTH_ATTACHMENT);
|
||||||
|
gl_attach_renderbuffer(state_->dbg(), id, depth_rb, GL_STENCIL_ATTACHMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum fb_status = GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
if ( !gl_check_framebuffer(state_->dbg(), id, &fb_status) ) {
|
||||||
|
state_->dbg().error("RENDER: Failed to create framebuffer: %0",
|
||||||
|
gl_framebuffer_status_to_cstr(fb_status));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<render_target>(
|
||||||
|
std::make_unique<render_target::internal_state>(
|
||||||
|
state_->dbg(),
|
||||||
|
std::move(id),
|
||||||
|
size,
|
||||||
|
std::move(color),
|
||||||
|
std::move(depth),
|
||||||
|
std::move(color_rb),
|
||||||
|
std::move(depth_rb)));
|
||||||
|
}
|
||||||
|
|
||||||
void render::draw(
|
void render::draw(
|
||||||
const material& mat,
|
const material& mat,
|
||||||
const geometry& geo)
|
const geometry& geo)
|
||||||
@@ -524,26 +711,35 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
|
|
||||||
render& render::clear_depth_buffer(f32 value) noexcept {
|
render& render::clear_depth_buffer(f32 value) noexcept {
|
||||||
GL_CHECK_CODE(state_->dbg(), glClearDepth(
|
const render_target_ptr& rt = state_->render_target();
|
||||||
math::numeric_cast<GLclampd>(math::saturate(value))));
|
if ( !rt || rt->state().depth() || !rt->state().depth_rb().empty() ) {
|
||||||
GL_CHECK_CODE(state_->dbg(), glClear(GL_DEPTH_BUFFER_BIT));
|
GL_CHECK_CODE(state_->dbg(), glClearDepth(
|
||||||
|
math::numeric_cast<GLclampd>(math::saturate(value))));
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
render& render::clear_stencil_buffer(u8 value) noexcept {
|
render& render::clear_stencil_buffer(u8 value) noexcept {
|
||||||
GL_CHECK_CODE(state_->dbg(), glClearStencil(
|
const render_target_ptr& rt = state_->render_target();
|
||||||
math::numeric_cast<GLint>(value)));
|
if ( !rt || rt->state().depth() || !rt->state().depth_rb().empty() ) {
|
||||||
GL_CHECK_CODE(state_->dbg(), glClear(GL_STENCIL_BUFFER_BIT));
|
GL_CHECK_CODE(state_->dbg(), glClearStencil(
|
||||||
|
math::numeric_cast<GLint>(value)));
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glClear(GL_STENCIL_BUFFER_BIT));
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
render& render::clear_color_buffer(const color& value) noexcept {
|
render& render::clear_color_buffer(const color& value) noexcept {
|
||||||
GL_CHECK_CODE(state_->dbg(), glClearColor(
|
const render_target_ptr& rt = state_->render_target();
|
||||||
math::numeric_cast<GLclampf>(math::saturate(value.r)),
|
if ( !rt || rt->state().color() || !rt->state().color_rb().empty() ) {
|
||||||
math::numeric_cast<GLclampf>(math::saturate(value.g)),
|
GL_CHECK_CODE(state_->dbg(), glClearColor(
|
||||||
math::numeric_cast<GLclampf>(math::saturate(value.b)),
|
math::numeric_cast<GLclampf>(math::saturate(value.r)),
|
||||||
math::numeric_cast<GLclampf>(math::saturate(value.a))));
|
math::numeric_cast<GLclampf>(math::saturate(value.g)),
|
||||||
GL_CHECK_CODE(state_->dbg(), glClear(GL_COLOR_BUFFER_BIT));
|
math::numeric_cast<GLclampf>(math::saturate(value.b)),
|
||||||
|
math::numeric_cast<GLclampf>(math::saturate(value.a))));
|
||||||
|
GL_CHECK_CODE(state_->dbg(), glClear(GL_COLOR_BUFFER_BIT));
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +751,11 @@ namespace e2d
|
|||||||
math::numeric_cast<GLsizei>(h)));
|
math::numeric_cast<GLsizei>(h)));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render& render::set_render_target(const render_target_ptr& rt) noexcept {
|
||||||
|
state_->set_render_target(rt);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ namespace
|
|||||||
*loc = glGetAttribLocation(program, name);
|
*loc = glGetAttribLocation(program, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gl_check_framebuffer_status(GLenum target, GLenum* res) noexcept {
|
||||||
|
E2D_ASSERT(res);
|
||||||
|
*res = glCheckFramebufferStatus(target);
|
||||||
|
}
|
||||||
|
|
||||||
bool process_shader_compilation_result(debug& debug, GLuint shader) noexcept {
|
bool process_shader_compilation_result(debug& debug, GLuint shader) noexcept {
|
||||||
E2D_ASSERT(glIsShader(shader));
|
E2D_ASSERT(glIsShader(shader));
|
||||||
GLint success = GL_FALSE;
|
GLint success = GL_FALSE;
|
||||||
@@ -169,12 +174,10 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_buffer_id::operator*() const noexcept {
|
GLuint gl_buffer_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum gl_buffer_id::target() const noexcept {
|
GLenum gl_buffer_id::target() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return target_;
|
return target_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,12 +250,10 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_shader_id::operator*() const noexcept {
|
GLuint gl_shader_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum gl_shader_id::type() const noexcept {
|
GLenum gl_shader_id::type() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +326,6 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_program_id::operator*() const noexcept {
|
GLuint gl_program_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,12 +405,10 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_texture_id::operator*() const noexcept {
|
GLuint gl_texture_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum gl_texture_id::target() const noexcept {
|
GLenum gl_texture_id::target() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return target_;
|
return target_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,12 +487,10 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_framebuffer_id::operator*() const noexcept {
|
GLuint gl_framebuffer_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum gl_framebuffer_id::target() const noexcept {
|
GLenum gl_framebuffer_id::target() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return target_;
|
return target_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,12 +569,10 @@ namespace e2d { namespace opengl
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLuint gl_renderbuffer_id::operator*() const noexcept {
|
GLuint gl_renderbuffer_id::operator*() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum gl_renderbuffer_id::target() const noexcept {
|
GLenum gl_renderbuffer_id::target() const noexcept {
|
||||||
E2D_ASSERT(!empty());
|
|
||||||
return target_;
|
return target_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,44 +687,109 @@ namespace e2d { namespace opengl
|
|||||||
|
|
||||||
namespace e2d { namespace opengl
|
namespace e2d { namespace opengl
|
||||||
{
|
{
|
||||||
GLint convert_format_to_internal_format(image_data_format idf) noexcept {
|
GLenum convert_image_data_format_to_external_format(image_data_format f) noexcept {
|
||||||
#define DEFINE_CASE(x,y) case image_data_format::x: return y;
|
#define DEFINE_CASE(x,y) case image_data_format::x: return y
|
||||||
switch ( idf ) {
|
switch ( f ) {
|
||||||
DEFINE_CASE(g8, GL_ALPHA);
|
DEFINE_CASE(g8, GL_LUMINANCE);
|
||||||
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
||||||
DEFINE_CASE(rgb8, GL_RGB);
|
DEFINE_CASE(rgb8, GL_RGB);
|
||||||
DEFINE_CASE(rgba8, GL_RGBA);
|
DEFINE_CASE(rgba8, GL_RGBA);
|
||||||
default:
|
default:
|
||||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||||
return 0;
|
return GL_RGBA;
|
||||||
}
|
}
|
||||||
#undef DEFINE_CASE
|
#undef DEFINE_CASE
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum convert_format_to_external_format(image_data_format idf) noexcept {
|
GLenum convert_image_data_format_to_external_data_type(image_data_format f) noexcept {
|
||||||
#define DEFINE_CASE(x,y) case image_data_format::x: return y;
|
#define DEFINE_CASE(x,y) case image_data_format::x: return y
|
||||||
switch ( idf ) {
|
switch ( f ) {
|
||||||
DEFINE_CASE(g8, GL_ALPHA);
|
|
||||||
DEFINE_CASE(ga8, GL_LUMINANCE_ALPHA);
|
|
||||||
DEFINE_CASE(rgb8, GL_RGB);
|
|
||||||
DEFINE_CASE(rgba8, GL_RGBA);
|
|
||||||
default:
|
|
||||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#undef DEFINE_CASE
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum convert_format_to_external_data_type(image_data_format idf) noexcept {
|
|
||||||
#define DEFINE_CASE(x,y) case image_data_format::x: return y;
|
|
||||||
switch ( idf ) {
|
|
||||||
DEFINE_CASE(g8, GL_UNSIGNED_BYTE);
|
DEFINE_CASE(g8, GL_UNSIGNED_BYTE);
|
||||||
DEFINE_CASE(ga8, GL_UNSIGNED_BYTE);
|
DEFINE_CASE(ga8, GL_UNSIGNED_BYTE);
|
||||||
DEFINE_CASE(rgb8, GL_UNSIGNED_BYTE);
|
DEFINE_CASE(rgb8, GL_UNSIGNED_BYTE);
|
||||||
DEFINE_CASE(rgba8, GL_UNSIGNED_BYTE);
|
DEFINE_CASE(rgba8, GL_UNSIGNED_BYTE);
|
||||||
default:
|
default:
|
||||||
E2D_ASSERT_MSG(false, "unexpected image data format");
|
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||||
return 0;
|
return GL_UNSIGNED_BYTE;
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum convert_pixel_type_to_external_format(pixel_declaration::pixel_type f) noexcept {
|
||||||
|
#define DEFINE_CASE(x,y) case pixel_declaration::pixel_type::x: return y
|
||||||
|
switch ( f ) {
|
||||||
|
DEFINE_CASE(rgba8, GL_RGBA);
|
||||||
|
DEFINE_CASE(depth24_stencil8, GL_DEPTH_STENCIL);
|
||||||
|
default:
|
||||||
|
E2D_ASSERT_MSG(false, "unexpected pixel type");
|
||||||
|
return GL_RGBA;
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum convert_pixel_type_to_external_data_type(pixel_declaration::pixel_type f) noexcept {
|
||||||
|
#define DEFINE_CASE(x,y) case pixel_declaration::pixel_type::x: return y
|
||||||
|
switch ( f ) {
|
||||||
|
DEFINE_CASE(rgba8, GL_UNSIGNED_BYTE);
|
||||||
|
DEFINE_CASE(depth24_stencil8, GL_UNSIGNED_INT_24_8);
|
||||||
|
default:
|
||||||
|
E2D_ASSERT_MSG(false, "unexpected pixel type");
|
||||||
|
return GL_UNSIGNED_BYTE;
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint convert_pixel_type_to_internal_format(pixel_declaration::pixel_type f) noexcept {
|
||||||
|
#define DEFINE_CASE(x,y) case pixel_declaration::pixel_type::x: return y
|
||||||
|
switch ( f ) {
|
||||||
|
DEFINE_CASE(rgba8, GL_RGBA);
|
||||||
|
DEFINE_CASE(depth24_stencil8, GL_DEPTH24_STENCIL8);
|
||||||
|
default:
|
||||||
|
E2D_ASSERT_MSG(false, "unexpected pixel type");
|
||||||
|
return GL_RGBA;
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum convert_pixel_type_to_compressed_format(pixel_declaration::pixel_type f) noexcept {
|
||||||
|
#define DEFINE_CASE(x,y) case pixel_declaration::pixel_type::x: return y
|
||||||
|
switch ( f ) {
|
||||||
|
DEFINE_CASE(dxt1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
|
||||||
|
DEFINE_CASE(dxt3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
|
||||||
|
DEFINE_CASE(dxt5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
|
||||||
|
|
||||||
|
DEFINE_CASE(rgb_pvrtc2, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG);
|
||||||
|
DEFINE_CASE(rgb_pvrtc4, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
|
||||||
|
|
||||||
|
DEFINE_CASE(rgba_pvrtc2, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG);
|
||||||
|
DEFINE_CASE(rgba_pvrtc4, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG);
|
||||||
|
default:
|
||||||
|
E2D_ASSERT_MSG(false, "unexpected pixel type");
|
||||||
|
return GL_RGBA;
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_declaration convert_image_data_format_to_pixel_declaration(image_data_format f) noexcept {
|
||||||
|
#define DEFINE_CASE(x,y) case image_data_format::x: return pixel_declaration(pixel_declaration::pixel_type::y)
|
||||||
|
switch ( f ) {
|
||||||
|
DEFINE_CASE(g8, rgba8);
|
||||||
|
DEFINE_CASE(ga8, rgba8);
|
||||||
|
DEFINE_CASE(rgb8, rgba8);
|
||||||
|
DEFINE_CASE(rgba8, rgba8);
|
||||||
|
|
||||||
|
DEFINE_CASE(dxt1, dxt1);
|
||||||
|
DEFINE_CASE(dxt3, dxt3);
|
||||||
|
DEFINE_CASE(dxt5, dxt5);
|
||||||
|
|
||||||
|
DEFINE_CASE(rgb_pvrtc2, rgb_pvrtc2);
|
||||||
|
DEFINE_CASE(rgb_pvrtc4, rgb_pvrtc4);
|
||||||
|
|
||||||
|
DEFINE_CASE(rgba_pvrtc2, rgba_pvrtc2);
|
||||||
|
DEFINE_CASE(rgba_pvrtc4, rgba_pvrtc4);
|
||||||
|
default:
|
||||||
|
E2D_ASSERT_MSG(false, "unexpected image data format");
|
||||||
|
return pixel_declaration(pixel_declaration::pixel_type::rgba8);
|
||||||
}
|
}
|
||||||
#undef DEFINE_CASE
|
#undef DEFINE_CASE
|
||||||
}
|
}
|
||||||
@@ -1071,6 +1130,19 @@ namespace e2d { namespace opengl
|
|||||||
#undef DEFINE_CASE
|
#undef DEFINE_CASE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* gl_framebuffer_status_to_cstr(GLenum s) noexcept {
|
||||||
|
#define DEFINE_CASE(x) case x: return #x
|
||||||
|
switch ( s ) {
|
||||||
|
DEFINE_CASE(GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
DEFINE_CASE(GL_FRAMEBUFFER_UNSUPPORTED);
|
||||||
|
DEFINE_CASE(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
|
||||||
|
DEFINE_CASE(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
|
||||||
|
default:
|
||||||
|
return "GL_FRAMEBUFFER_UNKNOWN";
|
||||||
|
}
|
||||||
|
#undef DEFINE_CASE
|
||||||
|
}
|
||||||
|
|
||||||
GLenum gl_target_to_get_target(GLenum t) noexcept {
|
GLenum gl_target_to_get_target(GLenum t) noexcept {
|
||||||
#define DEFINE_CASE(x,y) case x: return y
|
#define DEFINE_CASE(x,y) case x: return y
|
||||||
switch ( t ) {
|
switch ( t ) {
|
||||||
@@ -1181,31 +1253,6 @@ namespace e2d { namespace opengl
|
|||||||
: gl_program_id(debug);
|
: gl_program_id(debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_texture_id gl_compile_texture(debug& debug, const image& image) {
|
|
||||||
gl_texture_id id = gl_texture_id::create(
|
|
||||||
debug, GL_TEXTURE_2D);
|
|
||||||
if ( id.empty() ) {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
with_gl_bind_texture(debug, id, [&debug, &id, &image]() noexcept {
|
|
||||||
GL_CHECK_CODE(debug, glTexImage2D(
|
|
||||||
id.target(),
|
|
||||||
0,
|
|
||||||
convert_format_to_internal_format(image.format()),
|
|
||||||
math::numeric_cast<GLsizei>(image.size().x),
|
|
||||||
math::numeric_cast<GLsizei>(image.size().y),
|
|
||||||
0,
|
|
||||||
convert_format_to_external_format(image.format()),
|
|
||||||
convert_format_to_external_data_type(image.format()),
|
|
||||||
image.data().data()));
|
|
||||||
#if !defined(GL_ES_VERSION_2_0)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_buffer_id gl_compile_index_buffer(
|
gl_buffer_id gl_compile_index_buffer(
|
||||||
debug& debug, const buffer& indices, index_buffer::usage usage)
|
debug& debug, const buffer& indices, index_buffer::usage usage)
|
||||||
{
|
{
|
||||||
@@ -1241,6 +1288,76 @@ namespace e2d { namespace opengl
|
|||||||
});
|
});
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gl_check_framebuffer(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
GLenum* out_status) noexcept
|
||||||
|
{
|
||||||
|
E2D_ASSERT(!fb.empty());
|
||||||
|
GLenum status = GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
with_gl_bind_framebuffer(debug, fb, [&debug, &fb, &status]() noexcept {
|
||||||
|
GL_CHECK_CODE(debug, gl_check_framebuffer_status(
|
||||||
|
fb.target(), &status));
|
||||||
|
});
|
||||||
|
if ( out_status ) {
|
||||||
|
*out_status = status;
|
||||||
|
}
|
||||||
|
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_attach_texture(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
const gl_texture_id& tex,
|
||||||
|
GLenum attachment) noexcept
|
||||||
|
{
|
||||||
|
E2D_ASSERT(!fb.empty() && !tex.empty());
|
||||||
|
with_gl_bind_framebuffer(debug, fb, [&debug, &fb, &tex, &attachment]() noexcept {
|
||||||
|
GL_CHECK_CODE(debug, glFramebufferTexture2D(
|
||||||
|
fb.target(),
|
||||||
|
attachment,
|
||||||
|
tex.target(),
|
||||||
|
*tex,
|
||||||
|
0));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_attach_renderbuffer(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
const gl_renderbuffer_id& rb,
|
||||||
|
GLenum attachment) noexcept
|
||||||
|
{
|
||||||
|
E2D_ASSERT(!fb.empty() && !rb.empty());
|
||||||
|
with_gl_bind_framebuffer(debug, fb, [&debug, &fb, &rb, &attachment]() noexcept {
|
||||||
|
GL_CHECK_CODE(debug, glFramebufferRenderbuffer(
|
||||||
|
fb.target(),
|
||||||
|
attachment,
|
||||||
|
rb.target(),
|
||||||
|
*rb));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_renderbuffer_id gl_compile_renderbuffer(
|
||||||
|
debug& debug,
|
||||||
|
const v2u& size,
|
||||||
|
GLenum format)
|
||||||
|
{
|
||||||
|
gl_renderbuffer_id id = gl_renderbuffer_id::create(
|
||||||
|
debug, GL_RENDERBUFFER);
|
||||||
|
if ( id.empty() ) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
with_gl_bind_renderbuffer(debug, id, [&debug, &id, &size, &format]() noexcept {
|
||||||
|
GL_CHECK_CODE(debug, glRenderbufferStorage(
|
||||||
|
id.target(),
|
||||||
|
format,
|
||||||
|
math::numeric_cast<GLsizei>(size.x),
|
||||||
|
math::numeric_cast<GLsizei>(size.y)));
|
||||||
|
});
|
||||||
|
return id;
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
namespace e2d { namespace opengl
|
namespace e2d { namespace opengl
|
||||||
|
|||||||
@@ -14,6 +14,91 @@
|
|||||||
# include <OpenGL/gl.h>
|
# include <OpenGL/gl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/
|
||||||
|
// OES/OES_rgb8_rgba8.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GL_RGB8
|
||||||
|
# define GL_RGB8 0x8051
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_RGBA8
|
||||||
|
# define GL_RGBA8 0x8058
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/
|
||||||
|
// OES/OES_depth_texture.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GL_UNSIGNED_INT
|
||||||
|
# define GL_UNSIGNED_INT 0x1405
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_UNSIGNED_SHORT
|
||||||
|
# define GL_UNSIGNED_SHORT 0x1403
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_DEPTH_COMPONENT
|
||||||
|
# define GL_DEPTH_COMPONENT 0x1902
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/
|
||||||
|
// OES/OES_packed_depth_stencil.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GL_DEPTH_STENCIL
|
||||||
|
# define GL_DEPTH_STENCIL 0x84F9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_DEPTH24_STENCIL8
|
||||||
|
# define GL_DEPTH24_STENCIL8 0x88F0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_UNSIGNED_INT_24_8
|
||||||
|
# define GL_UNSIGNED_INT_24_8 0x84FA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/
|
||||||
|
// EXT/EXT_texture_compression_s3tc.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
||||||
|
# define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
|
||||||
|
# define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
|
||||||
|
# define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/
|
||||||
|
// IMG/IMG_texture_compression_pvrtc.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
|
||||||
|
# define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
|
||||||
|
# define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
|
||||||
|
# define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
|
||||||
|
# define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GL_FLUSH_ERRORS(dbg)\
|
#define GL_FLUSH_ERRORS(dbg)\
|
||||||
for ( GLenum err = glGetError(); err != GL_NO_ERROR; err = glGetError() ) {\
|
for ( GLenum err = glGetError(); err != GL_NO_ERROR; err = glGetError() ) {\
|
||||||
E2D_ASSERT_MSG(false, "RENDER: GL_FLUSH_ERRORS()");\
|
E2D_ASSERT_MSG(false, "RENDER: GL_FLUSH_ERRORS()");\
|
||||||
@@ -229,9 +314,15 @@ namespace e2d { namespace opengl
|
|||||||
|
|
||||||
namespace e2d { namespace opengl
|
namespace e2d { namespace opengl
|
||||||
{
|
{
|
||||||
GLint convert_format_to_internal_format(image_data_format idf) noexcept;
|
GLenum convert_image_data_format_to_external_format(image_data_format f) noexcept;
|
||||||
GLenum convert_format_to_external_format(image_data_format idf) noexcept;
|
GLenum convert_image_data_format_to_external_data_type(image_data_format f) noexcept;
|
||||||
GLenum convert_format_to_external_data_type(image_data_format idf) noexcept;
|
|
||||||
|
GLenum convert_pixel_type_to_external_format(pixel_declaration::pixel_type f) noexcept;
|
||||||
|
GLenum convert_pixel_type_to_external_data_type(pixel_declaration::pixel_type f) noexcept;
|
||||||
|
|
||||||
|
GLint convert_pixel_type_to_internal_format(pixel_declaration::pixel_type f) noexcept;
|
||||||
|
GLenum convert_pixel_type_to_compressed_format(pixel_declaration::pixel_type f) noexcept;
|
||||||
|
pixel_declaration convert_image_data_format_to_pixel_declaration(image_data_format f) noexcept;
|
||||||
|
|
||||||
GLenum convert_index_type(index_declaration::index_type it) noexcept;
|
GLenum convert_index_type(index_declaration::index_type it) noexcept;
|
||||||
GLenum convert_attribute_type(vertex_declaration::attribute_type at) noexcept;
|
GLenum convert_attribute_type(vertex_declaration::attribute_type at) noexcept;
|
||||||
@@ -258,6 +349,7 @@ namespace e2d { namespace opengl
|
|||||||
|
|
||||||
const char* glsl_type_to_cstr(GLenum t) noexcept;
|
const char* glsl_type_to_cstr(GLenum t) noexcept;
|
||||||
const char* gl_error_code_to_cstr(GLenum e) noexcept;
|
const char* gl_error_code_to_cstr(GLenum e) noexcept;
|
||||||
|
const char* gl_framebuffer_status_to_cstr(GLenum s) noexcept;
|
||||||
GLenum gl_target_to_get_target(GLenum t) noexcept;
|
GLenum gl_target_to_get_target(GLenum t) noexcept;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@@ -267,9 +359,30 @@ namespace e2d { namespace opengl
|
|||||||
void gl_trace_limits(debug& debug) noexcept;
|
void gl_trace_limits(debug& debug) noexcept;
|
||||||
gl_shader_id gl_compile_shader(debug& debug, const str& source, GLenum type) noexcept;
|
gl_shader_id gl_compile_shader(debug& debug, const str& source, GLenum type) noexcept;
|
||||||
gl_program_id gl_link_program(debug& debug, gl_shader_id vs, gl_shader_id fs) noexcept;
|
gl_program_id gl_link_program(debug& debug, gl_shader_id vs, gl_shader_id fs) noexcept;
|
||||||
gl_texture_id gl_compile_texture(debug& debug, const image& image);
|
|
||||||
gl_buffer_id gl_compile_index_buffer(debug& debug, const buffer& indices, index_buffer::usage usage);
|
gl_buffer_id gl_compile_index_buffer(debug& debug, const buffer& indices, index_buffer::usage usage);
|
||||||
gl_buffer_id gl_compile_vertex_buffer(debug& debug, const buffer& vertices, vertex_buffer::usage usage);
|
gl_buffer_id gl_compile_vertex_buffer(debug& debug, const buffer& vertices, vertex_buffer::usage usage);
|
||||||
|
|
||||||
|
bool gl_check_framebuffer(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
GLenum* out_status) noexcept;
|
||||||
|
|
||||||
|
void gl_attach_texture(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
const gl_texture_id& tex,
|
||||||
|
GLenum attachment) noexcept;
|
||||||
|
|
||||||
|
void gl_attach_renderbuffer(
|
||||||
|
debug& debug,
|
||||||
|
const gl_framebuffer_id& fb,
|
||||||
|
const gl_renderbuffer_id& rb,
|
||||||
|
GLenum attachment) noexcept;
|
||||||
|
|
||||||
|
gl_renderbuffer_id gl_compile_renderbuffer(
|
||||||
|
debug& debug,
|
||||||
|
const v2u& size,
|
||||||
|
GLenum format);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
namespace e2d { namespace opengl
|
namespace e2d { namespace opengl
|
||||||
|
|||||||
@@ -76,11 +76,11 @@ namespace e2d
|
|||||||
debug& debug,
|
debug& debug,
|
||||||
gl_texture_id id,
|
gl_texture_id id,
|
||||||
const v2u& size,
|
const v2u& size,
|
||||||
image_data_format format)
|
const pixel_declaration& decl)
|
||||||
: debug_(debug)
|
: debug_(debug)
|
||||||
, id_(std::move(id))
|
, id_(std::move(id))
|
||||||
, size_(size)
|
, size_(size)
|
||||||
, format_(format){
|
, decl_(decl){
|
||||||
E2D_ASSERT(!id_.empty());
|
E2D_ASSERT(!id_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ namespace e2d
|
|||||||
return size_;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
image_data_format texture::internal_state::format() const noexcept {
|
const pixel_declaration& texture::internal_state::decl() const noexcept {
|
||||||
return format_;
|
return decl_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -164,13 +164,63 @@ namespace e2d
|
|||||||
return decl_;
|
return decl_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// render_target::internal_state
|
||||||
|
//
|
||||||
|
render_target::internal_state::internal_state(
|
||||||
|
debug& debug,
|
||||||
|
opengl::gl_framebuffer_id id,
|
||||||
|
const v2u& size,
|
||||||
|
texture_ptr color,
|
||||||
|
texture_ptr depth,
|
||||||
|
opengl::gl_renderbuffer_id color_rb,
|
||||||
|
opengl::gl_renderbuffer_id depth_rb)
|
||||||
|
: debug_(debug)
|
||||||
|
, id_(std::move(id))
|
||||||
|
, size_(size)
|
||||||
|
, color_(std::move(color))
|
||||||
|
, depth_(std::move(depth))
|
||||||
|
, color_rb_(std::move(color_rb))
|
||||||
|
, depth_rb_(std::move(depth_rb)){
|
||||||
|
E2D_ASSERT(!id_.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
debug& render_target::internal_state::dbg() const noexcept {
|
||||||
|
return debug_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gl_framebuffer_id& render_target::internal_state::id() const noexcept {
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const v2u& render_target::internal_state::size() const noexcept {
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::internal_state::color() const noexcept {
|
||||||
|
return color_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const texture_ptr& render_target::internal_state::depth() const noexcept {
|
||||||
|
return depth_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gl_renderbuffer_id& render_target::internal_state::color_rb() const noexcept {
|
||||||
|
return color_rb_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gl_renderbuffer_id& render_target::internal_state::depth_rb() const noexcept {
|
||||||
|
return depth_rb_;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// render::internal_state
|
// render::internal_state
|
||||||
//
|
//
|
||||||
|
|
||||||
render::internal_state::internal_state(debug& debug, window& window)
|
render::internal_state::internal_state(debug& debug, window& window)
|
||||||
: debug_(debug)
|
: debug_(debug)
|
||||||
, window_(window) {}
|
, window_(window)
|
||||||
|
, default_fb_(gl_framebuffer_id::current(debug, GL_FRAMEBUFFER)) {}
|
||||||
|
|
||||||
debug& render::internal_state::dbg() const noexcept {
|
debug& render::internal_state::dbg() const noexcept {
|
||||||
return debug_;
|
return debug_;
|
||||||
@@ -180,6 +230,10 @@ namespace e2d
|
|||||||
return window_;
|
return window_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const render_target_ptr& render::internal_state::render_target() const noexcept {
|
||||||
|
return render_target_;
|
||||||
|
}
|
||||||
|
|
||||||
render::internal_state& render::internal_state::set_states(const state_block& rs) noexcept {
|
render::internal_state& render::internal_state::set_states(const state_block& rs) noexcept {
|
||||||
set_depth_state(rs.depth());
|
set_depth_state(rs.depth());
|
||||||
set_stencil_state(rs.stencil());
|
set_stencil_state(rs.stencil());
|
||||||
@@ -258,5 +312,19 @@ namespace e2d
|
|||||||
GL_CHECK_CODE(debug_, enable_or_disable(GL_STENCIL_TEST, cs.stencil_test()));
|
GL_CHECK_CODE(debug_, enable_or_disable(GL_STENCIL_TEST, cs.stencil_test()));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render::internal_state& render::internal_state::set_render_target(const render_target_ptr& rt) noexcept {
|
||||||
|
if ( rt ) {
|
||||||
|
GL_CHECK_CODE(debug_, glBindFramebuffer(
|
||||||
|
rt->state().id().target(),
|
||||||
|
*rt->state().id()));
|
||||||
|
} else {
|
||||||
|
GL_CHECK_CODE(debug_, glBindFramebuffer(
|
||||||
|
default_fb_.target(),
|
||||||
|
*default_fb_));
|
||||||
|
}
|
||||||
|
render_target_ = rt;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -64,18 +64,18 @@ namespace e2d
|
|||||||
debug& debug,
|
debug& debug,
|
||||||
opengl::gl_texture_id id,
|
opengl::gl_texture_id id,
|
||||||
const v2u& size,
|
const v2u& size,
|
||||||
image_data_format format);
|
const pixel_declaration& decl);
|
||||||
~internal_state() noexcept = default;
|
~internal_state() noexcept = default;
|
||||||
public:
|
public:
|
||||||
debug& dbg() const noexcept;
|
debug& dbg() const noexcept;
|
||||||
const opengl::gl_texture_id& id() const noexcept;
|
const opengl::gl_texture_id& id() const noexcept;
|
||||||
const v2u& size() const noexcept;
|
const v2u& size() const noexcept;
|
||||||
image_data_format format() const noexcept;
|
const pixel_declaration& decl() const noexcept;
|
||||||
private:
|
private:
|
||||||
debug& debug_;
|
debug& debug_;
|
||||||
opengl::gl_texture_id id_;
|
opengl::gl_texture_id id_;
|
||||||
v2u size_;
|
v2u size_;
|
||||||
image_data_format format_;
|
pixel_declaration decl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -126,6 +126,39 @@ namespace e2d
|
|||||||
vertex_declaration decl_;
|
vertex_declaration decl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// render_target::internal_state
|
||||||
|
//
|
||||||
|
|
||||||
|
class render_target::internal_state final : private e2d::noncopyable {
|
||||||
|
public:
|
||||||
|
internal_state(
|
||||||
|
debug& debug,
|
||||||
|
opengl::gl_framebuffer_id id,
|
||||||
|
const v2u& size,
|
||||||
|
texture_ptr color,
|
||||||
|
texture_ptr depth,
|
||||||
|
opengl::gl_renderbuffer_id color_rb,
|
||||||
|
opengl::gl_renderbuffer_id depth_rb);
|
||||||
|
~internal_state() noexcept = default;
|
||||||
|
public:
|
||||||
|
debug& dbg() const noexcept;
|
||||||
|
const opengl::gl_framebuffer_id& id() const noexcept;
|
||||||
|
const v2u& size() const noexcept;
|
||||||
|
const texture_ptr& color() const noexcept;
|
||||||
|
const texture_ptr& depth() const noexcept;
|
||||||
|
const opengl::gl_renderbuffer_id& color_rb() const noexcept;
|
||||||
|
const opengl::gl_renderbuffer_id& depth_rb() const noexcept;
|
||||||
|
private:
|
||||||
|
debug& debug_;
|
||||||
|
opengl::gl_framebuffer_id id_;
|
||||||
|
v2u size_;
|
||||||
|
texture_ptr color_;
|
||||||
|
texture_ptr depth_;
|
||||||
|
opengl::gl_renderbuffer_id color_rb_;
|
||||||
|
opengl::gl_renderbuffer_id depth_rb_;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// render::internal_state
|
// render::internal_state
|
||||||
//
|
//
|
||||||
@@ -139,6 +172,7 @@ namespace e2d
|
|||||||
public:
|
public:
|
||||||
debug& dbg() const noexcept;
|
debug& dbg() const noexcept;
|
||||||
window& wnd() const noexcept;
|
window& wnd() const noexcept;
|
||||||
|
const render_target_ptr& render_target() const noexcept;
|
||||||
public:
|
public:
|
||||||
internal_state& set_states(const state_block& rs) noexcept;
|
internal_state& set_states(const state_block& rs) noexcept;
|
||||||
internal_state& set_depth_state(const depth_state& ds) noexcept;
|
internal_state& set_depth_state(const depth_state& ds) noexcept;
|
||||||
@@ -146,9 +180,12 @@ namespace e2d
|
|||||||
internal_state& set_culling_state(const culling_state& cs) noexcept;
|
internal_state& set_culling_state(const culling_state& cs) noexcept;
|
||||||
internal_state& set_blending_state(const blending_state& bs) noexcept;
|
internal_state& set_blending_state(const blending_state& bs) noexcept;
|
||||||
internal_state& set_capabilities_state(const capabilities_state& cs) noexcept;
|
internal_state& set_capabilities_state(const capabilities_state& cs) noexcept;
|
||||||
|
internal_state& set_render_target(const render_target_ptr& rt) noexcept;
|
||||||
private:
|
private:
|
||||||
debug& debug_;
|
debug& debug_;
|
||||||
window& window_;
|
window& window_;
|
||||||
|
render_target_ptr render_target_;
|
||||||
|
opengl::gl_framebuffer_id default_fb_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,16 +72,16 @@ TEST_CASE("render"){
|
|||||||
}
|
}
|
||||||
SECTION("index_declaration"){
|
SECTION("index_declaration"){
|
||||||
index_declaration id;
|
index_declaration id;
|
||||||
REQUIRE(id.index().type == index_declaration::index_type::unsigned_short);
|
REQUIRE(id.type() == index_declaration::index_type::unsigned_short);
|
||||||
REQUIRE(id.index_size() == 2);
|
REQUIRE(id.bytes_per_index() == 2);
|
||||||
|
|
||||||
index_declaration id2(index_declaration::index_type::unsigned_short);
|
index_declaration id2(index_declaration::index_type::unsigned_short);
|
||||||
REQUIRE(id2.index().type == index_declaration::index_type::unsigned_short);
|
REQUIRE(id2.type() == index_declaration::index_type::unsigned_short);
|
||||||
REQUIRE(id2.index_size() == 2);
|
REQUIRE(id2.bytes_per_index() == 2);
|
||||||
|
|
||||||
index_declaration id3(index_declaration::index_type::unsigned_byte);
|
index_declaration id3(index_declaration::index_type::unsigned_byte);
|
||||||
REQUIRE(id3.index().type == index_declaration::index_type::unsigned_byte);
|
REQUIRE(id3.type() == index_declaration::index_type::unsigned_byte);
|
||||||
REQUIRE(id3.index_size() == 1);
|
REQUIRE(id3.bytes_per_index() == 1);
|
||||||
|
|
||||||
REQUIRE(id == id2);
|
REQUIRE(id == id2);
|
||||||
REQUIRE_FALSE(id == id3);
|
REQUIRE_FALSE(id == id3);
|
||||||
@@ -98,11 +98,11 @@ TEST_CASE("render"){
|
|||||||
SECTION("vertex_declaration"){
|
SECTION("vertex_declaration"){
|
||||||
vertex_declaration vd;
|
vertex_declaration vd;
|
||||||
REQUIRE(vd.attribute_count() == 0);
|
REQUIRE(vd.attribute_count() == 0);
|
||||||
REQUIRE(vd.vertex_size() == 0);
|
REQUIRE(vd.bytes_per_vertex() == 0);
|
||||||
|
|
||||||
REQUIRE(&vd == &vd.add_attribute<v2f>("hello"));
|
REQUIRE(&vd == &vd.add_attribute<v2f>("hello"));
|
||||||
REQUIRE(vd.attribute_count() == 1);
|
REQUIRE(vd.attribute_count() == 1);
|
||||||
REQUIRE(vd.vertex_size() == 8);
|
REQUIRE(vd.bytes_per_vertex() == 8);
|
||||||
|
|
||||||
vertex_declaration::attribute_info ai = vd.attribute(0);
|
vertex_declaration::attribute_info ai = vd.attribute(0);
|
||||||
REQUIRE(ai.name == make_hash("hello"));
|
REQUIRE(ai.name == make_hash("hello"));
|
||||||
@@ -112,11 +112,11 @@ TEST_CASE("render"){
|
|||||||
REQUIRE_FALSE(ai.normalized);
|
REQUIRE_FALSE(ai.normalized);
|
||||||
|
|
||||||
REQUIRE(&vd == &vd.skip_bytes(4));
|
REQUIRE(&vd == &vd.skip_bytes(4));
|
||||||
REQUIRE(vd.vertex_size() == 12);
|
REQUIRE(vd.bytes_per_vertex() == 12);
|
||||||
|
|
||||||
REQUIRE(&vd == &vd.add_attribute<u16>("world").normalized());
|
REQUIRE(&vd == &vd.add_attribute<u16>("world").normalized());
|
||||||
REQUIRE(vd.attribute_count() == 2);
|
REQUIRE(vd.attribute_count() == 2);
|
||||||
REQUIRE(vd.vertex_size() == 14);
|
REQUIRE(vd.bytes_per_vertex() == 14);
|
||||||
|
|
||||||
vertex_declaration::attribute_info ai2 = vd.attribute(1);
|
vertex_declaration::attribute_info ai2 = vd.attribute(1);
|
||||||
REQUIRE(ai2.name == make_hash("world"));
|
REQUIRE(ai2.name == make_hash("world"));
|
||||||
@@ -138,9 +138,9 @@ TEST_CASE("render"){
|
|||||||
REQUIRE_FALSE(vd == vd3);
|
REQUIRE_FALSE(vd == vd3);
|
||||||
REQUIRE(vd != vd3);
|
REQUIRE(vd != vd3);
|
||||||
|
|
||||||
REQUIRE(vd3.vertex_size() == 16);
|
REQUIRE(vd3.bytes_per_vertex() == 16);
|
||||||
vd3.skip_bytes(4);
|
vd3.skip_bytes(4);
|
||||||
REQUIRE(vd3.vertex_size() == 20);
|
REQUIRE(vd3.bytes_per_vertex() == 20);
|
||||||
|
|
||||||
vertex_declaration vd4 = vd2;
|
vertex_declaration vd4 = vd2;
|
||||||
REQUIRE(vd4 == vd);
|
REQUIRE(vd4 == vd);
|
||||||
|
|||||||
Reference in New Issue
Block a user