diff options
Diffstat (limited to 'servers/visual')
-rw-r--r-- | servers/visual/rasterizer.cpp | 25 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 299 | ||||
-rw-r--r-- | servers/visual/rasterizer_dummy.cpp | 40 | ||||
-rw-r--r-- | servers/visual/rasterizer_dummy.h | 19 | ||||
-rw-r--r-- | servers/visual/shader_graph.h | 3 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 148 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 9 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 1176 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 237 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 36 |
10 files changed, 1549 insertions, 443 deletions
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index e160b4dccc..c3dcd83a31 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -79,7 +79,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { if (texcoords_used&(1<<VS::FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM)) { code+="uniform mat4 fmp_uv_xform;\n"; - code+="vec2 uv_xform = fmp_uv_xform * UV;\n"; + code+="vec2 uv_xform = (fmp_uv_xform * vec4(UV,0,1)).xy;\n"; } /* HANDLE NORMAL MAPPING */ @@ -96,8 +96,14 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { } else { uv_str=_TEXUVSTR(VS::FIXED_MATERIAL_PARAM_NORMAL); } - scode+="vec3 normal=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; - scode+="NORMAL = mix( NORMAL,mat3(TANGENT,BINORMAL,NORMAL) * normal, fmp_normal);\n"; + if (p_key.use_xy_normalmap) { + scode+="vec2 ywnormal=tex( fmp_normal_tex,"+uv_str+").wy * vec2(2.0,2.0) - vec2(1.0,1.0);\n"; + scode+="NORMALMAP=vec3(ywnormal,sqrt(1 - (ywnormal.x * ywnormal.x) - (ywnormal.y * ywnormal.y) ));\n"; + } else { + scode+="NORMALMAP=tex( fmp_normal_tex,"+uv_str+").xyz * vec3(2.0,2.0,1.0) - vec3(1.0,1.0,0.0);\n"; + } + scode+="NORMALMAP_DEPTH=fmp_normal;\n"; + code+=scode; } @@ -323,6 +329,7 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: fm.use_color_array=p_enabled; break; case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: fm.use_pointsize=p_enabled; break; case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: fm.discard_alpha=p_enabled; break; + case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: fm.use_xy_normalmap=p_enabled; break; } if (!fm.dirty_list.in_list()) @@ -341,6 +348,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: return fm.use_color_array;; break; case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: return fm.use_pointsize;; break; case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: return fm.discard_alpha;; break; + case VS::FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP: return fm.use_xy_normalmap;; break; + } @@ -355,12 +364,13 @@ RID Rasterizer::fixed_material_create() { FixedMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); + material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) { material_set_param(mat,_fixed_material_param_names[i],fm.param[i]); //must be there } fixed_material_dirty_list.add(&fm.dirty_list); - //print_line("FMC: "+itos(mat.get_id())); + //print_line("FMC: "+itos(mat.get_id())); return mat; } @@ -558,8 +568,9 @@ void Rasterizer::_update_fixed_materials() { } material_set_param(fm.self,_fixed_material_uv_xform_name,fm.uv_xform); - if (fm.use_pointsize) + if (fm.use_pointsize) { material_set_param(fm.self,_fixed_material_point_size_name,fm.point_size); + } } fixed_material_dirty_list.remove(fixed_material_dirty_list.first()); @@ -610,6 +621,10 @@ Rasterizer::Rasterizer() { _fixed_material_uv_xform_name="fmp_uv_xform"; _fixed_material_point_size_name="fmp_point_size"; + draw_viewport_func=NULL; + + ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4); + } RID Rasterizer::create_overdraw_debug_material() { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 5b07c633c3..92c7b8ac14 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -40,6 +40,9 @@ class Rasterizer { protected: + + typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); + RID create_default_material(); RID create_overdraw_debug_material(); @@ -56,6 +59,7 @@ protected: bool use_color_array:1; bool use_pointsize:1; bool discard_alpha:1; + bool use_xy_normalmap:1; bool valid:1; }; @@ -83,6 +87,7 @@ protected: bool use_color_array; bool discard_alpha; bool use_pointsize; + bool use_xy_normalmap; float point_size; Transform uv_xform; VS::FixedMaterialLightShader light_shader; @@ -102,6 +107,7 @@ protected: k.use_alpha=use_alpha; k.use_color_array=use_color_array; k.use_pointsize=use_pointsize; + k.use_xy_normalmap=use_xy_normalmap; k.discard_alpha=discard_alpha; k.light_shader=light_shader; k.valid=true; @@ -123,6 +129,7 @@ protected: use_color_array=false; use_pointsize=false; discard_alpha=false; + use_xy_normalmap=false; point_size=1.0; light_shader=VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT; for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) { @@ -183,6 +190,7 @@ public: virtual bool texture_has_alpha(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_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0; /* SHADER API */ @@ -199,6 +207,11 @@ public: 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; + + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name)=0; + /* COMMON MATERIAL API */ virtual RID material_create()=0; @@ -499,6 +512,7 @@ public: VS::BakedLightMode mode; RID octree_texture; + RID light_texture; float color_multiplier; //used for both lightmaps and octree Transform octree_transform; Map<int,RID> lightmaps; @@ -510,6 +524,7 @@ public: float lightmap_multiplier; int octree_steps; Vector2 octree_tex_pixel_size; + Vector2 light_tex_pixel_size; }; struct InstanceData { @@ -517,6 +532,7 @@ public: Transform transform; RID skeleton; RID material_override; + RID sampled_light; Vector<RID> light_instances; Vector<float> morph_values; BakedLightData *baked_light; @@ -550,7 +566,279 @@ public: CANVAS_RECT_FLIP_H=4, CANVAS_RECT_FLIP_V=8 }; - + + struct CanvasItem { + + struct Command { + + enum Type { + + TYPE_LINE, + TYPE_RECT, + TYPE_STYLE, + TYPE_PRIMITIVE, + TYPE_POLYGON, + TYPE_POLYGON_PTR, + TYPE_CIRCLE, + TYPE_TRANSFORM, + TYPE_BLEND_MODE, + TYPE_CLIP_IGNORE, + }; + + Type type; + }; + + struct CommandLine : public Command { + + Point2 from,to; + Color color; + float width; + 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 CommandStyle : public Command { + + Rect2 rect; + RID texture; + float margin[4]; + float draw_center; + Color color; + CommandStyle() { draw_center=true; type = TYPE_STYLE; } + }; + + 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 CommandPolygonPtr : public Command { + + const int* indices; + const Point2* points; + const Point2* uvs; + const Color* colors; + RID texture; + int count; + + CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } + }; + + 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 CommandBlendMode : public Command { + + VS::MaterialBlendMode blend_mode; + CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = VS::MATERIAL_BLEND_MODE_MIX; } + }; + 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 ontop; + VS::MaterialBlendMode blend_mode; + Vector<Command*> commands; + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + CanvasItem*next; + RID shader; + Map<StringName,Variant> shader_param; + uint32_t shader_version; + + + float final_opacity; + Matrix32 final_transform; + Rect2 final_clip_rect; + CanvasItem* final_clip_owner; + CanvasItem* shader_owner; + ViewportRender *vp_render; + + 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 CanvasItem::Command * const *cmd = &commands[0]; + + + for (int i=0;i<s;i++) { + + const CanvasItem::Command *c=cmd[i]; + Rect2 r; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); + r.pos=line->from; + r.expand_to(line->to); + } break; + case CanvasItem::Command::TYPE_RECT: { + + const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); + r=crect->rect; + + } break; + case CanvasItem::Command::TYPE_STYLE: { + + const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); + r=style->rect; + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); + r.pos=primitive->points[0]; + for(int i=1;i<primitive->points.size();i++) { + + r.expand_to(primitive->points[i]); + + } + } break; + case CanvasItem::Command::TYPE_POLYGON: { + + const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::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 CanvasItem::Command::TYPE_POLYGON_PTR: { + + const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); + int l = polygon->count; + if (polygon->indices != NULL) { + + r.pos=polygon->points[polygon->indices[0]]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[polygon->indices[i]]); + }; + } else { + r.pos=polygon->points[0]; + for (int i=1; i<polygon->count; i++) { + + r.expand_to(polygon->points[i]); + }; + }; + } break; + case CanvasItem::Command::TYPE_CIRCLE: { + + const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::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: { + + const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); + xf=transform->xform; + found_xform=true; + continue; + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + } break; + case CanvasItem::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; shader_owner=NULL;} + CanvasItem() { 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; shader_version=0; shader_owner=NULL;} + virtual ~CanvasItem() { clear(); } + }; + + + CanvasItemDrawViewportFunc draw_viewport_func; + + virtual void canvas_begin()=0; virtual void canvas_disable_blending()=0; virtual void canvas_set_opacity(float p_opacity)=0; @@ -564,7 +852,10 @@ public: 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)=0; 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)=0; + + /* ENVIRONMENT */ @@ -582,6 +873,10 @@ public: virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value)=0; virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const=0; + /* SAMPLED LIGHT */ + virtual RID sampled_light_dp_create(int p_width,int p_height)=0; + virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier)=0; + /*MISC*/ diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 637c251cf1..6c1b6697c1 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -221,6 +221,21 @@ void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_ } + +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 */ @@ -1607,6 +1622,11 @@ void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) { } +void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list) { + + +} + /* ENVIRONMENT */ RID RasterizerDummy::environment_create() { @@ -1679,6 +1699,18 @@ Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxPar } + +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 { @@ -1816,6 +1848,14 @@ void RasterizerDummy::free(const RID& 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 ); + }; } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 373564249e..c72149f88f 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -353,6 +353,13 @@ class RasterizerDummy : public Rasterizer { mutable RID_Owner<Environment> environment_owner; + struct SampledLight { + + int w,h; + }; + + mutable RID_Owner<SampledLight> sampled_light_owner; + struct ShadowBuffer; struct LightInstance { @@ -422,6 +429,12 @@ public: 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(); @@ -697,6 +710,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); virtual void canvas_set_transform(const Matrix32& p_transform); + virtual void canvas_render_items(CanvasItem *p_item_list); + /* ENVIRONMENT */ virtual RID environment_create(); @@ -713,6 +728,10 @@ public: 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*/ diff --git a/servers/visual/shader_graph.h b/servers/visual/shader_graph.h index 5c5079202f..fe305f3955 100644 --- a/servers/visual/shader_graph.h +++ b/servers/visual/shader_graph.h @@ -26,8 +26,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_GRAPH_H -#define SHADER_GRAPH_H #if 0 @@ -109,4 +107,3 @@ public: }; #endif -#endif diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 14d35e89b1..9a76a009a9 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -436,7 +436,10 @@ ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_le return Token(TK_INDENTIFIER,str); } - return Token(TK_ERROR,"Unknown character"); + 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))); } break; } @@ -463,9 +466,9 @@ Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,Stri if (t.type==TK_ERROR) { if (r_error) { - return ERR_COMPILATION_FAILED; *r_error=t.text; *r_err_line=line; + return ERR_COMPILATION_FAILED; } } @@ -765,16 +768,20 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ //constructors {"bool",TYPE_BOOL,{TYPE_BOOL,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}}, + {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec3",TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC2,TYPE_VOID}}, {"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}}, {"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 @@ -853,6 +860,9 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"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}}, {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, @@ -890,6 +900,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"normalize",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"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}}, @@ -952,10 +963,16 @@ const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ {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}}, @@ -1038,10 +1055,12 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ { "VERTEX", TYPE_VEC3}, - { "POSITION", 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}, @@ -1087,6 +1106,61 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ }; + + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ + + { "SRC_VERTEX", TYPE_VEC2}, + { "VERTEX", TYPE_VEC2}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "VAR1", TYPE_VEC4}, + { "VAR2", TYPE_VEC4}, + { "POINT_SIZE", TYPE_FLOAT}, + + //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}, + { "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} + +}; + +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ + + { "COLOR", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "LIGHT_DIR", TYPE_VEC2}, + { "LIGHT_DISTANCE", TYPE_FLOAT}, + { "LIGHT", TYPE_VEC3}, + { "POINT_COORD", TYPE_VEC2}, +// { "SCREEN_POS", TYPE_VEC2}, +// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID} + +}; + const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={ { "IN_COLOR", TYPE_VEC3}, @@ -1199,9 +1273,25 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper Variant data; switch(p_func->return_cache) { case TYPE_FLOAT: data = cdata[0]; break; - case TYPE_VEC2: data = Vector2(cdata[0],cdata[1]); break; - case TYPE_VEC3: data = Vector3(cdata[0],cdata[1],cdata[2]); break; - case TYPE_VEC4: data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); break; + case TYPE_VEC2: + if (cdata.size()==1) + data = Vector2(cdata[0],cdata[0]); + else + data = Vector2(cdata[0],cdata[1]); + + break; + case TYPE_VEC3: + if (cdata.size()==1) + data = Vector3(cdata[0],cdata[0],cdata[0]); + else + data = Vector3(cdata[0],cdata[1],cdata[2]); + break; + case TYPE_VEC4: + if (cdata.size()==1) + data = Plane(cdata[0],cdata[0],cdata[0],cdata[0]); + else + data = Plane(cdata[0],cdata[1],cdata[2],cdata[3]); + break; } cn->datatype=p_func->return_cache; @@ -2437,6 +2527,27 @@ Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,Comp idx++; } } 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++; + } + } 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++; + } + } 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++; + } + } break; case SHADER_POST_PROCESS: { int idx=0; while (postprocess_fragment_builtins_defs[idx].name) { @@ -2483,6 +2594,9 @@ Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc uint64_t t = OS::get_singleton()->get_ticks_usec(); Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column); + if (err!=OK) { + print_line("tokenizer error!"); + } double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0; //print_line("tokenize time: "+rtos(tf)); @@ -2531,6 +2645,28 @@ void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keyword 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); + idx++; + } + } 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++; + } + } break; + case SHADER_POST_PROCESS: { idx=0; while (postprocess_fragment_builtins_defs[idx].name) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 7e01368dd5..f79c219d85 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -105,6 +105,9 @@ public: SHADER_MATERIAL_VERTEX, SHADER_MATERIAL_FRAGMENT, SHADER_MATERIAL_LIGHT, + SHADER_CANVAS_ITEM_VERTEX, + SHADER_CANVAS_ITEM_FRAGMENT, + SHADER_CANVAS_ITEM_LIGHT, SHADER_POST_PROCESS, }; @@ -376,6 +379,12 @@ private: static const BuiltinsDef vertex_builtins_defs[]; static const BuiltinsDef fragment_builtins_defs[]; static const BuiltinsDef light_builtins_defs[]; + + static const BuiltinsDef ci_vertex_builtins_defs[]; + static const BuiltinsDef ci_fragment_builtins_defs[]; + static const BuiltinsDef ci_light_builtins_defs[]; + + static const BuiltinsDef postprocess_fragment_builtins_defs[]; static DataType get_token_datatype(TokenType p_type); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 21ecd4030d..dc0bff4cf4 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -157,6 +157,16 @@ void VisualServerRaster::shader_get_param_list(RID p_shader, List<PropertyInfo> } +void VisualServerRaster::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + rasterizer->shader_set_default_texture_param(p_shader,p_name,p_texture); +} + +RID VisualServerRaster::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + + return rasterizer->shader_get_default_texture_param(p_shader,p_name); +} + /* Material */ @@ -1109,8 +1119,12 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< int tex_w; int tex_h; + int light_tex_w; + int light_tex_h; bool is16; + bool has_light_tex=false; { + DVector<uint8_t>::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); @@ -1123,7 +1137,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< baked_light->data.octree_steps=decode_uint32(&r[16]); baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + baked_light->data.texture_multiplier=decode_uint32(&r[20]); + light_tex_w=decode_uint16(&r[24]); + light_tex_h=decode_uint16(&r[26]); + print_line("ltexw "+itos(light_tex_w)); + print_line("ltexh "+itos(light_tex_h)); + + if (light_tex_w>0 && light_tex_h>0) { + baked_light->data.light_tex_pixel_size.x=1.0/light_tex_w; + baked_light->data.light_tex_pixel_size.y=1.0/light_tex_h; + has_light_tex=true; + } else { + baked_light->data.light_tex_pixel_size=baked_light->data.octree_tex_pixel_size; + + } + baked_light->octree_aabb.pos.x=decode_float(&r[32]); @@ -1141,12 +1170,33 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< rasterizer->free(baked_light->data.octree_texture); baked_light->data.octree_texture=RID(); + baked_light->octree_tex_size.x=0; + baked_light->octree_tex_size.y=0; + } + } + + 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->light_tex_size.x=0; + baked_light->light_tex_size.y=0; } } 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); + 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); + 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); @@ -1159,6 +1209,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } + DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ @@ -1174,6 +1225,67 @@ DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) c } } +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) { + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + ERR_FAIL_COND(p_light.size()==0); + + int tex_w=baked_light->light_tex_size.x; + int tex_h=baked_light->light_tex_size.y; + + ERR_FAIL_COND(tex_w==0 && tex_h==0); + ERR_FAIL_COND(!baked_light->data.light_texture.is_valid()); + + + + 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); + rasterizer->texture_set_data(baked_light->data.light_texture,img); + + + +} + +DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + + if (rasterizer->is_texture(baked_light->data.light_texture)) { + + Image img = rasterizer->texture_get_data(baked_light->data.light_texture); + return img.get_data(); + } else { + return DVector<uint8_t>(); + } +} + + + +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + baked_light->sampler=p_sampler; + + + +} + +DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { + + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,DVector<int>()); + + return baked_light->sampler; + +} + + void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ VS_CHANGED; @@ -1192,6 +1304,84 @@ void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ } +/* BAKED LIGHT SAMPLER */ + +RID VisualServerRaster::baked_light_sampler_create() { + + BakedLightSampler * blsamp = memnew( BakedLightSampler ); + RID rid = baked_light_sampler_owner.make_rid(blsamp); + _update_baked_light_sampler_dp_cache(blsamp); + return rid; +} + +void VisualServerRaster::baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value){ + + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + ERR_FAIL_INDEX(p_param,BAKED_LIGHT_SAMPLER_MAX); + blsamp->params[p_param]=p_value; + _dependency_queue_update(p_baked_light_sampler,true); +} + +float VisualServerRaster::baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const{ + + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + ERR_FAIL_INDEX_V(p_param,BAKED_LIGHT_SAMPLER_MAX,0); + return blsamp->params[p_param]; +} + +void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp) { + + int res = blsamp->resolution; + blsamp->dp_cache.resize(res*res*2); + Vector3 *dp_normals=blsamp->dp_cache.ptr(); + + for(int p=0;p<2;p++) { + float sign = p==0?1:-1; + int ofs = res*res*p; + for(int i=0;i<res;i++) { + for(int j=0;j<res;j++) { + + Vector2 v( + (i/float(res))*2.0-1.0, + (j/float(res))*2.0-1.0 + ); + + float l=v.length(); + if (l>1.0) { + v/=l; + l=1.0; //clamp to avoid imaginary + } + v*=(2*l)/(l*l+1); //inverse of the dual paraboloid function + Vector3 n = Vector3(v.x,v.y,sign*sqrtf(MAX(1 - v.dot(v),0))); //reconstruction of z + n.y*=sign; + dp_normals[j*res+i+ofs]=n; + } + } + } + +} + +void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ + + ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + VS_CHANGED; + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND(!blsamp); + blsamp->resolution=p_resolution; + _update_baked_light_sampler_dp_cache(blsamp); + +} +int VisualServerRaster::baked_light_sampler_get_resolution(RID p_baked_light_sampler) const{ + + BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); + ERR_FAIL_COND_V(!blsamp,0); + return blsamp->resolution; +} + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1202,7 +1392,7 @@ RID VisualServerRaster::camera_create() { } void VisualServerRaster::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) { - VS_CHANGED; + VS_CHANGED Camera *camera = camera_owner.get( p_camera ); ERR_FAIL_COND(!camera); camera->type=Camera::PERSPECTIVE; @@ -1226,7 +1416,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr VS_CHANGED; Camera *camera = camera_owner.get( p_camera ); ERR_FAIL_COND(!camera); - camera->transform=p_transform; + camera->transform=p_transform.orthonormalized(); } @@ -1786,6 +1976,17 @@ void VisualServerRaster::scenario_set_environment(RID p_scenario, RID p_environm } +void VisualServerRaster::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + VS_CHANGED; + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment=p_environment; + + +} + RID VisualServerRaster::scenario_get_environment(RID p_scenario, RID p_environment) const{ const Scenario *scenario = scenario_owner.get(p_scenario); @@ -1932,6 +2133,20 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_sampler_info) { + + while (instance->baked_light_sampler_info->owned_instances.size()) { + + instance_geometry_set_baked_light_sampler(instance->baked_light_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->baked_light_sampler_info->sampled_light); + } + memdelete( instance->baked_light_sampler_info ); + instance->baked_light_sampler_info=NULL; + } + instance->data.morph_values.clear(); } @@ -1981,6 +2196,16 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { //instance->portal_info = memnew(Instance::PortalInfo); //instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_BAKED_LIGHT_SAMPLER; + instance->baked_light_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->baked_light_sampler_info->sampler=baked_light_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(); @@ -2596,11 +2821,50 @@ RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance,RID() ); if (instance->baked_light) - instance->baked_light->self; + return instance->baked_light->self; return RID(); } + +void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->sampled_light) { + instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); + instance->data.sampled_light=RID(); + } + + if(p_baked_light_sampler.is_valid()) { + Instance *sampler_instance = instance_owner.get( p_baked_light_sampler ); + ERR_FAIL_COND( !sampler_instance ); + ERR_FAIL_COND( sampler_instance->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER ); + instance->sampled_light=sampler_instance; + instance->sampled_light->baked_light_sampler_info->owned_instances.insert(instance); + } else { + instance->sampled_light=NULL; + } + + instance->data.sampled_light=RID(); + +} + +RID VisualServerRaster::instance_geometry_get_baked_light_sampler(RID p_instance) const { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + + if (instance->sampled_light) + return instance->sampled_light->self; + else + return RID(); + +} + + void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ VS_CHANGED; @@ -2736,6 +3000,13 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { pairable=true; } + if (p_instance->base_type == INSTANCE_BAKED_LIGHT_SAMPLER) { + + pairable_mask=(1<<INSTANCE_BAKED_LIGHT); + pairable=true; + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { base_type|=INSTANCE_ROOMLESS_MASK; @@ -2848,6 +3119,16 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { new_aabb=baked_light->octree_aabb; } break; + case VisualServer::INSTANCE_BAKED_LIGHT_SAMPLER: { + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light_sampler); + float radius = baked_light_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; + default: {} } @@ -3071,129 +3352,6 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) { canvas_item->clip=p_clip; } -const Rect2& VisualServerRaster::CanvasItem::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 CanvasItem::Command * const *cmd = &commands[0]; - - - for (int i=0;i<s;i++) { - - const CanvasItem::Command *c=cmd[i]; - Rect2 r; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); - r.pos=line->from; - r.expand_to(line->to); - } break; - case CanvasItem::Command::TYPE_RECT: { - - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); - r=crect->rect; - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); - r=style->rect; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); - r.pos=primitive->points[0]; - for(int i=1;i<primitive->points.size();i++) { - - r.expand_to(primitive->points[i]); - - } - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::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 CanvasItem::Command::TYPE_POLYGON_PTR: { - - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); - int l = polygon->count; - if (polygon->indices != NULL) { - - r.pos=polygon->points[polygon->indices[0]]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[polygon->indices[i]]); - }; - } else { - r.pos=polygon->points[0]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[i]); - }; - }; - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::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: { - - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); - xf=transform->xform; - found_xform=true; - continue; - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - } break; - case CanvasItem::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 VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) { @@ -3531,6 +3689,83 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen canvas_item->commands.push_back(bm); }; +void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { + + ERR_FAIL_COND(p_z<CANVAS_ITEM_Z_MIN || p_z>CANVAS_ITEM_Z_MAX); + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z=p_z; + +} + +void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z_relative=p_enable; + +} + +void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->use_parent_shader=p_enable; + +} + +void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->shader=p_shader; +} + +RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{ + + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND_V(!canvas_item,RID()); + return canvas_item->shader; + +} + +void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){ + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); + ERR_FAIL_COND(!canvas_item); + if (p_value.get_type()==Variant::NIL) + canvas_item->shader_param.erase(p_param); + else + canvas_item->shader_param[p_param]=p_value; + +} +Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{ + + CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item ); + ERR_FAIL_COND_V(!canvas_item,Variant()); + if (!canvas_item->shader_param.has(p_param)) { + ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant()); + return rasterizer->shader_get_default_param(canvas_item->shader,p_param); + } + + return canvas_item->shader_param[p_param]; +} + + +void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->sort_y=p_enable; +} + + void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { VS_CHANGED; @@ -3742,6 +3977,17 @@ void VisualServerRaster::free( RID p_rid ) { baked_light_owner.free(p_rid); memdelete(baked_light); + } else if (baked_light_sampler_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); + ERR_FAIL_COND(!baked_light_sampler); + //if (baked_light->data.octree_texture.is_valid()) + // rasterizer->free(baked_light->data.octree_texture); + baked_light_sampler_owner.free(p_rid); + memdelete(baked_light_sampler); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3793,7 +4039,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); instance_geometry_set_baked_light(p_rid,RID()); + instance_geometry_set_baked_light_sampler(p_rid,RID()); instance_set_base(p_rid,RID()); + if (instance->data.skeleton.is_valid()) instance_attach_skeleton(p_rid,RID()); @@ -4937,6 +5185,15 @@ void* VisualServerRaster::instance_pair(void *p_self, OctreeElementID, Instance //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_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER,NULL); + B->baked_light_sampler_info->baked_lights.insert(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -4986,6 +5243,15 @@ void VisualServerRaster::instance_unpair(void *p_self, OctreeElementID, Instance self->_portal_attempt_connect(A); self->_portal_attempt_connect(B); + } else if (A->base_type==INSTANCE_BAKED_LIGHT || B->base_type==INSTANCE_BAKED_LIGHT) { + + if (B->base_type==INSTANCE_BAKED_LIGHT) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_BAKED_LIGHT_SAMPLER); + B->baked_light_sampler_info->baked_lights.erase(A); + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { if (B->base_type==INSTANCE_ROOM) @@ -5177,6 +5443,308 @@ void VisualServerRaster::_cull_room(Camera *p_camera, Instance *p_room,Instance } +void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instance *p_sampled_light,bool p_linear_colorspace) { + + + BakedLightSampler *sampler_opts = p_sampled_light->baked_light_sampler_info->sampler; + int res = sampler_opts->resolution; + int dp_size = res*res*2; + Color * dp_map = (Color*)alloca( sizeof(Color)*dp_size); //allocate the dual parabolloid colors + Vector3 * dp_normals = (Vector3*)alloca( sizeof(Vector3)*dp_size); //allocate the dual parabolloid normals + const Vector3 * dp_src_normals = p_sampled_light->baked_light_sampler_info->sampler->dp_cache.ptr(); + + + if (!p_sampled_light->baked_light_sampler_info->sampled_light.is_valid() || p_sampled_light->baked_light_sampler_info->resolution!=sampler_opts->resolution) { + if (p_sampled_light->baked_light_sampler_info->sampled_light.is_valid()) { + rasterizer->free(p_sampled_light->baked_light_sampler_info->sampled_light); + } + + p_sampled_light->baked_light_sampler_info->resolution=sampler_opts->resolution; + p_sampled_light->baked_light_sampler_info->sampled_light=rasterizer->sampled_light_dp_create(sampler_opts->resolution,sampler_opts->resolution*2); + + + } + + + zeromem(dp_map,sizeof(Color)*dp_size); + bool valid=false; + int samples=0; + + + for(Set<Instance*>::Element *E=p_sampled_light->baked_light_sampler_info->baked_lights.front();E;E=E->next()) { + + Instance *bl = E->get(); + if (bl->baked_light_info->baked_light->sampler.size()==0) + continue; //not usable + + + Matrix3 norm_xform = bl->baked_light_info->affine_inverse.basis;//.inverse(); + for(int i=0;i<dp_size;i++) { + dp_normals[i]=norm_xform.xform(dp_src_normals[i]).normalized(); + } + + //normals in place + + + //sample octree + + float r = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + float att = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_ATTENUATION]; + float str = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_STRENGTH]; + Vector3 s = p_sampled_light->data.transform.basis.get_scale(); + + r*=MAX(MAX(s.x,s.y),s.z); + AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); + //ok got octree local AABB + + DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); + const int *rptr = rp.ptr(); + + int first = rptr[1]; + int depth = rptr[2]; + bool islinear = rptr[3]&1; + depth+=1; + + AABB aabb; + aabb.pos.x=decode_float((const uint8_t*)&rptr[4]); + aabb.pos.y=decode_float((const uint8_t*)&rptr[5]); + aabb.pos.z=decode_float((const uint8_t*)&rptr[6]); + aabb.size.x=decode_float((const uint8_t*)&rptr[7]); + aabb.size.y=decode_float((const uint8_t*)&rptr[8]); + aabb.size.z=decode_float((const uint8_t*)&rptr[9]); + + uint32_t *stack=(uint32_t*)alloca(depth*sizeof(uint32_t)); + int *stack_ptr=(int*)alloca(depth*sizeof(int)); + AABB *aabb_stack=(AABB*)alloca(depth*sizeof(AABB)); + + stack[0]=0; + stack_ptr[0]=first; + aabb_stack[0]=aabb; + Vector3 center = sample_aabb.pos + sample_aabb.size * 0.5; + + + int stack_pos=0; + Color max_col; + + //int reso = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]; + + int lalimit = sample_aabb.get_longest_axis_index(); + float limit = sampler_opts->params[VS::BAKED_LIGHT_SAMPLER_DETAIL_RATIO]*sample_aabb.size[lalimit]; + + + while(true) { + + + bool leaf = (rptr[ stack_ptr[stack_pos] ]>>16)==0; + + if (aabb_stack[stack_pos].size[lalimit]<limit) { + leaf=true; + } + + + if (leaf) { + + Vector3 from = aabb_stack[stack_pos].pos + aabb_stack[stack_pos].size * 0.5; + Vector3 norm = (from-center).normalized(); + + + Color col; + col.r = ((rptr[ stack_ptr[stack_pos] ]&0xFFFF)/256.0); + col.g = ((rptr[ stack_ptr[stack_pos]+1 ]>>16)/256.0); + col.b = ((rptr[ stack_ptr[stack_pos]+1 ]&0xFFFF)/256.0); + + + max_col.r = MAX(max_col.r,col.r); + max_col.g = MAX(max_col.g,col.g); + max_col.b = MAX(max_col.b,col.b); + + if (!islinear && p_linear_colorspace) { + col=col.to_linear(); + } + + float distance; + + if (aabb_stack[stack_pos].has_point(center)) { + distance=0; + } else { + + Vector3 support = aabb_stack[stack_pos].get_support(norm); + distance = Math::absf(norm.dot(support)-norm.dot(center)); + + } + + if (distance>r) + distance=r; + + float mult = Math::pow(1.0-distance/r,att)*str; + if (mult>0) { + col.r*=mult; + col.g*=mult; + col.b*=mult; + + + + for(int i=0;i<dp_size;i++) { + float mult2 = norm.dot(dp_normals[i]); + if (mult2<0) + mult2=0; + Color col2(col.r*mult2,col.g*mult2,col.b*mult2,1.0); + dp_map[i].r=MAX(dp_map[i].r,col2.r); + dp_map[i].g=MAX(dp_map[i].g,col2.g); + dp_map[i].b=MAX(dp_map[i].b,col2.b); + } + + } + + samples++; + //nothing is valid unless you hit a leaf + valid=true; + stack_pos--; + } else if ((stack[stack_pos]&0xFF)<8) { + + int i = stack[stack_pos]&0xFF; + int base = (stack[stack_pos]>>8); + + if (!((rptr[ stack_ptr[stack_pos] ]>>16)&(1<<i))) { + //no bit, no test + stack[stack_pos]=(base<<8)+(i+1); + continue; + } + + stack[stack_pos]=((base+1)<<8)+(i+1); + + AABB child_aabb = aabb_stack[stack_pos]; + child_aabb.size*=0.5; + if (i&1) + child_aabb.pos.x+=child_aabb.size.x; + if (i&2) + child_aabb.pos.y+=child_aabb.size.y; + if (i&4) + child_aabb.pos.z+=child_aabb.size.z; + + if (!child_aabb.intersects(sample_aabb)) { + continue; + } + + if (child_aabb.encloses(sample_aabb)) { + stack[stack_pos]=(base<<8)|8; //don't test the rest + } + + stack_pos++; + ERR_FAIL_COND(stack_pos>=depth); + + stack[stack_pos]=0; + stack_ptr[stack_pos]=rptr[ stack_ptr[stack_pos-1]+2+base ]; + aabb_stack[stack_pos]=child_aabb; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + + } + + //print_line("samples "+itos(samples) ); + + if (valid) { + + for(int i=0;i<res;i++) { + //average seams to avoid aliasing + { + //top + int ofs1 = i; + int ofs2 = dp_size-res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //bottom + int ofs1 = res*res-res+i; + int ofs2 = res*res+i; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //left + int ofs1 = i*res; + int ofs2 = res*res+(res-i-1)*res; + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + { + //right + int ofs1 = i*res+(res-1); + int ofs2 = res*res+(res-i-1)*res+(res-1); + Color avg( + (dp_map[ofs1].r+dp_map[ofs2].r)*0.5, + (dp_map[ofs1].g+dp_map[ofs2].g)*0.5, + (dp_map[ofs1].b+dp_map[ofs2].b)*0.5, + 1.0 + ); + dp_map[ofs1]=avg; + dp_map[ofs2]=avg; + } + + } + + rasterizer->sampled_light_dp_update(p_sampled_light->baked_light_sampler_info->sampled_light,dp_map,1.0); + for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { + + F->get()->data.sampled_light=p_sampled_light->baked_light_sampler_info->sampled_light; + } + + + } else { + + 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 + } + } + + + + +/* + highp vec3 vtx = vertex_interp; + vtx.z*=dual_paraboloid.y; //side to affect + vtx.z+=0.01; + dp_clip=vtx.z; + highp float len=length( vtx ); + vtx=normalize(vtx); + vtx.xy/=1.0+vtx.z; + vtx.z = len*dual_paraboloid.x; // it's a reciprocal(len - z_near) / (z_far - z_near); + vtx+=normalize(vtx)*0.025; + vtx.z = vtx.z * 2.0 - 1.0; // fit to clipspace + vertex_interp=vtx; +*/ + + + + +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5228,6 +5796,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 2 - CULL */ int cull_count = p_scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); light_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())); @@ -5388,6 +5957,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S keep=true; } + + } @@ -5400,6 +5971,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S cull_range.min=min; if (max>cull_range.max) cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->baked_light_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->baked_light_sampler_info->last_pass=render_pass; + } + } } } @@ -5479,7 +6057,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } - { + { //this should eventually change to //assign shadows by distance to camera SortArray<Instance*,_InstanceLightsort> sorter; sorter.sort(light_cull_result,light_cull_count); @@ -5500,15 +6078,31 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S } } + /* ENVIRONMENT */ - - /* STEP 6 - PROCESS GEOMETRY AND DRAW SCENE*/ - RID environment; if (p_camera->env.is_valid()) //camera has more environment priority environment=p_camera->env; - else + else if (p_scenario->environment.is_valid()) environment=p_scenario->environment; + else + environment=p_scenario->fallback_environment; + + + /* 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(p_camera->transform,light_sampler_cull_result[i],islinear); + } + + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); @@ -5551,7 +6145,41 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S rasterizer->end_scene(); } -void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity) { + +void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect) { + + + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *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,1.0,0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i]); + } + +} + + +void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect) { + + VisualServerRaster *self=(VisualServerRaster*)(p_self); + Viewport *vp=(Viewport*)p_vp; + self->_draw_viewport(vp,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y); + self->rasterizer->canvas_begin(); + +} + +void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) { CanvasItem *ci = p_canvas_item; @@ -5570,200 +6198,100 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (global_rect.intersects(p_clip_rect) && ci->viewport.is_valid() && viewport_owner.owns(ci->viewport)) { - Viewport *vp = viewport_owner.get(ci->viewport); + Viewport *vp = viewport_owner.get(ci->viewport); Point2i from = xform.get_origin() + Point2(viewport_rect.x,viewport_rect.y); Point2i size = rect.size; size.x *= xform[0].length(); size.y *= xform[1].length(); + ci->vp_render = memnew( Rasterizer::CanvasItem::ViewportRender ); + ci->vp_render->owner=this; + ci->vp_render->udata=vp; + ci->vp_render->rect=Rect2(from.x, + from.y, + size.x, + size.y); +/* _draw_viewport(vp, from.x, from.y, size.x, size.y); +*/ + //rasterizer->canvas_begin(); + } else { + ci->vp_render=NULL; + } - rasterizer->canvas_begin(); + if (ci->use_parent_shader && p_shader_owner) + ci->shader_owner=p_shader_owner; + else { + p_shader_owner=ci; + ci->shader_owner=NULL; } - int s = ci->commands.size(); - bool reclip=false; float opacity = ci->opacity * p_opacity; -#ifndef ONTOP_DISABLED - CanvasItem **child_items = ci->child_items.ptr(); + int child_item_count=ci->child_items.size(); - int top_item_count=0; - CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*)); + CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*)); + copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*)); if (ci->clip) { - rasterizer->canvas_set_clip(true,global_rect); - canvas_clip=global_rect; - } - - for(int i=0;i<child_item_count;i++) { + ci->final_clip_rect=global_rect; + ci->final_clip_owner=ci; - if (child_items[i]->ontop) - top_items[top_item_count++]=child_items[i]; - else { - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); - } + } else { + ci->final_clip_owner=p_canvas_clip; } -#endif - - if (s!=0) { - - //Rect2 rect( ci->rect.pos + p_ofs, ci->rect.size); - - if (p_clip_rect.intersects(global_rect)) { - - rasterizer->canvas_begin_rect(xform); - rasterizer->canvas_set_opacity( opacity * ci->self_opacity ); - rasterizer->canvas_set_blend_mode( ci->blend_mode ); - - CanvasItem::Command **commands = &ci->commands[0]; - - for (int i=0;i<s;i++) { - CanvasItem::Command *c=commands[i]; + if (ci->sort_y) { - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); - rasterizer->canvas_draw_line(line->from,line->to,line->color,line->width); - } break; - case CanvasItem::Command::TYPE_RECT: { - - CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); -// rasterizer->canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); -#if 0 - int flags=0; - - if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { - flags|=Rasterizer::CANVAS_RECT_REGION; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { - flags|=Rasterizer::CANVAS_RECT_TILE; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_H; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_V; - } -#else - - int flags=rect->flags; -#endif - rasterizer->canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); - rasterizer->canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); - - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); - rasterizer->canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); - - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); - static const int numpoints=32; - Vector2 points[numpoints+1]; - points[numpoints]=circle->pos; - int indices[numpoints*3]; - - for(int i=0;i<numpoints;i++) { - - points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; - indices[i*3+0]=i; - indices[i*3+1]=(i+1)%numpoints; - indices[i*3+2]=numpoints; - } - rasterizer->canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); - //rasterizer->canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); - rasterizer->canvas_set_transform(transform->xform); - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); - rasterizer->canvas_set_blend_mode(bm->blend_mode); - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); - if (canvas_clip!=Rect2()) { - - if (ci->ignore!=reclip) { - if (ci->ignore) { - - rasterizer->canvas_set_clip(false,Rect2()); - reclip=true; - } else { - rasterizer->canvas_set_clip(true,canvas_clip); - reclip=false; - } - } - } + SortArray<CanvasItem*,CanvasItemPtrSort> sorter; + sorter.sort(child_items,child_item_count); + } + for(int i=0;i<child_item_count;i++) { - } break; - } - } - rasterizer->canvas_end_rect(); - } + if (child_items[i]->ontop) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner); } - if (reclip) { + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) { + //something to draw? + ci->final_transform=xform; + ci->final_opacity=opacity * ci->self_opacity; - rasterizer->canvas_set_clip(true,canvas_clip); - } + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; -#ifndef ONTOP_DISABLED + int zidx = p_z-CANVAS_ITEM_Z_MIN; - for(int i=0;i<top_item_count;i++) { + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; - _render_canvas_item(top_items[i],xform,p_clip_rect,opacity); - } + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } -#else - for(int i=0;i<p_canvas_item->child_items.size();i++) { + ci->next=NULL; - _render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity); } -#endif + for(int i=0;i<child_item_count;i++) { - if (ci->clip) { - rasterizer->canvas_set_clip(false,Rect2()); - canvas_clip=Rect2(); + if (!child_items[i]->ontop) + continue; + _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner); } } @@ -5773,29 +6301,61 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans rasterizer->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; + } + } - Canvas::ChildItem& ci=p_canvas->child_items[i]; - _render_canvas_item(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height); + if (!has_mirror) { - //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x!=0) { + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; } - if (ci.mirror.y!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); } - if (ci.mirror.y!=0 && ci.mirror.x!=0) { - Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i]); } + } else { + + for(int i=0;i<l;i++) { + + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,clip_rect); + + //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,clip_rect); + } + if (ci.mirror.y!=0) { + + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,clip_rect); + } + + } } } @@ -5819,6 +6379,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ desired_rect.x+=p_ofs_x; desired_rect.y+=p_ofs_y; + // if the viewport is different than the actual one, change it if ( p_viewport->render_target.is_valid() || viewport_rect.x != desired_rect.x || @@ -5828,7 +6389,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ viewport_rect=desired_rect; - rasterizer->set_viewport(viewport_rect); + rasterizer->set_viewport(viewport_rect); } @@ -5876,6 +6437,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ if (p_viewport->queue_capture) { rasterizer->capture_viewport(&p_viewport->capture); + p_viewport->queue_capture = false; } //restore @@ -5956,7 +6518,7 @@ void VisualServerRaster::_draw_viewports() { rasterizer->set_viewport(viewport_rect); } - rasterizer->canvas_begin(); + rasterizer->canvas_begin(); rasterizer->canvas_disable_blending(); rasterizer->canvas_begin_rect(Matrix32()); rasterizer->canvas_draw_rect(E->get()->rt_to_screen_rect,0,Rect2(Point2(),E->get()->rt_to_screen_rect.size),E->get()->render_target_texture,Color(1,1,1)); @@ -5975,7 +6537,14 @@ void VisualServerRaster::_draw_viewports() { int window_w = OS::get_singleton()->get_video_mode(E->get()).width; int window_h = OS::get_singleton()->get_video_mode(E->get()).height; - _draw_viewport(vp,0,0,window_w,window_h); + Rect2 r(0,0,vp->rect.width,vp->rect.height); + if (r.size.width==0) + r.size.width=window_w; + if (r.size.height==0) + r.size.height=window_w; + + + _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); } @@ -6204,6 +6773,7 @@ RID VisualServerRaster::get_test_cube() { VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { rasterizer=p_rasterizer; + rasterizer->draw_viewport_func=_render_canvas_item_viewport; instance_update_list=NULL; render_pass=0; clear_color=Color(0.3,0.3,0.3,1.0); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 49e7996c59..6c4e15827a 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -51,6 +51,7 @@ class VisualServerRaster : public VisualServer { MAX_LIGHTS_CULLED=256, MAX_ROOM_CULL=32, MAX_EXTERIOR_PORTALS=128, + MAX_LIGHT_SAMPLERS=256, INSTANCE_ROOMLESS_MASK=(1<<20) @@ -84,18 +85,36 @@ class VisualServerRaster : public VisualServer { 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); struct Camera { enum Type { @@ -169,6 +188,7 @@ class VisualServerRaster : public VisualServer { List<Instance*>::Element *RE; Instance *baked_light; List<Instance*>::Element *BLE; + Instance *sampled_light; bool exterior; uint64_t last_render_pass; @@ -179,6 +199,8 @@ class VisualServerRaster : public VisualServer { InstanceSet lights; bool light_cache_dirty; + + struct RoomInfo { Transform affine_inverse; @@ -235,6 +257,23 @@ class VisualServerRaster : public VisualServer { Transform affine_inverse; List<Instance*> owned_instances; }; + + struct BakedLightSamplerInfo { + + Set<Instance*> baked_lights; + Set<Instance*> owned_instances; + BakedLightSampler *sampler; + int resolution; + Vector<Color> light_bufer; + RID sampled_light; + uint64_t last_pass; + Transform xform; // viewspace normal to lightspace, might not use one. + BakedLightSamplerInfo() { + sampler=NULL; + last_pass=0; + resolution=0; + } + }; struct ParticlesInfo { @@ -247,6 +286,7 @@ class VisualServerRaster : public VisualServer { ParticlesInfo *particles_info; PortalInfo * portal_info; BakedLightInfo * baked_light_info; + BakedLightSamplerInfo * baked_light_sampler_info; Instance() { @@ -282,6 +322,8 @@ class VisualServerRaster : public VisualServer { baked_light=NULL; baked_light_info=NULL; + baked_light_sampler_info=NULL; + sampled_light=NULL; BLE=NULL; light_cache_dirty=true; @@ -320,6 +362,7 @@ class VisualServerRaster : public VisualServer { List<RID> directional_lights; RID environment; + RID fallback_environment; Instance *dirty_instances; @@ -328,143 +371,44 @@ class VisualServerRaster : public VisualServer { - - struct CanvasItem { - - struct Command { - - enum Type { - - TYPE_LINE, - TYPE_RECT, - TYPE_STYLE, - TYPE_PRIMITIVE, - TYPE_POLYGON, - TYPE_POLYGON_PTR, - TYPE_CIRCLE, - TYPE_TRANSFORM, - TYPE_BLEND_MODE, - TYPE_CLIP_IGNORE, - }; - - Type type; - }; - - struct CommandLine : public Command { - - Point2 from,to; - Color color; - float width; - 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 CommandStyle : public Command { - - Rect2 rect; - RID texture; - float margin[4]; - float draw_center; - Color color; - CommandStyle() { draw_center=true; type = TYPE_STYLE; } - }; - - 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 CommandPolygonPtr : public Command { + struct CanvasItem : public Rasterizer::CanvasItem { - const int* indices; - const Point2* points; - const Point2* uvs; - const Color* colors; - RID texture; - int count; - - CommandPolygonPtr() { type = TYPE_POLYGON_PTR; count = 0; } - }; - - 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 CommandBlendMode : public Command { - - MaterialBlendMode blend_mode; - CommandBlendMode() { type = TYPE_BLEND_MODE; blend_mode = MATERIAL_BLEND_MODE_MIX; }; - }; - struct CommandClipIgnore : public Command { - - bool ignore; - CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; }; - }; RID parent; // canvas it belongs to List<CanvasItem*>::Element *E; - Matrix32 xform; - bool clip; - bool visible; - bool ontop; + RID viewport; + int z; + bool z_relative; + bool sort_y; float opacity; float self_opacity; - MaterialBlendMode blend_mode; - RID viewport; + bool use_parent_shader; + - mutable bool custom_rect; - mutable bool rect_dirty; - mutable Rect2 rect; - - Vector<Command*> commands; Vector<CanvasItem*> child_items; - const Rect2& get_rect() const; - void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true;}; - CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; } - ~CanvasItem() { clear(); } + + CanvasItem() { + E=NULL; + z=0; + opacity=1; + self_opacity=1; + sort_y=false; + use_parent_shader=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 Canvas { @@ -594,6 +538,9 @@ class VisualServerRaster : public VisualServer { int exterior_portal_cull_count; bool exterior_visited; + Instance *light_sampler_cull_result[MAX_LIGHT_SAMPLERS]; + int light_samplers_culled; + Instance *room_cull_result[MAX_ROOM_CULL]; int room_cull_count; bool room_cull_enabled; @@ -629,6 +576,7 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Portal> portal_owner; mutable RID_Owner<BakedLight> baked_light_owner; + mutable RID_Owner<BakedLightSampler> baked_light_sampler_owner; mutable RID_Owner<Camera> camera_owner; mutable RID_Owner<Viewport> viewport_owner; @@ -649,8 +597,12 @@ class VisualServerRaster : public VisualServer { bool _test_portal_cull(Camera *p_camera, Instance *p_portal_from, Instance *p_portal_to); void _cull_portal(Camera *p_camera, Instance *p_portal,Instance *p_from_portal); void _cull_room(Camera *p_camera, Instance *p_room,Instance *p_from_portal=NULL); + void _process_sampled_light(const Transform &p_camera, Instance *p_sampled_light, bool p_linear_colorspace); + void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); - void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect,float p_opacity); + static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); + void _render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect); + void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner); void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -700,6 +652,10 @@ public: 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; + + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -944,12 +900,28 @@ public: 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; + 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; + + 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; + 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; 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); + /* BAKED LIGHT SAMPLER */ + + virtual RID baked_light_sampler_create(); + + 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; + + 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; + /* CAMERA API */ virtual RID camera_create(); @@ -1030,6 +1002,8 @@ public: 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); + /* INSTANCING API */ @@ -1085,6 +1059,9 @@ public: 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; + 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; @@ -1135,6 +1112,18 @@ public: 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_shader(RID p_item, RID p_shader); + virtual RID canvas_item_get_shader(RID p_item) const; + + virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable); + + + virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value); + virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const; virtual void canvas_item_clear(RID p_item); virtual void canvas_item_raise(RID p_item); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index f1ba4c453b..b59fdbc66a 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -653,6 +653,10 @@ public: 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); @@ -909,6 +913,12 @@ public: 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); @@ -916,6 +926,14 @@ public: FUNC1(baked_light_clear_lightmaps,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); @@ -929,6 +947,7 @@ public: 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); @@ -998,6 +1017,7 @@ public: 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 */ @@ -1053,6 +1073,9 @@ public: 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); @@ -1107,6 +1130,19 @@ public: 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); + + FUNC2(canvas_item_set_shader,RID, RID ); + FUNC1RC(RID,canvas_item_get_shader,RID ); + + FUNC2(canvas_item_set_use_parent_shader,RID, bool ); + + + FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&); + FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&); + FUNC1(canvas_item_clear,RID); FUNC1(canvas_item_raise,RID); |