diff options
Diffstat (limited to 'servers')
49 files changed, 966 insertions, 190 deletions
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h index 81af948530..b32b300dfa 100644 --- a/servers/audio/effects/audio_effect_chorus.h +++ b/servers/audio/effects/audio_effect_chorus.h @@ -60,7 +60,6 @@ class AudioEffectChorus : public AudioEffect { public: enum { - MAX_DELAY_MS = 50, MAX_DEPTH_MS = 20, MAX_WIDTH_MS = 50, diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h index a55000af4b..3b7f2ea458 100644 --- a/servers/audio/effects/audio_effect_delay.h +++ b/servers/audio/effects/audio_effect_delay.h @@ -62,7 +62,6 @@ class AudioEffectDelay : public AudioEffect { friend class AudioEffectDelayInstance; enum { - MAX_DELAY_MS = 3000, MAX_TAPS = 2 }; diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp index fb6b56d984..fdba1b59a3 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.cpp +++ b/servers/audio/effects/audio_effect_pitch_shift.cpp @@ -95,14 +95,12 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff expct = 2.*Math_PI*(double)stepSize/(double)fftFrameSize; inFifoLatency = fftFrameSize-stepSize; if (gRover == 0) { gRover = inFifoLatency; - } /* initialize our static arrays */ /* main processing loop */ for (i = 0; i < numSampsToProcess; i++){ - /* As long as we have not yet collected enough data just read in */ gInFIFO[gRover] = indata[i*stride]; outdata[i*stride] = gOutFIFO[gRover-inFifoLatency]; @@ -126,7 +124,6 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff /* this is the analysis step */ for (k = 0; k <= fftFrameSize2; k++) { - /* de-interlace FFT buffer */ real = gFFTworksp[2*k]; imag = gFFTworksp[2*k+1]; @@ -146,7 +143,6 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff qpd = tmp/Math_PI; if (qpd >= 0) { qpd += qpd&1; } else { qpd -= qpd&1; - } tmp -= Math_PI*(double)qpd; @@ -177,7 +173,6 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff /* ***************** SYNTHESIS ******************* */ /* this is the synthesis step */ for (k = 0; k <= fftFrameSize2; k++) { - /* get magnitude and true frequency from synthesis arrays */ magn = gSynMagn[k]; tmp = gSynFreq[k]; @@ -205,7 +200,6 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff /* zero negative frequencies */ for (k = fftFrameSize+2; k < 2*fftFrameSize; k++) { gFFTworksp[k] = 0.; - } /* do inverse transform */ @@ -217,7 +211,6 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff gOutputAccum[k] += 2.*window*gFFTworksp[2*k]/(fftFrameSize2*osamp); } for (k = 0; k < stepSize; k++) { gOutFIFO[k] = gOutputAccum[k]; - } /* shift accumulator */ @@ -225,13 +218,9 @@ void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long ff /* move input FIFO */ for (k = 0; k < inFifoLatency; k++) { gInFIFO[k] = gInFIFO[k+stepSize]; - } } } - - - } @@ -256,7 +245,6 @@ void SMBPitchShift::smbFft(float *fftBuffer, long fftFrameSize, long sign) for (i = 2; i < 2*fftFrameSize-2; i += 2) { for (bitm = 2, j = 0; bitm < 2*fftFrameSize; bitm <<= 1) { if (i & bitm) { j++; - } j <<= 1; } diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h index 7fb32bd8ec..98ee18ba5a 100644 --- a/servers/audio/effects/audio_effect_stereo_enhance.h +++ b/servers/audio/effects/audio_effect_stereo_enhance.h @@ -41,7 +41,6 @@ class AudioEffectStereoEnhanceInstance : public AudioEffectInstance { Ref<AudioEffectStereoEnhance> base; enum { - MAX_DELAY_MS = 50 }; diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h index 720c4dfcaf..c908c9c8fb 100644 --- a/servers/audio/effects/eq.h +++ b/servers/audio/effects/eq.h @@ -43,7 +43,6 @@ class EQ { public: enum Preset { - PRESET_6_BANDS, PRESET_8_BANDS, PRESET_10_BANDS, diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp index 7c35d88ced..1deb1499b5 100644 --- a/servers/audio/effects/reverb.cpp +++ b/servers/audio/effects/reverb.cpp @@ -127,13 +127,11 @@ void Reverb::process(float *p_src, float *p_dst, int p_frames) { int ap_size_limit[MAX_ALLPASS]; for (int i=0;i<MAX_ALLPASS;i++) { - AllPass &a=allpass[i]; ap_size_limit[i]=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread)); } for (int i=0;i<p_frames;i++) { - float sample=p_dst[i]; float aux,in; float AllPass*ap; diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h index 614de0c534..7dd88f9faf 100644 --- a/servers/audio/effects/reverb.h +++ b/servers/audio/effects/reverb.h @@ -46,7 +46,6 @@ public: private: enum { - MAX_COMBS = 8, MAX_ALLPASS = 4, MAX_ECHO_MS = 500 diff --git a/servers/audio_server.h b/servers/audio_server.h index 507aea7b89..83377a5e9e 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -122,7 +122,6 @@ public: class AudioDriverManager { enum { - MAX_DRIVERS = 10 }; diff --git a/servers/display_server.h b/servers/display_server.h index c2ffb23531..59bee794b8 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -177,7 +177,6 @@ public: } virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; enum ScreenOrientation { - SCREEN_LANDSCAPE, SCREEN_PORTRAIT, SCREEN_REVERSE_LANDSCAPE, diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 9d00d01759..755804fe36 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -1230,8 +1230,6 @@ void PhysicsServer2DSW::step(real_t p_step) { _update_shapes(); - doing_sync = false; - last_step = p_step; PhysicsDirectBodyState2DSW::singleton->step = p_step; island_count = 0; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index a8ab731ead..edadcabe0b 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -603,7 +603,6 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t * direction. Use a short ray shape if you want to achieve a similar effect. * if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { - cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); cbk.valid_depth = p_margin; //only valid depth is the collision margin cbk.invalid_by_dir = 0; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 5c5144ae22..93b62e0ba4 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -105,7 +105,6 @@ private: real_t test_motion_min_contact_depth; enum { - INTERSECTION_QUERY_MAX = 2048 }; diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index d1f16cb4ae..841e593ba3 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -628,7 +628,6 @@ void Body3DSW::integrate_velocities(real_t p_step) { /* void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { - Transform inv_xform = p_xform.affine_inverse(); if (!get_space()) { _set_transform(p_xform); @@ -655,8 +654,6 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { get_space()->body_add_to_state_query_list(&direct_state_query_list); simulated_motion=true; _set_transform(p_xform); - - } */ diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h index 59e36e7ea5..5f08d0cfa9 100644 --- a/servers/physics_3d/body_pair_3d_sw.h +++ b/servers/physics_3d/body_pair_3d_sw.h @@ -36,7 +36,6 @@ class BodyPair3DSW : public Constraint3DSW { enum { - MAX_CONTACTS = 4 }; diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp index d99a2532f8..e14949543e 100644 --- a/servers/physics_3d/gjk_epa.cpp +++ b/servers/physics_3d/gjk_epa.cpp @@ -102,7 +102,6 @@ typedef unsigned char U1; // MinkowskiDiff struct MinkowskiDiff { - const Shape3DSW* m_shapes[2]; Transform transform_A; @@ -127,7 +126,6 @@ struct MinkowskiDiff { return ( Support1 ( d ) ); } else { return ( Support0 ( d ) ); - } } }; @@ -281,7 +279,6 @@ struct GJK } } if(mask==15) { m_status=eStatus::Inside; - } } else @@ -312,12 +309,10 @@ struct GJK axis[i]=1; appendvertice(*m_simplex, axis); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); appendvertice(*m_simplex,-axis); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); } @@ -335,12 +330,10 @@ struct GJK { appendvertice(*m_simplex, p); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); appendvertice(*m_simplex,-p); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); } @@ -355,12 +348,10 @@ struct GJK { appendvertice(*m_simplex,n); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); appendvertice(*m_simplex,-n); if(EncloseOrigin()) { return(true); - } removevertice(*m_simplex); } @@ -372,7 +363,6 @@ struct GJK m_simplex->c[1]->w-m_simplex->c[3]->w, m_simplex->c[2]->w-m_simplex->c[3]->w))>0) { return(true); - } } break; @@ -580,7 +570,6 @@ struct GJK face->l[0] = nullptr; face->l[1] = list.root; if(list.root) { list.root->l[0]=face; - } list.root = face; ++list.count; @@ -588,13 +577,10 @@ struct GJK static inline void remove(sList& list,sFace* face) { if(face->l[1]) { face->l[1]->l[0]=face->l[0]; - } if(face->l[0]) { face->l[0]->l[1]=face->l[1]; - } if(face==list.root) { list.root=face->l[1]; - } --list.count; } @@ -616,7 +602,6 @@ struct GJK GJK::sSimplex& simplex=*gjk.m_simplex; if((simplex.rank>1)&&gjk.EncloseOrigin()) { - /* Clean up */ while(m_hull.root) { @@ -677,7 +662,6 @@ struct GJK append(m_stock,best); best=findbest(); if(best->p>=outer.p) { outer=*best; - } } else { m_status=eStatus::InvalidHull;break; } } else { m_status=eStatus::AccuraryReached;break; } @@ -711,7 +695,6 @@ struct GJK m_normal = m_normal/nl; } else { m_normal = Vector3(1,0,0); - } m_depth = 0; m_result.rank=1; @@ -747,10 +730,8 @@ struct GJK { return(face); } else { m_status=eStatus::NonConvex; - } } else { m_status=eStatus::Degenerated; - } remove(m_hull,face); append(m_stock,face); @@ -793,7 +774,6 @@ struct GJK { bind(nf,0,f,e); if(horizon.cf) { bind(horizon.cf,1,nf,2); } else { horizon.ff=nf; - } horizon.cf=nf; ++horizon.nf; @@ -917,7 +897,6 @@ bool Penetration( const Shape3DSW* shape0, results.distance = -epa.m_depth; return(true); } else { results.status=sResults::EPA_Failed; - } } break; @@ -948,8 +927,6 @@ bool Penetration( const Shape3DSW* shape0, #undef EPA_FALLBACK #undef EPA_PLANE_EPS #undef EPA_INSIDE_EPS - - } // end of namespace /* clang-format on */ diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp index fede40ca65..9ce5ebb7ed 100644 --- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp @@ -253,7 +253,6 @@ void Generic6DOFJoint3DSW::calculateAngleInfo() { /* if(m_debugDrawer) { - char buff[300]; sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", m_calculatedAxisAngleDiff[0], diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp index 52c7389e1f..c6fbc0f55f 100644 --- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp @@ -365,7 +365,6 @@ void HingeJoint3DSW::solve(real_t p_step) { void HingeJointSW::updateRHS(real_t timeStep) { (void)timeStep; - } */ diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp index 43bd49b4b5..dd6cc04f7c 100644 --- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp @@ -105,7 +105,6 @@ void SliderJoint3DSW::initParams() { m_targetAngMotorVelocity = real_t(0.); m_maxAngMotorForce = real_t(0.); m_accumulatedAngMotorImpulse = real_t(0.0); - } // SliderJointSW::initParams() //----------------------------------------------------------------------------- diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 143cc9ebbd..07a7498fec 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -174,7 +174,7 @@ real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) c PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) { Space3DSW *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, nullptr); - ERR_FAIL_COND_V_MSG(!doing_sync || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); + ERR_FAIL_COND_V_MSG(space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); return space->get_direct_state(); } @@ -888,7 +888,7 @@ int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_t PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { Body3DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, nullptr); - ERR_FAIL_COND_V_MSG(!doing_sync || body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); direct_state->body = body; return direct_state; @@ -1287,7 +1287,6 @@ void PhysicsServer3DSW::set_active(bool p_active) { }; void PhysicsServer3DSW::init() { - doing_sync = true; last_step = 0.001; iterations = 8; // 8? stepper = memnew(Step3DSW); @@ -1303,8 +1302,6 @@ void PhysicsServer3DSW::step(real_t p_step) { _update_shapes(); - doing_sync = false; - last_step = p_step; PhysicsDirectBodyState3DSW::singleton->step = p_step; @@ -1327,8 +1324,6 @@ void PhysicsServer3DSW::flush_queries() { return; } - doing_sync = true; - flushing_queries = true; uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index a45ee7c2c8..f96a8863c3 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -44,7 +44,6 @@ class PhysicsServer3DSW : public PhysicsServer3D { friend class PhysicsDirectSpaceState3DSW; bool active; int iterations; - bool doing_sync; real_t last_step; int island_count; @@ -365,7 +364,6 @@ public: virtual void set_active(bool p_active) override; virtual void init() override; virtual void step(real_t p_step) override; - virtual void sync() override {} virtual void flush_queries() override; virtual void finish() override; diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index b8b01de3c3..107f850ebd 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -333,7 +333,6 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s int i_n2 = next2[i]; static const real_t sign[4][2] = { - { -1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, -1.0 }, diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h index 6380bcc6dc..22535a6adb 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/space_3d_sw.h @@ -97,7 +97,6 @@ private: real_t test_motion_min_contact_depth; enum { - INTERSECTION_QUERY_MAX = 2048 }; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 283a2ab58c..f7607d5dd5 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -276,7 +276,6 @@ public: virtual bool space_is_active(RID p_space) const = 0; enum SpaceParameter { - SPACE_PARAM_CONTACT_RECYCLE_RADIUS, SPACE_PARAM_CONTACT_MAX_SEPARATION, SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, @@ -526,7 +525,6 @@ public: /* JOINT API */ enum JointType { - JOINT_PIN, JOINT_GROOVE, JOINT_DAMPED_SPRING @@ -587,7 +585,6 @@ public: virtual bool is_flushing_queries() const = 0; enum ProcessInfo { - INFO_ACTIVE_OBJECTS, INFO_COLLISION_PAIRS, INFO_ISLAND_COUNT diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 90ef2bb8dd..3f7ad26257 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -259,7 +259,6 @@ public: virtual bool space_is_active(RID p_space) const = 0; enum SpaceParameter { - SPACE_PARAM_CONTACT_RECYCLE_RADIUS, SPACE_PARAM_CONTACT_MAX_SEPARATION, SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, @@ -578,7 +577,6 @@ public: /* JOINT API */ enum JointType { - JOINT_PIN, JOINT_HINGE, JOINT_SLIDER, @@ -613,7 +611,6 @@ public: virtual Vector3 pin_joint_get_local_b(RID p_joint) const = 0; enum HingeJointParam { - HINGE_JOINT_BIAS, HINGE_JOINT_LIMIT_UPPER, HINGE_JOINT_LIMIT_LOWER, @@ -714,7 +711,6 @@ public: }; enum G6DOFJointAxisFlag { - G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, @@ -749,14 +745,12 @@ public: virtual void set_active(bool p_active) = 0; virtual void init() = 0; virtual void step(float p_step) = 0; - virtual void sync() = 0; virtual void flush_queries() = 0; virtual void finish() = 0; virtual bool is_flushing_queries() const = 0; enum ProcessInfo { - INFO_ACTIVE_OBJECTS, INFO_COLLISION_PAIRS, INFO_ISLAND_COUNT diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index efaa8f138a..4df140f8c3 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -752,6 +752,9 @@ public: virtual void render_target_disable_clear_request(RID p_render_target) = 0; virtual void render_target_do_clear_request(RID p_render_target) = 0; + virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0; + virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0; + virtual RS::InstanceType get_base_type(RID p_rid) const = 0; virtual bool free(RID p_rid) = 0; @@ -809,7 +812,6 @@ public: static RasterizerCanvas *singleton; enum CanvasRectFlags { - CANVAS_RECT_REGION = 1, CANVAS_RECT_TILE = 2, CANVAS_RECT_FLIP_H = 4, @@ -943,7 +945,6 @@ public: struct Command { enum Type { - TYPE_RECT, TYPE_NINEPATCH, TYPE_POLYGON, @@ -1326,7 +1327,7 @@ public: } }; - virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) = 0; + virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) = 0; virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; struct LightOccluderInstance { @@ -1338,12 +1339,14 @@ public: Transform2D xform; Transform2D xform_cache; int light_mask; + bool sdf_collision; RS::CanvasOccluderPolygonCullMode cull_cache; LightOccluderInstance *next; LightOccluderInstance() { enabled = true; + sdf_collision = false; next = nullptr; light_mask = 1; cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; @@ -1356,8 +1359,10 @@ public: virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0; + virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) = 0; + virtual RID occluder_polygon_create() = 0; - virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) = 0; + virtual void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) = 0; virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0; virtual void set_shadow_texture_size(int p_size) = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp index 5d9e68f2b4..921a7b966e 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -30,6 +30,7 @@ #include "rasterizer_canvas_rd.h" #include "core/config/project_settings.h" +#include "core/math/geometry_2d.h" #include "core/math/math_funcs.h" #include "rasterizer_rd.h" @@ -687,7 +688,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ #if 0 case Item::Command::TYPE_MESH: { - Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(c); _set_texture_rect_mode(false); @@ -702,7 +702,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); if (mesh_data) { - for (int j = 0; j < mesh_data->surfaces.size(); j++) { RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing @@ -723,7 +722,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } break; case Item::Command::TYPE_MULTIMESH: { - Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(c); RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); @@ -786,7 +784,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ int custom_data_ofs = color_ofs; switch (multi_mesh->color_format) { - case RS::MULTIMESH_COLOR_NONE: { glDisableVertexAttribArray(11); glVertexAttrib4f(11, 1, 1, 1, 1); @@ -807,7 +804,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } switch (multi_mesh->custom_data_format) { - case RS::MULTIMESH_CUSTOM_DATA_NONE: { glDisableVertexAttribArray(12); glVertexAttrib4f(12, 1, 1, 1, 1); @@ -841,7 +837,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } break; case Item::Command::TYPE_PARTICLES: { - Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c); RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); @@ -875,7 +870,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } if (!particles->use_local_coords) { - Transform2D inv_xf; inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); @@ -893,7 +887,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ int amount = particles->amount; if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_LIFETIME) { - glEnableVertexAttribArray(8); //xform x glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); glVertexAttribDivisor(8, 1); @@ -1059,10 +1052,19 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ } { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 7; + RID sdf = storage->render_target_get_sdf_texture(p_to_render_target); + u.ids.push_back(sdf); + uniforms.push_back(u); + } + + { //needs samplers for the material (uses custom textures) create them RD::Uniform u; u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 7; + u.binding = 8; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); @@ -1083,7 +1085,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 8; + u.binding = 9; u.ids.push_back(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } @@ -1190,7 +1192,8 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, RD::get_singleton()->draw_list_end(); } -void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { +void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) { + r_sdf_used = false; int item_count = 0; //setup canvas state uniforms if needed @@ -1373,6 +1376,25 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite state_buffer.directional_light_count = directional_light_count; + Vector2 canvas_scale = p_canvas_transform.get_scale(); + + state_buffer.sdf_to_screen[0] = render_target_size.width / canvas_scale.x; + state_buffer.sdf_to_screen[1] = render_target_size.height / canvas_scale.y; + + state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0]; + state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1]; + + Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target); + Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale); + + state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width; + state_buffer.sdf_to_tex[1] = 1.0 / sdf_tex_rect.size.height; + state_buffer.sdf_to_tex[2] = -sdf_tex_rect.position.x / sdf_tex_rect.size.width; + state_buffer.sdf_to_tex[3] = -sdf_tex_rect.position.y / sdf_tex_rect.size.height; + + //print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale)); + state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5); + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); } @@ -1410,6 +1432,9 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } } + if (md->shader_data->uses_sdf) { + r_sdf_used = true; + } if (md->last_frame != RasterizerRD::singleton->get_frame_number()) { md->last_frame = RasterizerRD::singleton->get_frame_number(); if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { @@ -1695,18 +1720,102 @@ void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow cl->shadow.directional_xform = to_shadow * to_light_xform; } +void RasterizerCanvasRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) { + RID fb = storage->render_target_get_sdf_framebuffer(p_render_target); + Rect2i rect = storage->render_target_get_sdf_rect(p_render_target); + + Transform2D to_sdf; + to_sdf.elements[0] *= rect.size.width; + to_sdf.elements[1] *= rect.size.height; + to_sdf.elements[2] = rect.position; + + Transform2D to_clip; + to_clip.elements[0] *= 2.0; + to_clip.elements[1] *= 2.0; + to_clip.elements[2] = -Vector2(1.0, 1.0); + + to_clip = to_clip * to_sdf.affine_inverse(); + + Vector<Color> cc; + cc.push_back(Color(0, 0, 0, 0)); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc); + + CameraMatrix projection; + + ShadowRenderPushConstant push_constant; + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + } + } + + push_constant.direction[0] = 0.0; + push_constant.direction[1] = 0.0; + push_constant.z_far = 0; + push_constant.pad = 0; + + LightOccluderInstance *instance = p_occluders; + + while (instance) { + OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder); + + if (!co || co->sdf_index_array.is_null()) { + instance = instance->next; + continue; + } + + _update_transform_2d_to_mat2x4(to_clip * instance->xform_cache, push_constant.modelview); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.sdf_render_pipelines[co->sdf_is_lines ? SHADOW_RENDER_SDF_LINES : SHADOW_RENDER_SDF_TRIANGLES]); + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->sdf_vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, co->sdf_index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + + instance = instance->next; + } + + RD::get_singleton()->draw_list_end(); + + storage->render_target_sdf_process(p_render_target); //done rendering, process it +} + RID RasterizerCanvasRD::occluder_polygon_create() { OccluderPolygon occluder; - occluder.point_count = 0; + occluder.line_point_count = 0; + occluder.sdf_point_count = 0; + occluder.sdf_index_count = 0; occluder.cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; return occluder_polygon_owner.make_rid(occluder); } -void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) { +void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) { OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); ERR_FAIL_COND(!oc); - if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) { + Vector<Vector2> lines; + int lc = p_points.size() * 2; + + lines.resize(lc - (p_closed ? 0 : 2)); + { + Vector2 *w = lines.ptrw(); + const Vector2 *r = p_points.ptr(); + + int max = lc / 2; + if (!p_closed) { + max--; + } + for (int i = 0; i < max; i++) { + Vector2 a = r[i]; + Vector2 b = r[(i + 1) % (lc / 2)]; + w[i * 2 + 0] = a; + w[i * 2 + 1] = b; + } + } + + if (oc->line_point_count != lines.size() && oc->vertex_array.is_valid()) { RD::get_singleton()->free(oc->vertex_array); RD::get_singleton()->free(oc->vertex_buffer); RD::get_singleton()->free(oc->index_array); @@ -1716,12 +1825,14 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con oc->vertex_buffer = RID(); oc->index_array = RID(); oc->index_buffer = RID(); + + oc->line_point_count = lines.size(); } - if (p_lines.size()) { + if (lines.size()) { Vector<uint8_t> geometry; Vector<uint8_t> indices; - int lc = p_lines.size(); + lc = lines.size(); geometry.resize(lc * 6 * sizeof(float)); indices.resize(lc * 3 * sizeof(uint16_t)); @@ -1732,7 +1843,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con uint8_t *iw = indices.ptrw(); uint16_t *iwptr = (uint16_t *)iw; - const Vector2 *lr = p_lines.ptr(); + const Vector2 *lr = lines.ptr(); const int POLY_HEIGHT = 16384; @@ -1786,6 +1897,62 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir); } } + + // sdf + + Vector<int> sdf_indices; + + if (p_closed) { + sdf_indices = Geometry2D::triangulate_polygon(p_points); + oc->sdf_is_lines = false; + } else { + int max = p_points.size(); + sdf_indices.resize(max * 2); + + int *iw = sdf_indices.ptrw(); + for (int i = 0; i < max; i++) { + iw[i * 2 + 0] = i; + iw[i * 2 + 1] = (i + 1) % max; + } + oc->sdf_is_lines = true; + } + + if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array.is_valid()) { + RD::get_singleton()->free(oc->sdf_vertex_array); + RD::get_singleton()->free(oc->sdf_vertex_buffer); + RD::get_singleton()->free(oc->sdf_index_array); + RD::get_singleton()->free(oc->sdf_index_buffer); + + oc->sdf_vertex_array = RID(); + oc->sdf_vertex_buffer = RID(); + oc->sdf_index_array = RID(); + oc->sdf_index_buffer = RID(); + + oc->sdf_index_count = sdf_indices.size(); + oc->sdf_point_count = p_points.size(); + + oc->sdf_is_lines = false; + } + + if (sdf_indices.size()) { + if (oc->sdf_vertex_array.is_null()) { + //create from scratch + //vertices + oc->sdf_vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_points.size() * 2 * sizeof(real_t), p_points.to_byte_array()); + oc->sdf_index_buffer = RD::get_singleton()->index_buffer_create(sdf_indices.size(), RD::INDEX_BUFFER_FORMAT_UINT32, sdf_indices.to_byte_array()); + oc->sdf_index_array = RD::get_singleton()->index_array_create(oc->sdf_index_buffer, 0, sdf_indices.size()); + + Vector<RID> buffer; + buffer.push_back(oc->sdf_vertex_buffer); + oc->sdf_vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), shadow_render.sdf_vertex_format, buffer); + //indices + + } else { + //update existing + RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr()); + RD::get_singleton()->buffer_update(oc->index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr()); + } + } } void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) { @@ -1802,6 +1969,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { ubo_size = 0; uniforms.clear(); uses_screen_texture = false; + uses_sdf = false; if (code == String()) { return; //just invalid, but no error @@ -1809,7 +1977,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { ShaderCompilerRD::GeneratedCode gen_code; - int light_mode = LIGHT_MODE_NORMAL; int blend_mode = BLEND_MODE_MIX; uses_screen_texture = false; @@ -1822,10 +1989,8 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA); actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED); - actions.render_mode_values["unshaded"] = Pair<int *, int>(&light_mode, LIGHT_MODE_UNSHADED); - actions.render_mode_values["light_only"] = Pair<int *, int>(&light_mode, LIGHT_MODE_LIGHT_ONLY); - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; + actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; actions.uniforms = &uniforms; @@ -2046,6 +2211,7 @@ Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName & RasterizerCanvasRD::ShaderData::ShaderData() { valid = false; uses_screen_texture = false; + uses_sdf = false; } RasterizerCanvasRD::ShaderData::~ShaderData() { @@ -2310,6 +2476,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.renames["LIGHT"] = "light"; actions.renames["SHADOW_MODULATE"] = "shadow_modulate"; + actions.renames["texture_sdf"] = "texture_sdf"; + actions.renames["texture_sdf_normal"] = "texture_sdf_normal"; + actions.renames["sdf_to_screen_uv"] = "sdf_to_screen_uv"; + actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf"; + actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; @@ -2319,6 +2490,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n"; actions.custom_samplers["TEXTURE"] = "texture_sampler"; actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler"; @@ -2339,7 +2512,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //shadow rendering Vector<String> versions; - versions.push_back(String()); //no versions + versions.push_back("\n#define MODE_SHADOW\n"); //shadow + versions.push_back("\n#define MODE_SDF\n"); //sdf shadow_render.shader.initialize(versions); { @@ -2360,16 +2534,34 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments); } + { + Vector<RD::AttachmentFormat> attachments; + + RD::AttachmentFormat af_color; + af_color.format = RD::DATA_FORMAT_R8_UNORM; + af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + attachments.push_back(af_color); + + shadow_render.sdf_framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments); + } + //pipelines Vector<RD::VertexAttribute> vf; RD::VertexAttribute vd; - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32B32_SFLOAT : RD::DATA_FORMAT_R64G64B64_SFLOAT; vd.location = 0; vd.offset = 0; - vd.stride = sizeof(float) * 3; + vd.stride = sizeof(real_t) * 3; vf.push_back(vd); shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf); + vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32_SFLOAT : RD::DATA_FORMAT_R64G64_SFLOAT; + vd.stride = sizeof(real_t) * 2; + + vf.write[0] = vd; + shadow_render.sdf_vertex_format = RD::get_singleton()->vertex_format_create(vf); + shadow_render.shader_version = shadow_render.shader.version_create(); for (int i = 0; i < 3; i++) { @@ -2379,7 +2571,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { ds.enable_depth_write = true; ds.enable_depth_test = true; ds.depth_compare_operator = RD::COMPARE_OP_LESS; - shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SHADOW), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } + + for (int i = 0; i < 2; i++) { + shadow_render.sdf_render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SDF), shadow_render.sdf_framebuffer_format, shadow_render.sdf_vertex_format, i == 0 ? RD::RENDER_PRIMITIVE_TRIANGLES : RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); } } @@ -2490,7 +2686,7 @@ bool RasterizerCanvasRD::free(RID p_rid) { light_set_use_shadow(p_rid, false); canvas_light_owner.free(p_rid); } else if (occluder_polygon_owner.owns(p_rid)) { - occluder_polygon_set_shape_as_lines(p_rid, Vector<Vector2>()); + occluder_polygon_set_shape(p_rid, Vector<Vector2>(), false); occluder_polygon_owner.free(p_rid); } else { return false; diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h index b516f63cbf..b09d6578f3 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h @@ -161,12 +161,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { BLEND_MODE_DISABLED, }; - enum LightMode { - LIGHT_MODE_NORMAL, - LIGHT_MODE_UNSHADED, - LIGHT_MODE_LIGHT_ONLY - }; - bool valid; RID version; PipelineVariants pipeline_variants; @@ -181,7 +175,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { String code; Map<StringName, RID> default_texture_params; - bool uses_screen_texture; + bool uses_screen_texture = false; + bool uses_sdf = false; virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture); @@ -284,11 +279,19 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct OccluderPolygon { RS::CanvasOccluderPolygonCullMode cull_mode; - int point_count; + int line_point_count; RID vertex_buffer; RID vertex_array; RID index_buffer; RID index_array; + + int sdf_point_count; + int sdf_index_count; + RID sdf_vertex_buffer; + RID sdf_vertex_array; + RID sdf_index_buffer; + RID sdf_index_array; + bool sdf_is_lines; }; struct LightUniform { @@ -310,12 +313,25 @@ class RasterizerCanvasRD : public RasterizerCanvas { RID_Owner<OccluderPolygon> occluder_polygon_owner; + enum ShadowRenderMode { + SHADOW_RENDER_MODE_SHADOW, + SHADOW_RENDER_MODE_SDF, + }; + + enum { + SHADOW_RENDER_SDF_TRIANGLES, + SHADOW_RENDER_SDF_LINES, + }; + struct { CanvasOcclusionShaderRD shader; RID shader_version; RID render_pipelines[3]; + RID sdf_render_pipelines[2]; RD::VertexFormatID vertex_format; + RD::VertexFormatID sdf_vertex_format; RD::FramebufferFormatID framebuffer_format; + RD::FramebufferFormatID sdf_framebuffer_format; } shadow_render; /***************/ @@ -336,8 +352,14 @@ class RasterizerCanvasRD : public RasterizerCanvas { float time; uint32_t use_pixel_snap; + float sdf_to_tex[4]; + float sdf_to_screen[2]; + float screen_to_sdf[2]; + uint32_t directional_light_count; - uint32_t pad[3]; + float tex_to_sdf; + uint32_t pad1; + uint32_t pad2; }; LightUniform *light_uniforms; @@ -423,11 +445,13 @@ public: void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders); + virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders); + RID occluder_polygon_create(); - void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines); + void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed); void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode); - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel); + void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used); void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {} diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index a275e46473..313188ba87 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -1238,7 +1238,6 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende } #if 0 if (p_render_buffers.is_valid() && render_buffers_is_sdfgi_enabled(p_render_buffers)) { - scene_state.ubo.sdfgi_cascade_count = render_buffers_get_sdfgi_cascade_count(p_render_buffers); scene_state.ubo.sdfgi_probe_axis_size = render_buffers_get_sdfgi_cascade_probe_count(p_render_buffers); scene_state.ubo.sdfgi_cascade_probe_size[0] = scene_state.ubo.sdfgi_probe_axis_size - 1; //float version for performance @@ -1583,7 +1582,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i } break; #if 0 case RS::INSTANCE_IMMEDIATE: { - RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); ERR_CONTINUE(!immediate); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index e1be9b0ef4..12fcc6fbb9 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -351,8 +351,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co RD::TextureFormat tf_probe_average = tf_probes; tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed - tf_probe_average.type = RD::TEXTURE_TYPE_2D_ARRAY; - tf_probe_average.array_layers = 1; + tf_probe_average.type = RD::TEXTURE_TYPE_2D; sdfgi->lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); sdfgi->lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); @@ -1471,7 +1470,9 @@ void RasterizerSceneRD::_setup_giprobes(RID p_render_buffers, const Transform &p } if (giprobes_changed) { - RD::get_singleton()->free(rb->gi_uniform_set); + if (RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) { + RD::get_singleton()->free(rb->gi_uniform_set); + } rb->gi_uniform_set = RID(); if (rb->volumetric_fog) { if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) { @@ -8216,7 +8217,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { RD::Uniform u; u.type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); uniforms.push_back(u); } { diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index 8bd4362637..444ef9c49a 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -5549,7 +5549,6 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t } RID shared_tex; { - RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_R8_UINT; shared_tex = RD::get_singleton()->texture_create_shared(tv, gi_probe->sdf_texture); @@ -6030,6 +6029,8 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { rt->backbuffer_uniform_set = RID(); //chain deleted } + _render_target_clear_sdf(rt); + rt->framebuffer = RID(); rt->color = RID(); } @@ -6300,6 +6301,275 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { rt->clear_requested = false; } +void RasterizerStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) { + return; + } + + rt->sdf_oversize = p_size; + rt->sdf_scale = p_scale; + + _render_target_clear_sdf(rt); +} + +Rect2i RasterizerStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const { + Size2i margin; + int scale; + switch (rt->sdf_oversize) { + case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: { + scale = 100; + } break; + case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: { + scale = 120; + } break; + case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: { + scale = 150; + } break; + case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: { + scale = 200; + } break; + default: { + } + } + + margin = (rt->size * scale / 100) - rt->size; + + Rect2i r(Vector2i(), rt->size); + r.position -= margin; + r.size += margin * 2; + + return r; +} + +Rect2i RasterizerStorageRD::render_target_get_sdf_rect(RID p_render_target) const { + const RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, Rect2i()); + + return _render_target_get_sdf_rect(rt); +} + +RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + if (rt->sdf_buffer_read.is_null()) { + // no texture, create a dummy one for the 2D uniform set + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + tformat.type = RD::TEXTURE_TYPE_2D; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + zeromem(pv.ptrw(), 16 * 4); + Vector<Vector<uint8_t>> vpv; + + rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + return rt->sdf_buffer_read; +} + +void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { + ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid()); + if (rt->sdf_buffer_read.is_valid()) { + RD::get_singleton()->free(rt->sdf_buffer_read); + rt->sdf_buffer_read = RID(); + } + + Size2i size = _render_target_get_sdf_rect(rt).size; + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8_UNORM; + tformat.width = size.width; + tformat.height = size.height; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tformat.type = RD::TEXTURE_TYPE_2D; + + rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + + { + Vector<RID> write_fb; + write_fb.push_back(rt->sdf_buffer_write); + rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb); + } + + int scale; + switch (rt->sdf_scale) { + case RS::VIEWPORT_SDF_SCALE_100_PERCENT: { + scale = 100; + } break; + case RS::VIEWPORT_SDF_SCALE_50_PERCENT: { + scale = 50; + } break; + case RS::VIEWPORT_SDF_SCALE_25_PERCENT: { + scale = 25; + } break; + default: { + scale = 100; + } break; + } + + rt->process_size = size * scale / 100; + rt->process_size.x = MAX(rt->process_size.x, 1); + rt->process_size.y = MAX(rt->process_size.y, 1); + + tformat.format = RD::DATA_FORMAT_R16G16_UINT; + tformat.width = rt->process_size.width; + tformat.height = rt->process_size.height; + tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + + rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + + tformat.format = RD::DATA_FORMAT_R16_UNORM; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(rt->sdf_buffer_write); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(rt->sdf_buffer_read); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(rt->sdf_buffer_process[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(rt->sdf_buffer_process[1]); + uniforms.push_back(u); + } + + rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0); + SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]); + rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0); + } +} + +void RasterizerStorageRD::_render_target_clear_sdf(RenderTarget *rt) { + if (rt->sdf_buffer_read.is_valid()) { + RD::get_singleton()->free(rt->sdf_buffer_read); + rt->sdf_buffer_read = RID(); + } + if (rt->sdf_buffer_write_fb.is_valid()) { + RD::get_singleton()->free(rt->sdf_buffer_write); + RD::get_singleton()->free(rt->sdf_buffer_process[0]); + RD::get_singleton()->free(rt->sdf_buffer_process[1]); + rt->sdf_buffer_write = RID(); + rt->sdf_buffer_write_fb = RID(); + rt->sdf_buffer_process[0] = RID(); + rt->sdf_buffer_process[1] = RID(); + rt->sdf_buffer_process_uniform_sets[0] = RID(); + rt->sdf_buffer_process_uniform_sets[1] = RID(); + } +} + +RID RasterizerStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (rt->sdf_buffer_write_fb.is_null()) { + _render_target_allocate_sdf(rt); + } + + return rt->sdf_buffer_write_fb; +} +void RasterizerStorageRD::render_target_sdf_process(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null()); + + RenderTargetSDF::PushConstant push_constant; + + Rect2i r = _render_target_get_sdf_rect(rt); + + push_constant.size[0] = r.size.width; + push_constant.size[1] = r.size.height; + push_constant.stride = 0; + push_constant.shift = 0; + push_constant.base_size[0] = r.size.width; + push_constant.base_size[1] = r.size.height; + + bool shrink = false; + + switch (rt->sdf_scale) { + case RS::VIEWPORT_SDF_SCALE_50_PERCENT: { + push_constant.size[0] >>= 1; + push_constant.size[1] >>= 1; + push_constant.shift = 1; + shrink = true; + } break; + case RS::VIEWPORT_SDF_SCALE_25_PERCENT: { + push_constant.size[0] >>= 2; + push_constant.size[1] >>= 2; + push_constant.shift = 2; + shrink = true; + } break; + default: { + }; + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* Load */ + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0] + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1); + + /* Process */ + + int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + bool swap = false; + + //jumpflood + while (stride > 0) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0); + push_constant.stride = stride; + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1); + stride /= 2; + swap = !swap; + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + /* Store */ + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1); + + RD::get_singleton()->compute_list_end(); +} + void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); @@ -7756,6 +8026,34 @@ RasterizerStorageRD::RasterizerStorageRD() { } } + { //create default cubemap white array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_CUBE; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + { //create default 3D RD::TextureFormat tformat; @@ -8128,6 +8426,24 @@ RasterizerStorageRD::RasterizerStorageRD() { particles_shader.copy_pipelines[i] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i)); } } + + { + Vector<String> sdf_modes; + sdf_modes.push_back("\n#define MODE_LOAD\n"); + sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n"); + sdf_modes.push_back("\n#define MODE_PROCESS\n"); + sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n"); + sdf_modes.push_back("\n#define MODE_STORE\n"); + sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n"); + + rt_sdf.shader.initialize(sdf_modes); + + rt_sdf.shader_version = rt_sdf.shader.version_create(); + + for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) { + rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i)); + } + } } RasterizerStorageRD::~RasterizerStorageRD() { diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index 05cb1b4a73..4a708fc94f 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -35,6 +35,7 @@ #include "servers/rendering/rasterizer.h" #include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h" #include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/particles.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/particles_copy.glsl.gen.h" @@ -155,6 +156,7 @@ public: DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, DEFAULT_RD_TEXTURE_3D_WHITE, DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, DEFAULT_RD_TEXTURE_2D_UINT, @@ -1002,6 +1004,15 @@ private: RID framebuffer_uniform_set; RID backbuffer_uniform_set; + RID sdf_buffer_write; + RID sdf_buffer_write_fb; + RID sdf_buffer_process[2]; + RID sdf_buffer_read; + RID sdf_buffer_process_uniform_sets[2]; + RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT; + RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; + Size2i process_size; + //texture generated for this owner (nor RD). RID texture; bool was_used; @@ -1011,11 +1022,38 @@ private: Color clear_color; }; - RID_Owner<RenderTarget> render_target_owner; + mutable RID_Owner<RenderTarget> render_target_owner; void _clear_render_target(RenderTarget *rt); void _update_render_target(RenderTarget *rt); void _create_render_target_backbuffer(RenderTarget *rt); + void _render_target_allocate_sdf(RenderTarget *rt); + void _render_target_clear_sdf(RenderTarget *rt); + Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const; + + struct RenderTargetSDF { + enum { + SHADER_LOAD, + SHADER_LOAD_SHRINK, + SHADER_PROCESS, + SHADER_PROCESS_OPTIMIZED, + SHADER_STORE, + SHADER_STORE_SHRINK, + SHADER_MAX + }; + + struct PushConstant { + int32_t size[2]; + int32_t stride; + int32_t shift; + int32_t base_size[2]; + int32_t pad[2]; + }; + + CanvasSdfShaderRD shader; + RID shader_version; + RID pipelines[SHADER_MAX]; + } rt_sdf; /* GLOBAL SHADER VARIABLES */ @@ -1929,6 +1967,12 @@ public: virtual void render_target_disable_clear_request(RID p_render_target); virtual void render_target_do_clear_request(RID p_render_target); + virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale); + RID render_target_get_sdf_texture(RID p_render_target); + RID render_target_get_sdf_framebuffer(RID p_render_target); + void render_target_sdf_process(RID p_render_target); + virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const; + Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index 1a33e9a567..df5513435a 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -671,7 +671,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } /* for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) { - if (SL::is_sampler_type(E->get().type)) { continue; } @@ -1073,6 +1072,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } else if (onode->op == SL::OP_CONSTRUCT) { code += String(vnode->name); } else { + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { + *p_actions.usage_flag_pointers[vnode->name] = true; + used_flag_pointers.insert(vnode->name); + } + if (internal_functions.has(vnode->name)) { code += vnode->name; is_texture_func = texture_functions.has(vnode->name); diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub index 9d531d63ad..4cddf0f685 100644 --- a/servers/rendering/rasterizer_rd/shaders/SCsub +++ b/servers/rendering/rasterizer_rd/shaders/SCsub @@ -5,6 +5,7 @@ Import("env") if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("canvas.glsl") env.RD_GLSL("canvas_occlusion.glsl") + env.RD_GLSL("canvas_sdf.glsl") env.RD_GLSL("copy.glsl") env.RD_GLSL("copy_to_fb.glsl") env.RD_GLSL("cubemap_roughness.glsl") diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl index 2a0f94e733..51d7193a03 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl @@ -233,6 +233,30 @@ MATERIAL_UNIFORMS } material; #endif +vec2 screen_uv_to_sdf(vec2 p_uv) { + return canvas_data.screen_to_sdf * p_uv; +} + +float texture_sdf(vec2 p_sdf) { + vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw; + float d = texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv).r; + d = d * SDF_MAX_LENGTH - 1.0; + return d * canvas_data.tex_to_sdf; +} + +vec2 texture_sdf_normal(vec2 p_sdf) { + vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw; + + const float EPSILON = 0.001; + return normalize(vec2( + texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(EPSILON, 0.0)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(EPSILON, 0.0)).r, + texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(0.0, EPSILON)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(0.0, EPSILON)).r)); +} + +vec2 sdf_to_screen_uv(vec2 p_sdf) { + return p_sdf * canvas_data.sdf_to_screen; +} + /* clang-format off */ FRAGMENT_SHADER_GLOBALS /* clang-format on */ @@ -500,8 +524,13 @@ FRAGMENT_SHADER_CODE color = vec4(0.0); //invisible by default due to using light mask } +#ifdef MODE_LIGHT_ONLY + color = vec4(0.0); +#else color *= canvas_data.canvas_modulation; -#ifdef USE_LIGHTING +#endif + +#if defined(USE_LIGHTING) && !defined(MODE_UNSHADED) // Directional Lights diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl index 421282cd4d..5c25235c58 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl @@ -2,6 +2,8 @@ #version 450 +VERSION_DEFINES + layout(location = 0) in highp vec3 vertex; layout(push_constant, binding = 0, std430) uniform Constants { @@ -13,12 +15,16 @@ layout(push_constant, binding = 0, std430) uniform Constants { } constants; +#ifdef MODE_SHADOW layout(location = 0) out highp float depth; +#endif void main() { highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); - depth = dot(constants.direction, vtx.xy); +#ifdef MODE_SHADOW + depth = dot(constants.direction, vtx.xy); +#endif gl_Position = constants.projection * vtx; } @@ -26,6 +32,8 @@ void main() { #version 450 +VERSION_DEFINES + layout(push_constant, binding = 0, std430) uniform Constants { mat4 projection; mat2x4 modelview; @@ -35,9 +43,17 @@ layout(push_constant, binding = 0, std430) uniform Constants { } constants; +#ifdef MODE_SHADOW layout(location = 0) in highp float depth; layout(location = 0) out highp float distance_buf; +#else +layout(location = 0) out highp float sdf_buf; +#endif void main() { +#ifdef MODE_SHADOW distance_buf = depth / constants.z_far; +#else + sdf_buf = 1.0; +#endif } diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl new file mode 100644 index 0000000000..302ad03b41 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl @@ -0,0 +1,135 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(r8, set = 0, binding = 1) uniform restrict readonly image2D src_pixels; +layout(r16, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf; + +layout(rg16i, set = 0, binding = 3) uniform restrict readonly iimage2D src_process; +layout(rg16i, set = 0, binding = 4) uniform restrict writeonly iimage2D dst_process; + +layout(push_constant, binding = 0, std430) uniform Params { + ivec2 size; + int stride; + int shift; + ivec2 base_size; + uvec2 pad; +} +params; + +#define SDF_MAX_LENGTH 16384.0 + +void main() { + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos, params.size))) { //too large, do nothing + return; + } + +#ifdef MODE_LOAD + + bool solid = imageLoad(src_pixels, pos).r > 0.5; + imageStore(dst_process, pos, solid ? ivec4(pos, 0, 0) : ivec4(ivec2(32767), 0, 0)); +#endif + +#ifdef MODE_LOAD_SHRINK + + int s = 1 << params.shift; + ivec2 base = pos << params.shift; + ivec2 center = base + ivec2(params.shift); + + ivec2 rel = ivec2(32767); + float d = 1e20; + for (int i = 0; i < s; i++) { + for (int j = 0; j < s; j++) { + ivec2 src_pos = base + ivec2(i, j); + if (any(greaterThanEqual(src_pos, params.base_size))) { + continue; + } + bool solid = imageLoad(src_pixels, src_pos).r > 0.5; + if (solid) { + float dist = length(vec2(src_pos - center)); + if (dist < d) { + d = dist; + rel = src_pos; + } + } + } + } + + imageStore(dst_process, pos, ivec4(rel, 0, 0)); +#endif + +#ifdef MODE_PROCESS + + ivec2 base = pos << params.shift; + ivec2 center = base + ivec2(params.shift); + + ivec2 rel = imageLoad(src_process, pos).xy; + + if (center != rel) { + //only process if it does not point to itself + const int ofs_table_size = 8; + const ivec2 ofs_table[ofs_table_size] = ivec2[]( + ivec2(-1, -1), + ivec2(0, -1), + ivec2(+1, -1), + + ivec2(-1, 0), + ivec2(+1, 0), + + ivec2(-1, +1), + ivec2(0, +1), + ivec2(+1, +1)); + + float dist = length(vec2(rel - center)); + for (int i = 0; i < ofs_table_size; i++) { + ivec2 src_pos = pos + ofs_table[i] * params.stride; + if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, params.size))) { + continue; + } + ivec2 src_rel = imageLoad(src_process, src_pos).xy; + float src_dist = length(vec2(src_rel - center)); + if (src_dist < dist) { + dist = src_dist; + rel = src_rel; + } + } + } + + imageStore(dst_process, pos, ivec4(rel, 0, 0)); +#endif + +#ifdef MODE_STORE + + ivec2 rel = imageLoad(src_process, pos).xy; + float d = length(vec2(rel - pos)); + if (d > 0.01) { + d += 1.0; //make it signed + } + d /= SDF_MAX_LENGTH; + d = clamp(d, 0.0, 1.0); + imageStore(dst_sdf, pos, vec4(d)); + +#endif + +#ifdef MODE_STORE_SHRINK + + ivec2 base = pos << params.shift; + ivec2 center = base + ivec2(params.shift); + + ivec2 rel = imageLoad(src_process, pos).xy; + float d = length(vec2(rel - center)); + + if (d > 0.01) { + d += 1.0; //make it signed + } + d /= SDF_MAX_LENGTH; + d = clamp(d, 0.0, 1.0); + imageStore(dst_sdf, pos, vec4(d)); + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl index bb39584cbb..cf7678ea31 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl @@ -3,6 +3,8 @@ #define M_PI 3.14159265359 +#define SDF_MAX_LENGTH 16384.0 + #define FLAGS_INSTANCING_STRIDE_MASK 0xF #define FLAGS_INSTANCING_ENABLED (1 << 4) #define FLAGS_INSTANCING_HAS_COLORS (1 << 5) @@ -24,6 +26,19 @@ #define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) +#define SAMPLER_NEAREST_CLAMP 0 +#define SAMPLER_LINEAR_CLAMP 1 +#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 +#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 +#define SAMPLER_NEAREST_REPEAT 6 +#define SAMPLER_LINEAR_REPEAT 7 +#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8 +#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 + // Push Constant layout(push_constant, binding = 0, std430) uniform DrawData { @@ -68,8 +83,12 @@ layout(set = 0, binding = 1, std140) uniform CanvasData { float time; bool use_pixel_snap; + vec4 sdf_to_tex; + vec2 screen_to_sdf; + vec2 sdf_to_screen; + uint directional_light_count; - uint pad0; + float tex_to_sdf; uint pad1; uint pad2; } @@ -115,10 +134,11 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture; layout(set = 0, binding = 5) uniform sampler shadow_sampler; layout(set = 0, binding = 6) uniform texture2D screen_texture; +layout(set = 0, binding = 7) uniform texture2D sdf_texture; -layout(set = 0, binding = 7) uniform sampler material_samplers[12]; +layout(set = 0, binding = 8) uniform sampler material_samplers[12]; -layout(set = 0, binding = 8, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index da3c60af04..285698f060 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -868,7 +868,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v inout float alpha, #endif inout vec3 diffuse_light, inout vec3 specular_light) { - vec3 light_rel_vec = lights.data[idx].position - vertex; float light_length = length(light_rel_vec); float normalized_distance = light_length * lights.data[idx].inv_radius; @@ -1158,7 +1157,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #endif inout vec3 diffuse_light, inout vec3 specular_light) { - vec3 light_rel_vec = lights.data[idx].position - vertex; float light_length = length(light_rel_vec); float normalized_distance = light_length * lights.data[idx].inv_radius; diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp index 4480b79f75..ffc1ec391d 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/rendering_server_canvas.cpp @@ -68,7 +68,11 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can RENDER_TIMESTAMP("Render Canvas Items"); - RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); + bool sdf_flag; + RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, sdf_flag); + if (sdf_flag) { + sdf_used = true; + } } void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) { @@ -115,7 +119,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo Rect2 rect = ci->get_rect(); Transform2D xform = ci->xform; if (snapping_2d_transforms_to_pixel) { - xform.elements[2].floor(); + xform.elements[2] = xform.elements[2].floor(); } xform = p_transform * xform; @@ -301,6 +305,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) { RENDER_TIMESTAMP(">Render Canvas"); + sdf_used = false; snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel; if (p_canvas->children_order_dirty) { @@ -347,6 +352,10 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, RENDER_TIMESTAMP("<End Render Canvas"); } +bool RenderingServerCanvas::was_sdf_used() { + return sdf_used; +} + RID RenderingServerCanvas::canvas_create() { Canvas *canvas = memnew(Canvas); ERR_FAIL_COND_V(!canvas, RID()); @@ -582,7 +591,6 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po } for (int i = 0; i < p_points.size(); i++) { - Vector2 t; if (i == p_points.size() - 1) { t = prev_t; @@ -608,7 +616,6 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po pline->triangles.write[i * 2 + 1] = p_points[i] - tangent; if (pline->triangle_colors.size() > 1) { - pline->triangle_colors.write[i * 2 + 0] = p_colors[i]; pline->triangle_colors.write[i * 2 + 1] = p_colors[i]; } @@ -1268,6 +1275,11 @@ void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RI } } +void RenderingServerCanvas::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) { + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); +} + void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) { RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); @@ -1289,53 +1301,24 @@ RID RenderingServerCanvas::canvas_occluder_polygon_create() { } void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) { - if (p_shape.size() < 3) { - canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape); - return; - } - - Vector<Vector2> lines; - int lc = p_shape.size() * 2; - - lines.resize(lc - (p_closed ? 0 : 2)); - { - Vector2 *w = lines.ptrw(); - const Vector2 *r = p_shape.ptr(); - - int max = lc / 2; - if (!p_closed) { - max--; - } - for (int i = 0; i < max; i++) { - Vector2 a = r[i]; - Vector2 b = r[(i + 1) % (lc / 2)]; - w[i * 2 + 0] = a; - w[i * 2 + 1] = b; - } - } - - canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines); -} - -void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) { LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); ERR_FAIL_COND(!occluder_poly); - ERR_FAIL_COND(p_shape.size() & 1); - int lc = p_shape.size(); + uint32_t pc = p_shape.size(); + ERR_FAIL_COND(pc < 2); + occluder_poly->aabb = Rect2(); - { - const Vector2 *r = p_shape.ptr(); - for (int i = 0; i < lc; i++) { - if (i == 0) { - occluder_poly->aabb.position = r[i]; - } else { - occluder_poly->aabb.expand_to(r[i]); - } + const Vector2 *r = p_shape.ptr(); + for (uint32_t i = 0; i < pc; i++) { + if (i == 0) { + occluder_poly->aabb.position = r[i]; + } else { + occluder_poly->aabb.expand_to(r[i]); } } - RSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape); + RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed); + for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->aabb_cache = occluder_poly->aabb; } diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h index 36e2f77e95..83b76539c4 100644 --- a/servers/rendering/rendering_server_canvas.h +++ b/servers/rendering/rendering_server_canvas.h @@ -153,6 +153,7 @@ public: RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner; bool disable_scale; + bool sdf_used = false; bool snapping_2d_transforms_to_pixel = false; private: @@ -165,6 +166,8 @@ private: public: void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel); + bool was_sdf_used(); + RID canvas_create(); void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); void canvas_set_modulate(RID p_canvas, const Color &p_color); @@ -247,12 +250,12 @@ public: void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas); void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled); void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon); + void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable); void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform); void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask); RID canvas_occluder_polygon_create(); void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed); - void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape); void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index daad706f8e..413fcda581 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -41,7 +41,6 @@ class RenderingServerRaster : public RenderingServer { enum { - MAX_INSTANCE_CULL = 8192, MAX_INSTANCE_LIGHTS = 4, LIGHT_CACHE_DIRTY = -1, @@ -537,6 +536,7 @@ public: BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &) BIND4(viewport_set_canvas_stacking, RID, RID, int, int) BIND2(viewport_set_shadow_atlas_size, RID, int) + BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale) BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) BIND2(viewport_set_msaa, RID, ViewportMSAA) BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) @@ -777,12 +777,12 @@ public: BIND2(canvas_light_occluder_attach_to_canvas, RID, RID) BIND2(canvas_light_occluder_set_enabled, RID, bool) BIND2(canvas_light_occluder_set_polygon, RID, RID) + BIND2(canvas_light_occluder_set_as_sdf_collision, RID, bool) BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &) BIND2(canvas_light_occluder_set_light_mask, RID, int) BIND0R(RID, canvas_occluder_polygon_create) BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool) - BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &) BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index a30aac3bb1..646b2a666f 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -45,7 +45,6 @@ class RenderingServerScene { public: enum { - MAX_INSTANCE_CULL = 65536, MAX_LIGHTS_CULLED = 4096, MAX_REFLECTION_PROBES_CULLED = 4096, diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp index c6682b1fcd..c048aa381f 100644 --- a/servers/rendering/rendering_server_viewport.cpp +++ b/servers/rendering/rendering_server_viewport.cpp @@ -146,6 +146,36 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: RasterizerCanvas::Light *directional_lights = nullptr; RasterizerCanvas::Light *directional_lights_with_shadow = nullptr; + if (p_viewport->sdf_active) { + //process SDF + + Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target); + + RasterizerCanvas::LightOccluderInstance *occluders = nullptr; + + //make list of occluders + for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { + RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); + + for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + if (!F->get()->enabled) { + continue; + } + F->get()->xform_cache = xf * F->get()->xform; + + if (sdf_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) { + F->get()->next = occluders; + occluders = F->get(); + } + } + } + + RSG::canvas_render->render_sdf(p_viewport->render_target, occluders); + + p_viewport->sdf_active = false; // if used, gets set active again + } + Rect2 shadow_rect; int light_count = 0; @@ -195,7 +225,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } //guess this is not needed, but keeping because it may be - //RSG::canvas_render->light_internal_update(cl->light_internal, cl); } } @@ -256,7 +285,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: light = light->shadows_next_ptr; } - //RSG::canvas_render->reset_canvas(); RENDER_TIMESTAMP("<End rendering 2D Shadows"); } @@ -340,7 +368,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: light = light->shadows_next_ptr; } - //RSG::canvas_render->reset_canvas(); RENDER_TIMESTAMP("<Render Directional 2D Shadows"); } @@ -380,6 +407,9 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel); + if (RSG::canvas->was_sdf_used()) { + p_viewport->sdf_active = true; + } i++; if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { @@ -400,8 +430,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: _draw_3d(p_viewport, p_eye); } } - - //RSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); } if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) { @@ -925,6 +953,13 @@ void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RI viewport->texture_repeat = p_repeat; } +void RenderingServerViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale); +} + bool RenderingServerViewport::free(RID p_rid) { if (viewport_owner.owns(p_rid)) { Viewport *viewport = viewport_owner.getornull(p_rid); diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h index 081f63690b..ba55b2e66e 100644 --- a/servers/rendering/rendering_server_viewport.h +++ b/servers/rendering/rendering_server_viewport.h @@ -82,6 +82,8 @@ public: RID shadow_atlas; int shadow_atlas_size; + bool sdf_active; + uint64_t last_pass = 0; int render_info[RS::VIEWPORT_RENDER_INFO_MAX]; @@ -146,6 +148,7 @@ public: render_info[i] = 0; } use_xr = false; + sdf_active = false; time_cpu_begin = 0; time_cpu_end = 0; @@ -232,6 +235,8 @@ public: void viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter); void viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat); + void viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_over_size, RS::ViewportSDFScale p_scale); + void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time); void set_default_clear_color(const Color &p_color); diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index d27b851d1d..d33bdb043a 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -440,6 +440,8 @@ public: FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) FUNC2(viewport_set_shadow_atlas_size, RID, int) + FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale) + FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) FUNC2(viewport_set_msaa, RID, ViewportMSAA) FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) @@ -676,12 +678,12 @@ public: FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID) FUNC2(canvas_light_occluder_set_enabled, RID, bool) FUNC2(canvas_light_occluder_set_polygon, RID, RID) + FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool) FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &) FUNC2(canvas_light_occluder_set_light_mask, RID, int) FUNCRID(canvas_occluder_polygon) FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool) - FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &) FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 046c6ba580..1ab353c9d0 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2157,7 +2157,6 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, { nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false } - }; const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = { diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 4d21807735..bd61f2a549 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -252,6 +252,27 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; + { + ShaderLanguage::StageFunctionInfo func; + func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2)); + func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf"] = func; + func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["sdf_to_screen_uv"] = func; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["sdf_to_screen_uv"] = func; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf_normal"] = func; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf_normal"] = func; + } + + { + ShaderLanguage::StageFunctionInfo func; + func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2)); + func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["screen_uv_to_sdf"] = func; + } + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cc959afdaa..ea37e0c143 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1431,7 +1431,6 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p } #if 0 Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { - Vector<AABB> vec = RS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface); Array arr; for (int i = 0; i < vec.size(); i++) { @@ -1859,7 +1858,6 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create); ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape); - ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines); ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode); ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index d676a1ba01..236112c3fb 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -730,6 +730,23 @@ public: virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0; virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0; + enum ViewportSDFOversize { + VIEWPORT_SDF_OVERSIZE_100_PERCENT, + VIEWPORT_SDF_OVERSIZE_120_PERCENT, + VIEWPORT_SDF_OVERSIZE_150_PERCENT, + VIEWPORT_SDF_OVERSIZE_200_PERCENT, + VIEWPORT_SDF_OVERSIZE_MAX + }; + + enum ViewportSDFScale { + VIEWPORT_SDF_SCALE_100_PERCENT, + VIEWPORT_SDF_SCALE_50_PERCENT, + VIEWPORT_SDF_SCALE_25_PERCENT, + VIEWPORT_SDF_SCALE_MAX + }; + + virtual void viewport_set_sdf_oversize_and_scale(RID p_viewport, ViewportSDFOversize p_oversize, ViewportSDFScale p_scale) = 0; + virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0; virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; @@ -1245,12 +1262,12 @@ public: virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0; virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0; virtual void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) = 0; + virtual void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) = 0; virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0; virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0; virtual RID canvas_occluder_polygon_create() = 0; virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) = 0; - virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) = 0; enum CanvasOccluderPolygonCullMode { CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, |