summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_server_sw.h4
-rw-r--r--servers/audio/sample_manager_sw.h2
-rw-r--r--servers/physics/broad_phase_octree.cpp2
-rw-r--r--servers/physics/constraint_sw.h2
-rw-r--r--servers/physics/shape_sw.h4
-rw-r--r--servers/physics/space_sw.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.cpp2
-rw-r--r--servers/physics_2d/constraint_2d_sw.h2
-rw-r--r--servers/physics_2d/shape_2d_sw.h4
-rw-r--r--servers/physics_2d/space_2d_sw.h2
-rw-r--r--servers/register_server_types.cpp8
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.h8
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.h8
-rw-r--r--servers/visual/particle_system_sw.cpp412
-rw-r--r--servers/visual/particle_system_sw.h131
-rw-r--r--servers/visual/rasterizer.cpp117
-rw-r--r--servers/visual/rasterizer.h1060
-rw-r--r--servers/visual/rasterizer_dummy.cpp1961
-rw-r--r--servers/visual/rasterizer_dummy.h791
-rw-r--r--servers/visual/shader_language.cpp4617
-rw-r--r--servers/visual/shader_language.h433
-rw-r--r--servers/visual/shader_types.cpp182
-rw-r--r--servers/visual/shader_types.h27
-rw-r--r--servers/visual/visual_server_canvas.cpp1268
-rw-r--r--servers/visual/visual_server_canvas.h214
-rw-r--r--servers/visual/visual_server_global.cpp10
-rw-r--r--servers/visual/visual_server_global.h26
-rw-r--r--servers/visual/visual_server_light_baker.cpp6
-rw-r--r--servers/visual/visual_server_light_baker.h29
-rw-r--r--servers/visual/visual_server_raster.cpp219
-rw-r--r--servers/visual/visual_server_raster.h933
-rw-r--r--servers/visual/visual_server_scene.cpp3580
-rw-r--r--servers/visual/visual_server_scene.h587
-rw-r--r--servers/visual/visual_server_viewport.cpp568
-rw-r--r--servers/visual/visual_server_viewport.h150
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp212
-rw-r--r--servers/visual/visual_server_wrap_mt.h739
-rw-r--r--servers/visual_server.cpp1653
-rw-r--r--servers/visual_server.h846
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