2D Shaders are working again using the new syntax, though all is buggy in general

This commit is contained in:
Juan Linietsky 2016-10-10 18:31:01 -03:00
parent 850eaf7ed7
commit 1527cf8c0d
26 changed files with 1980 additions and 173 deletions

View file

@ -49,7 +49,8 @@
enum ErrorHandlerType {
ERR_HANDLER_ERROR,
ERR_HANDLER_WARNING,
ERR_HANDLER_SCRIPT
ERR_HANDLER_SCRIPT,
ERR_HANDLER_SHADER,
};
typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);

View file

@ -68,6 +68,7 @@ void OS::print_error(const char* p_function,const char* p_file,int p_line,const
case ERR_ERROR: err_type="**ERROR**"; break;
case ERR_WARNING: err_type="**WARNING**"; break;
case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break;
case ERR_SHADER: err_type="**SHADER ERROR**"; break;
}
if (p_rationale && *p_rationale)

View file

@ -120,7 +120,8 @@ public:
enum ErrorType {
ERR_ERROR,
ERR_WARNING,
ERR_SCRIPT
ERR_SCRIPT,
ERR_SHADER
};
virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);

View file

@ -34,6 +34,9 @@ struct Pair {
F first;
S second;
Pair() {}
Pair( F p_first, S p_second) { first=p_first; second=p_second; }
};
#endif // PAIR_H

View file

@ -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) {
case VS::MATERIAL_BLEND_MODE_MIX: {
switch(blend_mode) {
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);

View file

@ -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];
};

View file

@ -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;
}

View file

@ -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)) {

View file

@ -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();

View file

@ -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());
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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();
};

View file

@ -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;

View file

@ -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;
}
}

View file

@ -1727,6 +1727,10 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
case ERR_SHADER:
print("SHADER ERROR: %s: %s\n", p_function, err_details);
print(" At: %s:%i\n", p_file, p_line);
break;
}
} else {
@ -1742,6 +1746,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
case ERR_ERROR: basecol = FOREGROUND_RED; break;
case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
}
basecol |= current_bg;
@ -1753,6 +1758,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
case ERR_ERROR: print("ERROR: "); break;
case ERR_WARNING: print("WARNING: "); break;
case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
case ERR_SCRIPT: print("SHADER ERROR: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
@ -1763,6 +1769,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
case ERR_ERROR: print(" At: "); break;
case ERR_WARNING: print(" At: "); break;
case ERR_SCRIPT: print(" At: "); break;
case ERR_SHADER: print(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);
@ -1775,6 +1782,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
case ERR_ERROR: print("ERROR: %s: ", p_function); break;
case ERR_WARNING: print("WARNING: %s: ", p_function); break;
case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
case ERR_SHADER: print("SCRIPT ERROR: %s: ", p_function); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
@ -1785,6 +1793,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
case ERR_ERROR: print(" At: "); break;
case ERR_WARNING: print(" At: "); break;
case ERR_SCRIPT: print(" At: "); break;
case ERR_SHADER: print(" At: "); break;
}
SetConsoleTextAttribute(hCon, current_fg | current_bg);

View file

