diff options
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 127 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_gles2.h | 4 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 40 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.h | 5 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 130 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 2 | ||||
-rw-r--r-- | scene/2d/canvas_item.cpp | 86 | ||||
-rw-r--r-- | scene/2d/canvas_item.h | 15 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 3 | ||||
-rw-r--r-- | scene/resources/material.cpp | 141 | ||||
-rw-r--r-- | scene/resources/material.h | 62 | ||||
-rw-r--r-- | scene/resources/shader.cpp | 2 | ||||
-rw-r--r-- | scene/resources/shader.h | 19 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 7 | ||||
-rw-r--r-- | servers/visual/shader_language.cpp | 75 | ||||
-rw-r--r-- | servers/visual/shader_language.h | 9 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 36 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 5 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 5 | ||||
-rw-r--r-- | servers/visual_server.h | 6 |
20 files changed, 583 insertions, 196 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 59f844904e..5617f5bd0b 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -1411,6 +1411,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { material_shader.free_custom_shader(shader->custom_code_id); } break; + case VS::SHADER_CANVAS_ITEM: { + canvas_shader.free_custom_shader(shader->custom_code_id); + } break; } shader->custom_code_id=0; @@ -1422,6 +1425,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { shader->custom_code_id=material_shader.create_custom_shader(); } break; + case VS::SHADER_CANVAS_ITEM: { + shader->custom_code_id=canvas_shader.create_custom_shader(); + } break; } _shader_make_dirty(shader); @@ -4518,7 +4524,33 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { } material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); - } else { + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Vector<const char*> enablers; + + if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { + enablers.push_back("#define USE_TIME\n"); + uses_time=true; + } + if (fragment_flags.uses_normal) { + enablers.push_back("#define NORMAL_USED\n"); + } + if (light_flags.uses_light) { + enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); + } + if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) + enablers.push_back("#define ENABLE_VAR1_INTERP\n"); + if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) + enablers.push_back("#define ENABLE_VAR2_INTERP\n"); + if (fragment_flags.uses_texscreen) { + enablers.push_back("#define ENABLE_TEXSCREEN\n"); + } + if (fragment_flags.uses_screen_uv) { + enablers.push_back("#define ENABLE_SCREEN_UV\n"); + } + + canvas_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); + //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); } @@ -4529,6 +4561,7 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { p_shader->has_texscreen=fragment_flags.uses_texscreen; p_shader->has_screen_uv=fragment_flags.uses_screen_uv; p_shader->can_zpass=!fragment_flags.uses_discard && !vertex_flags.vertex_code_writes_vertex; + p_shader->uses_normal=fragment_flags.uses_normal || light_flags.uses_normal; p_shader->uses_time=uses_time; p_shader->version++; @@ -7722,6 +7755,7 @@ void RasterizerGLES2::canvas_begin() { canvas_tex=RID(); //material_shader.unbind(); canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); canvas_shader.bind(); canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); _set_color_attrib(Color(1,1,1)); @@ -8219,8 +8253,20 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { CanvasItem *current_clip=NULL; + RID last_shader; + + Transform canvas_transform; + canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); + float csy = 1.0; + if (current_rt && current_rt_vflip) + csy = -1.0; + + canvas_transform.scale( Vector3( 2.0f / viewport.width, csy * -2.0f / viewport.height, 1.0f ) ); + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + while(p_item_list) { CanvasItem *ci=p_item_list; @@ -8231,6 +8277,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { } memdelete(ci->vp_render); ci->vp_render=NULL; + last_shader=RID(); } if (current_clip!=ci->final_clip_owner) { @@ -8248,10 +8295,86 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { glDisable(GL_SCISSOR_TEST); } } + + //begin rect + + if (ci->shader!=last_shader) { + + Shader *shader = NULL; + if (ci->shader.is_valid()) { + shader = shader_owner.get(ci->shader); + if (shader && !shader->valid) { + shader=NULL; + } + } + + if (shader) { + canvas_shader.set_custom_shader(shader->custom_code_id); + canvas_shader.bind(); + + if (ci->shader_version!=shader->version) { + //todo optimize uniforms + ci->shader_version=shader->version; + } + //this can be optimized.. + int tex_id=1; + int idx=0; + for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + + + Map<StringName,Variant>::Element *F=ci->shader_param.find(E->key()); + Variant &v=F?F->get():E->get().default_value; + if (v.get_type()==Variant::_RID || v.get_type()==Variant::OBJECT) { + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + RID tex = v; + Texture *t=texture_owner.get(tex); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + + } else { + canvas_shader.set_custom_uniform(idx,v); + } + + idx++; + } + + + if (shader->has_texscreen && framebuffer.active) { + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,tex_id); + glActiveTexture(GL_TEXTURE0+tex_id); + glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); + + } + if (shader->has_screen_uv) { + canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height)); + } + + if (shader->uses_time) { + canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0)); + draw_next_frame=true; + } + //if uses TIME - draw_next_frame=true + + } else { + canvas_shader.set_custom_shader(0); + } + + canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform); + } + canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform); canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32()); + bool reclip=false; if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { @@ -8291,6 +8414,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { int cc=ci->commands.size(); CanvasItem::Command **commands = ci->commands.ptr(); + canvas_opacity = ci->final_opacity; + for(int i=0;i<cc;i++) { CanvasItem::Command *c=commands[i]; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index f97d112395..f0dae00b53 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -191,6 +191,7 @@ class RasterizerGLES2 : public Rasterizer { bool writes_vertex; bool uses_discard; bool uses_time; + bool uses_normal; Map<StringName,ShaderLanguage::Uniform> uniforms; StringName first_texture; @@ -214,6 +215,7 @@ class RasterizerGLES2 : public Rasterizer { writes_vertex=false; uses_discard=false; uses_time=false; + uses_normal=false; } @@ -1199,7 +1201,7 @@ class RasterizerGLES2 : public Rasterizer { RID overdraw_material; mutable MaterialShaderGLES2 material_shader; - CanvasShaderGLES2 canvas_shader; + mutable CanvasShaderGLES2 canvas_shader; BlurShaderGLES2 blur_shader; CopyShaderGLES2 copy_shader; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 8eed423b8a..204a81d193 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -181,6 +181,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a if (vnode->name==vname_normalmap) { uses_normalmap=true; } + if (vnode->name==vname_normal) { + uses_normal=true; + } if (vnode->name==vname_screen_uv) { uses_screen_uv=true; } @@ -552,6 +555,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_light=false; uses_time=false; uses_normalmap=false; + uses_normal=false; vertex_code_writes_vertex=false; uniforms=r_uniforms; flags=&r_flags; @@ -562,6 +566,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_var1_interp=false; r_flags.use_var2_interp=false; r_flags.uses_normalmap=false; + r_flags.uses_normal=false; String error; int errline,errcol; @@ -584,6 +589,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_light=uses_light; r_flags.uses_time=uses_time; r_flags.uses_normalmap=uses_normalmap; + r_flags.uses_normal=uses_normalmap; r_code_line=code; r_globals_line=global_code; @@ -721,6 +727,39 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[2]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[2]["TIME"]="time"; + mode_replace_table[3]["SRC_VERTEX"]="src_vtx"; + mode_replace_table[3]["VERTEX"]="outvec.xy"; + mode_replace_table[3]["UV"]="uv_interp"; + mode_replace_table[3]["COLOR"]="color_interp"; + mode_replace_table[3]["VAR1"]="var1_interp"; + mode_replace_table[3]["VAR2"]="var2_interp"; + mode_replace_table[3]["POINT_SIZE"]="gl_PointSize"; + mode_replace_table[3]["WORLD_MATRIX"]="modelview_matrix"; + mode_replace_table[3]["PROJECTION_MATRIX"]="projection_matrix"; + mode_replace_table[3]["EXTRA_MATRIX"]="extra_matrix"; + mode_replace_table[3]["TIME"]="time"; + + mode_replace_table[4]["POSITION"]="gl_Position"; + mode_replace_table[4]["NORMAL"]="normal"; + mode_replace_table[4]["UV"]="uv_interp"; + mode_replace_table[4]["COLOR"]="color_interp"; + mode_replace_table[4]["TEXTURE"]="texture"; + mode_replace_table[4]["VAR1"]="var1_interp"; + mode_replace_table[4]["VAR2"]="var2_interp"; + mode_replace_table[4]["SCREEN_UV"]="screen_uv"; + mode_replace_table[4]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[4]["TIME"]="time"; + + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["NORMAL"]="normal"; + mode_replace_table[5]["LIGHT_DIR"]="light_dir"; + mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance"; + mode_replace_table[5]["LIGHT"]="light"; + mode_replace_table[5]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[5]["TIME"]="time"; + + + //mode_replace_table[2]["SCREEN_POS"]="SCREEN_POS"; //mode_replace_table[2]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; @@ -741,5 +780,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_light="LIGHT"; vname_time="TIME"; vname_normalmap="NORMALMAP"; + vname_normal="NORMAL"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 5012414c8b..47ba4aa474 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -51,6 +51,7 @@ private: bool uses_time; bool uses_screen_uv; bool uses_normalmap; + bool uses_normal; bool vertex_code_writes_vertex; Flags *flags; @@ -68,6 +69,7 @@ private: StringName vname_light; StringName vname_time; StringName vname_normalmap; + StringName vname_normal; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -79,7 +81,7 @@ private: String replace_string(const StringName& p_string); - Map<StringName,StringName> mode_replace_table[3]; + Map<StringName,StringName> mode_replace_table[9]; Map<StringName,StringName> replace_table; public: @@ -101,6 +103,7 @@ public: bool use_var2_interp; bool uses_light; bool uses_time; + bool uses_normal; }; Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index f36741d586..3e7e54e0fe 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -18,19 +18,56 @@ attribute highp vec2 uv_attrib; // attrib:4 varying vec2 uv_interp; varying vec4 color_interp; +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform highp mat4 light_matrix; +varying vec4 light_tex_pos; + +#endif + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + //uniform bool snap_pixels; +VERTEX_SHADER_GLOBALS + void main() { color_interp = color_attrib; uv_interp = uv_attrib; highp vec4 outvec = vec4(vertex, 1.0); +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec.xy+0.5); +#endif + + +#ifdef USE_LIGHTING + + light_tex_pos.xy = light_matrix * outvec; + light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong + #endif + + gl_Position = projection_matrix * outvec; } @@ -54,17 +91,106 @@ varying vec4 color_interp; #endif +#if defined(ENABLE_SCREEN_UV) + +uniform vec2 screen_uv_mult; + +#endif + +#if defined(ENABLE_TEXSCREEN) + +uniform vec2 texscreen_screen_mult; +uniform sampler2D texscreen_tex; + +#endif + + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform sampler2D light_texture; +varying vec4 light_tex_pos; + +#ifdef USE_SHADOWS + +uniform sampler2D shadow_texture; +uniform float shadow_attenuation; + +#endif + +#endif + +FRAGMENT_SHADER_GLOBALS + + void main() { vec4 color = color_interp; - +#if defined(NORMAL_USED) + vec3 normal = vec3(0,0,1); +#endif + color *= texture2D( texture, uv_interp ); +#if defined(ENABLE_SCREEN_UV) + vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; +#endif +{ +FRAGMENT_SHADER_CODE +} #ifdef DEBUG_ENCODED_32 highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); color = vec4(vec3(enc32),1.0); #endif +#ifdef USE_LIGHTING + + float att=1.0; + + vec3 light = texture2D(light_texture,light_tex_pos).rgb; +#ifdef USE_SHADOWS + //this might not be that great on mobile? + float light_dist = length(light_texture.zw); + float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5; + float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0)); + if (light_dist>shadow_dist) { + light*=shadow_attenuation; + } +//use shadows +#endif + +#if defined(USE_LIGHT_SHADER_CODE) +//light is written by the light shader +{ + vec2 light_dir = normalize(light_tex_pos.zw); + float light_distance = length(light_tex_pos.zw); +LIGHT_SHADER_CODE +} +#else + +#if defined(NORMAL_USED) + vec2 light_normal = normalize(light_tex_pos.zw); + light = color.rgb * light * max(dot(light_normal,normal),0); +#endif + + color.rgb=light; +//light shader code +#endif + +//use lighting +#endif // color.rgb*=color.a; gl_FragColor = color; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index a3a26ddb25..45d13da828 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -134,7 +134,7 @@ int OS_Windows::get_video_driver_count() const { } const char * OS_Windows::get_video_driver_name(int p_driver) const { - return p_driver=="GLES2"; + return "GLES2"; } OS::VideoMode OS_Windows::get_default_video_mode() const { diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index f90da51eea..c28bf71e04 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -720,6 +720,84 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{ return behind; } +void CanvasItem::set_shader(const Ref<Shader>& p_shader) { + + ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM); + +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->disconnect("changed",this,"_shader_changed"); + } +#endif + shader=p_shader; + +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->connect("changed",this,"_shader_changed"); + } +#endif + + RID rid; + if (shader.is_valid()) + rid=shader->get_rid(); + VS::get_singleton()->canvas_item_set_shader(canvas_item,rid); + _change_notify(); //properties for shader exposed +} + +Ref<Shader> CanvasItem::get_shader() const{ + + return shader; +} + +void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) { + + VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value); +} + +Variant CanvasItem::get_shader_param(const StringName& p_param) const { + + return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param); +} + +bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) { + + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (pr) { + set_shader_param(pr,p_value); + return true; + } + } + return false; +} + +bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{ + + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret=get_shader_param(pr); + return true; + } + } + return false; + +} +void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{ + + if (shader.is_valid()) { + shader->get_param_list(p_list); + } +} + +#ifdef TOOLS_ENABLED +void CanvasItem::_shader_changed() { + + _change_notify(); +} +#endif void CanvasItem::_bind_methods() { @@ -761,7 +839,9 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top); ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top); - +#ifdef TOOLS_ENABLED + ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed); +#endif //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0)); @@ -786,6 +866,9 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d); //ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport); + ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader); + ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader); + BIND_VMETHOD(MethodInfo("_draw")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") ); @@ -795,6 +878,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") ); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") ); //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled")); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index dbf8fd79e9..7c162d9c81 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -32,6 +32,7 @@ #include "scene/main/node.h" #include "scene/resources/texture.h" #include "scene/main/scene_main_loop.h" +#include "scene/resources/shader.h" class CanvasLayer; class Viewport; @@ -80,6 +81,8 @@ private: bool block_transform_notify; bool behind; + Ref<Shader> shader; + mutable Matrix32 global_transform; mutable bool global_invalid; @@ -99,8 +102,9 @@ private: void _queue_sort_children(); void _sort_children(); - - +#ifdef TOOLS_ENABLED + void _shader_changed(); +#endif void _notify_transform(CanvasItem *p_node); void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); } @@ -108,6 +112,9 @@ private: protected: + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } @@ -204,7 +211,11 @@ public: RID get_canvas() const; Ref<World2D> get_world_2d() const; + void set_shader(const Ref<Shader>& p_shader); + Ref<Shader> get_shader() const; + void set_shader_param(const StringName& p_param,const Variant& p_value); + Variant get_shader_param(const StringName& p_param) const; CanvasItem(); ~CanvasItem(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index cf49979118..2592751274 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -500,14 +500,13 @@ void register_scene_types() { ObjectTypeDB::register_type<Mesh>(); ObjectTypeDB::register_virtual_type<Material>(); ObjectTypeDB::register_type<FixedMaterial>(); - //ObjectTypeDB::register_type<ParticleSystemMaterial>(); - //ObjectTypeDB::register_type<UnshadedMaterial>(); ObjectTypeDB::register_type<ShaderMaterial>(); ObjectTypeDB::register_type<RoomBounds>(); ObjectTypeDB::register_virtual_type<Shader>(); ObjectTypeDB::register_virtual_type<ShaderGraph>(); ObjectTypeDB::register_type<MaterialShaderGraph>(); ObjectTypeDB::register_type<MaterialShader>(); + ObjectTypeDB::register_type<CanvasItemShader>(); ObjectTypeDB::add_compatibility_type("Shader","MaterialShader"); ObjectTypeDB::add_compatibility_type("ParticleSystemMaterial","FixedMaterial"); ObjectTypeDB::add_compatibility_type("UnshadedMaterial","FixedMaterial"); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index faba339fe1..355cc8884c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -467,10 +467,20 @@ bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) { return true; } else { - String n = p_name; - if (n.begins_with("param/")) { - VisualServer::get_singleton()->material_set_param(material,String(n.ptr()+6),p_value); - return true; + if (shader.is_valid()) { + + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/")==0) { //backwards compatibility + pr = n.substr(6,n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->material_set_param(material,pr,p_value); + return true; + } } } @@ -486,10 +496,13 @@ bool ShaderMaterial::_get(const StringName& p_name,Variant &r_ret) const { return true; } else { - String n = p_name; - if (n.begins_with("param/")) { - r_ret=VisualServer::get_singleton()->material_get_param(material,String(n.ptr()+6)); - return true; + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret=VisualServer::get_singleton()->material_get_param(material,pr); + return true; + } } } @@ -583,115 +596,3 @@ ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->materi ///////////////////////////////// - -void ParticleSystemMaterial::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_texture","texture"),&ParticleSystemMaterial::set_texture); - ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&ParticleSystemMaterial::get_texture); - - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture" ), _SCS("set_texture"), _SCS("get_texture")); - -} - -void ParticleSystemMaterial::set_texture(const Ref<Texture>& p_texture) { - texture=p_texture; - RID rid; - if (texture.is_valid()) - rid=texture->get_rid(); - - VS::get_singleton()->fixed_material_set_texture(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,rid); -} - -Ref<Texture> ParticleSystemMaterial::get_texture() const { - - return texture; -} - - -ParticleSystemMaterial::ParticleSystemMaterial() :Material(VisualServer::get_singleton()->fixed_material_create()){ - - set_flag(FLAG_DOUBLE_SIDED,true); - set_flag(FLAG_UNSHADED,true); - set_depth_draw_mode(DEPTH_DRAW_NEVER); - VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,true); - VisualServer::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); - set_flag(FLAG_COLOR_ARRAY_SRGB,true); - -} - -ParticleSystemMaterial::~ParticleSystemMaterial() { - - -} - -////////////////////////////// - - - -void UnshadedMaterial::_bind_methods() { - - ObjectTypeDB::bind_method(_MD("set_texture","texture"),&UnshadedMaterial::set_texture); - ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&UnshadedMaterial::get_texture); - - ObjectTypeDB::bind_method(_MD("set_use_alpha","enable"),&UnshadedMaterial::set_use_alpha); - ObjectTypeDB::bind_method(_MD("is_using_alpha"),&UnshadedMaterial::is_using_alpha); - - ObjectTypeDB::bind_method(_MD("set_use_color_array","enable"),&UnshadedMaterial::set_use_color_array); - ObjectTypeDB::bind_method(_MD("is_using_color_array"),&UnshadedMaterial::is_using_color_array); - - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture" ), _SCS("set_texture"), _SCS("get_texture")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "alpha" ), _SCS("set_use_alpha"), _SCS("is_using_alpha")); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "color_array" ), _SCS("set_use_color_array"), _SCS("is_using_color_array")); - -} - -void UnshadedMaterial::set_texture(const Ref<Texture>& p_texture) { - RID rid; - if (texture.is_valid()) - rid=texture->get_rid(); - - VS::get_singleton()->fixed_material_set_texture(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,rid); -} -Ref<Texture> UnshadedMaterial::get_texture() const { - - return texture; -} - -void UnshadedMaterial::set_use_alpha(bool p_use_alpha) { - - alpha=p_use_alpha; - VS::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_ALPHA,p_use_alpha); - //set_depth_draw_mode(); - //set_hint(HINT,p_use_alpha); - -} - -bool UnshadedMaterial::is_using_alpha() const{ - - return alpha; -} - -void UnshadedMaterial::set_use_color_array(bool p_use_color_array){ - - color_array=p_use_color_array; - VS::get_singleton()->fixed_material_set_flag(material,VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,p_use_color_array); - -} - -bool UnshadedMaterial::is_using_color_array() const{ - - return color_array; -} - -UnshadedMaterial::UnshadedMaterial() :Material(VisualServer::get_singleton()->fixed_material_create()){ - - set_flag(FLAG_UNSHADED,true); - set_use_alpha(true); - set_flag(FLAG_COLOR_ARRAY_SRGB,true); - -} - -UnshadedMaterial::~UnshadedMaterial() { - - -} diff --git a/scene/resources/material.h b/scene/resources/material.h index 2b10078e16..73d1a4e188 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -253,68 +253,6 @@ public: -class ParticleSystemMaterial : public Material { - - OBJ_TYPE( ParticleSystemMaterial, Material ); - REVERSE_GET_PROPERTY_LIST - -private: - - - - Ref<Texture> texture; - -protected: - - - static void _bind_methods(); - -public: - - void set_texture(const Ref<Texture>& p_texture); - Ref<Texture> get_texture() const; - - - ParticleSystemMaterial(); - ~ParticleSystemMaterial(); - -}; - -/////////////////////////////////////////// - - -class UnshadedMaterial : public Material { - - OBJ_TYPE( UnshadedMaterial, Material ); - REVERSE_GET_PROPERTY_LIST - -private: - - - bool alpha; - bool color_array; - Ref<Texture> texture; - -protected: - - - static void _bind_methods(); - -public: - - void set_texture(const Ref<Texture>& p_texture); - Ref<Texture> get_texture() const; - - void set_use_alpha(bool p_use_alpha); - bool is_using_alpha() const; - - void set_use_color_array(bool p_use_color_array); - bool is_using_color_array() const; - - UnshadedMaterial(); - ~UnshadedMaterial(); - -}; #endif diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index f3e625917a..42251124bd 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -84,7 +84,7 @@ void Shader::get_param_list(List<PropertyInfo> *p_params) const { for(List<PropertyInfo>::Element *E=local.front();E;E=E->next()) { PropertyInfo pi=E->get(); - pi.name="param/"+pi.name; + pi.name="shader_param/"+pi.name; params_cache[pi.name]=E->get().name; if (p_params) { diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 8c15ca43d4..4a380d455b 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -80,6 +80,16 @@ public: Ref<Texture> get_default_texture_param(const StringName& p_param) const; void get_default_texture_param_list(List<StringName>* r_textures) const; + _FORCE_INLINE_ StringName remap_param(const StringName& p_param) const { + if (params_cache_dirty) + get_param_list(NULL); + + const Map<StringName,StringName>::Element *E=params_cache.find(p_param); + if (E) + return E->get(); + return StringName(); + } + virtual RID get_rid() const; Shader(Mode p_mode); @@ -98,6 +108,15 @@ public: MaterialShader() : Shader(MODE_MATERIAL) {}; }; +class CanvasItemShader : public Shader { + + OBJ_TYPE(CanvasItemShader,Shader); + +public: + + CanvasItemShader() : Shader(MODE_CANVAS_ITEM) {}; +}; + class ResourceFormatLoaderShader : public ResourceFormatLoader { diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 2d6298cc99..ecd44fddfd 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -692,6 +692,9 @@ public: mutable bool rect_dirty; mutable Rect2 rect; CanvasItem*next; + RID shader; + Map<StringName,Variant> shader_param; + uint32_t shader_version; float final_opacity; @@ -824,8 +827,8 @@ public: 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;} - 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; } + void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_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;} virtual ~CanvasItem() { clear(); } }; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index f2348bf59f..d8b4a3e26b 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1105,6 +1105,60 @@ 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}, + { "MODELVIEW_MATRIX", TYPE_MAT4}, + { "TIME", TYPE_FLOAT}, + { NULL, TYPE_VOID}, +}; +const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ + + { "POSITION", TYPE_VEC4}, + { "NORMAL", TYPE_VEC3}, + { "UV", TYPE_VEC2}, + { "COLOR", TYPE_VEC4}, + { "TEXTURE", TYPE_TEXTURE}, + { "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}, @@ -2471,6 +2525,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) { 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 78094ee2aa..7e915be3d5 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -3699,6 +3699,42 @@ void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { } +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()); + ERR_FAIL_COND_V(!canvas_item->shader_param.has(p_param),Variant()); + + return canvas_item->shader_param[p_param]; +} + void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 81a492611b..098c57480a 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1110,6 +1110,11 @@ public: 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_shader(RID p_item, RID p_shader); + virtual RID canvas_item_get_shader(RID p_item) const; + + 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 0aa992564f..300aba4551 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1133,6 +1133,11 @@ public: FUNC2(canvas_item_set_sort_children_by_y,RID,bool); FUNC2(canvas_item_set_z,RID,int); + FUNC2(canvas_item_set_shader,RID, RID ); + FUNC1RC(RID,canvas_item_get_shader,RID ); + + 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); diff --git a/servers/visual_server.h b/servers/visual_server.h index 030bcd8208..6f759dcf05 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -989,6 +989,12 @@ public: virtual void canvas_item_clear(RID p_item)=0; virtual void canvas_item_raise(RID p_item)=0; + virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0; + virtual RID canvas_item_get_shader(RID p_item) const=0; + + virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0; + virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0; + /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0)=0; |