diff options
Diffstat (limited to 'servers')
39 files changed, 13065 insertions, 7756 deletions
diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h index 60af87e6f4..c416d3393f 100644 --- a/servers/audio/audio_server_sw.h +++ b/servers/audio/audio_server_sw.h @@ -53,7 +53,7 @@ class AudioServerSW : public AudioServer { virtual AudioMixer *get_mixer(); virtual void audio_mixer_chunk_callback(int p_frames); - struct Voice { + struct Voice : public RID_Data { float volume; volatile bool active; @@ -67,7 +67,7 @@ class AudioServerSW : public AudioServer { mutable RID_Owner<Voice> voice_owner; SelfList<Voice>::List active_list; - struct Stream { + struct Stream : public RID_Data { bool active; List<Stream*>::Element *E; AudioStream *audio_stream; diff --git a/servers/audio/sample_manager_sw.h b/servers/audio/sample_manager_sw.h index c0b5661a1c..ad71723cd6 100644 --- a/servers/audio/sample_manager_sw.h +++ b/servers/audio/sample_manager_sw.h @@ -74,7 +74,7 @@ public: class SampleManagerMallocSW : public SampleManagerSW { - struct Sample { + struct Sample : public RID_Data { void *data; int length; diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp index e747ea93ad..60fbf926bd 100644 --- a/servers/physics/broad_phase_octree.cpp +++ b/servers/physics/broad_phase_octree.cpp @@ -29,7 +29,7 @@ #include "broad_phase_octree.h" #include "collision_object_sw.h" -ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) { +BroadPhaseSW::ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) { ID oid = octree.create(p_object,AABB(),p_subindex,false,1<<p_object->get_type(),0); return oid; diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h index e178de441d..adc17cb753 100644 --- a/servers/physics/constraint_sw.h +++ b/servers/physics/constraint_sw.h @@ -31,7 +31,7 @@ #include "body_sw.h" -class ConstraintSW { +class ConstraintSW : public RID_Data { BodySW **_body_ptr; int _body_count; diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h index 5328a0b976..d031a9fb9b 100644 --- a/servers/physics/shape_sw.h +++ b/servers/physics/shape_sw.h @@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat class ShapeSW; -class ShapeOwnerSW { +class ShapeOwnerSW : public RID_Data { public: virtual void _shape_changed()=0; @@ -56,7 +56,7 @@ public: }; -class ShapeSW { +class ShapeSW : public RID_Data { RID self; AABB aabb; diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index 1180d787e5..21973b785e 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -58,7 +58,7 @@ public: -class SpaceSW { +class SpaceSW : public RID_Data { public: diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp index de2e89ce82..e1f6f4f92b 100644 --- a/servers/physics_2d/broad_phase_2d_basic.cpp +++ b/servers/physics_2d/broad_phase_2d_basic.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "broad_phase_2d_basic.h" -ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) { +BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) { current++; diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h index 9750b87249..4436f1f689 100644 --- a/servers/physics_2d/constraint_2d_sw.h +++ b/servers/physics_2d/constraint_2d_sw.h @@ -31,7 +31,7 @@ #include "body_2d_sw.h" -class Constraint2DSW { +class Constraint2DSW : public RID_Data { Body2DSW **_body_ptr; int _body_count; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 7857716634..a3e4ef94b3 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat class Shape2DSW; -class ShapeOwner2DSW { +class ShapeOwner2DSW : public RID_Data{ public: virtual void _shape_changed()=0; @@ -55,7 +55,7 @@ public: virtual ~ShapeOwner2DSW() {} }; -class Shape2DSW { +class Shape2DSW : public RID_Data { RID self; Rect2 aabb; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index b7976c589c..7fa9e17eea 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -59,7 +59,7 @@ public: -class Space2DSW { +class Space2DSW : public RID_Data { public: diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 21514a7f98..f3ff2223ed 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -36,7 +36,7 @@ #include "spatial_sound_server.h" #include "spatial_sound_2d_server.h" #include "script_debugger_remote.h" - +#include "visual/shader_types.h" static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsage>* r_usage) { List<VS::TextureInfo> tinfo; @@ -55,6 +55,8 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag } +ShaderTypes *shader_types=NULL; + void register_server_types() { Globals::get_singleton()->add_singleton( Globals::Singleton("VisualServer",VisualServer::get_singleton()) ); @@ -70,6 +72,8 @@ void register_server_types() { Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSound2DServer",SpatialSound2DServer::get_singleton()) ); Globals::get_singleton()->add_singleton( Globals::Singleton("SS2D",SpatialSound2DServer::get_singleton()) ); + shader_types = memnew( ShaderTypes ); + ObjectTypeDB::register_virtual_type<Physics2DDirectBodyState>(); ObjectTypeDB::register_virtual_type<Physics2DDirectSpaceState>(); @@ -87,5 +91,5 @@ void register_server_types() { void unregister_server_types(){ - + memdelete( shader_types ); } diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h index c9780607f0..c16753135b 100644 --- a/servers/spatial_sound/spatial_sound_server_sw.h +++ b/servers/spatial_sound/spatial_sound_server_sw.h @@ -67,7 +67,7 @@ class SpatialSoundServerSW : public SpatialSoundServer { struct Room; - struct Space { + struct Space : public RID_Data { RID default_room; Set<RID> rooms; @@ -79,7 +79,7 @@ class SpatialSoundServerSW : public SpatialSoundServer { mutable RID_Owner<Space> space_owner; - struct Room { + struct Room : public RID_Data{ RID space; Transform transform; Transform inverse_transform; @@ -97,7 +97,7 @@ class SpatialSoundServerSW : public SpatialSoundServer { - struct Source { + struct Source : public RID_Data { struct Voice { @@ -161,7 +161,7 @@ class SpatialSoundServerSW : public SpatialSoundServer { mutable RID_Owner<Source> source_owner; - struct Listener { + struct Listener : public RID_Data { RID space; Transform transform; diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h index fc595b7df0..ed28ec912e 100644 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h +++ b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h @@ -66,7 +66,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer { struct Room; - struct Space { + struct Space : public RID_Data { RID default_room; Set<RID> rooms; @@ -78,7 +78,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer { mutable RID_Owner<Space> space_owner; - struct Room { + struct Room : public RID_Data { RID space; Matrix32 transform; Matrix32 inverse_transform; @@ -96,7 +96,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer { - struct Source { + struct Source : public RID_Data { struct Voice { @@ -160,7 +160,7 @@ class SpatialSound2DServerSW : public SpatialSound2DServer { mutable RID_Owner<Source> source_owner; - struct Listener { + struct Listener : public RID_Data { RID space; Matrix32 transform; diff --git a/servers/visual/particle_system_sw.cpp b/servers/visual/particle_system_sw.cpp deleted file mode 100644 index 9f26589ff2..0000000000 --- a/servers/visual/particle_system_sw.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/*************************************************************************/ -/* particle_system_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "particle_system_sw.h" -#include "sort.h" - - -ParticleSystemSW::ParticleSystemSW() { - - amount=8; - emitting=true; - - for (int i=0;i<VS::PARTICLE_VAR_MAX;i++) { - particle_randomness[i]=0.0; - } - - particle_vars[VS::PARTICLE_LIFETIME]=2.0;// - particle_vars[VS::PARTICLE_SPREAD]=0.2;// - particle_vars[VS::PARTICLE_GRAVITY]=9.8;// - particle_vars[VS::PARTICLE_LINEAR_VELOCITY]=0.2;// - particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]=0.0;// - particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]=1.0;// - particle_vars[VS::PARTICLE_DAMPING]=0.0;// - particle_vars[VS::PARTICLE_INITIAL_SIZE]=1.0; - particle_vars[VS::PARTICLE_FINAL_SIZE]=0.8; - particle_vars[VS::PARTICLE_HEIGHT]=1; - particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]=1; - - height_from_velocity=false; - local_coordinates=false; - - particle_vars[VS::PARTICLE_INITIAL_ANGLE]=0.0;// - - gravity_normal=Vector3(0,-1.0,0); - //emission_half_extents=Vector3(0.1,0.1,0.1); - emission_half_extents=Vector3(1,1,1); - color_phase_count=0; - color_phases[0].pos=0.0; - color_phases[0].color=Color(1.0,0.0,0.0); - visibility_aabb=AABB(Vector3(-64,-64,-64),Vector3(128,128,128)); - - attractor_count=0; - -} - - -ParticleSystemSW::~ParticleSystemSW() -{ -} - - -#define DEFAULT_SEED 1234567 - -_FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) { - - uint32_t k; - uint32_t s = (*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = s; - - float v=((float)((*seed) & 0xFFFFF))/(float)0xFFFFF; - v=v*2.0-1.0; - return v; -} - -_FORCE_INLINE_ static uint32_t _irand_from_seed(uint32_t *seed) { - - uint32_t k; - uint32_t s = (*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = s; - - return s; -} - -void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time) { - - valid=false; - if (p_system->amount<=0) { - ERR_EXPLAIN("Invalid amount of particles: "+itos(p_system->amount)); - ERR_FAIL_COND(p_system->amount<=0); - } - if (p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS) { - ERR_EXPLAIN("Invalid amount of particle attractors."); - ERR_FAIL_COND(p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS); - } - float lifetime = p_system->particle_vars[VS::PARTICLE_LIFETIME]; - if (lifetime<CMP_EPSILON) { - ERR_EXPLAIN("Particle system lifetime too small."); - ERR_FAIL_COND(lifetime<CMP_EPSILON); - } - valid=true; - int particle_count=MIN(p_system->amount,ParticleSystemSW::MAX_PARTICLES);; - - - int emission_point_count = p_system->emission_points.size(); - DVector<Vector3>::Read r; - if (emission_point_count) - r=p_system->emission_points.read(); - - if (particle_count!=particle_data.size()) { - - //clear the whole system if particle amount changed - particle_data.clear(); - particle_data.resize(p_system->amount); - particle_system_time=0; - } - - float next_time = particle_system_time+p_time; - - if (next_time > lifetime) - next_time=Math::fmod(next_time,lifetime); - - - ParticleData *pdata=&particle_data[0]; - Vector3 attractor_positions[VS::MAX_PARTICLE_ATTRACTORS]; - - for(int i=0;i<p_system->attractor_count;i++) { - - attractor_positions[i]=p_transform.xform(p_system->attractors[i].pos); - } - - - for(int i=0;i<particle_count;i++) { - - ParticleData &p=pdata[i]; - - float restart_time = (i * lifetime / p_system->amount); - - bool restart=false; - - if ( next_time < particle_system_time ) { - - if (restart_time > particle_system_time || restart_time < next_time ) - restart=true; - - } else if (restart_time > particle_system_time && restart_time < next_time ) { - restart=true; - } - - if (restart) { - - - if (p_system->emitting) { - if (emission_point_count==0) { //use AABB - if (p_system->local_coordinates) - p.pos = p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ); - else - p.pos = p_transform.xform( p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ) ); - } else { - //use preset positions - if (p_system->local_coordinates) - p.pos = r[_irand_from_seed(&rand_seed)%emission_point_count]; - else - p.pos = p_transform.xform( r[_irand_from_seed(&rand_seed)%emission_point_count] ); - } - - - float angle1 = _rand_from_seed(&rand_seed)*p_system->particle_vars[VS::PARTICLE_SPREAD]*Math_PI; - float angle2 = _rand_from_seed(&rand_seed)*20.0*Math_PI; // make it more random like - - Vector3 rot_xz=Vector3( Math::sin(angle1), 0.0, Math::cos(angle1) ); - Vector3 rot = Vector3( Math::cos(angle2)*rot_xz.x,Math::sin(angle2)*rot_xz.x, rot_xz.z); - - p.vel=(rot*p_system->particle_vars[VS::PARTICLE_LINEAR_VELOCITY]+rot*p_system->particle_randomness[VS::PARTICLE_LINEAR_VELOCITY]*_rand_from_seed(&rand_seed)); - if (!p_system->local_coordinates) - p.vel=p_transform.basis.xform( p.vel ); - - p.vel+=p_system->emission_base_velocity; - - p.rot=p_system->particle_vars[VS::PARTICLE_INITIAL_ANGLE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_ANGLE]*_rand_from_seed(&rand_seed); - p.active=true; - for(int r=0;r<PARTICLE_RANDOM_NUMBERS;r++) - p.random[r]=_rand_from_seed(&rand_seed); - - } else { - - p.pos=Vector3(); - p.rot=0; - p.vel=Vector3(); - p.active=false; - } - - } else { - - if (!p.active) - continue; - - Vector3 force; - //apply gravity - force=p_system->gravity_normal * (p_system->particle_vars[VS::PARTICLE_GRAVITY]+(p_system->particle_randomness[VS::PARTICLE_GRAVITY]*p.random[0])); - //apply linear acceleration - force+=p.vel.normalized() * (p_system->particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_LINEAR_ACCELERATION]*p.random[1]); - //apply radial acceleration - Vector3 org; - if (!p_system->local_coordinates) - org=p_transform.origin; - force+=(p.pos-org).normalized() * (p_system->particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_RADIAL_ACCELERATION]*p.random[2]); - //apply tangential acceleration - force+=(p.pos-org).cross(p_system->gravity_normal).normalized() * (p_system->particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_TANGENTIAL_ACCELERATION]*p.random[3]); - //apply attractor forces - for(int a=0;a<p_system->attractor_count;a++) { - - force+=(p.pos-attractor_positions[a]).normalized() * p_system->attractors[a].force; - } - - - p.vel+=force * p_time; - if (p_system->particle_vars[VS::PARTICLE_DAMPING]) { - - float v = p.vel.length(); - float damp = p_system->particle_vars[VS::PARTICLE_DAMPING] + p_system->particle_vars[VS::PARTICLE_DAMPING] * p_system->particle_randomness[VS::PARTICLE_DAMPING]; - v -= damp * p_time; - if (v<0) { - p.vel=Vector3(); - } else { - p.vel=p.vel.normalized() * v; - } - - } - p.rot+=(p_system->particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]+p_system->particle_randomness[VS::PARTICLE_ANGULAR_VELOCITY]*p.random[4]) *p_time; - p.pos+=p.vel * p_time; - } - } - - particle_system_time=Math::fmod( particle_system_time+p_time, lifetime ); - - -} - -ParticleSystemProcessSW::ParticleSystemProcessSW() { - - particle_system_time=0; - rand_seed=1234567; - valid=false; -} - - -struct _ParticleSorterSW { - - - _FORCE_INLINE_ bool operator()(const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_a,const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_b) const { - - return p_a->d > p_b->d; // draw from further away to closest - } -}; - -void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform) { - - ERR_FAIL_COND(p_process->particle_data.size() != p_system->amount); - ERR_FAIL_COND(p_system->amount<=0 || p_system->amount>=ParticleSystemSW::MAX_PARTICLES); - - const ParticleSystemProcessSW::ParticleData *pdata=&p_process->particle_data[0]; - float time_pos=p_process->particle_system_time/p_system->particle_vars[VS::PARTICLE_LIFETIME]; - - ParticleSystemSW::ColorPhase cphase[VS::MAX_PARTICLE_COLOR_PHASES]; - - float last=-1; - int col_count=0; - - for(int i=0;i<p_system->color_phase_count;i++) { - - if (p_system->color_phases[i].pos<=last) - break; - cphase[i]=p_system->color_phases[i]; - col_count++; - } - - - - - - Vector3 camera_z_axis = p_camera_transform.basis.get_axis(2); - - for(int i=0;i<p_system->amount;i++) { - - ParticleDrawInfo &pdi=draw_info[i]; - pdi.data=&pdata[i]; - pdi.transform.origin=pdi.data->pos; - if (p_system->local_coordinates) - pdi.transform.origin=p_system_transform.xform(pdi.transform.origin); - - pdi.d=-camera_z_axis.dot(pdi.transform.origin); - - // adjust particle size, color and rotation - - float time = ((float)i / p_system->amount); - if (time<time_pos) - time=time_pos-time; - else - time=(1.0-time)+time_pos; - - Vector3 up=p_camera_transform.basis.get_axis(1); // up determines the rotation - float up_scale=1.0; - - if (p_system->height_from_velocity) { - - Vector3 veld = pdi.data->vel; - Vector3 cam_z = camera_z_axis.normalized(); - float vc = Math::abs(veld.normalized().dot(cam_z)); - - if (vc<(1.0-CMP_EPSILON)) { - up = Plane(cam_z,0).project(veld).normalized(); - float h = p_system->particle_vars[VS::PARTICLE_HEIGHT]+p_system->particle_randomness[VS::PARTICLE_HEIGHT]*pdi.data->random[7]; - float velh = veld.length(); - h+=velh*(p_system->particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]+p_system->particle_randomness[VS::PARTICLE_HEIGHT_SPEED_SCALE]*pdi.data->random[7]); - - - up_scale=Math::lerp(1.0,h,(1.0-vc)); - } - - } else if (pdi.data->rot) { - - up.rotate(camera_z_axis,pdi.data->rot); - } - - { - // matrix - Vector3 v_z = (p_camera_transform.origin-pdi.transform.origin).normalized(); -// Vector3 v_z = (p_camera_transform.origin-pdi.data->pos).normalized(); - Vector3 v_y = up; - Vector3 v_x = v_y.cross(v_z); - v_y = v_z.cross(v_x); - v_x.normalize(); - v_y.normalize(); - - - float initial_scale, final_scale; - initial_scale = p_system->particle_vars[VS::PARTICLE_INITIAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_SIZE]*pdi.data->random[5]; - final_scale = p_system->particle_vars[VS::PARTICLE_FINAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_FINAL_SIZE]*pdi.data->random[6]; - float scale = initial_scale + time * (final_scale - initial_scale); - - pdi.transform.basis.set_axis(0,v_x * scale); - pdi.transform.basis.set_axis(1,v_y * scale * up_scale); - pdi.transform.basis.set_axis(2,v_z * scale); - } - - - - int cpos=0; - - while(cpos<col_count) { - - if (cphase[cpos].pos > time) - break; - cpos++; - } - - cpos--; - - - if (cpos==-1) - pdi.color=Color(1,1,1,1); - else { - if (cpos==col_count-1) - pdi.color=cphase[cpos].color; - else { - float diff = (cphase[cpos+1].pos-cphase[cpos].pos); - if (diff>0) - pdi.color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (time - cphase[cpos].pos) / diff ); - else - pdi.color=cphase[cpos+1].color; - } - } - - - draw_info_order[i]=&pdi; - - } - - - SortArray<ParticleDrawInfo*,_ParticleSorterSW> particle_sort; - particle_sort.sort(&draw_info_order[0],p_system->amount); - -} diff --git a/servers/visual/particle_system_sw.h b/servers/visual/particle_system_sw.h deleted file mode 100644 index 8f4a5f8ec7..0000000000 --- a/servers/visual/particle_system_sw.h +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************/ -/* particle_system_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef PARTICLE_SYSTEM_SW_H -#define PARTICLE_SYSTEM_SW_H - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -#include "servers/visual_server.h" - -struct ParticleSystemSW { - enum { - - MAX_PARTICLES=1024 - }; - - float particle_vars[VS::PARTICLE_VAR_MAX]; - float particle_randomness[VS::PARTICLE_VAR_MAX]; - - Vector3 emission_half_extents; - DVector<Vector3> emission_points; - Vector3 gravity_normal; - Vector3 emission_base_velocity; - int amount; - bool emitting; - bool height_from_velocity; - AABB visibility_aabb; - bool sort; - bool local_coordinates; - - struct ColorPhase { - - float pos; - Color color; - ColorPhase() { pos=1.0; color=Color(0.0,0.0,1.0,1.0); } - }; - - int color_phase_count; - ColorPhase color_phases[VS::MAX_PARTICLE_COLOR_PHASES]; - - - struct Attractor { - - Vector3 pos; - float force; - }; - - int attractor_count; - Attractor attractors[VS::MAX_PARTICLE_ATTRACTORS]; - - - ParticleSystemSW(); - ~ParticleSystemSW(); - -}; - - -struct ParticleSystemProcessSW { - - enum { - PARTICLE_RANDOM_NUMBERS = 8, - }; - - struct ParticleData { - - Vector3 pos; - Vector3 vel; - float rot; - bool active; - float random[PARTICLE_RANDOM_NUMBERS]; - - ParticleData() { active=0; rot=0; } - }; - - - bool valid; - float particle_system_time; - uint32_t rand_seed; - Vector<ParticleData> particle_data; - - void process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time); - - ParticleSystemProcessSW(); -}; - -struct ParticleSystemDrawInfoSW { - - struct ParticleDrawInfo { - - const ParticleSystemProcessSW::ParticleData *data; - float d; - Transform transform; - Color color; - - }; - - ParticleDrawInfo draw_info[ParticleSystemSW::MAX_PARTICLES]; - ParticleDrawInfo *draw_info_order[ParticleSystemSW::MAX_PARTICLES]; - - void prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform); - -}; - -#endif diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index ed4bced760..1adf2ee021 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -30,6 +30,23 @@ #include "print_string.h" #include "os/os.h" + +Rasterizer* (*Rasterizer::_create_func)()=NULL; + +Rasterizer *Rasterizer::create() { + + return _create_func(); +} + +RasterizerStorage*RasterizerStorage::base_signleton=NULL; + +RasterizerStorage::RasterizerStorage() { + + base_signleton=this; +} + +#if 0 + RID Rasterizer::create_default_material() { return material_create(); @@ -38,10 +55,10 @@ RID Rasterizer::create_default_material() { /* Fixed MAterial SHADER API */ -RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { +RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) { ERR_FAIL_COND_V(!p_key.valid,RID()); - Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); if (E) { E->get().refcount++; @@ -50,7 +67,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { uint64_t t = OS::get_singleton()->get_ticks_usec(); - FixedMaterialShader fms; + FixedSpatialMaterialShader fms; fms.refcount=1; fms.shader=shader_create(); @@ -296,12 +313,12 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { return fms.shader; } -void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) { +void Rasterizer::_free_shader(const FixedSpatialMaterialShaderKey& p_key) { if (p_key.valid==0) return; //not a valid key - Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); ERR_FAIL_COND(!E); E->get().refcount--; @@ -313,12 +330,12 @@ void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) { } -void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) { +void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); switch(p_flag) { @@ -334,11 +351,11 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags } -bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const{ +bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,false); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); switch(p_flag) { case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break; @@ -357,8 +374,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags RID Rasterizer::fixed_material_create() { RID mat = material_create(); - fixed_materials[mat]=memnew( FixedMaterial() ); - FixedMaterial &fm=*fixed_materials[mat]; + fixed_materials[mat]=memnew( FixedSpatialMaterial() ); + FixedSpatialMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); @@ -374,11 +391,11 @@ RID Rasterizer::fixed_material_create() { -void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value){ +void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value){ - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -401,24 +418,24 @@ void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialP } -Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const{ +Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Variant()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,Variant()); return fm.param[p_parameter]; } -void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture){ +void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture){ - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (!E) { print_line("Not found: "+itos(p_material.get_id())); } ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -433,22 +450,22 @@ void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialPara } -RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const{ +RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,RID()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,RID()); return fm.texture[p_parameter]; } -void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode) { +void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); fm.get_key(); @@ -460,11 +477,11 @@ void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMateri } -VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const { +VS::FixedSpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_TEXCOORD_UV); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,VS::FIXED_MATERIAL_TEXCOORD_UV); return fm.texture_tc[p_parameter]; @@ -472,9 +489,9 @@ VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_uv_xform_name,p_transform); @@ -487,18 +504,18 @@ void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& Transform Rasterizer::fixed_material_get_uv_transform(RID p_material) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Transform()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.uv_xform; } -void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader) { +void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); fm.light_shader=p_shader; @@ -507,20 +524,20 @@ void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMateria } -VS::FixedMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { +VS::FixedSpatialMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.light_shader; } void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_point_size_name,p_size); @@ -532,9 +549,9 @@ void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { float Rasterizer::fixed_material_get_point_size(RID p_material) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,1.0); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.point_size; @@ -545,9 +562,9 @@ void Rasterizer::_update_fixed_materials() { while(fixed_material_dirty_list.first()) { - FixedMaterial &fm=*fixed_material_dirty_list.first()->self(); + FixedSpatialMaterial &fm=*fixed_material_dirty_list.first()->self(); - FixedMaterialShaderKey new_key = fm.get_key(); + FixedSpatialMaterialShaderKey new_key = fm.get_key(); if (new_key.key!=fm.current_key.key) { _free_shader(fm.current_key); @@ -577,7 +594,7 @@ void Rasterizer::_update_fixed_materials() { void Rasterizer::_free_fixed_material(const RID& p_material) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (E) { @@ -620,7 +637,7 @@ Rasterizer::Rasterizer() { draw_viewport_func=NULL; - ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4); + ERR_FAIL_COND( sizeof(FixedSpatialMaterialShaderKey)!=4); } @@ -636,3 +653,5 @@ RID Rasterizer::create_overdraw_debug_material() { return mat; } + +#endif diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 27faea69bb..3b3cd4caa4 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -29,6 +29,918 @@ #ifndef RASTERIZER_H #define RASTERIZER_H + +#include "servers/visual_server.h" +#include "camera_matrix.h" + +#include "self_list.h" + + +class RasterizerScene { +public: + + /* SHADOW ATLAS API */ + + virtual RID shadow_atlas_create()=0; + virtual void shadow_atlas_set_size(RID p_atlas,int p_size)=0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision)=0; + virtual bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version)=0; + + virtual int get_directional_light_shadow_size(RID p_light_intance)=0; + virtual void set_directional_shadow_count(int p_count)=0; + + /* ENVIRONMENT API */ + + virtual RID environment_create()=0; + + virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg)=0; + virtual void environment_set_skybox(RID p_env,RID p_skybox)=0; + virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0; + virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0; + virtual void environment_set_bg_energy(RID p_env,float p_energy)=0; + virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0; + virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0; + + virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0; + virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0; + + virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; + virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0; + + virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale)=0; + + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; + + struct InstanceBase : RID_Data { + + VS::InstanceType base_type; + RID base; + + RID skeleton; + RID material_override; + + Transform transform; + + int depth_layer; + uint32_t layer_mask; + + //RID sampled_light; + + Vector<RID> materials; + Vector<RID> light_instances; + Vector<RID> reflection_probe_instances; + Vector<RID> gi_probe_instances; + + Vector<float> morph_values; + + //BakedLightData *baked_light; + VS::ShadowCastingSetting cast_shadows; + //Transform *baked_light_octree_xform; + //int baked_lightmap_id; + + bool mirror :8; + bool depth_scale :8; + bool billboard :8; + bool billboard_y :8; + bool receive_shadows : 8; + + float depth; //used for sorting + + SelfList<InstanceBase> dependency_item; + InstanceBase *baked_light; //baked light to use + SelfList<InstanceBase> baked_light_item; + + virtual void base_removed()=0; + virtual void base_changed()=0; + virtual void base_material_changed()=0; + + InstanceBase() : dependency_item(this), baked_light_item(this) { + + base_type=VS::INSTANCE_NONE; + cast_shadows=VS::SHADOW_CASTING_SETTING_ON; + receive_shadows=true; + depth_scale=false; + billboard=false; + billboard_y=false; + depth_layer=0; + layer_mask=1; + baked_light=NULL; + + } + }; + + virtual RID light_instance_create(RID p_light)=0; + virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform)=0; + virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass)=0; + virtual void light_instance_mark_visible(RID p_light_instance)=0; + + virtual RID reflection_atlas_create()=0; + virtual void reflection_atlas_set_size(RID p_ref_atlas,int p_size)=0; + virtual void reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv)=0; + + virtual RID reflection_probe_instance_create(RID p_probe)=0; + virtual void reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform)=0; + virtual void reflection_probe_release_atlas_index(RID p_instance)=0; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance)=0; + virtual bool reflection_probe_instance_has_reflection(RID p_instance)=0; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas)=0; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0; + + virtual RID gi_probe_instance_create()=0; + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data)=0; + virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform)=0; + virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds)=0; + + virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass)=0; + virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count)=0; + + virtual void set_scene_pass(uint64_t p_pass)=0; + + virtual bool free(RID p_rid)=0; + + virtual ~RasterizerScene() {} +}; + + + + + + + +class RasterizerStorage { +public: + /* TEXTURE API */ + + virtual RID texture_create()=0; + virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT)=0; + virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT)=0; + virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const=0; + virtual void texture_set_flags(RID p_texture,uint32_t p_flags)=0; + virtual uint32_t texture_get_flags(RID p_texture) const=0; + virtual Image::Format texture_get_format(RID p_texture) const=0; + virtual uint32_t texture_get_width(RID p_texture) const=0; + virtual uint32_t texture_get_height(RID p_texture) const=0; + virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; + + virtual void texture_set_path(RID p_texture,const String& p_path)=0; + virtual String texture_get_path(RID p_texture) const=0; + + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0; + + virtual void texture_debug_usage(List<VS::TextureInfo> *r_info)=0; + + virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const=0; + + + virtual void textures_keep_original(bool p_enable)=0; + + /* SKYBOX API */ + + virtual RID skybox_create()=0; + virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0; + + /* SHADER API */ + + + virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL)=0; + + virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode)=0; + virtual VS::ShaderMode shader_get_mode(RID p_shader) const=0; + + virtual void shader_set_code(RID p_shader, const String& p_code)=0; + virtual String shader_get_code(RID p_shader) const=0; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + + + /* COMMON MATERIAL API */ + + virtual RID material_create()=0; + + virtual void material_set_shader(RID p_shader_material, RID p_shader)=0; + virtual RID material_get_shader(RID p_shader_material) const=0; + + virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; + virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0; + + virtual void material_set_line_width(RID p_material, float p_width)=0; + + virtual bool material_is_animated(RID p_material)=0; + virtual bool material_casts_shadows(RID p_material)=0; + + virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0; + virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0; + + /* MESH API */ + + virtual RID mesh_create()=0; + + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>())=0; + + virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount)=0; + virtual int mesh_get_morph_target_count(RID p_mesh) const=0; + + + virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode)=0; + virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const=0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0; + + virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0; + virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0; + + virtual DVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0; + virtual DVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0; + + + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0; + virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0; + + virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0; + virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0; + virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0; + + virtual void mesh_remove_surface(RID p_mesh,int p_index)=0; + virtual int mesh_get_surface_count(RID p_mesh) const=0; + + virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb)=0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const=0; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const=0; + virtual void mesh_clear(RID p_mesh)=0; + + /* MULTIMESH API */ + + + virtual RID multimesh_create()=0; + + virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format)=0; + virtual int multimesh_get_instance_count(RID p_multimesh) const=0; + + virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0; + virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Matrix32& p_transform)=0; + virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const=0; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0; + virtual Matrix32 multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0; + virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0; + + virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const=0; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const=0; + + /* IMMEDIATE API */ + + virtual RID immediate_create()=0; + virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID())=0; + virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0; + virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0; + virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0; + virtual void immediate_color(RID p_immediate,const Color& p_color)=0; + virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0; + virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0; + virtual void immediate_end(RID p_immediate)=0; + virtual void immediate_clear(RID p_immediate)=0; + virtual void immediate_set_material(RID p_immediate,RID p_material)=0; + virtual RID immediate_get_material(RID p_immediate) const=0; + virtual AABB immediate_get_aabb(RID p_immediate) const=0; + + + /* SKELETON API */ + + virtual RID skeleton_create()=0; + virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0; + virtual int skeleton_get_bone_count(RID p_skeleton) const=0; + virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const =0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform)=0; + virtual Matrix32 skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const=0; + + /* Light API */ + + virtual RID light_create(VS::LightType p_type)=0; + + virtual void light_set_color(RID p_light,const Color& p_color)=0; + virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value)=0; + virtual void light_set_shadow(RID p_light,bool p_enabled)=0; + virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0; + virtual void light_set_projector(RID p_light,RID p_texture)=0; + virtual void light_set_negative(RID p_light,bool p_enable)=0; + virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0; + + virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode)=0; + virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail)=0; + + virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode)=0; + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0; + virtual bool light_directional_get_blend_splits(RID p_light) const=0; + + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light)=0; + virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light)=0; + + virtual bool light_has_shadow(RID p_light) const=0; + + virtual VS::LightType light_get_type(RID p_light) const=0; + virtual AABB light_get_aabb(RID p_light) const=0; + virtual float light_get_param(RID p_light,VS::LightParam p_param)=0; + virtual Color light_get_color(RID p_light)=0; + virtual uint64_t light_get_version(RID p_light) const=0; + + + /* PROBE API */ + + virtual RID reflection_probe_create()=0; + + virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode)=0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient)=0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0; + + virtual AABB reflection_probe_get_aabb(RID p_probe) const=0; + virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const=0; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const=0; + virtual Vector3 reflection_probe_get_extents(RID p_probe) const=0; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const=0; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const=0; + virtual bool reflection_probe_renders_shadows(RID p_probe) const=0; + + + /* ROOM API */ + + virtual RID room_create()=0; + virtual void room_add_bounds(RID p_room, const DVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0; + virtual void room_clear_bounds(RID p_room)=0; + + /* PORTAL API */ + + // portals are only (x/y) points, forming a convex shape, which its clockwise + // order points outside. (z is 0)=0; + + virtual RID portal_create()=0; + virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0; + virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0; + virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; + virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; + + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + + virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; + + /* GI PROBE API */ + + virtual RID gi_probe_create()=0; + + virtual void gi_probe_set_bounds(RID p_probe,const AABB& p_bounds)=0; + virtual AABB gi_probe_get_bounds(RID p_probe) const=0; + + virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0; + virtual float gi_probe_get_cell_size(RID p_probe) const=0; + + virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0; + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0; + + virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data)=0; + virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0; + + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; + + virtual void gi_probe_set_energy(RID p_probe,float p_range)=0; + virtual float gi_probe_get_energy(RID p_probe) const=0; + + virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; + + virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_compressed(RID p_probe) const=0; + + virtual uint32_t gi_probe_get_version(RID p_probe)=0; + + enum GIProbeCompression { + GI_PROBE_UNCOMPRESSED, + GI_PROBE_S3TC, + GI_PROBE_ETC2 + }; + + virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const=0; + virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth,GIProbeCompression p_compression)=0; + virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data)=0; + + + /* PARTICLES */ + + virtual RID particles_create()=0; + + virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0; + virtual void particles_set_amount(RID p_particles,int p_amount)=0; + virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0; + virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0; + virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_custom_aabb(RID p_particles,const AABB& p_aabb)=0; + virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0; + virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0; + virtual void particles_set_process_material(RID p_particles,RID p_material)=0; + + virtual void particles_set_emission_shape(RID p_particles,VS::ParticlesEmissionShape p_shape)=0; + virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0; + virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0; + virtual void particles_set_emission_points(RID p_particles,const DVector<Vector3>& p_points)=0; + + + virtual void particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order)=0; + + virtual void particles_set_draw_passes(RID p_particles,int p_count)=0; + virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0; + virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0; + + virtual AABB particles_get_current_aabb(RID p_particles)=0; + + + + /* RENDER TARGET */ + + enum RenderTargetFlags { + RENDER_TARGET_VFLIP, + RENDER_TARGET_TRANSPARENT, + RENDER_TARGET_NO_3D, + RENDER_TARGET_NO_SAMPLING, + RENDER_TARGET_HDR, + RENDER_TARGET_FLAG_MAX + }; + + virtual RID render_target_create()=0; + virtual void render_target_set_size(RID p_render_target,int p_width, int p_height)=0; + virtual RID render_target_get_texture(RID p_render_target) const=0; + virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value)=0; + virtual bool render_target_renedered_in_frame(RID p_render_target)=0; + virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa)=0; + + + /* CANVAS SHADOW */ + + virtual RID canvas_light_shadow_buffer_create(int p_width)=0; + + /* LIGHT SHADOW MAPPING */ + + virtual RID canvas_light_occluder_create()=0; + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0; + + + virtual VS::InstanceType get_base_type(RID p_rid) const=0; + virtual bool free(RID p_rid)=0; + + + static RasterizerStorage*base_signleton; + RasterizerStorage(); + virtual ~RasterizerStorage() {} +}; + + + + + +class RasterizerCanvas { +public: + + enum CanvasRectFlags { + + CANVAS_RECT_REGION=1, + CANVAS_RECT_TILE=2, + CANVAS_RECT_FLIP_H=4, + CANVAS_RECT_FLIP_V=8, + CANVAS_RECT_TRANSPOSE=16 + }; + + + struct Light : public RID_Data { + + + + bool enabled; + Color color; + Matrix32 xform; + float height; + float energy; + float scale; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + VS::CanvasLightMode mode; + RID texture; + Vector2 texture_offset; + RID canvas; + RID shadow_buffer; + int shadow_buffer_size; + float shadow_gradient_length; + VS::CanvasLightShadowFilter shadow_filter; + Color shadow_color; + + + void *texture_cache; // implementation dependent + Rect2 rect_cache; + Matrix32 xform_cache; + float radius_cache; //used for shadow far plane + CameraMatrix shadow_matrix_cache; + + Matrix32 light_shader_xform; + Vector2 light_shader_pos; + + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *mask_next_ptr; + + RID light_internal; + + Light() { + enabled=true; + color=Color(1,1,1); + shadow_color=Color(0,0,0,0); + height=0; + z_min=-1024; + z_max=1024; + layer_min=0; + layer_max=0; + item_mask=1; + scale=1.0; + energy=1.0; + item_shadow_mask=-1; + mode=VS::CANVAS_LIGHT_MODE_ADD; + texture_cache=NULL; + next_ptr=NULL; + mask_next_ptr=NULL; + filter_next_ptr=NULL; + shadow_buffer_size=256; + shadow_gradient_length=0; + shadow_filter=VS::CANVAS_LIGHT_FILTER_NONE; + + } + }; + + virtual RID light_internal_create()=0; + virtual void light_internal_update(RID p_rid, Light* p_light)=0; + virtual void light_internal_free(RID p_rid)=0; + + struct Item : public RID_Data { + + struct Command { + + enum Type { + + TYPE_LINE, + TYPE_RECT, + TYPE_NINEPATCH, + TYPE_PRIMITIVE, + TYPE_POLYGON, + TYPE_MESH, + TYPE_MULTIMESH, + TYPE_CIRCLE, + TYPE_TRANSFORM, + TYPE_CLIP_IGNORE, + }; + + Type type; + virtual ~Command(){} + }; + + struct CommandLine : public Command { + + Point2 from,to; + Color color; + float width; + bool antialiased; + CommandLine() { type = TYPE_LINE; } + }; + + struct CommandRect : public Command { + + Rect2 rect; + RID texture; + Color modulate; + Rect2 source; + uint8_t flags; + + CommandRect() { flags=0; type = TYPE_RECT; } + }; + + struct CommandNinePatch : public Command { + + Rect2 rect; + Rect2 source; + RID texture; + float margin[4]; + bool draw_center; + Color color; + VS::NinePatchAxisMode axis_x; + VS::NinePatchAxisMode axis_y; + CommandNinePatch() { draw_center=true; type = TYPE_NINEPATCH; } + }; + + struct CommandPrimitive : public Command { + + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + float width; + + CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} + }; + + struct CommandPolygon : public Command { + + Vector<int> indices; + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + int count; + + CommandPolygon() { type = TYPE_POLYGON; count = 0; } + }; + + + struct CommandMesh : public Command { + + RID mesh; + RID skeleton; + CommandMesh() { type = TYPE_MESH; } + }; + + struct CommandMultiMesh : public Command { + + RID multimesh; + RID skeleton; + CommandMultiMesh() { type = TYPE_MULTIMESH; } + }; + + struct CommandCircle : public Command { + + Point2 pos; + float radius; + Color color; + CommandCircle() { type = TYPE_CIRCLE; } + }; + + struct CommandTransform : public Command { + + Matrix32 xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + + struct CommandClipIgnore : public Command { + + bool ignore; + CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; } + }; + + + struct ViewportRender { + VisualServer*owner; + void* udata; + Rect2 rect; + }; + + Matrix32 xform; + bool clip; + bool visible; + bool behind; + //VS::MaterialBlendMode blend_mode; + int light_mask; + Vector<Command*> commands; + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + RID material; + Item*next; + + struct CopyBackBuffer { + Rect2 rect; + Rect2 screen_rect; + bool full; + }; + CopyBackBuffer *copy_back_buffer; + + + Color final_modulate; + Matrix32 final_transform; + Rect2 final_clip_rect; + Item* final_clip_owner; + Item* material_owner; + ViewportRender *vp_render; + bool distance_field; + bool light_masked; + + Rect2 global_rect_cache; + + const Rect2& get_rect() const { + if (custom_rect || !rect_dirty) + return rect; + + //must update rect + int s=commands.size(); + if (s==0) { + + rect=Rect2(); + rect_dirty=false; + return rect; + } + + Matrix32 xf; + bool found_xform=false; + bool first=true; + + const Item::Command * const *cmd = &commands[0]; + + + for (int i=0;i<s;i++) { + + const Item::Command *c=cmd[i]; + Rect2 r; + + switch(c->type) { + case Item::Command::TYPE_LINE: { + + const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c); + r.pos=line->from; + r.expand_to(line->to); + } break; + case Item::Command::TYPE_RECT: { + + const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c); + r=crect->rect; + + } break; + case Item::Command::TYPE_NINEPATCH: { + + const Item::CommandNinePatch* style = static_cast< const Item::CommandNinePatch*>(c); + r=style->rect; + } break; + case Item::Command::TYPE_PRIMITIVE: { + + const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c); + r.pos=primitive->points[0]; + for(int i=1;i<primitive->points.size();i++) { + + r.expand_to(primitive->points[i]); + + } + } break; + case Item::Command::TYPE_POLYGON: { + + const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c); + int l = polygon->points.size(); + const Point2*pp=&polygon->points[0]; + r.pos=pp[0]; + for(int i=1;i<l;i++) { + + r.expand_to(pp[i]); + + } + } break; + case Item::Command::TYPE_MESH: { + + const Item::CommandMesh* mesh = static_cast< const Item::CommandMesh*>(c); + AABB aabb = RasterizerStorage::base_signleton->mesh_get_aabb(mesh->mesh,mesh->skeleton); + + r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y); + + } break; + case Item::Command::TYPE_MULTIMESH: { + + const Item::CommandMultiMesh* multimesh = static_cast< const Item::CommandMultiMesh*>(c); + AABB aabb = RasterizerStorage::base_signleton->multimesh_get_aabb(multimesh->multimesh); + + r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y); + + } break; + case Item::Command::TYPE_CIRCLE: { + + const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c); + r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; + r.size=Point2(circle->radius*2.0,circle->radius*2.0); + } break; + case Item::Command::TYPE_TRANSFORM: { + + const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c); + xf=transform->xform; + found_xform=true; + continue; + } break; + + case Item::Command::TYPE_CLIP_IGNORE: { + + } break; + } + + if (found_xform) { + r = xf.xform(r); + found_xform=false; + } + + + if (first) { + rect=r; + first=false; + } else + rect=rect.merge(r); + } + + rect_dirty=false; + return rect; + } + + void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; } + Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_modulate=Color(1,1,1,1); visible=true; rect_dirty=true; custom_rect=false; behind=false; material_owner=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } + virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } + }; + + + virtual void canvas_begin()=0; + + virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0; + virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0; + + + + struct LightOccluderInstance : public RID_Data { + + + bool enabled; + RID canvas; + RID polygon; + RID polygon_buffer; + Rect2 aabb_cache; + Matrix32 xform; + Matrix32 xform_cache; + int light_mask; + VS::CanvasOccluderPolygonCullMode cull_cache; + + LightOccluderInstance *next; + + LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; + + + virtual void reset_canvas()=0; + + virtual ~RasterizerCanvas() {} +}; + + +class Rasterizer { +protected: + static Rasterizer* (*_create_func)(); +public: + static Rasterizer *create(); + + virtual RasterizerStorage *get_storage()=0; + virtual RasterizerCanvas *get_canvas()=0; + virtual RasterizerScene *get_scene()=0; + + virtual void initialize()=0; + virtual void begin_frame()=0; + virtual void set_current_render_target(RID p_render_target)=0; + virtual void restore_render_target()=0; + virtual void clear_render_target(const Color& p_color)=0; + virtual void blit_render_target_to_screen(RID p_render_target,const Rect2& p_screen_rect,int p_screen=0)=0; + virtual void end_frame()=0; + virtual void finalize()=0; + + + virtual ~Rasterizer() {} +}; + + +#if 0 /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -41,7 +953,7 @@ class Rasterizer { protected: - typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); + typedef void (*ItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); RID create_default_material(); RID create_overdraw_debug_material(); @@ -49,7 +961,7 @@ protected: /* Fixed Material Shader API */ - union FixedMaterialShaderKey { + union FixedSpatialMaterialShaderKey { struct { uint16_t texcoord_mask; @@ -65,21 +977,21 @@ protected: uint32_t key; - _FORCE_INLINE_ bool operator<(const FixedMaterialShaderKey& p_key) const { return key<p_key.key; } + _FORCE_INLINE_ bool operator<(const FixedSpatialMaterialShaderKey& p_key) const { return key<p_key.key; } }; - struct FixedMaterialShader { + struct FixedSpatialMaterialShader { int refcount; RID shader; }; - Map<FixedMaterialShaderKey,FixedMaterialShader> fixed_material_shaders; + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader> fixed_material_shaders; - RID _create_shader(const FixedMaterialShaderKey& p_key); - void _free_shader(const FixedMaterialShaderKey& p_key); + RID _create_shader(const FixedSpatialMaterialShaderKey& p_key); + void _free_shader(const FixedSpatialMaterialShaderKey& p_key); - struct FixedMaterial { + struct FixedSpatialMaterial { RID self; @@ -90,19 +1002,19 @@ protected: bool use_xy_normalmap; float point_size; Transform uv_xform; - VS::FixedMaterialLightShader light_shader; + VS::FixedSpatialMaterialLightShader light_shader; RID texture[VS::FIXED_MATERIAL_PARAM_MAX]; Variant param[VS::FIXED_MATERIAL_PARAM_MAX]; - VS::FixedMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; + VS::FixedSpatialMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; - SelfList<FixedMaterial> dirty_list; + SelfList<FixedSpatialMaterial> dirty_list; - FixedMaterialShaderKey current_key; + FixedSpatialMaterialShaderKey current_key; - _FORCE_INLINE_ FixedMaterialShaderKey get_key() const { + _FORCE_INLINE_ FixedSpatialMaterialShaderKey get_key() const { - FixedMaterialShaderKey k; + FixedSpatialMaterialShaderKey k; k.key=0; k.use_alpha=use_alpha; k.use_color_array=use_color_array; @@ -123,7 +1035,7 @@ protected: } - FixedMaterial() : dirty_list(this) { + FixedSpatialMaterial() : dirty_list(this) { use_alpha=false; use_color_array=false; @@ -155,9 +1067,9 @@ protected: StringName _fixed_material_uv_xform_name; StringName _fixed_material_point_size_name; - Map<RID,FixedMaterial*> fixed_materials; + Map<RID,FixedSpatialMaterial*> fixed_materials; - SelfList<FixedMaterial>::List fixed_material_dirty_list; + SelfList<FixedSpatialMaterial>::List fixed_material_dirty_list; protected: void _update_fixed_materials(); @@ -244,23 +1156,23 @@ public: virtual RID fixed_material_create(); - virtual void fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const; + virtual void fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled); + virtual bool fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const; - virtual void fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value); + virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture); + virtual RID fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode); - virtual VS::FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode); + virtual VS::FixedSpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); virtual Transform fixed_material_get_uv_transform(RID p_material) const; - virtual void fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader); - virtual VS::FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const; + virtual void fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader); + virtual VS::FixedSpatialMaterialLightShader fixed_material_get_light_shader(RID p_material) const; virtual void fixed_material_set_point_size(RID p_material,float p_size); virtual float fixed_material_get_point_size(RID p_material) const; @@ -581,7 +1493,7 @@ public: }; - struct CanvasLight { + struct Light { @@ -597,7 +1509,7 @@ public: int layer_max; int item_mask; int item_shadow_mask; - VS::CanvasLightMode mode; + VS::LightMode mode; RID texture; Vector2 texture_offset; RID canvas; @@ -616,12 +1528,12 @@ public: Matrix32 light_shader_xform; Vector2 light_shader_pos; - CanvasLight *shadows_next_ptr; - CanvasLight *filter_next_ptr; - CanvasLight *next_ptr; - CanvasLight *mask_next_ptr; + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *mask_next_ptr; - CanvasLight() { + Light() { enabled=true; color=Color(1,1,1); shadow_color=Color(0,0,0,0); @@ -645,20 +1557,20 @@ public: } }; - struct CanvasItem; + struct Item; - struct CanvasItemMaterial { + struct ItemMaterial { RID shader; Map<StringName,Variant> shader_param; uint32_t shader_version; - Set<CanvasItem*> owners; - VS::CanvasItemShadingMode shading_mode; + Set<Item*> owners; + VS::ItemShadingMode shading_mode; - CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; } + ItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; } }; - struct CanvasItem { + struct Item { struct Command { @@ -788,8 +1700,8 @@ public: mutable bool custom_rect; mutable bool rect_dirty; mutable Rect2 rect; - CanvasItem*next; - CanvasItemMaterial* material; + Item*next; + ItemMaterial* material; struct CopyBackBuffer { Rect2 rect; Rect2 screen_rect; @@ -801,8 +1713,8 @@ public: float final_opacity; Matrix32 final_transform; Rect2 final_clip_rect; - CanvasItem* final_clip_owner; - CanvasItem* material_owner; + Item* final_clip_owner; + Item* material_owner; ViewportRender *vp_render; bool distance_field; bool light_masked; @@ -826,35 +1738,35 @@ public: bool found_xform=false; bool first=true; - const CanvasItem::Command * const *cmd = &commands[0]; + const Item::Command * const *cmd = &commands[0]; for (int i=0;i<s;i++) { - const CanvasItem::Command *c=cmd[i]; + const Item::Command *c=cmd[i]; Rect2 r; switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { + case Item::Command::TYPE_LINE: { - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); + const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c); r.pos=line->from; r.expand_to(line->to); } break; - case CanvasItem::Command::TYPE_RECT: { + case Item::Command::TYPE_RECT: { - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); + const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c); r=crect->rect; } break; - case CanvasItem::Command::TYPE_STYLE: { + case Item::Command::TYPE_STYLE: { - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); + const Item::CommandStyle* style = static_cast< const Item::CommandStyle*>(c); r=style->rect; } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { + case Item::Command::TYPE_PRIMITIVE: { - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); + const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c); r.pos=primitive->points[0]; for(int i=1;i<primitive->points.size();i++) { @@ -862,9 +1774,9 @@ public: } } break; - case CanvasItem::Command::TYPE_POLYGON: { + case Item::Command::TYPE_POLYGON: { - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); + const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c); int l = polygon->points.size(); const Point2*pp=&polygon->points[0]; r.pos=pp[0]; @@ -875,9 +1787,9 @@ public: } } break; - case CanvasItem::Command::TYPE_POLYGON_PTR: { + case Item::Command::TYPE_POLYGON_PTR: { - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); + const Item::CommandPolygonPtr* polygon = static_cast< const Item::CommandPolygonPtr*>(c); int l = polygon->count; if (polygon->indices != NULL) { @@ -894,23 +1806,23 @@ public: } } } break; - case CanvasItem::Command::TYPE_CIRCLE: { + case Item::Command::TYPE_CIRCLE: { - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); + const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c); r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; r.size=Point2(circle->radius*2.0,circle->radius*2.0); } break; - case CanvasItem::Command::TYPE_TRANSFORM: { + case Item::Command::TYPE_TRANSFORM: { - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); + const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c); xf=transform->xform; found_xform=true; continue; } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { + case Item::Command::TYPE_BLEND_MODE: { } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { + case Item::Command::TYPE_CLIP_IGNORE: { } break; } @@ -933,12 +1845,12 @@ public: } void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; } - CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } - virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } + Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } + virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } }; - CanvasItemDrawViewportFunc draw_viewport_func; + ItemDrawViewportFunc draw_viewport_func; virtual void begin_canvas_bg()=0; @@ -956,8 +1868,8 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0; virtual void canvas_set_transform(const Matrix32& p_transform)=0; - virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0; - virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0; + virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0; + virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0; /* LIGHT SHADOW MAPPING */ virtual RID canvas_light_occluder_create()=0; @@ -966,7 +1878,7 @@ public: virtual RID canvas_light_shadow_buffer_create(int p_width)=0; - struct CanvasLightOccluderInstance { + struct LightOccluderInstance { bool enabled; @@ -979,14 +1891,14 @@ public: int light_mask; VS::CanvasOccluderPolygonCullMode cull_cache; - CanvasLightOccluderInstance *next; + LightOccluderInstance *next; - CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } }; - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; /* ENVIRONMENT */ @@ -1050,5 +1962,5 @@ public: }; - +#endif #endif diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp deleted file mode 100644 index cc045cfa46..0000000000 --- a/servers/visual/rasterizer_dummy.cpp +++ /dev/null @@ -1,1961 +0,0 @@ -/*************************************************************************/ -/* rasterizer_dummy.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "rasterizer_dummy.h" - -/* TEXTURE API */ - - -RID RasterizerDummy::texture_create() { - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture,RID()); - return texture_owner.make_rid( texture ); - -} - -void RasterizerDummy::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { - - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - texture->width=p_width; - texture->height=p_height; - texture->format=p_format; - texture->flags=p_flags; -} - -void RasterizerDummy::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->format != p_image.get_format() ); - - texture->image[p_cube_side]=p_image; - -} - -Image RasterizerDummy::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - - return texture->image[p_cube_side]; -} - -void RasterizerDummy::texture_set_flags(RID p_texture,uint32_t p_flags) { - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; - texture->flags=p_flags|cube; // can't remove a cube from being a cube - -} -uint32_t RasterizerDummy::texture_get_flags(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->flags; - -} -Image::Format RasterizerDummy::texture_get_format(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image::FORMAT_GRAYSCALE); - - return texture->format; -} -uint32_t RasterizerDummy::texture_get_width(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->width; -} -uint32_t RasterizerDummy::texture_get_height(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->height; -} - -bool RasterizerDummy::texture_has_alpha(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return false; - -} - -void RasterizerDummy::texture_set_size_override(RID p_texture,int p_width, int p_height) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - ERR_FAIL_COND(p_width<=0 || p_width>4096); - ERR_FAIL_COND(p_height<=0 || p_height>4096); - //real texture size is in alloc width and height -// texture->width=p_width; -// texture->height=p_height; - -} - -void RasterizerDummy::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { - - -} - -/* SHADER API */ - -/* SHADER API */ - -RID RasterizerDummy::shader_create(VS::ShaderMode p_mode) { - - Shader *shader = memnew( Shader ); - shader->mode=p_mode; - shader->fragment_line=0; - shader->vertex_line=0; - shader->light_line=0; - RID rid = shader_owner.make_rid(shader); - - return rid; - -} - - - -void RasterizerDummy::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { - - ERR_FAIL_INDEX(p_mode,3); - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - shader->mode=p_mode; - -} -VS::ShaderMode RasterizerDummy::shader_get_mode(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,VS::SHADER_MATERIAL); - return shader->mode; -} - -void RasterizerDummy::shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs,int p_fragment_ofs,int p_light_ofs) { - - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - shader->fragment_code=p_fragment; - shader->vertex_code=p_vertex; - shader->light_code=p_light; - shader->fragment_line=p_fragment_ofs; - shader->vertex_line=p_vertex_ofs; - shader->light_line=p_vertex_ofs; - -} - - -String RasterizerDummy::shader_get_vertex_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->vertex_code; - -} - -String RasterizerDummy::shader_get_fragment_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->fragment_code; - -} - -String RasterizerDummy::shader_get_light_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->light_code; - -} - -void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - -} - - -void RasterizerDummy::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { - -} - -RID RasterizerDummy::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const { - - return RID(); -} - -Variant RasterizerDummy::shader_get_default_param(RID p_shader, const StringName& p_name) { - - return Variant(); -} - -/* COMMON MATERIAL API */ - - -RID RasterizerDummy::material_create() { - - return material_owner.make_rid( memnew( Material ) ); -} - -void RasterizerDummy::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->shader=p_shader; - -} - -RID RasterizerDummy::material_get_shader(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,RID()); - return material->shader; -} - -void RasterizerDummy::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type()==Variant::NIL) - material->shader_params.erase(p_param); - else - material->shader_params[p_param]=p_value; -} -Variant RasterizerDummy::material_get_param(RID p_material, const StringName& p_param) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,Variant()); - - if (material->shader_params.has(p_param)) - return material->shader_params[p_param]; - else - return Variant(); -} - - -void RasterizerDummy::material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); - material->flags[p_flag]=p_enabled; - -} -bool RasterizerDummy::material_get_flag(RID p_material,VS::MaterialFlag p_flag) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,false); - ERR_FAIL_INDEX_V(p_flag,VS::MATERIAL_FLAG_MAX,false); - return material->flags[p_flag]; - - -} - -void RasterizerDummy::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->depth_draw_mode=p_mode; -} - -VS::MaterialDepthDrawMode RasterizerDummy::material_get_depth_draw_mode(RID p_material) const{ - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_DEPTH_DRAW_ALWAYS); - return material->depth_draw_mode; - -} - - -void RasterizerDummy::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->blend_mode=p_mode; - -} -VS::MaterialBlendMode RasterizerDummy::material_get_blend_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_BLEND_MODE_ADD); - return material->blend_mode; -} - -void RasterizerDummy::material_set_line_width(RID p_material,float p_line_width) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->line_width=p_line_width; - -} -float RasterizerDummy::material_get_line_width(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,0); - - return material->line_width; -} - -/* MESH API */ - - -RID RasterizerDummy::mesh_create() { - - - return mesh_owner.make_rid( memnew( Mesh ) ); -} - - -void RasterizerDummy::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); - ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); - - Surface s; - - - s.format=0; - - for(int i=0;i<p_arrays.size();i++) { - - if (p_arrays[i].get_type()==Variant::NIL) - continue; - - s.format|=(1<<i); - - if (i==VS::ARRAY_VERTEX) { - - Vector3Array v = p_arrays[i]; - int len = v.size(); - ERR_FAIL_COND(len==0); - Vector3Array::Read r = v.read(); - - - for(int i=0;i<len;i++) { - - if (i==0) - s.aabb.pos=r[0]; - else - s.aabb.expand_to(r[i]); - } - - } - } - - ERR_FAIL_COND((s.format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory - - s.data=p_arrays; - s.morph_data=p_blend_shapes; - s.primitive=p_primitive; - s.alpha_sort=p_alpha_sort; - s.morph_target_count=mesh->morph_target_count; - s.morph_format=s.format; - - - Surface *surface = memnew( Surface ); - *surface=s; - - mesh->surfaces.push_back(surface); - - -} - - - -void RasterizerDummy::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { - - ERR_EXPLAIN("Dummy Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL_V(); -} - -Array RasterizerDummy::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->data; - - -} -Array RasterizerDummy::mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->morph_data; - -} - - -void RasterizerDummy::mesh_set_morph_target_count(RID p_mesh,int p_amount) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_COND( mesh->surfaces.size()!=0 ); - - mesh->morph_target_count=p_amount; - -} - -int RasterizerDummy::mesh_get_morph_target_count(RID p_mesh) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->morph_target_count; - -} - -void RasterizerDummy::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->morph_target_mode=p_mode; - -} - -VS::MorphTargetMode RasterizerDummy::mesh_get_morph_target_mode(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED); - - return mesh->morph_target_mode; - -} - - - -void RasterizerDummy::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND( !surface); - - if (surface->material_owned && surface->material.is_valid()) - free(surface->material); - - surface->material_owned=p_owned; - surface->material=p_material; -} - -RID RasterizerDummy::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, RID() ); - - return surface->material; -} - -int RasterizerDummy::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; - return arr.size(); - -} - -int RasterizerDummy::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - IntArray arr = surface->data[VS::ARRAY_INDEX]; - return arr.size(); - -} -uint32_t RasterizerDummy::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, 0 ); - - return surface->format; -} -VS::PrimitiveType RasterizerDummy::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_POINTS); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, VS::PRIMITIVE_POINTS ); - - return surface->primitive; -} - -void RasterizerDummy::mesh_remove_surface(RID p_mesh,int p_index) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_index, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_index]; - ERR_FAIL_COND( !surface); - - memdelete( mesh->surfaces[p_index] ); - mesh->surfaces.remove(p_index); - -} -int RasterizerDummy::mesh_get_surface_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->surfaces.size(); -} - -AABB RasterizerDummy::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - AABB aabb; - - for (int i=0;i<mesh->surfaces.size();i++) { - - if (i==0) - aabb=mesh->surfaces[i]->aabb; - else - aabb.merge_with(mesh->surfaces[i]->aabb); - } - - return aabb; -} - -void RasterizerDummy::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb=p_aabb; -} - -AABB RasterizerDummy::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - return mesh->custom_aabb; - -} - -/* MULTIMESH API */ - -RID RasterizerDummy::multimesh_create() { - - return multimesh_owner.make_rid( memnew( MultiMesh )); -} - -void RasterizerDummy::multimesh_set_instance_count(RID p_multimesh,int p_count) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations - multimesh->elements.resize(p_count); - -} -int RasterizerDummy::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - - return multimesh->elements.size(); -} - -void RasterizerDummy::multimesh_set_mesh(RID p_multimesh,RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->mesh=p_mesh; - -} -void RasterizerDummy::multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->aabb=p_aabb; -} -void RasterizerDummy::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - multimesh->elements[p_index].xform=p_transform; - -} -void RasterizerDummy::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh) - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - multimesh->elements[p_index].color=p_color; - -} - -RID RasterizerDummy::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,RID()); - - return multimesh->mesh; -} -AABB RasterizerDummy::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,AABB()); - - return multimesh->aabb; -} - -Transform RasterizerDummy::multimesh_instance_get_transform(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Transform()); - - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Transform()); - - return multimesh->elements[p_index].xform; - -} -Color RasterizerDummy::multimesh_instance_get_color(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Color()); - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Color()); - - return multimesh->elements[p_index].color; -} - -void RasterizerDummy::multimesh_set_visible_instances(RID p_multimesh,int p_visible) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->visible=p_visible; - -} - -int RasterizerDummy::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - return multimesh->visible; - -} - -/* IMMEDIATE API */ - - -RID RasterizerDummy::immediate_create() { - - Immediate *im = memnew( Immediate ); - return immediate_owner.make_rid(im); - -} - -void RasterizerDummy::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ - - -} -void RasterizerDummy::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ - - -} -void RasterizerDummy::immediate_normal(RID p_immediate,const Vector3& p_normal){ - - -} -void RasterizerDummy::immediate_tangent(RID p_immediate,const Plane& p_tangent){ - - -} -void RasterizerDummy::immediate_color(RID p_immediate,const Color& p_color){ - - -} -void RasterizerDummy::immediate_uv(RID p_immediate,const Vector2& tex_uv){ - - -} -void RasterizerDummy::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ - - -} - -void RasterizerDummy::immediate_end(RID p_immediate){ - - -} -void RasterizerDummy::immediate_clear(RID p_immediate) { - - -} - -AABB RasterizerDummy::immediate_get_aabb(RID p_immediate) const { - - return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); -} - -void RasterizerDummy::immediate_set_material(RID p_immediate,RID p_material) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - im->material=p_material; - -} - -RID RasterizerDummy::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im,RID()); - return im->material; - -} - -/* PARTICLES API */ - -RID RasterizerDummy::particles_create() { - - Particles *particles = memnew( Particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles_owner.make_rid(particles); -} - -void RasterizerDummy::particles_set_amount(RID p_particles, int p_amount) { - - ERR_FAIL_COND(p_amount<1); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.amount=p_amount; - -} - -int RasterizerDummy::particles_get_amount(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.amount; - -} - -void RasterizerDummy::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.emitting=p_emitting;; - -} -bool RasterizerDummy::particles_is_emitting(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.emitting; - -} - -void RasterizerDummy::particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.visibility_aabb=p_visibility; - -} - -void RasterizerDummy::particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_half_extents=p_half_extents; -} -Vector3 RasterizerDummy::particles_get_emission_half_extents(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_half_extents; -} - -void RasterizerDummy::particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_base_velocity=p_base_velocity; -} - -Vector3 RasterizerDummy::particles_get_emission_base_velocity(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_base_velocity; -} - - -void RasterizerDummy::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_points=p_points; -} - -DVector<Vector3> RasterizerDummy::particles_get_emission_points(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,DVector<Vector3>()); - - return particles->data.emission_points; - -} - -void RasterizerDummy::particles_set_gravity_normal(RID p_particles, const Vector3& p_normal) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.gravity_normal=p_normal; - -} -Vector3 RasterizerDummy::particles_get_gravity_normal(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.gravity_normal; -} - - -AABB RasterizerDummy::particles_get_visibility_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; - -} - -void RasterizerDummy::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value) { - - ERR_FAIL_INDEX(p_variable,VS::PARTICLE_VAR_MAX); - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_vars[p_variable]=p_value; - -} -float RasterizerDummy::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_vars[p_variable]; -} - -void RasterizerDummy::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_randomness[p_variable]=p_randomness; - -} -float RasterizerDummy::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_randomness[p_variable]; - -} - -void RasterizerDummy::particles_set_color_phases(RID p_particles, int p_phases) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_phases<0 || p_phases>VS::MAX_PARTICLE_COLOR_PHASES ); - particles->data.color_phase_count=p_phases; - -} -int RasterizerDummy::particles_get_color_phases(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phase_count; -} - - -void RasterizerDummy::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - if (p_pos<0.0) - p_pos=0.0; - if (p_pos>1.0) - p_pos=1.0; - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].pos=p_pos; - -} -float RasterizerDummy::particles_get_color_phase_pos(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phases[p_phase].pos; - -} - -void RasterizerDummy::particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].color=p_color; - - //update alpha - particles->has_alpha=false; - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - if (particles->data.color_phases[i].color.a<0.99) - particles->has_alpha=true; - } - -} - -Color RasterizerDummy::particles_get_color_phase_color(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color()); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Color()); - return particles->data.color_phases[p_phase].color; - -} - -void RasterizerDummy::particles_set_attractors(RID p_particles, int p_attractors) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_attractors<0 || p_attractors>VisualServer::MAX_PARTICLE_ATTRACTORS ); - particles->data.attractor_count=p_attractors; - -} -int RasterizerDummy::particles_get_attractors(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.attractor_count; -} - -void RasterizerDummy::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].pos=p_pos;; -} -Vector3 RasterizerDummy::particles_get_attractor_pos(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,Vector3()); - return particles->data.attractors[p_attractor].pos; -} - -void RasterizerDummy::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].force=p_force; -} - -float RasterizerDummy::particles_get_attractor_strength(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,0); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,0); - return particles->data.attractors[p_attractor].force; -} - -void RasterizerDummy::particles_set_material(RID p_particles, RID p_material,bool p_owned) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - if (particles->material_owned && particles->material.is_valid()) - free(particles->material); - - particles->material_owned=p_owned; - - particles->material=p_material; - -} -RID RasterizerDummy::particles_get_material(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles->material; - -} - -void RasterizerDummy::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.local_coordinates=p_enable; - -} - -bool RasterizerDummy::particles_is_using_local_coordinates(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.local_coordinates; -} -bool RasterizerDummy::particles_has_height_from_velocity(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.height_from_velocity; -} - -void RasterizerDummy::particles_set_height_from_velocity(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.height_from_velocity=p_enable; - -} - -AABB RasterizerDummy::particles_get_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; -} - -/* SKELETON API */ - -RID RasterizerDummy::skeleton_create() { - - Skeleton *skeleton = memnew( Skeleton ); - ERR_FAIL_COND_V(!skeleton,RID()); - return skeleton_owner.make_rid( skeleton ); -} -void RasterizerDummy::skeleton_resize(RID p_skeleton,int p_bones) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - if (p_bones == skeleton->bones.size()) { - return; - }; - - skeleton->bones.resize(p_bones); - -} -int RasterizerDummy::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, -1); - return skeleton->bones.size(); -} -void RasterizerDummy::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX( p_bone, skeleton->bones.size() ); - - skeleton->bones[p_bone] = p_transform; -} - -Transform RasterizerDummy::skeleton_bone_get_transform(RID p_skeleton,int p_bone) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V( p_bone, skeleton->bones.size(), Transform() ); - - // something - return skeleton->bones[p_bone]; -} - - -/* LIGHT API */ - -RID RasterizerDummy::light_create(VS::LightType p_type) { - - Light *light = memnew( Light ); - light->type=p_type; - return light_owner.make_rid(light); -} - -VS::LightType RasterizerDummy::light_get_type(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI); - return light->type; -} - -void RasterizerDummy::light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_type, 3 ); - light->colors[p_type]=p_color; -} -Color RasterizerDummy::light_get_color(RID p_light,VS::LightColor p_type) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, Color()); - ERR_FAIL_INDEX_V( p_type, 3, Color() ); - return light->colors[p_type]; -} - -void RasterizerDummy::light_set_shadow(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->shadow_enabled=p_enabled; -} - -bool RasterizerDummy::light_has_shadow(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->shadow_enabled; -} - -void RasterizerDummy::light_set_volumetric(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->volumetric_enabled=p_enabled; - -} -bool RasterizerDummy::light_is_volumetric(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->volumetric_enabled; -} - -void RasterizerDummy::light_set_projector(RID p_light,RID p_texture) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->projector=p_texture; -} -RID RasterizerDummy::light_get_projector(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,RID()); - return light->projector; -} - -void RasterizerDummy::light_set_var(RID p_light, VS::LightParam p_var, float p_value) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_var, VS::LIGHT_PARAM_MAX ); - - light->vars[p_var]=p_value; -} -float RasterizerDummy::light_get_var(RID p_light, VS::LightParam p_var) const { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,0); - - ERR_FAIL_INDEX_V( p_var, VS::LIGHT_PARAM_MAX,0 ); - - return light->vars[p_var]; -} - -void RasterizerDummy::light_set_operator(RID p_light,VS::LightOp p_op) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - - -}; - -VS::LightOp RasterizerDummy::light_get_operator(RID p_light) const { - - return VS::LightOp(0); -}; - -void RasterizerDummy::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { - - -} - -VS::LightOmniShadowMode RasterizerDummy::light_omni_get_shadow_mode(RID p_light) const{ - - return VS::LightOmniShadowMode(0); -} - -void RasterizerDummy::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { - - -} - -VS::LightDirectionalShadowMode RasterizerDummy::light_directional_get_shadow_mode(RID p_light) const { - - return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; -} - -void RasterizerDummy::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { - - -} - -float RasterizerDummy::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { - - return 0; -} - - -AABB RasterizerDummy::light_get_aabb(RID p_light) const { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,AABB()); - - switch( light->type ) { - - case VS::LIGHT_SPOT: { - - float len=light->vars[VS::LIGHT_PARAM_RADIUS]; - float size=Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE]))*len; - return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) ); - } break; - case VS::LIGHT_OMNI: { - - float r = light->vars[VS::LIGHT_PARAM_RADIUS]; - return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 ); - } break; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - } break; - default: {} - } - - ERR_FAIL_V( AABB() ); -} - - -RID RasterizerDummy::light_instance_create(RID p_light) { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light, RID()); - - LightInstance *light_instance = memnew( LightInstance ); - - light_instance->light=p_light; - light_instance->base=light; - - - return light_instance_owner.make_rid( light_instance ); -} -void RasterizerDummy::light_instance_set_transform(RID p_light_instance,const Transform& p_transform) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - lighti->transform=p_transform; - -} - -bool RasterizerDummy::light_instance_has_shadow(RID p_light_instance) const { - - return false; - -} - - -bool RasterizerDummy::light_instance_assign_shadow(RID p_light_instance) { - - return false; - -} - - -Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance) const { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti,Rasterizer::SHADOW_NONE); - - switch(lighti->base->type) { - - case VS::LIGHT_DIRECTIONAL: return SHADOW_PSM; break; - case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break; - case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break; - } - - return Rasterizer::SHADOW_NONE; -} - -Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { - - return SHADOW_NONE; -} -void RasterizerDummy::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - -} - -int RasterizerDummy::light_instance_get_shadow_passes(RID p_light_instance) const { - - return 0; -} - -bool RasterizerDummy::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { - - return false; -} - - -void RasterizerDummy::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - - ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL); - ERR_FAIL_INDEX(p_index,1); - - lighti->custom_projection=p_camera; - lighti->custom_transform=p_transform; - -} -void RasterizerDummy::shadow_clear_near() { - - -} - -bool RasterizerDummy::shadow_allocate_near(RID p_light) { - - return false; -} - -bool RasterizerDummy::shadow_allocate_far(RID p_light) { - - return false; -} - -/* PARTICLES INSTANCE */ - -RID RasterizerDummy::particles_instance_create(RID p_particles) { - - ERR_FAIL_COND_V(!particles_owner.owns(p_particles),RID()); - ParticlesInstance *particles_instance = memnew( ParticlesInstance ); - ERR_FAIL_COND_V(!particles_instance, RID() ); - particles_instance->particles=p_particles; - return particles_instance_owner.make_rid(particles_instance); -} - -void RasterizerDummy::particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform) { - - ParticlesInstance *particles_instance=particles_instance_owner.get(p_particles_instance); - ERR_FAIL_COND(!particles_instance); - particles_instance->transform=p_transform; -} - - -/* RENDER API */ -/* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - -RID RasterizerDummy::viewport_data_create() { - - return RID(); -} - -RID RasterizerDummy::render_target_create(){ - - return RID(); - -} -void RasterizerDummy::render_target_set_size(RID p_render_target, int p_width, int p_height){ - - -} -RID RasterizerDummy::render_target_get_texture(RID p_render_target) const{ - - return RID(); - -} -bool RasterizerDummy::render_target_renedered_in_frame(RID p_render_target){ - - return false; -} - - -void RasterizerDummy::begin_frame() { - - - -} - -void RasterizerDummy::capture_viewport(Image* r_capture) { - - -} - - -void RasterizerDummy::clear_viewport(const Color& p_color) { - - -}; - -void RasterizerDummy::set_viewport(const VS::ViewportRect& p_viewport) { - - - -} - -void RasterizerDummy::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { - - -} - - -void RasterizerDummy::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { - - -}; - -void RasterizerDummy::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { - -} - -void RasterizerDummy::set_camera(const Transform& p_world, const CameraMatrix& p_projection, bool p_ortho_hint) { - - -} - -void RasterizerDummy::add_light( RID p_light_instance ) { - - - -} - - - - -void RasterizerDummy::add_mesh( const RID& p_mesh, const InstanceData *p_data) { - - -} - -void RasterizerDummy::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ - - - - -} - -void RasterizerDummy::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ - - - -} - - - -void RasterizerDummy::end_scene() { - - -} -void RasterizerDummy::end_shadow_map() { - -} - - -void RasterizerDummy::end_frame() { - - -} - -RID RasterizerDummy::canvas_light_occluder_create() { - return RID(); -} - -void RasterizerDummy::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) { - - -} - -RID RasterizerDummy::canvas_light_shadow_buffer_create(int p_width) { - - return RID(); -} - -void RasterizerDummy::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { - - -} - -void RasterizerDummy::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) { - - -} - -/* CANVAS API */ - - -void RasterizerDummy::begin_canvas_bg() { - -} -void RasterizerDummy::canvas_begin() { - - - -} -void RasterizerDummy::canvas_disable_blending() { - - - -} - -void RasterizerDummy::canvas_set_opacity(float p_opacity) { - - -} - -void RasterizerDummy::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { - - -} - - -void RasterizerDummy::canvas_begin_rect(const Matrix32& p_transform) { - - - -} - -void RasterizerDummy::canvas_set_clip(bool p_clip, const Rect2& p_rect) { - - - - -} - -void RasterizerDummy::canvas_end_rect() { - - -} - -void RasterizerDummy::canvas_draw_line(const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width, bool p_antialiased) { - - - -} - -void RasterizerDummy::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) { - - - - -} -void RasterizerDummy::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { - - -} -void RasterizerDummy::canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) { - - - -} - - -void RasterizerDummy::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - - - -} - -void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) { - - -} - -void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) { - - -} - -/* ENVIRONMENT */ - -RID RasterizerDummy::environment_create() { - - Environment * env = memnew( Environment ); - return environment_owner.make_rid(env); -} - -void RasterizerDummy::environment_set_background(RID p_env,VS::EnvironmentBG p_bg) { - - ERR_FAIL_INDEX(p_bg,VS::ENV_BG_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_mode=p_bg; -} - -VS::EnvironmentBG RasterizerDummy::environment_get_background(RID p_env) const{ - - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,VS::ENV_BG_MAX); - return env->bg_mode; -} - -void RasterizerDummy::environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_BG_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_param[p_param]=p_value; - -} -Variant RasterizerDummy::environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_BG_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->bg_param[p_param]; - -} - -void RasterizerDummy::environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled){ - - ERR_FAIL_INDEX(p_effect,VS::ENV_FX_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_enabled[p_effect]=p_enabled; -} -bool RasterizerDummy::environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const{ - - ERR_FAIL_INDEX_V(p_effect,VS::ENV_FX_MAX,false); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,false); - return env->fx_enabled[p_effect]; - -} - -void RasterizerDummy::environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_FX_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_param[p_param]=p_value; -} -Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_FX_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->fx_param[p_param]; - -} - - -RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { - - return sampled_light_owner.make_rid(memnew(SampledLight)); -} - -void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { - - -} - - -/*MISC*/ - -bool RasterizerDummy::is_texture(const RID& p_rid) const { - - return texture_owner.owns(p_rid); -} -bool RasterizerDummy::is_material(const RID& p_rid) const { - - return material_owner.owns(p_rid); -} -bool RasterizerDummy::is_mesh(const RID& p_rid) const { - - return mesh_owner.owns(p_rid); -} - -bool RasterizerDummy::is_immediate(const RID& p_rid) const { - - return immediate_owner.owns(p_rid); -} - -bool RasterizerDummy::is_multimesh(const RID& p_rid) const { - - return multimesh_owner.owns(p_rid); -} -bool RasterizerDummy::is_particles(const RID &p_beam) const { - - return particles_owner.owns(p_beam); -} - -bool RasterizerDummy::is_light(const RID& p_rid) const { - - return light_owner.owns(p_rid); -} -bool RasterizerDummy::is_light_instance(const RID& p_rid) const { - - return light_instance_owner.owns(p_rid); -} -bool RasterizerDummy::is_particles_instance(const RID& p_rid) const { - - return particles_instance_owner.owns(p_rid); -} -bool RasterizerDummy::is_skeleton(const RID& p_rid) const { - - return skeleton_owner.owns(p_rid); -} -bool RasterizerDummy::is_environment(const RID& p_rid) const { - - return environment_owner.owns(p_rid); -} - -bool RasterizerDummy::is_canvas_light_occluder(const RID& p_rid) const { - - return false; -} - -bool RasterizerDummy::is_shader(const RID& p_rid) const { - - return false; -} - -void RasterizerDummy::free(const RID& p_rid) { - - if (texture_owner.owns(p_rid)) { - - // delete the texture - Texture *texture = texture_owner.get(p_rid); - texture_owner.free(p_rid); - memdelete(texture); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - Shader *shader = shader_owner.get(p_rid); - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - Material *material = material_owner.get( p_rid ); - material_owner.free(p_rid); - memdelete(material); - - } else if (mesh_owner.owns(p_rid)) { - - Mesh *mesh = mesh_owner.get(p_rid); - - for (int i=0;i<mesh->surfaces.size();i++) { - - memdelete( mesh->surfaces[i] ); - }; - - mesh->surfaces.clear(); - mesh_owner.free(p_rid); - memdelete(mesh); - - } else if (multimesh_owner.owns(p_rid)) { - - MultiMesh *multimesh = multimesh_owner.get(p_rid); - multimesh_owner.free(p_rid); - memdelete(multimesh); - - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.get(p_rid); - immediate_owner.free(p_rid); - memdelete(immediate); - - } else if (particles_owner.owns(p_rid)) { - - Particles *particles = particles_owner.get(p_rid); - particles_owner.free(p_rid); - memdelete(particles); - } else if (particles_instance_owner.owns(p_rid)) { - - ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); - particles_instance_owner.free(p_rid); - memdelete(particles_isntance); - - } else if (skeleton_owner.owns(p_rid)) { - - Skeleton *skeleton = skeleton_owner.get( p_rid ); - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (light_owner.owns(p_rid)) { - - Light *light = light_owner.get( p_rid ); - light_owner.free(p_rid); - memdelete(light); - - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.get( p_rid ); - light_instance_owner.free(p_rid); - memdelete( light_instance ); - - - } else if (environment_owner.owns(p_rid)) { - - Environment *env = environment_owner.get( p_rid ); - environment_owner.free(p_rid); - memdelete( env ); - } else if (sampled_light_owner.owns(p_rid)) { - - SampledLight *sampled_light = sampled_light_owner.get( p_rid ); - ERR_FAIL_COND(!sampled_light); - - sampled_light_owner.free(p_rid); - memdelete( sampled_light ); - - }; -} - - -void RasterizerDummy::custom_shade_model_set_shader(int p_model, RID p_shader) { - - -}; - -RID RasterizerDummy::custom_shade_model_get_shader(int p_model) const { - - return RID(); -}; - -void RasterizerDummy::custom_shade_model_set_name(int p_model, const String& p_name) { - -}; - -String RasterizerDummy::custom_shade_model_get_name(int p_model) const { - - return String(); -}; - -void RasterizerDummy::custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info) { - -}; - -void RasterizerDummy::custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const { - -}; - - - -void RasterizerDummy::init() { - - -} - -void RasterizerDummy::finish() { - - -} - -int RasterizerDummy::get_render_info(VS::RenderInfo p_info) { - - return 0; -} - -bool RasterizerDummy::needs_to_draw_next_frame() const { - - return false; -} - - -bool RasterizerDummy::has_feature(VS::Features p_feature) const { - - return false; - -} - -void RasterizerDummy::restore_framebuffer() { - -} - -RasterizerDummy::RasterizerDummy() { - -}; - -RasterizerDummy::~RasterizerDummy() { - -}; diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h deleted file mode 100644 index 4077c14262..0000000000 --- a/servers/visual/rasterizer_dummy.h +++ /dev/null @@ -1,791 +0,0 @@ -/*************************************************************************/ -/* rasterizer_dummy.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef RASTERIZER_DUMMY_H -#define RASTERIZER_DUMMY_H - -#include "servers/visual/rasterizer.h" - - -#include "image.h" -#include "rid.h" -#include "servers/visual_server.h" -#include "list.h" -#include "map.h" -#include "camera_matrix.h" -#include "sort.h" - - -#include "servers/visual/particle_system_sw.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class RasterizerDummy : public Rasterizer { - - struct Texture { - - uint32_t flags; - int width,height; - Image::Format format; - Image image[6]; - Texture() { - - flags=width=height=0; - format=Image::FORMAT_GRAYSCALE; - } - - ~Texture() { - - } - }; - - mutable RID_Owner<Texture> texture_owner; - - struct Shader { - - String vertex_code; - String fragment_code; - String light_code; - VS::ShaderMode mode; - Map<StringName,Variant> params; - int fragment_line; - int vertex_line; - int light_line; - bool valid; - bool has_alpha; - bool use_world_transform; - - }; - - mutable RID_Owner<Shader> shader_owner; - - - struct Material { - - bool flags[VS::MATERIAL_FLAG_MAX]; - - VS::MaterialDepthDrawMode depth_draw_mode; - - VS::MaterialBlendMode blend_mode; - - float line_width; - float point_size; - - RID shader; // shader material - - Map<StringName,Variant> shader_params; - - - Material() { - - - for(int i=0;i<VS::MATERIAL_FLAG_MAX;i++) - flags[i]=false; - flags[VS::MATERIAL_FLAG_VISIBLE]=true; - - depth_draw_mode=VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY; - line_width=1; - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - point_size = 1.0; - - } - }; - mutable RID_Owner<Material> material_owner; - - void _material_check_alpha(Material *p_material); - - - struct Geometry { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_POLY, - GEOMETRY_PARTICLES, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - bool has_alpha; - bool material_owned; - - Geometry() { has_alpha=false; material_owned = false; } - virtual ~Geometry() {}; - }; - - struct GeometryOwner { - - virtual ~GeometryOwner() {} - }; - - class Mesh; - - struct Surface : public Geometry { - - Array data; - Array morph_data; - - bool packed; - bool alpha_sort; - int morph_target_count; - AABB aabb; - - VS::PrimitiveType primitive; - - uint32_t format; - uint32_t morph_format; - - Surface() { - - packed=false; - morph_target_count=0; - material_owned=false; - format=0; - morph_format=0; - - primitive=VS::PRIMITIVE_POINTS; - } - - ~Surface() { - - } - }; - - - struct Mesh { - - bool active; - Vector<Surface*> surfaces; - int morph_target_count; - VS::MorphTargetMode morph_target_mode; - AABB custom_aabb; - - mutable uint64_t last_pass; - Mesh() { - morph_target_mode=VS::MORPH_MODE_NORMALIZED; - morph_target_count=0; - last_pass=0; - active=false; - } - }; - mutable RID_Owner<Mesh> mesh_owner; - - struct MultiMesh; - - struct MultiMeshSurface : public Geometry { - - Surface *surface; - MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; } - }; - - struct MultiMesh : public GeometryOwner { - - struct Element { - - Transform xform; - Color color; - }; - - AABB aabb; - RID mesh; - int visible; - - //IDirect3DVertexBuffer9* instance_buffer; - Vector<Element> elements; - - MultiMesh() { - visible=-1; - } - - - }; - - - mutable RID_Owner<MultiMesh> multimesh_owner; - - struct Immediate { - - - RID material; - int empty; - }; - - mutable RID_Owner<Immediate> immediate_owner; - - struct Particles : public Geometry { - - ParticleSystemSW data; // software particle system - - Particles() { - type=GEOMETRY_PARTICLES; - - } - }; - - mutable RID_Owner<Particles> particles_owner; - - struct ParticlesInstance : public GeometryOwner { - - RID particles; - - ParticleSystemProcessSW particles_process; - Transform transform; - - ParticlesInstance() { } - }; - - mutable RID_Owner<ParticlesInstance> particles_instance_owner; - ParticleSystemDrawInfoSW particle_draw_info; - - struct Skeleton { - - Vector<Transform> bones; - - }; - - mutable RID_Owner<Skeleton> skeleton_owner; - - - struct Light { - - VS::LightType type; - float vars[VS::LIGHT_PARAM_MAX]; - Color colors[3]; - bool shadow_enabled; - RID projector; - bool volumetric_enabled; - Color volumetric_color; - - - Light() { - - vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]=1; - vars[VS::LIGHT_PARAM_SPOT_ANGLE]=45; - vars[VS::LIGHT_PARAM_ATTENUATION]=1.0; - vars[VS::LIGHT_PARAM_ENERGY]=1.0; - vars[VS::LIGHT_PARAM_RADIUS]=1.0; - vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.05; - - colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1); - colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1); - shadow_enabled=false; - volumetric_enabled=false; - } - }; - - - struct Environment { - - - VS::EnvironmentBG bg_mode; - Variant bg_param[VS::ENV_BG_PARAM_MAX]; - bool fx_enabled[VS::ENV_FX_MAX]; - Variant fx_param[VS::ENV_FX_PARAM_MAX]; - - Environment() { - - bg_mode=VS::ENV_BG_DEFAULT_COLOR; - bg_param[VS::ENV_BG_PARAM_COLOR]=Color(0,0,0); - bg_param[VS::ENV_BG_PARAM_TEXTURE]=RID(); - bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID(); - bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; - - for(int i=0;i<VS::ENV_FX_MAX;i++) - fx_enabled[i]=false; - - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE]=10.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_WHITE]=1.0; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_TRESHOLD]=0.95; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE]=0.2; - fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE]=8.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED]=0.5; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]=1.0; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_BG]=true; - fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0; - - - } - - }; - - mutable RID_Owner<Environment> environment_owner; - - struct SampledLight { - - int w,h; - }; - - mutable RID_Owner<SampledLight> sampled_light_owner; - - struct ShadowBuffer; - - struct LightInstance { - - struct SplitInfo { - - CameraMatrix camera; - Transform transform; - float near; - float far; - }; - - RID light; - Light *base; - Transform transform; - CameraMatrix projection; - - Transform custom_transform; - CameraMatrix custom_projection; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - - LightInstance() { linear_att=1.0; } - - }; - - mutable RID_Owner<Light> light_owner; - mutable RID_Owner<LightInstance> light_instance_owner; - - - RID default_material; - - - - -public: - - /* TEXTURE API */ - - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const; - virtual void texture_set_flags(RID p_texture,uint32_t p_flags); - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual bool texture_has_alpha(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - virtual void texture_set_path(RID p_texture,const String& p_path) {} - virtual String texture_get_path(RID p_texture) const { return String(); } - virtual void texture_debug_usage(List<VS::TextureInfo> *r_info) {} - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable) {} - - /* SHADER API */ - - virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - - virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); - virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; - - virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); - - /* COMMON MATERIAL API */ - - virtual RID material_create(); - - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; - - virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant material_get_param(RID p_material, const StringName& p_param) const; - - virtual void material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,VS::MaterialFlag p_flag) const; - - virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode); - virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; - - virtual void material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode); - virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const; - - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; - - /* MESH API */ - - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); - - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; - - virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode); - virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; - - virtual void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh,RID p_skeleton=RID()) const; - - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - - /* MULTIMESH API */ - - virtual RID multimesh_create(); - - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); - - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh) const;; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; - - virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - - /* IMMEDIATE API */ - - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); - virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); - virtual void immediate_color(RID p_immediate,const Color& p_color); - virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - - virtual AABB immediate_get_aabb(RID p_mesh) const; - - /* PARTICLES API */ - - virtual RID particles_create(); - - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; - - virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; - - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; - - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; - - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); - - - /* LIGHT API */ - - virtual RID light_create(VS::LightType p_type); - virtual VS::LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,VS::LightColor p_type) const; - - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; - - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; - - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; - - virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value); - virtual float light_get_var(RID p_light, VS::LightParam p_var) const; - - virtual void light_set_operator(RID p_light,VS::LightOp p_op); - virtual VS::LightOp light_get_operator(RID p_light) const; - - virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - - virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const; - - virtual AABB light_get_aabb(RID p_poly) const; - - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); - - virtual bool light_instance_has_shadow(RID p_light_instance) const; - virtual bool light_instance_assign_shadow(RID p_light_instance); - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const; - virtual int light_instance_get_shadow_passes(RID p_light_instance) const; - virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const; - virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; } - - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const; - virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - - virtual void shadow_clear_near(); - virtual bool shadow_allocate_near(RID p_light); - virtual bool shadow_allocate_far(RID p_light); - - - /* PARTICLES INSTANCE */ - - virtual RID particles_instance_create(RID p_particles); - virtual void particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform); - - /* VIEWPORT */ - - virtual RID viewport_data_create(); - - virtual RID render_target_create(); - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); - virtual RID render_target_get_texture(RID p_render_target) const; - virtual bool render_target_renedered_in_frame(RID p_render_target); - - /* RENDER API */ - /* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - virtual void begin_frame(); - - virtual void set_viewport(const VS::ViewportRect& p_viewport); - virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false); - virtual void clear_viewport(const Color& p_color); - virtual void capture_viewport(Image* r_capture); - - - virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug); - virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint); - - virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls - - - virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data); - virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data); - virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {} - virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data); - - virtual void end_scene(); - virtual void end_shadow_map(); - - virtual void end_frame(); - - /* CANVAS API */ - - virtual void begin_canvas_bg(); - virtual void canvas_begin(); - virtual void canvas_disable_blending(); - virtual void canvas_set_opacity(float p_opacity); - virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode); - virtual void canvas_begin_rect(const Matrix32& p_transform); - virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect); - virtual void canvas_end_rect(); - virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased); - virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate); - virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width); - virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); - virtual void canvas_set_transform(const Matrix32& p_transform); - - virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light); - - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines); - - virtual RID canvas_light_shadow_buffer_create(int p_width); - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); - - virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); - - /* ENVIRONMENT */ - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual VS::EnvironmentBG environment_get_background(RID p_env) const; - - virtual void environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const; - - virtual void environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const; - - virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); - virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; - - /* SAMPLED LIGHT */ - virtual RID sampled_light_dp_create(int p_width,int p_height); - virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); - - - /*MISC*/ - - virtual bool is_texture(const RID& p_rid) const; - virtual bool is_material(const RID& p_rid) const; - virtual bool is_mesh(const RID& p_rid) const; - virtual bool is_immediate(const RID& p_rid) const; - virtual bool is_multimesh(const RID& p_rid) const; - virtual bool is_particles(const RID &p_beam) const; - - virtual bool is_light(const RID& p_rid) const; - virtual bool is_light_instance(const RID& p_rid) const; - virtual bool is_particles_instance(const RID& p_rid) const; - virtual bool is_skeleton(const RID& p_rid) const; - virtual bool is_environment(const RID& p_rid) const; - virtual bool is_canvas_light_occluder(const RID& p_rid) const; - - virtual bool is_shader(const RID& p_rid) const; - - virtual void free(const RID& p_rid); - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; - - - virtual void init(); - virtual void finish(); - - virtual int get_render_info(VS::RenderInfo p_info); - - virtual bool needs_to_draw_next_frame() const; - - virtual bool has_feature(VS::Features p_feature) const; - - virtual void restore_framebuffer(); - - RasterizerDummy(); - virtual ~RasterizerDummy(); -}; - - -#endif // RASTERIZER_DUMMY_H diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 39a260368c..ea634e8f06 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -44,14 +44,71 @@ static bool _is_hex(CharType c) { return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'); } + +String ShaderLanguage::get_operator_text(Operator p_op) { + + static const char* op_names[OP_MAX]={"==", + "!=", + "<", + "<=", + ">", + ">=", + "&&", + "||", + "!", + "-", + "+", + "-", + "*", + "/", + "%", + "<<", + ">>", + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "<<=", + ">>=", + "&=", + "|=", + "^=", + "&", + "|", + "^", + "~", + "++" + "--", + "()", + "construct"}; + + return op_names[p_op]; + +} + + const char * ShaderLanguage::token_names[TK_MAX]={ "EMPTY", - "INDENTIFIER", + "IDENTIFIER", "TRUE", "FALSE", "REAL_CONSTANT", + "INT_CONSTANT", "TYPE_VOID", "TYPE_BOOL", + "TYPE_BVEC2", + "TYPE_BVEC3", + "TYPE_BVEC4", + "TYPE_INT", + "TYPE_IVEC2", + "TYPE_IVEC3", + "TYPE_IVEC4", + "TYPE_UINT", + "TYPE_UVEC2", + "TYPE_UVEC3", + "TYPE_UVEC4", "TYPE_FLOAT", "TYPE_VEC2", "TYPE_VEC3", @@ -59,9 +116,13 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "TYPE_MAT2", "TYPE_MAT3", "TYPE_MAT4", - "TYPE_TEXTURE", - "TYPE_CUBEMAP", - "TYPE_COLOR", + "TYPE_SAMPLER2D", + "TYPE_ISAMPLER2D", + "TYPE_USAMPLER2D", + "TYPE_SAMPLERCUBE", + "PRECISION_LOW", + "PRECISION_MID", + "PRECISION_HIGH", "OP_EQUAL", "OP_NOT_EQUAL", "OP_LESS", @@ -75,14 +136,35 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "OP_SUB", "OP_MUL", "OP_DIV", - "OP_NEG", + "OP_MOD", + "OP_SHIFT_LEFT", + "OP_SHIFT_RIGHT", "OP_ASSIGN", "OP_ASSIGN_ADD", "OP_ASSIGN_SUB", "OP_ASSIGN_MUL", "OP_ASSIGN_DIV", + "OP_ASSIGN_MOD", + "OP_ASSIGN_SHIFT_LEFT", + "OP_ASSIGN_SHIFT_RIGHT", + "OP_ASSIGN_BIT_AND", + "OP_ASSIGN_BIT_OR", + "OP_ASSIGN_BIT_XOR", + "OP_BIT_AND", + "OP_BIT_OR", + "OP_BIT_XOR", + "OP_BIT_INVERT", + "OP_INCREMENT", + "OP_DECREMENT", "CF_IF", "CF_ELSE", + "CF_FOR", + "CF_WHILE", + "CF_DO", + "CF_SWITCH", + "CF_CASE", + "CF_BREAK", + "CF_CONTINUE", "CF_RETURN", "BRACKET_OPEN", "BRACKET_CLOSE", @@ -90,460 +172,504 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "CURLY_BRACKET_CLOSE", "PARENTHESIS_OPEN", "PARENTHESIS_CLOSE", + "QUESTION", "COMMA", + "COLON", "SEMICOLON", "PERIOD", "UNIFORM", + "VARYING", + "RENDER_MODE", + "HINT_WHITE_TEXTURE", + "HINT_BLACK_TEXTURE", + "HINT_NORMAL_TEXTURE", + "HINT_ANISO_TEXTURE", + "HINT_ALBEDO_TEXTURE", + "HINT_BLACK_ALBEDO_TEXTURE", + "HINT_COLOR", + "HINT_RANGE", + "CURSOR", "ERROR", + "EOF", }; -ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars) { +String ShaderLanguage::get_token_text(Token p_token) { -#define GETCHAR(m_idx) ((m_idx<p_len)?p_text[m_idx]:CharType(0)) + String name=token_names[p_token.type]; + if (p_token.type==TK_INT_CONSTANT || p_token.type==TK_REAL_CONSTANT) { + name+="("+rtos(p_token.constant)+")"; + } else if (p_token.type==TK_IDENTIFIER) { + name+="("+String(p_token.text)+")"; + } else if (p_token.type==TK_ERROR) { + name+="("+String(p_token.text)+")"; + } - r_chars=1; //by default everything eats one char - switch(GETCHAR(0)) { + return name; +} - case '\t': - case '\r': - case ' ': - return Token(); - case '\n': - r_line++; - return Token(); - case '/': { +ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type,const StringName& p_text) { - switch(GETCHAR(1)) { - case '*': { // block comment + Token tk; + tk.type=p_type; + tk.text=p_text; + tk.line=tk_line; + if (tk.type==TK_ERROR) { + _set_error(p_text); + } + return tk; +} +const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[]={ + {TK_TRUE,"true"}, + {TK_FALSE,"false"}, + {TK_TYPE_VOID,"void"}, + {TK_TYPE_BOOL,"bool"}, + {TK_TYPE_BVEC2,"bvec2"}, + {TK_TYPE_BVEC3,"bvec3"}, + {TK_TYPE_BVEC4,"bvec4"}, + {TK_TYPE_INT,"int"}, + {TK_TYPE_IVEC2,"ivec2"}, + {TK_TYPE_IVEC3,"ivec3"}, + {TK_TYPE_IVEC4,"ivec4"}, + {TK_TYPE_UINT,"uint"}, + {TK_TYPE_UVEC2,"uvec2"}, + {TK_TYPE_UVEC3,"uvec3"}, + {TK_TYPE_UVEC4,"uvec4"}, + {TK_TYPE_FLOAT,"float"}, + {TK_TYPE_VEC2,"vec2"}, + {TK_TYPE_VEC3,"vec3"}, + {TK_TYPE_VEC4,"vec4"}, + {TK_TYPE_MAT2,"mat2"}, + {TK_TYPE_MAT3,"mat3"}, + {TK_TYPE_MAT4,"mat4"}, + {TK_TYPE_SAMPLER2D,"sampler2D"}, + {TK_TYPE_ISAMPLER2D,"isampler2D"}, + {TK_TYPE_USAMPLER2D,"usampler2D"}, + {TK_TYPE_SAMPLERCUBE,"samplerCube"}, + {TK_PRECISION_LOW,"lowp"}, + {TK_PRECISION_MID,"mediump"}, + {TK_PRECISION_HIGH,"highp"}, + {TK_CF_IF,"if"}, + {TK_CF_ELSE,"else"}, + {TK_CF_FOR,"for"}, + {TK_CF_WHILE,"while"}, + {TK_CF_DO,"do"}, + {TK_CF_SWITCH,"switch"}, + {TK_CF_CASE,"case"}, + {TK_CF_BREAK,"break"}, + {TK_CF_CONTINUE,"continue"}, + {TK_CF_RETURN,"return"}, + {TK_UNIFORM,"uniform"}, + {TK_VARYING,"varying"}, + {TK_RENDER_MODE,"render_mode"}, + {TK_HINT_WHITE_TEXTURE,"hint_white"}, + {TK_HINT_BLACK_TEXTURE,"hint_black"}, + {TK_HINT_NORMAL_TEXTURE,"hint_normal"}, + {TK_HINT_ANISO_TEXTURE,"hint_aniso"}, + {TK_HINT_ALBEDO_TEXTURE,"hint_albedo"}, + {TK_HINT_BLACK_ALBEDO_TEXTURE,"hint_black_albedo"}, + {TK_HINT_COLOR,"hint_color"}, + {TK_HINT_RANGE,"hint_range"}, + + {TK_ERROR,NULL} +}; - while(true) { - if (GETCHAR(r_chars+1)==0) { - r_chars+=1; - break; - } if (GETCHAR(r_chars+1)=='*' && GETCHAR(r_chars+2)=='/') { - r_chars+=3; - break; - } if (GETCHAR(r_chars+1)=='\n') { - r_line++; - } - r_chars++; - } - return Token(); +ShaderLanguage::Token ShaderLanguage::_get_token() { - } break; - case '/': { // line comment skip +#define GETCHAR(m_idx) (((char_idx+m_idx)<code.length())?code[char_idx+m_idx]:CharType(0)) - while(GETCHAR(r_chars+1)!='\n' && GETCHAR(r_chars+1)!=0) { - r_chars++; - } - r_chars++; - //r_line++; - - return Token(); + while(true) { + char_idx++; + switch(GETCHAR(-1)) { + + case 0: + return _make_token(TK_EOF); + case 0xFFFF: + return _make_token(TK_CURSOR); //for completion + case '\t': + case '\r': + case ' ': + continue; + case '\n': + tk_line++; + continue; + case '/': { - } break; - case '=': { // diveq + switch(GETCHAR(0)) { + case '*': { // block comment - r_chars=2; - return Token(TK_OP_ASSIGN_DIV); + char_idx++; + while(true) { + if (GETCHAR(0)==0) { + return _make_token(TK_EOF); + } if (GETCHAR(0)=='*' && GETCHAR(1)=='/') { + char_idx+=2; + break; + } if (GETCHAR(0)=='\n') { + tk_line++; + } - } break; - default: - return Token(TK_OP_DIV); + char_idx++; + } - } - } break; - case '=': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_EQUAL); - } + } break; + case '/': { // line comment skip - return Token(TK_OP_ASSIGN); - } break; - case '<': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_LESS_EQUAL); - } /*else if (GETCHAR(1)=='<') { - r_chars++; - if (GETCHAR(2)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SHIFT_LEFT); - } + while(true) { + if (GETCHAR(0)=='\n') { + char_idx++; + break; + } + if (GETCHAR(0)==0) { + return _make_token(TK_EOF); + } + char_idx++; + } - return Token(TK_OP_SHIFT_LEFT); - }*/ + } break; + case '=': { // diveq - return Token(TK_OP_LESS); + char_idx++; + return _make_token(TK_OP_ASSIGN_DIV); - } break; - case '>': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_GREATER_EQUAL); - }/* else if (GETCHAR(1)=='<') { - r_chars++; - if (GETCHAR(2)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SHIFT_RIGHT); + } break; + default: + return _make_token(TK_OP_DIV); } - return Token(TK_OP_SHIFT_RIGHT); - }*/ - - return Token(TK_OP_GREATER); - - } break; - case '!': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_NOT_EQUAL); - } + continue; //a comment, continue to next token + } break; + case '=': { - return Token(TK_OP_NOT); - - } break; - //case '"' //string - no strings in shader - //case '\'' //string - no strings in shader - case '{': - return Token(TK_CURLY_BRACKET_OPEN); - case '}': - return Token(TK_CURLY_BRACKET_CLOSE); - //case '[': - // return Token(TK_BRACKET_OPEN); - //case ']': - // return Token(TK_BRACKET_CLOSE); - case '(': - return Token(TK_PARENTHESIS_OPEN); - case ')': - return Token(TK_PARENTHESIS_CLOSE); - case ',': - return Token(TK_COMMA); - case ';': - return Token(TK_SEMICOLON); - //case '?': - // return Token(TK_QUESTION_MARK); - //case ':': - // return Token(TK_COLON); //for methods maybe but now useless. - //case '^': - // return Token(TK_OP_BIT_XOR); - //case '~': - // return Token(TK_OP_BIT_INVERT); - case '&': { - - if (GETCHAR(1)=='&') { - - r_chars++; - return Token(TK_OP_AND); - } - - return Token(TK_ERROR,"Unknown character"); - -/* - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_BIT_AND); - } else if (GETCHAR(1)=='&') { - r_chars++; - return Token(TK_OP_AND); - } - return TK_OP_BIT_AND;*/ - } break; - case '|': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_EQUAL); + } - if (GETCHAR(1)=='|') { + return _make_token(TK_OP_ASSIGN); + + } break; + case '<': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_LESS_EQUAL); + } else if (GETCHAR(0)=='<') { + char_idx++; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_LEFT); + } - r_chars++; - return Token(TK_OP_OR); - } + return _make_token(TK_OP_SHIFT_LEFT); + } - return Token(TK_ERROR,"Unknown character"); + return _make_token(TK_OP_LESS); + + } break; + case '>': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_GREATER_EQUAL); + } else if (GETCHAR(0)=='<') { + char_idx++;; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_RIGHT); + } - /* - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_BIT_OR); - } else if (GETCHAR(1)=='|') { - r_chars++; - return Token(TK_OP_OR); - } - return TK_OP_BIT_OR; - */ - } break; - case '*': { + return _make_token(TK_OP_SHIFT_RIGHT); + } - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_MUL); - } - return TK_OP_MUL; - } break; - case '+': { + return _make_token(TK_OP_GREATER); - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_ADD); - } /*else if (GETCHAR(1)=='+') { + } break; + case '!': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_NOT_EQUAL); + } - r_chars++; - return Token(TK_OP_PLUS_PLUS); - }*/ + return _make_token(TK_OP_NOT); + + } break; + //case '"' //string - no strings in shader + //case '\'' //string - no strings in shader + case '{': + return _make_token(TK_CURLY_BRACKET_OPEN); + case '}': + return _make_token(TK_CURLY_BRACKET_CLOSE); + case '[': + return _make_token(TK_BRACKET_OPEN); + case ']': + return _make_token(TK_BRACKET_CLOSE); + case '(': + return _make_token(TK_PARENTHESIS_OPEN); + case ')': + return _make_token(TK_PARENTHESIS_CLOSE); + case ',': + return _make_token(TK_COMMA); + case ';': + return _make_token(TK_SEMICOLON); + case '?': + return _make_token(TK_QUESTION); + case ':': + return _make_token(TK_COLON); + case '^': + return _make_token(TK_OP_BIT_XOR); + case '~': + return _make_token(TK_OP_BIT_INVERT); + case '&': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_AND); + } else if (GETCHAR(0)=='&') { + char_idx++; + return _make_token(TK_OP_AND); + } + return _make_token(TK_OP_BIT_AND); + } break; + case '|': { + + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_OR); + } else if (GETCHAR(0)=='|') { + char_idx++; + return _make_token(TK_OP_OR); + } + return _make_token(TK_OP_BIT_OR); - return TK_OP_ADD; - } break; - case '-': { + } break; + case '*': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SUB); - }/* else if (GETCHAR(1)=='-') { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MUL); + } + return _make_token(TK_OP_MUL); + } break; + case '+': { - r_chars++; - return Token(TK_OP_MINUS_MINUS); - }*/ + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_ADD); + } else if (GETCHAR(0)=='+') { - return TK_OP_SUB; - } break; - /*case '%': { + char_idx++; + return _make_token(TK_OP_INCREMENT); + } - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_MOD); - } + return _make_token(TK_OP_ADD); + } break; + case '-': { - return TK_OP_MOD; - } break;*/ - default: { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SUB); + }else if (GETCHAR(0)=='-') { - if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) { - // parse number - bool period_found=false; - bool exponent_found=false; - bool hexa_found=false; - bool sign_found=false; + char_idx++; + return _make_token(TK_OP_DECREMENT); + } - String str; - int i=0; + return _make_token(TK_OP_SUB); + } break; + case '%': { - while(true) { - if (GETCHAR(i)=='.') { - if (period_found || exponent_found) - return Token(TK_ERROR,"Invalid numeric constant"); - period_found=true; - } else if (GETCHAR(i)=='x') { - if (hexa_found || str.length()!=1 || str[0]!='0') - return Token(TK_ERROR,"Invalid numeric constant"); - hexa_found=true; - } else if (GETCHAR(i)=='e') { - if (hexa_found || exponent_found) - return Token(TK_ERROR,"Invalid numeric constant"); - exponent_found=true; - } else if (_is_number(GETCHAR(i))) { - //all ok - } else if (hexa_found && _is_hex(GETCHAR(i))) { - - } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) { - if (sign_found) - return Token(TK_ERROR,"Invalid numeric constant"); - sign_found=true; - } else - break; - - str+=CharType(GETCHAR(i)); - i++; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MOD); } - if (!_is_number(str[str.length()-1])) - return Token(TK_ERROR,"Invalid numeric constant"); + return _make_token(TK_OP_MOD); + } break; + default: { - r_chars+=str.length()-1; - return Token(TK_REAL_CONSTANT,str); - /* - if (period_found) - return Token(TK_NUMBER_REAL,str); - else - return Token(TK_NUMBER_INTEGER,str);*/ + char_idx--; //go back one, since we have no idea what this is - } + if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) { + // parse number + bool period_found=false; + bool exponent_found=false; + bool hexa_found=false; + bool sign_found=false; + bool minus_exponent_found=false; - if (GETCHAR(0)=='.') { - //parse period - return Token(TK_PERIOD); - } + String str; + int i=0; - if (_is_text_char(GETCHAR(0))) { - // parse identifier - String str; - str+=CharType(GETCHAR(0)); + while(true) { + if (GETCHAR(i)=='.') { + if (period_found || exponent_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + period_found=true; + } else if (GETCHAR(i)=='x') { + if (hexa_found || str.length()!=1 || str[0]!='0') + return _make_token(TK_ERROR,"Invalid numeric constant"); + hexa_found=true; + } else if (GETCHAR(i)=='e') { + if (hexa_found || exponent_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + exponent_found=true; + } else if (_is_number(GETCHAR(i))) { + //all ok + } else if (hexa_found && _is_hex(GETCHAR(i))) { + + } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) { + if (sign_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + sign_found=true; + if (GETCHAR(i)=='-') + minus_exponent_found=true; + } else + break; - while(_is_text_char(GETCHAR(r_chars))) { + str+=CharType(GETCHAR(i)); + i++; + } - str+=CharType(GETCHAR(r_chars)); - r_chars++; - } + if (!_is_number(str[str.length()-1])) + return _make_token(TK_ERROR,"Invalid numeric constant"); - //see if keyword - struct _kws { TokenType token; const char *text;}; - static const _kws keyword_list[]={ - {TK_TRUE,"true"}, - {TK_FALSE,"false"}, - {TK_TYPE_VOID,"void"}, - {TK_TYPE_BOOL,"bool"}, - /*{TK_TYPE_INT,"int"}, - {TK_TYPE_INT2,"int2"}, - {TK_TYPE_INT3,"int3"}, - {TK_TYPE_INT4,"int4"},*/ - {TK_TYPE_FLOAT,"float"}, - /*{TK_TYPE_FLOAT2,"float2"}, - {TK_TYPE_FLOAT3,"float3"}, - {TK_TYPE_FLOAT4,"float4"},*/ - {TK_TYPE_VEC2,"vec2"}, - {TK_TYPE_VEC3,"vec3"}, - {TK_TYPE_VEC4,"vec4"}, - {TK_TYPE_TEXTURE,"texture"}, - {TK_TYPE_CUBEMAP,"cubemap"}, - {TK_TYPE_COLOR,"color"}, + char_idx+=str.length(); + Token tk; + if (period_found || minus_exponent_found) + tk.type=TK_REAL_CONSTANT; + else + tk.type=TK_INT_CONSTANT; - {TK_TYPE_MAT2,"mat2"}, - /*{TK_TYPE_MAT3,"mat3"}, - {TK_TYPE_MAT4,"mat3"},*/ - {TK_TYPE_MAT3,"mat3"}, - {TK_TYPE_MAT4,"mat4"}, - {TK_CF_IF,"if"}, - {TK_CF_ELSE,"else"}, - /* - {TK_CF_FOR,"for"}, - {TK_CF_WHILE,"while"}, - {TK_CF_DO,"do"}, - {TK_CF_SWITCH,"switch"}, - {TK_CF_BREAK,"break"}, - {TK_CF_CONTINUE,"continue"},*/ - {TK_CF_RETURN,"return"}, - {TK_UNIFORM,"uniform"}, - {TK_ERROR,NULL} - }; + if (!str.is_valid_float()) { + return _make_token(TK_ERROR,"Invalid numeric constant"); + } - int idx=0; + tk.constant=str.to_double(); + tk.line=tk_line; - while(keyword_list[idx].text) { + return tk; - if (str==keyword_list[idx].text) - return Token(keyword_list[idx].token); - idx++; } + if (GETCHAR(0)=='.') { + //parse period + char_idx++; + return _make_token(TK_PERIOD); + } - return Token(TK_INDENTIFIER,str); - } - - if (GETCHAR(0)>32) - return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); - else - return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); + if (_is_text_char(GETCHAR(0))) { + // parse identifier + String str; - } break; - } + while(_is_text_char(GETCHAR(0))) { - ERR_PRINT("BUG"); - return Token(); -} + str+=CharType(GETCHAR(0)); + char_idx++; + } -Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column) { + //see if keyword + //should be converted to a static map + int idx=0; + while(keyword_list[idx].text) { - int len =p_text.length(); - int pos=0; + if (str==keyword_list[idx].text) { - int line=0; + return _make_token(keyword_list[idx].token); + } + idx++; + } - while(pos<len) { - int advance=0; - int prev_line=line; - Token t = read_token(&p_text[pos],len-pos,line,advance); - t.line=prev_line; + return _make_token(TK_IDENTIFIER,str); + } - if (t.type==TK_ERROR) { + if (GETCHAR(0)>32) + return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); + else + return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); - if (r_error) { - *r_error=t.text; - *r_err_line=line; - return ERR_COMPILATION_FAILED; - } + } break; } + } + ERR_PRINT("BUG"); + return Token(); +} - if (t.type!=TK_EMPTY) - p_tokens->push_back(t); - //if (prev_line!=line) - // p_tokens->push_back(Token(TK_LINE,itos(line))); - pos+=advance; +String ShaderLanguage::token_debug(const String& p_code) { - } + clear(); - return OK; + code=p_code; -} + String output; -String ShaderLanguage::lex_debug(const String& p_code) { + Token tk = _get_token(); + while(tk.type!=TK_EOF && tk.type!=TK_ERROR) { - Vector<Token> tokens; - String error; - int errline,errcol; - if (tokenize(p_code,&tokens,&error,&errline,&errcol)!=OK) - return error; - String ret; - for(int i=0;i<tokens.size();i++) { - ret+=String(token_names[tokens[i].type])+":"+itos(tokens[i].line)+":"+itos(tokens[i].col)+":"+tokens[i].text+"\n"; + output+=itos(tk_line)+": "+get_token_text(tk)+"\n"; + tk = _get_token(); } - return ret; + return output; } bool ShaderLanguage::is_token_datatype(TokenType p_type) { - return - (p_type==TK_TYPE_VOID) || - (p_type==TK_TYPE_BOOL) || - (p_type==TK_TYPE_FLOAT) || - (p_type==TK_TYPE_VEC2) || - (p_type==TK_TYPE_VEC3) || - (p_type==TK_TYPE_VEC4) || - (p_type==TK_TYPE_COLOR) || - (p_type==TK_TYPE_MAT2) || - (p_type==TK_TYPE_MAT3) || - (p_type==TK_TYPE_MAT4) || - (p_type==TK_TYPE_CUBEMAP) || - (p_type==TK_TYPE_TEXTURE); + return ( + p_type==TK_TYPE_VOID || + p_type==TK_TYPE_BOOL || + p_type==TK_TYPE_BVEC2 || + p_type==TK_TYPE_BVEC3 || + p_type==TK_TYPE_BVEC4 || + p_type==TK_TYPE_INT || + p_type==TK_TYPE_IVEC2 || + p_type==TK_TYPE_IVEC3 || + p_type==TK_TYPE_IVEC4 || + p_type==TK_TYPE_UINT || + p_type==TK_TYPE_UVEC2 || + p_type==TK_TYPE_UVEC3 || + p_type==TK_TYPE_UVEC4 || + p_type==TK_TYPE_FLOAT || + p_type==TK_TYPE_VEC2 || + p_type==TK_TYPE_VEC3 || + p_type==TK_TYPE_VEC4 || + p_type==TK_TYPE_MAT2 || + p_type==TK_TYPE_MAT3 || + p_type==TK_TYPE_MAT4 || + p_type==TK_TYPE_SAMPLER2D || + p_type==TK_TYPE_ISAMPLER2D || + p_type==TK_TYPE_USAMPLER2D || + p_type==TK_TYPE_SAMPLERCUBE ); } ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { - switch(p_type) { + return DataType(p_type-TK_TYPE_VOID); +} - case TK_TYPE_VOID: return TYPE_VOID; - case TK_TYPE_BOOL: return TYPE_BOOL; - case TK_TYPE_FLOAT: return TYPE_FLOAT; - case TK_TYPE_VEC2: return TYPE_VEC2; - case TK_TYPE_VEC3: return TYPE_VEC3; - case TK_TYPE_VEC4: return TYPE_VEC4; - case TK_TYPE_COLOR: return TYPE_VEC4; - case TK_TYPE_MAT2: return TYPE_MAT2; - case TK_TYPE_MAT3: return TYPE_MAT3; - case TK_TYPE_MAT4: return TYPE_MAT4; - case TK_TYPE_TEXTURE: return TYPE_TEXTURE; - case TK_TYPE_CUBEMAP: return TYPE_CUBEMAP; - default: return TYPE_VOID; - } - return TYPE_VOID; +bool ShaderLanguage::is_token_precision(TokenType p_type) { + + return ( + p_type==TK_PRECISION_LOW || + p_type==TK_PRECISION_MID || + p_type==TK_PRECISION_HIGH ); + +} + +ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) { + + if (p_type==TK_PRECISION_LOW) + return PRECISION_LOWP; + else if (p_type==TK_PRECISION_HIGH) + return PRECISION_HIGHP; + else + return PRECISION_MEDIUMP; } @@ -553,6 +679,17 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_VOID: return "void"; case TYPE_BOOL: return "bool"; + case TYPE_BVEC2: return "bvec2"; + case TYPE_BVEC3: return "bvec3"; + case TYPE_BVEC4: return "bvec4"; + case TYPE_INT: return "int"; + case TYPE_IVEC2: return "ivec2"; + case TYPE_IVEC3: return "ivec3"; + case TYPE_IVEC4: return "ivec4"; + case TYPE_UINT: return "uint"; + case TYPE_UVEC2: return "uvec2"; + case TYPE_UVEC3: return "uvec3"; + case TYPE_UVEC4: return "uvec4"; case TYPE_FLOAT: return "float"; case TYPE_VEC2: return "vec2"; case TYPE_VEC3: return "vec3"; @@ -560,9 +697,10 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_MAT2: return "mat2"; case TYPE_MAT3: return "mat3"; case TYPE_MAT4: return "mat4"; - case TYPE_TEXTURE: return "texture"; - case TYPE_CUBEMAP: return "cubemap"; - default: return ""; + case TYPE_SAMPLER2D: return "sampler2D"; + case TYPE_ISAMPLER2D: return "isampler2D"; + case TYPE_USAMPLER2D: return "usampler2D"; + case TYPE_SAMPLERCUBE: return "samplerCube"; } return ""; @@ -571,211 +709,495 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { - return - (p_type==TK_TYPE_BOOL) || - (p_type==TK_TYPE_FLOAT) || - (p_type==TK_TYPE_VEC2) || - (p_type==TK_TYPE_VEC3) || - (p_type==TK_TYPE_VEC4) || - (p_type==TK_TYPE_COLOR) || - (p_type==TK_TYPE_MAT2) || - (p_type==TK_TYPE_MAT3) || - (p_type==TK_TYPE_MAT4) || - (p_type==TK_TYPE_TEXTURE) || - (p_type==TK_TYPE_CUBEMAP); + return is_token_datatype(p_type) && p_type!=TK_TYPE_VOID; } -bool ShaderLanguage::parser_is_at_function(Parser& parser) { - - return (is_token_datatype(parser.get_token_type(0)) && parser.get_token_type(1)==TK_INDENTIFIER && parser.get_token_type(2)==TK_PARENTHESIS_OPEN); -} - - - -bool ShaderLanguage::test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func,bool p_var,bool p_builtin) { +void ShaderLanguage::clear() { - Node *node = p_node; + current_function=StringName(); - while(node) { + completion_type=COMPLETION_NONE; + completion_block=NULL; + completion_function=StringName(); - if (node->type==Node::TYPE_BLOCK) { + error_line=0; + tk_line=1; + char_idx=0; + error_set=false; + error_str=""; + while(nodes) { + Node *n = nodes; + nodes=nodes->next; + memdelete(n); + } - BlockNode *block = (BlockNode*)node; - if (block->variables.has(p_identifier)) - return true; - } else if (node->type==Node::TYPE_PROGRAM) { +} - ProgramNode *program = (ProgramNode*)node; - for(int i=0;i<program->functions.size();i++) { - if (program->functions[i].name==p_identifier) { - return true; - } - } +bool ShaderLanguage::_find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type, IdentifierType *r_type) { - if(program->builtin_variables.has(p_identifier)) { - return true; - } - if(program->uniforms.has(p_identifier)) { - return true; - } - } else if (node->type==Node::TYPE_FUNCTION) { + if (p_builtin_types.has(p_identifier)) { - FunctionNode *func=(FunctionNode*)node; - for(int i=0;i<func->arguments.size();i++) - if (func->arguments[i].name==p_identifier) - return true; + if (r_data_type) { + *r_data_type=p_builtin_types[p_identifier]; + } + if (r_type) { + *r_type=IDENTIFIER_BUILTIN_VAR; } - node=node->parent; + return true; } - // try keywords + FunctionNode *function=NULL; - int idx=0; + while(p_block) { - //todo optimize - while(intrinsic_func_defs[idx].name) { + if (p_block->variables.has(p_identifier)) { + if (r_data_type) { + *r_data_type=p_block->variables[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_LOCAL_VAR; + } - if (p_identifier.operator String()==intrinsic_func_defs[idx].name) return true; - idx++; - } - + } - return false; + if (p_block->parent_function) { + function=p_block->parent_function; + break; + } else { + ERR_FAIL_COND_V(!p_block->parent_block,false); + p_block=p_block->parent_block; + } + } -} + if (function) { + for(int i=0;i<function->arguments.size();i++) { + if (function->arguments[i].name==p_identifier) { + if (r_data_type) { + *r_data_type=function->arguments[i].type; + } + if (r_type) { + *r_type=IDENTIFIER_FUNCTION_ARGUMENT; + } + return true; + } + } + } -Error ShaderLanguage::parse_function(Parser& parser,BlockNode *p_block) { - if (!p_block->parent || p_block->parent->type!=Node::TYPE_PROGRAM) { - parser.set_error("Misplaced function"); - return ERR_PARSE_ERROR; + if (shader->varyings.has(p_identifier)) { + if (r_data_type) { + *r_data_type=shader->varyings[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_VARYING; + } + return true; + } + if (shader->uniforms.has(p_identifier)) { + if (r_data_type) { + *r_data_type=shader->uniforms[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_UNIFORM; + } + return true; } + for(int i=0;i<shader->functions.size();i++) { - ProgramNode *program = (ProgramNode*)p_block->parent; + if (!shader->functions[i].callable) + continue; - StringName name = parser.get_token(1).text; + if (shader->functions[i].name==p_identifier) { + if (r_data_type) { + *r_data_type=shader->functions[i].function->return_type; + } + if (r_type) { + *r_type=IDENTIFIER_FUNCTION; + } + } + } - if (test_existing_identifier(p_block,name)) { + return false; - parser.set_error("Duplicate Identifier (existing variable/builtin/function): "+name); - return ERR_PARSE_ERROR; +} - } +bool ShaderLanguage::_validate_operator(OperatorNode *p_op,DataType *r_ret_type) { - FunctionNode *function = parser.create_node<FunctionNode>(program); - function->body = parser.create_node<BlockNode>(function); + bool valid=false; + DataType ret_type; + + switch(p_op->op) { + case OP_EQUAL: + case OP_NOT_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + valid=na==nb; + ret_type=TYPE_BOOL; + } break; + case OP_LESS: + case OP_LESS_EQUAL: + case OP_GREATER: + case OP_GREATER_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - function->name=name; + valid = na==nb && (na==TYPE_UINT || na==TYPE_INT || na==TYPE_FLOAT); + ret_type=TYPE_BOOL; - function->return_type=get_token_datatype(parser.get_token_type(0)); + } break; + case OP_AND: + case OP_OR: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - { //add to programnode - ProgramNode::Function f; - f.name=name; - f.function=function; - program->functions.push_back(f); - } + valid = na==nb && na==TYPE_BOOL; + ret_type=TYPE_BOOL; - int ofs=3; + } break; + case OP_NOT: { - while(true) { + DataType na = p_op->arguments[0]->get_datatype(); + valid = na==TYPE_BOOL; + ret_type=TYPE_BOOL; - //end of arguments - if (parser.get_token_type(ofs)==TK_PARENTHESIS_CLOSE) { - ofs++; - break; - } - //next argument awaits - if (parser.get_token_type(ofs)==TK_COMMA) { - if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+1))) { - parser.set_error("Expected Identifier or ')' following ','"); - return ERR_PARSE_ERROR; + } break; + case OP_INCREMENT: + case OP_DECREMENT: + case OP_POST_INCREMENT: + case OP_POST_DECREMENT: + case OP_NEGATE: { + DataType na = p_op->arguments[0]->get_datatype(); + valid = na>TYPE_BOOL && na<TYPE_MAT2; + ret_type=na; + } break; + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na>nb) { + //make things easier; + SWAP(na,nb); + } + + if (na==nb) { + valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4); + ret_type=na; + } else if (na==TYPE_INT && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_INT && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_INT && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_UINT && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UINT && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UINT && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC2) { + valid=true; + ret_type=TYPE_VEC2; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC3) { + valid=true; + ret_type=TYPE_VEC3; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC4) { + valid=true; + ret_type=TYPE_VEC4; + } else if (p_op->op==OP_MUL && na==TYPE_VEC2 && nb==TYPE_MAT2) { + valid=true; + ret_type=TYPE_MAT2; + } else if (p_op->op==OP_MUL && na==TYPE_VEC3 && nb==TYPE_MAT3) { + valid=true; + ret_type=TYPE_MAT3; + } else if (p_op->op==OP_MUL && na==TYPE_VEC4 && nb==TYPE_MAT4) { + valid=true; + ret_type=TYPE_MAT4; } - ofs++; - continue; - } + } break; + case OP_ASSIGN_MOD: + case OP_MOD: { + /* + * The operator modulus (%) operates on signed or unsigned integers or integer vectors. The operand + * types must both be signed or both be unsigned. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other vector, then the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. If both are vectors of the same size, the result is computed + * component-wise. + */ + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+0))) { - parser.set_error("Invalid Argument Type"); - return ERR_PARSE_ERROR; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + ///// + } else if (na==TYPE_UINT && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UINT; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; + } + } break; + case OP_ASSIGN_SHIFT_LEFT: + case OP_ASSIGN_SHIFT_RIGHT: + case OP_SHIFT_LEFT: + case OP_SHIFT_RIGHT: { - DataType identtype=get_token_datatype(parser.get_token_type(ofs+0)); + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - if (parser.get_token_type(ofs+1)!=TK_INDENTIFIER) { - parser.set_error("Expected Argument Identifier"); - return ERR_PARSE_ERROR; - } + if (na>=TYPE_UINT && na<=TYPE_UVEC4) { + na=DataType(na-4); + } - StringName identname=parser.get_token(ofs+1).text; + if (nb>=TYPE_UINT && nb<=TYPE_UVEC4) { + nb=DataType(nb-4); + } - if (test_existing_identifier(function,identname)) { - parser.set_error("Duplicate Argument Identifier: "+identname); - return ERR_DUPLICATE_SYMBOL; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + } + } break; + case OP_ASSIGN: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + valid=na==nb; + ret_type=na; + } break; + case OP_ASSIGN_ADD: + case OP_ASSIGN_SUB: + case OP_ASSIGN_MUL: + case OP_ASSIGN_DIV: { - FunctionNode::Argument arg; - arg.name=identname; - arg.type=identtype; - //function->body->variables[arg.name]=arg.type; - function->arguments.push_back(arg); + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - ofs+=2; - } - parser.advance(ofs); - // match { - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected '{'"); - return ERR_PARSE_ERROR; - } + if (na==nb) { + valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_ASSIGN_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4); + ret_type=na; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT ) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_VEC2 && nb==TYPE_FLOAT ) { + valid=true; + ret_type=TYPE_VEC2; + } else if (na==TYPE_VEC3 && nb==TYPE_FLOAT) { + valid=true; + ret_type=TYPE_VEC3; + } else if (na==TYPE_VEC4 && nb==TYPE_FLOAT) { + valid=true; + ret_type=TYPE_VEC4; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT2 && nb==TYPE_VEC2) { + valid=true; + ret_type=TYPE_MAT2; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT3 && nb==TYPE_VEC3) { + valid=true; + ret_type=TYPE_MAT3; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT4 && nb==TYPE_VEC4) { + valid=true; + ret_type=TYPE_MAT4; + } + } break; + case OP_ASSIGN_BIT_AND: + case OP_ASSIGN_BIT_OR: + case OP_ASSIGN_BIT_XOR: + case OP_BIT_AND: + case OP_BIT_OR: + case OP_BIT_XOR: { - parser.advance(); - Error err = parse_block(parser,function->body); + /* + * The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type + * signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned) + * must match. + */ - if (err) - return err; + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - // make sure that if the function has a return type, it does return something.. - if (function->return_type!=TYPE_VOID) { - bool found=false; - for(int i=0;i<function->body->statements.size();i++) { - if (function->body->statements[i]->type==Node::TYPE_CONTROL_FLOW) { + if (na>nb && p_op->op>=OP_BIT_AND) { + //can swap for non assign + SWAP(na,nb); + } - ControlFlowNode *cf = (ControlFlowNode*)function->body->statements[i]; - if (cf->flow_op==FLOW_OP_RETURN) { - // type of return was already checked when inserted - // no need to check here - found=true; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + ///// + } else if (na==TYPE_UINT && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UINT; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; } - } + } break; + case OP_BIT_INVERT: { //unaries + DataType na = p_op->arguments[0]->get_datatype(); + valid = na>=TYPE_INT && na<TYPE_FLOAT; + ret_type=na; + } break; + case OP_SELECT_IF: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + DataType nc = p_op->arguments[2]->get_datatype(); - if (!found) { - parser.set_error("Function must return a value (use the main block)"); - return ERR_PARSE_ERROR; + valid = na==TYPE_BOOL && (nb==nc); + ret_type=nb; + } break; + default: { + ERR_FAIL_V(false); } } - return OK; -} + if (r_ret_type) + *r_ret_type=ret_type; + return valid; +} -const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ +const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[]={ //constructors {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC3,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC3,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + + {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, @@ -791,10 +1213,132 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + + {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_IVEC2,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_IVEC2,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC3,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC3,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + + {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UVEC2,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UVEC2,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC2,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UVEC2,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC3,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC3,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"mat2",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - //intrinsics - trigonometry + + {"mat2",TYPE_MAT2,{TYPE_FLOAT,TYPE_VOID}}, + {"mat3",TYPE_MAT3,{TYPE_FLOAT,TYPE_VOID}}, + {"mat4",TYPE_MAT4,{TYPE_FLOAT,TYPE_VOID}}, + + //conversion scalars + + {"int",TYPE_INT,{TYPE_BOOL,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_UINT,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}}, + + {"float",TYPE_FLOAT,{TYPE_BOOL,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + + {"uint",TYPE_UINT,{TYPE_BOOL,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_INT,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}}, + + {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_INT,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_UINT,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + + //conversion vectors + + {"ivec2",TYPE_IVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"vec2",TYPE_VEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"uvec2",TYPE_UVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"bvec2",TYPE_BVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"ivec3",TYPE_IVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"vec3",TYPE_VEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"uvec3",TYPE_UVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"bvec3",TYPE_BVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"ivec4",TYPE_IVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"vec4",TYPE_VEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"uvec4",TYPE_UVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"bvec4",TYPE_BVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_VEC4,TYPE_VOID}}, + + //builtins - trigonometry {"sin",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"cos",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"tan",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, @@ -805,7 +1349,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"sinh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"cosh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"tanh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, - //intrinsics - exponential + //builtins - exponential {"pow",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, @@ -825,15 +1369,34 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"sqrt",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"sqrt",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"sqrt",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, - //intrinsics - common + //builtins - common {"abs",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"abs",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"abs",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"abs",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"abs",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"abs",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"abs",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"abs",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"abs",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"abs",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"abs",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"abs",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}}, + + {"sign",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"sign",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"sign",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"sign",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"sign",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"sign",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"sign",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"sign",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"floor",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"floor",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"floor",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, @@ -854,18 +1417,51 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"fract",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"fract",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"fract",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + {"mod",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"modf",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"modf",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"modf",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"modf",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"min",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"min",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"min",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"min",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"min",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"min",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"min",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"min",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + + {"min",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"min",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"min",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"min",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"max",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"max",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"max",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"max",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"max",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"max",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"max",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"max",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + + {"max",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"max",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"max",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"max",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + + {"clamp",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, @@ -873,13 +1469,39 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + + + {"clamp",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_INT,TYPE_INT,TYPE_VOID}}, + + {"clamp",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_BOOL,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BVEC2,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BVEC3,TYPE_VOID}}, {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BVEC3,TYPE_VOID}}, {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"step",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"step",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"step",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, @@ -895,7 +1517,37 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"smoothstep",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"smoothstep",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC4,TYPE_VOID}}, - //intrinsics - geometric + {"isnan",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}}, + + {"isinf",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}}, + + {"floatBitsToInt",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"floatBitsToUInt",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"intBitsToFloat",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"uintBitsToFloat",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}}, + + //builtins - geometric {"length",TYPE_FLOAT,{TYPE_VEC2,TYPE_VOID}}, {"length",TYPE_FLOAT,{TYPE_VEC3,TYPE_VOID}}, {"length",TYPE_FLOAT,{TYPE_VEC4,TYPE_VOID}}, @@ -911,318 +1563,211 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, {"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, - //intrinsics - texture - {"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}}, - {"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}}, - {"texscreen",TYPE_VEC3,{TYPE_VEC2,TYPE_VOID}}, - {"texpos",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, - {NULL,TYPE_VOID,{TYPE_VOID}} + {"facefordward",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"facefordward",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"facefordward",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -}; + {"matrixCompMult",TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2,TYPE_VOID}}, + {"matrixCompMult",TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3,TYPE_VOID}}, + {"matrixCompMult",TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ - - {OP_ASSIGN,TYPE_VOID,{TYPE_BOOL,TYPE_BOOL}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, - {OP_ADD,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ADD,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ADD,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ADD,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_SUB,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_SUB,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_SUB,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_SUB,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_MUL,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT3}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT2,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT2}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT3,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT4}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT4,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_MAT3,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_MAT4,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_MAT3}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_MAT4,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_MAT4}}, - {OP_MUL,TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2}}, - {OP_MUL,TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3}}, - {OP_MUL,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, - {OP_DIV,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}}, - {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}}, - {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_MAT2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_MAT4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_NEG,TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, - {OP_NEG,TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, - {OP_NEG,TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, - {OP_NEG,TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, - {OP_NOT,TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC2}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC4}}, - //{OP_CMP_EQ,TYPE_MAT3,{TYPE_MAT4,TYPE_MAT3}}, ?? - //{OP_CMP_EQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, ?? - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC2,TYPE_VEC2}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC4,TYPE_VEC4}}, - //{OP_CMP_NEQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, //? - {OP_CMP_LEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_GEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_LESS,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_GREATER,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_OR,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_AND,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_MAX,TYPE_VOID,{TYPE_VOID,TYPE_VOID}} -}; + {"outerProduct",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"outerProduct",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"outerProduct",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"transpose",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}}, + {"transpose",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}}, + {"transpose",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={ - - { "SRC_VERTEX", TYPE_VEC3}, - { "SRC_NORMAL", TYPE_VEC3}, - { "SRC_TANGENT", TYPE_VEC3}, - { "SRC_BINORMALF", TYPE_FLOAT}, - - { "POSITION", TYPE_VEC4 }, - { "VERTEX", TYPE_VEC3}, - { "NORMAL", TYPE_VEC3}, - { "TANGENT", TYPE_VEC3}, - { "BINORMAL", TYPE_VEC3}, - { "UV", TYPE_VEC2}, - { "UV2", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "BONES", TYPE_VEC4}, - { "WEIGHTS", TYPE_VEC4}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SPEC_EXP", TYPE_FLOAT}, - { "POINT_SIZE", TYPE_FLOAT}, - - //builtins - { "WORLD_MATRIX", TYPE_MAT4}, - { "INV_CAMERA_MATRIX", TYPE_MAT4}, - { "PROJECTION_MATRIX", TYPE_MAT4}, - { "MODELVIEW_MATRIX", TYPE_MAT4}, - { "INSTANCE_ID", TYPE_FLOAT}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID}, -}; -const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ - - { "VERTEX", TYPE_VEC3}, - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "TANGENT", TYPE_VEC3}, - { "BINORMAL", TYPE_VEC3}, - { "NORMALMAP", TYPE_VEC3}, - { "NORMALMAP_DEPTH", TYPE_FLOAT}, - { "UV", TYPE_VEC2}, - { "UV2", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "DIFFUSE", TYPE_VEC3}, - { "DIFFUSE_ALPHA", TYPE_VEC4}, - { "SPECULAR", TYPE_VEC3}, - { "EMISSION", TYPE_VEC3}, - { "SPEC_EXP", TYPE_FLOAT}, - { "GLOW", TYPE_FLOAT}, - { "SHADE_PARAM", TYPE_FLOAT}, - { "DISCARD", TYPE_BOOL}, - { "SCREEN_UV", TYPE_VEC2}, - { "POINT_COORD", TYPE_VEC2}, - { "INV_CAMERA_MATRIX", TYPE_MAT4}, - -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"determinant",TYPE_FLOAT,{TYPE_MAT2,TYPE_VOID}}, + {"determinant",TYPE_FLOAT,{TYPE_MAT3,TYPE_VOID}}, + {"determinant",TYPE_FLOAT,{TYPE_MAT4,TYPE_VOID}}, -}; + {"inverse",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}}, + {"inverse",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}}, + {"inverse",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ - - { "NORMAL", TYPE_VEC3}, - { "LIGHT_DIR", TYPE_VEC3}, - { "LIGHT_DIFFUSE", TYPE_VEC3}, - { "LIGHT_SPECULAR", TYPE_VEC3}, - { "EYE_VEC", TYPE_VEC3}, - { "DIFFUSE", TYPE_VEC3}, - { "SPECULAR", TYPE_VEC3}, - { "SPECULAR_EXP", TYPE_FLOAT}, - { "SHADE_PARAM", TYPE_FLOAT}, - { "LIGHT", TYPE_VEC3}, - { "SHADOW", TYPE_VEC3 }, - { "POINT_COORD", TYPE_VEC2 }, -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} -}; + {"lessThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"lessThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"lessThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ + {"greaterThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - { "SRC_VERTEX", TYPE_VEC2}, - { "VERTEX", TYPE_VEC2}, - { "WORLD_VERTEX", TYPE_VEC2}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "POINT_SIZE", TYPE_FLOAT}, + {"greaterThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, - //builtins - { "WORLD_MATRIX", TYPE_MAT4}, - { "PROJECTION_MATRIX", TYPE_MAT4}, - { "EXTRA_MATRIX", TYPE_MAT4}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID}, -}; -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ - - { "SRC_COLOR", TYPE_VEC4}, - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "NORMALMAP", TYPE_VEC3}, - { "NORMALMAP_DEPTH", TYPE_FLOAT}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "TEXTURE", TYPE_TEXTURE}, - { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SCREEN_UV", TYPE_VEC2}, - { "POINT_COORD", TYPE_VEC2}, - -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"greaterThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -}; + {"lessThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ - - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "TEXTURE", TYPE_TEXTURE}, - { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SCREEN_UV", TYPE_VEC2}, - { "LIGHT_VEC", TYPE_VEC2}, - { "LIGHT_HEIGHT", TYPE_FLOAT}, - { "LIGHT_COLOR", TYPE_VEC4}, - { "LIGHT_UV", TYPE_VEC2}, - { "LIGHT_SHADOW", TYPE_VEC4}, - { "LIGHT", TYPE_VEC4}, - { "SHADOW", TYPE_VEC4}, - { "POINT_COORD", TYPE_VEC2}, -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"lessThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, -}; + {"lessThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={ + {"greaterThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - { "IN_COLOR", TYPE_VEC3}, - { "IN_POSITION", TYPE_VEC3}, - { "OUT_COLOR", TYPE_VEC3}, - { "SCREEN_POS", TYPE_VEC2}, - { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} -}; + {"greaterThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"equal",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -ShaderLanguage::DataType ShaderLanguage::compute_node_type(Node *p_node) { + {"equal",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, - switch(p_node->type) { + {"equal",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, - case Node::TYPE_PROGRAM: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_FUNCTION: return static_cast<FunctionNode*>(p_node)->return_type; - case Node::TYPE_BLOCK: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_VARIABLE: return static_cast<VariableNode*>(p_node)->datatype_cache; - case Node::TYPE_CONSTANT: return static_cast<ConstantNode*>(p_node)->datatype; - case Node::TYPE_OPERATOR: return static_cast<OperatorNode*>(p_node)->return_cache; - case Node::TYPE_CONTROL_FLOW: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_MEMBER: return static_cast<MemberNode*>(p_node)->datatype; - } + {"equal",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}}, - return TYPE_VOID; -} + {"notEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"notEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"notEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, OperatorNode *p_func) { + {"notEqual",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}}, + + {"any",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"any",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"any",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + {"all",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"all",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"all",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + {"not",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"not",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"not",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + //builtins - texture + {"textureSize",TYPE_VEC2,{TYPE_SAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_ISAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_USAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_SAMPLERCUBE,TYPE_INT,TYPE_VOID}}, + + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texelFetch",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"texelFetch",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"texelFetch",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + + {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureGrad",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + + {"textureScreen",TYPE_VEC4,{TYPE_VEC2,TYPE_VOID}}, + + {"dFdx",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"dFdx",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"dFdx",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"dFdx",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"dFdy",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"dFdy",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"dFdy",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"dFdy",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"fwidth",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"fwidth",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"fwidth",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"fwidth",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + + {NULL,TYPE_VOID,{TYPE_VOID}} + +}; + + + +bool ShaderLanguage::_validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type) { ERR_FAIL_COND_V(p_func->op!=OP_CALL && p_func->op!=OP_CONSTRUCT,NULL); @@ -1231,44 +1776,49 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper ERR_FAIL_COND_V( p_func->arguments[0]->type!=Node::TYPE_VARIABLE, NULL ); - String name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String(); + StringName name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String(); bool all_const=true; for(int i=1;i<p_func->arguments.size();i++) { if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT) all_const=false; - args.push_back(compute_node_type(p_func->arguments[i])); + args.push_back(p_func->arguments[i]->get_datatype()); } int argcount=args.size(); - bool found_intrinsic=false; + bool failed_builtin=false; + if (argcount<=4) { - // test intrinsics + // test builtins int idx=0; - while (intrinsic_func_defs[idx].name) { + while (builtin_func_defs[idx].name) { - if (name==intrinsic_func_defs[idx].name) { + if (name==builtin_func_defs[idx].name) { + failed_builtin=true; bool fail=false; for(int i=0;i<argcount;i++) { - if (args[i]!=intrinsic_func_defs[idx].args[i]) { + if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),builtin_func_defs[idx].args[i])) { + //all good + } else if (args[i]!=builtin_func_defs[idx].args[i]) { fail=true; break; } } - if (!fail && argcount<4 && intrinsic_func_defs[idx].args[argcount]!=TYPE_VOID) + if (!fail && argcount<4 && builtin_func_defs[idx].args[argcount]!=TYPE_VOID) fail=true; //make sure the number of arguments matches if (!fail) { - p_func->return_cache=intrinsic_func_defs[idx].rettype; - found_intrinsic=true; - break; + if (r_ret_type) + *r_ret_type=builtin_func_defs[idx].rettype; + + return true; } } @@ -1277,8 +1827,24 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper } } + if (failed_builtin) { + String err ="Invalid arguments for built-in function: "+String(name)+"("; + for(int i=0;i<argcount;i++) { + if (i>0) + err+=","; + + if (p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && p_func->arguments[i+1]->get_datatype()==TYPE_INT && static_cast<ConstantNode*>(p_func->arguments[i+1])->values[0].sint<0) { + err+="-"; + } + err+=get_datatype_name(args[i]); + } + err+=")"; + _set_error(err); + return false; + } - if (found_intrinsic) { +#if 0 + if (found_builtin) { if (p_func->op==OP_CONSTRUCT && all_const) { @@ -1290,6 +1856,7 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper switch(v.get_type()) { case Variant::REAL: cdata.push_back(v); break; + case Variant::INT: cdata.push_back(v); break; case Variant::VECTOR2: { Vector2 v2=v; cdata.push_back(v2.x); cdata.push_back(v2.y); } break; case Variant::VECTOR3: { Vector3 v3=v; cdata.push_back(v3.x); cdata.push_back(v3.y); cdata.push_back(v3.z);} break; case Variant::PLANE: { Plane v4=v; cdata.push_back(v4.normal.x); cdata.push_back(v4.normal.y); cdata.push_back(v4.normal.z); cdata.push_back(v4.d); } break; @@ -1331,193 +1898,335 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper } return p_func; } - +#endif // try existing functions.. - FunctionNode *exclude_function=NULL; //exclude current function (in case inside one) - - - Node *node = p_func; + StringName exclude_function; + BlockNode *block = p_block; - while(node->parent) { + while(block) { - if (node->type==Node::TYPE_FUNCTION) { - - exclude_function = (FunctionNode*)node; + if (block->parent_function) { + exclude_function=block->parent_function->name; } + block=block->parent_block; + } - node=node->parent; + if (name==exclude_function) { + _set_error("Recursion is not allowed"); + return false; } - ERR_FAIL_COND_V(node->type!=Node::TYPE_PROGRAM,NULL); - ProgramNode *program = (ProgramNode*)node; + for(int i=0;i<shader->functions.size();i++) { - for(int i=0;i<program->functions.size();i++) { - if (program->functions[i].function==exclude_function) + if (name != shader->functions[i].name) continue; - FunctionNode *pfunc = program->functions[i].function; + if (!shader->functions[i].callable) { + _set_error("Function '"+String(name)+" can't be called from source code."); + return false; + } + + FunctionNode *pfunc = shader->functions[i].function; + if (pfunc->arguments.size()!=args.size()) continue; bool fail=false; + for(int i=0;i<args.size();i++) { - if (args[i]!=pfunc->arguments[i].type) { + + if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),pfunc->arguments[i].type)) { + //all good + } else if (args[i]!=pfunc->arguments[i].type) { fail=true; break; } } - if (!fail && name == program->functions[i].name) { + if (!fail) { p_func->return_cache=pfunc->return_type; - return p_func; + return true; } } - return NULL; + return false; } -ShaderLanguage::Node * ShaderLanguage::validate_operator(Parser& parser,OperatorNode *p_func) { +bool ShaderLanguage::_parse_function_arguments(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,OperatorNode* p_func,int *r_complete_arg) { - int argcount = p_func->arguments.size(); - ERR_FAIL_COND_V(argcount>2,NULL); + TkPos pos = _get_tkpos(); + Token tk = _get_token(); - DataType argtype[2]={TYPE_VOID,TYPE_VOID}; - bool all_const=true; + if (tk.type==TK_PARENTHESIS_CLOSE) { + return true; + } - for(int i=0;i<argcount;i++) { + _set_tkpos(pos);; + + + while(true) { + + + if (r_complete_arg) { + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type==TK_CURSOR) { + + *r_complete_arg=p_func->arguments.size()-1; + } else { + + _set_tkpos(pos); + } + } + + Node *arg= _parse_and_reduce_expression(p_block,p_builtin_types); + + if (!arg) { + + return false; + } + + + p_func->arguments.push_back(arg); + + tk = _get_token(); + + + if (tk.type==TK_PARENTHESIS_CLOSE) { + + return true; + } else if (tk.type!=TK_COMMA) { + // something is broken + _set_error("Expected ',' or ')' after argument"); + return false; + } - argtype[i]=compute_node_type(p_func->arguments[i]); - if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT) - all_const=false; } - int idx=0; - bool valid=false; - while(operator_defs[idx].op!=OP_MAX) { + return true; +} + +bool ShaderLanguage::is_token_operator(TokenType p_type) { - if (p_func->op==operator_defs[idx].op) { + return (p_type==TK_OP_EQUAL || + p_type==TK_OP_NOT_EQUAL || + p_type==TK_OP_LESS || + p_type==TK_OP_LESS_EQUAL || + p_type==TK_OP_GREATER || + p_type==TK_OP_GREATER_EQUAL || + p_type==TK_OP_AND || + p_type==TK_OP_OR || + p_type==TK_OP_NOT || + p_type==TK_OP_ADD || + p_type==TK_OP_SUB || + p_type==TK_OP_MUL || + p_type==TK_OP_DIV || + p_type==TK_OP_MOD || + p_type==TK_OP_SHIFT_LEFT || + p_type==TK_OP_SHIFT_RIGHT || + p_type==TK_OP_ASSIGN || + p_type==TK_OP_ASSIGN_ADD || + p_type==TK_OP_ASSIGN_SUB || + p_type==TK_OP_ASSIGN_MUL || + p_type==TK_OP_ASSIGN_DIV || + p_type==TK_OP_ASSIGN_MOD || + p_type==TK_OP_ASSIGN_SHIFT_LEFT || + p_type==TK_OP_ASSIGN_SHIFT_RIGHT || + p_type==TK_OP_ASSIGN_BIT_AND || + p_type==TK_OP_ASSIGN_BIT_OR || + p_type==TK_OP_ASSIGN_BIT_XOR || + p_type==TK_OP_BIT_AND || + p_type==TK_OP_BIT_OR || + p_type==TK_OP_BIT_XOR || + p_type==TK_OP_BIT_INVERT || + p_type==TK_OP_INCREMENT || + p_type==TK_OP_DECREMENT || + p_type==TK_QUESTION || + p_type==TK_COLON ); +} - if (operator_defs[idx].args[0]==argtype[0] && operator_defs[idx].args[1]==argtype[1]) { +bool ShaderLanguage::convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value) { - p_func->return_cache=operator_defs[idx].rettype; - valid=true; - break; + if (p_constant->datatype==p_to_type) { + if (p_value) { + for(int i=0;i<p_constant->values.size();i++) { + p_value[i]=p_constant->values[i]; } } + return true; + } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_FLOAT) { + + if (p_value) { + p_value->real=p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_FLOAT) { + + if (p_value) { + p_value->real=p_constant->values[0].uint; + } + return true; + } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_UINT) { + if (p_constant->values[0].sint<0) { + return false; + } + if (p_value) { + p_value->uint=p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_INT) { + + if (p_constant->values[0].uint>0x7FFFFFFF) { + return false; + } + if (p_value) { + p_value->sint=p_constant->values[0].uint; + } + return true; + } else + return false; + +} + +bool ShaderLanguage::is_scalar_type(DataType p_type) { + + return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT; +} + +bool ShaderLanguage::is_sampler_type(DataType p_type) { + + return p_type==TYPE_SAMPLER2D || p_type==TYPE_ISAMPLER2D || p_type==TYPE_USAMPLER2D || p_type==TYPE_SAMPLERCUBE; + +} + +void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { + + Set<String> kws; + + int idx=0; + + while(keyword_list[idx].text) { + kws.insert(keyword_list[idx].text); idx++; } - if (!valid) - return NULL; + idx=0; -#define _RCO2(m_op,m_vop)\ -case m_op: {\ - ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\ - cn->datatype=p_func->return_cache; \ - Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,static_cast<ConstantNode*>(p_func->arguments[1])->value,cn->value,valid);\ - if (!valid)\ - return NULL;\ - return cn;\ -} break; - -#define _RCO1(m_op,m_vop)\ -case m_op: {\ - ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\ - cn->datatype=p_func->return_cache; \ - Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,Variant(),cn->value,valid);\ - if (!valid)\ - return NULL;\ - return cn;\ -} break; - - if (all_const) { - //reduce constant operator - switch(p_func->op) { - _RCO2(OP_ADD,Variant::OP_ADD); - _RCO2(OP_SUB,Variant::OP_SUBSTRACT); - _RCO2(OP_MUL,Variant::OP_MULTIPLY); - _RCO2(OP_DIV,Variant::OP_DIVIDE); - _RCO1(OP_NEG,Variant::OP_NEGATE); - _RCO1(OP_NOT,Variant::OP_NOT); - _RCO2(OP_CMP_EQ,Variant::OP_EQUAL); - _RCO2(OP_CMP_NEQ,Variant::OP_NOT_EQUAL); - _RCO2(OP_CMP_LEQ,Variant::OP_LESS_EQUAL); - _RCO2(OP_CMP_GEQ,Variant::OP_GREATER_EQUAL); - _RCO2(OP_CMP_LESS,Variant::OP_LESS); - _RCO2(OP_CMP_GREATER,Variant::OP_GREATER); - _RCO2(OP_CMP_OR,Variant::OP_OR); - _RCO2(OP_CMP_AND,Variant::OP_AND); - default: {} - } + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for(Set<String>::Element *E=kws.front();E;E=E->next()) { + r_keywords->push_back(E->get()); } +} +void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { - return p_func; + Set<String> kws; + + int idx=0; + + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for(Set<String>::Element *E=kws.front();E;E=E->next()) { + r_keywords->push_back(E->get()); + } } -bool ShaderLanguage::is_token_operator(TokenType p_type) { - return (p_type==TK_OP_EQUAL) || - (p_type==TK_OP_NOT_EQUAL) || - (p_type==TK_OP_LESS) || - (p_type==TK_OP_LESS_EQUAL) || - (p_type==TK_OP_GREATER) || - (p_type==TK_OP_GREATER_EQUAL) || - (p_type==TK_OP_AND) || - (p_type==TK_OP_OR) || - (p_type==TK_OP_NOT) || - (p_type==TK_OP_ADD) || - (p_type==TK_OP_SUB) || - (p_type==TK_OP_MUL) || - (p_type==TK_OP_DIV) || - (p_type==TK_OP_NEG) || - (p_type==TK_OP_ASSIGN) || - (p_type==TK_OP_ASSIGN_ADD) || - (p_type==TK_OP_ASSIGN_SUB) || - (p_type==TK_OP_ASSIGN_MUL) || - (p_type==TK_OP_ASSIGN_DIV); +ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { + + static const DataType scalar_types[]={ + TYPE_VOID, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + }; + + return scalar_types[p_type]; } -ShaderLanguage::Operator ShaderLanguage::get_token_operator(TokenType p_type) { - switch(p_type) { - case TK_OP_EQUAL: return OP_CMP_EQ ; - case TK_OP_NOT_EQUAL: return OP_CMP_NEQ; - case TK_OP_LESS: return OP_CMP_LESS ; - case TK_OP_LESS_EQUAL: return OP_CMP_LEQ ; - case TK_OP_GREATER: return OP_CMP_GREATER ; - case TK_OP_GREATER_EQUAL: return OP_CMP_GEQ ; - case TK_OP_AND: return OP_CMP_AND ; - case TK_OP_OR: return OP_CMP_OR ; - case TK_OP_NOT: return OP_NOT ; - case TK_OP_ADD: return OP_ADD ; - case TK_OP_SUB: return OP_SUB ; - case TK_OP_MUL: return OP_MUL ; - case TK_OP_DIV: return OP_DIV ; - case TK_OP_NEG: return OP_NEG ; - case TK_OP_ASSIGN: return OP_ASSIGN ; - case TK_OP_ASSIGN_ADD: return OP_ASSIGN_ADD ; - case TK_OP_ASSIGN_SUB: return OP_ASSIGN_SUB ; - case TK_OP_ASSIGN_MUL: return OP_ASSIGN_MUL ; - case TK_OP_ASSIGN_DIV: return OP_ASSIGN_DIV ; - default: ERR_FAIL_V(OP_MAX); + +bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block,CompletionType p_type,StringName& identifier) { + + identifier=StringName(); + + TkPos pos; + + Token tk = _get_token(); + + if (tk.type==TK_IDENTIFIER) { + identifier=tk.text; + pos = _get_tkpos(); + tk = _get_token(); + } + + if (tk.type==TK_CURSOR) { + + completion_type=p_type; + completion_line=tk_line; + completion_block=p_block; + + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type==TK_IDENTIFIER) { + identifier=identifier.operator String() + tk.text.operator String(); + } else { + _set_tkpos(pos); + } + return true; + } else if (identifier!=StringName()){ + _set_tkpos(pos); } - return OP_MAX; + return false; } -Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_expr) { + +ShaderLanguage::Node* ShaderLanguage::_parse_expression(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types) { Vector<Expression> expression; //Vector<TokenType> operators; @@ -1525,416 +2234,462 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex while(true) { Node *expr=NULL; + TkPos prepos = _get_tkpos(); + Token tk = _get_token(); + TkPos pos = _get_tkpos(); - if (parser.get_token_type()==TK_PARENTHESIS_OPEN) { + if (tk.type==TK_PARENTHESIS_OPEN) { //handle subexpression - parser.advance(); - Error err = parse_expression(parser,p_parent,&expr); - if (err) - return err; - if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) { + expr = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!expr) + return NULL; - parser.set_error("Expected ')' in expression"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + + if (tk.type!=TK_PARENTHESIS_CLOSE) { - parser.advance(); + _set_error("Expected ')' in expression"); + return NULL; + } - } else if (parser.get_token_type()==TK_REAL_CONSTANT) { + } else if (tk.type==TK_REAL_CONSTANT) { - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=parser.get_token().text.operator String().to_double(); + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.real=tk.constant; + constant->values.push_back(v); constant->datatype=TYPE_FLOAT; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_TRUE) { + + } else if (tk.type==TK_INT_CONSTANT) { + + + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.sint=tk.constant; + constant->values.push_back(v); + constant->datatype=TYPE_INT; + expr=constant; + + } else if (tk.type==TK_TRUE) { //print_line("found true"); //handle true constant - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=true; + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.boolean=true; + constant->values.push_back(v); constant->datatype=TYPE_BOOL; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_FALSE) { + + } else if (tk.type==TK_FALSE) { //handle false constant - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=false; + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.boolean=false; + constant->values.push_back(v); constant->datatype=TYPE_BOOL; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_TYPE_VOID) { - - //make sure void is not used in expression - parser.set_error("Void value not allowed in Expression"); - return ERR_PARSE_ERROR; - } else if (parser.get_token_type(1)==TK_PARENTHESIS_OPEN && (is_token_nonvoid_datatype(parser.get_token_type()) || parser.get_token_type()==TK_INDENTIFIER)) { - - - //function or constructor - StringName name; - DataType constructor=TYPE_VOID; - if (is_token_nonvoid_datatype(parser.get_token_type())) { - - constructor=get_token_datatype(parser.get_token_type()); - switch(get_token_datatype(parser.get_token_type())) { - case TYPE_BOOL: name="bool"; break; - case TYPE_FLOAT: name="float"; break; - case TYPE_VEC2: name="vec2"; break; - case TYPE_VEC3: name="vec3"; break; - case TYPE_VEC4: name="vec4"; break; - case TYPE_MAT2: name="mat2"; break; - case TYPE_MAT3: name="mat3"; break; - case TYPE_MAT4: name="mat4"; break; - default: ERR_FAIL_V(ERR_BUG); - } - } else { - name=parser.get_token().text; - } + } else if (tk.type==TK_TYPE_VOID) { - if (!test_existing_identifier(p_parent,name)) { + //make sure void is not used in expression + _set_error("Void value not allowed in Expression"); + return NULL; + } else if (is_token_nonvoid_datatype(tk.type)) { + //basic type constructor - parser.set_error("Unknown identifier in expression: "+name); - return ERR_PARSE_ERROR; - } + OperatorNode *func = alloc_node<OperatorNode>(); + func->op=OP_CONSTRUCT; - parser.advance(2); - OperatorNode *func = parser.create_node<OperatorNode>(p_parent); + if (is_token_precision(tk.type)) { - func->op=constructor!=TYPE_VOID?OP_CONSTRUCT:OP_CALL; + func->return_precision_cache=get_token_precision(tk.type); + tk=_get_token(); + } - VariableNode *funcname = parser.create_node<VariableNode>(func); - funcname->name=name; + VariableNode *funcname = alloc_node<VariableNode>(); + funcname->name=get_datatype_name(get_token_datatype(tk.type)); func->arguments.push_back(funcname); - //parse parameters + tk=_get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after type name"); + return NULL; + } - if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) { - parser.advance(); - } else { + int carg=-1; - while(true) { + bool ok = _parse_function_arguments(p_block,p_builtin_types,func,&carg); + if (carg>=0) { + completion_type=COMPLETION_CALL_ARGUMENTS; + completion_line=tk_line; + completion_block=p_block; + completion_function=funcname->name; + completion_argument=carg; + } - Node *arg=NULL; - Error err = parse_expression(parser,func,&arg); - if (err) - return err; - func->arguments.push_back(arg); + if (!ok) + return NULL; - if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) { - parser.advance(); - break; + if (!_validate_function_call(p_block,func,&func->return_cache)) { + _set_error("No matching constructor found for: '"+String(funcname->name)+"'"); + return NULL; + } + //validate_Function_call() - } else if (parser.get_token_type()==TK_COMMA) { + expr=_reduce_expression(p_block,func); - if (parser.get_token_type(1)==TK_PARENTHESIS_CLOSE) { - parser.set_error("Expression expected"); - return ERR_PARSE_ERROR; - } + } else if (tk.type==TK_IDENTIFIER) { - parser.advance(); - } else { - // something is broken - parser.set_error("Expected ',' or ')'"); - return ERR_PARSE_ERROR; - } + _set_tkpos(prepos); - } - } + StringName identifier; - expr=validate_function_call(parser,func); - if (!expr) { + _get_completable_identifier(p_block,COMPLETION_IDENTIFIER,identifier); - parser.set_error("Invalid arguments to function/constructor: "+StringName(name)); - return ERR_PARSE_ERROR; - } + tk=_get_token(); + if (tk.type==TK_PARENTHESIS_OPEN) { + //a function + StringName name = identifier; - } else if (parser.get_token_type()==TK_INDENTIFIER) { - //probably variable + OperatorNode *func = alloc_node<OperatorNode>(); + func->op=OP_CALL; + VariableNode *funcname = alloc_node<VariableNode>(); + funcname->name=name; + func->arguments.push_back(funcname); + int carg=-1; - Node *node =p_parent; - bool existing=false; - DataType datatype; - StringName identifier=parser.get_token().text; + bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg); - while(node) { + for(int i=0;i<shader->functions.size();i++) { + if (shader->functions[i].name==name) { + shader->functions[i].uses_function.insert(name); + } + } - if (node->type==Node::TYPE_BLOCK) { - BlockNode *block = (BlockNode*)node; - if (block->variables.has(identifier)) { - existing=true; - datatype=block->variables[identifier]; - break; - } + if (carg>=0) { + completion_type=COMPLETION_CALL_ARGUMENTS; + completion_line=tk_line; + completion_block=p_block; + completion_function=funcname->name; + completion_argument=carg; } - if (node->type==Node::TYPE_FUNCTION) { + if (!ok) + return NULL; - FunctionNode *function=(FunctionNode*)node; - for(int i=0;i<function->arguments.size();i++) { - if (function->arguments[i].name==identifier) { - existing=true; - datatype=function->arguments[i].type; - break; - } - } + if (!_validate_function_call(p_block,func,&func->return_cache)) { + _set_error("No matching function found for: '"+String(funcname->name)+"'"); + return NULL; + } - if (existing) - break; + expr=func; - } + } else { + //an identifier - if (node->type==Node::TYPE_PROGRAM) { + _set_tkpos(pos); - ProgramNode *program = (ProgramNode*)node; - if (program->builtin_variables.has(identifier)) { - datatype = program->builtin_variables[identifier]; - existing=true; - break; - } - if (program->uniforms.has(identifier)) { - datatype = program->uniforms[identifier].type; - existing=true; - break; - } + DataType data_type; + IdentifierType ident_type; + if (!_find_identifier(p_block,p_builtin_types,identifier,&data_type,&ident_type)) { + _set_error("Unknown identifier in expression: "+String(identifier)); + return NULL; } - node=node->parent; - } + if (ident_type==IDENTIFIER_FUNCTION) { + _set_error("Can't use function as identifier: "+String(identifier)); + return NULL; + } - if (!existing) { - parser.set_error("Nonexistent identifier in expression: "+identifier); - return ERR_PARSE_ERROR; + VariableNode *varname = alloc_node<VariableNode>(); + varname->name=identifier; + varname->datatype_cache=data_type; + expr=varname; } - VariableNode *varname = parser.create_node<VariableNode>(p_parent); - varname->name=identifier; - varname->datatype_cache=datatype; - parser.advance(); - expr=varname; - - } else if (parser.get_token_type()==TK_OP_SUB || parser.get_token_type()==TK_OP_NOT) { - //single prefix operators - TokenType token_type=parser.get_token_type(); - parser.advance(); - //Node *subexpr=NULL; - //Error err = parse_expression(parser,p_parent,&subexpr); - //if (err) - // return err; + } else if (tk.type==TK_OP_ADD) { + continue; //this one does nothing + } else if (tk.type==TK_OP_SUB || tk.type==TK_OP_NOT || tk.type==TK_OP_BIT_INVERT || tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) { - //OperatorNode *op = parser.create_node<OperatorNode>(p_parent); Expression e; e.is_op=true; - switch(token_type) { - case TK_OP_SUB: e.op=TK_OP_NEG; break; - case TK_OP_NOT: e.op=TK_OP_NOT; break; - //case TK_OP_PLUS_PLUS: op->op=OP_PLUS_PLUS; break; - //case TK_OP_MINUS_MINUS: op->op=OP_MINUS_MINUS; break; - default: ERR_FAIL_V(ERR_BUG); + switch(tk.type) { + case TK_OP_SUB: e.op=OP_NEGATE; break; + case TK_OP_NOT: e.op=OP_NOT; break; + case TK_OP_BIT_INVERT: e.op=OP_BIT_INVERT; break; + case TK_OP_INCREMENT: e.op=OP_INCREMENT; break; + case TK_OP_DECREMENT: e.op=OP_DECREMENT; break; + default: ERR_FAIL_V(NULL); } expression.push_back(e); - continue; } else { - print_line("found bug?"); - print_line("misplaced token: "+String(token_names[parser.get_token_type()])); - - parser.set_error("Error parsing expression, misplaced: "+String(token_names[parser.get_token_type()])); - return ERR_PARSE_ERROR; + _set_error("Expected expression, found: "+get_token_text(tk)); + return NULL; //nothing } - ERR_FAIL_COND_V(!expr,ERR_BUG); + ERR_FAIL_COND_V(!expr,NULL); /* OK now see what's NEXT to the operator.. */ /* OK now see what's NEXT to the operator.. */ /* OK now see what's NEXT to the operator.. */ + while(true) { + TkPos pos = _get_tkpos(); + tk=_get_token(); - if (parser.get_token_type()==TK_PERIOD) { + if (tk.type==TK_PERIOD) { - if (parser.get_token_type(1)!=TK_INDENTIFIER) { - parser.set_error("Expected identifier as member"); - return ERR_PARSE_ERROR; - } - - DataType dt = compute_node_type(expr); - String ident = parser.get_token(1).text; - - bool ok=true; - DataType member_type; - switch(dt) { - case TYPE_VEC2: { - - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else { - ok=false; - break; - } + StringName identifier; + if (_get_completable_identifier(p_block,COMPLETION_INDEX,identifier)) { + completion_base=expr->get_datatype(); + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { + if (identifier==StringName()) { + _set_error("Expected identifier as member"); + return NULL; + } - switch(c[i]) { - case 'r': - case 'g': - case 'x': - case 'y': - break; - default: - ok=false; - break; + DataType dt = expr->get_datatype(); + String ident = identifier; + + bool ok=true; + DataType member_type; + switch(dt) { + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-1); + } else if (l==2) { + member_type=dt; + } else { + ok=false; + break; } - } - } break; - case TYPE_VEC3: { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'x': + case 'y': + break; + default: + ok=false; + break; + } + } - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else if (l==3) { - member_type=TYPE_VEC3; - } else { - ok=false; - break; - } + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-2); + } else if (l==2) { + member_type=DataType(dt-1); + } else if (l==3) { + member_type=dt; + } else { + ok=false; + break; + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'b': + case 'x': + case 'y': + case 'z': + break; + default: + ok=false; + break; + } + } - switch(c[i]) { - case 'r': - case 'g': - case 'b': - case 'x': - case 'y': - case 'z': - break; - default: - ok=false; - break; + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-3); + } else if (l==2) { + member_type=DataType(dt-2); + } else if (l==3) { + member_type=DataType(dt-1);; + } else if (l==4) { + member_type=dt; + } else { + ok=false; + break; } - } - } break; - case TYPE_VEC4: { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'b': + case 'a': + case 'x': + case 'y': + case 'z': + case 'w': + break; + default: + ok=false; + break; + } + } - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else if (l==3) { - member_type=TYPE_VEC3; - } else if (l==4) { - member_type=TYPE_VEC4; - } else { - ok=false; - break; - } + } break; + case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break; + case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break; + case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break; + default: {} + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { - - switch(c[i]) { - case 'r': - case 'g': - case 'b': - case 'a': - case 'x': - case 'y': - case 'z': - case 'w': - break; - default: - ok=false; - break; - } - } + if (!ok) { - } break; - case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break; - case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break; - case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break; - default: {} - } + _set_error("Invalid member for expression: ."+ident); + return NULL; + } - if (!ok) { + MemberNode *mn = alloc_node<MemberNode>(); + mn->basetype=dt; + mn->datatype=member_type; + mn->name=ident; + mn->owner=expr; + expr=mn; - parser.set_error("Invalid member for expression: ."+ident); - return ERR_PARSE_ERROR; - } - MemberNode *mn = parser.create_node<MemberNode>(p_parent); - mn->basetype=dt; - mn->datatype=member_type; - mn->name=ident; - mn->owner=expr; - expr=mn; + //todo + //member (period) has priority over any operator + //creates a subindexing expression in place - parser.advance(2); - //todo - //member (period) has priority over any operator - //creates a subindexing expression in place + /*} else if (tk.type==TK_BRACKET_OPEN) { + //todo + //subindexing has priority over any operator + //creates a subindexing expression in place - } else if (parser.get_token_type()==TK_BRACKET_OPEN) { - //todo - //subindexing has priority over any operator - //creates a subindexing expression in place + */ + } else if (tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) { + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=tk.type==TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT; + op->arguments.push_back(expr); - } /*else if (parser.get_token_type()==TK_OP_PLUS_PLUS || parser.get_token_type()==TK_OP_MINUS_MINUS) { - //todo - //inc/dec operators have priority over any operator - //creates a subindexing expression in place - //return OK; //wtfs + if (!_validate_operator(op,&op->return_cache)) { + _set_error("Invalid base type for increment/decrement operator"); + return NULL; + } + expr=op; + } else { - } */ + _set_tkpos(pos); + break; + } + } Expression e; e.is_op=false; e.node=expr; expression.push_back(e); + pos = _get_tkpos(); + tk = _get_token(); - if (is_token_operator(parser.get_token_type())) { + if (is_token_operator(tk.type)) { Expression o; o.is_op=true; - o.op=parser.get_token_type(); + + switch(tk.type) { + + case TK_OP_EQUAL: o.op = OP_EQUAL; break; + case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break; + case TK_OP_LESS: o.op = OP_LESS; break; + case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break; + case TK_OP_GREATER: o.op = OP_GREATER; break; + case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break; + case TK_OP_AND: o.op = OP_AND; break; + case TK_OP_OR: o.op = OP_OR; break; + case TK_OP_ADD: o.op = OP_ADD; break; + case TK_OP_SUB: o.op = OP_SUB; break; + case TK_OP_MUL: o.op = OP_MUL; break; + case TK_OP_DIV: o.op = OP_DIV; break; + case TK_OP_MOD: o.op = OP_MOD; break; + case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break; + case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break; + case TK_OP_ASSIGN: o.op = OP_ASSIGN; break; + case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break; + case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break; + case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break; + case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break; + case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break; + case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break; + case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break; + case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break; + case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break; + case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break; + case TK_OP_BIT_AND: o.op = OP_BIT_AND; break; + case TK_OP_BIT_OR: o.op = OP_BIT_OR ; break; + case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break; + case TK_QUESTION: o.op = OP_SELECT_IF; break; + case TK_COLON: o.op = OP_SELECT_ELSE; break; + default: { + _set_error("Invalid token for operator: "+get_token_text(tk)); + return NULL; + } + } + expression.push_back(o); - parser.advance(); + } else { + _set_tkpos(pos); //something else, so rollback and end break; } } @@ -1948,6 +2703,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex int next_op=-1; int min_priority=0xFFFFF; bool is_unary=false; + bool is_ternary=false; for(int i=0;i<expression.size();i++) { @@ -1957,45 +2713,48 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex } bool unary=false; + bool ternary=false; int priority; switch(expression[i].op) { - - case TK_OP_NOT: priority=0; unary=true; break; - case TK_OP_NEG: priority=0; unary=true; break; - - case TK_OP_MUL: priority=1; break; - case TK_OP_DIV: priority=1; break; - - case TK_OP_ADD: priority=2; break; - case TK_OP_SUB: priority=2; break; - - // shift left/right =2 - - case TK_OP_LESS: priority=4; break; - case TK_OP_LESS_EQUAL: priority=4; break; - case TK_OP_GREATER: priority=4; break; - case TK_OP_GREATER_EQUAL: priority=4; break; - - case TK_OP_EQUAL: priority=5; break; - case TK_OP_NOT_EQUAL: priority=5; break; - - //bit and =5 - //bit xor =6 - //bit or=7 - - case TK_OP_AND: priority=8; break; - case TK_OP_OR: priority=9; break; - - // ?: = 10 - - case TK_OP_ASSIGN_ADD: priority=11; break; - case TK_OP_ASSIGN_SUB: priority=11; break; - case TK_OP_ASSIGN_MUL: priority=11; break; - case TK_OP_ASSIGN_DIV: priority=11; break; - case TK_OP_ASSIGN: priority=11; break; - - default: ERR_FAIL_V(ERR_BUG); //unexpected operator + case OP_EQUAL: priority=8; break; + case OP_NOT_EQUAL: priority=8; break; + case OP_LESS: priority=7; break; + case OP_LESS_EQUAL: priority=7; break; + case OP_GREATER: priority=7; break; + case OP_GREATER_EQUAL: priority=7; break; + case OP_AND: priority=12; break; + case OP_OR: priority=14; break; + case OP_NOT: priority=3; unary=true; break; + case OP_NEGATE: priority=3; unary=true; break; + case OP_ADD: priority=5; break; + case OP_SUB: priority=5; break; + case OP_MUL: priority=4; break; + case OP_DIV: priority=4; break; + case OP_MOD: priority=4; break; + case OP_SHIFT_LEFT: priority=6; break; + case OP_SHIFT_RIGHT: priority=6; break; + case OP_ASSIGN: priority=16; break; + case OP_ASSIGN_ADD: priority=16; break; + case OP_ASSIGN_SUB: priority=16; break; + case OP_ASSIGN_MUL: priority=16; break; + case OP_ASSIGN_DIV: priority=16; break; + case OP_ASSIGN_MOD: priority=16; break; + case OP_ASSIGN_SHIFT_LEFT: priority=16; break; + case OP_ASSIGN_SHIFT_RIGHT: priority=16; break; + case OP_ASSIGN_BIT_AND: priority=16; break; + case OP_ASSIGN_BIT_OR: priority=16; break; + case OP_ASSIGN_BIT_XOR: priority=16; break; + case OP_BIT_AND: priority=9; break; + case OP_BIT_OR: priority=11; break; + case OP_BIT_XOR: priority=10; break; + case OP_BIT_INVERT: priority=3; unary=true; break; + case OP_INCREMENT: priority=3; unary=true; break; + case OP_DECREMENT: priority=3; unary=true; break; + case OP_SELECT_IF: priority=15; ternary=true; break; + case OP_SELECT_ELSE: priority=15; ternary=true; break; + + default: ERR_FAIL_V(NULL); //unexpected operator } @@ -2005,11 +2764,12 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex next_op=i; min_priority=priority; is_unary=unary; + is_ternary=ternary; } } - ERR_FAIL_COND_V(next_op==-1,ERR_BUG); + ERR_FAIL_COND_V(next_op==-1,NULL); // OK! create operator.. // OK! create operator.. @@ -2021,48 +2781,90 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex expr_pos++; if (expr_pos==expression.size()) { //can happen.. - parser.set_error("Unexpected end of expression.."); - return ERR_BUG; + _set_error("Unexpected end of expression.."); + return NULL; } } //consecutively do unary opeators for(int i=expr_pos-1;i>=next_op;i--) { - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(expression[i].op); + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[i].op; op->arguments.push_back(expression[i+1].node); expression[i].is_op=false; - expression[i].node=validate_operator(parser,op); - if (!expression[i].node) { + expression[i].node=op; + + + if (!_validate_operator(op,&op->return_cache)) { String at; for(int i=0;i<op->arguments.size();i++) { if (i>0) at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + at+=get_datatype_name(op->arguments[i]->get_datatype()); } - parser.set_error("Invalid argument to unary operator "+String(token_names[op->op])+": "+at); - return ERR_PARSE_ERROR; + _set_error("Invalid arguments to unary operator '"+get_operator_text(op->op)+"' :" +at); + return NULL; } expression.remove(i+1); } + + } else if (is_ternary) { + + if (next_op <1 || next_op>=(expression.size()-1)) { + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if (next_op+2 >= expression.size() || !expression[next_op+2].is_op || expression[next_op+2].op!=OP_SELECT_ELSE) { + _set_error("Mising matching ':' for select operator"); + return NULL; + } + + + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; + op->arguments.push_back(expression[next_op-1].node); + op->arguments.push_back(expression[next_op+1].node); + op->arguments.push_back(expression[next_op+3].node); + + expression[next_op-1].is_op=false; + expression[next_op-1].node=op; + if (!_validate_operator(op,&op->return_cache)) { + + String at; + for(int i=0;i<op->arguments.size();i++) { + if (i>0) + at+=" and "; + at+=get_datatype_name(op->arguments[i]->get_datatype()); + + } + _set_error("Invalid argument to ternary ?: operator: "+at); + return NULL; + } + + for(int i=0;i<4;i++) { + expression.remove(next_op); + } + } else { if (next_op <1 || next_op>=(expression.size()-1)) { - parser.set_error("Parser bug.."); - ERR_FAIL_V(ERR_BUG); + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); } - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(expression[next_op].op); + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; if (expression[next_op-1].is_op) { - parser.set_error("Parser bug.."); - ERR_FAIL_V(ERR_BUG); + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); } if (expression[next_op+1].is_op) { @@ -2071,645 +2873,1032 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex // can be followed by an unary op in a valid combination, // due to how precedence works, unaries will always dissapear first - parser.set_error("Parser bug.."); + _set_error("Parser bug.."); } op->arguments.push_back(expression[next_op-1].node); //expression goes as left op->arguments.push_back(expression[next_op+1].node); //next expression goes as right + expression[next_op-1].node=op; //replace all 3 nodes by this operator and make it an expression - expression[next_op-1].node=validate_operator(parser,op); - if (!expression[next_op-1].node) { + + if (!_validate_operator(op,&op->return_cache)) { String at; for(int i=0;i<op->arguments.size();i++) { if (i>0) at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + at+=get_datatype_name(op->arguments[i]->get_datatype()); } - static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"}; - - parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at); - return ERR_PARSE_ERROR; + _set_error("Invalid arguments to operator '"+get_operator_text(op->op)+"' :" +at); + return NULL; } + expression.remove(next_op); expression.remove(next_op); } -#if 0 - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(operators[next_op]); + } + + return expression[0].node; +} + + +ShaderLanguage::Node* ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) { + + if (p_node->type!=Node::TYPE_OPERATOR) + return p_node; + + //for now only reduce simple constructors + OperatorNode *op=static_cast<OperatorNode*>(p_node); + + if (op->op==OP_CONSTRUCT) { + + + ERR_FAIL_COND_V(op->arguments[0]->type!=Node::TYPE_VARIABLE,p_node); + VariableNode *vn = static_cast<VariableNode*>(op->arguments[0]); + // StringName name=vn->name; + + DataType base=get_scalar_type(op->get_datatype()); - op->arguments.push_back(expressions[next_op]); //expression goes as left - op->arguments.push_back(expressions[next_op+1]); //next expression goes as right + Vector<ConstantNode::Value> values; - expressions[next_op]=validate_operator(parser,op); - if (!expressions[next_op]) { - String at; - for(int i=0;i<op->arguments.size();i++) { - if (i>0) - at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + for(int i=1;i<op->arguments.size();i++) { + + op->arguments[i]=_reduce_expression(p_block,op->arguments[i]); + if (op->arguments[i]->type==Node::TYPE_CONSTANT) { + ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[i]); + + if (get_scalar_type(cn->datatype)==base) { + + for(int j=0;j<cn->values.size();j++) { + values.push_back(cn->values[j]); + } + } else if (get_scalar_type(cn->datatype)==cn->datatype) { + + ConstantNode::Value v; + if (!convert_constant(cn,base,&v)) { + return p_node; + } + values.push_back(v); + } else { + return p_node; + } + + } else { + return p_node; } - parser.set_error("Invalid arguments to operator "+String(token_names[operators[next_op]])+": "+at); - return ERR_PARSE_ERROR; } - expressions.remove(next_op+1); - operators.remove(next_op); -#endif + ConstantNode *cn=alloc_node<ConstantNode>(); + cn->datatype=op->get_datatype(); + cn->values=values; + return cn; + } else if (op->op==OP_NEGATE) { - } + op->arguments[0]=_reduce_expression(p_block,op->arguments[0]); + if (op->arguments[0]->type==Node::TYPE_CONSTANT) { - *r_expr=expression[0].node; + ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[0]); - return OK; + DataType base=get_scalar_type(cn->datatype); -/* - TokenType token_type=parser.get_token_type(); - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(parser.get_token_type()); + Vector<ConstantNode::Value> values; - op->arguments.push_back(*r_expr); //expression goes as left - parser.advance(); - Node *right_expr=NULL; - Error err = parse_expression(parser,p_parent,&right_expr); - if (err) - return err; - op->arguments.push_back(right_expr); + for(int i=0;i<cn->values.size();i++) { - if (!validate_operator(op)) { + ConstantNode::Value nv; + switch(base) { + case TYPE_BOOL: { + nv.boolean=!cn->values[i].boolean; + } break; + case TYPE_INT: { + nv.sint=-cn->values[i].sint; + } break; + case TYPE_UINT: { + nv.uint=-cn->values[i].uint; + } break; + case TYPE_FLOAT: { + nv.real=-cn->values[i].real; + } break; + default: {} + } - parser.set_error("Invalid arguments to operator "+String(token_names[token_type])); - return ERR_PARSE_ERROR; + values.push_back(nv); } -*/ + + cn->values=values; + return cn; + } + } + + return p_node; + } -Error ShaderLanguage::parse_variable_declaration(Parser& parser,BlockNode *p_block) { - bool uniform = parser.get_token(-1).type==TK_UNIFORM; +ShaderLanguage::Node* ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types) { - DataType type=get_token_datatype(parser.get_token_type(0)); - bool iscolor = parser.get_token_type(0)==TK_TYPE_COLOR; - if (type==TYPE_VOID) { + ShaderLanguage::Node* expr = _parse_expression(p_block,p_builtin_types); + if (!expr) //errored + return NULL; - parser.set_error("Cannot Declare a 'void' Variable"); - return ERR_PARSE_ERROR; - } + expr = _reduce_expression(p_block,expr); - if (type==TYPE_TEXTURE && !uniform) { + return expr; +} - parser.set_error("Cannot Declare a Non-Uniform Texture"); - return ERR_PARSE_ERROR; - } - if (type==TYPE_CUBEMAP && !uniform) { - parser.set_error("Cannot Declare a Non-Uniform Cubemap"); - return ERR_PARSE_ERROR; - } - parser.advance(); - int found=0; +Error ShaderLanguage::_parse_block(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,bool p_just_one,bool p_can_break,bool p_can_continue) { while(true) { + TkPos pos = _get_tkpos(); - if (found && parser.get_token_type()!=TK_COMMA) { - break; - } + Token tk = _get_token(); + if (tk.type==TK_CURLY_BRACKET_CLOSE) { //end of block + if (p_just_one) { + _set_error("Unexpected '}'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_INDENTIFIER) { + return OK; - parser.set_error("Identifier Expected"); - return ERR_PARSE_ERROR; + } else if (is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type)) { + DataPrecision precision=PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precission"); + return ERR_PARSE_ERROR; + } + } - } + DataType type = get_token_datatype(tk.type); - StringName name = parser.get_token().text; + tk = _get_token(); - if (test_existing_identifier(p_block,name)) { - parser.set_error("Duplicate Identifier (existing variable/function): "+name); - return ERR_PARSE_ERROR; - } + while(true) { - found=true; + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier after type"); + return ERR_PARSE_ERROR; + } - parser.advance(); - //see if declaration has an initializer - if (parser.get_token_type()==TK_OP_ASSIGN) { - parser.advance(); - OperatorNode * op = parser.create_node<OperatorNode>(p_block); - VariableNode * var = parser.create_node<VariableNode>(op); - var->name=name; - var->datatype_cache=type; - var->uniform=uniform; - Node *expr; - Error err = parse_expression(parser,p_block,&expr); + StringName name = tk.text; + if (_find_identifier(p_block,p_builtin_types,name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } - if (err) - return err; + BlockNode::Variable var; + var.type=type; + var.precision=precision; + var.line=tk_line; + p_block->variables[name]=var; - if (var->uniform) { + tk = _get_token(); - if (expr->type!=Node::TYPE_CONSTANT) { + if (tk.type==TK_OP_ASSIGN) { + //variable creted with assignment! must parse an expression + Node* n = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; - parser.set_error("Uniform can only be initialized to a constant."); - return ERR_PARSE_ERROR; + OperatorNode *assign = alloc_node<OperatorNode>(); + VariableNode *vnode = alloc_node<VariableNode>(); + vnode->name=name; + vnode->datatype_cache=type; + assign->arguments.push_back(vnode); + assign->arguments.push_back(n); + assign->op=OP_ASSIGN; + p_block->statements.push_back(assign); + tk = _get_token(); } - Uniform u; - u.order=parser.program->uniforms.size(); - u.type=type; - u.default_value=static_cast<ConstantNode*>(expr)->value; - if (iscolor && u.default_value.get_type()==Variant::PLANE) { - Color c; - Plane p = u.default_value; - c=Color(p.normal.x,p.normal.y,p.normal.z,p.d); - u.default_value=c; - } - parser.program->uniforms[var->name]=u; - } else { - op->op=OP_ASSIGN; - op->arguments.push_back(var); - op->arguments.push_back(expr); - Node *n=validate_operator(parser,op); - if (!n) { - parser.set_error("Invalid initializer for variable: "+name); + if (tk.type==TK_COMMA) { + tk = _get_token(); + //another variable + } else if (tk.type==TK_SEMICOLON) { + break; + } else { + _set_error("Expected ',' or ';' after variable"); return ERR_PARSE_ERROR; } - p_block->statements.push_back(n); + } + } else if (tk.type==TK_CURLY_BRACKET_OPEN) { + //a sub block, just because.. + BlockNode* block = alloc_node<BlockNode>(); + block->parent_block=p_block; + _parse_block(block,p_builtin_types,false,p_can_break,p_can_continue); + p_block->statements.push_back(block); + } else if (tk.type==TK_CF_IF) { + //if () {} + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after if"); + return ERR_PARSE_ERROR; } - } else { - //initialize it EMPTY - - OperatorNode * op = parser.create_node<OperatorNode>(p_block); - VariableNode * var = parser.create_node<VariableNode>(op); - ConstantNode * con = parser.create_node<ConstantNode>(op); - - var->name=name; - var->datatype_cache=type; - var->uniform=uniform; - con->datatype=type; - - switch(type) { - case TYPE_BOOL: con->value=false; break; - case TYPE_FLOAT: con->value=0.0; break; - case TYPE_VEC2: con->value=Vector2(); break; - case TYPE_VEC3: con->value=Vector3(); break; - case TYPE_VEC4: con->value=iscolor?Variant(Color()):Variant(Plane()); break; - case TYPE_MAT2: con->value=Matrix32(); break; - case TYPE_MAT3: con->value=Matrix3(); break; - case TYPE_MAT4: con->value=Transform(); break; - case TYPE_TEXTURE: - case TYPE_CUBEMAP: con->value=RID(); break; - default: {} + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op=FLOW_OP_IF; + Node* n = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected '(' after expression"); + return ERR_PARSE_ERROR; } - if (uniform) { - Uniform u; - u.type=type; - u.default_value=con->value; - u.order=parser.program->uniforms.size(); - parser.program->uniforms[var->name]=u; + BlockNode* block = alloc_node<BlockNode>(); + block->parent_block=p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + + Error err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue); + + pos=_get_tkpos(); + tk = _get_token(); + if (tk.type==TK_CF_ELSE) { + + block = alloc_node<BlockNode>(); + block->parent_block=p_block; + cf->blocks.push_back(block); + err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue); } else { - op->op=OP_ASSIGN; - op->arguments.push_back(var); - op->arguments.push_back(con); - p_block->statements.push_back(op); + _set_tkpos(pos); //rollback } - } + } else { - if (!uniform) - p_block->variables[name]=type; + //nothng else, so expression + _set_tkpos(pos); //rollback + Node*expr = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!expr) + return ERR_PARSE_ERROR; + p_block->statements.push_back(expr); + tk = _get_token(); - } + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';' after statement"); + return ERR_PARSE_ERROR; + } + } - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; + if (p_just_one) + break; } - return OK; - } -Error ShaderLanguage::parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement) { - ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent); +Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) { - cf->flow_op=FLOW_OP_IF; - parser.advance(); + Token tk = _get_token(); - if (parser.get_token_type()!=TK_PARENTHESIS_OPEN) { - parser.set_error("Expected '(' after 'if'"); - return ERR_PARSE_ERROR; - } - parser.advance(); + int texture_uniforms = 0; + int uniforms =0; - Node *expression=NULL; - Error err = parse_expression(parser,cf,&expression); - if (err) - return err; + while(tk.type!=TK_EOF) { - if (compute_node_type(expression)!=TYPE_BOOL) { + switch(tk.type) { + case TK_RENDER_MODE: { - parser.set_error("Expression for 'if' is not boolean"); - return ERR_PARSE_ERROR; - } + while(true) { - cf->statements.push_back(expression); + StringName mode; + _get_completable_identifier(NULL,COMPLETION_RENDER_MODE,mode); - if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) { - parser.set_error("Expected ')' after expression"); - return ERR_PARSE_ERROR; - } + if (mode==StringName()) { + _set_error("Expected identifier for render mode"); + return ERR_PARSE_ERROR; + } - parser.advance(); + if (!p_render_modes.has(mode)) { + _set_error("Invalid render mode: '"+String(mode)+"'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected statement block after 'if()'"); - return ERR_PARSE_ERROR; - } + if (shader->render_modes.find(mode)!=-1) { + _set_error("Duplicate render mode: '"+String(mode)+"'"); + return ERR_PARSE_ERROR; + } - Node *substatement=NULL; - err = parse_statement(parser,cf,&substatement); - if (err) - return err; + shader->render_modes.push_back(mode); - cf->statements.push_back(substatement); + tk = _get_token(); + if (tk.type==TK_COMMA) { + //all good, do nothing + } else if (tk.type==TK_SEMICOLON) { + break; //done + } else { + _set_error("Unexpected token: "+get_token_text(tk)); + return ERR_PARSE_ERROR; + } + } + } break; + case TK_UNIFORM: + case TK_VARYING: { + + bool uniform = tk.type==TK_UNIFORM; + DataPrecision precision = PRECISION_DEFAULT; + DataType type; + StringName name; + + tk = _get_token(); + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + } - if (parser.get_token_type()==TK_CF_ELSE) { + if (!is_token_datatype(tk.type)) { + _set_error("Expected datatype. "); + return ERR_PARSE_ERROR; + } - parser.advance(); + type = get_token_datatype(tk.type); - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected statement block after 'else'"); - return ERR_PARSE_ERROR; - } + if (type==TYPE_VOID) { + _set_error("void datatype not allowed here"); + return ERR_PARSE_ERROR; + } + if (!uniform && type<TYPE_FLOAT && type>TYPE_VEC4) { + _set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed."); + return ERR_PARSE_ERROR; + } - substatement=NULL; - err = parse_statement(parser,cf,&substatement); - if (err) - return err; + tk = _get_token(); + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier!"); + return ERR_PARSE_ERROR; + } - cf->statements.push_back(substatement); - } + name=tk.text; + if (_find_identifier(NULL,Map<StringName,DataType>(),name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } + if (uniform) { - *r_statement=cf; + ShaderNode::Uniform uniform; - return OK; -} + if (is_sampler_type(type)) { + uniform.texture_order=texture_uniforms++; + uniform.order=-1; + } else { + uniform.texture_order=-1; + uniform.order=uniforms++; + } + uniform.type=type; + uniform.precission=precision; -Error ShaderLanguage::parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement) { + //todo parse default value + tk = _get_token(); + if (tk.type==TK_OP_ASSIGN) { - FunctionNode *function=NULL; + Node* expr = _parse_and_reduce_expression(NULL,Map<StringName,DataType>()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type!=Node::TYPE_CONSTANT) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } - Node *parent=p_parent; + ConstantNode* cn = static_cast<ConstantNode*>(expr); - while(parent) { + uniform.default_value.resize(cn->values.size()); - if (parent->type==Node::TYPE_FUNCTION) { + if (!convert_constant(cn,uniform.type,uniform.default_value.ptr())) { + _set_error("Can't convert constant to "+get_datatype_name(uniform.type)); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } - function=(FunctionNode*)parent; - break; - } + if (tk.type==TK_COLON) { + //hint + + tk = _get_token(); + if (tk.type==TK_HINT_WHITE_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_WHITE; + } else if (tk.type==TK_HINT_BLACK_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_BLACK; + } else if (tk.type==TK_HINT_NORMAL_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_NORMAL; + } else if (tk.type==TK_HINT_ANISO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_ANISO; + } else if (tk.type==TK_HINT_ALBEDO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_ALBEDO; + } else if (tk.type==TK_HINT_BLACK_ALBEDO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_BLACK_ALBEDO; + } else if (tk.type==TK_HINT_COLOR) { + if (type!=TYPE_VEC4) { + _set_error("Color hint is for vec4 only"); + return ERR_PARSE_ERROR; + } + uniform.hint=ShaderNode::Uniform::HINT_COLOR; + } else if (tk.type==TK_HINT_RANGE) { + + uniform.hint=ShaderNode::Uniform::HINT_RANGE; + if (type!=TYPE_FLOAT && type!=TYPE_INT) { + _set_error("Range hint is for float and int only"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after hint_range"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + float sign=1.0; + + if (tk.type==TK_OP_SUB) { + sign=-1.0; + tk = _get_token(); + } + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[0]=tk.constant; + uniform.hint_range[0]*=sign; + + tk = _get_token(); + + if (tk.type!=TK_COMMA) { + _set_error("Expected ',' after integer constant"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + sign=1.0; + + if (tk.type==TK_OP_SUB) { + sign=-1.0; + tk = _get_token(); + } + + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[1]=tk.constant; + uniform.hint_range[1]*=sign; + + tk = _get_token(); + + if (tk.type==TK_COMMA) { + tk = _get_token(); + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[2]=tk.constant; + tk = _get_token(); + } else { + if (type==TYPE_INT) { + uniform.hint_range[2]=1; + } else { + uniform.hint_range[2]=0.001; + } + } + + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ','"); + return ERR_PARSE_ERROR; + } + + + } else { + _set_error("Expected valid type hint after ':'."); + } - parent=parent->parent; - } + if (uniform.hint!=ShaderNode::Uniform::HINT_RANGE && uniform.hint!=ShaderNode::Uniform::HINT_NONE && uniform.hint!=ShaderNode::Uniform::HINT_COLOR && type <=TYPE_MAT4) { + _set_error("This hint is only for sampler types"); + return ERR_PARSE_ERROR; - if (!function) { + } - parser.set_error("'return' must be inside a function"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + } - ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent); + shader->uniforms[name]=uniform; - cf->flow_op=FLOW_OP_RETURN; + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { - parser.advance(); + ShaderNode::Varying varying; + varying.type=type; + varying.precission=precision; + shader->varyings[name]=varying; - if (function->return_type!=TYPE_VOID) { - // should expect a return expression. + tk = _get_token(); + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } - Node *expr=NULL; - Error err = parse_expression(parser,cf,&expr); - if (err) - return err; + } - if (compute_node_type(expr)!=function->return_type) { - parser.set_error("Invalid type for 'return' expression"); - return ERR_PARSE_ERROR; - } - cf->statements.push_back(expr); - } - *r_statement=cf; + } break; + default: { + //function - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } + DataPrecision precision = PRECISION_DEFAULT; + DataType type; + StringName name; - return OK; -} + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + } -Error ShaderLanguage::parse_statement(Parser& parser,Node *p_parent,Node **r_statement) { + if (!is_token_datatype(tk.type)) { + _set_error("Expected funtion, uniform or varying "); + return ERR_PARSE_ERROR; + } - *r_statement=NULL; + type = get_token_datatype(tk.type); - TokenType token_type = parser.get_token_type(); + _get_completable_identifier(NULL,COMPLETION_MAIN_FUNCTION,name); - if (token_type==TK_CURLY_BRACKET_OPEN) { - //sub-block - parser.advance(); - BlockNode *block = parser.create_node<BlockNode>(p_parent); + if (name==StringName()) { + _set_error("Expected function name after datatype"); + return ERR_PARSE_ERROR; - *r_statement=block; - return parse_block(parser,block); - } else if (token_type==TK_SEMICOLON) { - // empty ; - parser.advance(); - return OK; - } else if (token_type==TK_CF_IF) { - return parse_flow_if(parser,p_parent,r_statement); + } - } else if (token_type==TK_CF_RETURN) { - return parse_flow_return(parser,p_parent,r_statement); - } else { - Error err=parse_expression(parser,p_parent,r_statement); - if (err) - return err; + if (_find_identifier(NULL,Map<StringName,DataType>(),name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after identifier"); + return ERR_PARSE_ERROR; - } + } - return OK; -} -Error ShaderLanguage::parse_block(Parser& parser,BlockNode *p_block) { + Map<StringName,DataType> builtin_types; + if (p_functions.has(name)) { + builtin_types=p_functions[name]; + } - while(true) { + ShaderNode::Function function; - if (parser.is_at_end()) { - if (p_block->parent->type!=Node::TYPE_PROGRAM) { - parser.set_error("Unexpected End of File"); - return ERR_PARSE_ERROR; - } - return OK; //bye - } + function.callable=!p_functions.has(name); + function.name=name; - TokenType token_type = parser.get_token_type(); + FunctionNode* func_node=alloc_node<FunctionNode>(); - if (token_type==TK_CURLY_BRACKET_CLOSE) { - if (p_block->parent->type==Node::TYPE_PROGRAM) { - parser.set_error("Unexpected '}'"); - return ERR_PARSE_ERROR; - } - parser.advance(); - return OK; // exit block + function.function=func_node; - } else if (token_type==TK_UNIFORM) { + shader->functions.push_back(function); - if (p_block!=parser.program->body) { + func_node->name=name; + func_node->return_type=type; + func_node->return_precision=precision; - parser.set_error("Uniform only allowed in main program body."); - return ERR_PARSE_ERROR; - } - parser.advance(); - Error err=parse_variable_declaration(parser,p_block); - if (err) - return err; + func_node->body = alloc_node<BlockNode>(); + func_node->body->parent_function=func_node; - } else if (is_token_datatype(token_type)) { - Error err=OK; - if (parser_is_at_function(parser)) - err = parse_function(parser,p_block); - else { - err = parse_variable_declaration(parser,p_block); - } + tk = _get_token(); - if (err) - return err; + while(true) { + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } - } else { - // must be a statement - Node *statement=NULL; + DataType ptype; + StringName pname; + DataPrecision pprecision = PRECISION_DEFAULT; - Error err = parse_statement(parser,p_block,&statement); - if (err) - return err; - if (statement) { - p_block->statements.push_back(statement); - } + if (is_token_precision(tk.type)) { + pprecision=get_token_precision(tk.type); + tk = _get_token(); + } + + if (!is_token_datatype(tk.type)) { + _set_error("Expected a valid datatype for argument"); + return ERR_PARSE_ERROR; + } + + ptype=get_token_datatype(tk.type); + + if (ptype==TYPE_VOID) { + _set_error("void not allowed in argument"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier for argument name"); + return ERR_PARSE_ERROR; + } + + pname = tk.text; + + if (_find_identifier(func_node->body,builtin_types,pname)) { + _set_error("Redefinition of '"+String(pname)+"'"); + return ERR_PARSE_ERROR; + } + FunctionNode::Argument arg; + arg.type=ptype; + arg.name=pname; + arg.precision=pprecision; + + func_node->arguments.push_back(arg); + + tk = _get_token(); + + + if (tk.type==TK_COMMA) { + tk = _get_token(); + //do none and go on + } else if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ',' or ')' after identifier"); + return ERR_PARSE_ERROR; + } + + } + + if (p_functions.has(name)) { + //if one of the core functions, make sure they are of the correct form + if (func_node->arguments.size() > 0) { + _set_error("Function '"+String(name)+"' expects no arguments."); + return ERR_PARSE_ERROR; + } + if (func_node->return_type!=TYPE_VOID) { + _set_error("Function '"+String(name)+"' must be of void return type."); + return ERR_PARSE_ERROR; + } + } + + + //all good let's parse inside the fucntion! + tk = _get_token(); + if (tk.type!=TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' to begin function"); + return ERR_PARSE_ERROR; + } + + current_function = name; + + Error err = _parse_block(func_node->body,builtin_types); + if (err) + return err; + current_function=StringName(); + } } + + tk = _get_token(); } return OK; } +Error ShaderLanguage::compile(const String& p_code, const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) { + clear(); -Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) { + code=p_code; + nodes=NULL; - Parser parser(p_tokens); - parser.program = parser.create_node<ProgramNode>(NULL); - parser.program->body = parser.create_node<BlockNode>(parser.program); + shader = alloc_node<ShaderNode>(); + Error err = _parse_shader(p_functions,p_render_modes); + if (err!=OK) { + return err; + } + return OK; +} - //add builtins - switch(p_type) { - case SHADER_MATERIAL_VERTEX: { - int idx=0; - while (vertex_builtins_defs[idx].name) { - parser.program->builtin_variables[vertex_builtins_defs[idx].name]=vertex_builtins_defs[idx].type; - idx++; - } +Error ShaderLanguage::complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint) { + + clear(); + + code=p_code; + + nodes=NULL; + + shader = alloc_node<ShaderNode>(); + Error err = _parse_shader(p_functions,p_render_modes); + + switch(completion_type) { + + case COMPLETION_NONE: { + //do none + return ERR_PARSE_ERROR; } break; - case SHADER_MATERIAL_FRAGMENT: { - int idx=0; - while (fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[fragment_builtins_defs[idx].name]=fragment_builtins_defs[idx].type; - idx++; + case COMPLETION_RENDER_MODE: { + for(const Set<String>::Element *E=p_render_modes.front();E;E=E->next()) { + + r_options->push_back(E->get()); } + + return OK; } break; - case SHADER_MATERIAL_LIGHT: { - int idx=0; - while (light_builtins_defs[idx].name) { - parser.program->builtin_variables[light_builtins_defs[idx].name]=light_builtins_defs[idx].type; - idx++; + case COMPLETION_MAIN_FUNCTION: { + + for(const Map< StringName, Map<StringName,DataType> >::Element *E=p_functions.front();E;E=E->next()) { + + r_options->push_back(E->key()); } + + return OK; } break; - case SHADER_CANVAS_ITEM_VERTEX: { - int idx=0; - while (ci_vertex_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_vertex_builtins_defs[idx].name]=ci_vertex_builtins_defs[idx].type; - idx++; + case COMPLETION_IDENTIFIER: + case COMPLETION_FUNCTION_CALL: { + + bool comp_ident=completion_type==COMPLETION_IDENTIFIER; + Set<String> matches; + + StringName skip_function; + + BlockNode *block=completion_block; + + + while(block) { + + if (comp_ident) { + for (const Map<StringName,BlockNode::Variable>::Element *E=block->variables.front();E;E=E->next()) { + + if (E->get().line<completion_line) { + matches.insert(E->key()); + } + } + } + + + if (block->parent_function) { + if (comp_ident) { + for(int i=0;i<block->parent_function->arguments.size();i++) { + matches.insert(block->parent_function->arguments[i].name); + } + } + skip_function=block->parent_function->name; + } + block=block->parent_block; } - } break; - case SHADER_CANVAS_ITEM_FRAGMENT: { - int idx=0; - while (ci_fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_fragment_builtins_defs[idx].name]=ci_fragment_builtins_defs[idx].type; - idx++; + + if (comp_ident && skip_function!=StringName() && p_functions.has(skip_function)) { + + for (Map<StringName,DataType>::Element *E=p_functions[skip_function].front();E;E=E->next()) { + matches.insert(E->key()); + } } - } break; - case SHADER_CANVAS_ITEM_LIGHT: { - int idx=0; - while (ci_light_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_light_builtins_defs[idx].name]=ci_light_builtins_defs[idx].type; - idx++; + + if (comp_ident) { + for (const Map<StringName,ShaderNode::Varying>::Element *E=shader->varyings.front();E;E=E->next()) { + matches.insert(E->key()); + + } + for (const Map<StringName,ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + matches.insert(E->key()); + } + + } - } break; - case SHADER_POST_PROCESS: { + + for(int i=0;i<shader->functions.size();i++) { + if (!shader->functions[i].callable || shader->functions[i].name==skip_function) + continue; + matches.insert(String(shader->functions[i].name)+"("); + } + int idx=0; - while (postprocess_fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[postprocess_fragment_builtins_defs[idx].name]=postprocess_fragment_builtins_defs[idx].type; + + while (builtin_func_defs[idx].name) { + + matches.insert(String(builtin_func_defs[idx].name)+"("); idx++; } + + for(Set<String>::Element *E=matches.front();E;E=E->next()) { + r_options->push_back(E->get()); + } + + return OK; + } break; - } + case COMPLETION_CALL_ARGUMENTS: { - Error err = parse_block(parser,parser.program->body); - if (err) { - parser.get_error(r_error,r_err_line,r_err_column); - return err; - } + for(int i=0;i<shader->functions.size();i++) { + if (!shader->functions[i].callable) + continue; + if (shader->functions[i].name==completion_function) { - if (p_compile_func) { - err = p_compile_func(p_userdata,parser.program); - } + String calltip; - //clean up nodes created - while(parser.nodegc.size()) { + calltip+=get_datatype_name( shader->functions[i].function->return_type ); + calltip+=" "; + calltip+=shader->functions[i].name; + calltip+="("; - memdelete( parser.nodegc.front()->get() ); - parser.nodegc.pop_front(); - } - return err; -} + for(int j=0;j<shader->functions[i].function->arguments.size();j++) { -Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) { + if (j>0) + calltip+=", "; + else + calltip+=" "; - *r_error=""; - *r_err_line=0; - *r_err_column=0; - Vector<Token> tokens; + if (j==completion_argument) { + calltip+=CharType(0xFFFF); + } - Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column); - if (err!=OK) { - print_line("tokenizer error!"); - } + calltip+=get_datatype_name(shader->functions[i].function->arguments[j].type); + calltip+=" "; + calltip+=shader->functions[i].function->arguments[j].name; - if (err!=OK) { - return err; - } - err = parse(tokens,p_type,p_compile_func,p_userdata,r_error,r_err_line,r_err_column); - if (err!=OK) { - return err; - } - return OK; -} + if (j==completion_argument) { + calltip+=CharType(0xFFFF); + } + } -void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keywords) { + if (shader->functions[i].function->arguments.size()) + calltip+=" "; + calltip+=")"; - int idx=0; + r_call_hint=calltip; + return OK; + } - p_keywords->push_back("uniform"); - p_keywords->push_back("texture"); - p_keywords->push_back("cubemap"); - p_keywords->push_back("color"); - p_keywords->push_back("if"); - p_keywords->push_back("else"); + } - while(intrinsic_func_defs[idx].name) { + int idx=0; - p_keywords->push_back(intrinsic_func_defs[idx].name); - idx++; - } + String calltip; + while (builtin_func_defs[idx].name) { - switch(p_type) { - case SHADER_MATERIAL_VERTEX: { - idx=0; - while (vertex_builtins_defs[idx].name) { - p_keywords->push_back(vertex_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_MATERIAL_FRAGMENT: { - idx=0; - while (fragment_builtins_defs[idx].name) { - p_keywords->push_back(fragment_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_MATERIAL_LIGHT: { - idx=0; - while (light_builtins_defs[idx].name) { - p_keywords->push_back(light_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_CANVAS_ITEM_VERTEX: { - idx=0; - while (ci_vertex_builtins_defs[idx].name) { - p_keywords->push_back(ci_vertex_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_CANVAS_ITEM_FRAGMENT: { - idx=0; - while (ci_fragment_builtins_defs[idx].name) { - p_keywords->push_back(ci_fragment_builtins_defs[idx].name); + if (completion_function==builtin_func_defs[idx].name) { + + if (calltip.length()) + calltip+="\n"; + + calltip+=get_datatype_name( builtin_func_defs[idx].rettype ); + calltip+=" "; + calltip+=builtin_func_defs[idx].name; + calltip+="("; + + bool found_arg=false; + for(int i=0;i<4;i++) { + + if (builtin_func_defs[idx].args[i]==TYPE_VOID) + break; + + if (i>0) + calltip+=", "; + else + calltip+=" "; + + if (i==completion_argument) { + calltip+=CharType(0xFFFF); + } + + calltip+=get_datatype_name(builtin_func_defs[idx].args[i]); + + if (i==completion_argument) { + calltip+=CharType(0xFFFF); + } + + found_arg=true; + + } + + if (found_arg) + calltip+=" "; + calltip+=")"; + + + } idx++; } + + r_call_hint=calltip; + + return OK; + } break; - case SHADER_CANVAS_ITEM_LIGHT: { - idx=0; - while (ci_light_builtins_defs[idx].name) { - p_keywords->push_back(ci_light_builtins_defs[idx].name); - idx++; + case COMPLETION_INDEX: { + + const char colv[4]={'r','g','b','a'}; + const char coordv[4]={'x','y','z','w'}; + + + int limit=0; + + switch(completion_base) { + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + limit=2; + + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + limit=3; + + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + limit=4; + + } break; + case TYPE_MAT2: limit=2; break; + case TYPE_MAT3: limit=3; break; + case TYPE_MAT4: limit=4; break; + default: {} } - } break; - case SHADER_POST_PROCESS: { - idx=0; - while (postprocess_fragment_builtins_defs[idx].name) { - p_keywords->push_back(postprocess_fragment_builtins_defs[idx].name); - idx++; + for(int i=0;i<limit;i++) { + r_options->push_back(String::chr(colv[i])); + r_options->push_back(String::chr(coordv[i])); } + } break; + } + return ERR_PARSE_ERROR; +} + +String ShaderLanguage::get_error_text() { + + return error_str; +} + +int ShaderLanguage::get_error_line() { + + return error_line; } + +ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() { + + return shader; +} + +ShaderLanguage::ShaderLanguage() { + + nodes=NULL; +} + +ShaderLanguage::~ShaderLanguage() { + + clear(); +} + + diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 233b965bc8..6326b5089e 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -46,12 +46,24 @@ public: enum TokenType { TK_EMPTY, - TK_INDENTIFIER, + TK_IDENTIFIER, TK_TRUE, TK_FALSE, TK_REAL_CONSTANT, + TK_INT_CONSTANT, TK_TYPE_VOID, TK_TYPE_BOOL, + TK_TYPE_BVEC2, + TK_TYPE_BVEC3, + TK_TYPE_BVEC4, + TK_TYPE_INT, + TK_TYPE_IVEC2, + TK_TYPE_IVEC3, + TK_TYPE_IVEC4, + TK_TYPE_UINT, + TK_TYPE_UVEC2, + TK_TYPE_UVEC3, + TK_TYPE_UVEC4, TK_TYPE_FLOAT, TK_TYPE_VEC2, TK_TYPE_VEC3, @@ -59,9 +71,13 @@ public: TK_TYPE_MAT2, TK_TYPE_MAT3, TK_TYPE_MAT4, - TK_TYPE_TEXTURE, - TK_TYPE_CUBEMAP, - TK_TYPE_COLOR, + TK_TYPE_SAMPLER2D, + TK_TYPE_ISAMPLER2D, + TK_TYPE_USAMPLER2D, + TK_TYPE_SAMPLERCUBE, + TK_PRECISION_LOW, + TK_PRECISION_MID, + TK_PRECISION_HIGH, TK_OP_EQUAL, TK_OP_NOT_EQUAL, TK_OP_LESS, @@ -75,14 +91,35 @@ public: TK_OP_SUB, TK_OP_MUL, TK_OP_DIV, - TK_OP_NEG, + TK_OP_MOD, + TK_OP_SHIFT_LEFT, + TK_OP_SHIFT_RIGHT, TK_OP_ASSIGN, TK_OP_ASSIGN_ADD, TK_OP_ASSIGN_SUB, TK_OP_ASSIGN_MUL, TK_OP_ASSIGN_DIV, + TK_OP_ASSIGN_MOD, + TK_OP_ASSIGN_SHIFT_LEFT, + TK_OP_ASSIGN_SHIFT_RIGHT, + TK_OP_ASSIGN_BIT_AND, + TK_OP_ASSIGN_BIT_OR, + TK_OP_ASSIGN_BIT_XOR, + TK_OP_BIT_AND, + TK_OP_BIT_OR, + TK_OP_BIT_XOR, + TK_OP_BIT_INVERT, + TK_OP_INCREMENT, + TK_OP_DECREMENT, TK_CF_IF, TK_CF_ELSE, + TK_CF_FOR, + TK_CF_WHILE, + TK_CF_DO, + TK_CF_SWITCH, + TK_CF_CASE, + TK_CF_BREAK, + TK_CF_CONTINUE, TK_CF_RETURN, TK_BRACKET_OPEN, TK_BRACKET_CLOSE, @@ -90,31 +127,44 @@ public: TK_CURLY_BRACKET_CLOSE, TK_PARENTHESIS_OPEN, TK_PARENTHESIS_CLOSE, + TK_QUESTION, TK_COMMA, + TK_COLON, TK_SEMICOLON, TK_PERIOD, TK_UNIFORM, + TK_VARYING, + TK_RENDER_MODE, + TK_HINT_WHITE_TEXTURE, + TK_HINT_BLACK_TEXTURE, + TK_HINT_NORMAL_TEXTURE, + TK_HINT_ANISO_TEXTURE, + TK_HINT_ALBEDO_TEXTURE, + TK_HINT_BLACK_ALBEDO_TEXTURE, + TK_HINT_COLOR, + TK_HINT_RANGE, + TK_CURSOR, TK_ERROR, + TK_EOF, TK_MAX }; - - /* COMPILER */ - enum ShaderType { - SHADER_MATERIAL_VERTEX, - SHADER_MATERIAL_FRAGMENT, - SHADER_MATERIAL_LIGHT, - SHADER_CANVAS_ITEM_VERTEX, - SHADER_CANVAS_ITEM_FRAGMENT, - SHADER_CANVAS_ITEM_LIGHT, - SHADER_POST_PROCESS, - }; - enum DataType { TYPE_VOID, TYPE_BOOL, + TYPE_BVEC2, + TYPE_BVEC3, + TYPE_BVEC4, + TYPE_INT, + TYPE_IVEC2, + TYPE_IVEC3, + TYPE_IVEC4, + TYPE_UINT, + TYPE_UVEC2, + TYPE_UVEC3, + TYPE_UVEC4, TYPE_FLOAT, TYPE_VEC2, TYPE_VEC3, @@ -122,30 +172,58 @@ public: TYPE_MAT2, TYPE_MAT3, TYPE_MAT4, - TYPE_TEXTURE, - TYPE_CUBEMAP, + TYPE_SAMPLER2D, + TYPE_ISAMPLER2D, + TYPE_USAMPLER2D, + TYPE_SAMPLERCUBE, + }; + + enum DataPrecision { + PRECISION_LOWP, + PRECISION_MEDIUMP, + PRECISION_HIGHP, + PRECISION_DEFAULT, }; enum Operator { - OP_ASSIGN, + OP_EQUAL, + OP_NOT_EQUAL, + OP_LESS, + OP_LESS_EQUAL, + OP_GREATER, + OP_GREATER_EQUAL, + OP_AND, + OP_OR, + OP_NOT, + OP_NEGATE, OP_ADD, OP_SUB, OP_MUL, OP_DIV, + OP_MOD, + OP_SHIFT_LEFT, + OP_SHIFT_RIGHT, + OP_ASSIGN, OP_ASSIGN_ADD, OP_ASSIGN_SUB, OP_ASSIGN_MUL, OP_ASSIGN_DIV, - OP_NEG, - OP_NOT, - OP_CMP_EQ, - OP_CMP_NEQ, - OP_CMP_LEQ, - OP_CMP_GEQ, - OP_CMP_LESS, - OP_CMP_GREATER, - OP_CMP_OR, - OP_CMP_AND, + OP_ASSIGN_MOD, + OP_ASSIGN_SHIFT_LEFT, + OP_ASSIGN_SHIFT_RIGHT, + OP_ASSIGN_BIT_AND, + OP_ASSIGN_BIT_OR, + OP_ASSIGN_BIT_XOR, + OP_BIT_AND, + OP_BIT_OR, + OP_BIT_XOR, + OP_BIT_INVERT, + OP_INCREMENT, + OP_DECREMENT, + OP_SELECT_IF, + OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments + OP_POST_INCREMENT, + OP_POST_DECREMENT, OP_CALL, OP_CONSTRUCT, OP_MAX @@ -154,18 +232,21 @@ public: enum FlowOperation { FLOW_OP_IF, FLOW_OP_RETURN, - //FLOW_OP_FOR, - //FLOW_OP_WHILE, - //FLOW_OP_DO, - //FLOW_OP_BREAK, - //FLOW_OP_CONTINUE, + FLOW_OP_FOR, + FLOW_OP_WHILE, + FLOW_OP_DO, + FLOW_OP_BREAK, + FLOW_OP_SWITCH, + FLOW_OP_CONTINUE }; struct Node { + Node *next; + enum Type { - TYPE_PROGRAM, + TYPE_SHADER, TYPE_FUNCTION, TYPE_BLOCK, TYPE_VARIABLE, @@ -175,7 +256,6 @@ public: TYPE_MEMBER }; - Node * parent; Type type; virtual DataType get_datatype() const { return TYPE_VOID; } @@ -183,46 +263,75 @@ public: virtual ~Node() {} }; + template<class T> + T* alloc_node() { + T* node = memnew(T); + node->next=nodes; + nodes=node; + return node; + } + + Node *nodes; + struct OperatorNode : public Node { DataType return_cache; + DataPrecision return_precision_cache; Operator op; Vector<Node*> arguments; virtual DataType get_datatype() const { return return_cache; } - OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; } + OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; return_precision_cache=PRECISION_DEFAULT; } }; struct VariableNode : public Node { - bool uniform; DataType datatype_cache; StringName name; virtual DataType get_datatype() const { return datatype_cache; } - VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; uniform=false; } + VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; } }; struct ConstantNode : public Node { DataType datatype; - Variant value; + + union Value { + bool boolean; + float real; + int32_t sint; + uint32_t uint; + }; + + Vector<Value> values; virtual DataType get_datatype() const { return datatype; } ConstantNode() { type=TYPE_CONSTANT; } }; + struct FunctionNode; + struct BlockNode : public Node { + FunctionNode *parent_function; + BlockNode *parent_block; + + struct Variable { + DataType type; + DataPrecision precision; + int line; //for completion + }; - Map<StringName,DataType> variables; + Map<StringName,Variable> variables; List<Node*> statements; - BlockNode() { type=TYPE_BLOCK; } + BlockNode() { type=TYPE_BLOCK; parent_block=NULL; parent_function=NULL; } }; struct ControlFlowNode : public Node { FlowOperation flow_op; - Vector<Node*> statements; + Vector<Node*> expressions; + Vector<BlockNode*> blocks; ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;} }; @@ -244,39 +353,67 @@ public: StringName name; DataType type; + DataPrecision precision; }; StringName name; DataType return_type; + DataPrecision return_precision; Vector<Argument> arguments; BlockNode *body; - FunctionNode() { type=TYPE_FUNCTION; } + FunctionNode() { type=TYPE_FUNCTION; return_precision=PRECISION_DEFAULT; } }; - struct Uniform { - - int order; - DataType type; - Variant default_value; - }; - struct ProgramNode : public Node { + struct ShaderNode : public Node { struct Function { StringName name; FunctionNode*function; + Set<StringName> uses_function; + bool callable; + }; + + struct Varying { + DataType type; + DataPrecision precission; + }; + + struct Uniform { + enum Hint { + HINT_NONE, + HINT_COLOR, + HINT_RANGE, + HINT_ALBEDO, + HINT_BLACK_ALBEDO, + HINT_NORMAL, + HINT_BLACK, + HINT_WHITE, + HINT_ANISO, + HINT_MAX + }; + + int order; + int texture_order; + DataType type; + DataPrecision precission; + Vector<ConstantNode::Value> default_value; + Hint hint; + float hint_range[3]; + + Uniform() { hint=HINT_NONE; hint_range[0]=0; hint_range[1]=1; hint_range[2]=0.001;} }; - Map<StringName,DataType> builtin_variables; + Map<StringName,Varying> varyings; Map<StringName,Uniform> uniforms; + Vector<StringName> render_modes; Vector<Function> functions; - BlockNode *body; - ProgramNode() { type=TYPE_PROGRAM; } + ShaderNode() { type=TYPE_SHADER; } }; @@ -284,12 +421,12 @@ public: bool is_op; union { - TokenType op; + Operator op; Node *node; }; }; - typedef Error (*CompileFunc)(void*,ProgramNode*); + struct VarInfo { @@ -297,133 +434,163 @@ public: DataType type; }; -private: - - - - static const char * token_names[TK_MAX]; + enum CompletionType { + COMPLETION_NONE, + COMPLETION_RENDER_MODE, + COMPLETION_MAIN_FUNCTION, + COMPLETION_IDENTIFIER, + COMPLETION_FUNCTION_CALL, + COMPLETION_CALL_ARGUMENTS, + COMPLETION_INDEX, + }; struct Token { TokenType type; StringName text; - uint16_t line,col; - - Token(TokenType p_type=TK_EMPTY,const String& p_text=String()) { type=p_type; text=p_text; line=0; col=0; } + double constant; + uint16_t line; }; + static String get_operator_text(Operator p_op); + static String get_token_text(Token p_token); + + static bool is_token_datatype(TokenType p_type); + static DataType get_token_datatype(TokenType p_type); + static bool is_token_precision(TokenType p_type); + static DataPrecision get_token_precision(TokenType p_type); + static String get_datatype_name(DataType p_type); + static bool is_token_nonvoid_datatype(TokenType p_type); + static bool is_token_operator(TokenType p_type); + + static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL); + static DataType get_scalar_type(DataType p_type); + static bool is_scalar_type(DataType p_type); + static bool is_sampler_type(DataType p_type); - static Token read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars); - static Error tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column); + static void get_keyword_list(List<String> *r_keywords); + static void get_builtin_funcs(List<String> *r_keywords); +private: + struct KeyWord { TokenType token; const char *text;}; + static const KeyWord keyword_list[]; + bool error_set; + String error_str; + int error_line; + String code; + int char_idx; + int tk_line; - class Parser { + StringName current_function; - Vector<Token> tokens; - int pos; - String error; - public: + struct TkPos { + int char_idx; + int tk_line; + }; + TkPos _get_tkpos() { + TkPos tkp; + tkp.char_idx=char_idx; + tkp.tk_line=tk_line; + return tkp; + } - void set_error(const String& p_error) { error=p_error; } - void get_error(String *r_error, int *r_line, int *r_column) { - *r_error=error; - *r_line=get_token(pos).line; - *r_column=get_token(pos).col; - } + void _set_tkpos(TkPos p_pos) { + char_idx=p_pos.char_idx; + tk_line=p_pos.tk_line; + } + void _set_error(const String& p_str) { + if (error_set) + return; + error_line=tk_line; + error_set=true; + error_str=p_str; + } - Token get_token(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return Token(TK_ERROR); return tokens[idx]; } - TokenType get_token_type(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return TK_ERROR; return tokens[idx].type; } - void advance(int p_amount=1) { pos+=p_amount; } - bool is_at_end() const { return pos>=tokens.size(); } - ProgramNode *program; - template<class T> - T* create_node(Node *p_parent) { T*n=memnew( T ); nodegc.push_back(n); n->parent=p_parent; return n; } - List<Node*> nodegc; + static const char * token_names[TK_MAX]; - Parser(const Vector<Token>& p_tokens) { tokens=p_tokens; pos=0;} - }; - struct IntrinsicFuncDef { - enum { MAX_ARGS=5 }; - const char* name; - DataType rettype; - const DataType args[MAX_ARGS]; + Token _make_token(TokenType p_type, const StringName& p_text=StringName()); + Token _get_token(); + + ShaderNode *shader; + + enum IdentifierType { + IDENTIFIER_FUNCTION, + IDENTIFIER_UNIFORM, + IDENTIFIER_VARYING, + IDENTIFIER_FUNCTION_ARGUMENT, + IDENTIFIER_LOCAL_VAR, + IDENTIFIER_BUILTIN_VAR, }; - static const IntrinsicFuncDef intrinsic_func_defs[]; + bool _find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type=NULL, IdentifierType *r_type=NULL); - struct OperatorDef { + bool _validate_operator(OperatorNode *p_op,DataType *r_ret_type=NULL); - enum { MAX_ARGS=2 }; - Operator op; + + struct BuiltinFuncDef { + + enum { MAX_ARGS=5 }; + const char* name; DataType rettype; const DataType args[MAX_ARGS]; + }; - static const OperatorDef operator_defs[]; + CompletionType completion_type; + int completion_line; + BlockNode *completion_block; + DataType completion_base; + StringName completion_function; + int completion_argument; - struct BuiltinsDef { - const char* name; - DataType type; - }; + bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName& identifier); - static const BuiltinsDef vertex_builtins_defs[]; - static const BuiltinsDef fragment_builtins_defs[]; - static const BuiltinsDef light_builtins_defs[]; + static const BuiltinFuncDef builtin_func_defs[]; + bool _validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type); - static const BuiltinsDef ci_vertex_builtins_defs[]; - static const BuiltinsDef ci_fragment_builtins_defs[]; - static const BuiltinsDef ci_light_builtins_defs[]; + bool _parse_function_arguments(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types, OperatorNode* p_func, int *r_complete_arg=NULL); + Node* _parse_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types); - static const BuiltinsDef postprocess_fragment_builtins_defs[]; + ShaderLanguage::Node* _reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); + Node* _parse_and_reduce_expression(BlockNode *p_block,const Map<StringName,DataType> &p_builtin_types); - static DataType get_token_datatype(TokenType p_type); - static String get_datatype_name(DataType p_type); - static bool is_token_datatype(TokenType p_type); - static bool is_token_nonvoid_datatype(TokenType p_type); + Error _parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one=false, bool p_can_break=false, bool p_can_continue=false); - static bool test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func=true,bool p_var=true,bool p_builtin=true); + Error _parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes); - static bool parser_is_at_function(Parser& parser); - static DataType compute_node_type(Node *p_node); - static Node* validate_function_call(Parser&parser, OperatorNode *p_func); - static Node* validate_operator(Parser& parser,OperatorNode *p_func); - static bool is_token_operator(TokenType p_type); - static Operator get_token_operator(TokenType p_type); +public: - static Error parse_expression(Parser& parser,Node *p_parent,Node **r_expr); +// static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); - static Error parse_variable_declaration(Parser& parser,BlockNode *p_block); - static Error parse_function(Parser& parser,BlockNode *p_block); - static Error parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_statement(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_block(Parser& parser,BlockNode *p_block); + void clear(); + Error compile(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes); + Error complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint); - static Error parse(const Vector<Token> &p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column); -; -public: + String get_error_text(); + int get_error_line(); - static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); + ShaderNode *get_shader(); - static Error compile(const String& p_code,ShaderType p_type, CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column); - static String lex_debug(const String& p_code); + String token_debug(const String& p_code); + ShaderLanguage(); + ~ShaderLanguage(); }; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp new file mode 100644 index 0000000000..0eb3e0fc5a --- /dev/null +++ b/servers/visual/shader_types.cpp @@ -0,0 +1,182 @@ +#include "shader_types.h" + + +const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& ShaderTypes::get_functions(VS::ShaderMode p_mode) { + + return shader_modes[p_mode].functions; +} + +const Set<String>& ShaderTypes::get_modes(VS::ShaderMode p_mode) { + + return shader_modes[p_mode].modes; +} + + +ShaderTypes *ShaderTypes::singleton=NULL; + +ShaderTypes::ShaderTypes() +{ + singleton=this; + + /*************** SPATIAL ***********************/ + + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_TANGENT"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_BONES"]=ShaderLanguage::TYPE_IVEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_WEIGHTS"]=ShaderLanguage::TYPE_VEC4; + + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POSITION"]=ShaderLanguage::TYPE_VEC4 ; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TANGENT"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV2"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INSTANCE_ID"]=ShaderLanguage::TYPE_INT; + + //builtins + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRAGCOORD"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRONT_FACING"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TANGENT"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV2"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALBEDO"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALPHA"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECULAR"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ROUGHNESS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM_TINT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT_GLOSS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY_FLOW"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SSS_STRENGTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_opaque"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_always"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform"); + + /************ CANVAS ITEM **************************/ + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR1"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR2"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_VEC"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_HEIGHT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_SHADOW"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SHADOW"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_transform"); + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mix"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_add"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha"); + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only"); + + + /************ PARTICLES **************************/ + + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["VELOCITY"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["MASS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ACTIVE"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RESTART"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["CUSTOM"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TRANSFORM"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["LIFETIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ORIGIN"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"]=ShaderLanguage::TYPE_INT; + + shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity"); + + + + +} diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h new file mode 100644 index 0000000000..411d5790a9 --- /dev/null +++ b/servers/visual/shader_types.h @@ -0,0 +1,27 @@ +#ifndef SHADERTYPES_H +#define SHADERTYPES_H + +#include "shader_language.h" +#include "servers/visual_server.h" +class ShaderTypes { + + + struct Type { + + Map< StringName, Map<StringName,ShaderLanguage::DataType> > functions; + Set<String> modes; + }; + + Map<VS::ShaderMode,Type> shader_modes; + + static ShaderTypes *singleton; +public: + static ShaderTypes *get_singleton() { return singleton; } + + const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& get_functions(VS::ShaderMode p_mode); + const Set<String>& get_modes(VS::ShaderMode p_mode); + + ShaderTypes(); +}; + +#endif // SHADERTYPES_H diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp new file mode 100644 index 0000000000..f70ce46a3d --- /dev/null +++ b/servers/visual/visual_server_canvas.cpp @@ -0,0 +1,1268 @@ +#include "visual_server_canvas.h" +#include "visual_server_global.h" +#include "visual_server_viewport.h" + +void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color& p_modulate, RasterizerCanvas::Light *p_lights) { + + + static const int z_range = VS::CANVAS_ITEM_Z_MAX-VS::CANVAS_ITEM_Z_MIN+1; + RasterizerCanvas::Item *z_list[z_range]; + RasterizerCanvas::Item *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + + + _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights); + } + +} + +void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, const Color &p_modulate,int p_z,RasterizerCanvas::Item **z_list,RasterizerCanvas::Item **z_last_list,Item *p_canvas_clip,Item *p_material_owner) { + + Item *ci = p_canvas_item; + + if (!ci->visible) + return; + + Rect2 rect = ci->get_rect(); + Matrix32 xform = p_transform * ci->xform; + Rect2 global_rect = xform.xform(rect); + global_rect.pos+=p_clip_rect.pos; + + + if (ci->use_parent_material && p_material_owner) + ci->material_owner=p_material_owner; + else { + p_material_owner=ci; + ci->material_owner=NULL; + } + + + Color modulate( ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g,ci->modulate.b * p_modulate.b,ci->modulate.a * p_modulate.a); + + if (modulate.a<0.007) + return; + + + int child_item_count=ci->child_items.size(); + Item **child_items=(Item**)alloca(child_item_count*sizeof(Item*)); + copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(Item*)); + + if (ci->clip) { + if (p_canvas_clip != NULL) { + ci->final_clip_rect=p_canvas_clip->final_clip_rect.clip(global_rect); + } else { + ci->final_clip_rect=global_rect; + } + ci->final_clip_owner=ci; + + } else { + ci->final_clip_owner=p_canvas_clip; + } + + if (ci->sort_y) { + + SortArray<Item*,ItemPtrSort> sorter; + sorter.sort(child_items,child_item_count); + } + + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,VS::CANVAS_ITEM_Z_MIN,VS::CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; + + for(int i=0;i<child_item_count;i++) { + + if (!child_items[i]->behind) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,modulate,p_z,z_list,z_last_list,(Item*)ci->final_clip_owner,p_material_owner); + } + + if (ci->copy_back_buffer) { + + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + } + + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { + //something to draw? + ci->final_transform=xform; + ci->final_modulate=Color(modulate.r*ci->self_modulate.r, modulate.g*ci->self_modulate.g, modulate.b*ci->self_modulate.b, modulate.a*ci->self_modulate.a ); + ci->global_rect_cache=global_rect; + ci->global_rect_cache.pos-=p_clip_rect.pos; + ci->light_masked=false; + + int zidx = p_z-VS::CANVAS_ITEM_Z_MIN; + + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; + + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } + + ci->next=NULL; + + } + + for(int i=0;i<child_item_count;i++) { + + if (child_items[i]->behind) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,modulate,p_z,z_list,z_last_list,(Item*)ci->final_clip_owner,p_material_owner); + } + +} + +void VisualServerCanvas::_light_mask_canvas_items(int p_z,RasterizerCanvas::Item *p_canvas_item,RasterizerCanvas::Light *p_masked_lights) { + + if (!p_masked_lights) + return; + + RasterizerCanvas::Item *ci=p_canvas_item; + + while(ci) { + + RasterizerCanvas::Light *light=p_masked_lights; + while(light) { + + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { + ci->light_masked=true; + } + + light=light->mask_next_ptr; + } + + ci=ci->next; + } + + + + +} + +void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) { + + VSG::canvas_render->canvas_begin(); + + int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); + + bool has_mirror=false; + for(int i=0;i<l;i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; + } + } + + + if (!has_mirror) { + + static const int z_range = VS::CANVAS_ITEM_Z_MAX-VS::CANVAS_ITEM_Z_MIN+1; + RasterizerCanvas::Item *z_list[z_range]; + RasterizerCanvas::Item *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL); + } + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + + if (p_masked_lights) { + _light_mask_canvas_items(VS::CANVAS_ITEM_Z_MIN+i,z_list[i],p_masked_lights); + } + + VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights); + } + } else { + + for(int i=0;i<l;i++) { + + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,p_clip_rect,p_canvas->modulate,p_lights); + + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + + } + } + +} + + +RID VisualServerCanvas::canvas_create() { + + Canvas * canvas = memnew( Canvas ); + ERR_FAIL_COND_V(!canvas,RID()); + RID rid = canvas_owner.make_rid( canvas ); + + return rid; +} + +void VisualServerCanvas::canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring) { + + Canvas * canvas = canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + int idx = canvas->find_item(canvas_item); + ERR_FAIL_COND(idx==-1); + canvas->child_items[idx].mirror=p_mirroring; + +} +void VisualServerCanvas::canvas_set_modulate(RID p_canvas,const Color& p_color) { + + Canvas * canvas = canvas_owner.get(p_canvas); + ERR_FAIL_COND(!canvas); + canvas->modulate=p_color; +} + + +RID VisualServerCanvas::canvas_item_create() { + + Item *canvas_item = memnew( Item ); + ERR_FAIL_COND_V(!canvas_item,RID()); + + return canvas_item_owner.make_rid( canvas_item ); +} + +void VisualServerCanvas::canvas_item_set_parent(RID p_item,RID p_parent) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.get(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.get(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + } + + canvas_item->parent=RID(); + } + + + if (p_parent.is_valid()) { + if (canvas_owner.owns(p_parent)) { + + Canvas *canvas = canvas_owner.get(p_parent); + Canvas::ChildItem ci; + ci.item=canvas_item; + canvas->child_items.push_back(ci); + canvas->children_order_dirty=true; + } else if (canvas_item_owner.owns(p_parent)) { + + Item *item_owner = canvas_item_owner.get(p_parent); + item_owner->child_items.push_back(canvas_item); + item_owner->children_order_dirty=true; + + } else { + + ERR_EXPLAIN("Invalid parent"); + ERR_FAIL(); + } + + + } + + canvas_item->parent=p_parent; + + +} +void VisualServerCanvas::canvas_item_set_visible(RID p_item,bool p_visible){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->visible=p_visible; + +} +void VisualServerCanvas::canvas_item_set_light_mask(RID p_item,int p_mask){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->light_mask=p_mask; + +} + +void VisualServerCanvas::canvas_item_set_transform(RID p_item, const Matrix32& p_transform){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->xform=p_transform; + +} +void VisualServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clip=p_clip; + +} +void VisualServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->distance_field=p_enable; + + +} +void VisualServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->custom_rect=p_custom_rect; + canvas_item->rect=p_rect; + +} +void VisualServerCanvas::canvas_item_set_modulate(RID p_item, const Color& p_color) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->modulate=p_color; + +} +void VisualServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color& p_color){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->self_modulate=p_color; + +} + +void VisualServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->behind=p_enable; + +} + + +void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandLine * line = memnew( Item::CommandLine ); + ERR_FAIL_COND(!line); + line->color=p_color; + line->from=p_from; + line->to=p_to; + line->width=p_width; + line->antialiased=p_antialiased; + canvas_item->rect_dirty=true; + + + canvas_item->commands.push_back(line); +} + +void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_color; + rect->rect=p_rect; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(rect); +} + +void VisualServerCanvas::canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandCircle * circle = memnew( Item::CommandCircle ); + ERR_FAIL_COND(!circle); + circle->color=p_color; + circle->pos=p_pos; + circle->radius=p_radius; + + canvas_item->commands.push_back(circle); + +} + +void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate,bool p_transpose) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_modulate; + rect->rect=p_rect; + rect->flags=0; + if (p_tile) { + rect->flags|=RasterizerCanvas::CANVAS_RECT_TILE; + rect->flags|=RasterizerCanvas::CANVAS_RECT_REGION; + rect->source=Rect2(0,0,p_rect.size.width,p_rect.size.height); + } + + if (p_rect.size.x<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_rect.size.y<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_transpose) { + rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + rect->texture=p_texture; + canvas_item->rect_dirty=true; + canvas_item->commands.push_back(rect); +} + +void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate,bool p_transpose) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_modulate; + rect->rect=p_rect; + rect->texture=p_texture; + rect->source=p_src_rect; + rect->flags=RasterizerCanvas::CANVAS_RECT_REGION; + + if (p_rect.size.x<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_rect.size.y<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_transpose) { + rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(rect); + +} + +void VisualServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode, VS::NinePatchAxisMode p_y_axis_mode,bool p_draw_center,const Color& p_modulate) { + + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandNinePatch * style = memnew( Item::CommandNinePatch ); + ERR_FAIL_COND(!style); + style->texture=p_texture; + style->rect=p_rect; + style->source=p_source; + style->draw_center=p_draw_center; + style->color=p_modulate; + style->margin[MARGIN_LEFT]=p_topleft.x; + style->margin[MARGIN_TOP]=p_topleft.y; + style->margin[MARGIN_RIGHT]=p_bottomright.x; + style->margin[MARGIN_BOTTOM]=p_bottomright.y; + style->axis_x=p_x_axis_mode; + style->axis_y=p_y_axis_mode; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(style); +} +void VisualServerCanvas::canvas_item_add_primitive(RID p_item,const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPrimitive * prim = memnew( Item::CommandPrimitive ); + ERR_FAIL_COND(!prim); + prim->texture=p_texture; + prim->points=p_points; + prim->uvs=p_uvs; + prim->colors=p_colors; + prim->width=p_width; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(prim); +} + +void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); +#ifdef DEBUG_ENABLED + int pointcount = p_points.size(); + ERR_FAIL_COND(pointcount<3); + int color_size=p_colors.size(); + int uv_size=p_uvs.size(); + ERR_FAIL_COND(color_size!=0 && color_size!=1 && color_size!=pointcount); + ERR_FAIL_COND(uv_size!=0 && (uv_size!=pointcount || !p_texture.is_valid())); +#endif + Vector<int> indices = Geometry::triangulate_polygon(p_points); + + if (indices.empty()) { + + ERR_EXPLAIN("Bad Polygon!"); + ERR_FAIL_V(); + } + + Item::CommandPolygon * polygon = memnew( Item::CommandPolygon ); + ERR_FAIL_COND(!polygon); + polygon->texture=p_texture; + polygon->points=p_points; + polygon->uvs=p_uvs; + polygon->colors=p_colors; + polygon->indices=indices; + polygon->count=indices.size(); + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(polygon); + +} + + +void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture, int p_count) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + int ps = p_points.size(); + ERR_FAIL_COND(!p_colors.empty() && p_colors.size()!=ps && p_colors.size()!=1); + ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size()!=ps); + + Vector<int> indices = p_indices; + + int count = p_count * 3; + + if (indices.empty()) { + + ERR_FAIL_COND( ps % 3 != 0 ); + if (p_count == -1) + count = ps; + } else { + + ERR_FAIL_COND( indices.size() % 3 != 0 ); + if (p_count == -1) + count = indices.size(); + } + + Item::CommandPolygon * polygon = memnew( Item::CommandPolygon ); + ERR_FAIL_COND(!polygon); + polygon->texture=p_texture; + polygon->points=p_points; + polygon->uvs=p_uvs; + polygon->colors=p_colors; + polygon->indices=indices; + polygon->count = count; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(polygon); +} + + +void VisualServerCanvas::canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandTransform * tr = memnew( Item::CommandTransform ); + ERR_FAIL_COND(!tr); + tr->xform=p_transform; + + canvas_item->commands.push_back(tr); + +} + +void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMesh * m = memnew( Item::CommandMesh ); + ERR_FAIL_COND(!m); + m->mesh=p_mesh; + m->skeleton=p_skeleton; + + canvas_item->commands.push_back(m); +} +void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMultiMesh * mm = memnew( Item::CommandMultiMesh ); + ERR_FAIL_COND(!mm); + mm->multimesh=p_mesh; + mm->skeleton=p_skeleton; + + canvas_item->commands.push_back(mm); + +} + +void VisualServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandClipIgnore * ci = memnew( Item::CommandClipIgnore); + ERR_FAIL_COND(!ci); + ci->ignore=p_ignore; + + canvas_item->commands.push_back(ci); +} +void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->sort_y=p_enable; +} +void VisualServerCanvas::canvas_item_set_z(RID p_item, int p_z){ + + ERR_FAIL_COND(p_z<VS::CANVAS_ITEM_Z_MIN || p_z>VS::CANVAS_ITEM_Z_MAX); + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z=p_z; +} +void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z_relative=p_enable; + +} +void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) { + if (p_enable) { + canvas_item->copy_back_buffer = memnew( RasterizerCanvas::Item::CopyBackBuffer ); + } else { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer=NULL; + } + } + + if (p_enable) { + canvas_item->copy_back_buffer->rect=p_rect; + canvas_item->copy_back_buffer->full=p_rect==Rect2(); + } + +} + +void VisualServerCanvas::canvas_item_clear(RID p_item){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clear(); +} +void VisualServerCanvas::canvas_item_set_draw_index(RID p_item,int p_index){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->index=p_index; + + if (canvas_item_owner.owns( canvas_item->parent)) { + Item *canvas_item_parent = canvas_item_owner.getornull( canvas_item->parent ); + canvas_item_parent->children_order_dirty=true; + return; + } + + Canvas* canvas = canvas_owner.getornull( canvas_item->parent ); + if (canvas) { + canvas->children_order_dirty=true; + return; + } + +} + +void VisualServerCanvas::canvas_item_set_material(RID p_item, RID p_material){ + + Item *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->material=p_material; +} + +void VisualServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->use_parent_material=p_enable; + +} + +RID VisualServerCanvas::canvas_light_create(){ + + RasterizerCanvas::Light *clight = memnew( RasterizerCanvas::Light ); + clight->light_internal = VSG::canvas_render->light_internal_create(); + return canvas_light_owner.make_rid(clight); + +} +void VisualServerCanvas::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(clight->canvas); + canvas->lights.erase(clight); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + + clight->canvas=p_canvas; + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(clight->canvas); + canvas->lights.insert(clight); + } +} + + +void VisualServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->enabled=p_enabled; + +} +void VisualServerCanvas::canvas_light_set_scale(RID p_light, float p_scale){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->scale=p_scale; + +} +void VisualServerCanvas::canvas_light_set_transform(RID p_light, const Matrix32& p_transform){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->xform=p_transform; + +} +void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->texture=p_texture; + +} +void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->texture_offset=p_offset; + +} +void VisualServerCanvas::canvas_light_set_color(RID p_light, const Color& p_color){ + + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->color=p_color; +} +void VisualServerCanvas::canvas_light_set_height(RID p_light, float p_height){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->height=p_height; + +} +void VisualServerCanvas::canvas_light_set_energy(RID p_light, float p_energy){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->energy=p_energy; + +} +void VisualServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->z_min=p_min_z; + clight->z_max=p_max_z; + +} +void VisualServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + + clight->layer_max=p_max_layer; + clight->layer_min=p_min_layer; + + +} +void VisualServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->item_mask=p_mask; + +} +void VisualServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->item_shadow_mask=p_mask; + +} +void VisualServerCanvas::canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->mode=p_mode; + +} + + +void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->shadow_buffer.is_valid()==p_enabled) + return; + if (p_enabled) { + clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } else { + VSG::storage->free(clight->shadow_buffer); + clight->shadow_buffer=RID(); + } + +} +void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){ + + ERR_FAIL_COND(p_size<32 || p_size>16384); + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + int new_size = nearest_power_of_2(p_size);; + if (new_size==clight->shadow_buffer_size) + return; + + clight->shadow_buffer_size=nearest_power_of_2(p_size); + + if (clight->shadow_buffer.is_valid()) { + VSG::storage->free(clight->shadow_buffer); + clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } +} + +void VisualServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) { + + ERR_FAIL_COND(p_length<0); + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_gradient_length=p_length; + +} +void VisualServerCanvas::canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter) { + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_filter=p_filter; + +} +void VisualServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color& p_color) { + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_color=p_color; +} + + + +RID VisualServerCanvas::canvas_light_occluder_create() { + + RasterizerCanvas::LightOccluderInstance *occluder = memnew( RasterizerCanvas::LightOccluderInstance ); + + return canvas_light_occluder_owner.make_rid(occluder); +} +void VisualServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas){ + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + + occluder->canvas=p_canvas; + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.insert(occluder); + } +} +void VisualServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->enabled=p_enabled; +} +void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + } + + occluder->polygon=p_polygon; + occluder->polygon_buffer=RID(); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (!occluder_poly) + occluder->polygon=RID(); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->owners.insert(occluder); + occluder->polygon_buffer=occluder_poly->occluder; + occluder->aabb_cache=occluder_poly->aabb; + occluder->cull_cache=occluder_poly->cull_mode; + } + +} +void VisualServerCanvas::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->xform=p_xform; +} +void VisualServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->light_mask=p_mask; +} + +RID VisualServerCanvas::canvas_occluder_polygon_create() { + + LightOccluderPolygon * occluder_poly = memnew( LightOccluderPolygon ); + occluder_poly->occluder=VSG::storage->canvas_light_occluder_create(); + return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); + +} +void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed) { + + if (p_shape.size()<3) { + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape); + return; + } + + DVector<Vector2> lines; + int lc = p_shape.size()*2; + + lines.resize(lc-(p_closed?0:2)); + { + DVector<Vector2>::Write w = lines.write(); + DVector<Vector2>::Read r = p_shape.read(); + + 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 VisualServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) { + + LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + ERR_FAIL_COND(p_shape.size()&1); + + int lc = p_shape.size(); + occluder_poly->aabb=Rect2(); + { + DVector<Vector2>::Read r = p_shape.read(); + for(int i=0;i<lc;i++) { + if (i==0) + occluder_poly->aabb.pos=r[i]; + else + occluder_poly->aabb.expand_to(r[i]); + } + } + + VSG::storage->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape); + for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->aabb_cache=occluder_poly->aabb; + } +} + + +void VisualServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode) { + + LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->cull_mode=p_mode; + for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->cull_cache=p_mode; + } +} + + + +bool VisualServerCanvas::free(RID p_rid) { + + if (canvas_owner.owns(p_rid)) { + + Canvas *canvas = canvas_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas,false); + + while(canvas->viewports.size()) { + + VisualServerViewport::Viewport *vp = VSG::viewport->viewport_owner.get(canvas->viewports.front()->get()); + ERR_FAIL_COND_V(!vp,true); + + Map<RID,VisualServerViewport::Viewport::CanvasData>::Element *E=vp->canvas_map.find(p_rid); + ERR_FAIL_COND_V(!E,true); + vp->canvas_map.erase(p_rid); + + canvas->viewports.erase( canvas->viewports.front() ); + } + + for (int i=0;i<canvas->child_items.size();i++) { + + canvas->child_items[i].item->parent=RID(); + } + + for (Set<RasterizerCanvas::Light*>::Element *E=canvas->lights.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + + for (Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + + canvas_owner.free( p_rid ); + + memdelete( canvas ); + + } else if (canvas_item_owner.owns(p_rid)) { + + Item *canvas_item = canvas_item_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas_item,true); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.get(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.get(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + + } + } + + for (int i=0;i<canvas_item->child_items.size();i++) { + + canvas_item->child_items[i]->parent=RID(); + } + +// if (canvas_item->material) { +// canvas_item->material->owners.erase(canvas_item); +// } + + canvas_item_owner.free( p_rid ); + + memdelete( canvas_item ); + + } else if (canvas_light_owner.owns(p_rid)) { + + RasterizerCanvas::Light *canvas_light = canvas_light_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas_light,true); + + if (canvas_light->canvas.is_valid()) { + Canvas* canvas = canvas_owner.get(canvas_light->canvas); + if (canvas) + canvas->lights.erase(canvas_light); + } + + if (canvas_light->shadow_buffer.is_valid()) + VSG::storage->free(canvas_light->shadow_buffer); + + VSG::canvas_render->light_internal_free(canvas_light->light_internal); + + canvas_light_owner.free( p_rid ); + memdelete( canvas_light ); + + } else if (canvas_light_occluder_owner.owns(p_rid)) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid); + ERR_FAIL_COND_V(!occluder,true); + + if (occluder->polygon.is_valid()) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + + } + + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + + } + + canvas_light_occluder_owner.free( p_rid ); + memdelete(occluder); + + } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid); + ERR_FAIL_COND_V(!occluder_poly,true); + VSG::storage->free(occluder_poly->occluder); + + while(occluder_poly->owners.size()) { + + occluder_poly->owners.front()->get()->polygon=RID(); + occluder_poly->owners.erase( occluder_poly->owners.front() ); + } + + canvas_light_occluder_polygon_owner.free( p_rid ); + memdelete(occluder_poly); + } else { + return false; + } + + return true; +} + + + +VisualServerCanvas::VisualServerCanvas() +{ + +} diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h new file mode 100644 index 0000000000..b5412ed608 --- /dev/null +++ b/servers/visual/visual_server_canvas.h @@ -0,0 +1,214 @@ +#ifndef VISUALSERVERCANVAS_H +#define VISUALSERVERCANVAS_H + +#include "rasterizer.h" +#include "visual_server_viewport.h" + +class VisualServerCanvas { +public: + + + struct Item : public RasterizerCanvas::Item { + + + RID parent; // canvas it belongs to + List<Item*>::Element *E; + int z; + bool z_relative; + bool sort_y; + Color modulate; + Color self_modulate; + bool use_parent_material; + int index; + bool children_order_dirty; + + + Vector<Item*> child_items; + + + Item() { + children_order_dirty=true; + E=NULL; + z=0; + modulate=Color(1,1,1,1); + self_modulate=Color(1,1,1,1); + sort_y=false; + use_parent_material=false; + z_relative=true; + index=0; + } + }; + + + struct ItemPtrSort { + + _FORCE_INLINE_ bool operator()(const Item* p_left,const Item* p_right) const { + + return p_left->xform.elements[2].y < p_right->xform.elements[2].y; + } + }; + + struct LightOccluderPolygon : RID_Data { + + bool active; + Rect2 aabb; + VS::CanvasOccluderPolygonCullMode cull_mode; + RID occluder; + Set<RasterizerCanvas::LightOccluderInstance*> owners; + + LightOccluderPolygon() { active=false; cull_mode=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + RID_Owner<LightOccluderPolygon> canvas_light_occluder_polygon_owner; + + RID_Owner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner; + + struct Canvas : public VisualServerViewport::CanvasBase { + + Set<RID> viewports; + struct ChildItem { + + Point2 mirror; + Item *item; + bool operator<(const ChildItem& p_item) const { + return item->index < p_item.item->index; + } + }; + + + + Set<RasterizerCanvas::Light*> lights; + + Set<RasterizerCanvas::LightOccluderInstance*> occluders; + + bool children_order_dirty; + Vector<ChildItem> child_items; + Color modulate; + + int find_item(Item *p_item) { + for(int i=0;i<child_items.size();i++) { + if (child_items[i].item==p_item) + return i; + } + return -1; + } + void erase_item(Item *p_item) { + int idx=find_item(p_item); + if (idx>=0) + child_items.remove(idx); + } + + + Canvas() { modulate=Color(1,1,1,1); children_order_dirty=true; } + + }; + + + RID_Owner<Canvas> canvas_owner; + RID_Owner<Item> canvas_item_owner; + RID_Owner<RasterizerCanvas::Light> canvas_light_owner; + +private: + + void _render_canvas_item_tree(Item *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights); + void _render_canvas_item(Item *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); + void _light_mask_canvas_items(int p_z,RasterizerCanvas::Item *p_canvas_item,RasterizerCanvas::Light *p_masked_lights); +public: + + void render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights,const Rect2& p_clip_rect); + + 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); + + + RID canvas_item_create(); + void canvas_item_set_parent(RID p_item,RID p_parent); + + void canvas_item_set_visible(RID p_item,bool p_visible); + void canvas_item_set_light_mask(RID p_item,int p_mask); + + void canvas_item_set_transform(RID p_item, const Matrix32& p_transform); + void canvas_item_set_clip(RID p_item, bool p_clip); + void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); + void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); + void canvas_item_set_modulate(RID p_item, const Color& p_color); + void canvas_item_set_self_modulate(RID p_item, const Color& p_color); + + void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); + + + void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false); + void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color); + void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color); + void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); + void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); + void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode=VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode=VS::NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); + void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0); + void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID()); + void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1); + void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID()); + void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID()); + void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform); + void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); + void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); + void canvas_item_set_z(RID p_item, int p_z); + void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); + void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect); + + void canvas_item_clear(RID p_item); + void canvas_item_set_draw_index(RID p_item, int p_index); + + void canvas_item_set_material(RID p_item, RID p_material); + + void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + + RID canvas_light_create(); + void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); + void canvas_light_set_enabled(RID p_light, bool p_enabled); + void canvas_light_set_scale(RID p_light, float p_scale); + void canvas_light_set_transform(RID p_light, const Matrix32& p_transform); + void canvas_light_set_texture(RID p_light, RID p_texture); + void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); + void canvas_light_set_color(RID p_light, const Color& p_color); + void canvas_light_set_height(RID p_light, float p_height); + void canvas_light_set_energy(RID p_light, float p_energy); + void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); + void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); + void canvas_light_set_item_cull_mask(RID p_light, int p_mask); + void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); + + void canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode); + + + void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); + void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + void canvas_light_set_shadow_gradient_length(RID p_light, float p_length); + void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter); + void canvas_light_set_shadow_color(RID p_light, const Color& p_color); + + + + RID canvas_light_occluder_create(); + 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_transform(RID p_occluder,const Matrix32& 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 DVector<Vector2>& p_shape,bool p_closed); + void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape); + + + void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode); + + + bool free(RID p_rid); + VisualServerCanvas(); + + +}; + +#endif // VISUALSERVERCANVAS_H diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_global.cpp new file mode 100644 index 0000000000..32b9710f42 --- /dev/null +++ b/servers/visual/visual_server_global.cpp @@ -0,0 +1,10 @@ +#include "visual_server_global.h" + +RasterizerStorage *VisualServerGlobals::storage=NULL; +RasterizerCanvas *VisualServerGlobals::canvas_render=NULL; +RasterizerScene *VisualServerGlobals::scene_render=NULL; +Rasterizer *VisualServerGlobals::rasterizer=NULL; + +VisualServerCanvas *VisualServerGlobals::canvas=NULL; +VisualServerViewport *VisualServerGlobals::viewport=NULL; +VisualServerScene *VisualServerGlobals::scene=NULL; diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_global.h new file mode 100644 index 0000000000..d413334ac4 --- /dev/null +++ b/servers/visual/visual_server_global.h @@ -0,0 +1,26 @@ +#ifndef VISUALSERVERGLOBAL_H +#define VISUALSERVERGLOBAL_H + +#include "rasterizer.h" + +class VisualServerCanvas; +class VisualServerViewport; +class VisualServerScene; + +class VisualServerGlobals +{ +public: + + static RasterizerStorage *storage; + static RasterizerCanvas *canvas_render; + static RasterizerScene *scene_render; + static Rasterizer *rasterizer; + + static VisualServerCanvas *canvas; + static VisualServerViewport *viewport; + static VisualServerScene *scene; +}; + +#define VSG VisualServerGlobals + +#endif // VISUALSERVERGLOBAL_H diff --git a/servers/visual/visual_server_light_baker.cpp b/servers/visual/visual_server_light_baker.cpp new file mode 100644 index 0000000000..4956d78ab0 --- /dev/null +++ b/servers/visual/visual_server_light_baker.cpp @@ -0,0 +1,6 @@ +#include "visual_server_light_baker.h" + +VisualServerLightBaker::VisualServerLightBaker() +{ + +} diff --git a/servers/visual/visual_server_light_baker.h b/servers/visual/visual_server_light_baker.h new file mode 100644 index 0000000000..42f016f614 --- /dev/null +++ b/servers/visual/visual_server_light_baker.h @@ -0,0 +1,29 @@ +#ifndef VISUALSERVERLIGHTBAKER_H +#define VISUALSERVERLIGHTBAKER_H + +#include "servers/visual_server.h" + +class VisualServerLightBaker { +public: + + struct BakeCell { + + uint32_t cells[8]; + uint32_t neighbours[7]; //one unused + uint32_t albedo; //albedo in RGBE + uint32_t emission; //emissive light in RGBE + uint32_t light[4]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) + float alpha; //used for upsampling + uint32_t directional_pass; //used for baking directional + + }; + + + + + + + VisualServerLightBaker(); +}; + +#endif // VISUALSERVERLIGHTBAKER_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 757b1605d5..58cfab3b97 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -32,8 +32,150 @@ #include "default_mouse_cursor.xpm" #include "sort.h" #include "io/marshalls.h" +#include "visual_server_canvas.h" +#include "visual_server_global.h" +#include "visual_server_scene.h" + // careful, these may run in different threads than the visual server + + + +/* CURSOR */ +void VisualServerRaster::cursor_set_rotation(float p_rotation, int p_cursor ){ + +} +void VisualServerRaster::cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor, const Rect2 &p_region){ + +} +void VisualServerRaster::cursor_set_visible(bool p_visible, int p_cursor ){ + +} +void VisualServerRaster::cursor_set_pos(const Point2& p_pos, int p_cursor ){ + +} + +/* BLACK BARS */ + + +void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom){ + +} +void VisualServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom){ + +} + + +/* FREE */ + +void VisualServerRaster::free( RID p_rid ){ + + if (VSG::storage->free(p_rid)) + return; + if (VSG::canvas->free(p_rid)) + return; + if (VSG::viewport->free(p_rid)) + return; + if (VSG::scene->free(p_rid)) + return; + +} + +/* EVENT QUEUING */ + +void VisualServerRaster::draw(){ + + //if (changes) + // print_line("changes: "+itos(changes)); + + changes=0; + + VSG::rasterizer->begin_frame(); + + VSG::scene->update_dirty_instances(); //update scene stuff + + VSG::viewport->draw_viewports(); + VSG::scene->render_probes(); + //_draw_cursors_and_margins(); + VSG::rasterizer->end_frame(); + //draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame(); +} +void VisualServerRaster::sync(){ + +} +bool VisualServerRaster::has_changed() const{ + + return changes>0; +} +void VisualServerRaster::init(){ + + VSG::rasterizer->initialize(); + +} +void VisualServerRaster::finish(){ + + if (test_cube.is_valid()) { + free(test_cube); + } + + VSG::rasterizer->finalize(); +} + +/* STATUS INFORMATION */ + + +int VisualServerRaster::get_render_info(RenderInfo p_info){ + + return 0; +} + + + +/* TESTING */ + + + +void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale){ + +} +void VisualServerRaster::set_default_clear_color(const Color& p_color){ + +} + +bool VisualServerRaster::has_feature(Features p_feature) const { + + return false; +} + +RID VisualServerRaster::get_test_cube() { + if (!test_cube.is_valid()) { + test_cube=_make_test_cube(); + } + return test_cube; +} + +VisualServerRaster::VisualServerRaster() { + + VSG::canvas = memnew( VisualServerCanvas); + VSG::viewport = memnew( VisualServerViewport); + VSG::scene = memnew( VisualServerScene ); + VSG::rasterizer = Rasterizer::create(); + VSG::storage=VSG::rasterizer->get_storage(); + VSG::canvas_render=VSG::rasterizer->get_canvas(); + VSG::scene_render=VSG::rasterizer->get_scene(); + +} + +VisualServerRaster::~VisualServerRaster() { + + memdelete(VSG::canvas); + memdelete(VSG::viewport); + memdelete(VSG::rasterizer); +} + + +#if 0 + BalloonAllocator<> *VisualServerRaster::OctreeAllocator::allocator=NULL; #define VS_CHANGED\ @@ -265,33 +407,33 @@ RID VisualServerRaster::fixed_material_create() { return rasterizer->fixed_material_create(); } -void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled) { +void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedSpatialMaterialFlags p_flag, bool p_enabled) { rasterizer->fixed_material_set_flag(p_material,p_flag,p_enabled); } -bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const { +bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedSpatialMaterialFlags p_flag) const { return rasterizer->fixed_material_get_flag(p_material,p_flag); } -void VisualServerRaster::fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value) { +void VisualServerRaster::fixed_material_set_param(RID p_material, FixedSpatialMaterialParam p_parameter, const Variant& p_value) { VS_CHANGED; rasterizer->fixed_material_set_parameter(p_material,p_parameter,p_value); } -Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const { +Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_parameter(p_material,p_parameter); } -void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture) { +void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedSpatialMaterialParam p_parameter, RID p_texture) { VS_CHANGED; rasterizer->fixed_material_set_texture(p_material,p_parameter,p_texture); } -RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const { +RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texture(p_material,p_parameter); } @@ -299,12 +441,12 @@ RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialP -void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode) { +void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter, FixedSpatialMaterialTexCoordMode p_mode) { VS_CHANGED; rasterizer->fixed_material_set_texcoord_mode(p_material,p_parameter,p_mode); } -VS::FixedMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const { +VS::FixedSpatialMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texcoord_mode(p_material,p_parameter); } @@ -331,14 +473,14 @@ Transform VisualServerRaster::fixed_material_get_uv_transform(RID p_material) co return rasterizer->fixed_material_get_uv_transform(p_material); } -void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader) { +void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedSpatialMaterialLightShader p_shader) { VS_CHANGED; rasterizer->fixed_material_set_light_shader(p_material,p_shader); } -VisualServerRaster::FixedMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ +VisualServerRaster::FixedSpatialMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ return rasterizer->fixed_material_get_light_shader(p_material); } @@ -1146,7 +1288,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (p_octree.size()==0) { if (baked_light->data.octree_texture.is_valid()) rasterizer->free(baked_light->data.octree_texture); - baked_light->data.octree_texture=RID(); + baked_light->data.octree_texture; baked_light->octree_aabb=AABB(); baked_light->octree_tex_size=Size2(); } else { @@ -1203,7 +1345,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (tex_w!=baked_light->octree_tex_size.x || tex_h!=baked_light->octree_tex_size.y) { rasterizer->free(baked_light->data.octree_texture); - baked_light->data.octree_texture=RID(); + baked_light->data.octree_texture; baked_light->octree_tex_size.x=0; baked_light->octree_tex_size.y=0; } @@ -1212,7 +1354,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (baked_light->data.light_texture.is_valid()) { if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { rasterizer->free(baked_light->data.light_texture); - baked_light->data.light_texture=RID(); + baked_light->data.light_texture; baked_light->light_tex_size.x=0; baked_light->light_tex_size.y=0; } @@ -1220,20 +1362,20 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); - rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER); baked_light->octree_tex_size.x=tex_w; baked_light->octree_tex_size.y=tex_h; } if (!baked_light->data.light_texture.is_valid() && has_light_tex) { baked_light->data.light_texture=rasterizer->texture_create(); - rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER); baked_light->light_tex_size.x=light_tex_w; baked_light->light_tex_size.y=light_tex_h; } - Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_octree); rasterizer->texture_set_data(baked_light->data.octree_texture,img); } @@ -1276,7 +1418,7 @@ void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<u print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); - Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_light); rasterizer->texture_set_data(baked_light->data.light_texture,img); @@ -1611,8 +1753,8 @@ void VisualServerRaster::viewport_set_as_render_target(RID p_viewport,bool p_ena if (!p_enable) { rasterizer->free(viewport->render_target); - viewport->render_target=RID(); - viewport->render_target_texture=RID(); + viewport->render_target; + viewport->render_target_texture; if (viewport->update_list.in_list()) viewport_update_list.remove(&viewport->update_list); @@ -1811,7 +1953,7 @@ void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) { // a camera viewport->camera=p_camera; } else { - viewport->camera=RID(); + viewport->camera; } } @@ -1830,7 +1972,7 @@ void VisualServerRaster::viewport_set_scenario(RID p_viewport,RID p_scenario) { // a camera viewport->scenario=p_scenario; } else { - viewport->scenario=RID(); + viewport->scenario; } } @@ -2284,7 +2426,7 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { instance->base_type=INSTANCE_NONE; - instance->base_rid=RID(); + instance->base_rid; if (p_base.is_valid()) { @@ -3003,7 +3145,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc if (instance->sampled_light) { instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); - instance->data.sampled_light=RID(); + instance->data.sampled_light; } if(p_baked_light_sampler.is_valid()) { @@ -3016,7 +3158,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc instance->sampled_light=NULL; } - instance->data.sampled_light=RID(); + instance->data.sampled_light; } @@ -3432,7 +3574,7 @@ void VisualServerRaster::canvas_item_set_parent(RID p_item,RID p_parent) { item_owner->child_items.erase(canvas_item); } - canvas_item->parent=RID(); + canvas_item->parent; } @@ -4057,7 +4199,7 @@ void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas) } if (!canvas_owner.owns(p_canvas)) - p_canvas=RID(); + p_canvas; clight->canvas=p_canvas; if (clight->canvas.is_valid()) { @@ -4184,7 +4326,7 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); } else { rasterizer->free(clight->shadow_buffer); - clight->shadow_buffer=RID(); + clight->shadow_buffer; } @@ -4246,7 +4388,7 @@ void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,R } if (!canvas_owner.owns(p_canvas)) - p_canvas=RID(); + p_canvas; occluder->canvas=p_canvas; @@ -4279,12 +4421,12 @@ void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_ } occluder->polygon=p_polygon; - occluder->polygon_buffer=RID(); + occluder->polygon_buffer; if (occluder->polygon.is_valid()) { CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); if (!occluder_poly) - occluder->polygon=RID(); + occluder->polygon; ERR_FAIL_COND(!occluder_poly); occluder_poly->owners.insert(occluder); occluder->polygon_buffer=occluder_poly->occluder; @@ -4558,7 +4700,7 @@ void VisualServerRaster::free( RID p_rid ) { //detach skeletons for (Set<Instance*>::Element *F=E->get().front();F;F=F->next()) { - F->get()->data.skeleton=RID(); + F->get()->data.skeleton; } skeleton_dependency_map.erase(E); } @@ -4688,17 +4830,17 @@ void VisualServerRaster::free( RID p_rid ) { for (int i=0;i<canvas->child_items.size();i++) { - canvas->child_items[i].item->parent=RID(); + canvas->child_items[i].item->parent; } for (Set<Rasterizer::CanvasLight*>::Element *E=canvas->lights.front();E;E=E->next()) { - E->get()->canvas=RID(); + E->get()->canvas; } for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) { - E->get()->canvas=RID(); + E->get()->canvas; } canvas_owner.free( p_rid ); @@ -4726,7 +4868,7 @@ void VisualServerRaster::free( RID p_rid ) { for (int i=0;i<canvas_item->child_items.size();i++) { - canvas_item->child_items[i]->parent=RID(); + canvas_item->child_items[i]->parent; } if (canvas_item->material) { @@ -4798,7 +4940,7 @@ void VisualServerRaster::free( RID p_rid ) { while(occluder_poly->owners.size()) { - occluder_poly->owners.front()->get()->polygon=RID(); + occluder_poly->owners.front()->get()->polygon; occluder_poly->owners.erase( occluder_poly->owners.front() ); } @@ -6417,7 +6559,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { - F->get()->data.sampled_light=RID(); //do not use because nothing close + F->get()->data.sampled_light; //do not use because nothing close } } @@ -7679,7 +7821,7 @@ void VisualServerRaster::init() { Image img; img.create(default_mouse_cursor_xpm); - //img.convert(Image::FORMAT_RGB); + //img.convert(Image::FORMAT_RGB8); default_cursor_texture = texture_create_from_image(img, 0); aabb_random_points.resize( GLOBAL_DEF("render/aabb_random_points",16) ); @@ -7766,3 +7908,4 @@ VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { VisualServerRaster::~VisualServerRaster() { } +#endif diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 0b1bf8618e..f68731bef5 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -34,12 +34,17 @@ #include "servers/visual/rasterizer.h" #include "allocators.h" #include "octree.h" - +#include "visual_server_global.h" +#include "visual_server_viewport.h" +#include "visual_server_canvas.h" +#include "visual_server_scene.h" /** @author Juan Linietsky <reduzio@gmail.com> */ + + class VisualServerRaster : public VisualServer { @@ -57,6 +62,12 @@ class VisualServerRaster : public VisualServer { }; + int changes; + bool draw_extra_frame; + RID test_cube; + + + #if 0 struct Room { bool occlude_exterior; @@ -131,7 +142,7 @@ class VisualServerRaster : public VisualServer { Transform transform; - Camera() { + Camera() { visible_layers=0xFFFFFFFF; fov=60; @@ -140,8 +151,8 @@ class VisualServerRaster : public VisualServer { size=1.0; vaspect=false; - } - }; + } + }; struct Instance; @@ -374,97 +385,6 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner; - struct CanvasItem : public Rasterizer::CanvasItem { - - - RID parent; // canvas it belongs to - List<CanvasItem*>::Element *E; - RID viewport; - int z; - bool z_relative; - bool sort_y; - float opacity; - float self_opacity; - bool use_parent_material; - - - Vector<CanvasItem*> child_items; - - - CanvasItem() { - E=NULL; - z=0; - opacity=1; - self_opacity=1; - sort_y=false; - use_parent_material=false; - z_relative=true; - } - }; - - - struct CanvasItemPtrSort { - - _FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const { - - return p_left->xform.elements[2].y < p_right->xform.elements[2].y; - } - }; - - struct CanvasLightOccluder; - - struct CanvasLightOccluderPolygon { - - bool active; - Rect2 aabb; - CanvasOccluderPolygonCullMode cull_mode; - RID occluder; - Set<Rasterizer::CanvasLightOccluderInstance*> owners; - - CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } - }; - - - RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner; - - RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner; - - struct CanvasLight; - - struct Canvas { - - Set<RID> viewports; - struct ChildItem { - - Point2 mirror; - CanvasItem *item; - }; - - Set<Rasterizer::CanvasLight*> lights; - Set<Rasterizer::CanvasLightOccluderInstance*> occluders; - - Vector<ChildItem> child_items; - Color modulate; - - int find_item(CanvasItem *p_item) { - for(int i=0;i<child_items.size();i++) { - if (child_items[i].item==p_item) - return i; - } - return -1; - } - void erase_item(CanvasItem *p_item) { - int idx=find_item(p_item); - if (idx>=0) - child_items.remove(idx); - } - - Canvas() { modulate=Color(1,1,1,1); } - - }; - - - RID_Owner<Rasterizer::CanvasLight> canvas_light_owner; struct Viewport { @@ -658,635 +578,584 @@ class VisualServerRaster : public VisualServer { Rasterizer *rasterizer; -public: - - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture,const Image& p_image,CubeMapSide p_cube_side=CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture,CubeMapSide p_cube_side=CUBEMAP_LEFT) const; - virtual void texture_set_flags(RID p_texture,uint32_t p_flags) ; - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual bool texture_can_stream(RID p_texture) const; - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - virtual void texture_set_path(RID p_texture,const String& p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_debug_usage(List<TextureInfo> *r_info); - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - - /* SHADER API */ - - virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,ShaderMode p_mode); - virtual ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); - virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; +#endif - /* COMMON MATERIAL API */ +public: - virtual RID material_create(); +#define DISPLAY_CHANGED changes++; - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; +#define BIND0R(m_r,m_name) m_r m_name() { return BINDBASE->m_name(); } +#define BIND1R(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); } +#define BIND1RC(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); } +#define BIND2RC(m_r,m_name,m_type1,m_type2) m_r m_name(m_type1 arg1,m_type2 arg2) const { return BINDBASE->m_name(arg1,arg2); } +#define BIND3RC(m_r,m_name,m_type1,m_type2,m_type3) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) const { return BINDBASE->m_name(arg1,arg2,arg3); } +#define BIND4RC(m_r,m_name,m_type1,m_type2,m_type3,m_type4) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) const { return BINDBASE->m_name(arg1,arg2,arg3,arg4); } - virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant material_get_param(RID p_material, const StringName& p_param) const; +#define BIND1(m_name,m_type1) void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); } +#define BIND2(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2); } +#define BIND2C(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) const { BINDBASE->m_name(arg1,arg2); } +#define BIND3(m_name,m_type1,m_type2,m_type3) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3); } +#define BIND4(m_name,m_type1,m_type2,m_type3,m_type4) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4); } +#define BIND5(m_name,m_type1,m_type2,m_type3,m_type4,m_type5) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5); } +#define BIND6(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6); } +#define BIND7(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7); } +#define BIND8(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); } +#define BIND9(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); } +#define BIND10(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9,m_type10) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9,m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); } - virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const; +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::storage - virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode); - virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; + /* TEXTURE API */ - virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode); - virtual MaterialBlendMode material_get_blend_mode(RID p_material) const; - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; + BIND0R(RID,texture_create) + BIND5(texture_allocate,RID,int,int,Image::Format,uint32_t) + BIND3(texture_set_data,RID,const Image&,CubeMapSide) + BIND2RC(Image,texture_get_data,RID,CubeMapSide) + BIND2(texture_set_flags,RID,uint32_t) + BIND1RC(uint32_t,texture_get_flags,RID) + BIND1RC(Image::Format,texture_get_format,RID) + BIND1RC(uint32_t,texture_get_width,RID) + BIND1RC(uint32_t,texture_get_height,RID) + BIND3(texture_set_size_override,RID,int,int) + BIND2RC(RID,texture_create_radiance_cubemap,RID,int) - /* FIXED MATERIAL */ - virtual RID fixed_material_create(); + BIND2(texture_set_path,RID,const String&) + BIND1RC(String,texture_get_path,RID) + BIND1(texture_set_shrink_all_x2_on_set_data,bool) + BIND1(texture_debug_usage,List<TextureInfo>*) - virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const; + BIND1(textures_keep_original,bool) - virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const; + /* SKYBOX API */ - virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const; + BIND0R(RID,skybox_create) + BIND3(skybox_set_texture,RID,RID,int) - virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode); - virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const; + /* SHADER API */ + BIND1R(RID,shader_create,ShaderMode) - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); - virtual Transform fixed_material_get_uv_transform(RID p_material) const; - virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader); - virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const; + BIND2(shader_set_mode,RID,ShaderMode) + BIND1RC(ShaderMode,shader_get_mode,RID) - virtual void fixed_material_set_point_size(RID p_material,float p_size); - virtual float fixed_material_get_point_size(RID p_material) const; + BIND2(shader_set_code,RID,const String&) + BIND1RC(String,shader_get_code,RID) - /* SURFACE API */ - virtual RID mesh_create(); + BIND2C(shader_get_param_list,RID, List<PropertyInfo> *) - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; + BIND3(shader_set_default_texture_param,RID,const StringName&,RID) + BIND2RC(RID,shader_get_default_texture_param,RID,const StringName&) - virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode); - virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); //this is used by each platform in a different way + /* COMMON MATERIAL API */ - virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; + BIND0R(RID,material_create) - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; + BIND2(material_set_shader,RID,RID) + BIND1RC(RID,material_get_shader,RID) - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + BIND3(material_set_param,RID, const StringName&, const Variant& ) + BIND2RC(Variant,material_get_param,RID, const StringName& ) - virtual void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; + BIND2(material_set_line_width,RID, float ) - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - virtual void mesh_clear(RID p_mesh); - /* MULTIMESH API */ + /* MESH API */ - virtual RID multimesh_create(); - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; + BIND0R(RID,mesh_create) - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); + BIND10(mesh_add_surface,RID,uint32_t,PrimitiveType,const DVector<uint8_t>&,int ,const DVector<uint8_t>& ,int ,const AABB&,const Vector<DVector<uint8_t> >&,const Vector<AABB>& ) - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const; - virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; + BIND2(mesh_set_morph_target_count,RID,int) + BIND1RC(int,mesh_get_morph_target_count,RID) - virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - /* IMMEDIATE API */ + BIND2(mesh_set_morph_target_mode,RID,MorphTargetMode) + BIND1RC(MorphTargetMode, mesh_get_morph_target_mode,RID ) - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); - virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); - virtual void immediate_color(RID p_immediate,const Color& p_color); - virtual void immediate_uv(RID p_immediate, const Vector2& p_uv); - virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; + BIND3(mesh_surface_set_material,RID, int , RID ) + BIND2RC(RID,mesh_surface_get_material,RID, int ) + BIND2RC(int,mesh_surface_get_array_len,RID,int) + BIND2RC(int,mesh_surface_get_array_index_len,RID,int) - /* PARTICLES API */ + BIND2RC(DVector<uint8_t>,mesh_surface_get_array,RID,int) + BIND2RC(DVector<uint8_t>,mesh_surface_get_index_array,RID, int) - virtual RID particles_create(); + BIND2RC(uint32_t,mesh_surface_get_format,RID,int) + BIND2RC(PrimitiveType,mesh_surface_get_primitive_type,RID,int) - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; + BIND2RC(AABB,mesh_surface_get_aabb,RID,int) + BIND2RC(Vector<DVector<uint8_t> >,mesh_surface_get_blend_shapes,RID,int) + BIND2RC(Vector<AABB>,mesh_surface_get_skeleton_aabb,RID,int) - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; + BIND2(mesh_remove_surface,RID,int) + BIND1RC(int,mesh_get_surface_count,RID) - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; + BIND2(mesh_set_custom_aabb,RID,const AABB&) + BIND1RC(AABB,mesh_get_custom_aabb,RID) - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; + BIND1(mesh_clear,RID) - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; + /* MULTIMESH API */ - virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const; - virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const; + BIND0R(RID,multimesh_create) - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; + BIND4(multimesh_allocate,RID,int,MultimeshTransformFormat,MultimeshColorFormat) + BIND1RC(int,multimesh_get_instance_count,RID) - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; + BIND2(multimesh_set_mesh,RID,RID) + BIND3(multimesh_instance_set_transform,RID,int,const Transform&) + BIND3(multimesh_instance_set_transform_2d,RID,int,const Matrix32& ) + BIND3(multimesh_instance_set_color,RID,int,const Color&) - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; + BIND1RC(RID,multimesh_get_mesh,RID) + BIND1RC(AABB,multimesh_get_aabb,RID) - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; + BIND2RC(Transform,multimesh_instance_get_transform,RID,int ) + BIND2RC(Matrix32,multimesh_instance_get_transform_2d,RID,int) + BIND2RC(Color,multimesh_instance_get_color,RID,int) - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; + BIND2(multimesh_set_visible_instances,RID,int) + BIND1RC(int,multimesh_get_visible_instances,RID) - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; + /* IMMEDIATE API */ - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; + BIND0R(RID,immediate_create) + BIND3(immediate_begin,RID,PrimitiveType,RID) + BIND2(immediate_vertex,RID,const Vector3&) + BIND2(immediate_normal,RID,const Vector3&) + BIND2(immediate_tangent,RID,const Plane&) + BIND2(immediate_color,RID,const Color&) + BIND2(immediate_uv,RID,const Vector2& ) + BIND2(immediate_uv2,RID,const Vector2&) + BIND1(immediate_end,RID) + BIND1(immediate_clear,RID) + BIND2(immediate_set_material,RID ,RID ) + BIND1RC(RID,immediate_get_material,RID) - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; + /* SKELETON API */ + BIND0R(RID,skeleton_create) + BIND3(skeleton_allocate,RID,int,bool) + BIND1RC(int,skeleton_get_bone_count,RID) + BIND3(skeleton_bone_set_transform,RID,int,const Transform&) + BIND2RC(Transform,skeleton_bone_get_transform,RID,int) + BIND3(skeleton_bone_set_transform_2d,RID,int, const Matrix32& ) + BIND2RC(Matrix32,skeleton_bone_get_transform_2d,RID,int) /* Light API */ - virtual RID light_create(LightType p_type); - virtual LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,LightColor p_type) const; - + BIND1R(RID,light_create,LightType) - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; + BIND2(light_set_color,RID,const Color&) + BIND3(light_set_param,RID ,LightParam ,float ) + BIND2(light_set_shadow,RID ,bool ) + BIND2(light_set_shadow_color,RID ,const Color& ) + BIND2(light_set_projector,RID,RID ) + BIND2(light_set_negative,RID,bool ) + BIND2(light_set_cull_mask,RID ,uint32_t ) - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; + BIND2(light_omni_set_shadow_mode,RID,LightOmniShadowMode) + BIND2(light_omni_set_shadow_detail,RID,LightOmniShadowDetail) - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; + BIND2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode) + BIND2(light_directional_set_blend_splits,RID,bool) - virtual void light_set_param(RID p_light, LightParam p_var, float p_value); - virtual float light_get_param(RID p_light, LightParam p_var) const; + /* PROBE API */ - virtual void light_set_operator(RID p_light,LightOp p_op); - virtual LightOp light_get_operator(RID p_light) const; + BIND0R(RID,reflection_probe_create) - virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode); - virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode); - virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const; - - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); + BIND2(reflection_probe_set_update_mode,RID, ReflectionProbeUpdateMode ) + BIND2(reflection_probe_set_intensity,RID, float ) + BIND2(reflection_probe_set_interior_ambient,RID, const Color& ) + BIND2(reflection_probe_set_interior_ambient_energy,RID, float ) + BIND2(reflection_probe_set_interior_ambient_probe_contribution,RID, float ) + BIND2(reflection_probe_set_max_distance,RID, float ) + BIND2(reflection_probe_set_extents,RID, const Vector3& ) + BIND2(reflection_probe_set_origin_offset,RID, const Vector3& ) + BIND2(reflection_probe_set_as_interior,RID, bool ) + BIND2(reflection_probe_set_enable_box_projection,RID, bool ) + BIND2(reflection_probe_set_enable_shadows,RID, bool ) + BIND2(reflection_probe_set_cull_mask,RID, uint32_t ) /* ROOM API */ - virtual RID room_create(); - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds); - virtual BSP_Tree room_get_bounds(RID p_room) const; + BIND0R(RID,room_create) + BIND4(room_add_bounds,RID, const DVector<Vector2>& ,float ,const Transform& ) + BIND1(room_clear_bounds,RID) /* PORTAL API */ - virtual RID portal_create(); - virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape); - virtual Vector<Point2> portal_get_shape(RID p_portal) const; - virtual void portal_set_enabled(RID p_portal, bool p_enabled); - virtual bool portal_is_enabled(RID p_portal) const; - virtual void portal_set_disable_distance(RID p_portal, float p_distance); - virtual float portal_get_disable_distance(RID p_portal) const; - virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); - virtual Color portal_get_disabled_color(RID p_portal) const; - virtual void portal_set_connect_range(RID p_portal, float p_range); - virtual float portal_get_connect_range(RID p_portal) const; - - /* BAKED LIGHT */ + // portals are only (x/y) points, forming a convex shape, which its clockwise + // order points outside. (z is 0); - virtual RID baked_light_create(); + BIND0R(RID,portal_create) + BIND2(portal_set_shape,RID , const Vector<Point2>& ) + BIND2(portal_set_enabled,RID , bool ) + BIND2(portal_set_disable_distance,RID , float ) + BIND2(portal_set_disabled_color,RID , const Color& ) - virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode); - virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const; + /* BAKED LIGHT API */ - virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree); - virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const; + BIND0R(RID, gi_probe_create) - virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light); - virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const; + BIND2(gi_probe_set_bounds,RID,const AABB&) + BIND1RC(AABB,gi_probe_get_bounds,RID) - virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler); - virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const; + BIND2(gi_probe_set_cell_size,RID,float) + BIND1RC(float,gi_probe_get_cell_size,RID) - virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); - virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; + BIND2(gi_probe_set_to_cell_xform,RID,const Transform&) + BIND1RC(Transform,gi_probe_get_to_cell_xform,RID) - virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); - virtual void baked_light_clear_lightmaps(RID p_baked_light); + BIND2(gi_probe_set_dynamic_range,RID,int) + BIND1RC(int,gi_probe_get_dynamic_range,RID) - virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled); - virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const; + BIND2(gi_probe_set_energy,RID,float) + BIND1RC(float,gi_probe_get_energy,RID) - virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color); - virtual Color baked_light_get_realtime_color(RID p_baked_light) const; + BIND2(gi_probe_set_interior,RID,bool) + BIND1RC(bool,gi_probe_is_interior,RID) - virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy); - virtual float baked_light_get_realtime_energy(RID p_baked_light) const; + BIND2(gi_probe_set_compress,RID,bool) + BIND1RC(bool,gi_probe_is_compressed,RID) - /* BAKED LIGHT SAMPLER */ + BIND2(gi_probe_set_dynamic_data,RID,const DVector<int>& ) + BIND1RC( DVector<int>,gi_probe_get_dynamic_data,RID) - virtual RID baked_light_sampler_create(); + /* PARTICLES */ - virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); - virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + BIND0R(RID, particles_create) - virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); - virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + BIND2(particles_set_emitting,RID,bool) + BIND2(particles_set_amount,RID,int ) + BIND2(particles_set_lifetime,RID,float ) + BIND2(particles_set_pre_process_time,RID,float ) + BIND2(particles_set_explosiveness_ratio,RID,float ) + BIND2(particles_set_randomness_ratio,RID,float ) + BIND2(particles_set_custom_aabb,RID,const AABB& ) + BIND2(particles_set_gravity,RID,const Vector3& ) + BIND2(particles_set_use_local_coordinates,RID,bool ) + BIND2(particles_set_process_material,RID,RID ) - /* CAMERA API */ + BIND2(particles_set_emission_shape,RID,VS::ParticlesEmissionShape ) + BIND2(particles_set_emission_sphere_radius,RID,float ) + BIND2(particles_set_emission_box_extents,RID,const Vector3& ) + BIND2(particles_set_emission_points,RID,const DVector<Vector3>& ) - virtual RID camera_create(); - virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far); - virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far); - virtual void camera_set_transform(RID p_camera,const Transform& p_transform); - virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers); - virtual uint32_t camera_get_visible_layers(RID p_camera) const; + BIND2(particles_set_draw_order,RID,VS::ParticlesDrawOrder ) - virtual void camera_set_environment(RID p_camera,RID p_env); - virtual RID camera_get_environment(RID p_camera) const; + BIND2(particles_set_draw_passes,RID,int ) + BIND3(particles_set_draw_pass_material,RID,int , RID ) + BIND3(particles_set_draw_pass_mesh,RID,int , RID ) - virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable); - virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const; + BIND1R(AABB,particles_get_current_aabb,RID); - /* VIEWPORT API */ - virtual RID viewport_create(); +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::scene - virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0); - virtual void viewport_detach(RID p_viewport); + /* CAMERA API */ - virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable); - virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode); - virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const; - virtual RID viewport_get_render_target_texture(RID p_viewport) const; - virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable); - virtual bool viewport_get_render_target_vflip(RID p_viewport) const; - virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable); - virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const; - virtual void viewport_render_target_clear(RID p_viewport); - virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect); + BIND0R(RID, camera_create) + BIND4(camera_set_perspective,RID,float, float , float ) + BIND4(camera_set_orthogonal,RID,float , float , float ) + BIND2(camera_set_transform,RID,const Transform&) + BIND2(camera_set_cull_mask,RID,uint32_t ) + BIND2(camera_set_environment,RID ,RID ) + BIND2(camera_set_use_vertical_aspect,RID,bool) - virtual void viewport_queue_screen_capture(RID p_viewport); - virtual Image viewport_get_screen_capture(RID p_viewport) const; +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::viewport - virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect); - virtual ViewportRect viewport_get_rect(RID p_viewport) const; + /* VIEWPORT TARGET API */ - virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide); - virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide); - virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable); - virtual void viewport_attach_camera(RID p_viewport,RID p_camera); - virtual void viewport_set_scenario(RID p_viewport,RID p_scenario); + BIND0R(RID,viewport_create) - virtual RID viewport_get_attached_camera(RID p_viewport) const; - virtual RID viewport_get_scenario(RID p_viewport) const; - virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas); - virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas); - virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset); - virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const; - virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform); - virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const; - virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer); - virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled); - virtual bool viewport_has_transparent_background(RID p_viewport) const; + BIND3(viewport_set_size,RID,int ,int ) + BIND2(viewport_set_active,RID ,bool ) + BIND2(viewport_set_parent_viewport,RID,RID) - /* ENVIRONMENT API */ + BIND2(viewport_set_clear_mode,RID,ViewportClearMode ) - virtual RID environment_create(); + BIND3(viewport_attach_to_screen,RID ,const Rect2& ,int ) + BIND1(viewport_detach,RID) - virtual void environment_set_background(RID p_env,EnvironmentBG p_bg); - virtual EnvironmentBG environment_get_background(RID p_env) const; + BIND2(viewport_set_update_mode,RID,ViewportUpdateMode ) + BIND2(viewport_set_vflip,RID,bool) - virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const; - virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_effect) const; + BIND1RC(RID,viewport_get_texture,RID ) + BIND2(viewport_set_hide_scenario,RID,bool ) + BIND2(viewport_set_hide_canvas,RID,bool ) + BIND2(viewport_set_disable_environment,RID,bool ) + BIND2(viewport_set_disable_3d,RID,bool ) - virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param); - virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const; + BIND2(viewport_attach_camera,RID,RID ) + BIND2(viewport_set_scenario,RID,RID ) + BIND2(viewport_attach_canvas,RID,RID ) + BIND2(viewport_remove_canvas,RID,RID ) + BIND3(viewport_set_canvas_transform,RID ,RID ,const Matrix32& ) + BIND2(viewport_set_transparent_background,RID ,bool ) - /* SCENARIO API */ + BIND2(viewport_set_global_canvas_transform,RID,const Matrix32& ) + BIND3(viewport_set_canvas_layer,RID ,RID ,int ) + BIND2(viewport_set_shadow_atlas_size,RID ,int ) + BIND3(viewport_set_shadow_atlas_quadrant_subdivision,RID ,int, int ) + BIND2(viewport_set_msaa,RID ,ViewportMSAA ) + BIND2(viewport_set_hdr,RID ,bool ) - virtual RID scenario_create(); - - virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode); - virtual void scenario_set_environment(RID p_scenario, RID p_environment); - virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const; - virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + /* ENVIRONMENT API */ +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::scene_render - /* INSTANCING API */ + BIND0R(RID,environment_create) - virtual RID instance_create(); + BIND2(environment_set_background,RID ,EnvironmentBG ) + BIND2(environment_set_skybox,RID,RID ) + BIND2(environment_set_skybox_scale,RID,float) + BIND2(environment_set_bg_color,RID,const Color& ) + BIND2(environment_set_bg_energy,RID,float ) + BIND2(environment_set_canvas_max_layer,RID,int ) + BIND4(environment_set_ambient_light,RID,const Color& ,float,float ) + BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool ) + BIND10(environment_set_ssao,RID ,bool , float , float , float,float,float , float ,const Color &,bool ) - virtual void instance_set_base(RID p_instance, RID p_base); - virtual RID instance_get_base(RID p_instance) const; - virtual void instance_set_scenario(RID p_instance, RID p_scenario); - virtual RID instance_get_scenario(RID p_instance) const; - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); - virtual uint32_t instance_get_layer_mask(RID p_instance) const; + BIND6(environment_set_dof_blur_near,RID,bool ,float,float,float,EnvironmentDOFBlurQuality) + BIND6(environment_set_dof_blur_far,RID,bool ,float,float,float,EnvironmentDOFBlurQuality) + BIND10(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode,float,float,bool ) + BIND5(environment_set_fog,RID,bool ,float ,float ,RID ) - virtual AABB instance_get_base_aabb(RID p_instance) const; + BIND9(environment_set_tonemap,RID,EnvironmentToneMapper, float ,float ,bool, float ,float ,float,float ) - virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID); - virtual uint32_t instance_get_object_instance_ID(RID p_instance) const; + BIND6(environment_set_adjustment,RID,bool ,float ,float ,float ,RID ) - virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton); - virtual RID instance_get_skeleton(RID p_instance) const; - virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight); - virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const; + /* SCENARIO API */ - virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material); +#undef BINDBASE +#define BINDBASE VSG::scene - virtual void instance_set_transform(RID p_instance, const Transform& p_transform); - virtual Transform instance_get_transform(RID p_instance) const; + BIND0R(RID,scenario_create) - virtual void instance_set_exterior( RID p_instance, bool p_enabled ); - virtual bool instance_is_exterior( RID p_instance) const; + BIND2(scenario_set_debug,RID,ScenarioDebugMode ) + BIND2(scenario_set_environment,RID, RID ) + BIND3(scenario_set_reflection_atlas_size,RID, int,int ) + BIND2(scenario_set_fallback_environment,RID, RID ) - virtual void instance_set_room( RID p_instance, RID p_room ); - virtual RID instance_get_room( RID p_instance ) const ; - virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ); - virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const; + /* INSTANCING API */ + // from can be mesh, light, area and portal so far. + BIND0R(RID,instance_create) - virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const; - virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const; - virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const; + BIND2(instance_set_base,RID, RID ) // from can be mesh, light, poly, area and portal so far. + BIND2(instance_set_scenario,RID, RID ) // from can be mesh, light, poly, area and portal so far. + BIND2(instance_set_layer_mask,RID, uint32_t ) + BIND2(instance_set_transform,RID, const Transform& ) + BIND2(instance_attach_object_instance_ID,RID,ObjectID ) + BIND3(instance_set_morph_target_weight,RID,int , float ) + BIND3(instance_set_surface_material,RID,int , RID ) - virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled); - virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const; + BIND2(instance_attach_skeleton,RID,RID ) + BIND2(instance_set_exterior, RID, bool ) + BIND2(instance_set_room, RID, RID ) - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting); - virtual VS::ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const; + BIND2(instance_set_extra_visibility_margin, RID, real_t ) - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); - virtual RID instance_geometry_get_material_override(RID p_instance) const; + // don't use these in a game! + BIND2RC(Vector<ObjectID>,instances_cull_aabb,const AABB& , RID) + BIND3RC(Vector<ObjectID>,instances_cull_ray,const Vector3& , const Vector3& , RID ) + BIND2RC(Vector<ObjectID>,instances_cull_convex,const Vector<Plane>& , RID) - virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max); - virtual float instance_geometry_get_draw_range_max(RID p_instance) const; - virtual float instance_geometry_get_draw_range_min(RID p_instance) const; - virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); - virtual RID instance_geometry_get_baked_light(RID p_instance) const; + BIND3(instance_geometry_set_flag,RID,InstanceFlags ,bool ) + BIND2(instance_geometry_set_cast_shadows_setting,RID, ShadowCastingSetting ) + BIND2(instance_geometry_set_material_override,RID, RID ) - virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); - virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; - virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); - virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; + BIND5(instance_geometry_set_draw_range,RID,float ,float ,float ,float ) + BIND2(instance_geometry_set_as_instance_lod,RID,RID ) - virtual void instance_light_set_enabled(RID p_instance,bool p_enabled); - virtual bool instance_light_is_enabled(RID p_instance) const; +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::canvas /* CANVAS (2D) */ - virtual RID canvas_create(); - virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring); - virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const; - virtual void canvas_set_modulate(RID p_canvas,const Color& p_color); - - - virtual RID canvas_item_create(); + BIND0R(RID,canvas_create) + BIND3(canvas_set_item_mirroring,RID ,RID ,const Point2& ) + BIND2(canvas_set_modulate,RID,const Color&) - virtual void canvas_item_set_parent(RID p_item,RID p_parent_item); - virtual RID canvas_item_get_parent(RID p_canvas_item) const; - virtual void canvas_item_set_visible(RID p_item,bool p_visible); - virtual bool canvas_item_is_visible(RID p_item) const; + BIND0R(RID,canvas_item_create) + BIND2(canvas_item_set_parent,RID ,RID) - virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend); - virtual void canvas_item_set_light_mask(RID p_canvas_item,int p_mask); + BIND2(canvas_item_set_visible,RID,bool ) + BIND2(canvas_item_set_light_mask,RID,int ) + BIND2(canvas_item_set_transform,RID, const Matrix32& ) + BIND2(canvas_item_set_clip,RID, bool ) + BIND2(canvas_item_set_distance_field_mode,RID, bool ) + BIND3(canvas_item_set_custom_rect,RID, bool ,const Rect2& ) + BIND2(canvas_item_set_modulate,RID, const Color& ) + BIND2(canvas_item_set_self_modulate,RID, const Color& ) + BIND2(canvas_item_set_draw_behind_parent,RID, bool ) - //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect); - virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform); - virtual void canvas_item_set_clip(RID p_item, bool p_clip); - virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); - virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); - virtual void canvas_item_set_opacity(RID p_item, float p_opacity); - virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const; - virtual void canvas_item_set_on_top(RID p_item, bool p_on_top); - virtual bool canvas_item_is_on_top(RID p_item) const; - virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity); - virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const; + BIND6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float ,bool ) + BIND3(canvas_item_add_rect,RID, const Rect2& , const Color& ) + BIND4(canvas_item_add_circle,RID, const Point2& , float ,const Color& ) + BIND6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color& ,bool ) + BIND6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color& ,bool ) + BIND10(canvas_item_add_nine_patch,RID, const Rect2& , const Rect2& , RID ,const Vector2& , const Vector2& ,NinePatchAxisMode , NinePatchAxisMode,bool ,const Color& ) + BIND6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float ) + BIND5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ) + BIND7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int) + BIND3(canvas_item_add_mesh,RID, const RID& ,RID ) + BIND3(canvas_item_add_multimesh,RID, RID ,RID ) + BIND2(canvas_item_add_set_transform,RID,const Matrix32& ) + BIND2(canvas_item_add_clip_ignore,RID, bool ) + BIND2(canvas_item_set_sort_children_by_y,RID, bool ) + BIND2(canvas_item_set_z,RID, int ) + BIND2(canvas_item_set_z_as_relative_to_parent,RID, bool ) + BIND3(canvas_item_set_copy_to_backbuffer,RID, bool ,const Rect2& ) - virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport); + BIND1(canvas_item_clear,RID ) + BIND2(canvas_item_set_draw_index,RID,int) - virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width=1.0, bool p_antialiased=false); - virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color); - virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color); - virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); - virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0); - virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID()); - virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1); - virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID()); - virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform); - virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend); - virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); - virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); - virtual void canvas_item_set_z(RID p_item, int p_z); - virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); - virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect); + BIND2(canvas_item_set_material,RID, RID ) - virtual void canvas_item_set_material(RID p_item, RID p_material); - virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + BIND2(canvas_item_set_use_parent_material,RID, bool ) - virtual RID canvas_light_create(); - virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); - virtual void canvas_light_set_enabled(RID p_light, bool p_enabled); - virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform); - virtual void canvas_light_set_scale(RID p_light, float p_scale); - virtual void canvas_light_set_texture(RID p_light, RID p_texture); - virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); - virtual void canvas_light_set_color(RID p_light, const Color& p_color); - virtual void canvas_light_set_height(RID p_light, float p_height); - virtual void canvas_light_set_energy(RID p_light, float p_energy); - virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); - virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); - virtual void canvas_light_set_item_mask(RID p_light, int p_mask); - virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask); - virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode); - virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); - virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); - virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier); - virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color); + BIND0R(RID,canvas_light_create) + BIND2(canvas_light_attach_to_canvas,RID,RID ) + BIND2(canvas_light_set_enabled,RID, bool ) + BIND2(canvas_light_set_scale,RID, float ) + BIND2(canvas_light_set_transform,RID, const Matrix32& ) + BIND2(canvas_light_set_texture,RID, RID ) + BIND2(canvas_light_set_texture_offset,RID, const Vector2& ) + BIND2(canvas_light_set_color,RID, const Color& ) + BIND2(canvas_light_set_height,RID, float ) + BIND2(canvas_light_set_energy,RID, float ) + BIND3(canvas_light_set_z_range,RID, int ,int ) + BIND3(canvas_light_set_layer_range,RID, int ,int ) + BIND2(canvas_light_set_item_cull_mask,RID, int ) + BIND2(canvas_light_set_item_shadow_cull_mask,RID, int ) + BIND2(canvas_light_set_mode,RID, CanvasLightMode ) + BIND2(canvas_light_set_shadow_enabled,RID, bool ) + BIND2(canvas_light_set_shadow_buffer_size,RID, int ) + BIND2(canvas_light_set_shadow_gradient_length,RID, float ) + BIND2(canvas_light_set_shadow_filter,RID, CanvasLightShadowFilter ) + BIND2(canvas_light_set_shadow_color,RID, const Color& ) - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas); - virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled); - virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon); - virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform); - virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask); - virtual RID canvas_occluder_polygon_create(); - virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close); - virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape); - virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode); + BIND0R(RID,canvas_light_occluder_create) + 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_transform,RID,const Matrix32& ) + BIND2(canvas_light_occluder_set_light_mask,RID,int ) + BIND0R(RID,canvas_occluder_polygon_create) + BIND3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>& ,bool) + BIND2(canvas_occluder_polygon_set_shape_as_lines,RID ,const DVector<Vector2>&) - virtual void canvas_item_clear(RID p_item); - virtual void canvas_item_raise(RID p_item); - - /* CANVAS ITEM MATERIAL */ - - virtual RID canvas_item_material_create(); - virtual void canvas_item_material_set_shader(RID p_material, RID p_shader); - virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const; - virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode); + BIND2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode) /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians - virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0, const Rect2 &p_region=Rect2()); + virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0, const Rect2 &p_region=Rect2()); virtual void cursor_set_visible(bool p_visible, int p_cursor = 0); virtual void cursor_set_pos(const Point2& p_pos, int p_cursor = 0); /* BLACK BARS */ + virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom); virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom); - /* FREE */ - - virtual void free( RID p_rid ); - /* CUSTOM SHADE MODEL */ + /* FREE */ - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; + virtual void free( RID p_rid ); ///< free RIDs associated with the visual server /* EVENT QUEUING */ virtual void draw(); virtual void sync(); - + virtual bool has_changed() const; virtual void init(); virtual void finish(); - virtual bool has_changed() const; + /* STATUS INFORMATION */ - /* RENDER INFO */ virtual int get_render_info(RenderInfo p_info); - virtual bool has_feature(Features p_feature) const; - RID get_test_cube(); + virtual RID get_test_cube(); - virtual void set_boot_image(const Image& p_image, const Color& p_color, bool p_scale); + + /* TESTING */ + + virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale); virtual void set_default_clear_color(const Color& p_color); - VisualServerRaster(Rasterizer *p_rasterizer); + virtual bool has_feature(Features p_feature) const; + + + VisualServerRaster(); ~VisualServerRaster(); +#undef DISPLAY_CHANGED + +#undef BIND0R +#undef BIND1RC +#undef BIND2RC +#undef BIND3RC +#undef BIND4RC + +#undef BIND1 +#undef BIND2 +#undef BIND3 +#undef BIND4 +#undef BIND5 +#undef BIND6 +#undef BIND7 +#undef BIND8 +#undef BIND9 +#undef BIND10 + }; #endif diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp new file mode 100644 index 0000000000..91694c3e12 --- /dev/null +++ b/servers/visual/visual_server_scene.cpp @@ -0,0 +1,3580 @@ +#include "visual_server_scene.h" +#include "visual_server_global.h" +#include "os/os.h" +/* CAMERA API */ + + + + + +RID VisualServerScene::camera_create() { + + Camera * camera = memnew( Camera ); + return camera_owner.make_rid( camera ); + +} + +void VisualServerScene::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->type=Camera::PERSPECTIVE; + camera->fov=p_fovy_degrees; + camera->znear=p_z_near; + camera->zfar=p_z_far; + +} + +void VisualServerScene::camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->type=Camera::ORTHOGONAL; + camera->size=p_size; + camera->znear=p_z_near; + camera->zfar=p_z_far; +} + +void VisualServerScene::camera_set_transform(RID p_camera,const Transform& p_transform) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->transform=p_transform.orthonormalized(); + + +} + +void VisualServerScene::camera_set_cull_mask(RID p_camera,uint32_t p_layers) { + + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + + camera->visible_layers=p_layers; + +} + +void VisualServerScene::camera_set_environment(RID p_camera,RID p_env) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->env=p_env; + +} + + +void VisualServerScene::camera_set_use_vertical_aspect(RID p_camera,bool p_enable) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->vaspect=p_enable; + +} + + +/* SCENARIO API */ + + + +void* VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int) { + +// VisualServerScene *self = (VisualServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A,B); //lesser always first + } + + if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceLightData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->lighting.push_back(B); + + List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo); + + if (geom->can_cast_shadows) { + + light->shadow_dirty=true; + } + geom->lighting_dirty=true; + + return E; //this element should make freeing faster + } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceReflectionProbeData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->reflection_probes.push_back(B); + + List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo); + + geom->reflection_dirty=true; + + return E; //this element should make freeing faster + } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceGIProbeData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->gi_probes.push_back(B); + + List<InstanceGIProbeData::PairInfo>::Element *E = gi_probe->geometries.push_back(pinfo); + + geom->gi_probes_dirty=true; + + return E; //this element should make freeing faster + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data); + + return gi_probe->lights.insert(A); + } + + + +#if 0 + if (A->base_type==INSTANCE_PORTAL) { + + ERR_FAIL_COND_V( B->base_type!=INSTANCE_PORTAL,NULL ); + + A->portal_info->candidate_set.insert(B); + B->portal_info->candidate_set.insert(A); + + self->_portal_attempt_connect(A); + //attempt to conncet portal A (will go through B anyway) + //this is a little hackish, but works fine in practice + + } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) { + + if (B->base_type==INSTANCE_GI_PROBE) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_GI_PROBE_SAMPLER,NULL); + B->gi_probe_sampler_info->gi_probes.insert(A); + + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { + + if (B->base_type==INSTANCE_ROOM) + SWAP(A,B); + + ERR_FAIL_COND_V(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK ),NULL); + + B->auto_rooms.insert(A); + A->room_info->owned_autoroom_geometry.insert(B); + + self->_instance_validate_autorooms(B); + + + } else { + + if (B->base_type==INSTANCE_LIGHT) { + + SWAP(A,B); + } else if (A->base_type!=INSTANCE_LIGHT) { + return NULL; + } + + + A->light_info->affected.insert(B); + B->lights.insert(A); + B->light_cache_dirty=true; + + + } +#endif + + return NULL; + +} +void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void* udata) { + +// VisualServerScene *self = (VisualServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A,B); //lesser always first + } + + + + if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element*>(udata); + + geom->lighting.erase(E->get().L); + light->geometries.erase(E); + + if (geom->can_cast_shadows) { + light->shadow_dirty=true; + } + geom->lighting_dirty=true; + + + } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element*>(udata); + + geom->reflection_probes.erase(E->get().L); + reflection_probe->geometries.erase(E); + + geom->reflection_dirty=true; + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element*>(udata); + + geom->gi_probes.erase(E->get().L); + gi_probe->geometries.erase(E); + + geom->gi_probes_dirty=true; + + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data); + + + Set<Instance*>::Element *E = reinterpret_cast<Set<Instance*>::Element*>(udata); + + gi_probe->lights.erase(E); + } +#if 0 + if (A->base_type==INSTANCE_PORTAL) { + + ERR_FAIL_COND( B->base_type!=INSTANCE_PORTAL ); + + + A->portal_info->candidate_set.erase(B); + B->portal_info->candidate_set.erase(A); + + //after disconnecting them, see if they can connect again + self->_portal_attempt_connect(A); + self->_portal_attempt_connect(B); + + } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) { + + if (B->base_type==INSTANCE_GI_PROBE) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_GI_PROBE_SAMPLER); + B->gi_probe_sampler_info->gi_probes.erase(A); + + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { + + if (B->base_type==INSTANCE_ROOM) + SWAP(A,B); + + ERR_FAIL_COND(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK )); + + B->auto_rooms.erase(A); + B->valid_auto_rooms.erase(A); + A->room_info->owned_autoroom_geometry.erase(B); + + }else { + + + + if (B->base_type==INSTANCE_LIGHT) { + + SWAP(A,B); + } else if (A->base_type!=INSTANCE_LIGHT) { + return; + } + + + A->light_info->affected.erase(B); + B->lights.erase(A); + B->light_cache_dirty=true; + + } +#endif +} + +RID VisualServerScene::scenario_create() { + + Scenario *scenario = memnew( Scenario ); + ERR_FAIL_COND_V(!scenario,RID()); + RID scenario_rid = scenario_owner.make_rid( scenario ); + scenario->self=scenario_rid; + + scenario->octree.set_pair_callback(_instance_pair,this); + scenario->octree.set_unpair_callback(_instance_unpair,this); + scenario->reflection_probe_shadow_atlas=VSG::scene_render->shadow_atlas_create(); + VSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas,1024); //make enough shadows for close distance, don't bother with rest + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,0,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,1,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,2,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,3,8); + scenario->reflection_atlas=VSG::scene_render->reflection_atlas_create(); + + return scenario_rid; +} + +void VisualServerScene::scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->debug=p_debug_mode; +} + +void VisualServerScene::scenario_set_environment(RID p_scenario, RID p_environment) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->environment=p_environment; + +} + +void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment=p_environment; + + +} + +void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas,p_size); + VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas,p_subdiv); + + +} + + + +/* INSTANCING API */ + +void VisualServerScene::_instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials) { + + if (p_update_aabb) + p_instance->update_aabb=true; + if (p_update_materials) + p_instance->update_materials=true; + + if (p_instance->update_item.in_list()) + return; + + _instance_update_list.add(&p_instance->update_item); + + +} + +// from can be mesh, light, area and portal so far. +RID VisualServerScene::instance_create(){ + + Instance *instance = memnew( Instance ); + ERR_FAIL_COND_V(!instance,RID()); + + RID instance_rid = instance_owner.make_rid(instance); + instance->self=instance_rid; + + + return instance_rid; + + +} + +void VisualServerScene::instance_set_base(RID p_instance, RID p_base){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + Scenario *scenario = instance->scenario; + + if (instance->base_type!=VS::INSTANCE_NONE) { + //free anything related to that base + + VSG::storage->instance_remove_dependency(instance->base,instance); + + if (scenario && instance->octree_id) { + scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id=0; + } + + switch(instance->base_type) { + case VS::INSTANCE_LIGHT: { + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (instance->scenario && light->D) { + instance->scenario->directional_lights.erase( light->D ); + light->D=NULL; + } + VSG::scene_render->free(light->instance); + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data); + VSG::scene_render->free(reflection_probe->instance); + if (reflection_probe->update_list.in_list()) { + reflection_probe_render_list.remove(&reflection_probe->update_list); + } + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + + while(gi_probe->dynamic.updating_stage==GI_UPDATE_STAGE_LIGHTING) { + //wait until bake is done if it's baking + OS::get_singleton()->delay_usec(1); + } + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + if (gi_probe->dynamic.probe_data.is_valid()) { + VSG::storage->free(gi_probe->dynamic.probe_data); + } + + VSG::scene_render->free(gi_probe->probe_instance); + + } break; + + } + + if (instance->base_data) { + memdelete( instance->base_data ); + instance->base_data=NULL; + } + + instance->morph_values.clear(); + + for(int i=0;i<instance->materials.size();i++) { + if (instance->materials[i].is_valid()) { + VSG::storage->material_remove_instance_owner(instance->materials[i],instance); + } + } + instance->materials.clear(); + +#if 0 + if (instance->light_info) { + + if (instance->scenario && instance->light_info->D) + instance->scenario->directional_lights.erase( instance->light_info->D ); + rasterizer->free(instance->light_info->instance); + memdelete(instance->light_info); + instance->light_info=NULL; + } + + + + if ( instance->room ) { + + instance_set_room(p_instance,RID()); + /* + if((1<<instance->base_type)&INSTANCE_GEOMETRY_MASK) + instance->room->room_info->owned_geometry_instances.erase(instance->RE); + else if (instance->base_type==INSTANCE_PORTAL) { + print_line("freeing portal, is it there? "+itos(instance->room->room_info->owned_portal_instances.(instance->RE))); + instance->room->room_info->owned_portal_instances.erase(instance->RE); + } else if (instance->base_type==INSTANCE_ROOM) + instance->room->room_info->owned_room_instances.erase(instance->RE); + else if (instance->base_type==INSTANCE_LIGHT) + instance->room->room_info->owned_light_instances.erase(instance->RE); + + instance->RE=NULL;*/ + } + + + + + + + if (instance->portal_info) { + + _portal_disconnect(instance,true); + memdelete(instance->portal_info); + instance->portal_info=NULL; + + } + + if (instance->gi_probe_info) { + + while(instance->gi_probe_info->owned_instances.size()) { + + Instance *owned=instance->gi_probe_info->owned_instances.front()->get(); + owned->gi_probe=NULL; + owned->data.gi_probe=NULL; + owned->data.gi_probe_octree_xform=NULL; + owned->BLE=NULL; + instance->gi_probe_info->owned_instances.pop_front(); + } + + memdelete(instance->gi_probe_info); + instance->gi_probe_info=NULL; + + } + + if (instance->scenario && instance->octree_id) { + instance->scenario->octree.erase( instance->octree_id ); + instance->octree_id=0; + } + + + if (instance->room_info) { + + for(List<Instance*>::Element *E=instance->room_info->owned_geometry_instances.front();E;E=E->next()) { + + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + for(List<Instance*>::Element *E=instance->room_info->owned_portal_instances.front();E;E=E->next()) { + + _portal_disconnect(E->get(),true); + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + + for(List<Instance*>::Element *E=instance->room_info->owned_room_instances.front();E;E=E->next()) { + + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + + if (instance->room_info->disconnected_child_portals.size()) { + ERR_PRINT("BUG: Disconnected portals remain!"); + } + memdelete(instance->room_info); + instance->room_info=NULL; + + } + + if (instance->particles_info) { + + rasterizer->free( instance->particles_info->instance ); + memdelete(instance->particles_info); + instance->particles_info=NULL; + + } + + if (instance->gi_probe_sampler_info) { + + while (instance->gi_probe_sampler_info->owned_instances.size()) { + + instance_geometry_set_gi_probe_sampler(instance->gi_probe_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->gi_probe_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->gi_probe_sampler_info->sampled_light); + } + memdelete( instance->gi_probe_sampler_info ); + instance->gi_probe_sampler_info=NULL; + } +#endif + + } + + + instance->base_type=VS::INSTANCE_NONE; + instance->base=RID(); + + + if (p_base.is_valid()) { + + instance->base_type=VSG::storage->get_base_type(p_base); + ERR_FAIL_COND(instance->base_type==VS::INSTANCE_NONE); + + switch(instance->base_type) { + case VS::INSTANCE_LIGHT: { + + InstanceLightData *light = memnew( InstanceLightData ); + + if (scenario && VSG::storage->light_get_type(p_base)==VS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + + light->instance = VSG::scene_render->light_instance_create(p_base); + + instance->base_data=light; + } break; + case VS::INSTANCE_MESH: + case VS::INSTANCE_MULTIMESH: + case VS::INSTANCE_IMMEDIATE: { + + InstanceGeometryData *geom = memnew( InstanceGeometryData ); + instance->base_data=geom; + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = memnew( InstanceReflectionProbeData ); + reflection_probe->owner=instance; + instance->base_data=reflection_probe; + + reflection_probe->instance=VSG::scene_render->reflection_probe_instance_create(p_base); + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = memnew( InstanceGIProbeData ); + instance->base_data=gi_probe; + gi_probe->owner=instance; + + if (scenario && !gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + gi_probe->probe_instance=VSG::scene_render->gi_probe_instance_create(); + + } break; + + } + + VSG::storage->instance_add_dependency(p_base,instance); + + instance->base=p_base; + + if (scenario) + _instance_queue_update(instance,true,true); + + +#if 0 + if (rasterizer->is_mesh(p_base)) { + instance->base_type=INSTANCE_MESH; + instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base)); + instance->data.materials.resize( rasterizer->mesh_get_surface_count(p_base)); + } else if (rasterizer->is_multimesh(p_base)) { + instance->base_type=INSTANCE_MULTIMESH; + } else if (rasterizer->is_immediate(p_base)) { + instance->base_type=INSTANCE_IMMEDIATE; + } else if (rasterizer->is_particles(p_base)) { + instance->base_type=INSTANCE_PARTICLES; + instance->particles_info=memnew( Instance::ParticlesInfo ); + instance->particles_info->instance = rasterizer->particles_instance_create( p_base ); + } else if (rasterizer->is_light(p_base)) { + + instance->base_type=INSTANCE_LIGHT; + instance->light_info = memnew( Instance::LightInfo ); + instance->light_info->instance = rasterizer->light_instance_create(p_base); + if (instance->scenario && rasterizer->light_get_type(p_base)==LIGHT_DIRECTIONAL) { + + instance->light_info->D = instance->scenario->directional_lights.push_back(instance->self); + } + + } else if (room_owner.owns(p_base)) { + instance->base_type=INSTANCE_ROOM; + instance->room_info = memnew( Instance::RoomInfo ); + instance->room_info->room=room_owner.get(p_base); + } else if (portal_owner.owns(p_base)) { + + instance->base_type=INSTANCE_PORTAL; + instance->portal_info = memnew(Instance::PortalInfo); + instance->portal_info->portal=portal_owner.get(p_base); + } else if (gi_probe_owner.owns(p_base)) { + + instance->base_type=INSTANCE_GI_PROBE; + instance->gi_probe_info=memnew(Instance::BakedLightInfo); + instance->gi_probe_info->gi_probe=gi_probe_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else if (gi_probe_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_GI_PROBE_SAMPLER; + instance->gi_probe_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->gi_probe_sampler_info->sampler=gi_probe_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + + } else { + ERR_EXPLAIN("Invalid base RID for instance!") + ERR_FAIL(); + } + + instance_dependency_map[ p_base ].insert( instance->self ); +#endif + + + } +} +void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->scenario) { + + instance->scenario->instances.remove( &instance->scenario_item ); + + if (instance->octree_id) { + instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id=0; + } + + + switch(instance->base_type) { + + case VS::INSTANCE_LIGHT: { + + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (light->D) { + instance->scenario->directional_lights.erase( light->D ); + light->D=NULL; + } + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data); + VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + } break; + + } + + instance->scenario=NULL; + } + + + if (p_scenario.is_valid()) { + + Scenario *scenario = scenario_owner.get( p_scenario ); + ERR_FAIL_COND(!scenario); + + instance->scenario=scenario; + + scenario->instances.add( &instance->scenario_item ); + + + switch(instance->base_type) { + + case VS::INSTANCE_LIGHT: { + + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (VSG::storage->light_get_type(instance->base)==VS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + } break; + } + + _instance_queue_update(instance,true,true); + } +} +void VisualServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask){ + + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + instance->layer_mask=p_mask; +} +void VisualServerScene::instance_set_transform(RID p_instance, const Transform& p_transform){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->transform==p_transform) + return; //must be checked to avoid worst evil + + instance->transform=p_transform; + _instance_queue_update(instance,true); +} +void VisualServerScene::instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + instance->object_ID=p_ID; + +} +void VisualServerScene::instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_shape,instance->morph_values.size()); + instance->morph_values[p_shape]=p_weight; +} + +void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surface, RID p_material){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_surface,instance->materials.size()); + + if (instance->materials[p_surface].is_valid()) { + VSG::storage->material_remove_instance_owner(instance->materials[p_surface],instance); + } + instance->materials[p_surface]=p_material; + instance->base_material_changed(); + + if (instance->materials[p_surface].is_valid()) { + VSG::storage->material_add_instance_owner(instance->materials[p_surface],instance); + } + + +} + +void VisualServerScene::instance_attach_skeleton(RID p_instance,RID p_skeleton){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->skeleton==p_skeleton) + return; + + if (instance->skeleton.is_valid()) { + VSG::storage->instance_remove_skeleton(p_skeleton,instance); + } + + instance->skeleton=p_skeleton; + + if (instance->skeleton.is_valid()) { + VSG::storage->instance_add_skeleton(p_skeleton,instance); + } + + _instance_queue_update(instance,true); +} + +void VisualServerScene::instance_set_exterior( RID p_instance, bool p_enabled ){ + +} +void VisualServerScene::instance_set_room( RID p_instance, RID p_room ){ + +} + +void VisualServerScene::instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ){ + +} + +Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB& p_aabb, RID p_scenario) const { + + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + culled=scenario->octree.cull_AABB(p_aabb,cull,1024); + + for (int i=0;i<culled;i++) { + + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; +} +Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario) const{ + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + culled=scenario->octree.cull_segment(p_from,p_to*10000,cull,1024); + + + for (int i=0;i<culled;i++) { + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; + +} +Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario) const{ + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + + + culled=scenario->octree.cull_convex(p_convex,cull,1024); + + for (int i=0;i<culled;i++) { + + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; + +} + +void VisualServerScene::instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + switch(p_flags) { + + case VS::INSTANCE_FLAG_VISIBLE: { + + instance->visible=p_enabled; + + } break; + case VS::INSTANCE_FLAG_BILLBOARD: { + + instance->billboard=p_enabled; + + } break; + case VS::INSTANCE_FLAG_BILLBOARD_FIX_Y: { + + instance->billboard_y=p_enabled; + + } break; + case VS::INSTANCE_FLAG_CAST_SHADOW: { + if (p_enabled == true) { + instance->cast_shadows = VS::SHADOW_CASTING_SETTING_ON; + } + else { + instance->cast_shadows = VS::SHADOW_CASTING_SETTING_OFF; + } + + instance->base_material_changed(); // to actually compute if shadows are visible or not + + } break; + case VS::INSTANCE_FLAG_DEPH_SCALE: { + + instance->depth_scale=p_enabled; + + } break; + case VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS: { + + instance->visible_in_all_rooms=p_enabled; + + } break; + + } +} +void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { + +} +void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->material_override.is_valid()) { + VSG::storage->material_remove_instance_owner(instance->material_override,instance); + } + instance->material_override=p_material; + instance->base_material_changed(); + + if (instance->material_override.is_valid()) { + VSG::storage->material_add_instance_owner(instance->material_override,instance); + } + +} + + +void VisualServerScene::instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin){ + +} +void VisualServerScene::instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance){ + +} + + +void VisualServerScene::_update_instance(Instance *p_instance) { + + p_instance->version++; + + if (p_instance->base_type == VS::INSTANCE_LIGHT) { + + InstanceLightData *light = static_cast<InstanceLightData*>(p_instance->base_data); + + VSG::scene_render->light_instance_set_transform( light->instance, p_instance->transform ); + light->shadow_dirty=true; + + } + + if (p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data); + + VSG::scene_render->reflection_probe_instance_set_transform( reflection_probe->instance, p_instance->transform ); + reflection_probe->reflection_dirty=true; + + } + + + if (p_instance->aabb.has_no_surface()) + return; + +#if 0 + if (p_instance->base_type == VS::INSTANCE_PARTICLES) { + + rasterizer->particles_instance_set_transform( p_instance->particles_info->instance, p_instance->data.transform ); + } + +#endif + if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data); + //make sure lights are updated if it casts shadow + + if (geom->can_cast_shadows) { + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data); + light->shadow_dirty=true; + } + } + + } +#if 0 + else if (p_instance->base_type == INSTANCE_ROOM) { + + p_instance->room_info->affine_inverse=p_instance->data.transform.affine_inverse(); + } else if (p_instance->base_type == INSTANCE_GI_PROBE) { + + Transform scale; + scale.basis.scale(p_instance->gi_probe_info->gi_probe->octree_aabb.size); + scale.origin=p_instance->gi_probe_info->gi_probe->octree_aabb.pos; + //print_line("scale: "+scale); + p_instance->gi_probe_info->affine_inverse=(p_instance->data.transform*scale).affine_inverse(); + } + + +#endif + + p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; + + AABB new_aabb; +#if 0 + if (p_instance->base_type==INSTANCE_PORTAL) { + + //portals need to be transformed in a special way, so they don't become too wide if they have scale.. + Transform portal_xform = p_instance->data.transform; + portal_xform.basis.set_axis(2,portal_xform.basis.get_axis(2).normalized()); + + p_instance->portal_info->plane_cache=Plane( p_instance->data.transform.origin, portal_xform.basis.get_axis(2)); + int point_count=p_instance->portal_info->portal->shape.size(); + p_instance->portal_info->transformed_point_cache.resize(point_count); + + AABB portal_aabb; + + for(int i=0;i<point_count;i++) { + + Point2 src = p_instance->portal_info->portal->shape[i]; + Vector3 point = portal_xform.xform(Vector3(src.x,src.y,0)); + p_instance->portal_info->transformed_point_cache[i]=point; + if (i==0) + portal_aabb.pos=point; + else + portal_aabb.expand_to(point); + } + + portal_aabb.grow_by(p_instance->portal_info->portal->connect_range); + + new_aabb = portal_aabb; + + } else { +#endif + new_aabb = p_instance->transform.xform(p_instance->aabb); +#if 0 + } +#endif + + + p_instance->transformed_aabb=new_aabb; + + if (!p_instance->scenario) { + + return; + } + + + + if (p_instance->octree_id==0) { + + uint32_t base_type = 1<<p_instance->base_type; + uint32_t pairable_mask=0; + bool pairable=false; + + if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type==VS::INSTANCE_REFLECTION_PROBE) { + + pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK:0; + pairable=true; + } + + if (p_instance->base_type == VS::INSTANCE_GI_PROBE) { + //lights and geometries + pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK|(1<<VS::INSTANCE_LIGHT):0; + pairable=true; + } + +#if 0 + + if (p_instance->base_type == VS::INSTANCE_PORTAL) { + + pairable_mask=(1<<INSTANCE_PORTAL); + pairable=true; + } + + if (p_instance->base_type == VS::INSTANCE_GI_PROBE_SAMPLER) { + + pairable_mask=(1<<INSTANCE_GI_PROBE); + pairable=true; + } + + + if (!p_instance->room && (1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + base_type|=VS::INSTANCE_ROOMLESS_MASK; + } + + if (p_instance->base_type == VS::INSTANCE_ROOM) { + + pairable_mask=INSTANCE_ROOMLESS_MASK; + pairable=true; + } +#endif + + // not inside octree + p_instance->octree_id = p_instance->scenario->octree.create(p_instance,new_aabb,0,pairable,base_type,pairable_mask); + + } else { + + // if (new_aabb==p_instance->data.transformed_aabb) + // return; + + p_instance->scenario->octree.move(p_instance->octree_id,new_aabb); + } +#if 0 + if (p_instance->base_type==INSTANCE_PORTAL) { + + _portal_attempt_connect(p_instance); + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { + + _instance_validate_autorooms(p_instance); + } + + if (p_instance->base_type == INSTANCE_ROOM) { + + for(Set<Instance*>::Element *E=p_instance->room_info->owned_autoroom_geometry.front();E;E=E->next()) + _instance_validate_autorooms(E->get()); + } +#endif + +} + +void VisualServerScene::_update_instance_aabb(Instance *p_instance) { + + AABB new_aabb; + + ERR_FAIL_COND(p_instance->base_type!=VS::INSTANCE_NONE && !p_instance->base.is_valid()); + + switch(p_instance->base_type) { + case VisualServer::INSTANCE_NONE: { + + // do nothing + } break; + case VisualServer::INSTANCE_MESH: { + + new_aabb = VSG::storage->mesh_get_aabb(p_instance->base,p_instance->skeleton); + + } break; + + case VisualServer::INSTANCE_MULTIMESH: { + + new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_IMMEDIATE: { + + new_aabb = VSG::storage->immediate_get_aabb(p_instance->base); + + + } break; +#if 0 + + case VisualServer::INSTANCE_PARTICLES: { + + new_aabb = rasterizer->particles_get_aabb(p_instance->base); + + + } break; +#endif + case VisualServer::INSTANCE_LIGHT: { + + new_aabb = VSG::storage->light_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_REFLECTION_PROBE: { + + new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_GI_PROBE: { + + new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base); + + } break; + +#if 0 + case VisualServer::INSTANCE_ROOM: { + + Room *room = room_owner.get( p_instance->base ); + ERR_FAIL_COND(!room); + new_aabb=room->bounds.get_aabb(); + + } break; + case VisualServer::INSTANCE_PORTAL: { + + Portal *portal = portal_owner.get( p_instance->base ); + ERR_FAIL_COND(!portal); + for (int i=0;i<portal->shape.size();i++) { + + Vector3 point( portal->shape[i].x, portal->shape[i].y, 0 ); + if (i==0) { + + new_aabb.pos=point; + new_aabb.size.z=0.01; // make it not flat for octree + } else { + + new_aabb.expand_to(point); + } + } + + } break; + case VisualServer::INSTANCE_GI_PROBE: { + + BakedLight *gi_probe = gi_probe_owner.get( p_instance->base ); + ERR_FAIL_COND(!gi_probe); + new_aabb=gi_probe->octree_aabb; + + } break; + case VisualServer::INSTANCE_GI_PROBE_SAMPLER: { + + BakedLightSampler *gi_probe_sampler = gi_probe_sampler_owner.get( p_instance->base ); + ERR_FAIL_COND(!gi_probe_sampler); + float radius = gi_probe_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; +#endif + default: {} + } + + if (p_instance->extra_margin) + new_aabb.grow_by(p_instance->extra_margin); + + p_instance->aabb=new_aabb; + +} + + + + + +void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario) { + + + InstanceLightData * light = static_cast<InstanceLightData*>(p_instance->base_data); + + switch(VSG::storage->light_get_type(p_instance->base)) { + + case VS::LIGHT_DIRECTIONAL: { + + float max_distance =p_cam_projection.get_z_far(); + float shadow_max = VSG::storage->light_get_param(p_instance->base,VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); + if (shadow_max>0) { + max_distance=MIN(shadow_max,max_distance); + } + max_distance=MAX(max_distance,p_cam_projection.get_z_near()+0.001); + + float range = max_distance-p_cam_projection.get_z_near(); + + int splits=0; + switch(VSG::storage->light_directional_get_shadow_mode(p_instance->base)) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits=1; break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits=2; break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits=4; break; + } + + float distances[5]; + + distances[0]=p_cam_projection.get_z_near(); + for(int i=0;i<splits;i++) { + distances[i+1]=p_cam_projection.get_z_near()+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range; + }; + + distances[splits]=max_distance; + + float texture_size=VSG::scene_render->get_directional_light_shadow_size(light->instance); + + bool overlap = VSG::storage->light_directional_get_blend_splits(p_instance->base); + + for (int i=0;i<splits;i++) { + + // setup a camera matrix for that range! + CameraMatrix camera_matrix; + + float aspect = p_cam_projection.get_aspect(); + + + if (p_cam_orthogonal) { + + float w,h; + p_cam_projection.get_viewport_size(w,h); + camera_matrix.set_orthogonal(w,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false); + } else { + + float fov = p_cam_projection.get_fov(); + camera_matrix.set_perspective(fov,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false); + } + + //obtain the frustum endpoints + + Vector3 endpoints[8]; // frustum plane endpoints + bool res = camera_matrix.get_endpoints(p_cam_transform,endpoints); + ERR_CONTINUE(!res); + + // obtain the light frustm ranges (given endpoints) + + Vector3 x_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_X ).normalized(); + Vector3 y_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Y ).normalized(); + Vector3 z_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Z ).normalized(); + //z_vec points agsint the camera, like in default opengl + + float x_min,x_max; + float y_min,y_max; + float z_min,z_max; + + float x_min_cam,x_max_cam; + float y_min_cam,y_max_cam; + float z_min_cam,z_max_cam; + + + //used for culling + for(int j=0;j<8;j++) { + + float d_x=x_vec.dot(endpoints[j]); + float d_y=y_vec.dot(endpoints[j]); + float d_z=z_vec.dot(endpoints[j]); + + if (j==0 || d_x<x_min) + x_min=d_x; + if (j==0 || d_x>x_max) + x_max=d_x; + + if (j==0 || d_y<y_min) + y_min=d_y; + if (j==0 || d_y>y_max) + y_max=d_y; + + if (j==0 || d_z<z_min) + z_min=d_z; + if (j==0 || d_z>z_max) + z_max=d_z; + + + } + + + + + + { + //camera viewport stuff + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + + Vector3 center; + + for(int j=0;j<8;j++) { + + center+=endpoints[j]; + } + center/=8.0; + + //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; + + float radius=0; + + for(int j=0;j<8;j++) { + + float d = center.distance_to(endpoints[j]); + if (d>radius) + radius=d; + } + + + radius *= texture_size/(texture_size-2.0); //add a texel by each side, so stepified texture will always fit + + x_max_cam=x_vec.dot(center)+radius; + x_min_cam=x_vec.dot(center)-radius; + y_max_cam=y_vec.dot(center)+radius; + y_min_cam=y_vec.dot(center)-radius; + z_max_cam=z_vec.dot(center)+radius; + z_min_cam=z_vec.dot(center)-radius; + + float unit = radius*2.0/texture_size; + + x_max_cam=Math::stepify(x_max_cam,unit); + x_min_cam=Math::stepify(x_min_cam,unit); + y_max_cam=Math::stepify(y_max_cam,unit); + y_min_cam=Math::stepify(y_min_cam,unit); + + } + + //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree + + Vector<Plane> light_frustum_planes; + light_frustum_planes.resize(6); + + //right/left + light_frustum_planes[0]=Plane( x_vec, x_max ); + light_frustum_planes[1]=Plane( -x_vec, -x_min ); + //top/bottom + light_frustum_planes[2]=Plane( y_vec, y_max ); + light_frustum_planes[3]=Plane( -y_vec, -y_min ); + //near/far + light_frustum_planes[4]=Plane( z_vec, z_max+1e6 ); + light_frustum_planes[5]=Plane( -z_vec, -z_min ); // z_min is ok, since casters further than far-light plane are not needed + + int cull_count = p_scenario->octree.cull_convex(light_frustum_planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + // a pre pass will need to be needed to determine the actual z-near to be used + + + for (int j=0;j<cull_count;j++) { + + float min,max; + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + + instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max); + if (max>z_max) + z_max=max; + } + + { + CameraMatrix ortho_camera; + real_t half_x = (x_max_cam-x_min_cam) * 0.5; + real_t half_y = (y_max_cam-y_min_cam) * 0.5; + + + ortho_camera.set_orthogonal( -half_x, half_x,-half_y,half_y, 0, (z_max-z_min_cam) ); + + Transform ortho_transform; + ortho_transform.basis=p_instance->transform.basis; + ortho_transform.origin=x_vec*(x_min_cam+half_x)+y_vec*(y_min_cam+half_y)+z_vec*z_max; + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,ortho_camera,ortho_transform,0,distances[i+1],i); + } + + + + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + + } + + } break; + case VS::LIGHT_OMNI: { + + VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base); + + switch(shadow_mode) { + case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: { + + for(int i=0;i<2;i++) { + + //using this one ensures that raster deferred will have it + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + + float z =i==0?-1:1; + Vector<Plane> planes; + planes.resize(5); + planes[0]=p_instance->transform.xform(Plane(Vector3(0,0,z),radius)); + planes[1]=p_instance->transform.xform(Plane(Vector3(1,0,z).normalized(),radius)); + planes[2]=p_instance->transform.xform(Plane(Vector3(-1,0,z).normalized(),radius)); + planes[3]=p_instance->transform.xform(Plane(Vector3(0,1,z).normalized(),radius)); + planes[4]=p_instance->transform.xform(Plane(Vector3(0,-1,z).normalized(),radius)); + + + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,i); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + } + } break; + case VS::LIGHT_OMNI_SHADOW_CUBE: { + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + CameraMatrix cm; + cm.set_perspective(90,1,0.01,radius); + + for(int i=0;i<6;i++) { + + //using this one ensures that raster deferred will have it + + + + static const Vector3 view_normals[6]={ + Vector3(-1, 0, 0), + Vector3(+1, 0, 0), + Vector3( 0,-1, 0), + Vector3( 0,+1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1) + }; + static const Vector3 view_up[6]={ + Vector3( 0,-1, 0), + Vector3( 0,-1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1), + Vector3( 0,-1, 0), + Vector3( 0,-1, 0) + }; + + Transform xform = p_instance->transform * Transform().looking_at(view_normals[i],view_up[i]); + + + Vector<Plane> planes = cm.get_projection_planes(xform); + + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,xform,radius,0,i); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + } + + //restore the regular DP matrix + VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,0); + + } break; + } + + + } break; + case VS::LIGHT_SPOT: { + + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE); + + CameraMatrix cm; + cm.set_perspective( angle*2.0, 1.0, 0.01, radius ); + + + Vector<Plane> planes = cm.get_projection_planes(p_instance->transform); + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,p_instance->transform,radius,0,0); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,0,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + + } break; + } + +} + + +void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size,RID p_shadow_atlas) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* STEP 1 - SETUP CAMERA */ + CameraMatrix camera_matrix; + bool ortho=false; + + + switch(camera->type) { + case Camera::ORTHOGONAL: { + + camera_matrix.set_orthogonal( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect + + ); + ortho=true; + } break; + case Camera::PERSPECTIVE: { + + camera_matrix.set_perspective( + camera->fov, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect + + ); + ortho=false; + + } break; + } + + _render_scene(camera->transform,camera_matrix,ortho,camera->env,camera->visible_layers,p_scenario,p_shadow_atlas,RID(),-1); + +} + + +void VisualServerScene::_render_scene(const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_force_environment,uint32_t p_visible_layers, RID p_scenario,RID p_shadow_atlas,RID p_reflection_probe,int p_reflection_probe_pass) { + + + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + render_pass++; + uint32_t camera_layer_mask=p_visible_layers; + + VSG::scene_render->set_scene_pass(render_pass); + + +// rasterizer->set_camera(camera->transform, camera_matrix,ortho); + + Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); + + Plane near_plane(p_cam_transform.origin,-p_cam_transform.basis.get_axis(2).normalized()); + float z_far = p_cam_projection.get_z_far(); + + /* STEP 2 - CULL */ + int cull_count = scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); + light_cull_count=0; + + reflection_probe_cull_count=0; + +// light_samplers_culled=0; + +/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); + print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); +// print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); + print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); +*/ + + /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ + + + // compute portals +#if 0 + exterior_visited=false; + exterior_portal_cull_count=0; + + if (room_cull_enabled) { + for(int i=0;i<cull_count;i++) { + + Instance *ins = instance_cull_result[i]; + ins->last_render_pass=render_pass; + + if (ins->base_type!=INSTANCE_PORTAL) + continue; + + if (ins->room) + continue; + + ERR_CONTINUE(exterior_portal_cull_count>=MAX_EXTERIOR_PORTALS); + exterior_portal_cull_result[exterior_portal_cull_count++]=ins; + + } + + room_cull_count = p_scenario->octree.cull_point(camera->transform.origin,room_cull_result,MAX_ROOM_CULL,NULL,(1<<INSTANCE_ROOM)|(1<<INSTANCE_PORTAL)); + + + Set<Instance*> current_rooms; + Set<Instance*> portal_rooms; + //add to set + for(int i=0;i<room_cull_count;i++) { + + if (room_cull_result[i]->base_type==INSTANCE_ROOM) { + current_rooms.insert(room_cull_result[i]); + } + if (room_cull_result[i]->base_type==INSTANCE_PORTAL) { + //assume inside that room if also inside the portal.. + if (room_cull_result[i]->room) { + portal_rooms.insert(room_cull_result[i]->room); + } + + SWAP(room_cull_result[i],room_cull_result[room_cull_count-1]); + room_cull_count--; + i--; + } + } + + //remove from set if it has a parent room or BSP doesn't contain + for(int i=0;i<room_cull_count;i++) { + Instance *r = room_cull_result[i]; + + //check inside BSP + Vector3 room_local_point = r->room_info->affine_inverse.xform( camera->transform.origin ); + + if (!portal_rooms.has(r) && !r->room_info->room->bounds.point_is_inside(room_local_point)) { + + current_rooms.erase(r); + continue; + } + + //check parent + while (r->room) {// has parent room + + current_rooms.erase(r); + r=r->room; + } + + } + + if (current_rooms.size()) { + //camera is inside a room + // go through rooms + for(Set<Instance*>::Element *E=current_rooms.front();E;E=E->next()) { + _cull_room(camera,E->get()); + } + + } else { + //start from exterior + _cull_room(camera,NULL); + + } + } + +#endif + /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ + + for(int i=0;i<cull_count;i++) { + + Instance *ins = instance_cull_result[i]; + + bool keep=false; + + if ((camera_layer_mask&ins->layer_mask)==0) { + + //failure + } else if (ins->base_type==VS::INSTANCE_LIGHT && ins->visible) { + + + if (ins->visible && light_cull_count<MAX_LIGHTS_CULLED) { + + InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data); + + if (!light->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + light_cull_result[light_cull_count]=ins; + light_instance_cull_result[light_cull_count]=light->instance; + if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(ins->base)) { + VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later + } + + light_cull_count++; + } + + + } + } else if (ins->base_type==VS::INSTANCE_REFLECTION_PROBE && ins->visible) { + + + if (ins->visible && reflection_probe_cull_count<MAX_REFLECTION_PROBES_CULLED) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(ins->base_data); + + if (p_reflection_probe!=reflection_probe->instance) { + //avoid entering The Matrix + + if (!reflection_probe->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + + if (reflection_probe->reflection_dirty || VSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) { + if (!reflection_probe->update_list.in_list()) { + reflection_probe->render_step=0; + reflection_probe_render_list.add(&reflection_probe->update_list); + } + + reflection_probe->reflection_dirty=false; + } + + if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) { + reflection_probe_instance_cull_result[reflection_probe_cull_count]=reflection_probe->instance; + reflection_probe_cull_count++; + } + + } + } + } + + } else if (ins->base_type==VS::INSTANCE_GI_PROBE && ins->visible) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(ins->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + } else if ((1<<ins->base_type)&VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows!=VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + + keep=true; +#if 0 + bool discarded=false; + + if (ins->draw_range_end>0) { + + float d = cull_range.nearp.distance_to(ins->data.transform.origin); + if (d<0) + d=0; + discarded=(d<ins->draw_range_begin || d>=ins->draw_range_end); + + + } + + if (!discarded) { + + // test if this geometry should be visible + + if (room_cull_enabled) { + + + if (ins->visible_in_all_rooms) { + keep=true; + } else if (ins->room) { + + if (ins->room->room_info->last_visited_pass==render_pass) + keep=true; + } else if (ins->auto_rooms.size()) { + + + for(Set<Instance*>::Element *E=ins->auto_rooms.front();E;E=E->next()) { + + if (E->get()->room_info->last_visited_pass==render_pass) { + keep=true; + break; + } + } + } else if(exterior_visited) + keep=true; + } else { + + keep=true; + } + + + } + + + if (keep) { + // update cull range + float min,max; + ins->transformed_aabb.project_range_in_plane(cull_range.nearp,min,max); + + if (min<cull_range.min) + cull_range.min=min; + if (max>cull_range.max) + cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->gi_probe_sampler_info->last_pass!=render_pass) { + if (light_samplers_culled<MAX_LIGHT_SAMPLERS) { + light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light; + ins->sampled_light->gi_probe_sampler_info->last_pass=render_pass; + } + } + } +#endif + + + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(ins->base_data); + + + if (geom->lighting_dirty) { + int l=0; + //only called when lights AABB enter/exit this geometry + ins->light_instances.resize(geom->lighting.size()); + + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + + InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data); + + ins->light_instances[l++]=light->instance; + } + + geom->lighting_dirty=false; + } + + if (geom->reflection_dirty) { + int l=0; + //only called when reflection probe AABB enter/exit this geometry + ins->reflection_probe_instances.resize(geom->reflection_probes.size()); + + for (List<Instance*>::Element *E=geom->reflection_probes.front();E;E=E->next()) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(E->get()->base_data); + + ins->reflection_probe_instances[l++]=reflection_probe->instance; + } + + geom->reflection_dirty=false; + } + + if (geom->gi_probes_dirty) { + int l=0; + //only called when reflection probe AABB enter/exit this geometry + ins->gi_probe_instances.resize(geom->gi_probes.size()); + + for (List<Instance*>::Element *E=geom->gi_probes.front();E;E=E->next()) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(E->get()->base_data); + + ins->gi_probe_instances[l++]=gi_probe->probe_instance; + } + + geom->gi_probes_dirty=false; + } + + ins->depth = near_plane.distance_to(ins->transform.origin); + ins->depth_layer=CLAMP(int(ins->depth*8/z_far),0,7); + + } + + if (!keep) { + // remove, no reason to keep + cull_count--; + SWAP( instance_cull_result[i], instance_cull_result[ cull_count ] ); + i--; + ins->last_render_pass=0; // make invalid + } else { + + ins->last_render_pass=render_pass; + } + } + + /* STEP 5 - PROCESS LIGHTS */ + + RID *directional_light_ptr=&light_instance_cull_result[light_cull_count]; + int directional_light_count=0; + + // directional lights + { + + Instance** lights_with_shadow = (Instance**)alloca(sizeof(Instance*)*scenario->directional_lights.size()); + int directional_shadow_count=0; + + for (List<Instance*>::Element *E=scenario->directional_lights.front();E;E=E->next()) { + + if (light_cull_count+directional_light_count>=MAX_LIGHTS_CULLED) { + break; + } + + if (!E->get()->visible) + continue; + + InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data); + + + //check shadow.. + + + if (light && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) { + lights_with_shadow[directional_shadow_count++]=E->get(); + + } + + //add to list + + directional_light_ptr[directional_light_count++]=light->instance; + } + + VSG::scene_render->set_directional_shadow_count(directional_shadow_count); + + for(int i=0;i<directional_shadow_count;i++) { + + _light_instance_update_shadow(lights_with_shadow[i],p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario); + + } + } + + + { //setup shadow maps + + //SortArray<Instance*,_InstanceLightsort> sorter; + //sorter.sort(light_cull_result,light_cull_count); + for (int i=0;i<light_cull_count;i++) { + + Instance *ins = light_cull_result[i]; + + if (!p_shadow_atlas.is_valid() || !VSG::storage->light_has_shadow(ins->base)) + continue; + + InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data); + + float coverage; + + { //compute coverage + + + Transform cam_xf = p_cam_transform; + float zn = p_cam_projection.get_z_near(); + Plane p (cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2) ); //camera near plane + + float vp_w,vp_h; //near plane size in screen coordinates + p_cam_projection.get_viewport_size(vp_w,vp_h); + + + switch(VSG::storage->light_get_type(ins->base)) { + + case VS::LIGHT_OMNI: { + + float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE); + + //get two points parallel to near plane + Vector3 points[2]={ + ins->transform.origin, + ins->transform.origin+cam_xf.basis.get_axis(0)*radius + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for(int j=0;j<2;j++) { + if (p.distance_to(points[j]) < 0 ) { + points[j].z=-zn; //small hack to keep size constant when hitting the screen + + } + + p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane + } + + + } + + float screen_diameter = points[0].distance_to(points[1])*2; + coverage = screen_diameter / (vp_w+vp_h); + } break; + case VS::LIGHT_SPOT: { + + float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE); + float angle = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_SPOT_ANGLE); + + + float w = radius*Math::sin(Math::deg2rad(angle)); + float d = radius*Math::cos(Math::deg2rad(angle)); + + + Vector3 base = ins->transform.origin-ins->transform.basis.get_axis(2).normalized()*d; + + Vector3 points[2]={ + base, + base+cam_xf.basis.get_axis(0)*w + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for(int j=0;j<2;j++) { + if (p.distance_to(points[j]) < 0 ) { + points[j].z=-zn; //small hack to keep size constant when hitting the screen + + } + + p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane + } + + + } + + float screen_diameter = points[0].distance_to(points[1])*2; + coverage = screen_diameter / (vp_w+vp_h); + + + } break; + default: { + ERR_PRINT("Invalid Light Type"); + } + } + + } + + + if (light->shadow_dirty) { + light->last_version++; + light->shadow_dirty=false; + } + + + bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version); + + if (redraw) { + print_line("redraw shadow"); + //must redraw! + _light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario); + } + + } + } + + /* ENVIRONMENT */ + + RID environment; + if (p_force_environment.is_valid()) //camera has more environment priority + environment=p_force_environment; + else if (scenario->environment.is_valid()) + environment=scenario->environment; + else + environment=scenario->fallback_environment; + +#if 0 + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;i<light_samplers_culled;i++) { + + _process_sampled_light(camera->transform,light_sampler_cull_result[i],islinear); + } +#endif + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + + VSG::scene_render->render_scene(p_cam_transform, p_cam_projection,p_cam_orthogonal,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,reflection_probe_instance_cull_result,reflection_probe_cull_count,environment,p_shadow_atlas,scenario->reflection_atlas,p_reflection_probe,p_reflection_probe_pass); + + +} + +bool VisualServerScene::_render_reflection_probe_step(Instance* p_instance,int p_step) { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data); + Scenario *scenario = p_instance->scenario; + ERR_FAIL_COND_V(!scenario,true); + + if (p_step==0) { + + if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance,scenario->reflection_atlas)) { + return true; //sorry, all full :( + } + } + + if (p_step>=0 && p_step<6) { + + static const Vector3 view_normals[6]={ + Vector3(-1, 0, 0), + Vector3(+1, 0, 0), + Vector3( 0,-1, 0), + Vector3( 0,+1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1) + }; + + Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base); + Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base); + float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); + + + Vector3 edge = view_normals[p_step]*extents; + float distance = ABS(view_normals[p_step].dot(edge)-view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit + + max_distance = MAX(max_distance,distance); + + + //render cubemap side + CameraMatrix cm; + cm.set_perspective(90,1,0.01,max_distance); + + + static const Vector3 view_up[6]={ + Vector3( 0,-1, 0), + Vector3( 0,-1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1), + Vector3( 0,-1, 0), + Vector3( 0,-1, 0) + }; + + Transform local_view; + local_view.set_look_at(origin_offset,origin_offset+view_normals[p_step],view_up[p_step]); + + Transform xform = p_instance->transform * local_view; + + RID shadow_atlas; + + if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) { + + shadow_atlas=scenario->reflection_probe_shadow_atlas; + } + + _render_scene(xform,cm,false,RID(),VSG::storage->reflection_probe_get_cull_mask(p_instance->base),p_instance->scenario->self,shadow_atlas,reflection_probe->instance,p_step); + + } else { + //do roughness postprocess step until it belives it's done + return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); + } + + return false; +} + +void VisualServerScene::_gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell* p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell) { + + if (p_level==p_header->cell_subdiv-1) { + + Vector3 emission; + emission.x=(p_cell[p_idx].emission>>24)/255.0; + emission.y=((p_cell[p_idx].emission>>16)&0xFF)/255.0; + emission.z=((p_cell[p_idx].emission>>8)&0xFF)/255.0; + float l = (p_cell[p_idx].emission&0xFF)/255.0; + l*=8.0; + + emission*=l; + + p_local_data[p_idx].energy[0]=uint16_t(emission.x*1024); //go from 0 to 1024 for light + p_local_data[p_idx].energy[1]=uint16_t(emission.y*1024); //go from 0 to 1024 for light + p_local_data[p_idx].energy[2]=uint16_t(emission.z*1024); //go from 0 to 1024 for light + } else { + + p_local_data[p_idx].energy[0]=0; + p_local_data[p_idx].energy[1]=0; + p_local_data[p_idx].energy[2]=0; + + int half=(1<<(p_header->cell_subdiv-1))>>(p_level+1); + + for(int i=0;i<8;i++) { + + uint32_t child = p_cell[p_idx].children[i]; + + if (child==0xFFFFFFFF) + continue; + + int x = p_x; + int y = p_y; + int z = p_z; + + if (i&1) + x+=half; + if (i&2) + y+=half; + if (i&4) + z+=half; + + _gi_probe_fill_local_data(child,p_level+1,x,y,z,p_cell,p_header,p_local_data,prev_cell); + } + } + + //position for each part of the mipmaped texture + p_local_data[p_idx].pos[0]=p_x>>(p_header->cell_subdiv-p_level-1); + p_local_data[p_idx].pos[1]=p_y>>(p_header->cell_subdiv-p_level-1); + p_local_data[p_idx].pos[2]=p_z>>(p_header->cell_subdiv-p_level-1); + + prev_cell[p_level].push_back(p_idx); + +} + + +void VisualServerScene::_gi_probe_bake_threads(void* self) { + + VisualServerScene* vss = (VisualServerScene*)self; + vss->_gi_probe_bake_thread(); +} + +void VisualServerScene::_setup_gi_probe(Instance *p_instance) { + + + InstanceGIProbeData *probe = static_cast<InstanceGIProbeData*>(p_instance->base_data); + + if (probe->dynamic.probe_data.is_valid()) { + VSG::storage->free(probe->dynamic.probe_data); + probe->dynamic.probe_data=RID(); + } + + probe->dynamic.light_data=VSG::storage->gi_probe_get_dynamic_data(p_instance->base); + + if (probe->dynamic.light_data.size()==0) + return; + //using dynamic data + DVector<int>::Read r=probe->dynamic.light_data.read(); + + const GIProbeDataHeader *header = (GIProbeDataHeader *)r.ptr(); + + probe->dynamic.local_data.resize(header->cell_count); + + int cell_count = probe->dynamic.local_data.size(); + DVector<InstanceGIProbeData::LocalData>::Write ldw = probe->dynamic.local_data.write(); + const GIProbeDataCell *cells = (GIProbeDataCell*)&r[16]; + + probe->dynamic.level_cell_lists.resize(header->cell_subdiv); + + _gi_probe_fill_local_data(0,0,0,0,0,cells,header,ldw.ptr(),probe->dynamic.level_cell_lists.ptr()); + + bool compress = VSG::storage->gi_probe_is_compressed(p_instance->base); + + probe->dynamic.compression = compress ? VSG::storage->gi_probe_get_dynamic_data_get_preferred_compression() : RasterizerStorage::GI_PROBE_UNCOMPRESSED; + + probe->dynamic.probe_data=VSG::storage->gi_probe_dynamic_data_create(header->width,header->height,header->depth,probe->dynamic.compression); + + probe->dynamic.bake_dynamic_range=VSG::storage->gi_probe_get_dynamic_range(p_instance->base); + + probe->dynamic.mipmaps_3d.clear(); + + probe->dynamic.grid_size[0]=header->width; + probe->dynamic.grid_size[1]=header->height; + probe->dynamic.grid_size[2]=header->depth; + + int size_limit = 1; + int size_divisor = 1; + + if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + print_line("S3TC"); + size_limit=4; + size_divisor=4; + } + for(int i=0;i<(int)header->cell_subdiv;i++) { + + uint32_t x = header->width >> i; + uint32_t y = header->height >> i; + uint32_t z = header->depth >> i; + + //create and clear mipmap + DVector<uint8_t> mipmap; + int size = x*y*z*4; + size/=size_divisor; + mipmap.resize(size); + DVector<uint8_t>::Write w = mipmap.write(); + zeromem(w.ptr(),size); + w = DVector<uint8_t>::Write(); + + probe->dynamic.mipmaps_3d.push_back(mipmap); + + if (x<=size_limit || y<=size_limit || z<=size_limit) + break; + } + + probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK; + probe->invalid=false; + probe->dynamic.enabled=true; + + Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base); + AABB bounds = VSG::storage->gi_probe_get_bounds(p_instance->base); + float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base); + + probe->dynamic.light_to_cell_xform=cell_to_xform * p_instance->transform.affine_inverse(); + + VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,probe->dynamic.probe_data); + VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance,probe->dynamic.light_to_cell_xform); + + VSG::scene_render->gi_probe_instance_set_bounds(probe->probe_instance,bounds.size/cell_size); + + probe->base_version=VSG::storage->gi_probe_get_version(p_instance->base); + + //if compression is S3TC, fill it up + if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + + //create all blocks + Vector<Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> > comp_blocks; + int mipmap_count = probe->dynamic.mipmaps_3d.size(); + comp_blocks.resize(mipmap_count); + + for(int i=0;i<cell_count;i++) { + + const GIProbeDataCell &c = cells[i]; + const InstanceGIProbeData::LocalData &ld = ldw[i]; + int level = c.level_alpha>>16; + int mipmap = header->cell_subdiv - level -1; + if (mipmap >= mipmap_count) + continue;//uninteresting + + + int blockx = (ld.pos[0]>>2); + int blocky = (ld.pos[1]>>2); + int blockz = (ld.pos[2]); //compression is x/y only + + int blockw = (header->width >> mipmap) >> 2; + int blockh = (header->height >> mipmap) >> 2; + + //print_line("cell "+itos(i)+" level "+itos(level)+"mipmap: "+itos(mipmap)+" pos: "+Vector3(blockx,blocky,blockz)+" size "+Vector2(blockw,blockh)); + + uint32_t key = blockz * blockw*blockh + blocky * blockw + blockx; + + Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> & cmap = comp_blocks[mipmap]; + + if (!cmap.has(key)) { + + InstanceGIProbeData::CompBlockS3TC k; + k.offset=key; //use offset as counter first + k.source_count=0; + cmap[key]=k; + } + + InstanceGIProbeData::CompBlockS3TC &k=cmap[key]; + ERR_CONTINUE(k.source_count==16); + k.sources[k.source_count++]=i; + } + + //fix the blocks, precomputing what is needed + probe->dynamic.mipmaps_s3tc.resize(mipmap_count); + + for(int i=0;i<mipmap_count;i++) { + print_line("S3TC level: "+itos(i)+" blocks: "+itos(comp_blocks[i].size())); + probe->dynamic.mipmaps_s3tc[i].resize(comp_blocks[i].size()); + DVector<InstanceGIProbeData::CompBlockS3TC>::Write w = probe->dynamic.mipmaps_s3tc[i].write(); + int block_idx=0; + + for (Map<uint32_t,InstanceGIProbeData::CompBlockS3TC>::Element *E=comp_blocks[i].front();E;E=E->next()) { + + InstanceGIProbeData::CompBlockS3TC k = E->get(); + + //PRECOMPUTE ALPHA + int max_alpha=-100000; + int min_alpha=k.source_count==16 ?100000 :0; //if the block is not completely full, minimum is always 0, (and those blocks will map to 1, which will be zero) + + uint8_t alpha_block[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; + + for(int j=0;j<k.source_count;j++) { + + int alpha = (cells[k.sources[j]].level_alpha>>8)&0xFF; + if (alpha<min_alpha) + min_alpha=alpha; + if (alpha>max_alpha) + max_alpha=alpha; + //fill up alpha block + alpha_block[ldw[k.sources[j]].pos[0]%4][ldw[k.sources[j]].pos[1]%4]=alpha; + + } + + //use the first mode (8 adjustable levels) + k.alpha[0]=max_alpha; + k.alpha[1]=min_alpha; + + uint64_t alpha_bits=0; + + if (max_alpha!=min_alpha) { + + int idx=0; + + for(int y=0;y<4;y++) { + for(int x=0;x<4;x++) { + + //substract minimum + uint32_t a = uint32_t(alpha_block[x][y])-min_alpha; + //convert range to 3 bits + a =int((a * 7.0 / (max_alpha-min_alpha))+0.5); + a = CLAMP(a,0,7); //just to be sure + a = 7-a; //because range is inverted in this mode + if (a==0) { + //do none, remain + } else if (a==7) { + a=1; + } else { + a=a+1; + } + + alpha_bits|=uint64_t(a)<<(idx*3); + idx++; + } + } + } + + k.alpha[2]=(alpha_bits >> 0)&0xFF; + k.alpha[3]=(alpha_bits >> 8)&0xFF; + k.alpha[4]=(alpha_bits >> 16)&0xFF; + k.alpha[5]=(alpha_bits >> 24)&0xFF; + k.alpha[6]=(alpha_bits >> 32)&0xFF; + k.alpha[7]=(alpha_bits >> 40)&0xFF; + + w[block_idx++]=k; + + } + + } + } + +} + +void VisualServerScene::_gi_probe_bake_thread() { + + while(true) { + + probe_bake_sem->wait(); + if (probe_bake_thread_exit) { + break; + } + + Instance* to_bake=NULL; + + probe_bake_mutex->lock(); + + if (!probe_bake_list.empty()) { + to_bake=probe_bake_list.front()->get(); + probe_bake_list.pop_front(); + + } + probe_bake_mutex->unlock(); + + if (!to_bake) + continue; + + _bake_gi_probe(to_bake); + } +} + + + +uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv) { + + + uint32_t cell=0; + + int ofs_x=0; + int ofs_y=0; + int ofs_z=0; + int size = 1<<(p_cell_subdiv-1); + int half=size/2; + + if (x<0 || x>=size) + return -1; + if (y<0 || y>=size) + return -1; + if (z<0 || z>=size) + return -1; + + for(int i=0;i<p_cell_subdiv-1;i++) { + + const GIProbeDataCell *bc = &cells[cell]; + + int child = 0; + if (x >= ofs_x + half) { + child|=1; + ofs_x+=half; + } + if (y >= ofs_y + half) { + child|=2; + ofs_y+=half; + } + if (z >= ofs_z + half) { + child|=4; + ofs_z+=half; + } + + cell = bc->children[child]; + if (cell==0xFFFFFFFF) + return 0xFFFFFFFF; + + half>>=1; + } + + return cell; + +} + +static float _get_normal_advance(const Vector3& p_normal ) { + + Vector3 normal = p_normal; + Vector3 unorm = normal.abs(); + + if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { + // x code + unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ; + } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { + // y code + unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ; + } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { + // z code + unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ; + } else { + // oh-no we messed up code + // has to be + unorm = Vector3( 1.0, 0.0, 0.0 ); + } + + return 1.0/normal.dot(unorm); + +} + +void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int leaf_count, const InstanceGIProbeData::LightCache& light_cache,int sign) { + + + int light_r = int(light_cache.color.r * light_cache.energy * 1024.0)*sign; + int light_g = int(light_cache.color.g * light_cache.energy * 1024.0)*sign; + int light_b = int(light_cache.color.b * light_cache.energy * 1024.0)*sign; + + float limits[3]={float(header->width),float(header->height),float(header->depth)}; + Plane clip[3]; + int clip_planes=0; + + + + switch(light_cache.type) { + + case VS::LIGHT_DIRECTIONAL: { + + float max_len = Vector3(limits[0],limits[1],limits[2]).length()*1.1; + + Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized(); + + for(int i=0;i<3;i++) { + + if (ABS(light_axis[i])<CMP_EPSILON) + continue; + clip[clip_planes].normal[i]=1.0; + + if (light_axis[i]<0) { + + clip[clip_planes].d=limits[i]+1; + } else { + clip[clip_planes].d-=1.0; + } + + clip_planes++; + } + + float distance_adv = _get_normal_advance(light_axis); + + int success_count=0; + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + for(int i=0;i<leaf_count;i++) { + + uint32_t idx = leaves[i]; + + const GIProbeDataCell *cell = &cells[idx]; + InstanceGIProbeData::LocalData *light = &local_data[idx]; + + Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + + + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + + Vector3 from = to - max_len * light_axis; + + for(int j=0;j<clip_planes;j++) { + + clip[j].intersects_segment(from,to,&from); + } + + float distance = (to - from).length(); + distance+=distance_adv-Math::fmod(distance,distance_adv); //make it reach the center of the box always + from = to - light_axis * distance; + + uint32_t result=0xFFFFFFFF; + + while(distance>-distance_adv) { //use this to avoid precision errors + + result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv); + if (result!=0xFFFFFFFF) { + break; + } + + from+=light_axis*distance_adv; + distance-=distance_adv; + } + + if (result==idx) { + //cell hit itself! hooray! + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + success_count++; + } + } + print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + print_line("valid cells: "+itos(success_count)); + + + } break; + case VS::LIGHT_OMNI: + case VS::LIGHT_SPOT: { + + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + Vector3 light_pos = light_cache.transform.origin; + Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); + + + float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length(); + + for(int i=0;i<leaf_count;i++) { + + uint32_t idx = leaves[i]; + + const GIProbeDataCell *cell = &cells[idx]; + InstanceGIProbeData::LocalData *light = &local_data[idx]; + + Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + + Vector3 light_axis = (to - light_pos).normalized(); + float distance_adv = _get_normal_advance(light_axis); + + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + + { + float d = light_pos.distance_to(to); + if (d+distance_adv > local_radius) + continue; // too far away + + float dt = CLAMP((d+distance_adv)/local_radius,0,1); + att*= powf(1.0-dt,light_cache.attenuation); + } + + + if (light_cache.type==VS::LIGHT_SPOT) { + + float angle = Math::rad2deg(acos(light_axis.dot(spot_axis))); + if (angle > light_cache.spot_angle) + continue; + + float d = CLAMP(angle/light_cache.spot_angle,1,0); + att*= powf(1.0-d,light_cache.spot_attenuation); + + } + + clip_planes=0; + + for(int c=0;c<3;c++) { + + if (ABS(light_axis[c])<CMP_EPSILON) + continue; + clip[clip_planes].normal[c]=1.0; + + if (light_axis[c]<0) { + + clip[clip_planes].d=limits[c]+1; + } else { + clip[clip_planes].d-=1.0; + } + + clip_planes++; + } + + Vector3 from = light_pos; + + for(int j=0;j<clip_planes;j++) { + + clip[j].intersects_segment(from,to,&from); + } + + float distance = (to - from).length(); + + + + distance-=Math::fmod(distance,distance_adv); //make it reach the center of the box always, but this tame make it closer + from = to - light_axis * distance; + + uint32_t result=0xFFFFFFFF; + + while(distance>-distance_adv) { //use this to avoid precision errors + + result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv); + if (result!=0xFFFFFFFF) { + break; + } + + from+=light_axis*distance_adv; + distance-=distance_adv; + } + + if (result==idx) { + //cell hit itself! hooray! + + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + + } + } + print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + + + } break; + } +} + + +void VisualServerScene::_bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data) { + + //average light to upper level + p_local_data[p_idx].energy[0]=0; + p_local_data[p_idx].energy[1]=0; + p_local_data[p_idx].energy[2]=0; + + int divisor=0; + + for(int i=0;i<8;i++) { + + uint32_t child = p_cells[p_idx].children[i]; + + if (child==0xFFFFFFFF) + continue; + + if (p_level+1 < (int)p_header->cell_subdiv-1) { + _bake_gi_downscale_light(child,p_level+1,p_cells,p_header,p_local_data); + } + + p_local_data[p_idx].energy[0]+=p_local_data[child].energy[0]; + p_local_data[p_idx].energy[1]+=p_local_data[child].energy[1]; + p_local_data[p_idx].energy[2]+=p_local_data[child].energy[2]; + divisor++; + + } + + //divide by eight for average + p_local_data[p_idx].energy[0]/=divisor; + p_local_data[p_idx].energy[1]/=divisor; + p_local_data[p_idx].energy[2]/=divisor; + +} + + +void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { + + InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data); + + DVector<int>::Read r=probe_data->dynamic.light_data.read(); + + const GIProbeDataHeader *header = (const GIProbeDataHeader *)r.ptr(); + const GIProbeDataCell *cells = (const GIProbeDataCell*)&r[16]; + + int leaf_count = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].size(); + const uint32_t *leaves = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].ptr(); + + DVector<InstanceGIProbeData::LocalData>::Write ldw = probe_data->dynamic.local_data.write(); + + InstanceGIProbeData::LocalData *local_data = ldw.ptr(); + + + //remove what must be removed + for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache.front();E;E=E->next()) { + + RID rid = E->key(); + const InstanceGIProbeData::LightCache& lc = E->get(); + + if (!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid]==lc)) { + //erase light data + + _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,-1); + } + + } + + //add what must be added + for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache_changes.front();E;E=E->next()) { + + RID rid = E->key(); + const InstanceGIProbeData::LightCache& lc = E->get(); + + if (!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid]==lc)) { + //add light data + + _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,1); + } + } + + SWAP(probe_data->dynamic.light_cache_changes,probe_data->dynamic.light_cache); + + //downscale to lower res levels + _bake_gi_downscale_light(0,0,cells,header,local_data); + + //plot result to 3D texture! + + if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_UNCOMPRESSED) { + + for(int i=0;i<(int)header->cell_subdiv;i++) { + + int stage = header->cell_subdiv - i -1; + + if (stage >= probe_data->dynamic.mipmaps_3d.size()) + continue; //no mipmap for this one + + print_line("generating mipmap stage: "+itos(stage)); + int level_cell_count = probe_data->dynamic.level_cell_lists[ i ].size(); + const uint32_t *level_cells = probe_data->dynamic.level_cell_lists[ i ].ptr(); + + DVector<uint8_t>::Write lw = probe_data->dynamic.mipmaps_3d[stage].write(); + uint8_t *mipmapw = lw.ptr(); + + uint32_t sizes[3]={header->width>>stage,header->height>>stage,header->depth>>stage}; + + for(int j=0;j<level_cell_count;j++) { + + uint32_t idx = level_cells[j]; + + uint32_t r = (uint32_t(local_data[idx].energy[0])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t g = (uint32_t(local_data[idx].energy[1])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t b = (uint32_t(local_data[idx].energy[2])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t a = (cells[idx].level_alpha>>8)&0xFF; + + uint32_t mm_ofs = sizes[0]*sizes[1]*(local_data[idx].pos[2]) + sizes[0]*(local_data[idx].pos[1]) + (local_data[idx].pos[0]); + mm_ofs*=4; //for RGBA (4 bytes) + + mipmapw[mm_ofs+0]=uint8_t(CLAMP(r,0,255)); + mipmapw[mm_ofs+1]=uint8_t(CLAMP(g,0,255)); + mipmapw[mm_ofs+2]=uint8_t(CLAMP(b,0,255)); + mipmapw[mm_ofs+3]=uint8_t(CLAMP(a,0,255)); + + + } + } + } else if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + + + int mipmap_count = probe_data->dynamic.mipmaps_3d.size(); + + for(int mmi=0;mmi<mipmap_count;mmi++) { + + DVector<uint8_t>::Write mmw = probe_data->dynamic.mipmaps_3d[mmi].write(); + int block_count = probe_data->dynamic.mipmaps_s3tc[mmi].size(); + DVector<InstanceGIProbeData::CompBlockS3TC>::Read mmr = probe_data->dynamic.mipmaps_s3tc[mmi].read(); + + for(int i=0;i<block_count;i++) { + + const InstanceGIProbeData::CompBlockS3TC& b = mmr[i]; + + uint8_t *blockptr = &mmw[b.offset*16]; + copymem(blockptr,b.alpha,8); //copy alpha part, which is precomputed + + Vector3 colors[16]; + + for(int j=0;j<b.source_count;j++) { + + colors[j].x=(local_data[b.sources[j]].energy[0]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + colors[j].y=(local_data[b.sources[j]].energy[1]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + colors[j].z=(local_data[b.sources[j]].energy[2]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + } + //super quick and dirty compression + //find 2 most futher apart + float distance=0; + Vector3 from,to; + + if (b.source_count==16) { + //all cells are used so, find minmax between them + int further_apart[2]={0,0}; + for(int j=0;j<b.source_count;j++) { + for(int k=j+1;k<b.source_count;k++) { + float d = colors[j].distance_squared_to(colors[k]); + if (d>distance) { + distance=d; + further_apart[0]=j; + further_apart[1]=k; + } + } + } + + from = colors[further_apart[0]]; + to = colors[further_apart[1]]; + + } else { + //if a block is missing, the priority is that this block remains black, + //otherwise the geometry will appear deformed + //correct shape wins over correct color in this case + //average all colors first + Vector3 average; + + for(int j=0;j<b.source_count;j++) { + average+=colors[j]; + } + average.normalize(); + //find max distance in normal from average + for(int j=0;j<b.source_count;j++) { + float d = average.dot(colors[j]); + distance=MAX(d,distance); + } + + from = Vector3(); //from black + to = average * distance; + //find max distance + + } + + + int indices[16]; + uint16_t color_0=0; + color_0 = CLAMP(int(from.x*31),0,31)<<11; + color_0 |= CLAMP(int(from.y*63),0,63)<<5; + color_0 |= CLAMP(int(from.z*31),0,31); + + uint16_t color_1=0; + color_1 = CLAMP(int(to.x*31),0,31)<<11; + color_1 |= CLAMP(int(to.y*63),0,63)<<5; + color_1 |= CLAMP(int(to.z*31),0,31); + + if (color_1 > color_0) { + SWAP(color_1,color_0); + SWAP(from,to); + } + + + if (distance>0) { + + Vector3 dir = (to-from).normalized(); + + + for(int j=0;j<b.source_count;j++) { + + float d = (colors[j]-from).dot(dir) / distance; + indices[j]=int(d*3+0.5); + + static const int index_swap[4]={0,3,1,2}; + + indices[j]=index_swap[CLAMP(indices[j],0,3)]; + + + } + } else { + for(int j=0;j<b.source_count;j++) { + indices[j]=0; + } + } + + //by default, 1 is black, otherwise it will be overriden by source + + uint32_t index_block[16]={1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 }; + + for(int j=0;j<b.source_count;j++) { + + int x=local_data[b.sources[j]].pos[0]%4; + int y=local_data[b.sources[j]].pos[1]%4; + + index_block[y*4+x]=indices[j]; + } + + uint32_t encode=0; + + for(int j=0;j<16;j++) { + encode|=index_block[j]<<(j*2); + } + + blockptr[8]=color_0&0xFF; + blockptr[9]=(color_0>>8)&0xFF; + blockptr[10]=color_1&0xFF; + blockptr[11]=(color_1>>8)&0xFF; + blockptr[12]=encode&0xFF; + blockptr[13]=(encode>>8)&0xFF; + blockptr[14]=(encode>>16)&0xFF; + blockptr[15]=(encode>>24)&0xFF; + + } + + + } + + } + + + //send back to main thread to update un little chunks + probe_data->dynamic.updating_stage=GI_UPDATE_STAGE_UPLOADING; + +} + +bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { + + InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data); + + probe_data->dynamic.light_cache_changes.clear(); + + bool all_equal=true; + + + for (List<Instance*>::Element *E=p_gi_probe->scenario->directional_lights.front();E;E=E->next()) { + + InstanceGIProbeData::LightCache lc; + lc.type=VSG::storage->light_get_type(E->get()->base); + lc.color=VSG::storage->light_get_color(E->get()->base); + lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY); + lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE); + lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION); + lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE); + lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION); + lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + + if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) { + all_equal=false; + } + + probe_data->dynamic.light_cache_changes[E->get()->self]=lc; + + } + + + for (Set<Instance*>::Element *E=probe_data->lights.front();E;E=E->next()) { + + InstanceGIProbeData::LightCache lc; + lc.type=VSG::storage->light_get_type(E->get()->base); + lc.color=VSG::storage->light_get_color(E->get()->base); + lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY); + lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE); + lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION); + lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE); + lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION); + lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + + if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) { + all_equal=false; + } + + probe_data->dynamic.light_cache_changes[E->get()->self]=lc; + } + + //lighting changed from after to before, must do some updating + return !all_equal || probe_data->dynamic.light_cache_changes.size()!=probe_data->dynamic.light_cache.size(); + +} + +void VisualServerScene::render_probes() { + + /* REFLECTION PROBES */ + + SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first(); + + bool busy=false; + + while(ref_probe) { + + SelfList<InstanceReflectionProbeData> *next=ref_probe->next(); + RID base = ref_probe->self()->owner->base; + + switch(VSG::storage->reflection_probe_get_update_mode(base)) { + + case VS::REFLECTION_PROBE_UPDATE_ONCE: { + if (busy) //already rendering something + break; + + bool done = _render_reflection_probe_step(ref_probe->self()->owner,ref_probe->self()->render_step); + if (done) { + reflection_probe_render_list.remove(ref_probe); + } else { + ref_probe->self()->render_step++; + } + + busy=true; //do not render another one of this kind + } break; + case VS::REFLECTION_PROBE_UPDATE_ALWAYS: { + + int step=0; + bool done=false; + while(!done) { + done = _render_reflection_probe_step(ref_probe->self()->owner,step); + step++; + } + + reflection_probe_render_list.remove(ref_probe); + } break; + + } + + ref_probe=next; + } + + /* GI PROBES */ + + SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first(); + + while(gi_probe) { + + SelfList<InstanceGIProbeData> *next=gi_probe->next(); + + InstanceGIProbeData *probe = gi_probe->self(); + Instance *instance_probe = probe->owner; + + //check if probe must be setup, but don't do if on the lighting thread + + bool force_lighting=false; + + if (probe->invalid || (probe->dynamic.updating_stage==GI_UPDATE_STAGE_CHECK && probe->base_version!=VSG::storage->gi_probe_get_version(instance_probe->base))) { + + _setup_gi_probe(instance_probe); + force_lighting=true; + } + + if (probe->invalid==false && probe->dynamic.enabled) { + + switch(probe->dynamic.updating_stage) { + case GI_UPDATE_STAGE_CHECK: { + + if (_check_gi_probe(instance_probe) || force_lighting) { + //send to lighting thread + probe->dynamic.updating_stage=GI_UPDATE_STAGE_LIGHTING; + +#ifndef NO_THREADS + probe_bake_mutex->lock(); + probe_bake_list.push_back(instance_probe); + probe_bake_mutex->unlock(); + probe_bake_sem->post(); + +#else + + _bake_gi_probe(instance_probe); +#endif + + } + } break; + case GI_UPDATE_STAGE_LIGHTING: { + //do none, wait til done! + + } break; + case GI_UPDATE_STAGE_UPLOADING: { + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + for(int i=0;i<(int)probe->dynamic.mipmaps_3d.size();i++) { + + int mmsize = probe->dynamic.mipmaps_3d[i].size(); + DVector<uint8_t>::Read r = probe->dynamic.mipmaps_3d[i].read(); + VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data,0,probe->dynamic.grid_size[2]>>i,i,r.ptr()); + } + + + probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK; + +// print_line("UPLOAD TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + } break; + + } + } + //_update_gi_probe(gi_probe->self()->owner); + + + gi_probe=next; + } + + + +} + +void VisualServerScene::_update_dirty_instance(Instance *p_instance) { + + if (p_instance->update_aabb) + _update_instance_aabb(p_instance); + + + if (p_instance->update_materials) { + + if (p_instance->base_type==VS::INSTANCE_MESH) { + //remove materials no longer used and un-own them + + int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base); + for(int i=p_instance->materials.size()-1;i>=new_mat_count;i--) { + if (p_instance->materials[i].is_valid()) { + VSG::storage->material_remove_instance_owner(p_instance->materials[i],p_instance); + } + } + p_instance->materials.resize(new_mat_count); + + int new_morph_count = VSG::storage->mesh_get_morph_target_count(p_instance->base); + if (new_morph_count!=p_instance->morph_values.size()) { + p_instance->morph_values.resize(new_morph_count); + for(int i=0;i<new_morph_count;i++) { + p_instance->morph_values[i]=0; + } + } + } + + if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data); + + bool can_cast_shadows=true; + + if (p_instance->cast_shadows==VS::SHADOW_CASTING_SETTING_OFF) { + can_cast_shadows=false; + } else if (p_instance->material_override.is_valid()) { + can_cast_shadows=VSG::storage->material_casts_shadows(p_instance->material_override); + } else { + + + + if (p_instance->base_type==VS::INSTANCE_MESH) { + RID mesh=p_instance->base; + + if (mesh.is_valid()) { + bool cast_shadows=false; + + for(int i=0;i<p_instance->materials.size();i++) { + + + RID mat = p_instance->materials[i].is_valid()?p_instance->materials[i]:VSG::storage->mesh_surface_get_material(mesh,i); + + if (!mat.is_valid()) { + cast_shadows=true; + break; + } + + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows=true; + break; + } + } + + if (!cast_shadows) { + can_cast_shadows=false; + } + } + + } else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) { + RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base); + if (mesh.is_valid()) { + bool cast_shadows=false; + + int sc = VSG::storage->mesh_get_surface_count(mesh); + for(int i=0;i<sc;i++) { + + RID mat =VSG::storage->mesh_surface_get_material(mesh,i); + + if (!mat.is_valid()) { + cast_shadows=true; + break; + } + + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows=true; + break; + } + } + + if (!cast_shadows) { + can_cast_shadows=false; + } + } + } else if (p_instance->base_type==VS::INSTANCE_IMMEDIATE) { + + RID mat = VSG::storage->immediate_get_material(p_instance->base); + + if (!mat.is_valid() || VSG::storage->material_casts_shadows(mat)) { + can_cast_shadows=true; + } else { + can_cast_shadows=false; + } + + + } + + + + } + + if (can_cast_shadows!=geom->can_cast_shadows) { + //ability to cast shadows change, let lights now + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data); + light->shadow_dirty=true; + } + + geom->can_cast_shadows=can_cast_shadows; + } + } + + } + + _update_instance(p_instance); + + p_instance->update_aabb=false; + p_instance->update_materials=false; + + _instance_update_list.remove( &p_instance->update_item ); +} + + +void VisualServerScene::update_dirty_instances() { + + while(_instance_update_list.first()) { + + _update_dirty_instance( _instance_update_list.first()->self() ); + } +} + +bool VisualServerScene::free(RID p_rid) { + + if (camera_owner.owns(p_rid)) { + + Camera *camera = camera_owner.get( p_rid ); + + camera_owner.free(p_rid); + memdelete(camera); + + } else if (scenario_owner.owns(p_rid)) { + + Scenario *scenario = scenario_owner.get( p_rid ); + + while(scenario->instances.first()) { + instance_set_scenario(scenario->instances.first()->self()->self,RID()); + } + VSG::scene_render->free(scenario->reflection_probe_shadow_atlas); + VSG::scene_render->free(scenario->reflection_atlas); + scenario_owner.free(p_rid); + memdelete(scenario); + + } else if (instance_owner.owns(p_rid)) { + // delete the instance + + update_dirty_instances(); + + Instance *instance = instance_owner.get(p_rid); + + instance_set_room(p_rid,RID()); + instance_set_scenario(p_rid,RID()); + instance_set_base(p_rid,RID()); + instance_geometry_set_material_override(p_rid,RID()); + instance_attach_skeleton(p_rid,RID()); + + update_dirty_instances(); //in case something changed this + + instance_owner.free(p_rid); + memdelete(instance); + } else { + return false; + } + + + return true; +} + +VisualServerScene *VisualServerScene::singleton=NULL; + + +VisualServerScene::VisualServerScene() { + +#ifndef NO_THREADS + probe_bake_sem = Semaphore::create(); + probe_bake_mutex = Mutex::create(); + probe_bake_thread = Thread::create(_gi_probe_bake_threads,this); + probe_bake_thread_exit=false; +#endif + + + render_pass=1; + singleton=this; + +} + +VisualServerScene::~VisualServerScene() { + +#ifndef NO_THREADS + probe_bake_thread_exit=true; + Thread::wait_to_finish(probe_bake_thread); + memdelete(probe_bake_thread); + memdelete(probe_bake_sem); + memdelete(probe_bake_mutex); + +#endif + + +} diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h new file mode 100644 index 0000000000..aa498e2752 --- /dev/null +++ b/servers/visual/visual_server_scene.h @@ -0,0 +1,587 @@ +#ifndef VISUALSERVERSCENE_H +#define VISUALSERVERSCENE_H + +#include "servers/visual/rasterizer.h" + +#include "geometry.h" +#include "allocators.h" +#include "octree.h" +#include "self_list.h" +#include "os/thread.h" +#include "os/semaphore.h" +#include "os/semaphore.h" + +class VisualServerScene { +public: + + + enum { + + MAX_INSTANCE_CULL=65536, + MAX_LIGHTS_CULLED=4096, + MAX_REFLECTION_PROBES_CULLED=4096, + MAX_ROOM_CULL=32, + MAX_EXTERIOR_PORTALS=128, + }; + + uint64_t render_pass; + + + static VisualServerScene *singleton; +#if 0 + struct Portal { + + bool enabled; + float disable_distance; + Color disable_color; + float connect_range; + Vector<Point2> shape; + Rect2 bounds; + + + Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; } + }; + + struct BakedLight { + + Rasterizer::BakedLightData data; + DVector<int> sampler; + AABB octree_aabb; + Size2i octree_tex_size; + Size2i light_tex_size; + + }; + + struct BakedLightSampler { + + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector<Vector3> dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); + +#endif + + + /* CAMERA API */ + + struct Camera : public RID_Data { + + enum Type { + PERSPECTIVE, + ORTHOGONAL + }; + Type type; + float fov; + float znear,zfar; + float size; + uint32_t visible_layers; + bool vaspect; + RID env; + + Transform transform; + + Camera() { + + visible_layers=0xFFFFFFFF; + fov=60; + type=PERSPECTIVE; + znear=0.1; zfar=100; + size=1.0; + vaspect=false; + + } + }; + + mutable RID_Owner<Camera> camera_owner; + + virtual RID camera_create(); + virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far); + virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far); + virtual void camera_set_transform(RID p_camera,const Transform& p_transform); + virtual void camera_set_cull_mask(RID p_camera,uint32_t p_layers); + virtual void camera_set_environment(RID p_camera,RID p_env); + virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable); + + + /* + + struct RoomInfo { + + Transform affine_inverse; + Room *room; + List<Instance*> owned_geometry_instances; + List<Instance*> owned_portal_instances; + List<Instance*> owned_room_instances; + List<Instance*> owned_light_instances; //not used, but just for the sake of it + Set<Instance*> disconnected_child_portals; + Set<Instance*> owned_autoroom_geometry; + uint64_t last_visited_pass; + RoomInfo() { last_visited_pass=0; } + + }; + + struct InstancePortal { + + Portal *portal; + Set<Instance*> candidate_set; + Instance *connected; + uint64_t last_visited_pass; + + Plane plane_cache; + Vector<Vector3> transformed_point_cache; + + + PortalInfo() { connected=NULL; last_visited_pass=0;} + }; +*/ + + + + /* SCENARIO API */ + + struct Instance; + + struct Scenario : RID_Data { + + + VS::ScenarioDebugMode debug; + RID self; + // well wtf, balloon allocator is slower? + + Octree<Instance,true> octree; + + List<Instance*> directional_lights; + RID environment; + RID fallback_environment; + RID reflection_probe_shadow_atlas; + RID reflection_atlas; + + + SelfList<Instance>::List instances; + + Scenario() { debug=VS::SCENARIO_DEBUG_DISABLED; } + }; + + mutable RID_Owner<Scenario> scenario_owner; + + static void* _instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int); + static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void*); + + virtual RID scenario_create(); + + virtual void scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode); + virtual void scenario_set_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv); + + + /* INSTANCING API */ + + struct InstanceBaseData { + + + virtual ~InstanceBaseData() {} + }; + + + + struct Instance : RasterizerScene::InstanceBase { + + RID self; + //scenario stuff + OctreeElementID octree_id; + Scenario *scenario; + SelfList<Instance> scenario_item; + + //aabb stuff + bool update_aabb; + bool update_materials; + + SelfList<Instance> update_item; + + + AABB aabb; + AABB transformed_aabb; + float extra_margin; + uint32_t object_ID; + bool visible; + + float lod_begin; + float lod_end; + float lod_begin_hysteresis; + float lod_end_hysteresis; + RID lod_instance; + + Instance *room; + SelfList<Instance> room_item; + bool visible_in_all_rooms; + + uint64_t last_render_pass; + uint64_t last_frame_pass; + + uint64_t version; // changes to this, and changes to base increase version + + InstanceBaseData *base_data; + + virtual void base_removed() { + + singleton->instance_set_base(self,RID()); + } + + virtual void base_changed() { + + singleton->_instance_queue_update(this,true,true); + } + + virtual void base_material_changed() { + + singleton->_instance_queue_update(this,false,true); + } + + + Instance() : scenario_item(this), update_item(this), room_item(this) { + + octree_id=0; + scenario=NULL; + + + update_aabb=false; + update_materials=false; + + extra_margin=0; + + + object_ID=0; + visible=true; + + lod_begin=0; + lod_end=0; + lod_begin_hysteresis=0; + lod_end_hysteresis=0; + + room=NULL; + visible_in_all_rooms=false; + + + + last_render_pass=0; + last_frame_pass=0; + version=1; + base_data=NULL; + + } + + ~Instance() { + + if (base_data) + memdelete(base_data); + + } + }; + + SelfList<Instance>::List _instance_update_list; + void _instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials=false); + + + struct InstanceGeometryData : public InstanceBaseData { + + List<Instance*> lighting; + bool lighting_dirty; + bool can_cast_shadows; + + List<Instance*> reflection_probes; + bool reflection_dirty; + + List<Instance*> gi_probes; + bool gi_probes_dirty; + + InstanceGeometryData() { + + lighting_dirty=false; + reflection_dirty=true; + can_cast_shadows=true; + gi_probes_dirty=true; + } + }; + + struct InstanceReflectionProbeData : public InstanceBaseData { + + + Instance *owner; + + struct PairInfo { + List<Instance*>::Element *L; //reflection iterator in geometry + Instance *geometry; + }; + List<PairInfo> geometries; + + + RID instance; + bool reflection_dirty; + SelfList<InstanceReflectionProbeData> update_list; + + int render_step; + + InstanceReflectionProbeData() : update_list(this) { + + reflection_dirty=true; + render_step=-1; + } + }; + + SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list; + + struct InstanceLightData : public InstanceBaseData { + + struct PairInfo { + List<Instance*>::Element *L; //light iterator in geometry + Instance *geometry; + }; + + RID instance; + uint64_t last_version; + List<Instance*>::Element *D; // directional light in scenario + + bool shadow_dirty; + + List<PairInfo> geometries; + + Instance *baked_light; + + InstanceLightData() { + + shadow_dirty=true; + D=NULL; + last_version=0; + baked_light=NULL; + } + }; + + struct InstanceGIProbeData : public InstanceBaseData { + + + Instance *owner; + + struct PairInfo { + List<Instance*>::Element *L; //gi probe iterator in geometry + Instance *geometry; + }; + + List<PairInfo> geometries; + + Set<Instance*> lights; + + struct LightCache { + + VS::LightType type; + Transform transform; + Color color; + float energy; + float radius; + float attenuation; + float spot_angle; + float spot_attenuation; + + bool operator==(const LightCache& p_cache) { + + return (type==p_cache.type && + transform==p_cache.transform && + color==p_cache.color && + energy==p_cache.energy && + radius==p_cache.radius && + attenuation==p_cache.attenuation && + spot_angle==p_cache.spot_angle && + spot_attenuation==p_cache.spot_attenuation); + } + + LightCache() { + + type=VS::LIGHT_DIRECTIONAL; + energy=1.0; + radius=1.0; + attenuation=1.0; + spot_angle=1.0; + spot_attenuation=1.0; + + } + + }; + + struct LocalData { + uint16_t pos[3]; + uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights + }; + + struct CompBlockS3TC { + uint32_t offset; //offset in mipmap + uint32_t source_count; //sources + uint32_t sources[16]; //id for each source + uint8_t alpha[8]; //alpha block is pre-computed + }; + + + struct Dynamic { + + Map<RID,LightCache> light_cache; + Map<RID,LightCache> light_cache_changes; + DVector<int> light_data; + DVector<LocalData> local_data; + Vector<Vector<uint32_t> > level_cell_lists; + RID probe_data; + bool enabled; + int bake_dynamic_range; + RasterizerStorage::GIProbeCompression compression; + + Vector< DVector<uint8_t> > mipmaps_3d; + Vector< DVector<CompBlockS3TC> > mipmaps_s3tc; //for s3tc + + int updating_stage; + + int grid_size[3]; + + Transform light_to_cell_xform; + + } dynamic; + + + RID probe_instance; + + + bool invalid; + uint32_t base_version; + + SelfList<InstanceGIProbeData> update_element; + + InstanceGIProbeData() : update_element(this) { + invalid=true; + base_version=0; + } + + }; + + + SelfList<InstanceGIProbeData>::List gi_probe_update_list; + + + Instance *instance_cull_result[MAX_INSTANCE_CULL]; + Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps + Instance *light_cull_result[MAX_LIGHTS_CULLED]; + RID light_instance_cull_result[MAX_LIGHTS_CULLED]; + int light_cull_count; + RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; + int reflection_probe_cull_count; + + + RID_Owner<Instance> instance_owner; + + // from can be mesh, light, area and portal so far. + virtual RID instance_create(); // from can be mesh, light, poly, area and portal so far. + + virtual void instance_set_base(RID p_instance, RID p_base); // from can be mesh, light, poly, area and portal so far. + virtual void instance_set_scenario(RID p_instance, RID p_scenario); // from can be mesh, light, poly, area and portal so far. + virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); + virtual void instance_set_transform(RID p_instance, const Transform& p_transform); + virtual void instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID); + virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight); + virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material); + + virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton); + virtual void instance_set_exterior( RID p_instance, bool p_enabled ); + virtual void instance_set_room( RID p_instance, RID p_room ); + + virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ); + + + // don't use these in a game! + virtual Vector<ObjectID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const; + virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const; + + + virtual void instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled); + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting); + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); + + + virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin); + virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance); + + + _FORCE_INLINE_ void _update_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); + _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); + + _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario); + + void _render_scene(const Transform p_cam_transform, const CameraMatrix& p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + + void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); + void update_dirty_instances(); + + //probes + struct GIProbeDataHeader { + + uint32_t version; + uint32_t cell_subdiv; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t cell_count; + uint32_t leaf_cell_count; + }; + + + struct GIProbeDataCell { + + uint32_t children[8]; + uint32_t albedo; + uint32_t emission; + uint32_t normal; + uint32_t level_alpha; + }; + + enum { + GI_UPDATE_STAGE_CHECK, + GI_UPDATE_STAGE_LIGHTING, + GI_UPDATE_STAGE_UPLOADING, + }; + + void _gi_probe_bake_thread(); + static void _gi_probe_bake_threads(void*); + + volatile bool probe_bake_thread_exit; + Thread *probe_bake_thread; + Semaphore *probe_bake_sem; + Mutex *probe_bake_mutex; + List<Instance*> probe_bake_list; + + bool _render_reflection_probe_step(Instance* p_instance,int p_step); + void _gi_probe_fill_local_data(int p_idx,int p_level,int p_x,int p_y,int p_z,const GIProbeDataCell* p_cell,const GIProbeDataHeader *p_header,InstanceGIProbeData::LocalData *p_local_data,Vector<uint32_t> *prev_cell); + + _FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv); + void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data); + void _bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int p_leaf_count, const InstanceGIProbeData::LightCache& light_cache,int p_sign); + void _bake_gi_probe(Instance *p_probe); + bool _check_gi_probe(Instance *p_gi_probe); + void _setup_gi_probe(Instance *p_instance); + + void render_probes(); + + + bool free(RID p_rid); + + VisualServerScene(); + ~VisualServerScene(); +}; + +#endif // VISUALSERVERSCENE_H diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp new file mode 100644 index 0000000000..558a3e4c23 --- /dev/null +++ b/servers/visual/visual_server_viewport.cpp @@ -0,0 +1,568 @@ +#include "visual_server_viewport.h" +#include "visual_server_global.h" +#include "visual_server_canvas.h" +#include "visual_server_scene.h" +#include "globals.h" + + + +void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { + + /* Camera should always be BEFORE any other 3D */ +#if 0 + bool scenario_draw_canvas_bg=false; + int scenario_canvas_max_layer=0; + + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { + + Scenario *scenario=scenario_owner.get(p_viewport->scenario); + if (scenario->environment.is_valid()) { + if (rasterizer->is_environment(scenario->environment)) { + scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS; + scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER); + } + } + } + + bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); + + + if (scenario_draw_canvas_bg) { + + rasterizer->begin_canvas_bg(); + } + + if (!scenario_draw_canvas_bg && can_draw_3d) { + + _draw_viewport_camera(p_viewport,false); + + } else if (true /*|| !p_viewport->canvas_list.empty()*/){ + + //clear the viewport black because of no camera? i seriously should.. + if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) { + if (p_viewport->transparent_bg) { + rasterizer->clear_viewport(Color(0,0,0,0)); + } + else { + Color cc=clear_color; + if (scenario_draw_canvas_bg) + cc.a=0; + rasterizer->clear_viewport(cc); + } + p_viewport->render_target_clear=false; + } + } +#endif + + if (p_viewport->clear_mode!=VS::VIEWPORT_CLEAR_NEVER) { + VSG::rasterizer->clear_render_target(clear_color); + if (p_viewport->clear_mode==VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { + p_viewport->clear_mode=VS::VIEWPORT_CLEAR_NEVER; + } + } + + + if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) { + + VSG::scene->render_camera(p_viewport->camera,p_viewport->scenario,p_viewport->size,p_viewport->shadow_atlas); + } + + if (!p_viewport->hide_canvas) { + int i=0; + + Map<Viewport::CanvasKey,Viewport::CanvasData*> canvas_map; + + Rect2 clip_rect(0,0,p_viewport->size.x,p_viewport->size.y); + RasterizerCanvas::Light *lights=NULL; + RasterizerCanvas::Light *lights_with_shadow=NULL; + RasterizerCanvas::Light *lights_with_mask=NULL; + Rect2 shadow_rect; + + int light_count=0; + + for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { + + Matrix32 xf = p_viewport->global_transform * E->get().transform; + + VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get().canvas); + + //find lights in canvas + + + for(Set<RasterizerCanvas::Light*>::Element *F=canvas->lights.front();F;F=F->next()) { + + + RasterizerCanvas::Light* cl=F->get(); + if (cl->enabled && cl->texture.is_valid()) { + //not super efficient.. + Size2 tsize(VSG::storage->texture_get_width(cl->texture),VSG::storage->texture_get_height(cl->texture)); + tsize*=cl->scale; + + Vector2 offset=tsize/2.0; + cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize); + cl->xform_cache=xf * cl->xform; + + + if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) { + + cl->filter_next_ptr=lights; + lights=cl; + cl->texture_cache=NULL; + Matrix32 scale; + scale.scale(cl->rect_cache.size); + scale.elements[2]=cl->rect_cache.pos; + cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse(); + cl->light_shader_pos=cl->xform_cache[2]; + if (cl->shadow_buffer.is_valid()) { + + cl->shadows_next_ptr=lights_with_shadow; + if (lights_with_shadow==NULL) { + shadow_rect = cl->xform_cache.xform(cl->rect_cache); + } else { + shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) ); + } + lights_with_shadow=cl; + cl->radius_cache=cl->rect_cache.size.length(); + + } + if (cl->mode==VS::CANVAS_LIGHT_MODE_MASK) { + cl->mask_next_ptr=lights_with_mask; + lights_with_mask=cl; + } + + light_count++; + } + + VSG::canvas_render->light_internal_update(cl->light_internal,cl); + + } + } + + //print_line("lights: "+itos(light_count)); + canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get(); + + } + + if (lights_with_shadow) { + //update shadows if any + + RasterizerCanvas::LightOccluderInstance * occluders=NULL; + + //make list of occluders + for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { + + VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get().canvas); + Matrix32 xf = p_viewport->global_transform * E->get().transform; + + + 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 (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) { + + F->get()->next=occluders; + occluders=F->get(); + + } + } + } + //update the light shadowmaps with them + RasterizerCanvas::Light *light=lights_with_shadow; + while(light) { + + VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache); + light=light->shadows_next_ptr; + } + + // VSG::canvas_render->reset_canvas(); + } + + VSG::rasterizer->restore_render_target(); + + +#if 0 + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) { + + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + + } +#endif + + + for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) { + + VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get()->canvas); + + // print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); + //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); + Matrix32 xform = p_viewport->global_transform * E->get()->transform; + + RasterizerCanvas::Light *canvas_lights=NULL; + + RasterizerCanvas::Light *ptr=lights; + while(ptr) { + if (E->get()->layer>=ptr->layer_min && E->get()->layer<=ptr->layer_max) { + ptr->next_ptr=canvas_lights; + canvas_lights=ptr; + } + ptr=ptr->filter_next_ptr; + } + + VSG::canvas->render_canvas( canvas,xform,canvas_lights,lights_with_mask,clip_rect ); + i++; +#if 0 + if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } +#endif + + + } +#if 0 + if (scenario_draw_canvas_bg) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } +#endif + + //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); + } + + + +} + +void VisualServerViewport::draw_viewports() { + + //sort viewports + + + //draw viewports + + clear_color=GLOBAL_DEF("rendering/viewport/default_clear_color",Color(0.5,0.5,0.5)); + + + active_viewports.sort_custom<ViewportSort>(); + + for(int i=0;i<active_viewports.size();i++) { + + Viewport *vp = active_viewports[i]; + + if (vp->update_mode==VS::VIEWPORT_UPDATE_DISABLED) + continue; + + ERR_CONTINUE( !vp->render_target.is_valid() ); + + bool visible = vp->viewport_to_screen_rect!=Rect2() || vp->update_mode==VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode==VS::VIEWPORT_UPDATE_ONCE; + + if (!visible) + continue; + + VSG::rasterizer->set_current_render_target(vp->render_target); + _draw_viewport(vp); + + if (vp->viewport_to_screen_rect!=Rect2()) { + //copy to screen if set as such + VSG::rasterizer->set_current_render_target(RID()); + VSG::rasterizer->blit_render_target_to_screen(vp->render_target,vp->viewport_to_screen_rect,vp->viewport_to_screen); + } + + if (vp->update_mode==VS::VIEWPORT_UPDATE_ONCE) { + vp->update_mode=VS::VIEWPORT_UPDATE_DISABLED; + } + } +} + + +RID VisualServerViewport::viewport_create() { + + Viewport * viewport = memnew( Viewport ); + + RID rid = viewport_owner.make_rid(viewport); + + viewport->self=rid; + viewport->hide_scenario=false; + viewport->hide_canvas=false; + viewport->render_target=VSG::storage->render_target_create(); + viewport->shadow_atlas=VSG::scene_render->shadow_atlas_create(); + + return rid; + +} + +void VisualServerViewport::viewport_set_size(RID p_viewport,int p_width,int p_height){ + + ERR_FAIL_COND(p_width<0 && p_height<0); + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + + viewport->size=Size2(p_width,p_height); + VSG::storage->render_target_set_size(viewport->render_target,p_width,p_height); + + +} + +void VisualServerViewport::viewport_set_active(RID p_viewport,bool p_active) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_active) { + ERR_FAIL_COND(active_viewports.find(viewport)!=-1);//already active + active_viewports.push_back(viewport); + } else { + active_viewports.erase(viewport); + } + + +} + +void VisualServerViewport::viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->parent=p_parent_viewport; +} + +void VisualServerViewport::viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->clear_mode=p_clear_mode; + +} + + +void VisualServerViewport::viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect,int p_screen){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->viewport_to_screen_rect=p_rect; + viewport->viewport_to_screen=p_screen; +} +void VisualServerViewport::viewport_detach(RID p_viewport){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->viewport_to_screen_rect=Rect2(); + viewport->viewport_to_screen=0; + +} + +void VisualServerViewport::viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->update_mode=p_mode; + +} +void VisualServerViewport::viewport_set_vflip(RID p_viewport,bool p_enable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_VFLIP,p_enable); + +} + +RID VisualServerViewport::viewport_get_texture(RID p_viewport) const{ + + const Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND_V(!viewport,RID()); + + return VSG::storage->render_target_get_texture(viewport->render_target); + +} + +void VisualServerViewport::viewport_set_hide_scenario(RID p_viewport,bool p_hide){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_scenario=p_hide; +} +void VisualServerViewport::viewport_set_hide_canvas(RID p_viewport,bool p_hide){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_canvas=p_hide; +} +void VisualServerViewport::viewport_set_disable_environment(RID p_viewport,bool p_disable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + viewport->disable_environment=p_disable; +} + +void VisualServerViewport::viewport_set_disable_3d(RID p_viewport,bool p_disable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + viewport->disable_3d=p_disable; + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_NO_3D,p_disable); +} + +void VisualServerViewport::viewport_attach_camera(RID p_viewport,RID p_camera){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->camera=p_camera; +} +void VisualServerViewport::viewport_set_scenario(RID p_viewport,RID p_scenario){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->scenario=p_scenario; +} +void VisualServerViewport::viewport_attach_canvas(RID p_viewport,RID p_canvas){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(viewport->canvas_map.has(p_canvas)); + VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + canvas->viewports.insert(p_viewport); + viewport->canvas_map[p_canvas]=Viewport::CanvasData(); + viewport->canvas_map[p_canvas].layer=0; + viewport->canvas_map[p_canvas].canvas=canvas; + +} + +void VisualServerViewport::viewport_remove_canvas(RID p_viewport,RID p_canvas){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + viewport->canvas_map.erase(p_canvas); + canvas->viewports.erase(p_viewport); + +} +void VisualServerViewport::viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].transform=p_offset; + +} +void VisualServerViewport::viewport_set_transparent_background(RID p_viewport,bool p_enabled){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_TRANSPARENT,p_enabled); + +} + +void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->global_transform=p_transform; + +} +void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].layer=p_layer; + +} + +void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport,int p_size) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->shadow_atlas_size=p_size; + + VSG::scene_render->shadow_atlas_set_size( viewport->shadow_atlas, viewport->shadow_atlas_size); + +} + +void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::scene_render->shadow_atlas_set_quadrant_subdivision( viewport->shadow_atlas, p_quadrant, p_subdiv); + +} + +void VisualServerViewport::viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_msaa(viewport->render_target,p_msaa); +} + +void VisualServerViewport::viewport_set_hdr(RID p_viewport,bool p_enabled) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_HDR,p_enabled); + +} + +bool VisualServerViewport::free(RID p_rid) { + + if (viewport_owner.owns(p_rid)) { + + Viewport * viewport = viewport_owner.getornull(p_rid); + + + VSG::storage->free( viewport->render_target ); + VSG::scene_render->free( viewport->shadow_atlas ); + + while(viewport->canvas_map.front()) { + viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key()); + } + + viewport_set_scenario(p_rid,RID()); + active_viewports.erase(viewport); + + viewport_owner.free(p_rid); + memdelete(viewport); + + + return true; + } + + return false; + +} + +VisualServerViewport::VisualServerViewport() +{ + +} diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h new file mode 100644 index 0000000000..3b14ee2b1c --- /dev/null +++ b/servers/visual/visual_server_viewport.h @@ -0,0 +1,150 @@ +#ifndef VISUALSERVERVIEWPORT_H +#define VISUALSERVERVIEWPORT_H + +#include "servers/visual_server.h" +#include "rasterizer.h" +#include "self_list.h" + +class VisualServerViewport { +public: + + struct CanvasBase : public RID_Data { + + + }; + + + + struct Viewport : public RID_Data { + + RID self; + RID parent; + + Size2i size; + RID camera; + RID scenario; + + VS::ViewportUpdateMode update_mode; + RID render_target; + RID render_target_texture; + + int viewport_to_screen; + Rect2 viewport_to_screen_rect; + + bool hide_scenario; + bool hide_canvas; + bool disable_environment; + bool disable_3d; + + RID shadow_atlas; + int shadow_atlas_size; + + + VS::ViewportClearMode clear_mode; + + bool rendered_in_prev_frame; + + struct CanvasKey { + + int layer; + RID canvas; + bool operator<(const CanvasKey& p_canvas) const { if (layer==p_canvas.layer) return canvas < p_canvas.canvas; return layer<p_canvas.layer; } + CanvasKey() { layer=0; } + CanvasKey(const RID& p_canvas, int p_layer) { canvas=p_canvas; layer=p_layer; } + }; + + struct CanvasData { + + CanvasBase *canvas; + Matrix32 transform; + int layer; + }; + + Matrix32 global_transform; + + Map<RID,CanvasData> canvas_map; + + Viewport() { + update_mode=VS::VIEWPORT_UPDATE_WHEN_VISIBLE; + clear_mode=VS::VIEWPORT_CLEAR_ALWAYS; + rendered_in_prev_frame=false; + disable_environment=false; + viewport_to_screen=0; + shadow_atlas_size=0; + disable_3d=false; + + } + }; + + mutable RID_Owner<Viewport> viewport_owner; + + + struct ViewportSort { + _FORCE_INLINE_ bool operator()(const Viewport*p_left,const Viewport* p_right) const { + + bool left_to_screen = p_left->viewport_to_screen_rect.size!=Size2(); + bool right_to_screen = p_right->viewport_to_screen_rect.size!=Size2(); + + if (left_to_screen==right_to_screen) { + + return p_left->parent==p_right->self; + } else { + return right_to_screen; + } + } + }; + + + Vector<Viewport*> active_viewports; +private: + Color clear_color; + void _draw_viewport(Viewport *p_viewport); +public: + + + RID viewport_create(); + + void viewport_set_size(RID p_viewport,int p_width,int p_height); + + void viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect=Rect2(),int p_screen=0); + void viewport_detach(RID p_viewport); + + void viewport_set_active(RID p_viewport,bool p_active); + void viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport); + void viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode); + void viewport_set_vflip(RID p_viewport,bool p_enable); + + + void viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode); + + RID viewport_get_texture(RID p_viewport) const; + + void viewport_set_hide_scenario(RID p_viewport,bool p_hide); + void viewport_set_hide_canvas(RID p_viewport,bool p_hide); + void viewport_set_disable_environment(RID p_viewport,bool p_disable); + void viewport_set_disable_3d(RID p_viewport,bool p_disable); + + void viewport_attach_camera(RID p_viewport,RID p_camera); + void viewport_set_scenario(RID p_viewport,RID p_scenario); + void viewport_attach_canvas(RID p_viewport,RID p_canvas); + void viewport_remove_canvas(RID p_viewport,RID p_canvas); + void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset); + void viewport_set_transparent_background(RID p_viewport,bool p_enabled); + + void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform); + void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer); + + void viewport_set_shadow_atlas_size(RID p_viewport,int p_size); + void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv); + + void viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa); + void viewport_set_hdr(RID p_viewport,bool p_enabled); + + void draw_viewports(); + + bool free(RID p_rid); + + VisualServerViewport(); +}; + +#endif // VISUALSERVERVIEWPORT_H diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp deleted file mode 100644 index e673158ba2..0000000000 --- a/servers/visual/visual_server_wrap_mt.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "visual_server_wrap_mt.h" -#include "os/os.h" -#include "globals.h" -void VisualServerWrapMT::thread_exit() { - - exit=true; -} - -void VisualServerWrapMT::thread_draw() { - - - draw_mutex->lock(); - - draw_pending--; - bool draw=(draw_pending==0);// only draw when no more flushes are pending - - draw_mutex->unlock(); - - if (draw) { - - visual_server->draw(); - } - -} - -void VisualServerWrapMT::thread_flush() { - - - draw_mutex->lock(); - - draw_pending--; - - draw_mutex->unlock(); - -} - - - -void VisualServerWrapMT::_thread_callback(void *_instance) { - - VisualServerWrapMT *vsmt = reinterpret_cast<VisualServerWrapMT*>(_instance); - - - vsmt->thread_loop(); -} - -void VisualServerWrapMT::thread_loop() { - - server_thread=Thread::get_caller_ID(); - - OS::get_singleton()->make_rendering_thread(); - - visual_server->init(); - - exit=false; - draw_thread_up=true; - while(!exit) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush_one(); - } - - command_queue.flush_all(); // flush all - - visual_server->finish(); - -} - - -/* EVENT QUEUING */ - -void VisualServerWrapMT::sync() { - - if (create_thread) { - - /* TODO: sync with the thread */ - - /* - ERR_FAIL_COND(!draw_mutex); - draw_mutex->lock(); - draw_pending++; //cambiar por un saferefcount - draw_mutex->unlock(); - */ - //command_queue.push( this, &VisualServerWrapMT::thread_flush); - } else { - - command_queue.flush_all(); //flush all pending from other threads - } - -} - -void VisualServerWrapMT::draw() { - - - if (create_thread) { - - /* TODO: Make it draw - ERR_FAIL_COND(!draw_mutex); - draw_mutex->lock(); - draw_pending++; //cambiar por un saferefcount - draw_mutex->unlock(); - - command_queue.push( this, &VisualServerWrapMT::thread_draw); - */ - } else { - - visual_server->draw(); - } -} - - -void VisualServerWrapMT::init() { - - if (create_thread) { - - draw_mutex = Mutex::create(); - print_line("CREATING RENDER THREAD"); - OS::get_singleton()->release_rendering_thread(); - if (create_thread) { - thread = Thread::create( _thread_callback, this ); - print_line("STARTING RENDER THREAD"); - } - while(!draw_thread_up) { - OS::get_singleton()->delay_usec(1000); - } - print_line("DONE RENDER THREAD"); - } else { - - visual_server->init(); - } - -} - -void VisualServerWrapMT::finish() { - - - if (thread) { - - command_queue.push( this, &VisualServerWrapMT::thread_exit); - Thread::wait_to_finish( thread ); - memdelete(thread); - - - texture_free_cached_ids(); - mesh_free_cached_ids(); - - thread=NULL; - } else { - visual_server->finish(); - } - - if (draw_mutex) - memdelete(draw_mutex); - -} - - -VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) { - - visual_server=p_contained; - create_thread=p_create_thread; - thread=NULL; - draw_mutex=NULL; - draw_pending=0; - draw_thread_up=false; - alloc_mutex=Mutex::create(); - texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",5); - mesh_pool_max_size=GLOBAL_DEF("core/rid_pool_prealloc",20); - if (!p_create_thread) { - server_thread=Thread::get_caller_ID(); - } else { - server_thread=0; - } -} - - -VisualServerWrapMT::~VisualServerWrapMT() { - - memdelete(visual_server); - memdelete(alloc_mutex); - //finish(); - -} - - diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h deleted file mode 100644 index 56b63f3429..0000000000 --- a/servers/visual/visual_server_wrap_mt.h +++ /dev/null @@ -1,739 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef VISUAL_SERVER_WRAP_MT_H -#define VISUAL_SERVER_WRAP_MT_H - - -#include "servers/visual_server.h" -#include "command_queue_mt.h" -#include "os/thread.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class VisualServerWrapMT : public VisualServer { - - // the real visual server - mutable VisualServer *visual_server; - - mutable CommandQueueMT command_queue; - - static void _thread_callback(void *_instance); - void thread_loop(); - - Thread::ID server_thread; - volatile bool exit; - Thread *thread; - volatile bool draw_thread_up; - bool create_thread; - - Mutex *draw_mutex; - int draw_pending; - void thread_draw(); - void thread_flush(); - - void thread_exit(); - - Mutex*alloc_mutex; - - - int texture_pool_max_size; - List<RID> texture_id_pool; - - int mesh_pool_max_size; - List<RID> mesh_id_pool; - -//#define DEBUG_SYNC - -#ifdef DEBUG_SYNC -#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); -#else -#define SYNC_DEBUG -#endif - -public: - -#define ServerName VisualServer -#define ServerNameWrapMT VisualServerWrapMT -#define server_name visual_server -#include "servers/server_wrap_mt_common.h" - - //FUNC0R(RID,texture_create); - FUNCRID(texture); - FUNC5(texture_allocate,RID,int,int,Image::Format,uint32_t); - FUNC3(texture_set_data,RID,const Image&,CubeMapSide); - FUNC2RC(Image,texture_get_data,RID,CubeMapSide); - FUNC2(texture_set_flags,RID,uint32_t); - FUNC1RC(Image::Format,texture_get_format,RID); - FUNC1RC(uint32_t,texture_get_flags,RID); - FUNC1RC(uint32_t,texture_get_width,RID); - FUNC1RC(uint32_t,texture_get_height,RID); - FUNC3(texture_set_size_override,RID,int,int); - FUNC1RC(bool,texture_can_stream,RID); - FUNC3C(texture_set_reload_hook,RID,ObjectID,const StringName&); - - FUNC2(texture_set_path,RID,const String&); - FUNC1RC(String,texture_get_path,RID); - - FUNC1(texture_set_shrink_all_x2_on_set_data,bool); - - virtual void texture_debug_usage(List<TextureInfo> *r_info) { - //pass directly, should lock the server anyway - visual_server->texture_debug_usage(r_info); - } - - - /* SHADER API */ - - FUNC1R(RID,shader_create,ShaderMode); - FUNC2(shader_set_mode,RID,ShaderMode); - FUNC1RC(ShaderMode,shader_get_mode,RID); - FUNC7(shader_set_code,RID,const String&,const String&,const String&,int,int,int); - FUNC1RC(String,shader_get_vertex_code,RID); - FUNC1RC(String,shader_get_fragment_code,RID); - FUNC1RC(String,shader_get_light_code,RID); - FUNC2SC(shader_get_param_list,RID,List<PropertyInfo>*); - - FUNC3(shader_set_default_texture_param,RID,const StringName&,RID); - FUNC2RC(RID,shader_get_default_texture_param,RID,const StringName&); - - - /*virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) { - if (Thread::get_caller_ID()!=server_thread) { - command_queue.push_and_sync( visual_server, &VisualServer::shader_get_param_list,p_shader,p_param_list); - } else { - visual_server->m_type(p1, p2, p3, p4, p5); - } - }*/ - -// virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list); - - - /* COMMON MATERIAL API */ - - FUNC0R(RID,material_create); - FUNC2(material_set_shader,RID,RID); - FUNC1RC(RID,material_get_shader,RID); - - FUNC3(material_set_param,RID,const StringName&,const Variant&); - FUNC2RC(Variant,material_get_param,RID,const StringName&); - - FUNC3(material_set_flag,RID,MaterialFlag,bool); - FUNC2RC(bool,material_get_flag,RID,MaterialFlag); - - FUNC2(material_set_depth_draw_mode,RID,MaterialDepthDrawMode); - FUNC1RC(MaterialDepthDrawMode,material_get_depth_draw_mode,RID); - - FUNC2(material_set_blend_mode,RID,MaterialBlendMode); - FUNC1RC(MaterialBlendMode,material_get_blend_mode,RID); - - FUNC2(material_set_line_width,RID,float); - FUNC1RC(float,material_get_line_width,RID); - - /* FIXED MATERIAL */ - - - FUNC0R(RID,fixed_material_create); - - FUNC3(fixed_material_set_flag,RID, FixedMaterialFlags , bool ); - FUNC2RC(bool, fixed_material_get_flag,RID, FixedMaterialFlags); - - FUNC3(fixed_material_set_param,RID, FixedMaterialParam, const Variant& ); - FUNC2RC(Variant, fixed_material_get_param,RID ,FixedMaterialParam); - - FUNC3(fixed_material_set_texture,RID ,FixedMaterialParam, RID ); - FUNC2RC(RID, fixed_material_get_texture,RID,FixedMaterialParam); - - - - FUNC3(fixed_material_set_texcoord_mode,RID,FixedMaterialParam, FixedMaterialTexCoordMode ); - FUNC2RC(FixedMaterialTexCoordMode, fixed_material_get_texcoord_mode,RID,FixedMaterialParam); - - FUNC2(fixed_material_set_light_shader,RID,FixedMaterialLightShader); - FUNC1RC(FixedMaterialLightShader, fixed_material_get_light_shader,RID); - - FUNC2(fixed_material_set_uv_transform,RID,const Transform&); - FUNC1RC(Transform, fixed_material_get_uv_transform,RID); - - FUNC2(fixed_material_set_point_size,RID ,float); - FUNC1RC(float,fixed_material_get_point_size,RID); - - /* SURFACE API */ - FUNCRID(mesh); - - FUNC2(mesh_set_morph_target_count,RID,int); - FUNC1RC(int,mesh_get_morph_target_count,RID); - - - FUNC2(mesh_set_morph_target_mode,RID,MorphTargetMode); - FUNC1RC(MorphTargetMode,mesh_get_morph_target_mode,RID); - - FUNC2(mesh_add_custom_surface,RID,const Variant&); //this is used by each platform in a different way - - FUNC5(mesh_add_surface,RID,PrimitiveType,const Array&,const Array&,bool); - FUNC2RC(Array,mesh_get_surface_arrays,RID,int); - FUNC2RC(Array,mesh_get_surface_morph_arrays,RID,int); - - FUNC4(mesh_surface_set_material,RID, int, RID,bool); - FUNC2RC(RID,mesh_surface_get_material,RID, int); - - FUNC2RC(int,mesh_surface_get_array_len,RID, int); - FUNC2RC(int,mesh_surface_get_array_index_len,RID, int); - FUNC2RC(uint32_t,mesh_surface_get_format,RID, int); - FUNC2RC(PrimitiveType,mesh_surface_get_primitive_type,RID, int); - - FUNC2(mesh_remove_surface,RID,int); - FUNC1RC(int,mesh_get_surface_count,RID); - FUNC1(mesh_clear,RID); - - - FUNC2(mesh_set_custom_aabb,RID,const AABB&); - FUNC1RC(AABB,mesh_get_custom_aabb,RID); - - - /* MULTIMESH API */ - - FUNC0R(RID,multimesh_create); - FUNC2(multimesh_set_instance_count,RID,int); - FUNC1RC(int,multimesh_get_instance_count,RID); - - FUNC2(multimesh_set_mesh,RID,RID); - FUNC2(multimesh_set_aabb,RID,const AABB&); - FUNC3(multimesh_instance_set_transform,RID,int,const Transform&); - FUNC3(multimesh_instance_set_color,RID,int,const Color&); - - FUNC1RC(RID,multimesh_get_mesh,RID); - FUNC2RC(AABB,multimesh_get_aabb,RID,const AABB&); - FUNC2RC(Transform,multimesh_instance_get_transform,RID,int); - FUNC2RC(Color,multimesh_instance_get_color,RID,int); - - FUNC2(multimesh_set_visible_instances,RID,int); - FUNC1RC(int,multimesh_get_visible_instances,RID); - - /* IMMEDIATE API */ - - - FUNC0R(RID,immediate_create); - FUNC3(immediate_begin,RID,PrimitiveType,RID); - FUNC2(immediate_vertex,RID,const Vector3&); - FUNC2(immediate_normal,RID,const Vector3&); - FUNC2(immediate_tangent,RID,const Plane&); - FUNC2(immediate_color,RID,const Color&); - FUNC2(immediate_uv,RID,const Vector2&); - FUNC2(immediate_uv2,RID,const Vector2&); - FUNC1(immediate_end,RID); - FUNC1(immediate_clear,RID); - FUNC2(immediate_set_material,RID,RID); - FUNC1RC(RID,immediate_get_material,RID); - - - /* PARTICLES API */ - - FUNC0R(RID,particles_create); - - FUNC2(particles_set_amount,RID, int ); - FUNC1RC(int,particles_get_amount,RID); - - FUNC2(particles_set_emitting,RID, bool ); - FUNC1RC(bool,particles_is_emitting,RID); - - FUNC2(particles_set_visibility_aabb,RID, const AABB&); - FUNC1RC(AABB,particles_get_visibility_aabb,RID); - - FUNC2(particles_set_emission_half_extents,RID, const Vector3&); - FUNC1RC(Vector3,particles_get_emission_half_extents,RID); - - FUNC2(particles_set_emission_base_velocity,RID, const Vector3&); - FUNC1RC(Vector3,particles_get_emission_base_velocity,RID); - - FUNC2(particles_set_emission_points,RID, const DVector<Vector3>& ); - FUNC1RC(DVector<Vector3>,particles_get_emission_points,RID); - - FUNC2(particles_set_gravity_normal,RID, const Vector3& ); - FUNC1RC(Vector3,particles_get_gravity_normal,RID); - - FUNC3(particles_set_variable,RID, ParticleVariable ,float); - FUNC2RC(float,particles_get_variable,RID, ParticleVariable ); - - FUNC3(particles_set_randomness,RID, ParticleVariable ,float); - FUNC2RC(float,particles_get_randomness,RID, ParticleVariable ); - - FUNC3(particles_set_color_phase_pos,RID, int , float); - FUNC2RC(float,particles_get_color_phase_pos,RID, int ); - - FUNC2(particles_set_color_phases,RID, int ); - FUNC1RC(int,particles_get_color_phases,RID); - - FUNC3(particles_set_color_phase_color,RID, int , const Color& ); - FUNC2RC(Color,particles_get_color_phase_color,RID, int ); - - FUNC2(particles_set_attractors,RID, int); - FUNC1RC(int,particles_get_attractors,RID); - - FUNC3(particles_set_attractor_pos,RID, int, const Vector3&); - FUNC2RC(Vector3,particles_get_attractor_pos,RID,int); - - FUNC3(particles_set_attractor_strength,RID, int, float); - FUNC2RC(float,particles_get_attractor_strength,RID,int); - - FUNC3(particles_set_material,RID, RID,bool); - FUNC1RC(RID,particles_get_material,RID); - - FUNC2(particles_set_height_from_velocity,RID, bool); - FUNC1RC(bool,particles_has_height_from_velocity,RID); - - FUNC2(particles_set_use_local_coordinates,RID, bool); - FUNC1RC(bool,particles_is_using_local_coordinates,RID); - - - /* Light API */ - - FUNC1R(RID,light_create,LightType); - FUNC1RC(LightType,light_get_type,RID); - - FUNC3(light_set_color,RID,LightColor , const Color& ); - FUNC2RC(Color,light_get_color,RID,LightColor ); - - - FUNC2(light_set_shadow,RID,bool ); - FUNC1RC(bool,light_has_shadow,RID); - - FUNC2(light_set_volumetric,RID,bool ); - FUNC1RC(bool,light_is_volumetric,RID); - - FUNC2(light_set_projector,RID,RID ); - FUNC1RC(RID,light_get_projector,RID); - - FUNC3(light_set_param,RID, LightParam , float ); - FUNC2RC(float,light_get_param,RID, LightParam ); - - FUNC2(light_set_operator,RID,LightOp); - FUNC1RC(LightOp,light_get_operator,RID); - - FUNC2(light_omni_set_shadow_mode,RID,LightOmniShadowMode); - FUNC1RC(LightOmniShadowMode,light_omni_get_shadow_mode,RID); - - FUNC2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode); - FUNC1RC(LightDirectionalShadowMode,light_directional_get_shadow_mode,RID); - FUNC3(light_directional_set_shadow_param,RID,LightDirectionalShadowParam, float ); - FUNC2RC(float,light_directional_get_shadow_param,RID,LightDirectionalShadowParam ); - - - /* SKELETON API */ - - FUNC0R(RID,skeleton_create); - FUNC2(skeleton_resize,RID,int ); - FUNC1RC(int,skeleton_get_bone_count,RID) ; - FUNC3(skeleton_bone_set_transform,RID,int, const Transform&); - FUNC2R(Transform,skeleton_bone_get_transform,RID,int ); - - /* ROOM API */ - - FUNC0R(RID,room_create); - FUNC2(room_set_bounds,RID, const BSP_Tree&); - FUNC1RC(BSP_Tree,room_get_bounds,RID); - - /* PORTAL API */ - - FUNC0R(RID,portal_create); - FUNC2(portal_set_shape,RID,const Vector<Point2>&); - FUNC1RC(Vector<Point2>,portal_get_shape,RID); - FUNC2(portal_set_enabled,RID, bool); - FUNC1RC(bool,portal_is_enabled,RID); - FUNC2(portal_set_disable_distance,RID, float); - FUNC1RC(float,portal_get_disable_distance,RID); - FUNC2(portal_set_disabled_color,RID, const Color&); - FUNC1RC(Color,portal_get_disabled_color,RID); - FUNC2(portal_set_connect_range,RID, float); - FUNC1RC(float,portal_get_connect_range,RID); - - - FUNC0R(RID,baked_light_create); - FUNC2(baked_light_set_mode,RID,BakedLightMode); - FUNC1RC(BakedLightMode,baked_light_get_mode,RID); - - FUNC2(baked_light_set_octree,RID,DVector<uint8_t>); - FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID); - - FUNC2(baked_light_set_light,RID,DVector<uint8_t>); - FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID); - - FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&); - FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID); - - FUNC2(baked_light_set_lightmap_multiplier,RID,float); - FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); - - FUNC3(baked_light_add_lightmap,RID,RID,int); - FUNC1(baked_light_clear_lightmaps,RID); - - FUNC2(baked_light_set_realtime_color_enabled, RID, const bool); - FUNC1RC(bool, baked_light_get_realtime_color_enabled, RID); - - FUNC2(baked_light_set_realtime_color, RID, const Color&); - FUNC1RC(Color, baked_light_get_realtime_color, RID); - - FUNC2(baked_light_set_realtime_energy, RID, const float); - FUNC1RC(float, baked_light_get_realtime_energy, RID); - - FUNC0R(RID,baked_light_sampler_create); - - FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); - FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); - - FUNC2(baked_light_sampler_set_resolution,RID,int); - FUNC1RC(int,baked_light_sampler_get_resolution,RID); - - /* CAMERA API */ - - FUNC0R(RID,camera_create); - FUNC4(camera_set_perspective,RID,float , float , float ); - FUNC4(camera_set_orthogonal,RID,float, float , float ); - FUNC2(camera_set_transform,RID,const Transform& ); - - FUNC2(camera_set_visible_layers,RID,uint32_t); - FUNC1RC(uint32_t,camera_get_visible_layers,RID); - - FUNC2(camera_set_environment,RID,RID); - FUNC1RC(RID,camera_get_environment,RID); - - - FUNC2(camera_set_use_vertical_aspect,RID,bool); - FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool); - - - /* VIEWPORT API */ - - FUNC0R(RID,viewport_create); - - FUNC2(viewport_attach_to_screen,RID,int ); - FUNC1(viewport_detach,RID); - - FUNC2(viewport_set_as_render_target,RID,bool); - FUNC2(viewport_set_render_target_update_mode,RID,RenderTargetUpdateMode); - FUNC1RC(RenderTargetUpdateMode,viewport_get_render_target_update_mode,RID); - FUNC1RC(RID,viewport_get_render_target_texture,RID); - - FUNC2(viewport_set_render_target_vflip,RID,bool); - FUNC1RC(bool,viewport_get_render_target_vflip,RID); - FUNC2(viewport_set_render_target_to_screen_rect,RID,const Rect2&); - - FUNC2(viewport_set_render_target_clear_on_new_frame,RID,bool); - FUNC1RC(bool,viewport_get_render_target_clear_on_new_frame,RID); - FUNC1(viewport_render_target_clear,RID); - - FUNC1(viewport_queue_screen_capture,RID); - FUNC1RC(Image,viewport_get_screen_capture,RID); - - FUNC2(viewport_set_rect,RID,const ViewportRect&); - FUNC1RC(ViewportRect,viewport_get_rect,RID); - - FUNC2(viewport_set_hide_scenario,RID,bool ); - FUNC2(viewport_set_hide_canvas,RID,bool ); - FUNC2(viewport_attach_camera,RID,RID ); - FUNC2(viewport_set_scenario,RID,RID ); - FUNC2(viewport_set_disable_environment,RID,bool ); - - FUNC1RC(RID,viewport_get_attached_camera,RID); - FUNC1RC(RID,viewport_get_scenario,RID ); - FUNC2(viewport_attach_canvas,RID,RID); - FUNC2(viewport_remove_canvas,RID,RID); - FUNC3(viewport_set_canvas_transform,RID,RID,const Matrix32&); - FUNC2RC(Matrix32,viewport_get_canvas_transform,RID,RID); - FUNC2(viewport_set_global_canvas_transform,RID,const Matrix32&); - FUNC1RC(Matrix32,viewport_get_global_canvas_transform,RID); - FUNC3(viewport_set_canvas_layer,RID,RID ,int); - FUNC2(viewport_set_transparent_background,RID,bool); - FUNC1RC(bool,viewport_has_transparent_background,RID); - - - /* ENVIRONMENT API */ - - FUNC0R(RID,environment_create); - - FUNC2(environment_set_background,RID,EnvironmentBG); - FUNC1RC(EnvironmentBG,environment_get_background,RID); - - FUNC3(environment_set_background_param,RID,EnvironmentBGParam, const Variant&); - FUNC2RC(Variant,environment_get_background_param,RID,EnvironmentBGParam ); - - FUNC3(environment_set_enable_fx,RID,EnvironmentFx,bool); - FUNC2RC(bool,environment_is_fx_enabled,RID,EnvironmentFx); - - - FUNC3(environment_fx_set_param,RID,EnvironmentFxParam,const Variant&); - FUNC2RC(Variant,environment_fx_get_param,RID,EnvironmentFxParam); - - - /* SCENARIO API */ - - FUNC0R(RID,scenario_create); - - FUNC2(scenario_set_debug,RID,ScenarioDebugMode); - FUNC2(scenario_set_environment,RID, RID); - FUNC2RC(RID,scenario_get_environment,RID, RID); - FUNC2(scenario_set_fallback_environment,RID, RID); - - - /* INSTANCING API */ - - FUNC0R(RID,instance_create); - - FUNC2(instance_set_base,RID, RID); - FUNC1RC(RID,instance_get_base,RID); - - FUNC2(instance_set_scenario,RID, RID); - FUNC1RC(RID,instance_get_scenario,RID); - - FUNC2(instance_set_layer_mask,RID, uint32_t); - FUNC1RC(uint32_t,instance_get_layer_mask,RID); - - FUNC1RC(AABB,instance_get_base_aabb,RID); - - FUNC2(instance_attach_object_instance_ID,RID,uint32_t); - FUNC1RC(uint32_t,instance_get_object_instance_ID,RID); - - FUNC2(instance_attach_skeleton,RID,RID); - FUNC1RC(RID,instance_get_skeleton,RID); - - FUNC3(instance_set_morph_target_weight,RID,int, float); - FUNC2RC(float,instance_get_morph_target_weight,RID,int); - - FUNC3(instance_set_surface_material,RID,int, RID); - - FUNC2(instance_set_transform,RID, const Transform&); - FUNC1RC(Transform,instance_get_transform,RID); - - FUNC2(instance_set_exterior,RID, bool ); - FUNC1RC(bool,instance_is_exterior,RID); - - FUNC2(instance_set_room,RID, RID ); - FUNC1RC(RID,instance_get_room,RID ) ; - - FUNC2(instance_set_extra_visibility_margin,RID, real_t ); - FUNC1RC(real_t,instance_get_extra_visibility_margin,RID ); - - FUNC2RC(Vector<RID>,instances_cull_aabb,const AABB& , RID ); - FUNC3RC(Vector<RID>,instances_cull_ray,const Vector3& ,const Vector3&, RID ); - FUNC2RC(Vector<RID>,instances_cull_convex,const Vector<Plane>& , RID ); - - FUNC3(instance_geometry_set_flag,RID,InstanceFlags ,bool ); - FUNC2RC(bool,instance_geometry_get_flag,RID,InstanceFlags ); - - FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting); - FUNC1RC(ShadowCastingSetting, instance_geometry_get_cast_shadows_setting, RID); - - FUNC2(instance_geometry_set_material_override,RID, RID ); - FUNC1RC(RID,instance_geometry_get_material_override,RID); - - FUNC3(instance_geometry_set_draw_range,RID,float ,float); - FUNC1RC(float,instance_geometry_get_draw_range_max,RID); - FUNC1RC(float,instance_geometry_get_draw_range_min,RID); - - FUNC2(instance_geometry_set_baked_light,RID, RID ); - FUNC1RC(RID,instance_geometry_get_baked_light,RID); - - FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); - FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); - - FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); - FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); - - FUNC2(instance_light_set_enabled,RID,bool); - FUNC1RC(bool,instance_light_is_enabled,RID); - - /* CANVAS (2D) */ - - FUNC0R(RID,canvas_create); - FUNC3(canvas_set_item_mirroring,RID,RID,const Point2&); - FUNC2RC(Point2,canvas_get_item_mirroring,RID,RID); - FUNC2(canvas_set_modulate,RID,const Color&); - - - FUNC0R(RID,canvas_item_create); - - FUNC2(canvas_item_set_parent,RID,RID ); - FUNC1RC(RID,canvas_item_get_parent,RID); - - FUNC2(canvas_item_set_visible,RID,bool ); - FUNC1RC(bool,canvas_item_is_visible,RID); - - FUNC2(canvas_item_set_blend_mode,RID,MaterialBlendMode ); - FUNC2(canvas_item_set_light_mask,RID,int ); - - //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect); - FUNC2(canvas_item_set_transform,RID, const Matrix32& ); - FUNC2(canvas_item_set_clip,RID, bool ); - FUNC2(canvas_item_set_distance_field_mode,RID, bool ); - FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&); - FUNC2(canvas_item_set_opacity,RID, float ); - FUNC2RC(float,canvas_item_get_opacity,RID, float ); - FUNC2(canvas_item_set_on_top,RID, bool ); - FUNC1RC(bool,canvas_item_is_on_top,RID); - - FUNC2(canvas_item_set_self_opacity,RID, float ); - FUNC2RC(float,canvas_item_get_self_opacity,RID, float ); - - FUNC2(canvas_item_attach_viewport,RID, RID ); - - FUNC6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float,bool); - FUNC3(canvas_item_add_rect,RID, const Rect2& , const Color& ); - FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& ); - FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool ); - FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool ); - FUNC8(canvas_item_add_style_box,RID, const Rect2& , const Rect2&, RID ,const Vector2& ,const Vector2&, bool ,const Color& ); - FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float ); - FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ); - FUNC7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int ); - FUNC7(canvas_item_add_triangle_array_ptr,RID, int , const int* , const Point2* , const Color* ,const Point2* , RID ); - - - FUNC2(canvas_item_add_set_transform,RID,const Matrix32& ); - FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode ); - FUNC2(canvas_item_add_clip_ignore,RID, bool ); - - FUNC2(canvas_item_set_sort_children_by_y,RID,bool); - FUNC2(canvas_item_set_z,RID,int); - FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool); - FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&); - - - FUNC2(canvas_item_set_material,RID, RID ); - - FUNC2(canvas_item_set_use_parent_material,RID, bool ); - - FUNC1(canvas_item_clear,RID); - FUNC1(canvas_item_raise,RID); - - /* CANVAS LIGHT */ - FUNC0R(RID,canvas_light_create); - FUNC2(canvas_light_attach_to_canvas,RID,RID); - FUNC2(canvas_light_set_enabled,RID,bool); - FUNC2(canvas_light_set_transform,RID,const Matrix32&); - FUNC2(canvas_light_set_scale,RID,float); - FUNC2(canvas_light_set_texture,RID,RID); - FUNC2(canvas_light_set_texture_offset,RID,const Vector2&); - FUNC2(canvas_light_set_color,RID,const Color&); - FUNC2(canvas_light_set_height,RID,float); - FUNC2(canvas_light_set_energy,RID,float); - FUNC3(canvas_light_set_layer_range,RID,int,int); - FUNC3(canvas_light_set_z_range,RID,int,int); - FUNC2(canvas_light_set_item_mask,RID,int); - FUNC2(canvas_light_set_item_shadow_mask,RID,int); - - FUNC2(canvas_light_set_mode,RID,CanvasLightMode); - FUNC2(canvas_light_set_shadow_enabled,RID,bool); - FUNC2(canvas_light_set_shadow_buffer_size,RID,int); - FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float); - FUNC2(canvas_light_set_shadow_color,RID,const Color&); - - - - /* CANVAS OCCLUDER */ - - FUNC0R(RID,canvas_light_occluder_create); - 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_transform,RID,const Matrix32&); - FUNC2(canvas_light_occluder_set_light_mask,RID,int); - - - FUNC0R(RID,canvas_occluder_polygon_create); - FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool); - FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&); - FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode); - - /* CANVAS MATERIAL */ - - FUNC0R(RID,canvas_item_material_create); - FUNC2(canvas_item_material_set_shader,RID,RID); - FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&); - FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&); - FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode); - - /* CURSOR */ - FUNC2(cursor_set_rotation,float , int ); // radians - FUNC4(cursor_set_texture,RID , const Point2 &, int, const Rect2 &); - FUNC2(cursor_set_visible,bool , int ); - FUNC2(cursor_set_pos,const Point2& , int ); - - /* BLACK BARS */ - - FUNC4(black_bars_set_margins,int , int , int , int ); - FUNC4(black_bars_set_images,RID , RID , RID , RID ); - - /* FREE */ - - FUNC1(free,RID); - - /* CUSTOM SHADE MODEL */ - - FUNC2(custom_shade_model_set_shader,int , RID ); - FUNC1RC(RID,custom_shade_model_get_shader,int ); - FUNC2(custom_shade_model_set_name,int , const String& ); - FUNC1RC(String,custom_shade_model_get_name,int ); - FUNC2(custom_shade_model_set_param_info,int , const List<PropertyInfo>& ); - FUNC2SC(custom_shade_model_get_param_info,int , List<PropertyInfo>* ); - - /* EVENT QUEUING */ - - - virtual void init(); - virtual void finish(); - virtual void draw(); - virtual void sync(); - FUNC0RC(bool,has_changed); - - /* RENDER INFO */ - - FUNC1R(int,get_render_info,RenderInfo ); - virtual bool has_feature(Features p_feature) const { return visual_server->has_feature(p_feature); } - - FUNC3(set_boot_image,const Image& , const Color&,bool ); - FUNC1(set_default_clear_color,const Color& ); - - FUNC0R(RID,get_test_cube ); - - - VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread); - ~VisualServerWrapMT(); - -#undef ServerName -#undef ServerNameWrapMT -#undef server_name - -}; - -#ifdef DEBUG_SYNC -#undef DEBUG_SYNC -#endif -#undef SYNC_DEBUG - -#endif diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 18d11a993c..e9c479f339 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -39,16 +39,6 @@ VisualServer *VisualServer::get_singleton() { } -void VisualServer::set_mipmap_policy(MipMapPolicy p_policy) { - - mm_policy=p_policy; -} - -VisualServer::MipMapPolicy VisualServer::get_mipmap_policy() const { - - return (VisualServer::MipMapPolicy)mm_policy; -} - DVector<String> VisualServer::_shader_get_param_list(RID p_shader) const { @@ -93,38 +83,48 @@ RID VisualServer::texture_create_from_image(const Image& p_image,uint32_t p_flag RID VisualServer::get_test_texture() { - if (test_texture) { + if (test_texture.is_valid()) { return test_texture; }; #define TEST_TEXTURE_SIZE 256 - Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,0,Image::FORMAT_RGB); - for (int x=0;x<TEST_TEXTURE_SIZE;x++) { + DVector<uint8_t> test_data; + test_data.resize(TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*3); + + { + DVector<uint8_t>::Write w=test_data.write(); - for (int y=0;y<TEST_TEXTURE_SIZE;y++) { + for (int x=0;x<TEST_TEXTURE_SIZE;x++) { - Color c; - int r=255-(x+y)/2; + for (int y=0;y<TEST_TEXTURE_SIZE;y++) { - if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) { + Color c; + int r=255-(x+y)/2; - c.r=y; - c.g=r; - c.b=x; + if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) { - } else { + c.r=y; + c.g=r; + c.b=x; - c.r=r; - c.g=x; - c.b=y; - } + } else { - data.put_pixel(x, y, c); + c.r=r; + c.g=x; + c.b=y; + } + + w[(y*TEST_TEXTURE_SIZE+x)*3+0]=uint8_t(CLAMP(c.r*255,0,255)); + w[(y*TEST_TEXTURE_SIZE+x)*3+1]=uint8_t(CLAMP(c.g*255,0,255)); + w[(y*TEST_TEXTURE_SIZE+x)*3+2]=uint8_t(CLAMP(c.b*255,0,255)); + } } } + Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,false,Image::FORMAT_RGB8,test_data); + test_texture = texture_create_from_image(data); return test_texture; @@ -217,10 +217,10 @@ RID VisualServer::_make_test_cube() { indices.set(i,i); d[VisualServer::ARRAY_INDEX]=indices; - mesh_add_surface( test_cube, PRIMITIVE_TRIANGLES,d ); - + mesh_add_surface_from_arrays( test_cube, PRIMITIVE_TRIANGLES,d ); +/* test_material = fixed_material_create(); //material_set_flag(material, MATERIAL_FLAG_BILLBOARD_TOGGLE,true); fixed_material_set_texture( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, get_test_texture() ); @@ -229,7 +229,7 @@ RID VisualServer::_make_test_cube() { fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, Color(1, 1, 1) ); fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR, Color(1,1,1) ); - +*/ mesh_surface_set_material(test_cube, 0, test_material ); return test_cube; @@ -289,7 +289,7 @@ RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) { d[ARRAY_VERTEX]=vertices; d[ARRAY_NORMAL]=normals; - mesh_add_surface(mesh,PRIMITIVE_TRIANGLES,d); + mesh_add_surface_from_arrays(mesh,PRIMITIVE_TRIANGLES,d); return mesh; } @@ -311,7 +311,7 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_ //not valid, make - material_2d[version]=fixed_material_create(); +/* material_2d[version]=fixed_material_create(); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_ALPHA,p_transparent); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_DISCARD_ALPHA,p_cut_alpha); @@ -319,7 +319,8 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_ material_set_flag(material_2d[version],MATERIAL_FLAG_DOUBLE_SIDED,true); material_set_depth_draw_mode(material_2d[version],p_opaque_prepass?MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA:MATERIAL_DEPTH_DRAW_OPAQUE_ONLY); fixed_material_set_texture(material_2d[version],FIXED_MATERIAL_PARAM_DIFFUSE,get_white_texture()); - //material cut alpha? + //material cut alpha?*/ + return material_2d[version]; } @@ -335,14 +336,1230 @@ RID VisualServer::get_white_texture() { for(int i=0;i<16*3;i++) w[i]=255; } - Image white(4,4,0,Image::FORMAT_RGB,wt); + Image white(4,4,0,Image::FORMAT_RGB8,wt); white_texture=texture_create(); - texture_allocate(white_texture,4,4,Image::FORMAT_RGB); + texture_allocate(white_texture,4,4,Image::FORMAT_RGB8); texture_set_data(white_texture,white); return white_texture; } + +Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,DVector<uint8_t> &r_vertex_array,int p_vertex_array_len,DVector<uint8_t> &r_index_array,int p_index_array_len,AABB &r_aabb,Vector<AABB> r_bone_aabb) { + + DVector<uint8_t>::Write vw = r_vertex_array.write(); + + DVector<uint8_t>::Write iw; + if (r_index_array.size()) { + iw=r_index_array.write(); + } + + int max_bone=0; + + + for(int ai=0;ai<VS::ARRAY_MAX;ai++) { + + if (!(p_format&(1<<ai))) // no array + continue; + + + switch(ai) { + + case VS::ARRAY_VERTEX: { + + if (p_format& VS::ARRAY_FLAG_USE_2D_VERTICES) { + + DVector<Vector2> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + DVector<Vector2>::Read read = array.read(); + const Vector2* src=read.ptr(); + + // setting vertices means regenerating the AABB + Rect2 aabb; + + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + for (int i=0;i<p_vertex_array_len;i++) { + + + uint16_t vector[2]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*2); + + if (i==0) { + + aabb=Rect2(src[i],Vector2()); + } else { + + aabb.expand_to( src[i] ); + } + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[2]={ src[i].x, src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*2); + + if (i==0) { + + aabb=Rect2(src[i],Vector2()); + } else { + + aabb.expand_to( src[i] ); + } + } + } + + r_aabb=AABB(Vector3(aabb.pos.x,aabb.pos.y,0),Vector3(aabb.size.x,aabb.size.y,0)); + + + } else { + DVector<Vector3> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + DVector<Vector3>::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + AABB aabb; + + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + for (int i=0;i<p_vertex_array_len;i++) { + + + uint16_t vector[4]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y), Math::make_half_float(src[i].z), Math::make_half_float(1.0) }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*4); + + if (i==0) { + + aabb=AABB(src[i],Vector3()); + } else { + + aabb.expand_to( src[i] ); + } + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[3]={ src[i].x, src[i].y, src[i].z }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*3); + + if (i==0) { + + aabb=AABB(src[i],Vector3()); + } else { + + aabb.expand_to( src[i] ); + } + } + } + + r_aabb=aabb; + + } + + + } break; + case VS::ARRAY_NORMAL: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<Vector3> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + DVector<Vector3>::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + + if (p_format&ARRAY_COMPRESS_NORMAL) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t vector[4]={ + CLAMP(src[i].x*127,-128,127), + CLAMP(src[i].y*127,-128,127), + CLAMP(src[i].z*127,-128,127), + 0, + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, 4); + + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[3]={ src[i].x, src[i].y, src[i].z }; + copymem(&vw[p_offsets[ai]+i*p_stride], vector, 3*4); + + } + } + + } break; + + case VS::ARRAY_TANGENT: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<real_t> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*4, ERR_INVALID_PARAMETER ); + + + DVector<real_t>::Read read = array.read(); + const real_t* src = read.ptr(); + + if (p_format&ARRAY_COMPRESS_TANGENT) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t xyzw[4]={ + CLAMP(src[i*4+0]*127,-128,127), + CLAMP(src[i*4+1]*127,-128,127), + CLAMP(src[i*4+2]*127,-128,127), + CLAMP(src[i*4+3]*127,-128,127) + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4); + + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float xyzw[4]={ + src[i*4+0], + src[i*4+1], + src[i*4+2], + src[i*4+3] + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4*4); + + } + } + + } break; + case VS::ARRAY_COLOR: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::COLOR_ARRAY, ERR_INVALID_PARAMETER ); + + + DVector<Color> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + DVector<Color>::Read read = array.read(); + const Color* src = read.ptr(); + + if (p_format&ARRAY_COMPRESS_COLOR) { + + for (int i=0;i<p_vertex_array_len;i++) { + + + uint8_t colors[4]; + + for(int j=0;j<4;j++) { + + colors[j]=CLAMP( int((src[i][j])*255.0), 0,255 ); + } + + copymem(&vw[p_offsets[ai]+i*p_stride], colors, 4); + + } + } else { + + for (int i=0;i<p_vertex_array_len;i++) { + + + copymem(&vw[p_offsets[ai]+i*p_stride], &src[i], 4*4); + } + + } + + + } break; + case VS::ARRAY_TEX_UV: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<Vector2> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER); + + DVector<Vector2>::Read read = array.read(); + + const Vector2 * src=read.ptr(); + + + + if (p_format&ARRAY_COMPRESS_TEX_UV) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2); + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float uv[2]={ src[i].x , src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4); + + } + } + + + } break; + + case VS::ARRAY_TEX_UV2: { + + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<Vector2> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER); + + DVector<Vector2>::Read read = array.read(); + + const Vector2 * src=read.ptr(); + + + + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2); + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float uv[2]={ src[i].x , src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4); + + } + } + } break; + case VS::ARRAY_WEIGHTS: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<real_t> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + DVector<real_t>::Read read = array.read(); + + const real_t * src = read.ptr(); + + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j]*65535,0,65535); + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4); + } + } else { + + for (int i=0;i<p_vertex_array_len;i++) { + + float data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 4*4); + + + } + } + + } break; + case VS::ARRAY_BONES: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<int> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + DVector<int>::Read read = array.read(); + + const int * src = read.ptr(); + + + if (!(p_format&ARRAY_FLAG_USE_16_BIT_BONES)) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j],0,255); + max_bone=MAX(data[j],max_bone); + + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 4); + + + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; + max_bone=MAX(data[j],max_bone); + + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4); + + + } + } + + + } break; + case VS::ARRAY_INDEX: { + + + ERR_FAIL_COND_V( p_index_array_len<=0, ERR_INVALID_DATA ); + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); + + DVector<int> indices = p_arrays[ai]; + ERR_FAIL_COND_V( indices.size() == 0, ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V( indices.size() != p_index_array_len, ERR_INVALID_PARAMETER ); + + /* determine wether using 16 or 32 bits indices */ + + DVector<int>::Read read = indices.read(); + const int *src=read.ptr(); + + for (int i=0;i<p_index_array_len;i++) { + + + if (p_vertex_array_len<(1<<16)) { + uint16_t v=src[i]; + + copymem(&iw[i*2], &v, 2); + } else { + uint32_t v=src[i]; + + copymem(&iw[i*4], &v, 4); + } + } + } break; + default: { + ERR_FAIL_V( ERR_INVALID_DATA ); + } + } + } + + + if (p_format&VS::ARRAY_FORMAT_BONES) { + //create AABBs for each detected bone + int total_bones = max_bone+1; + + bool first = r_bone_aabb.size()==0; + + r_bone_aabb.resize(total_bones); + + if (first) { + for(int i=0;i<total_bones;i++) { + r_bone_aabb[i].size==Vector3(-1,-1,-1); //negative means unused + } + } + + DVector<Vector3> vertices = p_arrays[VS::ARRAY_VERTEX]; + DVector<int> bones = p_arrays[VS::ARRAY_BONES]; + DVector<float> weights = p_arrays[VS::ARRAY_WEIGHTS]; + + bool any_valid=false; + + if (vertices.size() && bones.size()==vertices.size()*4 && weights.size()==bones.size()) { + + int vs = vertices.size(); + DVector<Vector3>::Read rv =vertices.read(); + DVector<int>::Read rb=bones.read(); + DVector<float>::Read rw=weights.read(); + + AABB *bptr = r_bone_aabb.ptr(); + + for(int i=0;i<vs;i++) { + + Vector3 v = rv[i]; + for(int j=0;j<4;j++) { + + int idx = rb[i*4+j]; + float w = rw[i*4+j]; + if (w==0) + continue;//break; + ERR_FAIL_INDEX_V(idx,total_bones,ERR_INVALID_DATA); + + if (bptr->size.x<0) { + //first + bptr[idx]=AABB(); + bptr[idx].pos=v; + any_valid=true; + } else { + bptr[idx].expand_to(v); + } + } + } + } + + if (!any_valid && first) { + + r_bone_aabb.clear(); + } + } + return OK; +} + + +void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,uint32_t p_compress_format) { + + ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); + ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); + + uint32_t format=0; + + // validation + int index_array_len=0; + int array_len=0; + + for(int i=0;i<p_arrays.size();i++) { + + if (p_arrays[i].get_type()==Variant::NIL) + continue; + + format|=(1<<i); + + if (i==VS::ARRAY_VERTEX) { + + Variant var = p_arrays[i]; + switch(var.get_type()) { + case Variant::VECTOR2_ARRAY: { + DVector<Vector2> v2 = var; + array_len=v2.size(); + } break; + case Variant::VECTOR3_ARRAY: { + DVector<Vector3> v3 = var; + array_len=v3.size(); + } break; + default: { + Array v = var; + array_len=v.size(); + } break; + } + + array_len=Vector3Array(p_arrays[i]).size(); + ERR_FAIL_COND(array_len==0); + } else if (i==VS::ARRAY_INDEX) { + + index_array_len=IntArray(p_arrays[i]).size(); + } + } + + ERR_FAIL_COND((format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory + + + if (p_blend_shapes.size()) { + //validate format for morphs + for(int i=0;i<p_blend_shapes.size();i++) { + + uint32_t bsformat=0; + Array arr = p_blend_shapes[i]; + for(int j=0;j<arr.size();j++) { + + + if (arr[j].get_type()!=Variant::NIL) + bsformat|=(1<<j); + } + + ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_INDEX-1))); + } + } + + uint32_t offsets[VS::ARRAY_MAX]; + + int total_elem_size=0; + + for (int i=0;i<VS::ARRAY_MAX;i++) { + + + offsets[i]=0; //reset + + if (!(format&(1<<i))) // no array + continue; + + + int elem_size=0; + + switch(i) { + + case VS::ARRAY_VERTEX: { + + Variant arr = p_arrays[0]; + if (arr.get_type()==Variant::VECTOR2_ARRAY) { + elem_size=2; + p_compress_format|=ARRAY_FLAG_USE_2D_VERTICES; + } else if (arr.get_type()==Variant::VECTOR3_ARRAY) { + p_compress_format&=~ARRAY_FLAG_USE_2D_VERTICES; + elem_size=3; + } else { + elem_size=(p_compress_format&ARRAY_FLAG_USE_2D_VERTICES)?2:3; + } + + if (p_compress_format&ARRAY_COMPRESS_VERTEX) { + elem_size*=sizeof(int16_t); + } else { + elem_size*=sizeof(float); + } + + if (elem_size==6) { + //had to pad + elem_size=8; + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_compress_format&ARRAY_COMPRESS_NORMAL) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*3; + } + + } break; + + case VS::ARRAY_TANGENT: { + if (p_compress_format&ARRAY_COMPRESS_TANGENT) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_compress_format&ARRAY_COMPRESS_COLOR) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + } break; + case VS::ARRAY_TEX_UV: { + if (p_compress_format&ARRAY_COMPRESS_TEX_UV) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + + case VS::ARRAY_TEX_UV2: { + if (p_compress_format&ARRAY_COMPRESS_TEX_UV2) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_compress_format&ARRAY_COMPRESS_WEIGHTS) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_BONES: { + + DVector<int> bones = p_arrays[VS::ARRAY_BONES]; + int max_bone=0; + + { + int bc = bones.size(); + DVector<int>::Read r=bones.read(); + for(int j=0;j<bc;j++) { + max_bone=MAX(r[j],max_bone); + } + } + + if (max_bone > 255) { + p_compress_format|=ARRAY_FLAG_USE_16_BIT_BONES; + elem_size=sizeof(uint16_t)*4; + } else { + p_compress_format&=~ARRAY_FLAG_USE_16_BIT_BONES; + elem_size=sizeof(uint32_t); + } + + + } break; + case VS::ARRAY_INDEX: { + + if (index_array_len<=0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine wether using 16 or 32 bits indices */ + if (array_len>=(1<<16)) { + + elem_size=4; + + } else { + elem_size=2; + } + offsets[i]=elem_size; + continue; + } break; + default: { + ERR_FAIL( ); + } + } + + offsets[i]=total_elem_size; + total_elem_size+=elem_size; + + + } + + uint32_t mask = (1<<ARRAY_MAX)-1; + format|=(~mask)&p_compress_format; //make the full format + + + int array_size = total_elem_size * array_len; + + DVector<uint8_t> vertex_array; + vertex_array.resize(array_size); + + int index_array_size = offsets[VS::ARRAY_INDEX]*index_array_len; + + DVector<uint8_t> index_array; + index_array.resize(index_array_size); + + AABB aabb; + Vector<AABB> bone_aabb; + + Error err = _surface_set_data(p_arrays,format,offsets,total_elem_size,vertex_array,array_len,index_array,index_array_len,aabb,bone_aabb); + + if (err) { + ERR_EXPLAIN("Invalid array format for surface"); + ERR_FAIL_COND(err!=OK); + } + + Vector<DVector<uint8_t> > blend_shape_data; + + for(int i=0;i<p_blend_shapes.size();i++) { + + DVector<uint8_t> vertex_array_shape; + vertex_array_shape.resize(array_size); + DVector<uint8_t> noindex; + + AABB laabb; + Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array_shape,array_len,noindex,0,laabb,bone_aabb); + aabb.merge_with(laabb); + if (err) { + ERR_EXPLAIN("Invalid blend shape array format for surface"); + ERR_FAIL_COND(err!=OK); + } + + blend_shape_data.push_back(vertex_array_shape); + } + + mesh_add_surface(p_mesh,format,p_primitive,vertex_array,array_len,index_array,index_array_len,aabb,blend_shape_data,bone_aabb); + +} + +Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector<uint8_t> p_vertex_data,int p_vertex_len,DVector<uint8_t> p_index_data,int p_index_len) const { + + + uint32_t offsets[ARRAY_MAX]; + + int total_elem_size=0; + + for (int i=0;i<VS::ARRAY_MAX;i++) { + + + offsets[i]=0; //reset + + if (!(p_format&(1<<i))) // no array + continue; + + + int elem_size=0; + + switch(i) { + + case VS::ARRAY_VERTEX: { + + + if (p_format&ARRAY_FLAG_USE_2D_VERTICES) { + elem_size=2; + } else { + elem_size=3; + } + + if (p_format&ARRAY_COMPRESS_VERTEX) { + elem_size*=sizeof(int16_t); + } else { + elem_size*=sizeof(float); + } + + if (elem_size==6) { + elem_size=8; + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_format&ARRAY_COMPRESS_NORMAL) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*3; + } + + } break; + + case VS::ARRAY_TANGENT: { + if (p_format&ARRAY_COMPRESS_TANGENT) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_format&ARRAY_COMPRESS_COLOR) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + } break; + case VS::ARRAY_TEX_UV: { + if (p_format&ARRAY_COMPRESS_TEX_UV) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + + case VS::ARRAY_TEX_UV2: { + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_BONES: { + + if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(uint32_t); + } + + } break; + case VS::ARRAY_INDEX: { + + if (p_index_len<=0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine wether using 16 or 32 bits indices */ + if (p_vertex_len>=(1<<16)) { + + elem_size=4; + + } else { + elem_size=2; + } + offsets[i]=elem_size; + continue; + } break; + default: { + ERR_FAIL_V( Array() ); + } + } + + offsets[i]=total_elem_size; + total_elem_size+=elem_size; + + + } + + Array ret; + ret.resize(VS::ARRAY_MAX); + + DVector<uint8_t>::Read r = p_vertex_data.read(); + + for(int i=0;i<VS::ARRAY_MAX;i++) { + + if (!(p_format&(1<<i))) + continue; + + + switch(i) { + + case VS::ARRAY_VERTEX: { + + + if (p_format&ARRAY_FLAG_USE_2D_VERTICES) { + + DVector<Vector2> arr_2d; + arr_2d.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + DVector<Vector2>::Write w = arr_2d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + DVector<Vector2>::Write w = arr_2d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr_2d; + } else { + + DVector<Vector3> arr_3d; + arr_3d.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + DVector<Vector3>::Write w = arr_3d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]),Math::halfptr_to_float(&v[2])); + } + } else { + + DVector<Vector3>::Write w = arr_3d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(v[0],v[1],v[2]); + } + } + + ret[i]=arr_3d; + } + + + } break; + case VS::ARRAY_NORMAL: { + DVector<Vector3> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_NORMAL) { + + DVector<Vector3>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0 ); + } + } else { + DVector<Vector3>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(v[0],v[1],v[2]); + } + } + + ret[i]=arr; + + } break; + + case VS::ARRAY_TANGENT: { + DVector<float> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_COMPRESS_TANGENT) { + DVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=float(v[k]/255.0)*2.0-1.0; + } + } + } else { + + DVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_COLOR: { + + DVector<Color> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_COLOR) { + + DVector<Color>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Color( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0, float(v[3]/255.0)*2.0-1.0 ); + } + } else { + DVector<Color>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Color(v[0],v[1],v[2],v[3]); + } + } + + ret[i]=arr; + } break; + case VS::ARRAY_TEX_UV: { + + DVector<Vector2> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_TEX_UV) { + + DVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + DVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr; + } break; + + case VS::ARRAY_TEX_UV2: { + DVector<Vector2> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + + DVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + DVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr; + + } break; + case VS::ARRAY_WEIGHTS: { + + DVector<float> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + DVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=float(v[k]/65535.0)*2.0-1.0; + } + } + } else { + + DVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_BONES: { + + DVector<int> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { + + DVector<int>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + } else { + + DVector<int>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_INDEX: { + /* determine wether using 16 or 32 bits indices */ + + DVector<uint8_t>::Read ir = p_index_data.read(); + + DVector<int> arr; + arr.resize(p_index_len); + if (p_vertex_len<(1<<16)) { + + DVector<int>::Write w = arr.write(); + + for(int j=0;j<p_index_len;j++) { + + const uint16_t *v = (const uint16_t*)&ir[j*2]; + w[j]=*v; + } + } else { + + DVector<int>::Write w = arr.write(); + + for(int j=0;j<p_index_len;j++) { + const int *v = (const int*)&ir[j*4]; + w[j]=*v; + } + + } + ret[i]=arr; + } break; + default: { + ERR_FAIL_V( ret ); + } + } + } + + return ret; +} + +Array VisualServer::mesh_surface_get_arrays(RID p_mesh,int p_surface) const { + + DVector<uint8_t> vertex_data = mesh_surface_get_array(p_mesh,p_surface); + ERR_FAIL_COND_V(vertex_data.size()==0,Array()); + int vertex_len = mesh_surface_get_array_len(p_mesh,p_surface); + + DVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh,p_surface); + int index_len = mesh_surface_get_array_index_len(p_mesh,p_surface); + + uint32_t format = mesh_surface_get_format(p_mesh,p_surface); + + + return _get_array_from_surface(format,vertex_data,vertex_len,index_data,index_len); + +} + void VisualServer::_bind_methods() { @@ -358,349 +1575,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data ); -#ifndef _3D_DISABLED - - - ObjectTypeDB::bind_method(_MD("shader_create","mode"),&VisualServer::shader_create,DEFVAL(SHADER_MATERIAL)); - ObjectTypeDB::bind_method(_MD("shader_set_mode","shader","mode"),&VisualServer::shader_set_mode); - - - - ObjectTypeDB::bind_method(_MD("material_create"),&VisualServer::material_create); - - ObjectTypeDB::bind_method(_MD("material_set_shader","shader"),&VisualServer::material_set_shader); - ObjectTypeDB::bind_method(_MD("material_get_shader"),&VisualServer::material_get_shader); - - ObjectTypeDB::bind_method(_MD("material_set_param"),&VisualServer::material_set_param); - ObjectTypeDB::bind_method(_MD("material_get_param"),&VisualServer::material_get_param); - ObjectTypeDB::bind_method(_MD("material_set_flag"),&VisualServer::material_set_flag); - ObjectTypeDB::bind_method(_MD("material_get_flag"),&VisualServer::material_get_flag); - ObjectTypeDB::bind_method(_MD("material_set_blend_mode"),&VisualServer::material_set_blend_mode); - ObjectTypeDB::bind_method(_MD("material_get_blend_mode"),&VisualServer::material_get_blend_mode); - ObjectTypeDB::bind_method(_MD("material_set_line_width"),&VisualServer::material_set_line_width); - ObjectTypeDB::bind_method(_MD("material_get_line_width"),&VisualServer::material_get_line_width); - - - ObjectTypeDB::bind_method(_MD("mesh_create"),&VisualServer::mesh_create); - ObjectTypeDB::bind_method(_MD("mesh_add_surface"),&VisualServer::mesh_add_surface, DEFVAL(NO_INDEX_ARRAY)); - ObjectTypeDB::bind_method(_MD("mesh_surface_set_material"),&VisualServer::mesh_surface_set_material,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_material"),&VisualServer::mesh_surface_get_material); - - ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_len"),&VisualServer::mesh_surface_get_array_len); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_index_len"),&VisualServer::mesh_surface_get_array_index_len); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_format"),&VisualServer::mesh_surface_get_format); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_primitive_type"),&VisualServer::mesh_surface_get_primitive_type); - - ObjectTypeDB::bind_method(_MD("mesh_remove_surface"),&VisualServer::mesh_remove_surface); - ObjectTypeDB::bind_method(_MD("mesh_get_surface_count"),&VisualServer::mesh_get_surface_count); - - - ObjectTypeDB::bind_method(_MD("multimesh_create"),&VisualServer::multimesh_create); - ObjectTypeDB::bind_method(_MD("multimesh_set_mesh"),&VisualServer::multimesh_set_mesh); - ObjectTypeDB::bind_method(_MD("multimesh_set_aabb"),&VisualServer::multimesh_set_aabb); - ObjectTypeDB::bind_method(_MD("multimesh_instance_set_transform"),&VisualServer::multimesh_instance_set_transform); - ObjectTypeDB::bind_method(_MD("multimesh_instance_set_color"),&VisualServer::multimesh_instance_set_color); - ObjectTypeDB::bind_method(_MD("multimesh_get_mesh"),&VisualServer::multimesh_get_mesh); - ObjectTypeDB::bind_method(_MD("multimesh_get_aabb"),&VisualServer::multimesh_get_aabb); - ObjectTypeDB::bind_method(_MD("multimesh_instance_get_transform"),&VisualServer::multimesh_instance_get_transform); - ObjectTypeDB::bind_method(_MD("multimesh_instance_get_color"),&VisualServer::multimesh_instance_get_color); - - - - ObjectTypeDB::bind_method(_MD("particles_create"),&VisualServer::particles_create); - ObjectTypeDB::bind_method(_MD("particles_set_amount"),&VisualServer::particles_set_amount); - ObjectTypeDB::bind_method(_MD("particles_get_amount"),&VisualServer::particles_get_amount); - ObjectTypeDB::bind_method(_MD("particles_set_emitting"),&VisualServer::particles_set_emitting); - ObjectTypeDB::bind_method(_MD("particles_is_emitting"),&VisualServer::particles_is_emitting); - ObjectTypeDB::bind_method(_MD("particles_set_visibility_aabb"),&VisualServer::particles_set_visibility_aabb); - ObjectTypeDB::bind_method(_MD("particles_get_visibility_aabb"),&VisualServer::particles_get_visibility_aabb); - ObjectTypeDB::bind_method(_MD("particles_set_variable"),&VisualServer::particles_set_variable); - ObjectTypeDB::bind_method(_MD("particles_get_variable"),&VisualServer::particles_get_variable); - ObjectTypeDB::bind_method(_MD("particles_set_randomness"),&VisualServer::particles_set_randomness); - ObjectTypeDB::bind_method(_MD("particles_get_randomness"),&VisualServer::particles_get_randomness); - ObjectTypeDB::bind_method(_MD("particles_set_color_phases"),&VisualServer::particles_set_color_phases); - ObjectTypeDB::bind_method(_MD("particles_get_color_phases"),&VisualServer::particles_get_color_phases); - ObjectTypeDB::bind_method(_MD("particles_set_color_phase_pos"),&VisualServer::particles_set_color_phase_pos); - ObjectTypeDB::bind_method(_MD("particles_get_color_phase_pos"),&VisualServer::particles_get_color_phase_pos); - ObjectTypeDB::bind_method(_MD("particles_set_color_phase_color"),&VisualServer::particles_set_color_phase_color); - ObjectTypeDB::bind_method(_MD("particles_get_color_phase_color"),&VisualServer::particles_get_color_phase_color); - ObjectTypeDB::bind_method(_MD("particles_set_attractors"),&VisualServer::particles_set_attractors); - ObjectTypeDB::bind_method(_MD("particles_get_attractors"),&VisualServer::particles_get_attractors); - ObjectTypeDB::bind_method(_MD("particles_set_attractor_pos"),&VisualServer::particles_set_attractor_pos); - ObjectTypeDB::bind_method(_MD("particles_get_attractor_pos"),&VisualServer::particles_get_attractor_pos); - ObjectTypeDB::bind_method(_MD("particles_set_attractor_strength"),&VisualServer::particles_set_attractor_strength); - ObjectTypeDB::bind_method(_MD("particles_get_attractor_strength"),&VisualServer::particles_get_attractor_strength); - ObjectTypeDB::bind_method(_MD("particles_set_material"),&VisualServer::particles_set_material,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("particles_set_height_from_velocity"),&VisualServer::particles_set_height_from_velocity); - ObjectTypeDB::bind_method(_MD("particles_has_height_from_velocity"),&VisualServer::particles_has_height_from_velocity); - - - - ObjectTypeDB::bind_method(_MD("light_create"),&VisualServer::light_create); - ObjectTypeDB::bind_method(_MD("light_get_type"),&VisualServer::light_get_type); - ObjectTypeDB::bind_method(_MD("light_set_color"),&VisualServer::light_set_color); - ObjectTypeDB::bind_method(_MD("light_get_color"),&VisualServer::light_get_color); - ObjectTypeDB::bind_method(_MD("light_set_shadow"),&VisualServer::light_set_shadow); - ObjectTypeDB::bind_method(_MD("light_has_shadow"),&VisualServer::light_has_shadow); - ObjectTypeDB::bind_method(_MD("light_set_volumetric"),&VisualServer::light_set_volumetric); - ObjectTypeDB::bind_method(_MD("light_is_volumetric"),&VisualServer::light_is_volumetric); - ObjectTypeDB::bind_method(_MD("light_set_projector"),&VisualServer::light_set_projector); - ObjectTypeDB::bind_method(_MD("light_get_projector"),&VisualServer::light_get_projector); - ObjectTypeDB::bind_method(_MD("light_set_var"),&VisualServer::light_set_param); - ObjectTypeDB::bind_method(_MD("light_get_var"),&VisualServer::light_get_param); - - ObjectTypeDB::bind_method(_MD("skeleton_create"),&VisualServer::skeleton_create); - ObjectTypeDB::bind_method(_MD("skeleton_resize"),&VisualServer::skeleton_resize); - ObjectTypeDB::bind_method(_MD("skeleton_get_bone_count"),&VisualServer::skeleton_get_bone_count); - ObjectTypeDB::bind_method(_MD("skeleton_bone_set_transform"),&VisualServer::skeleton_bone_set_transform); - ObjectTypeDB::bind_method(_MD("skeleton_bone_get_transform"),&VisualServer::skeleton_bone_get_transform); - - - - ObjectTypeDB::bind_method(_MD("room_create"),&VisualServer::room_create); - ObjectTypeDB::bind_method(_MD("room_set_bounds"),&VisualServer::room_set_bounds); - ObjectTypeDB::bind_method(_MD("room_get_bounds"),&VisualServer::room_get_bounds); - - ObjectTypeDB::bind_method(_MD("portal_create"),&VisualServer::portal_create); - ObjectTypeDB::bind_method(_MD("portal_set_shape"),&VisualServer::portal_set_shape); - ObjectTypeDB::bind_method(_MD("portal_get_shape"),&VisualServer::portal_get_shape); - ObjectTypeDB::bind_method(_MD("portal_set_enabled"),&VisualServer::portal_set_enabled); - ObjectTypeDB::bind_method(_MD("portal_is_enabled"),&VisualServer::portal_is_enabled); - ObjectTypeDB::bind_method(_MD("portal_set_disable_distance"),&VisualServer::portal_set_disable_distance); - ObjectTypeDB::bind_method(_MD("portal_get_disable_distance"),&VisualServer::portal_get_disable_distance); - ObjectTypeDB::bind_method(_MD("portal_set_disabled_color"),&VisualServer::portal_set_disabled_color); - ObjectTypeDB::bind_method(_MD("portal_get_disabled_color"),&VisualServer::portal_get_disabled_color); - - - ObjectTypeDB::bind_method(_MD("camera_create"),&VisualServer::camera_create); - ObjectTypeDB::bind_method(_MD("camera_set_perspective"),&VisualServer::camera_set_perspective); - ObjectTypeDB::bind_method(_MD("camera_set_orthogonal"),&VisualServer::_camera_set_orthogonal); - ObjectTypeDB::bind_method(_MD("camera_set_transform"),&VisualServer::camera_set_transform); - - - ObjectTypeDB::bind_method(_MD("viewport_create"),&VisualServer::viewport_create); - ObjectTypeDB::bind_method(_MD("viewport_set_rect"),&VisualServer::_viewport_set_rect); - ObjectTypeDB::bind_method(_MD("viewport_get_rect"),&VisualServer::_viewport_get_rect); - ObjectTypeDB::bind_method(_MD("viewport_attach_camera"),&VisualServer::viewport_attach_camera,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("viewport_get_attached_camera"),&VisualServer::viewport_get_attached_camera); - ObjectTypeDB::bind_method(_MD("viewport_get_scenario"),&VisualServer::viewport_get_scenario); - ObjectTypeDB::bind_method(_MD("viewport_attach_canvas"),&VisualServer::viewport_attach_canvas); - ObjectTypeDB::bind_method(_MD("viewport_remove_canvas"),&VisualServer::viewport_remove_canvas); - ObjectTypeDB::bind_method(_MD("viewport_set_global_canvas_transform"),&VisualServer::viewport_set_global_canvas_transform); - - ObjectTypeDB::bind_method(_MD("scenario_create"),&VisualServer::scenario_create); - ObjectTypeDB::bind_method(_MD("scenario_set_debug"),&VisualServer::scenario_set_debug); - - - ObjectTypeDB::bind_method(_MD("instance_create"),&VisualServer::instance_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("instance_get_base"),&VisualServer::instance_get_base); - ObjectTypeDB::bind_method(_MD("instance_get_base_aabb"),&VisualServer::instance_get_base); - ObjectTypeDB::bind_method(_MD("instance_set_transform"),&VisualServer::instance_set_transform); - ObjectTypeDB::bind_method(_MD("instance_get_transform"),&VisualServer::instance_get_transform); - ObjectTypeDB::bind_method(_MD("instance_attach_object_instance_ID"),&VisualServer::instance_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("instance_get_object_instance_ID"),&VisualServer::instance_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("instance_attach_skeleton"),&VisualServer::instance_attach_skeleton); - ObjectTypeDB::bind_method(_MD("instance_get_skeleton"),&VisualServer::instance_get_skeleton); - ObjectTypeDB::bind_method(_MD("instance_set_room"),&VisualServer::instance_set_room); - ObjectTypeDB::bind_method(_MD("instance_get_room"),&VisualServer::instance_get_room); - - ObjectTypeDB::bind_method(_MD("instance_set_exterior"),&VisualServer::instance_set_exterior); - ObjectTypeDB::bind_method(_MD("instance_is_exterior"),&VisualServer::instance_is_exterior); - - ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb); - ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray); - ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex); - - - - ObjectTypeDB::bind_method(_MD("instance_geometry_override_material_param"),&VisualServer::instance_get_room); - ObjectTypeDB::bind_method(_MD("instance_geometry_get_material_param"),&VisualServer::instance_get_room); - - ObjectTypeDB::bind_method(_MD("get_test_cube"),&VisualServer::get_test_cube); -#endif - ObjectTypeDB::bind_method(_MD("canvas_create"),&VisualServer::canvas_create); - ObjectTypeDB::bind_method(_MD("canvas_item_create"),&VisualServer::canvas_item_create); - ObjectTypeDB::bind_method(_MD("canvas_item_set_parent"),&VisualServer::canvas_item_set_parent); - ObjectTypeDB::bind_method(_MD("canvas_item_get_parent"),&VisualServer::canvas_item_get_parent); - ObjectTypeDB::bind_method(_MD("canvas_item_set_transform"),&VisualServer::canvas_item_set_transform); - ObjectTypeDB::bind_method(_MD("canvas_item_set_custom_rect"),&VisualServer::canvas_item_set_custom_rect); - ObjectTypeDB::bind_method(_MD("canvas_item_set_clip"),&VisualServer::canvas_item_set_clip); - ObjectTypeDB::bind_method(_MD("canvas_item_set_opacity"),&VisualServer::canvas_item_set_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_get_opacity"),&VisualServer::canvas_item_get_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_set_self_opacity"),&VisualServer::canvas_item_set_self_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_get_self_opacity"),&VisualServer::canvas_item_get_self_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_set_z"),&VisualServer::canvas_item_set_z); - - ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect"),&VisualServer::canvas_item_add_texture_rect, DEFVAL(Color(1,1,1)), DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect_region"),&VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1,1,1)), DEFVAL(false)); - - ObjectTypeDB::bind_method(_MD("canvas_item_add_style_box"),&VisualServer::_canvas_item_add_style_box, DEFVAL(Color(1,1,1))); -// ObjectTypeDB::bind_method(_MD("canvas_item_add_primitive"),&VisualServer::canvas_item_add_primitive,DEFVAL(Vector<Vector2>()),DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("canvas_item_add_circle"),&VisualServer::canvas_item_add_circle); - - ObjectTypeDB::bind_method(_MD("viewport_set_canvas_transform"),&VisualServer::viewport_set_canvas_transform); - - ObjectTypeDB::bind_method(_MD("canvas_item_clear"),&VisualServer::canvas_item_clear); - ObjectTypeDB::bind_method(_MD("canvas_item_raise"),&VisualServer::canvas_item_raise); - - - ObjectTypeDB::bind_method(_MD("cursor_set_rotation"),&VisualServer::cursor_set_rotation); - ObjectTypeDB::bind_method(_MD("cursor_set_texture"),&VisualServer::cursor_set_texture); - ObjectTypeDB::bind_method(_MD("cursor_set_visible"),&VisualServer::cursor_set_visible); - ObjectTypeDB::bind_method(_MD("cursor_set_pos"),&VisualServer::cursor_set_pos); - - ObjectTypeDB::bind_method(_MD("black_bars_set_margins","left","top","right","bottom"),&VisualServer::black_bars_set_margins); - ObjectTypeDB::bind_method(_MD("black_bars_set_images","left","top","right","bottom"),&VisualServer::black_bars_set_images); - - ObjectTypeDB::bind_method(_MD("make_sphere_mesh"),&VisualServer::make_sphere_mesh); - ObjectTypeDB::bind_method(_MD("mesh_add_surface_from_planes"),&VisualServer::mesh_add_surface_from_planes); - - ObjectTypeDB::bind_method(_MD("draw"),&VisualServer::draw); - ObjectTypeDB::bind_method(_MD("sync"),&VisualServer::sync); - ObjectTypeDB::bind_method(_MD("free_rid"),&VisualServer::free); - - ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color); - - ObjectTypeDB::bind_method(_MD("get_render_info"),&VisualServer::get_render_info); - - BIND_CONSTANT( NO_INDEX_ARRAY ); - BIND_CONSTANT( CUSTOM_ARRAY_SIZE ); - BIND_CONSTANT( ARRAY_WEIGHTS_SIZE ); - BIND_CONSTANT( MAX_PARTICLE_COLOR_PHASES ); - BIND_CONSTANT( MAX_PARTICLE_ATTRACTORS ); - BIND_CONSTANT( MAX_CURSORS ); - - BIND_CONSTANT( TEXTURE_FLAG_MIPMAPS ); - BIND_CONSTANT( TEXTURE_FLAG_REPEAT ); - BIND_CONSTANT( TEXTURE_FLAG_FILTER ); - BIND_CONSTANT( TEXTURE_FLAG_CUBEMAP ); - BIND_CONSTANT( TEXTURE_FLAGS_DEFAULT ); - - BIND_CONSTANT( CUBEMAP_LEFT ); - BIND_CONSTANT( CUBEMAP_RIGHT ); - BIND_CONSTANT( CUBEMAP_BOTTOM ); - BIND_CONSTANT( CUBEMAP_TOP ); - BIND_CONSTANT( CUBEMAP_FRONT ); - BIND_CONSTANT( CUBEMAP_BACK ); - - BIND_CONSTANT( SHADER_MATERIAL ); ///< param 0: name - BIND_CONSTANT( SHADER_POST_PROCESS ); ///< param 0: name - - BIND_CONSTANT( MATERIAL_FLAG_VISIBLE ); - BIND_CONSTANT( MATERIAL_FLAG_DOUBLE_SIDED ); - BIND_CONSTANT( MATERIAL_FLAG_INVERT_FACES ); - BIND_CONSTANT( MATERIAL_FLAG_UNSHADED ); - BIND_CONSTANT( MATERIAL_FLAG_ONTOP ); - BIND_CONSTANT( MATERIAL_FLAG_MAX ); - - BIND_CONSTANT( MATERIAL_BLEND_MODE_MIX ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_ADD ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_SUB ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_MUL ); - - BIND_CONSTANT( FIXED_MATERIAL_PARAM_DIFFUSE ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_DETAIL ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_EMISSION ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR_EXP ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_GLOW ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_NORMAL ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SHADE_PARAM ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_MAX ); - - - - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_SPHERE ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV2 ); - - - BIND_CONSTANT( ARRAY_VERTEX ); - BIND_CONSTANT( ARRAY_NORMAL ); - BIND_CONSTANT( ARRAY_TANGENT ); - BIND_CONSTANT( ARRAY_COLOR ); - BIND_CONSTANT( ARRAY_TEX_UV ); - BIND_CONSTANT( ARRAY_BONES ); - BIND_CONSTANT( ARRAY_WEIGHTS ); - BIND_CONSTANT( ARRAY_INDEX ); - BIND_CONSTANT( ARRAY_MAX ); - - BIND_CONSTANT( ARRAY_FORMAT_VERTEX ); - BIND_CONSTANT( ARRAY_FORMAT_NORMAL ); - BIND_CONSTANT( ARRAY_FORMAT_TANGENT ); - BIND_CONSTANT( ARRAY_FORMAT_COLOR ); - BIND_CONSTANT( ARRAY_FORMAT_TEX_UV ); - BIND_CONSTANT( ARRAY_FORMAT_BONES ); - BIND_CONSTANT( ARRAY_FORMAT_WEIGHTS ); - BIND_CONSTANT( ARRAY_FORMAT_INDEX ); - - BIND_CONSTANT( PRIMITIVE_POINTS ); - BIND_CONSTANT( PRIMITIVE_LINES ); - BIND_CONSTANT( PRIMITIVE_LINE_STRIP ); - BIND_CONSTANT( PRIMITIVE_LINE_LOOP ); - BIND_CONSTANT( PRIMITIVE_TRIANGLES ); - BIND_CONSTANT( PRIMITIVE_TRIANGLE_STRIP ); - BIND_CONSTANT( PRIMITIVE_TRIANGLE_FAN ); - BIND_CONSTANT( PRIMITIVE_MAX ); - - BIND_CONSTANT( PARTICLE_LIFETIME ); - BIND_CONSTANT( PARTICLE_SPREAD ); - BIND_CONSTANT( PARTICLE_GRAVITY ); - BIND_CONSTANT( PARTICLE_LINEAR_VELOCITY ); - BIND_CONSTANT( PARTICLE_ANGULAR_VELOCITY ); - BIND_CONSTANT( PARTICLE_LINEAR_ACCELERATION ); - BIND_CONSTANT( PARTICLE_RADIAL_ACCELERATION ); - BIND_CONSTANT( PARTICLE_TANGENTIAL_ACCELERATION ); - BIND_CONSTANT( PARTICLE_INITIAL_SIZE ); - BIND_CONSTANT( PARTICLE_FINAL_SIZE ); - BIND_CONSTANT( PARTICLE_INITIAL_ANGLE ); - BIND_CONSTANT( PARTICLE_HEIGHT ); - BIND_CONSTANT( PARTICLE_HEIGHT_SPEED_SCALE ); - BIND_CONSTANT( PARTICLE_VAR_MAX ); - - BIND_CONSTANT( LIGHT_DIRECTIONAL ); - BIND_CONSTANT( LIGHT_OMNI ); - BIND_CONSTANT( LIGHT_SPOT ); - - - BIND_CONSTANT( LIGHT_COLOR_DIFFUSE ); - BIND_CONSTANT( LIGHT_COLOR_SPECULAR ); - - BIND_CONSTANT( LIGHT_PARAM_SPOT_ATTENUATION ); - BIND_CONSTANT( LIGHT_PARAM_SPOT_ANGLE ); - BIND_CONSTANT( LIGHT_PARAM_RADIUS ); - BIND_CONSTANT( LIGHT_PARAM_ENERGY ); - BIND_CONSTANT( LIGHT_PARAM_ATTENUATION ); - BIND_CONSTANT( LIGHT_PARAM_MAX ); - - BIND_CONSTANT( SCENARIO_DEBUG_DISABLED ); - BIND_CONSTANT( SCENARIO_DEBUG_WIREFRAME ); - BIND_CONSTANT( SCENARIO_DEBUG_OVERDRAW ); - - BIND_CONSTANT( INSTANCE_MESH ); - BIND_CONSTANT( INSTANCE_MULTIMESH ); - - BIND_CONSTANT( INSTANCE_PARTICLES ); - BIND_CONSTANT( INSTANCE_LIGHT ); - BIND_CONSTANT( INSTANCE_ROOM ); - BIND_CONSTANT( INSTANCE_PORTAL ); - BIND_CONSTANT( INSTANCE_GEOMETRY_MASK ); - - - BIND_CONSTANT( INFO_OBJECTS_IN_FRAME ); - BIND_CONSTANT( INFO_VERTICES_IN_FRAME ); - BIND_CONSTANT( INFO_MATERIAL_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_SHADER_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_SURFACE_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_DRAW_CALLS_IN_FRAME ); - BIND_CONSTANT( INFO_USAGE_VIDEO_MEM_TOTAL ); - BIND_CONSTANT( INFO_VIDEO_MEM_USED ); - BIND_CONSTANT( INFO_TEXTURE_MEM_USED ); - BIND_CONSTANT( INFO_VERTEX_MEM_USED ); } @@ -708,7 +1583,7 @@ void VisualServer::_bind_methods() { void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) { ERR_FAIL_COND(p_margins.size()!=4); - canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); + //canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); } void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) { @@ -716,21 +1591,6 @@ void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_ne camera_set_orthogonal(p_camera,p_size,p_z_near,p_z_far); } -void VisualServer::_viewport_set_rect(RID p_viewport,const Rect2& p_rect) { - - ViewportRect r; - r.x=p_rect.pos.x; - r.y=p_rect.pos.y; - r.width=p_rect.size.x; - r.height=p_rect.size.y; - viewport_set_rect(p_viewport,r); -} -Rect2 VisualServer::_viewport_get_rect(RID p_viewport) const { - - ViewportRect r=viewport_get_rect(p_viewport); - return Rect2(r.x,r.y,r.width,r.height); -} - @@ -761,7 +1621,7 @@ void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry:: d.resize(VS::ARRAY_MAX); d[ARRAY_VERTEX]=vertices; d[ARRAY_NORMAL]=normals; - mesh_add_surface(p_mesh,PRIMITIVE_TRIANGLES, d); + mesh_add_surface_from_arrays(p_mesh,PRIMITIVE_TRIANGLES, d); #else @@ -797,6 +1657,10 @@ void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane } +void VisualServer::immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex) { + immediate_vertex(p_immediate,Vector3(p_vertex.x,p_vertex.y,0)); +} + RID VisualServer::instance_create2(RID p_base, RID p_scenario) { RID instance = instance_create(); @@ -810,9 +1674,6 @@ VisualServer::VisualServer() { // ERR_FAIL_COND(singleton); singleton=this; - mm_policy=GLOBAL_DEF("render/mipmap_policy",0); - if (mm_policy<0 || mm_policy>2) - mm_policy=0; } diff --git a/servers/visual_server.h b/servers/visual_server.h index 4b91989507..2a8255b78b 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -50,9 +50,9 @@ class VisualServer : public Object { DVector<String> _shader_get_param_list(RID p_shader) const; void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far); - void _viewport_set_rect(RID p_viewport,const Rect2& p_rect); - Rect2 _viewport_get_rect(RID p_viewport) const; void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1)); + Array _get_array_from_surface(uint32_t p_format,DVector<uint8_t> p_vertex_data,int p_vertex_len,DVector<uint8_t> p_index_data,int p_index_len) const; + protected: RID _make_test_cube(); void _free_internal_rids(); @@ -61,6 +61,9 @@ protected: RID test_material; RID material_2d[16]; + + Error _surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,DVector<uint8_t> &r_vertex_array,int p_vertex_array_len,DVector<uint8_t> &r_index_array,int p_index_array_len,AABB &r_aabb,Vector<AABB> r_bone_aabb); + static VisualServer* (*create_func)(); static void _bind_methods(); public: @@ -68,28 +71,16 @@ public: static VisualServer *get_singleton(); static VisualServer *create(); - enum MipMapPolicy { - - MIPMAPS_ENABLED, - MIPMAPS_ENABLED_FOR_PO2, - MIPMAPS_DISABLED - }; - - - virtual void set_mipmap_policy(MipMapPolicy p_policy); - virtual MipMapPolicy get_mipmap_policy() const; - enum { NO_INDEX_ARRAY=-1, - CUSTOM_ARRAY_SIZE=8, ARRAY_WEIGHTS_SIZE=4, - MAX_PARTICLE_COLOR_PHASES=4, - MAX_PARTICLE_ATTRACTORS=4, CANVAS_ITEM_Z_MIN=-4096, CANVAS_ITEM_Z_MAX=4096, + MAX_GLOW_LEVELS=7, + @@ -106,7 +97,7 @@ public: TEXTURE_FLAG_CONVERT_TO_LINEAR=16, TEXTURE_FLAG_MIRRORED_REPEAT=32, /// Repeat texture, with alternate sections mirrored TEXTURE_FLAG_CUBEMAP=2048, - TEXTURE_FLAG_VIDEO_SURFACE=4096, + TEXTURE_FLAG_USED_FOR_STREAMING=4096, TEXTURE_FLAGS_DEFAULT=TEXTURE_FLAG_REPEAT|TEXTURE_FLAG_MIPMAPS|TEXTURE_FLAG_FILTER }; @@ -132,8 +123,6 @@ public: virtual uint32_t texture_get_width(RID p_texture) const=0; virtual uint32_t texture_get_height(RID p_texture) const=0; virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; - virtual bool texture_can_stream(RID p_texture) const=0; - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0; virtual void texture_set_path(RID p_texture,const String& p_path)=0; virtual String texture_get_path(RID p_texture) const=0; @@ -150,26 +139,31 @@ public: virtual void texture_debug_usage(List<TextureInfo> *r_info)=0; + virtual void textures_keep_original(bool p_enable)=0; + + /* SKYBOX API */ + + virtual RID skybox_create()=0; + virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0; /* SHADER API */ enum ShaderMode { - SHADER_MATERIAL, + SHADER_SPATIAL, SHADER_CANVAS_ITEM, - SHADER_POST_PROCESS, + SHADER_PARTICLES, + SHADER_MAX }; - virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL)=0; + virtual RID shader_create(ShaderMode p_mode=SHADER_SPATIAL)=0; virtual void shader_set_mode(RID p_shader,ShaderMode p_mode)=0; virtual ShaderMode shader_get_mode(RID p_shader) const=0; - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light, int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0)=0; - virtual String shader_get_fragment_code(RID p_shader) const=0; - virtual String shader_get_vertex_code(RID p_shader) const=0; - virtual String shader_get_light_code(RID p_shader) const=0; + virtual void shader_set_code(RID p_shader, const String& p_code)=0; + virtual String shader_get_code(RID p_shader) const=0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; @@ -186,113 +180,7 @@ public: virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0; - enum MaterialFlag { - MATERIAL_FLAG_VISIBLE, - MATERIAL_FLAG_DOUBLE_SIDED, - MATERIAL_FLAG_INVERT_FACES, ///< Invert front/back of the object - MATERIAL_FLAG_UNSHADED, - MATERIAL_FLAG_ONTOP, - MATERIAL_FLAG_LIGHTMAP_ON_UV2, - MATERIAL_FLAG_COLOR_ARRAY_SRGB, - MATERIAL_FLAG_MAX, - }; - - virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled)=0; - virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const=0; - - enum MaterialDepthDrawMode { - MATERIAL_DEPTH_DRAW_ALWAYS, - MATERIAL_DEPTH_DRAW_OPAQUE_ONLY, - MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA, - MATERIAL_DEPTH_DRAW_NEVER - }; - - virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode)=0; - virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const=0; - - enum MaterialBlendMode { - MATERIAL_BLEND_MODE_MIX, //default - MATERIAL_BLEND_MODE_ADD, - MATERIAL_BLEND_MODE_SUB, - MATERIAL_BLEND_MODE_MUL, - MATERIAL_BLEND_MODE_PREMULT_ALPHA - }; - - - virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode)=0; - virtual MaterialBlendMode material_get_blend_mode(RID p_material) const=0; - - virtual void material_set_line_width(RID p_material,float p_line_width)=0; - virtual float material_get_line_width(RID p_material) const=0; - - - //fixed material api - - virtual RID fixed_material_create()=0; - - enum FixedMaterialParam { - - FIXED_MATERIAL_PARAM_DIFFUSE, - FIXED_MATERIAL_PARAM_DETAIL, - FIXED_MATERIAL_PARAM_SPECULAR, - FIXED_MATERIAL_PARAM_EMISSION, - FIXED_MATERIAL_PARAM_SPECULAR_EXP, - FIXED_MATERIAL_PARAM_GLOW, - FIXED_MATERIAL_PARAM_NORMAL, - FIXED_MATERIAL_PARAM_SHADE_PARAM, - FIXED_MATERIAL_PARAM_MAX - }; - - enum FixedMaterialTexCoordMode { - - FIXED_MATERIAL_TEXCOORD_UV, - FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM, - FIXED_MATERIAL_TEXCOORD_UV2, - FIXED_MATERIAL_TEXCOORD_SPHERE - }; - - enum FixedMaterialFlags { - - FIXED_MATERIAL_FLAG_USE_ALPHA, - FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, - FIXED_MATERIAL_FLAG_USE_POINT_SIZE, - FIXED_MATERIAL_FLAG_DISCARD_ALPHA, - FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP, - FIXED_MATERIAL_FLAG_MAX, - }; - - - virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled)=0; - virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const=0; - - virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value)=0; - virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const=0; - - virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture)=0; - virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const=0; - - - enum FixedMaterialLightShader { - - FIXED_MATERIAL_LIGHT_SHADER_LAMBERT, - FIXED_MATERIAL_LIGHT_SHADER_WRAP, - FIXED_MATERIAL_LIGHT_SHADER_VELVET, - FIXED_MATERIAL_LIGHT_SHADER_TOON, - - }; - - - virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader)=0; - virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const=0; - - virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode)=0; - virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const=0; - - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform)=0; - virtual Transform fixed_material_get_uv_transform(RID p_material) const=0; - - virtual void fixed_material_set_point_size(RID p_material,float p_size)=0; - virtual float fixed_material_get_point_size(RID p_material) const=0; + virtual void material_set_line_width(RID p_material, float p_width)=0; /* MESH API */ @@ -321,8 +209,26 @@ public: ARRAY_FORMAT_BONES=1<<ARRAY_BONES, ARRAY_FORMAT_WEIGHTS=1<<ARRAY_WEIGHTS, ARRAY_FORMAT_INDEX=1<<ARRAY_INDEX, + + ARRAY_COMPRESS_BASE=(ARRAY_INDEX+1), + ARRAY_COMPRESS_VERTEX=1<<(ARRAY_VERTEX+ARRAY_COMPRESS_BASE), // mandatory + ARRAY_COMPRESS_NORMAL=1<<(ARRAY_NORMAL+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TANGENT=1<<(ARRAY_TANGENT+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_COLOR=1<<(ARRAY_COLOR+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV=1<<(ARRAY_TEX_UV+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV2=1<<(ARRAY_TEX_UV2+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_BONES=1<<(ARRAY_BONES+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_WEIGHTS=1<<(ARRAY_WEIGHTS+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_INDEX=1<<(ARRAY_INDEX+ARRAY_COMPRESS_BASE), + + ARRAY_FLAG_USE_2D_VERTICES=ARRAY_COMPRESS_INDEX<<1, + ARRAY_FLAG_USE_16_BIT_BONES=ARRAY_COMPRESS_INDEX<<2, + + ARRAY_COMPRESS_DEFAULT=ARRAY_COMPRESS_VERTEX|ARRAY_COMPRESS_NORMAL|ARRAY_COMPRESS_TANGENT|ARRAY_COMPRESS_COLOR|ARRAY_COMPRESS_TEX_UV|ARRAY_COMPRESS_TEX_UV2|ARRAY_COMPRESS_WEIGHTS + }; + enum PrimitiveType { PRIMITIVE_POINTS=0, PRIMITIVE_LINES=1, @@ -336,12 +242,10 @@ public: virtual RID mesh_create()=0; - virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false)=0; - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const=0; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const=0; + virtual void mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),uint32_t p_compress_format=ARRAY_COMPRESS_DEFAULT); + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>())=0; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat)=0; //this is used by each platform in a different way virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount)=0; virtual int mesh_get_morph_target_count(RID p_mesh) const=0; @@ -353,14 +257,24 @@ public: virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode)=0; virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const=0; - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false)=0; + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0; virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0; virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0; virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0; + + virtual DVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0; + virtual DVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0; + + virtual Array mesh_surface_get_arrays(RID p_mesh,int p_surface) const; + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0; virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0; + virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0; + virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0; + virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0; + virtual void mesh_remove_surface(RID p_mesh,int p_index)=0; virtual int mesh_get_surface_count(RID p_mesh) const=0; @@ -371,30 +285,45 @@ public: /* MULTIMESH API */ + virtual RID multimesh_create()=0; - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count)=0; + enum MultimeshTransformFormat { + MULTIMESH_TRANSFORM_2D, + MULTIMESH_TRANSFORM_3D, + }; + + enum MultimeshColorFormat { + MULTIMESH_COLOR_NONE, + MULTIMESH_COLOR_8BIT, + MULTIMESH_COLOR_FLOAT, + }; + + virtual void multimesh_allocate(RID p_multimesh,int p_instances,MultimeshTransformFormat p_transform_format,MultimeshColorFormat p_color_format)=0; virtual int multimesh_get_instance_count(RID p_multimesh) const=0; virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0; - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb)=0; virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Matrix32& p_transform)=0; virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0; virtual RID multimesh_get_mesh(RID p_multimesh) const=0; - virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const=0;; + virtual AABB multimesh_get_aabb(RID p_multimesh) const=0; virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0; + virtual Matrix32 multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0; virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0; virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0; virtual int multimesh_get_visible_instances(RID p_multimesh) const=0; + /* IMMEDIATE API */ virtual RID immediate_create()=0; virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID())=0; virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0; + virtual void immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex); virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0; virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0; virtual void immediate_color(RID p_immediate,const Color& p_color)=0; @@ -405,82 +334,15 @@ public: virtual void immediate_set_material(RID p_immediate,RID p_material)=0; virtual RID immediate_get_material(RID p_immediate) const=0; + /* SKELETON API */ - /* PARTICLES API */ - - virtual RID particles_create()=0; - - enum ParticleVariable { - PARTICLE_LIFETIME, - PARTICLE_SPREAD, - PARTICLE_GRAVITY, - PARTICLE_LINEAR_VELOCITY, - PARTICLE_ANGULAR_VELOCITY, - PARTICLE_LINEAR_ACCELERATION, - PARTICLE_RADIAL_ACCELERATION, - PARTICLE_TANGENTIAL_ACCELERATION, - PARTICLE_DAMPING, - PARTICLE_INITIAL_SIZE, - PARTICLE_FINAL_SIZE, - PARTICLE_INITIAL_ANGLE, - PARTICLE_HEIGHT, - PARTICLE_HEIGHT_SPEED_SCALE, - PARTICLE_VAR_MAX - }; - - virtual void particles_set_amount(RID p_particles, int p_amount)=0; - virtual int particles_get_amount(RID p_particles) const=0; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting)=0; - virtual bool particles_is_emitting(RID p_particles) const=0; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility)=0; - virtual AABB particles_get_visibility_aabb(RID p_particles) const=0; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents)=0; - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const=0; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity)=0; - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const=0; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points)=0; - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const=0; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal)=0; - virtual Vector3 particles_get_gravity_normal(RID p_particles) const=0; - - virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value)=0; - virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const=0; - - virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness)=0; - virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const=0; - - virtual void particles_set_color_phases(RID p_particles, int p_phases)=0; - virtual int particles_get_color_phases(RID p_particles) const=0; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos)=0; - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const=0; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color)=0; - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const=0; - - virtual void particles_set_attractors(RID p_particles, int p_attractors)=0; - virtual int particles_get_attractors(RID p_particles) const=0; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos)=0; - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const=0; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force)=0; - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const=0; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false)=0; - virtual RID particles_get_material(RID p_particles) const=0; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable)=0; - virtual bool particles_has_height_from_velocity(RID p_particles) const=0; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable)=0; - virtual bool particles_is_using_local_coordinates(RID p_particles) const=0; + virtual RID skeleton_create()=0; + virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0; + virtual int skeleton_get_bone_count(RID p_skeleton) const=0; + virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const=0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Matrix32& p_transform)=0; + virtual Matrix32 skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone)const =0; /* Light API */ @@ -490,99 +352,89 @@ public: LIGHT_SPOT }; - enum LightColor { - LIGHT_COLOR_DIFFUSE, - LIGHT_COLOR_SPECULAR - }; - enum LightParam { - LIGHT_PARAM_SPOT_ATTENUATION, - LIGHT_PARAM_SPOT_ANGLE, - LIGHT_PARAM_RADIUS, LIGHT_PARAM_ENERGY, + LIGHT_PARAM_SPECULAR, + LIGHT_PARAM_RANGE, LIGHT_PARAM_ATTENUATION, - LIGHT_PARAM_SHADOW_DARKENING, - LIGHT_PARAM_SHADOW_Z_OFFSET, - LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE, - LIGHT_PARAM_SHADOW_ESM_MULTIPLIER, - LIGHT_PARAM_SHADOW_BLUR_PASSES, + LIGHT_PARAM_SPOT_ANGLE, + LIGHT_PARAM_SPOT_ATTENUATION, + LIGHT_PARAM_SHADOW_MAX_DISTANCE, + LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, + LIGHT_PARAM_SHADOW_NORMAL_BIAS, + LIGHT_PARAM_SHADOW_BIAS, + LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, LIGHT_PARAM_MAX }; virtual RID light_create(LightType p_type)=0; - virtual LightType light_get_type(RID p_light) const=0; - - virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color)=0; - virtual Color light_get_color(RID p_light,LightColor p_type) const=0; + virtual void light_set_color(RID p_light,const Color& p_color)=0; + virtual void light_set_param(RID p_light,LightParam p_param,float p_value)=0; virtual void light_set_shadow(RID p_light,bool p_enabled)=0; - virtual bool light_has_shadow(RID p_light) const=0; - - virtual void light_set_volumetric(RID p_light,bool p_enabled)=0; - virtual bool light_is_volumetric(RID p_light) const=0; - + virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0; virtual void light_set_projector(RID p_light,RID p_texture)=0; - virtual RID light_get_projector(RID p_light) const=0; - - virtual void light_set_param(RID p_light, LightParam p_var, float p_value)=0; - virtual float light_get_param(RID p_light, LightParam p_var) const=0; - - enum LightOp { - - LIGHT_OPERATOR_ADD, - LIGHT_OPERATOR_SUB - }; - - virtual void light_set_operator(RID p_light,LightOp p_op)=0; - virtual LightOp light_get_operator(RID p_light) const=0; + virtual void light_set_negative(RID p_light,bool p_enable)=0; + virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0; // omni light enum LightOmniShadowMode { - LIGHT_OMNI_SHADOW_DEFAULT, LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, - LIGHT_OMNI_SHADOW_CUBEMAP + LIGHT_OMNI_SHADOW_CUBE, }; virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode)=0; - virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const=0; + + // omni light + enum LightOmniShadowDetail { + LIGHT_OMNI_SHADOW_DETAIL_VERTICAL, + LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL + }; + + virtual void light_omni_set_shadow_detail(RID p_light,LightOmniShadowDetail p_detail)=0; // directional light enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, - LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS }; virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode)=0; - virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const=0; + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0; + + /* PROBE API */ - enum LightDirectionalShadowParam { + virtual RID reflection_probe_create()=0; - LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE, - LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_SPLIT_WEIGHT, - LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE, + enum ReflectionProbeUpdateMode { + REFLECTION_PROBE_UPDATE_ONCE, + REFLECTION_PROBE_UPDATE_ALWAYS, }; - virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value)=0; - virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const=0; - //@TODO fallof model and all that stuff + virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode)=0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_color)=0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0; - /* SKELETON API */ - - virtual RID skeleton_create()=0; - virtual void skeleton_resize(RID p_skeleton,int p_bones)=0; - virtual int skeleton_get_bone_count(RID p_skeleton) const=0; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone)=0; /* ROOM API */ virtual RID room_create()=0; - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds)=0; - virtual BSP_Tree room_get_bounds(RID p_room) const=0; + virtual void room_add_bounds(RID p_room, const DVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0; + virtual void room_clear_bounds(RID p_room)=0; /* PORTAL API */ @@ -591,69 +443,85 @@ public: virtual RID portal_create()=0; virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0; - virtual Vector<Point2> portal_get_shape(RID p_portal) const=0; virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0; - virtual bool portal_is_enabled(RID p_portal) const=0; virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; - virtual float portal_get_disable_distance(RID p_portal) const=0; virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; - virtual Color portal_get_disabled_color(RID p_portal) const=0; - virtual void portal_set_connect_range(RID p_portal, float p_range) =0; - virtual float portal_get_connect_range(RID p_portal) const =0; + /* GI PROBE API */ - /* BAKED LIGHT API */ + virtual RID gi_probe_create()=0; - virtual RID baked_light_create()=0; - enum BakedLightMode { - BAKED_LIGHT_OCTREE, - BAKED_LIGHT_LIGHTMAPS - }; + virtual void gi_probe_set_bounds(RID p_probe,const AABB& p_bounds)=0; + virtual AABB gi_probe_get_bounds(RID p_probe) const=0; - virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode)=0; - virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const=0; + virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0; + virtual float gi_probe_get_cell_size(RID p_probe) const=0; - virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0; - virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0; + virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0; + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0; - virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0; - virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0; + virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data)=0; + virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0; - virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0; - virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; - virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; - virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; + virtual void gi_probe_set_energy(RID p_probe,float p_range)=0; + virtual float gi_probe_get_energy(RID p_probe) const=0; - virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; - virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; - virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled)=0; - virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const=0; + virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_compressed(RID p_probe) const=0; - virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color)=0; - virtual Color baked_light_get_realtime_color(RID p_baked_light) const=0; + /* PARTICLES API */ + + virtual RID particles_create()=0; + + virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0; + virtual void particles_set_amount(RID p_particles,int p_amount)=0; + virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0; + virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0; + virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_custom_aabb(RID p_particles,const AABB& p_aabb)=0; + virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0; + virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0; + virtual void particles_set_process_material(RID p_particles,RID p_material)=0; + + enum ParticlesEmissionShape { + PARTICLES_EMSSION_POINT, + PARTICLES_EMSSION_SPHERE, + PARTICLES_EMSSION_BOX, + PARTICLES_EMSSION_POINTS, + PARTICLES_EMSSION_SEGMENTS, + }; - virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy) = 0; - virtual float baked_light_get_realtime_energy(RID p_baked_light) const = 0; + virtual void particles_set_emission_shape(RID p_particles,ParticlesEmissionShape)=0; + virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0; + virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0; + virtual void particles_set_emission_points(RID p_particles,const DVector<Vector3>& p_points)=0; - /* BAKED LIGHT SAMPLER */ + enum ParticlesDrawOrder { + PARTICLES_DRAW_ORDER_INDEX, + PARTICLES_DRAW_ORDER_LIFETIME, + PARTICLES_DRAW_ORDER_VIEW_DEPTH, + }; - virtual RID baked_light_sampler_create()=0; + virtual void particles_set_draw_order(RID p_particles,ParticlesDrawOrder p_order)=0; - enum BakedLightSamplerParam { - BAKED_LIGHT_SAMPLER_RADIUS, - BAKED_LIGHT_SAMPLER_STRENGTH, - BAKED_LIGHT_SAMPLER_ATTENUATION, - BAKED_LIGHT_SAMPLER_DETAIL_RATIO, - BAKED_LIGHT_SAMPLER_MAX + enum ParticlesDrawPassMode { + PARTICLES_DRAW_PASS_MODE_QUAD, + PARTICLES_DRAW_PASS_MODE_MESH }; - virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; - virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; - virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; - virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; + virtual void particles_set_draw_passes(RID p_particles,int p_count)=0; + virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0; + virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0; + + virtual AABB particles_get_current_aabb(RID p_particles)=0; /* CAMERA API */ @@ -661,96 +529,80 @@ public: virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far)=0; virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far)=0; virtual void camera_set_transform(RID p_camera,const Transform& p_transform)=0; - - virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers)=0; - virtual uint32_t camera_get_visible_layers(RID p_camera) const=0; - + virtual void camera_set_cull_mask(RID p_camera,uint32_t p_layers)=0; virtual void camera_set_environment(RID p_camera,RID p_env)=0; - virtual RID camera_get_environment(RID p_camera) const=0; - virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable)=0; - virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const=0; /* - virtual void camera_add_layer(RID p_camera); - virtual void camera_layer_move_up(RID p_camera,int p_layer); - virtual void camera_layer_move_down(RID p_camera,int p_layer); - virtual void camera_layer_set_mask(RID p_camera,int p_layer,int p_mask); - virtual int camera_layer_get_mask(RID p_camera,int p_layer) const; - - enum CameraLayerFlag { - - FLAG_CLEAR_DEPTH, - FLAG_CLEAR_COLOR, - FLAG_IGNORE_FOG, + enum ParticlesCollisionMode { + PARTICLES_COLLISION_NONE, + PARTICLES_COLLISION_TEXTURE, + PARTICLES_COLLISION_CUBEMAP, }; - virtual void camera_layer_set_flag(RID p_camera,int p_layer,bool p_enable); - virtual bool camera_layer_get_flag(RID p_camera,int p_layer) const; + virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0; */ - - - /* VIEWPORT API */ + /* VIEWPORT TARGET API */ virtual RID viewport_create()=0; - virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0)=0; + virtual void viewport_set_size(RID p_viewport,int p_width,int p_height)=0; + virtual void viewport_set_active(RID p_viewport,bool p_active)=0; + virtual void viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport)=0; + + virtual void viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect=Rect2(),int p_screen=0)=0; virtual void viewport_detach(RID p_viewport)=0; - virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect)=0; - enum RenderTargetUpdateMode { - RENDER_TARGET_UPDATE_DISABLED, - RENDER_TARGET_UPDATE_ONCE, //then goes to disabled - RENDER_TARGET_UPDATE_WHEN_VISIBLE, // default - RENDER_TARGET_UPDATE_ALWAYS + enum ViewportUpdateMode { + VIEWPORT_UPDATE_DISABLED, + VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated + VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_ALWAYS }; - virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable)=0; - virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode)=0; - virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const=0; - virtual RID viewport_get_render_target_texture(RID p_viewport) const=0; - virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable)=0; - virtual bool viewport_get_render_target_vflip(RID p_viewport) const=0; - virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable)=0; - virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const=0; - virtual void viewport_render_target_clear(RID p_viewport)=0; - - virtual void viewport_queue_screen_capture(RID p_viewport)=0; - virtual Image viewport_get_screen_capture(RID p_viewport) const=0; - + virtual void viewport_set_update_mode(RID p_viewport,ViewportUpdateMode p_mode)=0; + virtual void viewport_set_vflip(RID p_viewport,bool p_enable)=0; + enum ViewportClearMode { - struct ViewportRect { - - int x,y,width,height; - ViewportRect() { x=y=width=height=0; } + VIEWPORT_CLEAR_ALWAYS, + VIEWPORT_CLEAR_NEVER, + VIEWPORT_CLEAR_ONLY_NEXT_FRAME }; - virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect)=0; - virtual ViewportRect viewport_get_rect(RID p_viewport) const=0; + virtual void viewport_set_clear_mode(RID p_viewport,ViewportClearMode p_clear_mode)=0; + + virtual RID viewport_get_texture(RID p_viewport) const=0; virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide)=0; virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide)=0; virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable)=0; + virtual void viewport_set_disable_3d(RID p_viewport,bool p_disable)=0; virtual void viewport_attach_camera(RID p_viewport,RID p_camera)=0; virtual void viewport_set_scenario(RID p_viewport,RID p_scenario)=0; - virtual RID viewport_get_attached_camera(RID p_viewport) const=0; - virtual RID viewport_get_scenario(RID p_viewport) const=0; virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas)=0; virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas)=0; virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset)=0; - virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const=0; virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled)=0; - virtual bool viewport_has_transparent_background(RID p_viewport) const=0; - virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform)=0; - virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const=0; virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer)=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; + + enum ViewportMSAA { + VIEWPORT_MSAA_DISABLED, + VIEWPORT_MSAA_2X, + VIEWPORT_MSAA_4X, + VIEWPORT_MSAA_8X, + VIEWPORT_MSAA_16X, + }; + virtual void viewport_set_msaa(RID p_viewport,ViewportMSAA p_msaa)=0; + virtual void viewport_set_hdr(RID p_viewport,bool p_enabled)=0; /* ENVIRONMENT API */ @@ -758,104 +610,61 @@ public: enum EnvironmentBG { - ENV_BG_KEEP, - ENV_BG_DEFAULT_COLOR, + ENV_BG_CLEAR_COLOR, ENV_BG_COLOR, - ENV_BG_TEXTURE, - ENV_BG_CUBEMAP, + ENV_BG_SKYBOX, ENV_BG_CANVAS, + ENV_BG_KEEP, ENV_BG_MAX }; virtual void environment_set_background(RID p_env,EnvironmentBG p_bg)=0; - virtual EnvironmentBG environment_get_background(RID p_env) const=0; - - enum EnvironmentBGParam { - - ENV_BG_PARAM_CANVAS_MAX_LAYER, - ENV_BG_PARAM_COLOR, - ENV_BG_PARAM_TEXTURE, - ENV_BG_PARAM_CUBEMAP, - ENV_BG_PARAM_ENERGY, - ENV_BG_PARAM_SCALE, - ENV_BG_PARAM_GLOW, - ENV_BG_PARAM_MAX - }; + virtual void environment_set_skybox(RID p_env,RID p_skybox)=0; + virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0; + virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0; + virtual void environment_set_bg_energy(RID p_env,float p_energy)=0; + virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0; + virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0; + //set default SSAO options + //set default SSR options + //set default SSSSS options - virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value)=0; - virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const=0; - - enum EnvironmentFx { - ENV_FX_AMBIENT_LIGHT, - ENV_FX_FXAA, - ENV_FX_GLOW, - ENV_FX_DOF_BLUR, - ENV_FX_HDR, - ENV_FX_FOG, - ENV_FX_BCS, - ENV_FX_SRGB, - ENV_FX_MAX + enum EnvironmentDOFBlurQuality { + ENV_DOF_BLUR_QUALITY_LOW, + ENV_DOF_BLUR_QUALITY_MEDIUM, + ENV_DOF_BLUR_QUALITY_HIGH, }; + virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0; - - virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled)=0; - virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_mode) const=0; - - enum EnvironmentFxBlurBlendMode { - ENV_FX_BLUR_BLEND_MODE_ADDITIVE, - ENV_FX_BLUR_BLEND_MODE_SCREEN, - ENV_FX_BLUR_BLEND_MODE_SOFTLIGHT, + enum EnvironmentGlowBlendMode { + GLOW_BLEND_MODE_ADDITIVE, + GLOW_BLEND_MODE_SCREEN, + GLOW_BLEND_MODE_SOFTLIGHT, + GLOW_BLEND_MODE_REPLACE, }; + virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0; + virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0; - enum EnvironmentFxHDRToneMapper { - ENV_FX_HDR_TONE_MAPPER_LINEAR, - ENV_FX_HDR_TONE_MAPPER_LOG, - ENV_FX_HDR_TONE_MAPPER_REINHARDT, - ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE, - }; - enum EnvironmentFxParam { - ENV_FX_PARAM_AMBIENT_LIGHT_COLOR, - ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY, - ENV_FX_PARAM_GLOW_BLUR_PASSES, - ENV_FX_PARAM_GLOW_BLUR_SCALE, - ENV_FX_PARAM_GLOW_BLUR_STRENGTH, - ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE, - ENV_FX_PARAM_GLOW_BLOOM, - ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD, - ENV_FX_PARAM_DOF_BLUR_PASSES, - ENV_FX_PARAM_DOF_BLUR_BEGIN, - ENV_FX_PARAM_DOF_BLUR_RANGE, - ENV_FX_PARAM_HDR_TONEMAPPER, - ENV_FX_PARAM_HDR_EXPOSURE, - ENV_FX_PARAM_HDR_WHITE, - ENV_FX_PARAM_HDR_GLOW_TRESHOLD, - ENV_FX_PARAM_HDR_GLOW_SCALE, - ENV_FX_PARAM_HDR_MIN_LUMINANCE, - ENV_FX_PARAM_HDR_MAX_LUMINANCE, - ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED, - ENV_FX_PARAM_FOG_BEGIN, - ENV_FX_PARAM_FOG_BEGIN_COLOR, - ENV_FX_PARAM_FOG_END_COLOR, - ENV_FX_PARAM_FOG_ATTENUATION, - ENV_FX_PARAM_FOG_BG, - ENV_FX_PARAM_BCS_BRIGHTNESS, - ENV_FX_PARAM_BCS_CONTRAST, - ENV_FX_PARAM_BCS_SATURATION, - ENV_FX_PARAM_MAX + enum EnvironmentToneMapper { + ENV_TONE_MAPPER_LINEAR, + ENV_TONE_MAPPER_REINHARDT, + ENV_TONE_MAPPER_FILMIC, + ENV_TONE_MAPPER_ACES }; - virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param)=0; - virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const=0; + virtual void environment_set_tonemap(RID p_env,EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_grey)=0; + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; + virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; + virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0; /* SCENARIO API */ - - virtual RID scenario_create()=0; enum ScenarioDebugMode { @@ -869,7 +678,7 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0; virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0; - virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0; + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv)=0; virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0; @@ -883,12 +692,14 @@ public: INSTANCE_IMMEDIATE, INSTANCE_PARTICLES, INSTANCE_LIGHT, + INSTANCE_REFLECTION_PROBE, INSTANCE_ROOM, INSTANCE_PORTAL, - INSTANCE_BAKED_LIGHT, - INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GI_PROBE, + INSTANCE_MAX, + /*INSTANCE_BAKED_LIGHT_SAMPLER,*/ - INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) + INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE) }; @@ -899,51 +710,29 @@ public: virtual RID instance_create()=0; // from can be mesh, light, poly, area and portal so far. virtual void instance_set_base(RID p_instance, RID p_base)=0; // from can be mesh, light, poly, area and portal so far. - virtual RID instance_get_base(RID p_instance) const=0; - virtual void instance_set_scenario(RID p_instance, RID p_scenario)=0; // from can be mesh, light, poly, area and portal so far. - virtual RID instance_get_scenario(RID p_instance) const=0; - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask)=0; - virtual uint32_t instance_get_layer_mask(RID p_instance) const=0; - - virtual AABB instance_get_base_aabb(RID p_instance) const=0; - virtual void instance_set_transform(RID p_instance, const Transform& p_transform)=0; - virtual Transform instance_get_transform(RID p_instance) const=0; - - - virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID)=0; - virtual uint32_t instance_get_object_instance_ID(RID p_instance) const=0; - + virtual void instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID)=0; virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight)=0; - virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const=0; - virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material)=0; virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton)=0; - virtual RID instance_get_skeleton(RID p_instance) const=0; - virtual void instance_set_exterior( RID p_instance, bool p_enabled )=0; - virtual bool instance_is_exterior( RID p_instance) const=0; - virtual void instance_set_room( RID p_instance, RID p_room )=0; - virtual RID instance_get_room( RID p_instance ) const =0; virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin )=0; - virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const =0; // don't use these in a game! - virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const=0; - virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0; - virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0; enum InstanceFlags { INSTANCE_FLAG_VISIBLE, INSTANCE_FLAG_BILLBOARD, INSTANCE_FLAG_BILLBOARD_FIX_Y, INSTANCE_FLAG_CAST_SHADOW, - INSTANCE_FLAG_RECEIVE_SHADOWS, INSTANCE_FLAG_DEPH_SCALE, INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, INSTANCE_FLAG_USE_BAKED_LIGHT, @@ -958,80 +747,53 @@ public: }; virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled)=0; - virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const=0; - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0; - virtual ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const = 0; - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material)=0; - virtual RID instance_geometry_get_material_override(RID p_instance) const=0; - - virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max)=0; - virtual float instance_geometry_get_draw_range_max(RID p_instance) const=0; - virtual float instance_geometry_get_draw_range_min(RID p_instance) const=0; - - virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0; - virtual RID instance_geometry_get_baked_light(RID p_instance) const=0; - virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0; - virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0; - virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0; - virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0; - - - virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0; - virtual bool instance_light_is_enabled(RID p_instance) const=0; + virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin)=0; + virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance)=0; /* CANVAS (2D) */ virtual RID canvas_create()=0; virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring)=0; - virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const=0; virtual void canvas_set_modulate(RID p_canvas,const Color& p_color)=0; - virtual RID canvas_item_create()=0; virtual void canvas_item_set_parent(RID p_item,RID p_parent)=0; - virtual RID canvas_item_get_parent(RID p_canvas_item) const=0; virtual void canvas_item_set_visible(RID p_item,bool p_visible)=0; - virtual bool canvas_item_is_visible(RID p_item) const=0; - virtual void canvas_item_set_light_mask(RID p_item,int p_mask)=0; - virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend)=0; - - virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport)=0; - - //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect)=0; - virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0; virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0; virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0; virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0; - virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0; - virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0; + virtual void canvas_item_set_modulate(RID p_item, const Color& p_color)=0; + virtual void canvas_item_set_self_modulate(RID p_item, const Color& p_color)=0; - virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity)=0; - virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const=0; + virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable)=0; - virtual void canvas_item_set_on_top(RID p_item, bool p_on_top)=0; - virtual bool canvas_item_is_on_top(RID p_item) const=0; + enum NinePatchAxisMode { + NINE_PATCH_STRETCH, + NINE_PATCH_TILE, + NINE_PATCH_TILE_FIT, + }; virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false)=0; virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color)=0; virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; - virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0; + virtual void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,NinePatchAxisMode p_x_axis_mode=NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode=NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0)=0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID())=0; virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1)=0; - virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID())=0; + virtual void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID())=0; + virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID())=0; virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0; - virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0; virtual void canvas_item_set_z(RID p_item, int p_z)=0; @@ -1039,7 +801,7 @@ public: virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0; virtual void canvas_item_clear(RID p_item)=0; - virtual void canvas_item_raise(RID p_item)=0; + virtual void canvas_item_set_draw_index(RID p_item,int p_index)=0; virtual void canvas_item_set_material(RID p_item, RID p_material)=0; @@ -1057,8 +819,8 @@ public: virtual void canvas_light_set_energy(RID p_light, float p_energy)=0; virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0; - virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; - virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask)=0; enum CanvasLightMode { CANVAS_LIGHT_MODE_ADD, @@ -1068,9 +830,20 @@ public: }; virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0; + + + enum CanvasLightShadowFilter { + CANVAS_LIGHT_FILTER_NONE, + CANVAS_LIGHT_FILTER_PCF3, + CANVAS_LIGHT_FILTER_PCF5, + CANVAS_LIGHT_FILTER_PCF9, + CANVAS_LIGHT_FILTER_PCF13, + }; + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; - virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0; + virtual void canvas_light_set_shadow_gradient_length(RID p_light, float p_length)=0; + virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter)=0; virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color)=0; @@ -1085,6 +858,7 @@ public: virtual RID canvas_occluder_polygon_create()=0; virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0; virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0; + enum CanvasOccluderPolygonCullMode { CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE, @@ -1092,21 +866,6 @@ public: }; virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0; - /* CANVAS ITEM MATERIAL */ - - virtual RID canvas_item_material_create()=0; - virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0; - virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; - virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0; - - - enum CanvasItemShadingMode { - CANVAS_ITEM_SHADING_NORMAL, - CANVAS_ITEM_SHADING_UNSHADED, - CANVAS_ITEM_SHADING_ONLY_LIGHT, - }; - - virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0; /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians @@ -1125,15 +884,6 @@ public: virtual void free( RID p_rid )=0; ///< free RIDs associated with the visual server - /* CUSTOM SHADING */ - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader)=0; - virtual RID custom_shade_model_get_shader(int p_model) const=0; - virtual void custom_shade_model_set_name(int p_model, const String& p_name)=0; - virtual String custom_shade_model_get_name(int p_model) const=0; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info)=0; - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const=0; - /* EVENT QUEUING */ virtual void draw()=0; @@ -1166,7 +916,6 @@ public: RID material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha,bool p_opaque_prepass); - /* TESTING */ virtual RID get_test_cube()=0; @@ -1185,7 +934,6 @@ public: enum Features { FEATURE_SHADERS, FEATURE_MULTITHREADED, - FEATURE_NEEDS_RELOAD_HOOK, }; virtual bool has_feature(Features p_feature) const=0; @@ -1200,19 +948,15 @@ public: VARIANT_ENUM_CAST( VisualServer::CubeMapSide ); VARIANT_ENUM_CAST( VisualServer::TextureFlags ); VARIANT_ENUM_CAST( VisualServer::ShaderMode ); -VARIANT_ENUM_CAST( VisualServer::MaterialFlag ); -VARIANT_ENUM_CAST( VisualServer::MaterialBlendMode ); -VARIANT_ENUM_CAST( VisualServer::ParticleVariable ); VARIANT_ENUM_CAST( VisualServer::ArrayType ); VARIANT_ENUM_CAST( VisualServer::ArrayFormat ); VARIANT_ENUM_CAST( VisualServer::PrimitiveType ); VARIANT_ENUM_CAST( VisualServer::LightType ); -VARIANT_ENUM_CAST( VisualServer::LightColor ); VARIANT_ENUM_CAST( VisualServer::LightParam ); VARIANT_ENUM_CAST( VisualServer::ScenarioDebugMode ); VARIANT_ENUM_CAST( VisualServer::InstanceType ); VARIANT_ENUM_CAST( VisualServer::RenderInfo ); -VARIANT_ENUM_CAST( VisualServer::MipMapPolicy ); + //typedef VisualServer VS; // makes it easier to use #define VS VisualServer |