@ -55,7 +55,7 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value)
}
}
if (pr) {
VisualServer::get_singleton()->material_set_param(material,pr,p_value);
VisualServer::get_singleton()->material_set_param(_get_material(),pr,p_value);
return true;
}
}
@ -78,7 +78,7 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
StringName pr = shader->remap_param(p_name);
if (pr) {
r_ret=VisualServer::get_singleton()->material_get_param(material,pr);
r_ret=VisualServer::get_singleton()->material_get_param(_get_material(),pr);
return true;
}
}
@ -111,7 +111,7 @@ void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) {
if (shader.is_valid())
rid=shader->get_rid();
VS::get_singleton()->material_set_shader(material,rid);
VS::get_singleton()->material_set_shader(_get_material(),rid);
_change_notify(); //properties for shader exposed
emit_changed();
}
@ -123,18 +123,14 @@ Ref<Shader> CanvasItemMaterial::get_shader() const{
void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
VS::get_singleton()->material_set_param(material,p_param,p_value);
VS::get_singleton()->material_set_param(_get_material(),p_param,p_value);
}
Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
return VS::get_singleton()->material_get_param(material,p_param);
return VS::get_singleton()->material_get_param(_get_material(),p_param);
}
RID CanvasItemMaterial::get_rid() const {
return material;
}
void CanvasItemMaterial::_bind_methods() {

View file

@ -41,10 +41,9 @@ class Font;
class StyleBox;
class CanvasItemMaterial : public Material{
class CanvasItemMaterial : public Material {
OBJ_TYPE(CanvasItemMaterial,Material);
RID material;
Ref<Shader> shader;
public:
/*enum ShadingMode {
@ -70,7 +69,6 @@ public:
void set_shader_param(const StringName& p_param,const Variant& p_value);
Variant get_shader_param(const StringName& p_param) const;
virtual RID get_rid() const;
CanvasItemMaterial();
~CanvasItemMaterial();
};

View file

@ -34,31 +34,12 @@
#include "os/input.h"
#include "os/keyboard.h"
void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,float s,float v) {
if (!mat.is_valid())
return;
Ref<Shader> sdr = mat->get_shader();
if (!sdr.is_valid())
return;
mat->set_shader_param("R",p_color.r);
mat->set_shader_param("G",p_color.g);
mat->set_shader_param("B",p_color.b);
mat->set_shader_param("H",h);
mat->set_shader_param("S",s);
mat->set_shader_param("V",v);
mat->set_shader_param("A",p_color.a);
}
void ColorPicker::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_THEME_CHANGED: {
uv_material->set_shader(get_shader("uv_editor"));
w_material->set_shader(get_shader("w_editor"));
update_material(uv_material,color,h,s,v);
update_material(w_material,color,h,s,v);
uv_edit->set_texture(get_icon("color_main"));
w_edit->set_texture(get_icon("color_hue"));
sample->set_texture(get_icon("color_sample"));
@ -68,8 +49,6 @@ void ColorPicker::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
update_material(uv_material, color,h,s,v);
update_material(w_material, color,h,s,v);
uv_edit->get_child(0)->cast_to<Control>()->update();
w_edit->get_child(0)->cast_to<Control>()->update();
@ -113,8 +92,6 @@ void ColorPicker::set_color(const Color& p_color) {
if (!is_inside_tree())
return;
update_material(uv_material, color,h,s,v);
update_material(w_material, color,h,s,v);
uv_edit->get_child(0)->cast_to<Control>()->update();
w_edit->get_child(0)->cast_to<Control>()->update();
@ -509,7 +486,6 @@ ColorPicker::ColorPicker() :
uv_edit->add_child(c);
c->set_area_as_parent_rect();
c->set_stop_mouse(false);
c->set_material(memnew ( CanvasItemMaterial ));
Vector<Variant> args=Vector<Variant>();
args.push_back(0);
args.push_back(c);
@ -525,7 +501,6 @@ ColorPicker::ColorPicker() :
w_edit->add_child(c);
c->set_area_as_parent_rect();
c->set_stop_mouse(false);
c->set_material(memnew ( CanvasItemMaterial ));
args.clear();
args.push_back(1);
args.push_back(c);
@ -593,18 +568,6 @@ ColorPicker::ColorPicker() :
//_update_color();
updating=false;
uv_material.instance();
Ref<Shader> s_uv = get_shader("uv_editor");
uv_material->set_shader(s_uv);
w_material.instance();
Ref<Shader> s_w = get_shader("w_editor");
w_material->set_shader(s_w);
uv_edit->set_material(uv_material);
w_edit->set_material(w_material);
set_color(Color(1,1,1));

View file

@ -57,8 +57,6 @@ private:
List<Color> presets;
ToolButton *btn_pick;
CheckButton *btn_mode;
Ref<CanvasItemMaterial> uv_material;
Ref<CanvasItemMaterial> w_material;
HSlider *scroll[4];
SpinBox *values[4];
Label *labels[4];

View file

@ -46,6 +46,9 @@ class Material : public Resource {
OBJ_SAVE_TYPE( Material );
RID material;
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
public:
virtual RID get_rid() const;

View file

@ -712,6 +712,8 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
void ShaderLanguage::clear() {
current_function=StringName();
completion_type=COMPLETION_NONE;
completion_block=NULL;
completion_function=StringName();
@ -2096,6 +2098,12 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) {
return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT;
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
return p_type==TYPE_SAMPLER2D || p_type==TYPE_ISAMPLER2D || p_type==TYPE_USAMPLER2D || p_type==TYPE_SAMPLERCUBE;
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
Set<String> kws;
@ -2122,6 +2130,27 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
}
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
Set<String> kws;
int idx=0;
while (builtin_func_defs[idx].name) {
kws.insert(builtin_func_defs[idx].name);
idx++;
}
for(Set<String>::Element *E=kws.front();E;E=E->next()) {
r_keywords->push_back(E->get());
}
}
ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
static const DataType scalar_types[]={
@ -2342,6 +2371,12 @@ ShaderLanguage::Node* ShaderLanguage::_parse_expression(BlockNode* p_block,const
bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg);
for(int i=0;i<shader->functions.size();i++) {
if (shader->functions[i].name==name) {
shader->functions[i].uses_function.insert(name);
}
}
if (carg>=0) {
@ -3140,6 +3175,9 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
Token tk = _get_token();
int texture_uniforms = 0;
int uniforms =0;
while(tk.type!=TK_EOF) {
switch(tk.type) {
@ -3160,12 +3198,12 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
return ERR_PARSE_ERROR;
}
if (shader->render_modes.has(tk.text)) {
if (shader->render_modes.find(tk.text)!=-1) {
_set_error("Duplicate render mode: '"+String(tk.text)+"'");
return ERR_PARSE_ERROR;
}
shader->render_modes.insert(tk.text);
shader->render_modes.push_back(tk.text);
tk = _get_token();
if (tk.type==TK_COMMA) {
@ -3225,6 +3263,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
ShaderNode::Uniform uniform;
uniform.order=shader->uniforms.size();
if (is_sampler_type(type)) {
uniform.texture_order=texture_uniforms++;
uniform.order=-1;
} else {
uniform.texture_order=-1;
uniform.order=uniforms++;
}
uniform.type=type;
uniform.precission=precision;
@ -3520,9 +3565,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
return ERR_PARSE_ERROR;
}
current_function = name;
Error err = _parse_block(func_node->body,builtin_types);
if (err)
return err;
current_function=StringName();
}
}

View file

@ -370,6 +370,7 @@ public:
struct Function {
StringName name;
FunctionNode*function;
Set<StringName> uses_function;
bool callable;
};
@ -391,6 +392,7 @@ public:
};
int order;
int texture_order;
DataType type;
DataPrecision precission;
Vector<ConstantNode::Value> default_value;
@ -403,7 +405,7 @@ public:
Map<StringName,Varying> varyings;
Map<StringName,Uniform> uniforms;
Set<StringName> render_modes;
Vector<StringName> render_modes;
Vector<Function> functions;
@ -461,8 +463,10 @@ public:
static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL);
static DataType get_scalar_type(DataType p_type);
static bool is_scalar_type(DataType p_type);
static bool is_sampler_type(DataType p_type);
static void get_keyword_list(List<String> *r_keywords);
static void get_builtin_funcs(List<String> *r_keywords);
private:
struct KeyWord { TokenType token; const char *text;};
@ -476,6 +480,8 @@ private:
int char_idx;
int tk_line;
StringName current_function;
struct TkPos {
int char_idx;
int tk_line;

View file

@ -18,6 +18,7 @@ ShaderTypes::ShaderTypes()
{
singleton=this;
/*************** SPATIAL ***********************/
shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3;
@ -96,4 +97,65 @@ ShaderTypes::ShaderTypes()
shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_model_space");
shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_camera_space");
/************ CANVAS ITEM **************************/
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX_COLOR"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"]=ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR1"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR2"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_VEC"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_HEIGHT"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_COLOR"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_UV"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_SHADOW"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SHADOW"]=ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_premul_alpha");
shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
shader_modes[VS::SHADER_SPATIAL].modes.insert("light_only");
}

View file

@ -140,6 +140,7 @@ public:
SHADER_SPATIAL,
SHADER_CANVAS_ITEM,
SHADER_LIGHT,
SHADER_MAX
};

View file

@ -67,6 +67,10 @@ void EditorLog::_error_handler(void *p_self, const char*p_func, const char*p_fil
icon = self->get_icon("ScriptError","EditorIcons");
} break;
case ERR_HANDLER_SHADER: {
icon = self->get_icon("Shader","EditorIcons");
} break;
}