mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-08 06:38:27 +03:00
Texture Skinning Buffer
This commit is contained in:
+156
-14
@@ -475,7 +475,17 @@ void render_data::set_skinning_data(p_gl_rend_state& p_gl_rend_st, const mat4* m
|
||||
}
|
||||
}
|
||||
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
if (sv_texture_skinning_buffer) {
|
||||
GLuint texture = 0;
|
||||
vec2i offset = 0;
|
||||
if (rctx_ptr->get_texture_skinning_buffer_data((size_t)mats, texture, offset)) {
|
||||
vec2i_to_vec2(offset, *(vec2*)&buffer_batch_data.g_bump_depth.z);
|
||||
enum_or(flags, RENDER_DATA_BATCH_UPDATE);
|
||||
p_gl_rend_st.active_bind_texture_2d(21, texture);
|
||||
p_gl_rend_st.bind_sampler(21, rctx_ptr->render_samplers[1]);
|
||||
}
|
||||
}
|
||||
else if (sv_shared_storage_uniform_buffer) {
|
||||
GLuint buffer = 0;
|
||||
size_t offset = 0;
|
||||
size_t size = 0;
|
||||
@@ -570,7 +580,7 @@ void render_data::set_state(p_gl_rend_state& p_gl_rend_st) {
|
||||
p_gl_rend_st.bind_uniform_buffer_base(1, buffer_scene);
|
||||
p_gl_rend_st.bind_uniform_buffer_base(2, buffer_batch);
|
||||
|
||||
if (shader_flags.arr[U_SKINNING] && !sv_shared_storage_uniform_buffer)
|
||||
if (shader_flags.arr[U_SKINNING] && !sv_shared_storage_uniform_buffer && !sv_texture_skinning_buffer)
|
||||
if (GLAD_GL_VERSION_4_3)
|
||||
p_gl_rend_st.bind_shader_storage_buffer_base(0, buffer_skinning);
|
||||
else
|
||||
@@ -675,7 +685,10 @@ void render_data_context::set_batch_material_parameter(const vec4* specular, con
|
||||
const vec4& intensity, const float_t reflect_uv_scale, const float_t refract_uv_scale) {
|
||||
if (specular)
|
||||
data.buffer_batch_data.g_material_state_specular = *specular;
|
||||
data.buffer_batch_data.g_bump_depth = bump_depth;
|
||||
if (sv_texture_skinning_buffer)
|
||||
*(vec2*)&data.buffer_batch_data.g_bump_depth.x = *(vec2*)&bump_depth;
|
||||
else
|
||||
data.buffer_batch_data.g_bump_depth = bump_depth;
|
||||
data.buffer_batch_data.g_intensity = intensity;
|
||||
data.buffer_batch_data.g_reflect_uv_scale.x = reflect_uv_scale;
|
||||
data.buffer_batch_data.g_reflect_uv_scale.y = reflect_uv_scale;
|
||||
@@ -983,6 +996,59 @@ size_t render_context::shared_uniform_buffer::fill_data(const void* data, size_t
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool render_context::texture_skinning_buffer::can_fill_data(int32_t width) {
|
||||
return (x + width) <= this->width || (y + 1) < height;
|
||||
}
|
||||
|
||||
void render_context::texture_skinning_buffer::create(int32_t width, int32_t height) {
|
||||
if (texture)
|
||||
return;
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
gl_state.bind_texture_2d(texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
static const vec4 border_color = 0.0f;
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
|
||||
gl_state.bind_texture_2d(0);
|
||||
data = force_malloc(sizeof(vec4) * width * height);
|
||||
memset(data, 0, sizeof(vec4) * width * height);
|
||||
x = 0;
|
||||
y = 0;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
}
|
||||
|
||||
void render_context::texture_skinning_buffer::destroy() {
|
||||
if (texture) {
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
|
||||
free_def(data);
|
||||
}
|
||||
|
||||
vec2i render_context::texture_skinning_buffer::fill_data(const void* data, int32_t width) {
|
||||
if (x + width > this->width) {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
|
||||
int32_t x = this->x;
|
||||
int32_t y = this->y;
|
||||
memcpy((void*)((size_t)this->data + (sizeof(vec4) * this->width * y
|
||||
+ sizeof(vec4) * x)), data, sizeof(vec4) * width);
|
||||
this->x = x + width;
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
render_context::render_context() : litproj(), chara_reflect(), chara_refract(), box_vao(), lens_ghost_vao(),
|
||||
common_vao(), empty_texture_2d(), empty_texture_cube_map(), samplers(), render_samplers(), sprite_samplers(),
|
||||
sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_width(), screen_height() {
|
||||
@@ -1181,6 +1247,14 @@ sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_wi
|
||||
}
|
||||
|
||||
render_context::~render_context() {
|
||||
if (sv_texture_skinning_buffer) {
|
||||
texture_skinning_buffer_entries.clear();
|
||||
|
||||
for (render_context::texture_skinning_buffer& i : texture_skinning_buffers)
|
||||
i.destroy();
|
||||
texture_skinning_buffers.clear();
|
||||
}
|
||||
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
shared_uniform_buffer_entries.clear();
|
||||
|
||||
@@ -1434,6 +1508,24 @@ void render_context::add_shared_storage_uniform_buffer_data(size_t index,
|
||||
}
|
||||
}
|
||||
|
||||
void render_context::add_texture_skinning_buffer_data(size_t index, const void* data, int32_t width) {
|
||||
render_context::texture_skinning_buffer* buffer = 0;
|
||||
for (render_context::texture_skinning_buffer& i : texture_skinning_buffers)
|
||||
if (i.can_fill_data(width)) {
|
||||
buffer = &i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
texture_skinning_buffers.push_back({});
|
||||
buffer = &texture_skinning_buffers.back();
|
||||
buffer->create(1024, 128);
|
||||
}
|
||||
|
||||
vec2i offset = buffer->fill_data(data, width);
|
||||
texture_skinning_buffer_entries.insert({ index, { buffer->texture, offset } });
|
||||
}
|
||||
|
||||
bool render_context::get_shared_storage_uniform_buffer_data(size_t index,
|
||||
GLuint& buffer, size_t& offset, size_t& size, bool storage) {
|
||||
if (storage) {
|
||||
@@ -1458,21 +1550,38 @@ bool render_context::get_shared_storage_uniform_buffer_data(size_t index,
|
||||
}
|
||||
}
|
||||
|
||||
bool render_context::get_texture_skinning_buffer_data(size_t index, GLuint& texture, vec2i& offset) {
|
||||
auto elem = texture_skinning_buffer_entries.find(index);
|
||||
if (elem == texture_skinning_buffer_entries.end())
|
||||
return false;
|
||||
|
||||
texture = elem->second.texture;
|
||||
offset = elem->second.offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
void render_context::pre_proc() {
|
||||
if (sv_shared_storage_uniform_buffer) {
|
||||
if (sv_texture_skinning_buffer || sv_shared_storage_uniform_buffer) {
|
||||
auto add_obj_list = [](render_context* rctx, const mdl::ObjSubMeshArgs* args) {
|
||||
if (!args->mat_count || !args->mats)
|
||||
return;
|
||||
|
||||
if (GLAD_GL_VERSION_4_3) {
|
||||
auto elem = rctx->shared_storage_buffer_entries.find((size_t)args->mats);
|
||||
if (elem != rctx->shared_storage_buffer_entries.end())
|
||||
if (sv_texture_skinning_buffer) {
|
||||
auto elem = rctx->texture_skinning_buffer_entries.find((size_t)args->mats);
|
||||
if (elem != rctx->texture_skinning_buffer_entries.end())
|
||||
return;
|
||||
}
|
||||
else {
|
||||
auto elem = rctx->shared_uniform_buffer_entries.find((size_t)args->mats);
|
||||
if (elem != rctx->shared_uniform_buffer_entries.end())
|
||||
return;
|
||||
if (GLAD_GL_VERSION_4_3) {
|
||||
auto elem = rctx->shared_storage_buffer_entries.find((size_t)args->mats);
|
||||
if (elem != rctx->shared_storage_buffer_entries.end())
|
||||
return;
|
||||
}
|
||||
else {
|
||||
auto elem = rctx->shared_uniform_buffer_entries.find((size_t)args->mats);
|
||||
if (elem != rctx->shared_uniform_buffer_entries.end())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t mat_count = min_def(args->mat_count, 256);
|
||||
@@ -1488,10 +1597,15 @@ void render_context::pre_proc() {
|
||||
g_joint_transform[2] = mat.row2;
|
||||
}
|
||||
|
||||
const size_t buffer_size = sizeof(vec4) * 3 * 256;
|
||||
const size_t size = sizeof(vec4) * 3 * mat_count;
|
||||
rctx->add_shared_storage_uniform_buffer_data((size_t)args->mats,
|
||||
g_joint_transforms, size, buffer_size, !!GLAD_GL_VERSION_4_3);
|
||||
if (sv_texture_skinning_buffer)
|
||||
rctx->add_texture_skinning_buffer_data((size_t)args->mats,
|
||||
g_joint_transforms, 3 * mat_count);
|
||||
else {
|
||||
const size_t buffer_size = sizeof(vec4) * 3 * 256;
|
||||
const size_t size = sizeof(vec4) * 3 * mat_count;
|
||||
rctx->add_shared_storage_uniform_buffer_data((size_t)args->mats,
|
||||
g_joint_transforms, size, buffer_size, !!GLAD_GL_VERSION_4_3);
|
||||
}
|
||||
};
|
||||
|
||||
for (int32_t type = 0; type < mdl::OBJ_TYPE_MAX; type++)
|
||||
@@ -1552,6 +1666,25 @@ void render_context::pre_proc() {
|
||||
memset((void*)((size_t)i.data + i.offset), 0, align);
|
||||
i.buffer.WriteMemory(gl_state, 0, size, i.data);
|
||||
}
|
||||
|
||||
for (render_context::texture_skinning_buffer& i : texture_skinning_buffers) {
|
||||
if (!i.x && !i.y)
|
||||
continue;
|
||||
|
||||
const int32_t align_x = i.width - i.x;
|
||||
if (align_x)
|
||||
memset((void*)((size_t)i.data + (sizeof(vec4) * i.width * i.y
|
||||
+ sizeof(vec4) * i.x)), 0, sizeof(vec4) * align_x);
|
||||
if (GLAD_GL_VERSION_4_5)
|
||||
glTextureSubImage2D(i.texture, 0, 0, 0, i.width, i.y + 1, GL_RGBA, GL_FLOAT, i.data);
|
||||
else {
|
||||
gl_state.bind_texture_2d(i.texture);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, i.width, i.y + 1, GL_RGBA, GL_FLOAT, i.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!GLAD_GL_VERSION_4_5)
|
||||
gl_state.bind_texture_2d(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1573,4 +1706,13 @@ void render_context::post_proc() {
|
||||
|
||||
shared_uniform_buffer_entries.clear();
|
||||
}
|
||||
|
||||
if (sv_texture_skinning_buffer) {
|
||||
for (render_context::texture_skinning_buffer& i : texture_skinning_buffers) {
|
||||
i.x = 0;
|
||||
i.y = 0;
|
||||
}
|
||||
|
||||
texture_skinning_buffer_entries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user