Skip to content

Commit

Permalink
Permit overriding the projection matrix passed to shaders without aff…
Browse files Browse the repository at this point in the history
…ecting culling logic.
  • Loading branch information
lyuma authored and fire committed Jun 5, 2024
1 parent 8a4e882 commit 7e3c501
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 3 deletions.
6 changes: 6 additions & 0 deletions doc/classes/Camera3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@
<member name="near" type="float" setter="set_near" getter="get_near" default="0.05">
The distance to the near culling boundary for this camera relative to its local Z axis. Lower values allow the camera to see objects more up close to its origin, at the cost of lower precision across the [i]entire[/i] range. Values lower than the default can lead to increased Z-fighting.
</member>
<member name="override_projection" type="Projection" setter="set_override_projection" getter="get_override_projection" default="Projection(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)">
If set to a non-zero Projection, overrides the view-projection matrix passed to shaders with this custom matrix. This *only* overrides the projection passed to shaders on the GPU. The [constant PROJECTION_PERSPECTIVE], [constant PROJECTION_ORTHOGONAL] or [constant PROJECTION_FRUSTUM] values are still used for CPU-side operations such as culling, which can be used to provide a separate culling frustum.
To clear the overridden projection, set to [code]Projection(Vector4.ZERO, Vector4.ZERO, Vector4.ZERO, Vector4.ZERO)[/code].

[member override_projection] does not currently support stereo cameras.
</member>
<member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera3D.ProjectionType" default="0">
The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size.
</member>
Expand Down
11 changes: 11 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,17 @@
Sets camera to use orthogonal projection, also known as orthographic projection. Objects remain the same size on the screen no matter how far away they are.
</description>
</method>
<method name="camera_set_override_projection">
<return type="void" />
<param index="0" name="camera" type="RID" />
<param index="1" name="matrix" type="Projection" />
<description>
If set to a non-zero Projection, overrides the view-projection matrix passed to shaders with this custom matrix. This *only* overrides the projection passed to shaders on the GPU. The [method camera_set_frustum], [method camera_set_orthogonal] or [method camera_set_frustum] values are still used for CPU-side operations such as culling, which can be used to provide a separate culling frustum.
To clear the overridden projection, set to [code]Projection(Vector4.ZERO, Vector4.ZERO, Vector4.ZERO, Vector4.ZERO)[/code].

[method camera_set_override_projection] does not currently support stereo cameras.
</description>
</method>
<method name="camera_set_perspective">
<return type="void" />
<param index="0" name="camera" type="RID" />
Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,7 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows, float p_shadow_bias) {
Projection correction;
correction.set_depth_correction(p_flip_y, true, false);
Projection projection = correction * p_render_data->cam_projection;
Projection projection = correction * p_render_data->view_projection[0];
//store camera into ubo
GLES3::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
Expand Down
13 changes: 13 additions & 0 deletions scene/3d/camera_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,15 @@ void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, rea
update_gizmos();
}

Projection Camera3D::get_override_projection() const {
return override_projection;
}

void Camera3D::set_override_projection(const Projection &p_matrix) {
override_projection = p_matrix;
RenderingServer::get_singleton()->camera_set_override_projection(camera, override_projection);
}

