add GL/Texture
This commit is contained in:
parent
58d39739e8
commit
4b79c5e4df
@ -52,8 +52,7 @@ struct Obj_BufferMeta final {
|
||||
|
||||
const GLenum type;
|
||||
|
||||
size_t size = 0;
|
||||
uint8_t* ptr = nullptr; // address returned by glMapBuffer or nullptr
|
||||
size_t size = 0;
|
||||
|
||||
static GLuint Gen() noexcept {
|
||||
GLuint id;
|
||||
@ -70,9 +69,14 @@ using BufferFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Buffer>>
|
||||
|
||||
struct Obj_TextureMeta final {
|
||||
public:
|
||||
GLenum type;
|
||||
GLenum format;
|
||||
uint32_t w, h, d;
|
||||
Obj_TextureMeta() = delete;
|
||||
Obj_TextureMeta(GLenum t) noexcept : type(t) {
|
||||
}
|
||||
|
||||
const GLenum type;
|
||||
|
||||
GLint format = 0;
|
||||
uint32_t w = 0, h = 0, d = 0;
|
||||
|
||||
static GLuint Gen() noexcept {
|
||||
GLuint id;
|
||||
|
@ -31,4 +31,12 @@ struct EnumSerializer {
|
||||
}
|
||||
};
|
||||
|
||||
#define NF7_YAS_DEFINE_ENUM_SERIALIZER(T) \
|
||||
template <size_t F> \
|
||||
struct serializer< \
|
||||
yas::detail::type_prop::is_enum, \
|
||||
yas::detail::ser_case::use_internal_serializer, \
|
||||
F, T> : nf7::EnumSerializer<T> { \
|
||||
}
|
||||
|
||||
} // namespace nf7
|
||||
|
239
file/gl_obj.cc
239
file/gl_obj.cc
@ -1,3 +1,4 @@
|
||||
#include <cinttypes>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
@ -352,26 +353,236 @@ struct ObjBase<Buffer>::TypeInfo final {
|
||||
static inline const nf7::GenericTypeInfo<ObjBase<Buffer>> kType = {"GL/Buffer", {"nf7::DirItem"}};
|
||||
};
|
||||
|
||||
|
||||
struct Texture {
|
||||
public:
|
||||
static void UpdateTypeTooltip() noexcept {
|
||||
ImGui::TextUnformatted("OpenGL texture");
|
||||
}
|
||||
|
||||
static inline const std::vector<std::string> kInputs = {
|
||||
"upload",
|
||||
};
|
||||
static inline const std::vector<std::string> kOutputs = {
|
||||
};
|
||||
|
||||
using Product = nf7::gl::Texture;
|
||||
|
||||
enum class Type {
|
||||
Tex2D = 0x20,
|
||||
Rect = 0x21,
|
||||
};
|
||||
enum class Format {
|
||||
U8 = 0x01,
|
||||
F32 = 0x14,
|
||||
};
|
||||
enum class Comp : uint8_t {
|
||||
R = 1,
|
||||
RG = 2,
|
||||
RGB = 3,
|
||||
RGBA = 4,
|
||||
};
|
||||
|
||||
Texture() = default;
|
||||
Texture(const Texture&) = default;
|
||||
Texture(Texture&&) = default;
|
||||
Texture& operator=(const Texture&) = default;
|
||||
Texture& operator=(Texture&&) = default;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(type_, format_);
|
||||
}
|
||||
|
||||
std::string Stringify() noexcept {
|
||||
YAML::Emitter st;
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "type";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(type_)};
|
||||
st << YAML::Key << "format";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(format_)};
|
||||
st << YAML::Key << "comp";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(comp_)};
|
||||
st << YAML::EndMap;
|
||||
return std::string {st.c_str(), st.size()};
|
||||
}
|
||||
|
||||
void Parse(const std::string& v)
|
||||
try {
|
||||
const auto yaml = YAML::Load(v);
|
||||
|
||||
const auto new_type = magic_enum::
|
||||
enum_cast<Type>(yaml["type"].as<std::string>()).value();
|
||||
const auto new_format = magic_enum::
|
||||
enum_cast<Format>(yaml["format"].as<std::string>()).value();
|
||||
const auto new_comp = magic_enum::
|
||||
enum_cast<Comp>(yaml["comp"].as<std::string>()).value();
|
||||
|
||||
type_ = new_type;
|
||||
format_ = new_format;
|
||||
comp_ = new_comp;
|
||||
} catch (std::bad_optional_access&) {
|
||||
throw nf7::Exception {"unknown enum"};
|
||||
} catch (YAML::Exception& e) {
|
||||
throw nf7::Exception {std::string {"YAML error: "}+e.what()};
|
||||
}
|
||||
|
||||
nf7::Future<std::shared_ptr<Product>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx, nf7::Env::Watcher&) noexcept {
|
||||
nf7::Future<std::shared_ptr<Product>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [ctx, pro, t = type_]() mutable {
|
||||
pro.Return(std::make_shared<Product>(ctx, GLuint {0}, FromType(t)));
|
||||
});
|
||||
return pro.future();
|
||||
}
|
||||
|
||||
bool Handle(const std::shared_ptr<nf7::Node::Lambda>& handler,
|
||||
const nf7::Mutex::Resource<std::shared_ptr<Product>>& res,
|
||||
const nf7::Node::Lambda::Msg& in) {
|
||||
if (in.name == "upload") {
|
||||
const auto& v = in.value;
|
||||
|
||||
const auto vec = v.tuple("vec").vector();
|
||||
|
||||
auto& tex = **res;
|
||||
auto& m = tex.meta();
|
||||
|
||||
uint32_t w = 0, h = 0, d = 0;
|
||||
switch (type_) {
|
||||
case Type::Tex2D:
|
||||
case Type::Rect:
|
||||
w = v.tuple("w").integer<uint32_t>();
|
||||
h = v.tuple("h").integer<uint32_t>();
|
||||
if (w == 0 || h == 0) return false;
|
||||
break;
|
||||
}
|
||||
m.w = w, m.h = h, m.d = d;
|
||||
m.format = ToInternalFormat(format_, comp_);
|
||||
|
||||
const auto vecsz =
|
||||
w*h* // number of texels
|
||||
magic_enum::enum_integer(comp_)* // number of color components
|
||||
(magic_enum::enum_integer(format_) & 0xF); // size of a component
|
||||
if (vec->size() < static_cast<size_t>(vecsz)) {
|
||||
throw nf7::Exception {"vector is too small"};
|
||||
}
|
||||
|
||||
const auto type = ToCompType(format_);
|
||||
const auto fmt = ToFormat(comp_);
|
||||
handler->env().ExecGL(handler, [handler, res, &tex, &m, type, fmt, vec]() {
|
||||
glBindTexture(m.type, tex.id());
|
||||
switch (m.type) {
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_RECTANGLE:
|
||||
glTexImage2D(m.type, 0, m.format,
|
||||
static_cast<GLsizei>(m.w),
|
||||
static_cast<GLsizei>(m.h),
|
||||
0, fmt, type, vec->data());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
glTexParameteri(m.type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(m.type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(m.type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(m.type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(m.type, 0);
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
throw nf7::Exception {"unknown input: "+in.name};
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTooltip(const std::shared_ptr<Product>& prod) noexcept {
|
||||
const auto t = magic_enum::enum_name(type_);
|
||||
ImGui::Text("type : %.*s", static_cast<int>(t.size()), t.data());
|
||||
|
||||
const auto f = magic_enum::enum_name(format_);
|
||||
ImGui::Text("format: %.*s", static_cast<int>(f.size()), f.data());
|
||||
|
||||
const auto c = magic_enum::enum_name(comp_);
|
||||
ImGui::Text("comp : %.*s (%" PRIu8 " values)",
|
||||
static_cast<int>(c.size()), c.data(),
|
||||
magic_enum::enum_integer(comp_));
|
||||
|
||||
ImGui::Spacing();
|
||||
if (prod) {
|
||||
const auto id = static_cast<intptr_t>(prod->id());
|
||||
const auto& m = prod->meta();
|
||||
ImGui::Text(" id: %" PRIiPTR, id);
|
||||
ImGui::Text("size: %" PRIu32 " x %" PRIu32 " x %" PRIu32, m.w, m.h, m.d);
|
||||
|
||||
if (m.type == GL_TEXTURE_2D) {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted("preview:");
|
||||
ImGui::Image(reinterpret_cast<void*>(id),
|
||||
ImVec2 {static_cast<float>(m.w), static_cast<float>(m.h)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Type type_ = Type::Rect;
|
||||
Format format_ = Format::U8;
|
||||
Comp comp_ = Comp::RGBA;
|
||||
|
||||
static GLenum FromType(Type t) {
|
||||
return
|
||||
t == Type::Tex2D? GL_TEXTURE_2D:
|
||||
t == Type::Rect? GL_TEXTURE_RECTANGLE:
|
||||
throw 0;
|
||||
}
|
||||
static GLenum ToCompType(Format c) {
|
||||
return
|
||||
c == Format::U8? GL_UNSIGNED_BYTE:
|
||||
c == Format::F32? GL_FLOAT:
|
||||
throw 0;
|
||||
}
|
||||
static GLenum ToFormat(Comp f) {
|
||||
return
|
||||
f == Comp::R? GL_RED:
|
||||
f == Comp::RG? GL_RG:
|
||||
f == Comp::RGB? GL_RGB:
|
||||
f == Comp::RGBA? GL_RGBA:
|
||||
throw 0;
|
||||
}
|
||||
static GLint ToInternalFormat(Format f, Comp c) {
|
||||
switch (f) {
|
||||
case Format::U8:
|
||||
return
|
||||
c == Comp::R? GL_R8:
|
||||
c == Comp::RG? GL_RG8:
|
||||
c == Comp::RGB? GL_RGB8:
|
||||
c == Comp::RGBA? GL_RGBA8:
|
||||
throw 0;
|
||||
case Format::F32:
|
||||
return
|
||||
c == Comp::R? GL_R32F:
|
||||
c == Comp::RG? GL_RG32F:
|
||||
c == Comp::RGB? GL_RGB32F:
|
||||
c == Comp::RGBA? GL_RGBA32F:
|
||||
throw 0;
|
||||
}
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct ObjBase<Texture>::TypeInfo final {
|
||||
static inline const nf7::GenericTypeInfo<ObjBase<Texture>> kType = {"GL/Texture", {"nf7::DirItem"}};
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nf7
|
||||
|
||||
|
||||
namespace yas::detail {
|
||||
|
||||
template <size_t F>
|
||||
struct serializer<
|
||||
yas::detail::type_prop::is_enum,
|
||||
yas::detail::ser_case::use_internal_serializer,
|
||||
F, nf7::Buffer::Type> :
|
||||
nf7::EnumSerializer<nf7::Buffer::Type> {
|
||||
};
|
||||
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::Buffer::Type);
|
||||
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::Buffer::Usage);
|
||||
|
||||
template <size_t F>
|
||||
struct serializer<
|
||||
yas::detail::type_prop::is_enum,
|
||||
yas::detail::ser_case::use_internal_serializer,
|
||||
F, nf7::Buffer::Usage> :
|
||||
nf7::EnumSerializer<nf7::Buffer::Usage> {
|
||||
};
|
||||
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::Texture::Type);
|
||||
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::Texture::Format);
|
||||
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::Texture::Comp);
|
||||
|
||||
} // namespace yas::detail
|
||||
|
Loading…
x
Reference in New Issue
Block a user