support drawing with depth test in GL/Program

This commit is contained in:
falsycat 2022-10-29 11:56:55 +09:00
parent fa1a29c325
commit 0cb8468a58
4 changed files with 85 additions and 33 deletions

View File

@ -182,6 +182,31 @@ inline bool HasStencil(InternalFormat fmt) noexcept {
}
enum class TestFunc {
Never,
Always,
Equal,
NotEqual,
Less,
LessOrEqual,
Greater,
GreaterOrEqual,
};
template <>
struct EnumMeta<TestFunc> {
static inline const std::unordered_map<TestFunc, GLenum> glmap = {
{TestFunc::Never, GL_NEVER},
{TestFunc::Always, GL_ALWAYS},
{TestFunc::Equal, GL_EQUAL},
{TestFunc::NotEqual, GL_NOTEQUAL},
{TestFunc::Less, GL_LESS},
{TestFunc::LessOrEqual, GL_LEQUAL},
{TestFunc::Greater, GL_GREATER},
{TestFunc::GreaterOrEqual, GL_GEQUAL},
};
};
enum class BufferTarget {
Array,
ElementArray,
@ -280,31 +305,6 @@ struct EnumMeta<DrawMode> {
};
};
enum class FramebufferSlot {
Color0,
Color1,
Color2,
Color3,
Color4,
Color5,
Color6,
Color7,
};
template <>
struct EnumMeta<FramebufferSlot> {
static inline const std::unordered_map<FramebufferSlot, GLenum> glmap = {
{FramebufferSlot::Color0, GL_COLOR_ATTACHMENT0},
{FramebufferSlot::Color1, GL_COLOR_ATTACHMENT0+1},
{FramebufferSlot::Color2, GL_COLOR_ATTACHMENT0+2},
{FramebufferSlot::Color3, GL_COLOR_ATTACHMENT0+3},
{FramebufferSlot::Color4, GL_COLOR_ATTACHMENT0+4},
{FramebufferSlot::Color5, GL_COLOR_ATTACHMENT0+5},
{FramebufferSlot::Color6, GL_COLOR_ATTACHMENT0+6},
{FramebufferSlot::Color7, GL_COLOR_ATTACHMENT0+7},
};
};
} // namespace nf7::gl
@ -312,6 +312,8 @@ namespace yas::detail {
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::NumericType);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::ColorComp);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::InternalFormat);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::TestFunc);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::BufferTarget);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::BufferUsage);
@ -322,6 +324,4 @@ NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::ShaderType);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::DrawMode);
NF7_YAS_DEFINE_ENUM_SERIALIZER(nf7::gl::FramebufferSlot);
} // namespace yas::detail

View File

@ -186,6 +186,19 @@ nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Obj_ProgramMeta::Create(
return pro.future();
}
void Obj_ProgramMeta::ApplyState() const noexcept {
if (depth) {
glEnable(GL_DEPTH_TEST);
glDepthRange(depth->near, depth->far);
glDepthFunc(gl::ToEnum(depth->func));
}
}
void Obj_ProgramMeta::RevertState() const noexcept {
if (depth) {
glDisable(GL_DEPTH_TEST);
}
}
nf7::Future<std::shared_ptr<Obj<Obj_VertexArrayMeta>>> Obj_VertexArrayMeta::Create(
const std::shared_ptr<nf7::Context>& ctx) const noexcept

View File

@ -113,6 +113,13 @@ struct Obj_ProgramMeta final {
public:
struct Param { };
struct Depth {
float near = 0, far = 1;
gl::TestFunc func = gl::TestFunc::Less;
void serialize(auto& ar) { ar(near, far, func); }
};
static void Delete(GLuint id) noexcept {
glDeleteProgram(id);
}
@ -121,6 +128,11 @@ struct Obj_ProgramMeta final {
nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Create(
const std::shared_ptr<nf7::Context>& ctx,
const std::vector<nf7::File::Id>& shaders) noexcept;
void ApplyState() const noexcept;
void RevertState() const noexcept;
std::optional<Depth> depth;
};
using Program = Obj<Obj_ProgramMeta>;
using ProgramFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Program>>>;

View File

@ -730,7 +730,7 @@ struct Program {
Program& operator=(Program&&) = default;
void serialize(auto& ar) {
ar(shaders_);
ar(shaders_, depth_);
}
std::string Stringify() noexcept {
@ -742,6 +742,18 @@ struct Program {
st << shader.Stringify();
}
st << YAML::EndSeq;
if (depth_) {
st << YAML::Key << "depth";
st << YAML::BeginMap;
st << YAML::Key << "near";
st << YAML::Value << depth_->near;
st << YAML::Key << "far";
st << YAML::Value << depth_->far;
st << YAML::Key << "func";
st << YAML::Value << std::string {magic_enum::enum_name(depth_->func)};
st << YAML::EndMap;
}
st << YAML::EndMap;
return std::string {st.c_str(), st.size()};
}
@ -749,16 +761,25 @@ struct Program {
try {
const auto yaml = YAML::Load(v);
std::vector<nf7::File::Path> shaders;
Program ret;
for (const auto& shader : yaml["shaders"]) {
shaders.push_back(
ret.shaders_.push_back(
nf7::File::Path::Parse(shader.as<std::string>()));
}
if (shaders.size() == 0) {
if (ret.shaders_.size() == 0) {
throw nf7::Exception {"no shader is attached"};
}
shaders_ = std::move(shaders);
if (const auto& yaml_depth = yaml["depth"]) {
depth_.emplace(Product::Meta::Depth {
.near = yaml_depth["near"].as<float>(),
.far = yaml_depth["far"].as<float>(),
.func = magic_enum::enum_cast<gl::TestFunc>(
yaml_depth["func"].as<std::string>()).value(),
});
}
*this = std::move(ret);
} catch (YAML::Exception& e) {
throw nf7::Exception {std::string {"YAML error: "}+e.what()};
}
@ -802,6 +823,9 @@ struct Program {
throw nf7::Exception {"negative size viewport"};
}
gl::Program::Meta config = (**p.obj).meta();
// TODO: override configurations
// this will be triggered when all preparation done
nf7::AggregatePromise apro {p.la};
@ -903,12 +927,14 @@ struct Program {
}
// draw
config.ApplyState();
if (vao->meta().index) {
const auto numtype = gl::ToEnum(vao->meta().index->numtype);
glDrawElementsInstanced(mode, count, numtype, nullptr, inst);
} else {
glDrawArraysInstanced(mode, 0, count, inst);
}
config.RevertState();
const auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// unbind all
@ -934,7 +960,8 @@ struct Program {
}
private:
std::vector<nf7::File::Path> shaders_;
std::vector<nf7::File::Path> shaders_;
std::optional<Product::Meta::Depth> depth_ = {{}};
static void SetUniform(GLuint prog, const char* name, const nf7::Value& v) {