void Camera3D::set_projection(ProjectionType p_mode) {
if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) {
mode = p_mode;
Expand Down Expand Up @@ -536,6 +545,8 @@ void Camera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_near", "near"), &Camera3D::set_near);
ClassDB::bind_method(D_METHOD("get_projection"), &Camera3D::get_projection);
ClassDB::bind_method(D_METHOD("set_projection", "mode"), &Camera3D::set_projection);
ClassDB::bind_method(D_METHOD("get_override_projection"), &Camera3D::get_override_projection);
ClassDB::bind_method(D_METHOD("set_override_projection", "projection_matrix"), &Camera3D::set_override_projection);
ClassDB::bind_method(D_METHOD("set_h_offset", "offset"), &Camera3D::set_h_offset);
ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera3D::get_h_offset);
ClassDB::bind_method(D_METHOD("set_v_offset", "offset"), &Camera3D::set_v_offset);
Expand Down Expand Up @@ -571,6 +582,7 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
ADD_PROPERTY(PropertyInfo(Variant::PROJECTION, "override_projection"), "set_override_projection", "get_override_projection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_size", "get_size");
Expand Down Expand Up @@ -748,6 +760,7 @@ RID Camera3D::get_pyramid_shape_rid() {

Camera3D::Camera3D() {
camera = RenderingServer::get_singleton()->camera_create();
override_projection.set_zero();
set_perspective(75.0, 0.05, 4000.0);
RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers);
//active=false;
Expand Down
3 changes: 3 additions & 0 deletions scene/3d/camera_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Camera3D : public Node3D {
real_t v_offset = 0.0;
real_t h_offset = 0.0;
KeepAspect keep_aspect = KEEP_HEIGHT;
Projection override_projection;

RID camera;
RID scenario_id;
Expand Down Expand Up @@ -133,6 +134,7 @@ class Camera3D : public Node3D {
real_t get_far() const;
real_t get_near() const;
Vector2 get_frustum_offset() const;
Projection get_override_projection() const;

ProjectionType get_projection() const;

Expand All @@ -141,6 +143,7 @@ class Camera3D : public Node3D {
void set_far(real_t p_far);
void set_near(real_t p_near);
void set_frustum_offset(Vector2 p_offset);
void set_override_projection(const Projection &p_matrix);

virtual Transform3D get_camera_transform() const;
virtual Projection get_camera_projection() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p
Projection correction;
correction.set_depth_correction(p_flip_y);
correction.add_jitter_offset(taa_jitter);
Projection projection = correction * cam_projection;
Projection projection = correction * view_projection[0];

//store camera into ubo
RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix);
Expand Down Expand Up @@ -261,7 +261,7 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p
Projection prev_correction;
prev_correction.set_depth_correction(true);
prev_correction.add_jitter_offset(prev_taa_jitter);
Projection prev_projection = prev_correction * prev_cam_projection;
Projection prev_projection = prev_correction * view_projection[0];

//store camera into ubo
RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix);
Expand Down
12 changes: 12 additions & 0 deletions servers/rendering/renderer_scene_cull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p
camera->zfar = p_z_far;
}

void RendererSceneCull::camera_set_override_projection(RID p_camera, const Projection &p_matrix) {
Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
Projection zero;
zero.set_zero();
camera->has_override_projection = (p_matrix != zero);
camera->override_projection = p_matrix;
}

void RendererSceneCull::camera_set_transform(RID p_camera, const Transform3D &p_transform) {
Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_NULL(camera);
Expand Down Expand Up @@ -2607,6 +2616,9 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
}

camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, camera->visible_layers);
if (camera->has_override_projection) {
camera_data.set_override_projection(camera->override_projection);
}
} else {
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
Expand Down
5 changes: 5 additions & 0 deletions servers/rendering/renderer_scene_cull.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ class RendererSceneCull : public RenderingMethod {
Vector2 offset;
uint32_t visible_layers;
bool vaspect;
bool has_override_projection;
RID env;
RID attributes;
RID compositor;

Transform3D transform;
Projection override_projection;

Camera() {
visible_layers = 0xFFFFFFFF;
Expand All @@ -96,6 +98,8 @@ class RendererSceneCull : public RenderingMethod {
size = 1.0;
offset = Vector2();
vaspect = false;
has_override_projection = false;
override_projection.set_zero();
}
};

Expand All @@ -107,6 +111,7 @@ class RendererSceneCull : public RenderingMethod {
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
virtual void camera_set_override_projection(RID p_camera, const Projection &p_matrix);
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform);
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
virtual void camera_set_environment(RID p_camera, RID p_env);
Expand Down
6 changes: 6 additions & 0 deletions servers/rendering/renderer_scene_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
taa_jitter = p_taa_jitter;
}

void RendererSceneRender::CameraData::set_override_projection(const Projection &p_projection) {
if (view_count == 1) {
view_projection[0] = p_projection;
}
}

void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");

Expand Down
1 change: 1 addition & 0 deletions servers/rendering/renderer_scene_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ class RendererSceneRender {
Vector2 taa_jitter;

void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), uint32_t p_visible_layers = 0xFFFFFFFF);
void set_override_projection(const Projection &p_projection);
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};

Expand Down
1 change: 1 addition & 0 deletions servers/rendering/rendering_method.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class RenderingMethod {
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
virtual void camera_set_override_projection(RID p_camera, const Projection &p_matrix) = 0;
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/rendering_server_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ class RenderingServerDefault : public RenderingServer {
FUNC4(camera_set_perspective, RID, float, float, float)
FUNC4(camera_set_orthogonal, RID, float, float, float)
FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
FUNC2(camera_set_override_projection, RID, const Projection &)
FUNC2(camera_set_transform, RID, const Transform3D &)
FUNC2(camera_set_cull_mask, RID, uint32_t)
FUNC2(camera_set_environment, RID, RID)
Expand Down
1 change: 1 addition & 0 deletions servers/rendering_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &RenderingServer::camera_set_perspective);
ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &RenderingServer::camera_set_orthogonal);
ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &RenderingServer::camera_set_frustum);
ClassDB::bind_method(D_METHOD("camera_set_override_projection", "camera", "matrix"), &RenderingServer::camera_set_override_projection);
ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &RenderingServer::camera_set_transform);
ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask);
ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment);
Expand Down
1 change: 1 addition & 0 deletions servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ class RenderingServer : public Object {
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
virtual void camera_set_override_projection(RID p_camera, const Projection &p_matrix) = 0;
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
Expand Down

0 comments on commit 7e3c501

Please sign in to comment.