712 lines
21 KiB
C++
712 lines
21 KiB
C++
#include "pch.h"
|
|
#include "log.h"
|
|
#include "texture.h"
|
|
#include "util.h"
|
|
#include "app.h"
|
|
#include "renderer_gl/opengl_capabilities.h"
|
|
|
|
#include <cstdint>
|
|
|
|
namespace {
|
|
|
|
void gen_opengl_textures(std::uint32_t count, std::uint32_t* ids) noexcept
|
|
{
|
|
glGenTextures(static_cast<GLsizei>(count), reinterpret_cast<GLuint*>(ids));
|
|
}
|
|
|
|
void delete_opengl_textures(std::uint32_t count, const std::uint32_t* ids) noexcept
|
|
{
|
|
glDeleteTextures(static_cast<GLsizei>(count), reinterpret_cast<const GLuint*>(ids));
|
|
}
|
|
|
|
void bind_opengl_texture(std::uint32_t target, std::uint32_t texture) noexcept
|
|
{
|
|
glBindTexture(static_cast<GLenum>(target), static_cast<GLuint>(texture));
|
|
}
|
|
|
|
void upload_opengl_texture_2d(
|
|
std::uint32_t target,
|
|
std::int32_t level,
|
|
std::int32_t internal_format,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::int32_t border,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
const void* data) noexcept
|
|
{
|
|
glTexImage2D(
|
|
static_cast<GLenum>(target),
|
|
static_cast<GLint>(level),
|
|
static_cast<GLint>(internal_format),
|
|
static_cast<GLsizei>(width),
|
|
static_cast<GLsizei>(height),
|
|
static_cast<GLint>(border),
|
|
static_cast<GLenum>(pixel_format),
|
|
static_cast<GLenum>(component_type),
|
|
data);
|
|
}
|
|
|
|
void update_opengl_texture_2d_region(
|
|
std::uint32_t target,
|
|
std::int32_t level,
|
|
std::int32_t x,
|
|
std::int32_t y,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
const void* data) noexcept
|
|
{
|
|
glTexSubImage2D(
|
|
static_cast<GLenum>(target),
|
|
static_cast<GLint>(level),
|
|
static_cast<GLint>(x),
|
|
static_cast<GLint>(y),
|
|
static_cast<GLsizei>(width),
|
|
static_cast<GLsizei>(height),
|
|
static_cast<GLenum>(pixel_format),
|
|
static_cast<GLenum>(component_type),
|
|
data);
|
|
}
|
|
|
|
void generate_opengl_mipmap(std::uint32_t target) noexcept
|
|
{
|
|
glGenerateMipmap(static_cast<GLenum>(target));
|
|
}
|
|
|
|
void gen_opengl_framebuffers(std::uint32_t count, std::uint32_t* ids) noexcept
|
|
{
|
|
glGenFramebuffers(static_cast<GLsizei>(count), reinterpret_cast<GLuint*>(ids));
|
|
}
|
|
|
|
void delete_opengl_framebuffers(std::uint32_t count, const std::uint32_t* ids) noexcept
|
|
{
|
|
glDeleteFramebuffers(static_cast<GLsizei>(count), reinterpret_cast<const GLuint*>(ids));
|
|
}
|
|
|
|
void query_opengl_integer(std::uint32_t name, std::int32_t* value) noexcept
|
|
{
|
|
glGetIntegerv(static_cast<GLenum>(name), reinterpret_cast<GLint*>(value));
|
|
}
|
|
|
|
void bind_opengl_framebuffer(std::uint32_t target, std::uint32_t framebuffer) noexcept
|
|
{
|
|
glBindFramebuffer(static_cast<GLenum>(target), static_cast<GLuint>(framebuffer));
|
|
}
|
|
|
|
void attach_opengl_framebuffer_texture_2d(
|
|
std::uint32_t target,
|
|
std::uint32_t attachment,
|
|
std::uint32_t texture_target,
|
|
std::uint32_t texture,
|
|
std::int32_t level) noexcept
|
|
{
|
|
glFramebufferTexture2D(
|
|
static_cast<GLenum>(target),
|
|
static_cast<GLenum>(attachment),
|
|
static_cast<GLenum>(texture_target),
|
|
static_cast<GLuint>(texture),
|
|
static_cast<GLint>(level));
|
|
}
|
|
|
|
std::uint32_t check_opengl_framebuffer_status(std::uint32_t target) noexcept
|
|
{
|
|
return static_cast<std::uint32_t>(glCheckFramebufferStatus(static_cast<GLenum>(target)));
|
|
}
|
|
|
|
void read_opengl_pixels(
|
|
std::int32_t x,
|
|
std::int32_t y,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
void* pixels) noexcept
|
|
{
|
|
glReadPixels(
|
|
static_cast<GLint>(x),
|
|
static_cast<GLint>(y),
|
|
static_cast<GLsizei>(width),
|
|
static_cast<GLsizei>(height),
|
|
static_cast<GLenum>(pixel_format),
|
|
static_cast<GLenum>(component_type),
|
|
pixels);
|
|
}
|
|
|
|
void gen_opengl_samplers(std::uint32_t count, std::uint32_t* ids) noexcept
|
|
{
|
|
#if USE_SAMPLER
|
|
glGenSamplers(static_cast<GLsizei>(count), reinterpret_cast<GLuint*>(ids));
|
|
#else
|
|
for (std::uint32_t i = 0U; i < count; ++i) {
|
|
ids[i] = 0U;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void set_opengl_sampler_parameter_i(
|
|
std::uint32_t sampler,
|
|
std::uint32_t parameter,
|
|
std::int32_t value) noexcept
|
|
{
|
|
#if USE_SAMPLER
|
|
glSamplerParameteri(
|
|
static_cast<GLuint>(sampler),
|
|
static_cast<GLenum>(parameter),
|
|
static_cast<GLint>(value));
|
|
#else
|
|
(void)sampler;
|
|
(void)parameter;
|
|
(void)value;
|
|
#endif
|
|
}
|
|
|
|
void set_opengl_sampler_parameter_fv(
|
|
std::uint32_t sampler,
|
|
std::uint32_t parameter,
|
|
const float* values) noexcept
|
|
{
|
|
#if USE_SAMPLER && !defined(__GLES__)
|
|
glSamplerParameterfv(
|
|
static_cast<GLuint>(sampler),
|
|
static_cast<GLenum>(parameter),
|
|
values);
|
|
#else
|
|
(void)sampler;
|
|
(void)parameter;
|
|
(void)values;
|
|
#endif
|
|
}
|
|
|
|
void bind_opengl_sampler(std::uint32_t unit, std::uint32_t sampler) noexcept
|
|
{
|
|
#if USE_SAMPLER
|
|
glBindSampler(static_cast<GLuint>(unit), static_cast<GLuint>(sampler));
|
|
#else
|
|
(void)unit;
|
|
(void)sampler;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
std::map<uint16_t, Texture2D> TextureManager::m_textures;
|
|
std::array<int, 6> TextureCube::m_faces_map {
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(0U)),
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(1U)),
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(2U)),
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(3U)),
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(4U)),
|
|
static_cast<int>(pp::renderer::gl::cube_face_texture_target(5U)),
|
|
};
|
|
|
|
TextureCube::TextureCube(TextureCube&& other) noexcept
|
|
{
|
|
other.m_faces = std::move(other.m_faces);
|
|
m_cubetex_id = other.m_cubetex_id; other.m_cubetex_id = 0;
|
|
m_resolution = other.m_resolution; other.m_resolution = 0;
|
|
}
|
|
|
|
TextureCube::~TextureCube()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
void TextureCube::operator=(TextureCube&& other) noexcept
|
|
{
|
|
other.m_faces = std::move(other.m_faces);
|
|
m_cubetex_id = other.m_cubetex_id; other.m_cubetex_id = 0;
|
|
m_resolution = other.m_resolution; other.m_resolution = 0;
|
|
}
|
|
|
|
bool TextureCube::create(int resolution) noexcept
|
|
{
|
|
App::I->render_task([this, resolution]
|
|
{
|
|
destroy();
|
|
m_resolution = resolution;
|
|
const auto format = pp::renderer::gl::texture_format_for_channel_count(4U);
|
|
const auto texture = pp::renderer::gl::allocate_opengl_texture_cube(
|
|
pp::renderer::gl::OpenGlTextureCubeAllocation {
|
|
.resolution = m_resolution,
|
|
.internal_format = static_cast<std::int32_t>(format.internal_format),
|
|
.pixel_format = format.pixel_format,
|
|
.component_type = pp::renderer::gl::unsigned_byte_component_type(),
|
|
},
|
|
pp::renderer::gl::OpenGlTextureCubeAllocationDispatch {
|
|
.gen_textures = gen_opengl_textures,
|
|
.bind_texture = bind_opengl_texture,
|
|
.tex_image_2d = upload_opengl_texture_2d,
|
|
});
|
|
if (!texture.ok())
|
|
{
|
|
LOG("TextureCube::create() failed because: %s", texture.status().message);
|
|
return;
|
|
}
|
|
m_cubetex_id = static_cast<GLuint>(texture.value());
|
|
});
|
|
return m_cubetex_id != 0;
|
|
}
|
|
|
|
void TextureCube::destroy() noexcept
|
|
{
|
|
if (m_cubetex_id)
|
|
{
|
|
App::I->render_task([f=m_faces, id=m_cubetex_id]
|
|
{
|
|
std::array<std::uint32_t, 7> texture_ids {};
|
|
for (std::size_t i = 0U; i < f.size(); ++i)
|
|
texture_ids[i] = static_cast<std::uint32_t>(f[i]);
|
|
texture_ids[f.size()] = static_cast<std::uint32_t>(id);
|
|
const auto status = pp::renderer::gl::delete_opengl_texture_objects(
|
|
texture_ids,
|
|
pp::renderer::gl::OpenGlTexture2DDeleteDispatch {
|
|
.delete_textures = delete_opengl_textures,
|
|
});
|
|
if (!status.ok())
|
|
LOG("TextureCube::destroy() failed because: %s", status.message);
|
|
});
|
|
m_cubetex_id = 0;
|
|
m_faces.fill(0);
|
|
m_resolution = 0;
|
|
}
|
|
}
|
|
|
|
void TextureCube::bind() const noexcept
|
|
{
|
|
assert(App::I->is_render_thread());
|
|
const auto status = pp::renderer::gl::bind_opengl_texture_cube(
|
|
static_cast<std::uint32_t>(m_cubetex_id),
|
|
pp::renderer::gl::OpenGlTexture2DBindDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
});
|
|
if (!status.ok())
|
|
LOG("TextureCube::bind() failed because: %s", status.message);
|
|
}
|
|
|
|
bool TextureManager::load(const char* path, bool generate_mipmaps)
|
|
{
|
|
uint16_t id = const_hash(path);
|
|
auto t = m_textures.find(id);
|
|
if (t == m_textures.end() || !m_textures[id].ready())
|
|
{
|
|
if (!m_textures[id].load(path))
|
|
return false;
|
|
}
|
|
if (generate_mipmaps && !m_textures[id].has_mips)
|
|
m_textures[id].create_mipmaps();
|
|
return true;
|
|
}
|
|
|
|
void TextureManager::assign(uint16_t id, GLuint tex, int w, int h, GLuint internal_format, GLuint format)
|
|
{
|
|
m_textures[id].assign(tex, w, h, internal_format, format);
|
|
}
|
|
|
|
void TextureManager::assign(uint16_t id, GLuint tex, int w, int h)
|
|
{
|
|
assign(
|
|
id,
|
|
tex,
|
|
w,
|
|
h,
|
|
pp::renderer::gl::rgba8_internal_format(),
|
|
pp::renderer::gl::rgba_pixel_format());
|
|
}
|
|
|
|
Texture2D& TextureManager::get(uint16_t id)
|
|
{
|
|
return m_textures[id];
|
|
}
|
|
|
|
void TextureManager::invalidate()
|
|
{
|
|
for (auto& t : m_textures)
|
|
{
|
|
t.second.destroy();
|
|
}
|
|
m_textures.clear();
|
|
}
|
|
|
|
Image Texture2D::get_image() const noexcept
|
|
{
|
|
Image ret;
|
|
ret.create(m_width, m_height);
|
|
App::I->render_task([&]
|
|
{
|
|
const auto readback = pp::renderer::gl::readback_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DReadback {
|
|
.texture_id = static_cast<std::uint32_t>(m_tex),
|
|
.width = m_width,
|
|
.height = m_height,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = ret.m_data.get(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DReadbackDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
.gen_framebuffers = gen_opengl_framebuffers,
|
|
.get_integer = query_opengl_integer,
|
|
.bind_framebuffer = bind_opengl_framebuffer,
|
|
.framebuffer_texture_2d = attach_opengl_framebuffer_texture_2d,
|
|
.check_framebuffer_status = check_opengl_framebuffer_status,
|
|
.read_pixels = read_opengl_pixels,
|
|
.delete_framebuffers = delete_opengl_framebuffers,
|
|
});
|
|
if (!readback.ok()) {
|
|
LOG("Texture2D::get_image() failed because: %s", readback.status().message);
|
|
return;
|
|
}
|
|
|
|
if (!readback.value().pixels_read) {
|
|
LOG("Texture2D::get_image() failed because: %s",
|
|
pp::renderer::gl::framebuffer_status_name(readback.value().framebuffer_status));
|
|
}
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
Texture2D::Texture2D(Texture2D&& other) noexcept
|
|
{
|
|
m_tex = other.m_tex;
|
|
m_width = other.m_width;
|
|
m_height = other.m_height;
|
|
m_format = other.m_format;
|
|
m_iformat = other.m_iformat;
|
|
has_mips = other.has_mips;
|
|
other.m_tex = false;
|
|
}
|
|
|
|
void Texture2D::operator=(Texture2D&& other) noexcept
|
|
{
|
|
m_tex = other.m_tex;
|
|
m_width = other.m_width;
|
|
m_height = other.m_height;
|
|
m_format = other.m_format;
|
|
m_iformat = other.m_iformat;
|
|
has_mips = other.has_mips;
|
|
other.m_tex = false;
|
|
}
|
|
|
|
bool Texture2D::create(int width, int height)
|
|
{
|
|
return create(
|
|
width,
|
|
height,
|
|
static_cast<GLint>(pp::renderer::gl::rgba8_internal_format()),
|
|
static_cast<GLint>(pp::renderer::gl::rgba_pixel_format()));
|
|
}
|
|
|
|
bool Texture2D::create(int width, int height, GLint internal_format)
|
|
{
|
|
return create(
|
|
width,
|
|
height,
|
|
internal_format,
|
|
static_cast<GLint>(pp::renderer::gl::rgba_pixel_format()));
|
|
}
|
|
|
|
bool Texture2D::create(int width, int height, GLint internal_format, GLint format, const uint8_t* data)
|
|
{
|
|
App::I->render_task([=]
|
|
{
|
|
destroy();
|
|
const auto component_type = pp::renderer::gl::texture_upload_type_for_internal_format(
|
|
static_cast<std::uint32_t>(internal_format));
|
|
const auto texture = pp::renderer::gl::allocate_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DAllocation {
|
|
.width = width,
|
|
.height = height,
|
|
.internal_format = internal_format,
|
|
.pixel_format = static_cast<std::uint32_t>(format),
|
|
.component_type = component_type,
|
|
.data = data,
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DAllocationDispatch {
|
|
.gen_textures = gen_opengl_textures,
|
|
.bind_texture = bind_opengl_texture,
|
|
.tex_image_2d = upload_opengl_texture_2d,
|
|
});
|
|
if (!texture.ok()) {
|
|
LOG("Texture2D::create() failed because: %s", texture.status().message);
|
|
return;
|
|
}
|
|
|
|
m_width = width;
|
|
m_height = height;
|
|
m_format = format;
|
|
m_iformat = internal_format;
|
|
m_tex = static_cast<GLuint>(texture.value());
|
|
});
|
|
return true;
|
|
}
|
|
bool Texture2D::create(const Image& img)
|
|
{
|
|
const auto format = pp::renderer::gl::texture_format_for_channel_count(static_cast<std::uint32_t>(img.comp));
|
|
if (format.channel_count == 0U)
|
|
return false;
|
|
|
|
return create(
|
|
img.width,
|
|
img.height,
|
|
static_cast<GLint>(format.internal_format),
|
|
static_cast<GLint>(format.pixel_format),
|
|
img.data());
|
|
}
|
|
|
|
void Texture2D::create_mipmaps()
|
|
{
|
|
App::I->render_task([this]
|
|
{
|
|
const auto status = pp::renderer::gl::generate_opengl_texture_2d_mipmaps(
|
|
static_cast<std::uint32_t>(m_tex),
|
|
pp::renderer::gl::OpenGlTexture2DMipmapDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
.generate_mipmap = generate_opengl_mipmap,
|
|
});
|
|
if (!status.ok()) {
|
|
LOG("Texture2D::create_mipmaps() failed because: %s", status.message);
|
|
return;
|
|
}
|
|
has_mips = true;
|
|
});
|
|
}
|
|
|
|
void Texture2D::assign(GLuint tex, int w, int h, GLuint internal_format, GLuint format)
|
|
{
|
|
m_tex = tex;
|
|
m_width = w;
|
|
m_height = h;
|
|
m_format = format;
|
|
m_iformat = internal_format;
|
|
}
|
|
|
|
void Texture2D::assign(GLuint tex, int w, int h)
|
|
{
|
|
assign(
|
|
tex,
|
|
w,
|
|
h,
|
|
pp::renderer::gl::rgba8_internal_format(),
|
|
pp::renderer::gl::rgba_pixel_format());
|
|
}
|
|
|
|
bool Texture2D::load(std::string filename)
|
|
{
|
|
LOG("load texture %s", filename.c_str());
|
|
Image img;
|
|
if (!img.load(filename))
|
|
return false;
|
|
return create(img);
|
|
}
|
|
|
|
bool Texture2D::load_file(std::string filename)
|
|
{
|
|
LOG("load texture %s", filename.c_str());
|
|
Image img;
|
|
if (!img.load_file(filename))
|
|
return false;
|
|
return create(img);
|
|
}
|
|
|
|
void Texture2D::destroy()
|
|
{
|
|
if (m_tex)
|
|
{
|
|
App::I->render_task_async([id = m_tex]
|
|
{
|
|
const auto status = pp::renderer::gl::delete_opengl_texture_2d(
|
|
static_cast<std::uint32_t>(id),
|
|
pp::renderer::gl::OpenGlTexture2DDeleteDispatch {
|
|
.delete_textures = delete_opengl_textures,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Texture2D::destroy() failed because: %s", status.message);
|
|
});
|
|
m_tex = 0;
|
|
}
|
|
}
|
|
|
|
void Texture2D::bind() const
|
|
{
|
|
assert(App::I->is_render_thread());
|
|
const auto status = pp::renderer::gl::bind_opengl_texture_2d(
|
|
static_cast<std::uint32_t>(m_tex),
|
|
pp::renderer::gl::OpenGlTexture2DBindDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Texture2D::bind() failed because: %s", status.message);
|
|
}
|
|
|
|
void Texture2D::unbind() const
|
|
{
|
|
assert(App::I->is_render_thread());
|
|
const auto status = pp::renderer::gl::bind_opengl_texture_2d(
|
|
0U,
|
|
pp::renderer::gl::OpenGlTexture2DBindDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Texture2D::unbind() failed because: %s", status.message);
|
|
}
|
|
|
|
void Texture2D::update(const uint8_t* data)
|
|
{
|
|
App::I->render_task([this, data]
|
|
{
|
|
const auto status = pp::renderer::gl::update_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DUpdate {
|
|
.texture_id = static_cast<std::uint32_t>(m_tex),
|
|
.width = m_width,
|
|
.height = m_height,
|
|
.pixel_format = static_cast<std::uint32_t>(m_format),
|
|
.component_type = pp::renderer::gl::unsigned_byte_component_type(),
|
|
.data = data,
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DUpdateDispatch {
|
|
.bind_texture = bind_opengl_texture,
|
|
.tex_sub_image_2d = update_opengl_texture_2d_region,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Texture2D::update() failed because: %s", status.message);
|
|
});
|
|
}
|
|
|
|
glm::vec2 Texture2D::size() const
|
|
{
|
|
return { m_width, m_height };
|
|
}
|
|
|
|
Texture2D::~Texture2D()
|
|
{
|
|
destroy();
|
|
}
|
|
|
|
bool Sampler::create(GLint filter, GLint wrap)
|
|
{
|
|
bool ret = false;
|
|
App::I->render_task([this, &ret, filter, wrap]
|
|
{
|
|
const auto parameters = pp::renderer::gl::sampler_parameters_for_filter_wrap(
|
|
static_cast<std::uint32_t>(filter),
|
|
static_cast<std::uint32_t>(wrap));
|
|
const auto sampler = pp::renderer::gl::create_opengl_sampler(
|
|
parameters,
|
|
pp::renderer::gl::OpenGlSamplerCreateDispatch {
|
|
.gen_samplers = gen_opengl_samplers,
|
|
.sampler_parameter_i = set_opengl_sampler_parameter_i,
|
|
});
|
|
if (!sampler.ok())
|
|
{
|
|
ret = false;
|
|
LOG("Sampler::create() failed because: %s", sampler.status().message);
|
|
return;
|
|
}
|
|
id = static_cast<GLuint>(sampler.value());
|
|
ret = true;
|
|
});
|
|
return ret;
|
|
}
|
|
|
|
bool Sampler::create()
|
|
{
|
|
return create(
|
|
static_cast<GLint>(pp::renderer::gl::linear_texture_filter()),
|
|
static_cast<GLint>(pp::renderer::gl::clamp_to_edge_texture_wrap()));
|
|
}
|
|
|
|
bool Sampler::create(GLint filter)
|
|
{
|
|
return create(filter, static_cast<GLint>(pp::renderer::gl::clamp_to_edge_texture_wrap()));
|
|
}
|
|
|
|
void Sampler::set(GLint filter, GLint wrap)
|
|
{
|
|
App::I->render_task([=]
|
|
{
|
|
const auto parameters = pp::renderer::gl::sampler_parameters_for_filter_wrap(
|
|
static_cast<std::uint32_t>(filter),
|
|
static_cast<std::uint32_t>(wrap));
|
|
const auto status = pp::renderer::gl::set_opengl_sampler_parameters(
|
|
static_cast<std::uint32_t>(id),
|
|
parameters,
|
|
pp::renderer::gl::OpenGlSamplerParameterDispatch {
|
|
.sampler_parameter_i = set_opengl_sampler_parameter_i,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Sampler::set() failed because: %s", status.message);
|
|
});
|
|
}
|
|
|
|
void Sampler::set()
|
|
{
|
|
set(
|
|
static_cast<GLint>(pp::renderer::gl::linear_texture_filter()),
|
|
static_cast<GLint>(pp::renderer::gl::clamp_to_edge_texture_wrap()));
|
|
}
|
|
|
|
void Sampler::set(GLint filter)
|
|
{
|
|
set(filter, static_cast<GLint>(pp::renderer::gl::clamp_to_edge_texture_wrap()));
|
|
}
|
|
|
|
void Sampler::set_filter(GLint filter_min, GLint filter_mag)
|
|
{
|
|
App::I->render_task([=]
|
|
{
|
|
const auto parameters = pp::renderer::gl::sampler_filter_parameters(
|
|
static_cast<std::uint32_t>(filter_min),
|
|
static_cast<std::uint32_t>(filter_mag));
|
|
const auto status = pp::renderer::gl::set_opengl_sampler_parameters(
|
|
static_cast<std::uint32_t>(id),
|
|
parameters,
|
|
pp::renderer::gl::OpenGlSamplerParameterDispatch {
|
|
.sampler_parameter_i = set_opengl_sampler_parameter_i,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Sampler::set_filter() failed because: %s", status.message);
|
|
});
|
|
}
|
|
void Sampler::set_border(glm::vec4 rgba)
|
|
{
|
|
App::I->render_task([this, rgba]
|
|
{
|
|
const auto status = pp::renderer::gl::set_opengl_sampler_border_color(
|
|
static_cast<std::uint32_t>(id),
|
|
pp::renderer::gl::sampler_border_color_parameter_name(),
|
|
glm::value_ptr(rgba),
|
|
pp::renderer::gl::OpenGlSamplerBorderDispatch {
|
|
.sampler_parameter_fv = set_opengl_sampler_parameter_fv,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Sampler::set_border() failed because: %s", status.message);
|
|
});
|
|
}
|
|
void Sampler::bind(int unit) const
|
|
{
|
|
assert(App::I->is_render_thread());
|
|
current_unit = unit;
|
|
const auto status = pp::renderer::gl::bind_opengl_sampler_object(
|
|
static_cast<std::uint32_t>(unit),
|
|
static_cast<std::uint32_t>(id),
|
|
pp::renderer::gl::OpenGlSamplerBindDispatch {
|
|
.bind_sampler = bind_opengl_sampler,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Sampler::bind() failed because: %s", status.message);
|
|
}
|
|
void Sampler::unbind()
|
|
{
|
|
assert(App::I->is_render_thread());
|
|
const auto status = pp::renderer::gl::bind_opengl_sampler_object(
|
|
static_cast<std::uint32_t>(current_unit),
|
|
0U,
|
|
pp::renderer::gl::OpenGlSamplerBindDispatch {
|
|
.bind_sampler = bind_opengl_sampler,
|
|
});
|
|
if (!status.ok())
|
|
LOG("Sampler::unbind() failed because: %s", status.message);
|
|
}
|
|
|