summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp143
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp10
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp899
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h109
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp528
-rw-r--r--drivers/gles3/shader_compiler_gles3.h67
-rw-r--r--drivers/gles3/shader_gles3.cpp83
-rw-r--r--drivers/gles3/shader_gles3.h27
-rw-r--r--drivers/gles3/shaders/canvas.glsl72
-rw-r--r--drivers/unix/os_unix.cpp4
11 files changed, 1828 insertions, 116 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index a1e755cb4a..b2228a6cfa 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -138,6 +138,7 @@ void RasterizerCanvasGLES3::canvas_begin(){
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false);
+ state.canvas_shader.set_custom_shader(0);
state.canvas_shader.bind();
state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1));
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32());
@@ -520,6 +521,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
//err..
}
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size);
+
glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y);
glVertexAttrib4f(2,src_rect.pos.x,src_rect.pos.y,src_rect.size.x,src_rect.size.y);
@@ -567,6 +570,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height );
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size);
+
#define DSTRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(1,m_x,m_y,m_w,m_h)
#define SRCRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(2,(m_x)*texpixel_size.x,(m_y)*texpixel_size.y,(m_w)*texpixel_size.x,(m_h)*texpixel_size.y)
@@ -634,8 +639,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
ERR_CONTINUE( primitive->points.size()<1);
- _bind_canvas_texture(primitive->texture);
+ RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(primitive->texture);
+
+ if (texture ) {
+ Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height );
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size);
+ }
if (primitive->colors.size()==1 && primitive->points.size()>1) {
Color c = primitive->colors[0];
@@ -652,6 +662,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
Item::CommandPolygon* polygon = static_cast<Item::CommandPolygon*>(c);
_set_texture_rect_mode(false);
+
+ RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(polygon->texture);
+
+ if (texture ) {
+ Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height );
+ state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size);
+
+ }
_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
} break;
@@ -800,10 +818,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
+ int last_blend_mode=-1;
+
RID canvas_last_material;
bool prev_distance_field=false;
+
+
while(p_item_list) {
Item *ci=p_item_list;
@@ -878,53 +900,71 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
RID material = material_owner->material;
if (material!=canvas_last_material || rebind_shader) {
-#if 0
- Shader *shader = NULL;
- if (material && material->shader.is_valid()) {
- shader = shader_owner.get(material->shader);
- if (shader && !shader->valid) {
- shader=NULL;
+
+ RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material);
+ RasterizerStorageGLES3::Shader *shader_ptr = NULL;
+
+ if (material_ptr) {
+
+ shader_ptr = material_ptr->shader;
+
+ if (shader_ptr && shader_ptr->mode!=VS::SHADER_CANVAS_ITEM) {
+ shader_ptr=NULL; //do not use non canvasitem shader
}
}
- shader_cache=shader;
- if (shader) {
- canvas_shader.set_custom_shader(shader->custom_code_id);
- _canvas_item_setup_shader_params(material,shader);
- } else {
- shader_cache=NULL;
- canvas_shader.set_custom_shader(0);
- canvas_shader.bind();
- uses_texpixel_size=false;
+ if (shader_ptr && shader_ptr!=shader_cache) {
+
+ state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
+ state.canvas_shader.bind();
+
+ if (material_ptr->ubo_id) {
+ glBindBufferBase(GL_UNIFORM_BUFFER,2,material_ptr->ubo_id);
+ }
+
+ int tc = material_ptr->textures.size();
+ RID* textures = material_ptr->textures.ptr();
+
+ for(int i=0;i<tc;i++) {
+
+ glActiveTexture(GL_TEXTURE1+i);
+
+ RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] );
+ if (!t) {
+ //check hints
+ glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
+ continue;
+ }
+
+ glBindTexture(t->target,t->tex_id);
+ }
+
+
+ } else if (!shader_ptr) {
+ state.canvas_shader.set_custom_shader(0);
+ state.canvas_shader.bind();
}
+ shader_cache=shader_ptr;
- canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,canvas_transform);
- if (canvas_use_modulate)
- reset_modulate=true;
canvas_last_material=material;
rebind_shader=false;
-#endif
- }
- if (material.is_valid() && shader_cache) {
-#if 0
- _canvas_item_setup_shader_uniforms(material,shader_cache);
-#endif
}
- bool unshaded = false; //(material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX;
+ int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
+ bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode==RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode!=RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX);
bool reclip=false;
-#if 0
- if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) {
- switch(ci->blend_mode) {
+ if (last_blend_mode!=blend_mode) {
+
+ switch(blend_mode) {
- case VS::MATERIAL_BLEND_MODE_MIX: {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: {
glBlendEquation(GL_FUNC_ADD);
- if (current_rt && current_rt_transparent) {
+ if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else {
@@ -932,33 +972,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
}
} break;
- case VS::MATERIAL_BLEND_MODE_ADD: {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
- case VS::MATERIAL_BLEND_MODE_SUB: {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
- case VS::MATERIAL_BLEND_MODE_MUL: {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_DST_COLOR,GL_ZERO);
} break;
- case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
+ case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
} break;
}
- canvas_blend_mode=ci->blend_mode;
+ last_blend_mode=blend_mode;
}
-#endif
-
-// canvas_shader.set_uniform(CanvasShaderGLES3::CANVAS_MODULATE,unshaded ? Color(1,1,1,1) : p_modulate);
state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
ci->final_modulate.r * p_modulate.r,
@@ -974,10 +1011,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,state.extra_matrix);
- if (unshaded || (state.canvas_item_modulate.a>0.001 && (!material.is_valid() /*|| material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT*/) && !ci->light_masked ))
+ if (unshaded || (state.canvas_item_modulate.a>0.001 && (!shader_cache || shader_cache->canvas_item.light_mode!=RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked ))
_canvas_item_render_commands(ci,current_clip,reclip);
- if (/*canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX &&*/ p_light && !unshaded) {
+ if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) {
Light *light = p_light;
bool light_used=false;
@@ -1046,12 +1083,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
bool light_rebind = state.canvas_shader.bind();
if (light_rebind) {
-#if 0
- if (material && shader_cache) {
- _canvas_item_setup_shader_params(material,shader_cache);
- _canvas_item_setup_shader_uniforms(material,shader_cache);
- }
-#endif
+
state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate);
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform);
state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32());
@@ -1100,15 +1132,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9,false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false);
-
state.canvas_shader.bind();
-#if 0
- if (material && shader_cache) {
- _canvas_item_setup_shader_params(material,shader_cache);
- _canvas_item_setup_shader_uniforms(material,shader_cache);
- }
-#endif
+ last_blend_mode=-1;
+
+ /*
+ //this is set again, so it should not be needed anyway?
state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
ci->final_modulate.r * p_modulate.r,
ci->final_modulate.g * p_modulate.g,
@@ -1120,7 +1149,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32());
state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate);
-
glBlendEquation(GL_FUNC_ADD);
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
@@ -1130,6 +1158,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
}
//@TODO RESET canvas_blend_mode
+ */
}
@@ -1380,6 +1409,9 @@ void RasterizerCanvasGLES3::reset_canvas() {
state.vp=canvas_transform;
store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix);
+ for(int i=0;i<4;i++) {
+ state.canvas_item_ubo_data.time[i]=storage->frame.time[i];
+ }
glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data);
@@ -1442,6 +1474,7 @@ void RasterizerCanvasGLES3::initialize() {
glBindBuffer(GL_UNIFORM_BUFFER, 0);
state.canvas_shader.init();
+ state.canvas_shader.set_base_material_tex_index(1);
state.canvas_shadow_shader.init();
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS,storage->config.use_rgba_2d_shadows);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 1f72a8dbcf..8f34f07d06 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -5,12 +5,14 @@
#include "rasterizer_storage_gles3.h"
#include "shaders/canvas_shadow.glsl.h"
+
class RasterizerCanvasGLES3 : public RasterizerCanvas {
public:
struct CanvasItemUBO {
float projection_matrix[16];
+ float time[4];
};
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 27b0690645..eaa9825605 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -115,8 +115,17 @@ void RasterizerGLES3::initialize() {
void RasterizerGLES3::begin_frame(){
+ double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0;
+ storage->frame.time[0]=time_total;
+ storage->frame.time[1]=Math::fmod(time_total,3600);
+ storage->frame.time[2]=Math::fmod(time_total,900);
+ storage->frame.time[3]=Math::fmod(time_total,60);
+
+ storage->update_dirty_shaders();
+ storage->update_dirty_materials();
}
+
void RasterizerGLES3::set_current_render_target(RID p_render_target){
if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
@@ -257,6 +266,7 @@ RasterizerGLES3::RasterizerGLES3()
storage = memnew( RasterizerStorageGLES3 );
canvas = memnew( RasterizerCanvasGLES3 );
canvas->storage=storage;
+ storage->canvas=canvas;
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index b4d65080a4..74b7d72652 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1,4 +1,5 @@
#include "rasterizer_storage_gles3.h"
+#include "rasterizer_canvas_gles3.h"
#include "globals.h"
/* TEXTURE API */
@@ -1000,65 +1001,906 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable
RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode){
- return RID();
+ Shader *shader = memnew( Shader );
+ shader->mode=p_mode;
+ RID rid = shader_owner.make_rid(shader);
+ shader_set_mode(rid,p_mode);
+ _shader_make_dirty(shader);
+ shader->self=rid;
+
+ return rid;
+}
+
+void RasterizerStorageGLES3::_shader_make_dirty(Shader* p_shader) {
+
+ if (p_shader->dirty_list.in_list())
+ return;
+
+ _shader_dirty_list.add(&p_shader->dirty_list);
}
void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode){
+ ERR_FAIL_INDEX(p_mode,VS::SHADER_MAX);
+ Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ if (shader->custom_code_id && p_mode==shader->mode)
+ return;
+
+
+ if (shader->custom_code_id) {
+
+ shader->shader->free_custom_shader(shader->custom_code_id);
+ shader->custom_code_id=0;
+ }
+
+ shader->mode=p_mode;
+
+ ShaderGLES3* shaders[VS::SHADER_MAX]={
+ &canvas->state.canvas_shader,
+ &canvas->state.canvas_shader,
+ &canvas->state.canvas_shader,
+
+ };
+
+ shader->shader=shaders[p_mode];
+
+ shader->custom_code_id = shader->shader->create_custom_shader();
+
+ _shader_make_dirty(shader);
}
VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const {
- return VS::SHADER_SPATIAL;
+ const Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND_V(!shader,VS::SHADER_MAX);
+
+ return shader->mode;
}
void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String& p_code){
+ Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND(!shader);
+ shader->code=p_code;
+ _shader_make_dirty(shader);
}
String RasterizerStorageGLES3::shader_get_code(RID p_shader) const{
- return String();
+ const Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND_V(!shader,String());
+
+
+ return shader->code;
}
+
+void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
+
+
+ _shader_dirty_list.remove( &p_shader->dirty_list );
+
+ p_shader->valid=false;
+
+ p_shader->uniforms.clear();
+
+ ShaderCompilerGLES3::GeneratedCode gen_code;
+ ShaderCompilerGLES3::IdentifierActions *actions=NULL;
+
+
+
+ switch(p_shader->mode) {
+ case VS::SHADER_CANVAS_ITEM: {
+
+ p_shader->canvas_item.light_mode=Shader::CanvasItem::LIGHT_MODE_NORMAL;
+ p_shader->canvas_item.blend_mode=Shader::CanvasItem::BLEND_MODE_MIX;
+
+ shaders.actions_canvas.render_mode_values["blend_add"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_ADD);
+ shaders.actions_canvas.render_mode_values["blend_mix"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MIX);
+ shaders.actions_canvas.render_mode_values["blend_sub"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_SUB);
+ shaders.actions_canvas.render_mode_values["blend_mul"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MUL);
+ shaders.actions_canvas.render_mode_values["blend_premul_alpha"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_PMALPHA);
+
+ shaders.actions_canvas.render_mode_values["unshaded"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_UNSHADED);
+ shaders.actions_canvas.render_mode_values["light_only"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
+
+ actions=&shaders.actions_canvas;
+ actions->uniforms=&p_shader->uniforms;
+
+ } break;
+ }
+
+
+ Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code);
+
+ ERR_FAIL_COND(err!=OK);
+
+ p_shader->shader->set_custom_shader_code(p_shader->custom_code_id,gen_code.vertex,gen_code.vertex_global,gen_code.fragment,gen_code.light,gen_code.fragment_global,gen_code.uniforms,gen_code.texture_uniforms,gen_code.defines);
+
+ p_shader->ubo_size=gen_code.uniform_total_size;
+ p_shader->ubo_offsets=gen_code.uniform_offsets;
+ p_shader->texture_count=gen_code.texture_uniforms.size();
+
+ //all materials using this shader will have to be invalidated, unfortunately
+
+ for (SelfList<Material>* E = p_shader->materials.first();E;E=E->next() ) {
+
+ _material_make_dirty(E->self());
+ }
+
+ p_shader->valid=true;
+ p_shader->version++;
+
+}
+
+void RasterizerStorageGLES3::update_dirty_shaders() {
+
+ while( _shader_dirty_list.first() ) {
+ _update_shader(_shader_dirty_list.first()->self() );
+ }
+}
+
void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const{
+ Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND(!shader);
+
+
+ if (shader->dirty_list.in_list())
+ _update_shader(shader); // ok should be not anymore dirty
+
+
+ Map<int,StringName> order;
+
+ for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
+
+
+ order[E->get().order]=E->key();
+ }
+
+
+ for(Map<int,StringName>::Element *E=order.front();E;E=E->next()) {
+
+ PropertyInfo pi;
+ ShaderLanguage::ShaderNode::Uniform &u=shader->uniforms[E->get()];
+ pi.name=E->get();
+ switch(u.type) {
+ case ShaderLanguage::TYPE_VOID: pi.type=Variant::NIL; break;
+ case ShaderLanguage::TYPE_BOOL: pi.type=Variant::BOOL; break;
+ case ShaderLanguage::TYPE_BVEC2: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y"; break;
+ case ShaderLanguage::TYPE_BVEC3: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z"; break;
+ case ShaderLanguage::TYPE_BVEC4: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z,w"; break;
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_INT: {
+ pi.type=Variant::INT;
+ if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint=PROPERTY_HINT_RANGE;
+ pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1]);
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_UVEC4: {
+
+ pi.type=Variant::INT_ARRAY;
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ pi.type=Variant::REAL;
+ if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
+ pi.hint=PROPERTY_HINT_RANGE;
+ pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1])+","+rtos(u.hint_range[2]);
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: pi.type=Variant::VECTOR2; break;
+ case ShaderLanguage::TYPE_VEC3: pi.type=Variant::VECTOR3; break;
+ case ShaderLanguage::TYPE_VEC4: {
+ if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ pi.type=Variant::COLOR;
+ } else {
+ pi.type=Variant::PLANE;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: pi.type=Variant::MATRIX32; break;
+ case ShaderLanguage::TYPE_MAT3: pi.type=Variant::MATRIX3; break;
+ case ShaderLanguage::TYPE_MAT4: pi.type=Variant::TRANSFORM; break;
+ case ShaderLanguage::TYPE_SAMPLER2D:
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D: {
+
+ pi.type=Variant::OBJECT;
+ pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string="Texture";
+ } break;
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+
+ pi.type=Variant::OBJECT;
+ pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string="CubeMap";
+ } break;
+ };
+
+ p_param_list->push_back(pi);
+
+ }
}
void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture){
+ Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND(!shader);
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
+
+ if (p_texture.is_valid())
+ shader->default_textures[p_name]=p_texture;
+ else
+ shader->default_textures.erase(p_name);
+ _shader_make_dirty(shader);
}
RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{
- return RID();
+ const Shader *shader=shader_owner.get(p_shader);
+ ERR_FAIL_COND_V(!shader,RID());
+
+ const Map<StringName,RID>::Element *E=shader->default_textures.find(p_name);
+ if (!E)
+ return RID();
+ return E->get();
}
/* COMMON MATERIAL API */
+void RasterizerStorageGLES3::_material_make_dirty(Material* p_material) const {
+
+ if (p_material->dirty_list.in_list())
+ return;
+
+ _material_dirty_list.add(&p_material->dirty_list);
+}
+
RID RasterizerStorageGLES3::material_create(){
- return RID();
+ Material *material = memnew( Material );
+
+ return material_owner.make_rid(material);
}
-void RasterizerStorageGLES3::material_set_shader(RID p_shader_material, RID p_shader){
+void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader){
+
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+
+ Shader *shader=shader_owner.getornull(p_shader);
+
+ if (material->shader) {
+ //if shader, remove from previous shader material list
+ material->shader->materials.remove( &material->list );
+ }
+ material->shader=shader;
+
+ if (shader) {
+ shader->materials.add(&material->list);
+ }
+ _material_make_dirty(material);
}
-RID RasterizerStorageGLES3::material_get_shader(RID p_shader_material) const{
+
+RID RasterizerStorageGLES3::material_get_shader(RID p_material) const{
+
+ const Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,RID());
+
+ if (material->shader)
+ return material->shader->self;
return RID();
}
void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){
+ Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+
+ if (p_value.get_type()==Variant::NIL)
+ material->params.erase(p_param);
+ else
+ material->params[p_param]=p_value;
+
+ _material_make_dirty(material);
}
Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName& p_param) const{
+ const Material *material = material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,RID());
+
+ if (material->params.has(p_param))
+ return material->params[p_param];
+
return Variant();
}
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data) {
+ switch(type) {
+ case ShaderLanguage::TYPE_BOOL: {
+
+ bool v = value;
+
+ GLuint *gui = (GLuint*)data;
+ *gui = v ? GL_TRUE : GL_FALSE;
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+
+ int v = value;
+ GLuint *gui = (GLuint*)data;
+ gui[0]=v&1 ? GL_TRUE : GL_FALSE;
+ gui[1]=v&2 ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+
+ int v = value;
+ GLuint *gui = (GLuint*)data;
+ gui[0]=v&1 ? GL_TRUE : GL_FALSE;
+ gui[1]=v&2 ? GL_TRUE : GL_FALSE;
+ gui[2]=v&4 ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+
+ int v = value;
+ GLuint *gui = (GLuint*)data;
+ gui[0]=v&1 ? GL_TRUE : GL_FALSE;
+ gui[1]=v&2 ? GL_TRUE : GL_FALSE;
+ gui[2]=v&4 ? GL_TRUE : GL_FALSE;
+ gui[3]=v&8 ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+
+ int v = value;
+ GLint *gui = (GLint*)data;
+ gui[0]=v;
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLint *gui = (GLint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<2;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLint *gui = (GLint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<3;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+
+
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLint *gui = (GLint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<4;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+
+ }
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+
+ int v = value;
+ GLuint *gui = (GLuint*)data;
+ gui[0]=v;
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLuint *gui = (GLuint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<2;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLuint *gui = (GLuint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<3;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ DVector<int> iv = value;
+ int s = iv.size();
+ GLuint *gui = (GLuint*)data;
+
+ DVector<int>::Read r = iv.read();
+
+ for(int i=0;i<4;i++) {
+ if (i<s)
+ gui[i]=r[i];
+ else
+ gui[i]=0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float v = value;
+ GLfloat *gui = (GLfloat*)data;
+ gui[0]=v;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ Vector2 v = value;
+ GLfloat *gui = (GLfloat*)data;
+ gui[0]=v.x;
+ gui[1]=v.y;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ Vector3 v = value;
+ GLfloat *gui = (GLfloat*)data;
+ gui[0]=v.x;
+ gui[1]=v.y;
+ gui[2]=v.z;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+
+ GLfloat *gui = (GLfloat*)data;
+
+ if (value.get_type()==Variant::COLOR) {
+ Color v=value;
+
+ gui[0]=v.r;
+ gui[1]=v.g;
+ gui[3]=v.b;
+ gui[4]=v.a;
+ } else if (value.get_type()==Variant::RECT2) {
+ Rect2 v=value;
+
+ gui[0]=v.pos.x;
+ gui[1]=v.pos.y;
+ gui[3]=v.size.x;
+ gui[4]=v.size.y;
+ } else if (value.get_type()==Variant::QUAT) {
+ Quat v=value;
+
+ gui[0]=v.x;
+ gui[1]=v.y;
+ gui[3]=v.z;
+ gui[4]=v.w;
+ } else {
+ Plane v=value;
+
+ gui[0]=v.normal.x;
+ gui[1]=v.normal.y;
+ gui[3]=v.normal.x;
+ gui[4]=v.d;
+
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ Matrix32 v = value;
+ GLfloat *gui = (GLfloat*)data;
+
+ gui[ 0]=v.elements[0][0];
+ gui[ 1]=v.elements[0][1];
+ gui[ 2]=v.elements[1][0];
+ gui[ 3]=v.elements[1][1];
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+
+
+ Matrix3 v = value;
+ GLfloat *gui = (GLfloat*)data;
+
+ gui[ 0]=v.elements[0][0];
+ gui[ 1]=v.elements[1][0];
+ gui[ 2]=v.elements[2][0];
+ gui[ 3]=0;
+ gui[ 4]=v.elements[0][1];
+ gui[ 5]=v.elements[1][1];
+ gui[ 6]=v.elements[2][1];
+ gui[ 7]=0;
+ gui[ 8]=v.elements[0][2];
+ gui[ 9]=v.elements[1][2];
+ gui[10]=v.elements[2][2];
+ gui[11]=0;
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+
+ Transform v = value;
+ GLfloat *gui = (GLfloat*)data;
+
+ gui[ 0]=v.basis.elements[0][0];
+ gui[ 1]=v.basis.elements[1][0];
+ gui[ 2]=v.basis.elements[2][0];
+ gui[ 3]=0;
+ gui[ 4]=v.basis.elements[0][1];
+ gui[ 5]=v.basis.elements[1][1];
+ gui[ 6]=v.basis.elements[2][1];
+ gui[ 7]=0;
+ gui[ 8]=v.basis.elements[0][2];
+ gui[ 9]=v.basis.elements[1][2];
+ gui[10]=v.basis.elements[2][2];
+ gui[11]=0;
+ gui[12]=v.origin.x;
+ gui[13]=v.origin.y;
+ gui[14]=v.origin.z;
+ gui[15]=1;
+ } break;
+ default: {}
+ }
+
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value>& value, uint8_t *data) {
+
+ switch(type) {
+ case ShaderLanguage::TYPE_BOOL: {
+
+ GLuint *gui = (GLuint*)data;
+ *gui = value[0].boolean ? GL_TRUE : GL_FALSE;
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+
+ GLuint *gui = (GLuint*)data;
+ gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE;
+ gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+
+ GLuint *gui = (GLuint*)data;
+ gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE;
+ gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE;
+ gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+
+ GLuint *gui = (GLuint*)data;
+ gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE;
+ gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE;
+ gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE;
+ gui[3]=value[3].boolean ? GL_TRUE : GL_FALSE;
+
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+
+ GLint *gui = (GLint*)data;
+ gui[0]=value[0].sint;
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<2;i++) {
+ gui[i]=value[i].sint;
+
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<3;i++) {
+ gui[i]=value[i].sint;
+
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<4;i++) {
+ gui[i]=value[i].sint;
+
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+
+
+ GLuint *gui = (GLuint*)data;
+ gui[0]=value[0].uint;
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<2;i++) {
+ gui[i]=value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<3;i++) {
+ gui[i]=value[i].uint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ GLint *gui = (GLint*)data;
+
+ for(int i=0;i<4;i++) {
+ gui[i]=value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+
+ GLfloat *gui = (GLfloat*)data;
+ gui[0]=value[0].real;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+
+ GLfloat *gui = (GLfloat*)data;
+
+ for(int i=0;i<2;i++) {
+ gui[i]=value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+
+ GLfloat *gui = (GLfloat*)data;
+
+ for(int i=0;i<3;i++) {
+ gui[i]=value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+
+ GLfloat *gui = (GLfloat*)data;
+
+ for(int i=0;i<4;i++) {
+ gui[i]=value[i].real;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ GLfloat *gui = (GLfloat*)data;
+
+ for(int i=0;i<2;i++) {
+ gui[i]=value[i].real;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+
+
+
+ GLfloat *gui = (GLfloat*)data;
+
+ gui[ 0]=value[0].real;
+ gui[ 1]=value[1].real;
+ gui[ 2]=value[2].real;
+ gui[ 3]=0;
+ gui[ 4]=value[3].real;
+ gui[ 5]=value[4].real;
+ gui[ 6]=value[5].real;
+ gui[ 7]=0;
+ gui[ 8]=value[6].real;
+ gui[ 9]=value[7].real;
+ gui[10]=value[8].real;
+ gui[11]=0;
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+
+ GLfloat *gui = (GLfloat*)data;
+
+ for(int i=0;i<16;i++) {
+ gui[i]=value[i].real;
+ }
+ } break;
+ default: {}
+ }
+
+}
+
+
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) {
+
+ switch(type) {
+
+ case ShaderLanguage::TYPE_BOOL:
+ case ShaderLanguage::TYPE_INT:
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_FLOAT: {
+ zeromem(data,4);
+ } break;
+ case ShaderLanguage::TYPE_BVEC2:
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_VEC2: {
+ zeromem(data,8);
+ } break;
+ case ShaderLanguage::TYPE_BVEC3:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_BVEC4:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_VEC4:
+ case ShaderLanguage::TYPE_MAT2:{
+
+ zeromem(data,16);
+ } break;
+ case ShaderLanguage::TYPE_MAT3:{
+
+ zeromem(data,48);
+ } break;
+ case ShaderLanguage::TYPE_MAT4:{
+ zeromem(data,64);
+ } break;
+
+ default: {}
+ }
+
+}
+
+void RasterizerStorageGLES3::_update_material(Material* material) {
+
+ if (material->dirty_list.in_list())
+ _material_dirty_list.remove( &material->dirty_list );
+
+ //clear ubo if it needs to be cleared
+ if (material->ubo_size) {
+
+ if (!material->shader || material->shader->ubo_size!=material->ubo_size) {
+ //by by ubo
+ glDeleteBuffers(1,&material->ubo_id);
+ material->ubo_id=0;
+ material->ubo_size=0;
+ }
+ }
+
+ //create ubo if it needs to be created
+ if (material->ubo_size==0 && material->shader && material->shader->ubo_size) {
+
+ glGenBuffers(1, &material->ubo_id);
+ glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id);
+ glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ material->ubo_size=material->shader->ubo_size;
+ }
+
+ //fill up the UBO if it needs to be filled
+ if (material->shader && material->ubo_size) {
+ uint8_t* local_ubo = (uint8_t*)alloca(material->ubo_size);
+
+ for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) {
+
+ if (E->get().order<0)
+ continue; // texture, does not go here
+
+ //regular uniform
+ uint8_t *data = &local_ubo[ material->shader->ubo_offsets[E->get().order] ];
+
+ Map<StringName,Variant>::Element *V = material->params.find(E->key());
+
+ if (V) {
+ //user provided
+ _fill_std140_variant_ubo_value(E->get().type,V->get(),data);
+ } else if (E->get().default_value.size()){
+ //default value
+ _fill_std140_ubo_value(E->get().type,E->get().default_value,data);
+ //value=E->get().default_value;
+ } else {
+ //zero because it was not provided
+ _fill_std140_ubo_empty(E->get().type,data);
+ }
+
+
+ }
+
+ glBindBuffer(GL_UNIFORM_BUFFER,material->ubo_id);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, material->ubo_size, local_ubo);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ }
+
+ //set up the texture array, for easy access when it needs to be drawn
+ if (material->shader && material->shader->texture_count) {
+
+ material->textures.resize(material->shader->texture_count);
+
+ for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) {
+
+ if (E->get().texture_order<0)
+ continue; // not a texture, does not go here
+
+ RID texture;
+
+ Map<StringName,Variant>::Element *V = material->params.find(E->key());
+ if (V) {
+ texture=V->get();
+ }
+
+ if (!texture.is_valid()) {
+ Map<StringName,RID>::Element *W = material->shader->default_textures.find(E->key());
+ if (W) {
+ texture=W->get();
+ }
+ }
+
+ material->textures[ E->get().texture_order ]=texture;
+
+
+ }
+
+
+ } else {
+ material->textures.clear();
+ }
+
+}
+
+void RasterizerStorageGLES3::update_dirty_materials() {
+
+ while( _material_dirty_list.first() ) {
+
+ Material *material = _material_dirty_list.first()->self();
+
+ _update_material(material);
+ }
+}
+
/* MESH API */
RID RasterizerStorageGLES3::mesh_create(){
@@ -1950,6 +2792,49 @@ bool RasterizerStorageGLES3::free(RID p_rid){
info.texture_mem-=texture->total_data_size;
texture_owner.free(p_rid);
memdelete(texture);
+
+ } else if (shader_owner.owns(p_rid)) {
+
+ // delete the texture
+ Shader *shader = shader_owner.get(p_rid);
+
+ if (shader->shader)
+ shader->shader->free_custom_shader(shader->custom_code_id);
+
+ if (shader->dirty_list.in_list())
+ _shader_dirty_list.remove(&shader->dirty_list);
+
+ while (shader->materials.first()) {
+
+ Material *mat = shader->materials.first()->self();
+
+ mat->shader=NULL;
+ _material_make_dirty(mat);
+
+ shader->materials.remove( shader->materials.first() );
+ }
+
+ //material_shader.free_custom_shader(shader->custom_code_id);
+ shader_owner.free(p_rid);
+ memdelete(shader);
+
+ } else if (material_owner.owns(p_rid)) {
+
+ // delete the texture
+ Material *material = material_owner.get(p_rid);
+
+ if (material->shader) {
+ material->shader->materials.remove( & material->list );
+ }
+
+ if (material->ubo_id) {
+ glDeleteBuffers(1,&material->ubo_id);
+ }
+
+ material_owner.free(p_rid);
+ memdelete(material);
+
+
} else if (canvas_occluder_owner.owns(p_rid)) {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 9820fbc941..b7b3e607c6 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -2,16 +2,21 @@
#define RASTERIZERSTORAGEGLES3_H
#include "servers/visual/rasterizer.h"
+#include "servers/visual/shader_language.h"
#include "shader_gles3.h"
#include "shaders/copy.glsl.h"
#include "shaders/canvas.glsl.h"
+#include "self_list.h"
+#include "shader_compiler_gles3.h"
-
+class RasterizerCanvasGLES3;
class RasterizerStorageGLES3 : public RasterizerStorage {
public:
+ RasterizerCanvasGLES3 *canvas;
+
enum FBOFormat {
FBO_FORMAT_16_BITS,
FBO_FORMAT_32_BITS,
@@ -47,9 +52,13 @@ public:
Set<String> extensions;
} config;
- struct Shaders {
+ mutable struct Shaders {
CopyShaderGLES3 copy;
+
+ ShaderCompilerGLES3 compiler;
+
+ ShaderCompilerGLES3::IdentifierActions actions_canvas;
} shaders;
struct Resources {
@@ -169,11 +178,71 @@ public:
/* SHADER API */
+ struct Material;
+
struct Shader : public RID_Data {
+ RID self;
+
+ VS::ShaderMode mode;
+ ShaderGLES3 *shader;
+ String code;
+ SelfList<Material>::List materials;
+
+
+
+ Map<StringName,ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ uint32_t texture_count;
+
+ uint32_t custom_code_id;
+ uint32_t version;
+
+ SelfList<Shader> dirty_list;
+
+ Map<StringName,RID> default_textures;
+
+ bool valid;
+
+ String path;
+
+ struct CanvasItem {
+
+ enum BlendMode {
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ BLEND_MODE_PMALPHA,
+ };
+
+ int blend_mode;
+ enum LightMode {
+ LIGHT_MODE_NORMAL,
+ LIGHT_MODE_UNSHADED,
+ LIGHT_MODE_LIGHT_ONLY
+ };
+
+ int light_mode;
+
+ } canvas_item;
+
+ Shader() : dirty_list(this) {
+
+ shader=NULL;
+ valid=false;
+ custom_code_id=0;
+ version=1;
+ }
};
+ mutable SelfList<Shader>::List _shader_dirty_list;
+ void _shader_make_dirty(Shader* p_shader);
+
+ mutable RID_Owner<Shader> shader_owner;
virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL);
@@ -187,17 +256,48 @@ public:
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;
+ void _update_shader(Shader* p_shader) const;
+
+ void update_dirty_shaders();
/* COMMON MATERIAL API */
+ struct Material : public RID_Data {
+
+ Shader *shader;
+ GLuint ubo_id;
+ uint32_t ubo_size;
+ Map<StringName,Variant> params;
+ SelfList<Material> list;
+ SelfList<Material> dirty_list;
+ Vector<RID> textures;
+
+ Material() : list(this), dirty_list(this) {
+ shader=NULL;
+ ubo_id=0;
+ ubo_size=0;
+ }
+
+ };
+
+ mutable SelfList<Material>::List _material_dirty_list;
+ void _material_make_dirty(Material *p_material) const;
+
+
+ mutable RID_Owner<Material> material_owner;
+
virtual RID material_create();
- virtual void material_set_shader(RID p_shader_material, RID p_shader);
- virtual RID material_get_shader(RID p_shader_material) const;
+ virtual void material_set_shader(RID p_material, RID p_shader);
+ virtual RID material_get_shader(RID p_material) const;
virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value);
virtual Variant material_get_param(RID p_material, const StringName& p_param) const;
+ void _update_material(Material* material);
+
+ void update_dirty_materials();
+
/* MESH API */
virtual RID mesh_create();
@@ -432,6 +532,7 @@ public:
bool clear_request;
Color clear_request_color;
int canvas_draw_commands;
+ float time[4];
} frame;
void initialize();
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
new file mode 100644
index 0000000000..49707400ca
--- /dev/null
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -0,0 +1,528 @@
+#include "shader_compiler_gles3.h"
+#include "os/os.h"
+
+#define SL ShaderLanguage
+
+static String _mktab(int p_level) {
+
+ String tb;
+ for(int i=0;i<p_level;i++) {
+ tb+="\t";
+ }
+
+ return tb;
+}
+
+static String _typestr(SL::DataType p_type) {
+
+ return ShaderLanguage::get_datatype_name(p_type);
+}
+
+static int _get_datatype_size(SL::DataType p_type) {
+
+ switch(p_type) {
+
+ case SL::TYPE_VOID: return 0;
+ case SL::TYPE_BOOL: return 4;
+ case SL::TYPE_BVEC2: return 8;
+ case SL::TYPE_BVEC3: return 16;
+ case SL::TYPE_BVEC4: return 16;
+ case SL::TYPE_INT: return 4;
+ case SL::TYPE_IVEC2: return 8;
+ case SL::TYPE_IVEC3: return 16;
+ case SL::TYPE_IVEC4: return 16;
+ case SL::TYPE_UINT: return 4;
+ case SL::TYPE_UVEC2: return 8;
+ case SL::TYPE_UVEC3: return 16;
+ case SL::TYPE_UVEC4: return 16;
+ case SL::TYPE_FLOAT: return 4;
+ case SL::TYPE_VEC2: return 8;
+ case SL::TYPE_VEC3: return 16;
+ case SL::TYPE_VEC4: return 16;
+ case SL::TYPE_MAT2: return 16;
+ case SL::TYPE_MAT3: return 48;
+ case SL::TYPE_MAT4: return 64;
+ case SL::TYPE_SAMPLER2D: return 16;
+ case SL::TYPE_ISAMPLER2D: return 16;
+ case SL::TYPE_USAMPLER2D: return 16;
+ case SL::TYPE_SAMPLERCUBE: return 16;
+ }
+
+
+}
+
+
+static String _prestr(SL::DataPrecision p_pres) {
+
+
+ switch(p_pres) {
+ case SL::PRECISION_LOWP: return "lowp ";
+ case SL::PRECISION_MEDIUMP: return "mediump ";
+ case SL::PRECISION_HIGHP: return "highp ";
+ case SL::PRECISION_DEFAULT: return "";
+ }
+ return "";
+}
+
+
+static String _opstr(SL::Operator p_op) {
+
+ return SL::get_operator_text(p_op);
+}
+
+static String _mkid(const String& p_id) {
+
+ return "m_"+p_id;
+}
+
+static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value>& p_values) {
+
+ switch(p_type) {
+ case SL::TYPE_BOOL: return p_values[0].boolean?"true":"false";
+ case SL::TYPE_BVEC2: return String()+"bvec2("+(p_values[0].boolean?"true":"false")+(p_values[1].boolean?"true":"false")+")";
+ case SL::TYPE_BVEC3: return String()+"bvec3("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+")";
+ case SL::TYPE_BVEC4: return String()+"bvec4("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+","+(p_values[3].boolean?"true":"false")+")";
+ case SL::TYPE_INT: return rtos(p_values[0].sint);
+ case SL::TYPE_IVEC2: return String()+"ivec2("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+")";
+ case SL::TYPE_IVEC3: return String()+"ivec3("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+")";
+ case SL::TYPE_IVEC4: return String()+"ivec4("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+","+rtos(p_values[3].sint)+")";
+ case SL::TYPE_UINT: return rtos(p_values[0].real);
+ case SL::TYPE_UVEC2: return String()+"uvec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")";
+ case SL::TYPE_UVEC3: return String()+"uvec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")";
+ case SL::TYPE_UVEC4: return String()+"uvec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")";
+ case SL::TYPE_FLOAT: return rtos(p_values[0].real);
+ case SL::TYPE_VEC2: return String()+"vec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")";
+ case SL::TYPE_VEC3: return String()+"vec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")";
+ case SL::TYPE_VEC4: return String()+"vec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")";
+ default: ERR_FAIL_V(String());
+ }
+}
+
+void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode* p_node, const StringName& p_for_func, const Map<StringName,String>& p_func_code, String& r_to_add, Set<StringName> &added) {
+
+ int fidx=-1;
+
+ for(int i=0;i<p_node->functions.size();i++) {
+ if (p_node->functions[i].name==p_for_func) {
+ fidx=i;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND(fidx==-1);
+
+ for (Set<StringName>::Element *E=p_node->functions[fidx].uses_function.front();E;E=E->next()) {
+
+ if (added.has(E->get())) {
+ continue; //was added already
+ }
+
+ _dump_function_deps(p_node,E->get(),p_func_code,r_to_add,added);
+
+ SL::FunctionNode *fnode=NULL;
+
+ for(int i=0;i<p_node->functions.size();i++) {
+ if (p_node->functions[i].name==E->get()) {
+ fnode=p_node->functions[i].function;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND(!fnode);
+
+ r_to_add+="\n";
+
+ String header;
+ header=_typestr(fnode->return_type)+" "+_mkid(fnode->name)+"(";
+ for(int i=0;i<fnode->arguments.size();i++) {
+
+ if (i>0)
+ header+=", ";
+ header+=_prestr(fnode->arguments[i].precision)+_typestr(fnode->arguments[i].type)+" "+_mkid(fnode->arguments[i].name);
+ }
+
+ header+=")\n";
+ r_to_add+=header;
+ r_to_add+=p_func_code[E->get()];
+
+ added.insert(E->get());
+ }
+}
+
+String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode& r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions) {
+
+ String code;
+
+ switch(p_node->type) {
+
+ case SL::Node::TYPE_SHADER: {
+
+ SL::ShaderNode *pnode=(SL::ShaderNode*)p_node;
+
+ for(int i=0;i<pnode->render_modes.size();i++) {
+
+ if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) {
+
+ r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]].utf8());
+ used_rmode_defines.insert(pnode->render_modes[i]);
+ }
+
+ if (p_actions.render_mode_flags.has(pnode->render_modes[i])) {
+ *p_actions.render_mode_flags[pnode->render_modes[i]]=true;
+ }
+
+ if (p_actions.render_mode_values.has(pnode->render_modes[i])) {
+ Pair<int*,int> &p = p_actions.render_mode_values[pnode->render_modes[i]];
+ *p.first=p.second;
+ }
+ }
+
+
+ int max_texture_uniforms=0;
+ int max_uniforms=0;
+
+ for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
+ if (SL::is_sampler_type(E->get().type))
+ max_texture_uniforms++;
+ else
+ max_uniforms++;
+ }
+
+ r_gen_code.texture_uniforms.resize(max_texture_uniforms);
+
+ Vector<int> uniform_sizes;
+ uniform_sizes.resize(max_uniforms);
+
+ for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
+
+ String ucode="uniform ";
+ ucode+=_prestr(E->get().precission);
+ ucode+=_typestr(E->get().type);
+ ucode+=" "+_mkid(E->key());
+ ucode+=";\n";
+ if (SL::is_sampler_type(E->get().type)) {
+ r_gen_code.vertex_global+=ucode;
+ r_gen_code.fragment_global+=ucode;
+ r_gen_code.texture_uniforms[E->get().texture_order]=_mkid(E->key());
+ } else {
+ if (r_gen_code.uniforms.empty()) {
+
+ r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii());
+ }
+ r_gen_code.uniforms+=ucode;
+ uniform_sizes[E->get().order]=_get_datatype_size(E->get().type);
+ }
+
+ p_actions.uniforms->insert(E->key(),E->get());
+
+ }
+
+ // add up
+ for(int i=0;i<uniform_sizes.size();i++) {
+
+ if (i>0)
+ uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1];
+ }
+ //offset
+ r_gen_code.uniform_offsets.resize(uniform_sizes.size());
+ for(int i=0;i<uniform_sizes.size();i++) {
+
+ if (i>0)
+ r_gen_code.uniform_offsets[i]=uniform_sizes[i]-1;
+ else
+ r_gen_code.uniform_offsets[i]=0;
+ }
+
+ if (uniform_sizes.size()) {
+ r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ];
+ } else {
+ r_gen_code.uniform_total_size=0;
+ }
+
+ for(Map<StringName,SL::ShaderNode::Varying>::Element *E=pnode->varyings.front();E;E=E->next()) {
+
+ String vcode;
+ vcode+=_prestr(E->get().precission);
+ vcode+=_typestr(E->get().type);
+ vcode+=" "+String(E->key());
+ vcode+=";\n";
+ r_gen_code.vertex_global+="out "+vcode;
+ r_gen_code.fragment_global+="in "+vcode;
+ }
+
+ Map<StringName,String> function_code;
+
+ //code for functions
+ for(int i=0;i<pnode->functions.size();i++) {
+ SL::FunctionNode *fnode=pnode->functions[i].function;
+ function_code[fnode->name]=_dump_node_code(fnode->body,p_level+1,r_gen_code,p_actions,p_default_actions);
+ }
+
+ //place functions in actual code
+
+ Set<StringName> added_vtx;
+ Set<StringName> added_fragment; //share for light
+
+ for(int i=0;i<pnode->functions.size();i++) {
+
+ SL::FunctionNode *fnode=pnode->functions[i].function;
+
+
+ if (fnode->name=="vertex") {
+
+ _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.vertex_global,added_vtx);
+ r_gen_code.vertex=function_code["vertex"];
+ }
+
+ if (fnode->name=="fragment") {
+
+ _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment);
+ r_gen_code.fragment=function_code["fragment"];
+ }
+
+ if (fnode->name=="light") {
+
+ _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment);
+ r_gen_code.light=function_code["light"];
+ }
+ }
+
+ //code+=dump_node_code(pnode->body,p_level);
+ } break;
+ case SL::Node::TYPE_FUNCTION: {
+
+ } break;
+ case SL::Node::TYPE_BLOCK: {
+ SL::BlockNode *bnode=(SL::BlockNode*)p_node;
+
+ //variables
+ code+=_mktab(p_level-1)+"{\n";
+ for(Map<StringName,SL::BlockNode::Variable>::Element *E=bnode->variables.front();E;E=E->next()) {
+
+ code+=_mktab(p_level)+_prestr(E->get().precision)+_typestr(E->get().type)+" "+_mkid(E->key())+";\n";
+ }
+
+ for(int i=0;i<bnode->statements.size();i++) {
+
+ String scode = _dump_node_code(bnode->statements[i],p_level,r_gen_code,p_actions,p_default_actions);
+
+ if (bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW) {
+ code+=scode; //use directly
+ } else {
+ code+=_mktab(p_level)+scode+";\n";
+ }
+ }
+ code+=_mktab(p_level-1)+"}\n";
+
+
+ } break;
+ case SL::Node::TYPE_VARIABLE: {
+ SL::VariableNode *vnode=(SL::VariableNode*)p_node;
+
+ if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) {
+ r_gen_code.defines.push_back(p_default_actions.usage_defines[vnode->name].utf8());
+ used_name_defines.insert(vnode->name);
+ }
+
+ if (p_actions.usage_flag_pointers.has(vnode->name) && !used_name_defines.has(vnode->name)) {
+ *p_actions.usage_flag_pointers[vnode->name]=true;
+ used_name_defines.insert(vnode->name);
+ }
+
+ if (p_default_actions.renames.has(vnode->name))
+ code=p_default_actions.renames[vnode->name];
+ else
+ code=_mkid(vnode->name);
+
+
+ } break;
+ case SL::Node::TYPE_CONSTANT: {
+ SL::ConstantNode *cnode=(SL::ConstantNode*)p_node;
+ return get_constant_text(cnode->datatype,cnode->values);
+
+ } break;
+ case SL::Node::TYPE_OPERATOR: {
+ SL::OperatorNode *onode=(SL::OperatorNode*)p_node;
+
+
+ switch(onode->op) {
+
+ case SL::OP_ASSIGN:
+ case SL::OP_ASSIGN_ADD:
+ case SL::OP_ASSIGN_SUB:
+ case SL::OP_ASSIGN_MUL:
+ case SL::OP_ASSIGN_DIV:
+ case SL::OP_ASSIGN_SHIFT_LEFT:
+ case SL::OP_ASSIGN_SHIFT_RIGHT:
+ case SL::OP_ASSIGN_MOD:
+ case SL::OP_ASSIGN_BIT_AND:
+ case SL::OP_ASSIGN_BIT_OR:
+ case SL::OP_ASSIGN_BIT_XOR:
+ code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions);
+ break;
+ case SL::OP_BIT_INVERT:
+ case SL::OP_NEGATE:
+ case SL::OP_NOT:
+ case SL::OP_DECREMENT:
+ case SL::OP_INCREMENT:
+ code=_opstr(onode->op)+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions);
+ break;
+ case SL::OP_POST_DECREMENT:
+ case SL::OP_POST_INCREMENT:
+ code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op);
+ break;
+ case SL::OP_CALL:
+ case SL::OP_CONSTRUCT: {
+
+ ERR_FAIL_COND_V(onode->arguments[0]->type!=SL::Node::TYPE_VARIABLE,String());
+
+ SL::VariableNode *vnode=(SL::VariableNode*)onode->arguments[0];
+
+ if (onode->op==SL::OP_CONSTRUCT) {
+ code+=String(vnode->name);
+ } else {
+
+ if (internal_functions.has(vnode->name)) {
+ code+=vnode->name;
+ } else if (p_default_actions.renames.has(vnode->name)) {
+ code+=p_default_actions.renames[vnode->name];
+ } else {
+ code+=_mkid(vnode->name);
+ }
+ }
+
+ code+="(";
+
+ for(int i=1;i<onode->arguments.size();i++) {
+ if (i>1)
+ code+=", ";
+ code+=_dump_node_code(onode->arguments[i],p_level,r_gen_code,p_actions,p_default_actions);
+ }
+ code+=")";
+ } break;
+ default: {
+
+ code="("+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions)+")";
+ break;
+
+ }
+ }
+
+ } break;
+ case SL::Node::TYPE_CONTROL_FLOW: {
+ SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node;
+ if (cfnode->flow_op==SL::FLOW_OP_IF) {
+
+ code+=_mktab(p_level)+"if ("+_dump_node_code(cfnode->expressions[0],p_level,r_gen_code,p_actions,p_default_actions)+")\n";
+ code+=_dump_node_code(cfnode->blocks[0],p_level+1,r_gen_code,p_actions,p_default_actions);
+ if (cfnode->blocks.size()==2) {
+
+ code+=_mktab(p_level)+"else\n";
+ code+=_dump_node_code(cfnode->blocks[1],p_level+1,r_gen_code,p_actions,p_default_actions);
+ }
+
+
+ } else if (cfnode->flow_op==SL::FLOW_OP_RETURN) {
+
+ if (cfnode->blocks.size()) {
+ code="return "+_dump_node_code(cfnode->blocks[0],p_level,r_gen_code,p_actions,p_default_actions);
+ } else {
+ code="return";
+ }
+ }
+
+ } break;
+ case SL::Node::TYPE_MEMBER: {
+ SL::MemberNode *mnode=(SL::MemberNode*)p_node;
+ code=_dump_node_code(mnode->owner,p_level,r_gen_code,p_actions,p_default_actions)+"."+mnode->name;
+
+ } break;
+ }
+
+ return code;
+
+}
+
+
+Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String &p_path,GeneratedCode& r_gen_code) {
+
+
+
+ Error err = parser.compile(p_code,ShaderTypes::get_singleton()->get_functions(p_mode),ShaderTypes::get_singleton()->get_modes(p_mode));
+
+ if (err!=OK) {
+ _err_print_error(NULL,p_path.utf8().get_data(),parser.get_error_line(),parser.get_error_text().utf8().get_data(),ERR_HANDLER_SHADER);
+ return err;
+ }
+
+ r_gen_code.defines.clear();
+ r_gen_code.vertex=String();
+ r_gen_code.vertex_global=String();
+ r_gen_code.fragment=String();
+ r_gen_code.fragment_global=String();
+ r_gen_code.light=String();
+
+
+
+ used_name_defines.clear();
+ used_rmode_defines.clear();
+
+ _dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]);
+
+ return OK;
+
+}
+
+
+ShaderCompilerGLES3::ShaderCompilerGLES3() {
+
+ /** CANVAS ITEM SHADER **/
+
+ actions[VS::SHADER_CANVAS_ITEM].renames["SRC_VERTEX"]="vertex";
+ actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"]="outvec.xy";
+ actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX_COLOR"]="vertex_color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp";
+ actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"]="gl_PointSize";
+
+ actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"]="modelview_matrix";
+ actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"]="projection_matrix";
+ actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"]=="extra_matrix";
+ actions[VS::SHADER_CANVAS_ITEM].renames["TIME"]="time";
+
+ actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"]="normal";
+ actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"]="normal_map";
+ actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"]="normal_depth";
+ actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp";
+ actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"]="color_texture";
+ actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"]="color_texpixel_size";
+ actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"]="screen_uv";
+ actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"]="screen_texture";
+ actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"]="gl_PointCoord";
+
+ actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"]="light_vec";
+ actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"]="light_height";
+ actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"]="light_color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"]="light_uv";
+ //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"]="light";
+ actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"]="shadow_color";
+
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"]="#define COLOR_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"]="#define SCREEN_TEXTURE_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"]="#define SCREEN_UV_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"]="#define NORMAL_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"]="#define NORMALMAP_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"]="#define SHADOW_COLOR_USED\n";
+
+ actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n";
+
+ List<String> func_list;
+
+ ShaderLanguage::get_builtin_funcs(&func_list);
+
+ for (List<String>::Element *E=func_list.front();E;E=E->next()) {
+ internal_functions.insert(E->get());
+ }
+}
diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h
new file mode 100644
index 0000000000..ad51b99927
--- /dev/null
+++ b/drivers/gles3/shader_compiler_gles3.h
@@ -0,0 +1,67 @@
+#ifndef SHADERCOMPILERGLES3_H
+#define SHADERCOMPILERGLES3_H
+
+#include "servers/visual/shader_language.h"
+#include "servers/visual/shader_types.h"
+#include "servers/visual_server.h"
+#include "pair.h"
+
+class ShaderCompilerGLES3 {
+public:
+ struct IdentifierActions {
+
+ Map<StringName,Pair<int*,int> > render_mode_values;
+ Map<StringName,bool*> render_mode_flags;
+ Map<StringName,bool*> usage_flag_pointers;
+
+ Map<StringName,ShaderLanguage::ShaderNode::Uniform> *uniforms;
+ };
+
+ struct GeneratedCode {
+
+ Vector<CharString> defines;
+ Vector<StringName> texture_uniforms;
+ Vector<uint32_t> uniform_offsets;
+ uint32_t uniform_total_size;
+ String uniforms;
+ String vertex_global;
+ String vertex;
+ String fragment_global;
+ String fragment;
+ String light;
+
+ };
+
+private:
+
+ ShaderLanguage parser;
+
+ struct DefaultIdentifierActions {
+
+ Map<StringName,String> renames;
+ Map<StringName,String> render_mode_defines;
+ Map<StringName,String> usage_defines;
+ };
+
+ void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName& p_for_func, const Map<StringName, String> &p_func_code, String& r_to_add,Set<StringName> &added);
+ String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions);
+
+
+
+ Set<StringName> used_name_defines;
+ Set<StringName> used_rmode_defines;
+ Set<StringName> internal_functions;
+
+
+ DefaultIdentifierActions actions[VS::SHADER_MAX];
+
+public:
+
+
+ Error compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String& p_path, GeneratedCode& r_gen_code);
+
+
+ ShaderCompilerGLES3();
+};
+
+#endif // SHADERCOMPILERGLES3_H
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index f8c0234943..35191fecf7 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -214,6 +214,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
}
+
+
v.ok=false;
/* SETUP CONDITIONALS */
@@ -245,6 +247,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
CharString code_string;
CharString code_string2;
CharString code_globals;
+ CharString material_string;
//print_line("code version? "+itos(conditional_version.code_version));
@@ -258,6 +261,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
cc=&custom_code_map[conditional_version.code_version];
v.code_version=cc->version;
define_line_ofs+=2;
+
}
@@ -273,7 +277,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
if (cc) {
for(int i=0;i<cc->custom_defines.size();i++) {
- strings.push_back(cc->custom_defines[i]);
+ strings.push_back(cc->custom_defines[i].get_data());
DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i]));
}
}
@@ -305,14 +309,22 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
code_globals=cc->vertex_globals.ascii();
strings.push_back(code_globals.get_data());
}
+
strings.push_back(vertex_code1.get_data());
if (cc) {
+ material_string=cc->uniforms.ascii();
+ strings.push_back(material_string.get_data());
+ }
+
+ strings.push_back(vertex_code2.get_data());
+
+ if (cc) {
code_string=cc->vertex.ascii();
strings.push_back(code_string.get_data());
}
- strings.push_back(vertex_code2.get_data());
+ strings.push_back(vertex_code3.get_data());
#ifdef DEBUG_SHADER
DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data()));
@@ -367,7 +379,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
ERR_FAIL_V(NULL);
}
-
+
+
/* FRAGMENT SHADER */
strings.resize(strings_base_size);
@@ -396,21 +409,29 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
code_globals=cc->fragment_globals.ascii();
strings.push_back(code_globals.get_data());
}
+
strings.push_back(fragment_code1.get_data());
if (cc) {
+ material_string=cc->uniforms.ascii();
+ strings.push_back(material_string.get_data());
+ }
+
+ strings.push_back(fragment_code2.get_data());
+
+ if (cc) {
code_string=cc->fragment.ascii();
strings.push_back(code_string.get_data());
}
- strings.push_back(fragment_code2.get_data());
+ strings.push_back(fragment_code3.get_data());
if (cc) {
code_string2=cc->light.ascii();
strings.push_back(code_string2.get_data());
}
- strings.push_back(fragment_code3.get_data());
+ strings.push_back(fragment_code4.get_data());
#ifdef DEBUG_SHADER
DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data()));
@@ -463,7 +484,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
ERR_FAIL_V( NULL );
}
-
+
glAttachShader(v.id,v.frag_id);
glAttachShader(v.id,v.vert_id);
@@ -552,10 +573,11 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
if ( cc ) {
- v.custom_uniform_locations.resize(cc->custom_uniforms.size());
- for(int i=0;i<cc->custom_uniforms.size();i++) {
+ v.texture_uniform_locations.resize(cc->texture_uniforms.size());
+ for(int i=0;i<cc->texture_uniforms.size();i++) {
- v.custom_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->custom_uniforms[i]).ascii().get_data());
+ v.texture_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->texture_uniforms[i]).ascii().get_data());
+ glUniform1i(v.texture_uniform_locations[i],i+base_material_tex_index);
}
}
@@ -597,6 +619,7 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
//split vertex and shader code (thank you, retarded shader compiler programmers from you know what company).
{
String globals_tag="\nVERTEX_SHADER_GLOBALS";
+ String material_tag="\nMATERIAL_UNIFORMS";
String code_tag="\nVERTEX_SHADER_CODE";
String code = vertex_code;
int cpos = code.find(globals_tag);
@@ -606,20 +629,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
vertex_code0=code.substr(0,cpos).ascii();
code = code.substr(cpos+globals_tag.length(),code.length());
- cpos = code.find(code_tag);
+ cpos = code.find(material_tag);
if (cpos==-1) {
vertex_code1=code.ascii();
} else {
vertex_code1=code.substr(0,cpos).ascii();
- vertex_code2=code.substr(cpos+code_tag.length(),code.length()).ascii();
+ String code2 = code.substr(cpos+material_tag.length(),code.length());
+
+ cpos = code2.find(code_tag);
+ if (cpos==-1) {
+ vertex_code2=code2.ascii();
+ } else {
+
+ vertex_code2=code2.substr(0,cpos).ascii();
+ vertex_code3 = code2.substr(cpos+code_tag.length(),code2.length()).ascii();
+ }
+
}
}
}
{
String globals_tag="\nFRAGMENT_SHADER_GLOBALS";
+ String material_tag="\nMATERIAL_UNIFORMS";
String code_tag="\nFRAGMENT_SHADER_CODE";
String light_code_tag="\nLIGHT_SHADER_CODE";
String code = fragment_code;
@@ -630,22 +664,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
fragment_code0=code.substr(0,cpos).ascii();
code = code.substr(cpos+globals_tag.length(),code.length());
- cpos = code.find(code_tag);
+ cpos = code.find(material_tag);
if (cpos==-1) {
fragment_code1=code.ascii();
} else {
fragment_code1=code.substr(0,cpos).ascii();
- String code2 = code.substr(cpos+code_tag.length(),code.length());
+ String code2 = code.substr(cpos+material_tag.length(),code.length());
- cpos = code2.find(light_code_tag);
+ cpos = code2.find(code_tag);
if (cpos==-1) {
fragment_code2=code2.ascii();
} else {
fragment_code2=code2.substr(0,cpos).ascii();
- fragment_code3 = code2.substr(cpos+light_code_tag.length(),code2.length()).ascii();
+ String code3 = code2.substr(cpos+code_tag.length(),code2.length());
+
+ cpos = code3.find(light_code_tag);
+ if (cpos==-1) {
+ fragment_code3=code3.ascii();
+ } else {
+
+ fragment_code3=code3.substr(0,cpos).ascii();
+ fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii();
+ }
}
}
}
@@ -697,7 +740,7 @@ uint32_t ShaderGLES3::create_custom_shader() {
return last_custom_code++;
}
-void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_light, const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines) {
+void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals, const String& p_fragment, const String& p_light, const String& p_fragment_globals, const String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines) {
ERR_FAIL_COND(!custom_code_map.has(p_code_id));
CustomCode *cc=&custom_code_map[p_code_id];
@@ -707,7 +750,8 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver
cc->fragment=p_fragment;
cc->fragment_globals=p_fragment_globals;
cc->light=p_light;
- cc->custom_uniforms=p_uniforms;
+ cc->texture_uniforms=p_texture_uniforms;
+ cc->uniforms=p_uniforms;
cc->custom_defines=p_custom_defines;
cc->version++;
}
@@ -734,13 +778,16 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) {
}
+void ShaderGLES3::set_base_material_tex_index(int p_idx) {
+ base_material_tex_index=p_idx;
+}
ShaderGLES3::ShaderGLES3() {
version=NULL;
last_custom_code=1;
uniforms_dirty = true;
-
+ base_material_tex_index=0;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units);
}
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 7aaf65d450..176a2282fd 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -105,9 +105,10 @@ private:
String fragment;
String fragment_globals;
String light;
+ String uniforms;
uint32_t version;
- Vector<StringName> custom_uniforms;
- Vector<const char*> custom_defines;
+ Vector<StringName> texture_uniforms;
+ Vector<CharString> custom_defines;
};
@@ -118,7 +119,7 @@ private:
GLuint vert_id;
GLuint frag_id;
GLint *uniform_location;
- Vector<GLint> custom_uniform_locations;
+ Vector<GLint> texture_uniform_locations;
uint32_t code_version;
bool ok;
Version() { code_version=0; ok=false; uniform_location=NULL; }
@@ -166,10 +167,14 @@ private:
CharString fragment_code1;
CharString fragment_code2;
CharString fragment_code3;
+ CharString fragment_code4;
CharString vertex_code0;
CharString vertex_code1;
CharString vertex_code2;
+ CharString vertex_code3;
+
+ int base_material_tex_index;
Version * get_current_version();
@@ -308,7 +313,7 @@ public:
void clear_caches();
uint32_t create_custom_shader();
- void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines);
+ void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const String& p_uniforms,const Vector<StringName>& p_texture_uniforms,const Vector<CharString> &p_custom_defines);
void set_custom_shader(uint32_t p_id);
void free_custom_shader(uint32_t p_id);
@@ -332,23 +337,25 @@ public:
uniforms_dirty = true;
};
- _FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant& p_value) {
+ _FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant& p_value) {
ERR_FAIL_COND(!version);
- ERR_FAIL_INDEX(p_idx,version->custom_uniform_locations.size());
- _set_uniform_variant( version->custom_uniform_locations[p_idx], p_value );
+ ERR_FAIL_INDEX(p_idx,version->texture_uniform_locations.size());
+ _set_uniform_variant( version->texture_uniform_locations[p_idx], p_value );
}
- _FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) {
+ _FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) {
ERR_FAIL_COND_V(!version,-1);
- ERR_FAIL_INDEX_V(p_idx,version->custom_uniform_locations.size(),-1);
- return version->custom_uniform_locations[p_idx];
+ ERR_FAIL_INDEX_V(p_idx,version->texture_uniform_locations.size(),-1);
+ return version->texture_uniform_locations[p_idx];
}
virtual void init()=0;
void finish();
+ void set_base_material_tex_index(int p_idx);
+
virtual ~ShaderGLES3();
};
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index eed2239ec9..cf2e0f776f 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -1,7 +1,7 @@
[vertex]
-layout(location=0) in highp vec3 vertex;
+layout(location=0) in highp vec2 vertex;
layout(location=3) in vec4 color_attrib;
#ifdef USE_TEXTURE_RECT
@@ -20,6 +20,7 @@ layout(location=4) in highp vec2 uv_attrib;
layout(std140) uniform CanvasItemData { //ubo:0
highp mat4 projection_matrix;
+ highp vec4 time;
};
uniform highp mat4 modelview_matrix;
@@ -29,10 +30,6 @@ uniform highp mat4 extra_matrix;
out mediump vec2 uv_interp;
out mediump vec4 color_interp;
-#if defined(USE_TIME)
-uniform float time;
-#endif
-
#ifdef USE_LIGHTING
layout(std140) uniform LightData { //ubo:1
@@ -51,6 +48,7 @@ layout(std140) uniform LightData { //ubo:1
highp float shadow_distance_mult;
};
+
out vec4 light_uv_interp;
#if defined(NORMAL_USED)
@@ -66,20 +64,30 @@ out highp vec2 pos;
VERTEX_SHADER_GLOBALS
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData { //ubo:2
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
void main() {
- color_interp = color_attrib;
+ vec4 vertex_color = color_attrib;
#ifdef USE_TEXTURE_RECT
- uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.xy;
- highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex.xy,vec2(1.0,1.0)-vertex.xy,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0);
+ uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
+ highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex,vec2(1.0,1.0)-vertex,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0);
#else
uv_interp = uv_attrib;
- highp vec4 outvec = vec4(vertex, 1.0);
+ highp vec4 outvec = vec4(vertex,0.0,1.0);
#endif
@@ -90,16 +98,16 @@ VERTEX_SHADER_CODE
}
-#if !defined(USE_WORLD_VEC)
+#if !defined(SKIP_TRANSFORM_USED)
outvec = extra_matrix * outvec;
outvec = modelview_matrix * outvec;
#endif
-
+ color_interp = vertex_color;
#ifdef USE_PIXEL_SNAP
- outvec.xy=floor(outvec.xy+0.5);
+ outvec.xy=floor(outvec+0.5);
#endif
@@ -132,20 +140,24 @@ VERTEX_SHADER_CODE
uniform mediump sampler2D color_texture; // texunit:0
+uniform highp vec2 color_texpixel_size;
in mediump vec2 uv_interp;
in mediump vec4 color_interp;
-#if defined(ENABLE_TEXSCREEN)
+#if defined(SCREEN_TEXTURE_USED)
-uniform sampler2D texscreen_tex; // texunit:-3
+uniform sampler2D screen_texture; // texunit:-3
#endif
-#if defined(USE_TIME)
-uniform float time;
-#endif
+layout(std140) uniform CanvasItemData {
+
+ highp mat4 projection_matrix;
+ highp vec4 time;
+};
+
#ifdef USE_LIGHTING
@@ -188,6 +200,17 @@ FRAGMENT_SHADER_GLOBALS
layout(location=0) out mediump vec4 frag_color;
+
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData {
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
void main() {
vec4 color = color_interp;
@@ -195,6 +218,9 @@ void main() {
vec3 normal = vec3(0.0,0.0,1.0);
#endif
+#if !defined(COLOR_USED)
+//default behavior, texture by color
+
#ifdef USE_DISTANCE_FIELD
const float smoothing = 1.0/32.0;
float distance = texture(color_texture, uv_interp).a;
@@ -204,6 +230,7 @@ void main() {
#endif
+#endif
#if defined(ENABLE_SCREEN_UV)
vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult;
@@ -211,14 +238,15 @@ void main() {
{
-#if defined(USE_NORMALMAP)
- vec3 normal_map=vec3(0.0,0.0,1.0);
float normal_depth=1.0;
+
+#if defined(NORMALMAP_USED)
+ vec3 normal_map=vec3(0.0,0.0,1.0);
#endif
FRAGMENT_SHADER_CODE
-#if defined(USE_NORMALMAP)
+#if defined(NORMALMAP_USED)
normal = mix(vec3(0.0,0.0,1.0), normal_map * vec3(2.0,-2.0,1.0) - vec3( 1.0, -1.0, 0.0 ), normal_depth );
#endif
@@ -246,7 +274,7 @@ FRAGMENT_SHADER_CODE
vec2 light_uv = light_uv_interp.xy;
vec4 light = texture(light_texture,light_uv) * light_color;
-#if defined(USE_OUTPUT_SHADOW_COLOR)
+#if defined(SHADOW_COLOR_USED)
vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
#endif
@@ -409,7 +437,7 @@ LIGHT_SHADER_CODE
#endif
-#if defined(USE_OUTPUT_SHADOW_COLOR)
+#if defined(SHADOW_COLOR_USED)
color=mix(shadow_color,color,shadow_attenuation);
#else
//color*=shadow_attenuation;
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 271cf302ef..b9ee6178f0 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -88,6 +88,10 @@ void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,c
print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
break;
+ case ERR_SHADER:
+ print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;36m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
}
}