You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-08 12:40:44 +00:00
Implement motion vectors in mobile renderer
This commit is contained in:
@@ -320,6 +320,10 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
|
||||
format = RenderingDevice::DATA_FORMAT_B8G8R8A8_UINT;
|
||||
usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
break;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
format = RenderingDevice::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
break;
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
format = RenderingDevice::DATA_FORMAT_D32_SFLOAT;
|
||||
usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
@@ -166,6 +166,34 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu
|
||||
ERR_FAIL_NULL(render_buffers); // Huh? really?
|
||||
}
|
||||
|
||||
RID RendererSceneRenderImplementation::RenderForwardMobile::RenderBufferDataForwardMobile::get_motion_vectors_fb() {
|
||||
ERR_FAIL_NULL_V(render_buffers, RID());
|
||||
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
ERR_FAIL_NULL_V(texture_storage, RID());
|
||||
|
||||
RID velocity = render_buffers->get_velocity_buffer(false);
|
||||
RID velocity_depth = render_buffers->get_velocity_depth_buffer();
|
||||
|
||||
if (velocity.is_valid() && velocity_depth.is_valid()) {
|
||||
Vector<RID> textures;
|
||||
textures.push_back(velocity);
|
||||
textures.push_back(velocity_depth);
|
||||
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
passes.push_back(pass);
|
||||
|
||||
uint32_t view_count = render_buffers->get_view_count();
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
|
||||
}
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
|
||||
ERR_FAIL_NULL_V(render_buffers, RID());
|
||||
|
||||
@@ -776,19 +804,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
|
||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||
|
||||
/* TODO
|
||||
// check if we need motion vectors
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
|
||||
p_render_data->scene_data->calculate_motion_vectors = true;
|
||||
} else if (_compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) {
|
||||
p_render_data->scene_data->calculate_motion_vectors = true;
|
||||
} else if (render target has velocity override) { // TODO
|
||||
p_render_data->scene_data->calculate_motion_vectors = true;
|
||||
} else {
|
||||
p_render_data->scene_data->calculate_motion_vectors = false;
|
||||
}
|
||||
*/
|
||||
p_render_data->scene_data->calculate_motion_vectors = false; // for now, not yet supported...
|
||||
p_render_data->scene_data->calculate_motion_vectors = RendererRD::TextureStorage::get_singleton()->render_target_get_override_velocity(rb->get_render_target()).is_valid();
|
||||
|
||||
p_render_data->scene_data->directional_light_count = 0;
|
||||
p_render_data->scene_data->opaque_prepass_threshold = 0.0;
|
||||
@@ -1098,6 +1114,25 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
breadcrumb = RDD::BreadcrumbMarker::REFLECTION_PROBES;
|
||||
}
|
||||
|
||||
if (rb_data.is_valid() && p_render_data->scene_data->calculate_motion_vectors) {
|
||||
RID mv_fb = rb_data->get_motion_vectors_fb();
|
||||
|
||||
if (mv_fb.is_valid()) {
|
||||
RENDER_TIMESTAMP("Render Motion Vectors");
|
||||
|
||||
Vector<Color> mv_pass_clear;
|
||||
mv_pass_clear.push_back(Color(0, 0, 0, 0));
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Motion Vectors");
|
||||
|
||||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_MOTION_VECTORS, rp_uniform_set, base_specialization);
|
||||
_render_list_with_draw_list(&render_list_params, mv_fb, RD::DRAW_CLEAR_ALL, mv_pass_clear);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
}
|
||||
|
||||
// opaque pass
|
||||
RD::get_singleton()->draw_command_begin_label("Render Opaque");
|
||||
|
||||
@@ -1871,14 +1906,22 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint
|
||||
scene_state.instance_data[p_render_list].resize(p_offset + element_total);
|
||||
rl->element_info.resize(p_offset + element_total);
|
||||
|
||||
uint64_t frame = RSG::rasterizer->get_frame_number();
|
||||
|
||||
for (uint32_t i = 0; i < element_total; i++) {
|
||||
GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset];
|
||||
GeometryInstanceForwardMobile *inst = surface->owner;
|
||||
|
||||
SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset];
|
||||
|
||||
if (inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame) {
|
||||
inst->prev_transform = inst->transform;
|
||||
inst->prev_transform_dirty = false;
|
||||
}
|
||||
|
||||
if (inst->store_transform_cache) {
|
||||
RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform);
|
||||
RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform);
|
||||
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
// Split the origin into two components, the float approximation and the missing precision.
|
||||
@@ -1889,6 +1932,7 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint
|
||||
#endif
|
||||
} else {
|
||||
RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform);
|
||||
RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform);
|
||||
}
|
||||
|
||||
instance_data.flags = inst->flags_cache;
|
||||
@@ -2068,7 +2112,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
|
||||
}
|
||||
|
||||
// ADD Element
|
||||
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
|
||||
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_MOTION_VECTORS) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
|
||||
#else
|
||||
@@ -2155,6 +2199,9 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list,
|
||||
case PASS_MODE_DEPTH_MATERIAL: {
|
||||
_render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
|
||||
} break;
|
||||
case PASS_MODE_MOTION_VECTORS: {
|
||||
_render_list_template<PASS_MODE_MOTION_VECTORS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2170,6 +2217,7 @@ void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_pa
|
||||
template <RenderForwardMobile::PassMode p_pass_mode>
|
||||
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
|
||||
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
|
||||
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
|
||||
|
||||
RD::DrawListID draw_list = p_draw_list;
|
||||
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
|
||||
@@ -2215,11 +2263,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
push_constant.base_index = i + p_params->element_offset;
|
||||
|
||||
if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) {
|
||||
push_constant.uv_offset[0] = p_params->uv_offset.x;
|
||||
push_constant.uv_offset[1] = p_params->uv_offset.y;
|
||||
push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16;
|
||||
push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x);
|
||||
} else {
|
||||
push_constant.uv_offset[0] = 0.0;
|
||||
push_constant.uv_offset[1] = 0.0;
|
||||
push_constant.uv_offset = 0;
|
||||
}
|
||||
|
||||
if (shadow_pass) {
|
||||
@@ -2301,6 +2348,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
|
||||
pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
|
||||
} break;
|
||||
case PASS_MODE_MOTION_VECTORS: {
|
||||
pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_MOTION_VECTORS_MULTIVIEW;
|
||||
}
|
||||
}
|
||||
|
||||
pipeline_key.framebuffer_format_id = framebuffer_format;
|
||||
@@ -2319,9 +2369,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
// Skeleton and blend shape.
|
||||
uint64_t input_mask = shader->get_vertex_input_mask(pipeline_key.version, pipeline_key.ubershader);
|
||||
if (surf->owner->mesh_instance.is_valid()) {
|
||||
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, false, vertex_array_rd, vertex_format);
|
||||
mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format);
|
||||
} else {
|
||||
mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, false, vertex_array_rd, vertex_format);
|
||||
mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format);
|
||||
}
|
||||
|
||||
pipeline_key.vertex_format_id = vertex_format;
|
||||
@@ -2388,6 +2438,15 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
prev_material_uniform_set = material_uniform_set;
|
||||
}
|
||||
|
||||
if (surf->owner->base_flags & INSTANCE_DATA_FLAG_PARTICLES) {
|
||||
particles_storage->particles_get_instance_buffer_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
|
||||
} else if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) {
|
||||
mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
|
||||
} else {
|
||||
push_constant.multimesh_motion_vectors_current_offset = 0;
|
||||
push_constant.multimesh_motion_vectors_previous_offset = 0;
|
||||
}
|
||||
|
||||
size_t push_constant_size = 0;
|
||||
if (pipeline_key.ubershader) {
|
||||
push_constant_size = sizeof(SceneState::PushConstant);
|
||||
@@ -2439,6 +2498,17 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base
|
||||
return ginstance;
|
||||
}
|
||||
|
||||
void RendererSceneRenderImplementation::RenderForwardMobile::GeometryInstanceForwardMobile::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
|
||||
uint64_t frame = RSG::rasterizer->get_frame_number();
|
||||
if (frame != prev_transform_change_frame) {
|
||||
prev_transform = transform;
|
||||
prev_transform_change_frame = frame;
|
||||
prev_transform_dirty = true;
|
||||
}
|
||||
|
||||
RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabb);
|
||||
}
|
||||
|
||||
void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
|
||||
lightmap_instance = p_lightmap_instance;
|
||||
lightmap_uv_scale = p_lightmap_uv_scale;
|
||||
@@ -2847,6 +2917,7 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
|
||||
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
|
||||
|
||||
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
|
||||
if (false) { // 2D particles
|
||||
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
|
||||
|
||||
@@ -89,6 +89,8 @@ private:
|
||||
virtual void free_data() override;
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
|
||||
|
||||
RID get_motion_vectors_fb();
|
||||
|
||||
private:
|
||||
RenderSceneBuffersRD *render_buffers = nullptr;
|
||||
};
|
||||
@@ -108,6 +110,7 @@ private:
|
||||
// PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
// PASS_MODE_SDF,
|
||||
PASS_MODE_MOTION_VECTORS,
|
||||
};
|
||||
|
||||
struct RenderElementInfo;
|
||||
@@ -198,14 +201,16 @@ private:
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
float uv_offset[2];
|
||||
uint32_t uv_offset;
|
||||
uint32_t base_index;
|
||||
uint32_t pad;
|
||||
uint32_t multimesh_motion_vectors_current_offset;
|
||||
uint32_t multimesh_motion_vectors_previous_offset;
|
||||
PushConstantUbershader ubershader;
|
||||
};
|
||||
|
||||
struct InstanceData {
|
||||
float transform[16];
|
||||
float prev_transform[16];
|
||||
uint32_t flags;
|
||||
uint32_t instance_uniforms_ofs; // Base offset in global buffer for instance variables.
|
||||
uint32_t gi_offset; // GI information when using lightmapping (VCT or lightmap index).
|
||||
@@ -497,6 +502,10 @@ protected:
|
||||
uint32_t instance_count = 0;
|
||||
uint32_t trail_steps = 1;
|
||||
|
||||
uint64_t prev_transform_change_frame = UINT_MAX;
|
||||
bool prev_transform_dirty = true;
|
||||
Transform3D prev_transform;
|
||||
|
||||
// lightmap
|
||||
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
|
||||
RID lightmap_instance;
|
||||
@@ -524,6 +533,7 @@ protected:
|
||||
|
||||
virtual void _mark_dirty() override;
|
||||
|
||||
virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
|
||||
virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
|
||||
virtual void set_lightmap_capture(const Color *p_sh9) override;
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
|
||||
// Alpha does not write to depth.
|
||||
@@ -322,7 +322,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
|
||||
// Do not use this version (error case).
|
||||
}
|
||||
} else {
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
// Contains nothing.
|
||||
@@ -502,6 +502,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
|
||||
}
|
||||
|
||||
Vector<RD::PipelineImmutableSampler> immutable_samplers;
|
||||
@@ -711,7 +712,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 10;
|
||||
actions.base_varying_index = 14;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
SHADER_VERSION_COLOR_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_SHADOW_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_MOTION_VECTORS_MULTIVIEW,
|
||||
|
||||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
@@ -66,6 +66,15 @@ layout(location = 10) in uvec4 bone_attrib;
|
||||
layout(location = 11) in vec4 weight_attrib;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_RENDER_MOTION_VECTORS)
|
||||
layout(location = 12) in vec4 previous_vertex_attrib;
|
||||
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
layout(location = 13) in vec4 previous_normal_attrib;
|
||||
#endif
|
||||
|
||||
#endif // MODE_RENDER_MOTION_VECTORS
|
||||
|
||||
vec3 oct_to_vec3(vec2 e) {
|
||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||
float t = max(-v.z, 0.0);
|
||||
@@ -127,6 +136,11 @@ layout(location = 9) out highp float dp_clip;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MODE_RENDER_MOTION_VECTORS)
|
||||
layout(location = 12) out highp vec4 screen_position;
|
||||
layout(location = 13) out highp vec4 prev_screen_position;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
#extension GL_EXT_multiview : enable
|
||||
#define ViewIndex gl_ViewIndex
|
||||
@@ -185,15 +199,77 @@ uint multimesh_stride() {
|
||||
return stride;
|
||||
}
|
||||
|
||||
void main() {
|
||||
void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position, vec3 p_compressed_aabb_size,
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
vec4 p_normal_in,
|
||||
#ifdef NORMAL_USED
|
||||
out vec3 r_normal,
|
||||
#endif
|
||||
out vec3 r_tangent,
|
||||
out vec3 r_binormal,
|
||||
#endif
|
||||
out vec3 r_vertex) {
|
||||
|
||||
r_vertex = p_vertex_in.xyz * p_compressed_aabb_size + p_compressed_aabb_position;
|
||||
#ifdef NORMAL_USED
|
||||
r_normal = oct_to_vec3(p_normal_in.xy * 2.0 - 1.0);
|
||||
#endif
|
||||
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||
|
||||
float binormal_sign;
|
||||
|
||||
// This works because the oct value (0, 1) maps onto (0, 0, -1) which encodes to (1, 1).
|
||||
// Accordingly, if p_normal_in.z contains octahedral values, it won't equal (0, 1).
|
||||
if (p_normal_in.z > 0.0 || p_normal_in.w < 1.0) {
|
||||
// Uncompressed format.
|
||||
vec2 signed_tangent_attrib = p_normal_in.zw * 2.0 - 1.0;
|
||||
r_tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
|
||||
binormal_sign = sign(signed_tangent_attrib.y);
|
||||
r_binormal = normalize(cross(r_normal, r_tangent) * binormal_sign);
|
||||
} else {
|
||||
// Compressed format.
|
||||
float angle = p_vertex_in.w;
|
||||
binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller.
|
||||
angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably.
|
||||
vec3 axis = r_normal;
|
||||
axis_angle_to_tbn(axis, angle, r_tangent, r_binormal, r_normal);
|
||||
r_binormal *= binormal_sign;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void vertex_shader(in vec3 vertex,
|
||||
#ifdef NORMAL_USED
|
||||
in vec3 normal,
|
||||
#endif
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
in vec3 tangent,
|
||||
in vec3 binormal,
|
||||
#endif
|
||||
in uint instance_index, in uint multimesh_offset, in mat4 model_matrix,
|
||||
#ifdef MODE_DUAL_PARABOLOID
|
||||
in float dual_paraboloid_side,
|
||||
in float z_far,
|
||||
#endif
|
||||
#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL)
|
||||
in uint scene_flags,
|
||||
#endif
|
||||
in mat4 projection_matrix,
|
||||
in mat4 inv_projection_matrix,
|
||||
#ifdef USE_MULTIVIEW
|
||||
in vec4 scene_eye_offset,
|
||||
#endif
|
||||
in mat4 view_matrix,
|
||||
in mat4 inv_view_matrix,
|
||||
in vec2 viewport_size,
|
||||
in uint scene_directional_light_count,
|
||||
out vec4 screen_position_output) {
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
#if defined(COLOR_USED)
|
||||
color_interp = color_attrib;
|
||||
#endif
|
||||
|
||||
mat4 model_matrix = instances.data[draw_call.instance_index].transform;
|
||||
mat4 inv_view_matrix = scene_data.inv_view_matrix;
|
||||
|
||||
#ifdef USE_DOUBLE_PRECISION
|
||||
vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]);
|
||||
model_matrix[0][3] = 0.0;
|
||||
@@ -206,7 +282,7 @@ void main() {
|
||||
#endif
|
||||
|
||||
mat3 model_normal_matrix;
|
||||
if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
|
||||
model_normal_matrix = transpose(inverse(mat3(model_matrix)));
|
||||
} else {
|
||||
model_normal_matrix = mat3(model_matrix);
|
||||
@@ -219,7 +295,7 @@ void main() {
|
||||
//multimesh, instances are for it
|
||||
|
||||
#ifdef USE_PARTICLE_TRAILS
|
||||
uint trail_size = (instances.data[draw_call.instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;
|
||||
uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;
|
||||
uint stride = 3 + 1 + 1; //particles always uses this format
|
||||
|
||||
uint offset = trail_size * stride * gl_InstanceIndex;
|
||||
@@ -264,7 +340,7 @@ void main() {
|
||||
|
||||
#else
|
||||
uint stride = multimesh_stride();
|
||||
uint offset = stride * gl_InstanceIndex;
|
||||
uint offset = stride * (gl_InstanceIndex + multimesh_offset);
|
||||
|
||||
if (sc_multimesh_format_2d()) {
|
||||
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
@@ -300,33 +376,6 @@ void main() {
|
||||
model_normal_matrix = model_normal_matrix * mat3(matrix);
|
||||
}
|
||||
|
||||
vec3 vertex = vertex_angle_attrib.xyz * instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz + instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz;
|
||||
#ifdef NORMAL_USED
|
||||
vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0);
|
||||
#endif
|
||||
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||
|
||||
vec3 binormal;
|
||||
float binormal_sign;
|
||||
vec3 tangent;
|
||||
if (axis_tangent_attrib.z > 0.0 || axis_tangent_attrib.w < 1.0) {
|
||||
// Uncompressed format.
|
||||
vec2 signed_tangent_attrib = axis_tangent_attrib.zw * 2.0 - 1.0;
|
||||
tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
|
||||
binormal_sign = sign(signed_tangent_attrib.y);
|
||||
binormal = normalize(cross(normal, tangent) * binormal_sign);
|
||||
} else {
|
||||
// Compressed format.
|
||||
float angle = vertex_angle_attrib.w;
|
||||
binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller.
|
||||
angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably.
|
||||
vec3 axis = normal;
|
||||
axis_angle_to_tbn(axis, angle, tangent, binormal, normal);
|
||||
binormal *= binormal_sign;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UV_USED
|
||||
uv_interp = uv_attrib;
|
||||
#endif
|
||||
@@ -335,7 +384,7 @@ void main() {
|
||||
uv2_interp = uv2_attrib;
|
||||
#endif
|
||||
|
||||
vec4 uv_scale = instances.data[draw_call.instance_index].uv_scale;
|
||||
vec4 uv_scale = instances.data[instance_index].uv_scale;
|
||||
|
||||
if (uv_scale != vec4(0.0)) { // Compression enabled
|
||||
#ifdef UV_USED
|
||||
@@ -351,14 +400,10 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
|
||||
mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
|
||||
vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
|
||||
vec3 eye_offset = scene_eye_offset.xyz;
|
||||
#else
|
||||
mat4 projection_matrix = scene_data.projection_matrix;
|
||||
mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
|
||||
vec3 eye_offset = vec3(0.0, 0.0, 0.0);
|
||||
#endif //USE_MULTIVIEW
|
||||
#endif // USE_MULTIVIEW
|
||||
|
||||
//using world coordinates
|
||||
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
|
||||
@@ -383,10 +428,10 @@ void main() {
|
||||
|
||||
float roughness = 1.0;
|
||||
|
||||
mat4 modelview = scene_data.view_matrix * model_matrix;
|
||||
mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix;
|
||||
mat4 read_view_matrix = scene_data.view_matrix;
|
||||
vec2 read_viewport_size = scene_data.viewport_size;
|
||||
mat4 modelview = view_matrix * model_matrix;
|
||||
mat3 modelview_normal = mat3(view_matrix) * model_normal_matrix;
|
||||
mat4 read_view_matrix = view_matrix;
|
||||
vec2 read_viewport_size = viewport_size;
|
||||
|
||||
{
|
||||
#CODE : VERTEX
|
||||
@@ -406,8 +451,8 @@ void main() {
|
||||
}
|
||||
vertex = mat3(inv_view_matrix * modelview) * vertex;
|
||||
vec3 temp_precision;
|
||||
vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision);
|
||||
vertex = mat3(scene_data.view_matrix) * vertex;
|
||||
vertex += double_add_vec3(model_origin, model_precision, inv_view_matrix[3].xyz, view_precision, temp_precision);
|
||||
vertex = mat3(view_matrix) * vertex;
|
||||
#else
|
||||
vertex = (modelview * vec4(vertex, 1.0)).xyz;
|
||||
#endif
|
||||
@@ -425,14 +470,14 @@ void main() {
|
||||
//using world coordinates
|
||||
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
|
||||
|
||||
vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz;
|
||||
vertex = (view_matrix * vec4(vertex, 1.0)).xyz;
|
||||
#ifdef NORMAL_USED
|
||||
normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz;
|
||||
normal = (view_matrix * vec4(normal, 0.0)).xyz;
|
||||
#endif
|
||||
|
||||
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
|
||||
binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz;
|
||||
tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz;
|
||||
binormal = (view_matrix * vec4(binormal, 0.0)).xyz;
|
||||
tangent = (view_matrix * vec4(tangent, 0.0)).xyz;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -461,7 +506,7 @@ void main() {
|
||||
specular_light_interp = vec4(0.0);
|
||||
|
||||
uint omni_light_count = sc_omni_lights(8);
|
||||
uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights;
|
||||
uvec2 omni_light_indices = instances.data[instance_index].omni_lights;
|
||||
for (uint i = 0; i < omni_light_count; i++) {
|
||||
uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF);
|
||||
if (i > 0 && light_index == 0xFF) {
|
||||
@@ -472,7 +517,7 @@ void main() {
|
||||
}
|
||||
|
||||
uint spot_light_count = sc_spot_lights(8);
|
||||
uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights;
|
||||
uvec2 spot_light_indices = instances.data[instance_index].spot_lights;
|
||||
for (uint i = 0; i < spot_light_count; i++) {
|
||||
uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF);
|
||||
if (i > 0 && light_index == 0xFF) {
|
||||
@@ -482,18 +527,18 @@ void main() {
|
||||
light_process_spot_vertex(light_index, vertex, view, normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
|
||||
}
|
||||
|
||||
uint directional_lights_count = sc_directional_lights(scene_data.directional_light_count);
|
||||
uint directional_lights_count = sc_directional_lights(scene_directional_light_count);
|
||||
if (directional_lights_count > 0) {
|
||||
// We process the first directional light separately as it may have shadows.
|
||||
vec3 directional_diffuse = vec3(0.0);
|
||||
vec3 directional_specular = vec3(0.0);
|
||||
|
||||
for (uint i = 0; i < directional_lights_count; i++) {
|
||||
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
|
||||
if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
|
||||
continue; // Not masked, skip.
|
||||
}
|
||||
|
||||
if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
|
||||
if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
|
||||
continue; // Statically baked light and object uses lightmap, skip.
|
||||
}
|
||||
if (i == 0) {
|
||||
@@ -539,7 +584,7 @@ void main() {
|
||||
|
||||
#ifdef MODE_DUAL_PARABOLOID
|
||||
|
||||
vertex_interp.z *= scene_data.dual_paraboloid_side;
|
||||
vertex_interp.z *= dual_paraboloid_side;
|
||||
|
||||
dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
|
||||
|
||||
@@ -549,7 +594,7 @@ void main() {
|
||||
float distance = length(vtx);
|
||||
vtx = normalize(vtx);
|
||||
vtx.xy /= 1.0 - vtx.z;
|
||||
vtx.z = (distance / scene_data.z_far);
|
||||
vtx.z = (distance / z_far);
|
||||
vtx.z = vtx.z * 2.0 - 1.0;
|
||||
vertex_interp = vtx;
|
||||
|
||||
@@ -568,14 +613,14 @@ void main() {
|
||||
#endif
|
||||
|
||||
#ifdef MODE_RENDER_DEPTH
|
||||
if (bool(scene_data.flags & SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS)) {
|
||||
if (bool(scene_flags & SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS)) {
|
||||
if (gl_Position.z >= 0.9999) {
|
||||
gl_Position.z = 0.9999;
|
||||
}
|
||||
}
|
||||
#endif // MODE_RENDER_DEPTH
|
||||
#ifdef MODE_RENDER_MATERIAL
|
||||
if (bool(scene_data.flags & SCENE_DATA_FLAGS_USE_UV2_MATERIAL)) {
|
||||
if (bool(scene_flags & SCENE_DATA_FLAGS_USE_UV2_MATERIAL)) {
|
||||
vec2 uv_dest_attrib;
|
||||
if (uv_scale != vec4(0.0)) {
|
||||
uv_dest_attrib = (uv2_attrib.xy - 0.5) * uv_scale.zw;
|
||||
@@ -583,11 +628,128 @@ void main() {
|
||||
uv_dest_attrib = uv2_attrib.xy;
|
||||
}
|
||||
|
||||
gl_Position.xy = (uv_dest_attrib + draw_call.uv_offset) * 2.0 - 1.0;
|
||||
vec2 uv_offset = unpackHalf2x16(draw_call.uv_offset);
|
||||
gl_Position.xy = (uv_dest_attrib + uv_offset) * 2.0 - 1.0;
|
||||
gl_Position.z = 0.00001;
|
||||
gl_Position.w = 1.0;
|
||||
}
|
||||
#endif // MODE_RENDER_MATERIAL
|
||||
#ifdef MODE_RENDER_MOTION_VECTORS
|
||||
screen_position_output = gl_Position;
|
||||
#endif // MODE_RENDER_MOTION_VECTORS
|
||||
}
|
||||
|
||||
void main() {
|
||||
#if defined(MODE_RENDER_MOTION_VECTORS)
|
||||
vec3 prev_vertex;
|
||||
#ifdef NORMAL_USED
|
||||
vec3 prev_normal;
|
||||
#endif
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
vec3 prev_tangent;
|
||||
vec3 prev_binormal;
|
||||
#endif
|
||||
|
||||
_unpack_vertex_attributes(
|
||||
previous_vertex_attrib,
|
||||
instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz,
|
||||
instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz,
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
previous_normal_attrib,
|
||||
#ifdef NORMAL_USED
|
||||
prev_normal,
|
||||
#endif
|
||||
prev_tangent,
|
||||
prev_binormal,
|
||||
#endif
|
||||
prev_vertex);
|
||||
|
||||
vertex_shader(prev_vertex,
|
||||
#ifdef NORMAL_USED
|
||||
prev_normal,
|
||||
#endif
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
prev_tangent,
|
||||
prev_binormal,
|
||||
#endif
|
||||
draw_call.instance_index, draw_call.multimesh_motion_vectors_previous_offset, instances.data[draw_call.instance_index].prev_transform,
|
||||
#ifdef MODE_DUAL_PARABOLOID
|
||||
scene_data_block.prev_data.dual_paraboloid_side,
|
||||
scene_data_block.prev_data.z_far,
|
||||
#endif
|
||||
#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL)
|
||||
scene_data_block.prev_data.flags,
|
||||
#endif
|
||||
#ifdef USE_MULTIVIEW
|
||||
scene_data_block.prev_data.projection_matrix_view[ViewIndex],
|
||||
scene_data_block.prev_data.inv_projection_matrix_view[ViewIndex],
|
||||
scene_data_block.prev_data.eye_offset[ViewIndex],
|
||||
#else
|
||||
scene_data_block.prev_data.projection_matrix,
|
||||
scene_data_block.prev_data.inv_projection_matrix,
|
||||
#endif
|
||||
scene_data_block.prev_data.view_matrix,
|
||||
scene_data_block.prev_data.inv_view_matrix,
|
||||
scene_data_block.prev_data.viewport_size,
|
||||
scene_data_block.prev_data.directional_light_count,
|
||||
prev_screen_position);
|
||||
#else
|
||||
// Unused output.
|
||||
vec4 screen_position;
|
||||
#endif // MODE_RENDER_MOTION_VECTORS
|
||||
|
||||
vec3 vertex;
|
||||
#ifdef NORMAL_USED
|
||||
vec3 normal;
|
||||
#endif
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
vec3 tangent;
|
||||
vec3 binormal;
|
||||
#endif
|
||||
|
||||
_unpack_vertex_attributes(
|
||||
vertex_angle_attrib,
|
||||
instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz,
|
||||
instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz,
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
axis_tangent_attrib,
|
||||
#ifdef NORMAL_USED
|
||||
normal,
|
||||
#endif
|
||||
tangent,
|
||||
binormal,
|
||||
#endif
|
||||
vertex);
|
||||
|
||||
vertex_shader(vertex,
|
||||
#ifdef NORMAL_USED
|
||||
normal,
|
||||
#endif
|
||||
#if defined(NORMAL_USED) || defined(TANGENT_USED)
|
||||
tangent,
|
||||
binormal,
|
||||
#endif
|
||||
draw_call.instance_index, draw_call.multimesh_motion_vectors_current_offset, instances.data[draw_call.instance_index].transform,
|
||||
#ifdef MODE_DUAL_PARABOLOID
|
||||
scene_data_block.data.dual_paraboloid_side,
|
||||
scene_data_block.data.z_far,
|
||||
#endif
|
||||
#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL)
|
||||
scene_data_block.data.flags,
|
||||
#endif
|
||||
#ifdef USE_MULTIVIEW
|
||||
scene_data_block.data.projection_matrix_view[ViewIndex],
|
||||
scene_data_block.data.inv_projection_matrix_view[ViewIndex],
|
||||
scene_data_block.data.eye_offset[ViewIndex],
|
||||
#else
|
||||
scene_data_block.data.projection_matrix,
|
||||
scene_data_block.data.inv_projection_matrix,
|
||||
#endif
|
||||
scene_data_block.data.view_matrix,
|
||||
scene_data_block.data.inv_view_matrix,
|
||||
scene_data_block.data.viewport_size,
|
||||
scene_data_block.data.directional_light_count,
|
||||
screen_position);
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
@@ -644,6 +806,11 @@ layout(location = 9) highp in float dp_clip;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MODE_RENDER_MOTION_VECTORS)
|
||||
layout(location = 12) in highp vec4 screen_position;
|
||||
layout(location = 13) in highp vec4 prev_screen_position;
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHTMAP
|
||||
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
|
||||
float w0(float a) {
|
||||
@@ -1970,4 +2137,15 @@ void main() {
|
||||
#endif //MODE_MULTIPLE_RENDER_TARGETS
|
||||
|
||||
#endif //MODE_RENDER_DEPTH
|
||||
|
||||
#ifdef MODE_RENDER_MOTION_VECTORS
|
||||
// These motion vectors are in NDC space (as opposed to screen space) to fit the OpenXR XR_FB_space_warp specification.
|
||||
// https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_FB_space_warp
|
||||
|
||||
vec3 ndc = screen_position.xyz / screen_position.w;
|
||||
ndc.y = -ndc.y;
|
||||
vec3 prev_ndc = prev_screen_position.xyz / prev_screen_position.w;
|
||||
prev_ndc.y = -prev_ndc.y;
|
||||
frag_color = vec4(ndc - prev_ndc, 0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
#define USING_MOBILE_RENDERER
|
||||
|
||||
layout(push_constant, std430) uniform DrawCall {
|
||||
vec2 uv_offset;
|
||||
uint uv_offset;
|
||||
uint instance_index;
|
||||
uint pad;
|
||||
uint multimesh_motion_vectors_current_offset;
|
||||
uint multimesh_motion_vectors_previous_offset;
|
||||
#ifdef UBERSHADER
|
||||
uint sc_packed_0;
|
||||
uint sc_packed_1;
|
||||
@@ -303,6 +304,7 @@ scene_data_block;
|
||||
|
||||
struct InstanceData {
|
||||
highp mat4 transform; // 64 - 64
|
||||
highp mat4 prev_transform;
|
||||
uint flags; // 04 - 68
|
||||
uint instance_uniforms_ofs; // Base offset in global buffer for instance variables. // 04 - 72
|
||||
uint gi_offset; // GI information when using lightmapping (VCT or lightmap index). // 04 - 76
|
||||
|
||||
@@ -702,6 +702,12 @@ RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer)
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_velocity_depth_buffer() {
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
RID velocity_depth = texture_storage->render_target_get_override_velocity_depth(render_target);
|
||||
return velocity_depth;
|
||||
}
|
||||
|
||||
uint32_t RenderSceneBuffersRD::get_color_usage_bits(bool p_resolve, bool p_msaa, bool p_storage) {
|
||||
DEV_ASSERT((!p_resolve && !p_msaa) || (p_resolve != p_msaa));
|
||||
|
||||
|
||||
@@ -312,6 +312,8 @@ public:
|
||||
RID get_velocity_buffer(bool p_get_msaa);
|
||||
RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer);
|
||||
|
||||
RID get_velocity_depth_buffer();
|
||||
|
||||
// Samplers adjusted with the mipmap bias that is best fit for the configuration of these render buffers.
|
||||
|
||||
_FORCE_INLINE_ RendererRD::MaterialStorage::Samplers get_samplers() const {
|
||||
|
||||
@@ -3526,6 +3526,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color
|
||||
rt->overridden.color = p_color_texture;
|
||||
rt->overridden.depth = p_depth_texture;
|
||||
rt->overridden.velocity = p_velocity_texture;
|
||||
rt->overridden.velocity_depth = p_velocity_depth_texture;
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_override_color(RID p_render_target) const {
|
||||
@@ -3587,6 +3588,13 @@ RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_targe
|
||||
}
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_override_velocity_depth(RID p_render_target) const {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL_V(rt, RID());
|
||||
|
||||
return rt->overridden.velocity_depth;
|
||||
}
|
||||
|
||||
void RendererRD::TextureStorage::render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_NULL(rt);
|
||||
|
||||
@@ -399,6 +399,7 @@ private:
|
||||
RID color;
|
||||
RID depth;
|
||||
RID velocity;
|
||||
RID velocity_depth;
|
||||
|
||||
// In a multiview scenario, which is the most likely where we
|
||||
// override our destination textures, we need to obtain slices
|
||||
@@ -791,7 +792,7 @@ public:
|
||||
RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
|
||||
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
|
||||
RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;
|
||||
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
|
||||
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override;
|
||||
|
||||
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
|
||||
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
|
||||
|
||||
Reference in New Issue
Block a user