/* by korenkonder GitHub/GitLab: korenkonder */ #include "render_context.hpp" #include "shader_ft.hpp" #include "sound.hpp" #include "sprite.hpp" #include "task.hpp" float_t delta_frame_history = 0; int32_t delta_frame_history_int = 0; extern float_t rob_frame; extern render_context* rctx_ptr; //extern void dw_gui_ctrl_disp(); static void render_context_light_param_data_ibl_set_diffuse(light_param_ibl_diffuse* diffuse, int32_t level); static void render_context_light_param_data_ibl_set_specular(light_param_ibl_specular* specular); static const GLuint POSITION_INDEX = 0; static const GLuint BONE_WEIGHT_INDEX = 1; static const GLuint NORMAL_INDEX = 2; static const GLuint COLOR0_INDEX = 3; static const GLuint COLOR1_INDEX = 4; static const GLuint MORPH_COLOR_INDEX = 5; static const GLuint TANGENT_INDEX = 6; static const GLuint UNKNOWN_INDEX = 7; static const GLuint TEXCOORD0_INDEX = 8; static const GLuint TEXCOORD1_INDEX = 9; static const GLuint MORPH_POSITION_INDEX = 10; static const GLuint MORPH_NORMAL_INDEX = 11; static const GLuint MORPH_TANGENT_INDEX = 12; static const GLuint MORPH_TEXCOORD0_INDEX = 13; static const GLuint MORPH_TEXCOORD1_INDEX = 14; static const GLuint BONE_INDEX_INDEX = 15; draw_state_stats::draw_state_stats() : object_draw_count(), object_translucent_draw_count(), object_reflect_draw_count(), field_C(), field_10(), draw_count(), draw_triangle_count(), field_1C() { } void draw_state_stats::reset() { object_draw_count = 0; object_translucent_draw_count = 0; object_reflect_draw_count = 0; field_C = 0; field_10 = 0; draw_count = 0; draw_triangle_count = 0; field_1C = 0; } draw_state::draw_state() : wireframe(), wireframe_overlay(), light(), self_shadow(), shader_debug_flag(), use_global_material(), fog_height(), ex_data_mat(), field_68() { shader = true; shader_index = -1; show = -1; bump_depth = 1.0f; intensity = 1.0f; reflectivity = 1.0f; reflect_uv_scale = 0.1f; refract_uv_scale = 0.1f; fresnel = 7.0f; } void draw_state::set_fog_height(bool value) { fog_height = value; } sss_data::sss_data() : init_data(), enable(), npr_contour(), param() { init_data = true; enable = true; npr_contour = true; param = { 0.0f, 0.0f, 0.0f, 1.0f }; } sss_data::~sss_data() { } void sss_data::free() { } void sss_data::init() { textures[0].Init(640, 360, 0, GL_RGBA16F, GL_ZERO /*GL_DEPTH_COMPONENT32F*/); textures[1].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); textures[2].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); textures[3].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); } light_proj::light_proj(int32_t width, int32_t height) : enable(), texture_id() { shadow_texture[0].Init(2048, 512, 0, GL_R32F, GL_DEPTH_COMPONENT32F); shadow_texture[1].Init(2048, 512, 0, GL_R32F, GL_ZERO); draw_texture.Init(width, height, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F); } light_proj::~light_proj() { } void light_proj::resize(int32_t width, int32_t height) { if (!this) return; draw_texture.Init(width, height, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F); } bool light_proj::set() { if (!this) return false; static const vec4 color_clear = 1.0f; static const GLfloat depth_clear = 1.0f; shadow_texture[0].Bind(); glViewport(0, 0, 2048, 512); gl_state_enable_depth_test(); gl_state_set_depth_mask(GL_TRUE); glClearBufferfv(GL_COLOR, 0, (float_t*)&color_clear); glClearBufferfv(GL_DEPTH, 0, &depth_clear); if (set_mat(false)) { rctx_ptr->draw_state->shader_index = SHADER_FT_SIL; uniform_value[U0A] = 1; return true; } else { draw_texture.Bind(); draw_texture.SetViewport(); gl_state_enable_depth_test(); gl_state_set_depth_mask(GL_TRUE); glClearBufferfv(GL_COLOR, 0, (float_t*)&color_clear); glClearBufferfv(GL_DEPTH, 0, &depth_clear); } return false; } bool light_proj::set_mat(bool set_mat) { render_context* rctx = rctx_ptr; light_set* set = &rctx->light_set[LIGHT_SET_MAIN]; light_data* data = &set->lights[LIGHT_PROJECTION]; if (data->get_type() != LIGHT_SPOT) return false; vec3 position; vec3 spot_direction; data->get_position(position); data->get_spot_direction(spot_direction); if (vec3::length_squared(spot_direction) <= 0.000001f) return false; float_t spot_cutoff = data->get_spot_cutoff(); float_t fov = atanf(tanf(spot_cutoff * DEG_TO_RAD_FLOAT) * 0.25f) * 2.0f; vec3 interest = position + spot_direction; if (set_mat) { mat4 temp; mat4_translate(0.5f, 0.5f, 0.5f, &temp); mat4_scale_rot(&temp, 0.5f, 0.5f, 0.5f, &temp); mat4 proj; mat4_persp(fov, 4.0f, 0.1f, 10.0f, &proj); mat4_mul(&proj, &temp, &proj); mat4 view; vec3 up = { 0.0f, 1.0f, 0.0f }; mat4_look_at(&position, &interest, &up, &view); mat4 mat; mat4_mul(&view, &proj, &mat); rctx->obj_scene.set_g_light_projection(mat); } else { mat4_persp(fov, 4.0f, 0.1f, 10.0f, &rctx->proj_mat); vec3 up = { 0.0f, 1.0f, 0.0f }; mat4_look_at(&position, &interest, &up, &rctx->view_mat); rctx->obj_scene.set_projection_view(rctx->view_mat, rctx->proj_mat); } return true; } void obj_scene_shader_data::set_g_irradiance_r_transforms(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_irradiance_r_transforms[0] = temp.row0; g_irradiance_r_transforms[1] = temp.row1; g_irradiance_r_transforms[2] = temp.row2; g_irradiance_r_transforms[3] = temp.row3; } void obj_scene_shader_data::set_g_irradiance_g_transforms(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_irradiance_g_transforms[0] = temp.row0; g_irradiance_g_transforms[1] = temp.row1; g_irradiance_g_transforms[2] = temp.row2; g_irradiance_g_transforms[3] = temp.row3; } void obj_scene_shader_data::set_g_irradiance_b_transforms(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_irradiance_b_transforms[0] = temp.row0; g_irradiance_b_transforms[1] = temp.row1; g_irradiance_b_transforms[2] = temp.row2; g_irradiance_b_transforms[3] = temp.row3; } void obj_scene_shader_data::set_g_normal_tangent_transforms(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_normal_tangent_transforms[0] = temp.row0; g_normal_tangent_transforms[1] = temp.row1; g_normal_tangent_transforms[2] = temp.row2; } void obj_scene_shader_data::set_g_self_shadow_receivers(int32_t index, const mat4& mat) { size_t _index = index * 3LL; mat4 temp; mat4_transpose(&mat, &temp); g_self_shadow_receivers[_index + 0] = temp.row0; g_self_shadow_receivers[_index + 1] = temp.row1; g_self_shadow_receivers[_index + 2] = temp.row2; } void obj_scene_shader_data::set_g_light_projection(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_light_projection[0] = temp.row0; g_light_projection[1] = temp.row1; g_light_projection[2] = temp.row2; g_light_projection[3] = temp.row3; } void obj_scene_shader_data::set_projection_view(const mat4& view, const mat4& proj) { mat4 temp; mat4_transpose(&view, &temp); g_view[0] = temp.row0; g_view[1] = temp.row1; g_view[2] = temp.row2; mat4_invert(&view, &temp); mat4_transpose(&temp, &temp); g_view_inverse[0] = temp.row0; g_view_inverse[1] = temp.row1; g_view_inverse[2] = temp.row2; mat4_mul(&view, &proj, &temp); mat4_transpose(&temp, &temp); g_projection_view[0] = temp.row0; g_projection_view[1] = temp.row1; g_projection_view[2] = temp.row2; g_projection_view[3] = temp.row3; } void obj_batch_shader_data::set_g_joint(const mat4& mat) { mat4 temp; mat4_transpose(&mat, &temp); g_joint[0] = temp.row0; g_joint[1] = temp.row1; g_joint[2] = temp.row2; mat4_invert(&mat, &temp); mat4_transpose(&temp, &temp); g_joint_inverse[0] = temp.row0; g_joint_inverse[1] = temp.row1; g_joint_inverse[2] = temp.row2; } void obj_batch_shader_data::set_g_texcoord_transforms(int32_t index, const mat4& mat) { size_t _index = index * 2LL; mat4 temp; mat4_transpose(&mat, &temp); g_texcoord_transforms[_index + 0] = temp.row0; g_texcoord_transforms[_index + 1] = temp.row1; } void obj_batch_shader_data::set_transforms(const mat4& model, const mat4& view, const mat4& proj) { mat4 temp; mat4_transpose(&model, &temp); g_worlds[0] = temp.row0; g_worlds[1] = temp.row1; g_worlds[2] = temp.row2; mat4_invert(&model, &temp); g_worlds_invtrans[0] = temp.row0; g_worlds_invtrans[1] = temp.row1; g_worlds_invtrans[2] = temp.row2; mat4 mv; mat4_mul(&model, &view, &mv); mat4_transpose(&mv, &temp); g_worldview[0] = temp.row0; g_worldview[1] = temp.row1; g_worldview[2] = temp.row2; mat4_invert(&mv, &temp); mat4_transpose(&temp, &temp); g_worldview_inverse[0] = temp.row0; g_worldview_inverse[1] = temp.row1; g_worldview_inverse[2] = temp.row2; mat4_mul(&mv, &proj, &temp); mat4_transpose(&temp, &temp); g_transforms[0] = temp.row0; g_transforms[1] = temp.row1; g_transforms[2] = temp.row2; g_transforms[3] = temp.row3; } 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() { camera = new ::camera; draw_state = new ::draw_state; disp_manager = new mdl::DispManager; render_manager = new rndr::RenderManager; sss_data = new ::sss_data; static const float_t box_texcoords[] = { 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, -1.5f, -1.5f, 0.5f, 1.5f, -0.5f, -0.5f, 1.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, -1.5f, -1.5f, 0.5f, 1.5f, -0.5f, -0.5f, 1.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, -1.5f, -1.5f, 0.5f, 1.5f, -0.5f, -0.5f, 1.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, -1.5f, -1.5f, 0.5f, 1.5f, -0.5f, -0.5f, 1.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.5f, -3.5f, -1.5f, -3.5f, 1.5f, -1.5f, -3.5f, -1.5f, 3.5f, 1.5f, -1.5f, 1.5f, 1.5f, 3.5f, -3.5f, 3.5f, 3.5f, -3.5f, -1.5f, -3.5f, 1.5f, -1.5f, -3.5f, -1.5f, 3.5f, 1.5f, -1.5f, 1.5f, 1.5f, 3.5f, -3.5f, 3.5f, 3.5f, -3.5f, -1.5f, -3.5f, 1.5f, -1.5f, -3.5f, -1.5f, 3.5f, 1.5f, -1.5f, 1.5f, 1.5f, 3.5f, -3.5f, 3.5f, 3.5f, -3.5f, -1.5f, -3.5f, 1.5f, -1.5f, -3.5f, -1.5f, 3.5f, 1.5f, -1.5f, 1.5f, 1.5f, 3.5f, -3.5f, 3.5f, }; glGenVertexArrays(1, &box_vao); gl_state_bind_vertex_array(box_vao); box_vbo.Create(sizeof(box_texcoords), box_texcoords); box_vbo.Bind(); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(float_t) * 16, (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float_t) * 16, (void*)(sizeof(float_t) * 4)); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(float_t) * 16, (void*)(sizeof(float_t) * 8)); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(float_t) * 16, (void*)(sizeof(float_t) * 12)); glGenVertexArrays(1, &lens_ghost_vao); gl_state_bind_vertex_array(lens_ghost_vao); lens_ghost_vbo.Create(sizeof(float_t) * 5 * (6 * 16)); lens_ghost_vbo.Bind(); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float_t) * 5, (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float_t) * 5, (void*)(sizeof(float_t) * 2)); gl_state_bind_array_buffer(0); gl_state_bind_vertex_array(0); glGenVertexArrays(1, &common_vao); contour_coef_ubo.Create(sizeof(contour_coef_shader_data)); contour_params_ubo.Create(sizeof(contour_params_shader_data)); filter_scene_ubo.Create(sizeof(filter_scene_shader_data)); esm_filter_batch_ubo.Create(sizeof(esm_filter_batch_shader_data)); imgfilter_batch_ubo.Create(sizeof(imgfilter_batch_shader_data)); exposure_measure_ubo.Create(sizeof(exposure_measure_shader_data)); gaussian_coef_ubo.Create(sizeof(gaussian_coef_shader_data)); glass_eye_batch_ubo.Create(sizeof(glass_eye_batch_shader_data)); glitter_batch_ubo.Create(sizeof(glitter_batch_shader_data)); quad_ubo.Create(sizeof(quad_shader_data)); sprite_scene_ubo.Create(sizeof(sprite_scene_shader_data)); sss_filter_gaussian_coef_ubo.Create(sizeof(sss_filter_gaussian_coef_shader_data)); sun_quad_ubo.Create(sizeof(sun_quad_shader_data)); tone_map_ubo.Create(sizeof(tone_map_shader_data)); transparency_batch_ubo.Create(sizeof(transparency_batch_shader_data)); obj_scene = {}; obj_batch = {}; obj_skinning = {}; obj_scene_ubo.Create(sizeof(obj_scene_shader_data)); obj_batch_ubo.Create(sizeof(obj_batch_shader_data)); obj_skinning_ubo.Create(sizeof(obj_skinning_shader_data)); static const uint8_t empty_texture_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const GLenum target_cube_map_array[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; glGenTextures(1, &empty_texture_2d); gl_state_bind_texture_2d(empty_texture_2d); texture_set_params(GL_TEXTURE_2D, 0, false); glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, empty_texture_data); gl_state_bind_texture_2d(0); glGenTextures(1, &empty_texture_cube_map); gl_state_bind_texture_cube_map(empty_texture_cube_map); texture_set_params(GL_TEXTURE_CUBE_MAP, 0, false); for (int32_t side = 0; side < 6; side++) glCompressedTexImage2D(target_cube_map_array[side], 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8, empty_texture_data); gl_state_bind_texture_cube_map(0); static const vec4 border_color = 0.0f; glGenSamplers(18, samplers); for (int32_t i = 0; i < 18; i++) { GLuint sampler = samplers[i]; glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, i % 2 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); GLuint wrap_s; switch (i / 2 % 3) { case 0: wrap_s = GL_CLAMP_TO_EDGE; break; case 1: wrap_s = GL_REPEAT; break; case 2: wrap_s = GL_MIRRORED_REPEAT; break; } glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wrap_s); GLenum wrap_t; switch (i / 6 % 3) { case 0: wrap_t = GL_CLAMP_TO_EDGE; break; case 1: wrap_t = GL_REPEAT; break; case 2: wrap_t = GL_MIRRORED_REPEAT; break; } glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wrap_t); } GLuint sampler; glGenSamplers(4, render_samplers); sampler = render_samplers[0]; glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); sampler = render_samplers[1]; glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); sampler = render_samplers[2]; glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); sampler = render_samplers[3]; glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); glGenSamplers(3, sprite_samplers); sampler = sprite_samplers[0]; glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); sampler = sprite_samplers[1]; glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_REPEAT); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_REPEAT); glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); sampler = sprite_samplers[2]; glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); } render_context::~render_context() { glDeleteSamplers(3, sprite_samplers); glDeleteSamplers(4, render_samplers); glDeleteSamplers(18, samplers); glDeleteTextures(1, &empty_texture_cube_map); glDeleteTextures(1, &empty_texture_2d); obj_skinning_ubo.Destroy(); obj_batch_ubo.Destroy(); obj_scene_ubo.Destroy(); tone_map_ubo.Destroy(); transparency_batch_ubo.Destroy(); sun_quad_ubo.Destroy(); sss_filter_gaussian_coef_ubo.Destroy(); sprite_scene_ubo.Destroy(); quad_ubo.Destroy(); glitter_batch_ubo.Destroy(); glass_eye_batch_ubo.Destroy(); gaussian_coef_ubo.Destroy(); exposure_measure_ubo.Destroy(); imgfilter_batch_ubo.Destroy(); esm_filter_batch_ubo.Destroy(); filter_scene_ubo.Destroy(); contour_params_ubo.Destroy(); contour_coef_ubo.Destroy(); if (common_vao) { glDeleteVertexArrays(1, &common_vao); common_vao = 0; } if (lens_ghost_vao) { glDeleteVertexArrays(1, &lens_ghost_vao); lens_ghost_vao = 0; } lens_ghost_vbo.Destroy(); if (box_vao) { glDeleteVertexArrays(1, &box_vao); box_vao = 0; } box_vbo.Destroy(); if (sss_data) { delete sss_data; sss_data = 0; } if (render_manager) { delete render_manager; render_manager = 0; } if (disp_manager) { delete disp_manager; disp_manager = 0; } if (draw_state) { delete draw_state; draw_state = 0; } if (camera) { delete camera; camera = 0; } } void render_context::ctrl() { delta_frame_history += get_delta_frame(); float_t v1; delta_frame_history = modff(delta_frame_history, &v1); delta_frame_history_int = (int32_t)v1; if (delta_frame_history < 0.001f) delta_frame_history = 0.0f; else if (1.0f - delta_frame_history < 0.001f) delta_frame_history_int++; rctx_ptr = this; app::TaskWork::ctrl(); sound_ctrl(); file_handler_storage_ctrl(); } void render_context::disp() { rctx_ptr = this; disp_manager->refresh(); sprite_manager_reset_req_list(); draw_state->stats_prev = draw_state->stats; draw_state->stats.reset(); app::TaskWork::disp(); shadow_ptr_get()->Ctrl(); int32_t sprite_index = sprite_manager_get_index(); //sprite_manager_set_index(3); sprite_manager_set_index(0); extern void dw_gui_ctrl_disp(); dw_gui_ctrl_disp(); sprite_manager_set_index(sprite_index); render.ctrl(camera); render_manager->render_all(); render.lens_flare_texture = 0; render.aet_back = 0; render_manager->field_31C = false; app::TaskWork::basic(); } void render_context::free() { shadow_buffer.Free(); screen_buffer.Free(); render_buffer.Free(); reflect_buffer.Free(); } void render_context::init() { auto init_copy_buffer = [&](RenderTexture& src, RenderTexture& dst) { dst.Init(src.GetWidth(), src.GetHeight(), 0, src.color_texture->internal_format, src.depth_texture ? src.depth_texture->internal_format : GL_ZERO); }; RenderTexture& render_buffer = render.rend_texture[0]; RenderTexture& reflect_buffer = render_manager->get_render_texture(1); RenderTexture& shadow_buffer = shadow_ptr_get()->render_textures[1]; init_copy_buffer(reflect_buffer, this->reflect_buffer); init_copy_buffer(render_buffer, this->render_buffer); init_copy_buffer(shadow_buffer, this->shadow_buffer); screen_buffer.Init(sprite_width, sprite_height, 0, GL_RGBA16F, 0); // Was GL_R11F_G11F_B10F } void render_context::light_param_data_light_set(light_param_light * light) { for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) { light_param_light_group* group = &light->group[i]; ::light_set* set = &light_set[i]; for (int32_t j = LIGHT_CHARA; j < LIGHT_MAX; j++) { light_param_light_data* data = &group->data[j]; light_data* light = &set->lights[j]; if (data->has_type) light->set_type(data->type); if (data->has_ambient) light->set_ambient(data->ambient); if (data->has_diffuse) light->set_diffuse(data->diffuse); if (data->has_specular) light->set_specular(data->specular); if (data->has_position) light->set_position(data->position); if (data->has_spot_direction) light->set_spot_direction(data->spot_direction); if (data->has_spot_exponent) light->set_spot_exponent(data->spot_exponent); if (data->has_spot_cutoff) light->set_spot_cutoff(data->spot_cutoff); if (data->has_attenuation) light->set_attenuation(data->attenuation); light->set_clip_plane(data->clip_plane); if (data->has_tone_curve) light->set_tone_curve(data->tone_curve); } } } void render_context::light_param_data_fog_set(light_param_fog* f) { for (int32_t i = FOG_DEPTH; i < FOG_MAX; i++) { light_param_fog_group* group = &f->group[i]; ::fog* fog = &this->fog[i]; if (group->has_type) fog->set_type(group->type); if (group->has_density) fog->set_density(group->density); if (group->has_linear) { fog->set_start(group->linear_start); fog->set_end(group->linear_end); } if (group->has_color) fog->set_color(group->color); } } void render_context::light_param_data_glow_set(light_param_glow* glow) { render.set_auto_exposure(true); render.set_tone_map(TONE_MAP_YCC_EXPONENT); render.reset_saturate_coeff(0, false); render.reset_scene_fade(0); render.reset_tone_trans(0); if (glow->has_exposure) render.set_exposure(glow->exposure); if (glow->has_gamma) render.set_gamma(glow->gamma); if (glow->has_saturate_power) render.set_saturate_power(glow->saturate_power); if (glow->has_saturate_coef) render.set_saturate_coeff(glow->saturate_coef, 0, false); if (glow->has_flare) render.set_lens(glow->flare); if (glow->has_sigma) render.set_radius(glow->sigma); if (glow->has_intensity) render.set_intensity(glow->intensity); if (glow->has_auto_exposure) render.set_auto_exposure(glow->auto_exposure); if (glow->has_tone_map_method) render.set_tone_map(glow->tone_map_method); if (glow->has_fade_color) { vec4 fade_color = glow->fade_color; render.set_scene_fade(fade_color, 0); render.set_scene_fade_blend_func(glow->fade_color_blend_func, 0); } if (glow->has_tone_transform) render.set_tone_trans(glow->tone_transform_start, glow->tone_transform_end, 0); } void render_context::light_param_data_ibl_set( light_param_ibl* ibl, light_param_data_storage* storage) { if (!ibl->ready) return; for (int32_t i = 0, j = -1; i < 5; i++, j++) { gl_state_bind_texture_cube_map(storage->textures[i]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); if (!i) { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); render_context_light_param_data_ibl_set_diffuse(&ibl->diffuse[0], 0); render_context_light_param_data_ibl_set_diffuse(&ibl->diffuse[1], 1); } else { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, ibl->specular[j].max_level); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, 0.0f); render_context_light_param_data_ibl_set_specular(&ibl->specular[j]); } } gl_state_bind_texture_cube_map(0); ::light_set* set = &light_set[LIGHT_SET_MAIN]; set->set_irradiance(ibl->diff_coef[1][0], ibl->diff_coef[1][1], ibl->diff_coef[1][2]); float_t len; vec3 pos; light_data* l = &set->lights[LIGHT_CHARA]; l->get_position(pos); len = vec3::length(pos); if (fabsf(len - 1.0f) < 0.02f) l->set_position(ibl->lit_dir[0]); l->set_ibl_color0(ibl->lit_col[0]); l->set_ibl_color1(ibl->lit_col[2]); l->set_ibl_direction(ibl->lit_dir[0]); l = &set->lights[LIGHT_STAGE]; l->get_position(pos); len = vec3::length(pos); if (fabsf(len - 1.0f) < 0.02f) l->set_position(ibl->lit_dir[1]); l->set_ibl_color0(ibl->lit_col[1]); l->set_ibl_direction(ibl->lit_dir[1]); } void render_context::light_param_data_wind_set(light_param_wind* w) { wind* wind = task_wind->ptr; if (w->has_scale) wind->scale = w->scale; if (w->has_cycle) wind->cycle = w->cycle; if (w->has_rot) { wind->rot_y = w->rot_y; wind->rot_z = w->rot_z; } if (w->has_bias) wind->bias = w->bias; for (int32_t i = 0; i < 16; i++) if (w->has_spc[i]) { wind->spc[i].cos = w->spc[i].cos; wind->spc[i].sin = w->spc[i].sin; } } void render_context::light_param_data_face_set(light_param_face* face) { this->face.set_offset(face->offset); this->face.set_scale(face->scale); this->face.set_position(face->position); this->face.set_direction(face->direction); } void render_context::resize(int32_t render_width, int32_t render_height, int32_t sprite_width, int32_t sprite_height, int32_t screen_width, int32_t screen_height) { bool render_res_change = render.inner_width != render_width || render.inner_height != render_height; bool sprite_res_change = this->sprite_width != sprite_width || this->sprite_height != sprite_height; bool screen_res_change = this->screen_width != screen_width || this->screen_height != screen_height; if (!render_res_change && !sprite_res_change && !screen_res_change) return; this->sprite_width = sprite_width; this->sprite_height = sprite_height; screen_x_offset = (screen_width - sprite_width) / 2 + (screen_width - sprite_width) % 2; screen_y_offset = (screen_height - sprite_height) / 2 + (screen_height - sprite_height) % 2; this->screen_width = screen_width; this->screen_height = screen_height; if (render_res_change) render.resize(render_width, render_height); if (sprite_res_change) render_manager->resize(sprite_width, sprite_height); if (render_res_change) litproj->resize(render_width, render_height); sprite_manager_set_res((double_t)sprite_width / (double_t)sprite_height, sprite_width, sprite_height); if (render_res_change) { free(); init(); } } static void render_context_light_param_data_ibl_set_diffuse(light_param_ibl_diffuse* diffuse, int32_t level) { int32_t size = diffuse->size; size_t data_size = size; data_size = 4 * data_size * data_size; glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 0]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 1]); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 2]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 3]); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 4]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 5]); } static void render_context_light_param_data_ibl_set_specular(light_param_ibl_specular* specular) { int32_t size = specular->size; int32_t max_level = specular->max_level; for (int32_t i = 0; i <= max_level; i++, size /= 2) { std::vector& data = specular->data[i]; size_t data_size = size; data_size = 4 * data_size * data_size; glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 0]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 1]); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 2]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 3]); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 4]); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, i, GL_RGBA16F, size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 5]); } }