diff options
Diffstat (limited to 'scene/resources/shader.cpp')
-rw-r--r-- | scene/resources/shader.cpp | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp new file mode 100644 index 0000000000..ffdd92c2d1 --- /dev/null +++ b/scene/resources/shader.cpp @@ -0,0 +1,417 @@ +/*************************************************************************/ +/* shader.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "shader.h" +#include "servers/visual_server.h" +#include "texture.h" +#include "os/file_access.h" +#include "scene/scene_string_names.h" + + +void Shader::set_mode(Mode p_mode) { + + ERR_FAIL_INDEX(p_mode,2); + VisualServer::get_singleton()->shader_set_mode(shader,VisualServer::ShaderMode(p_mode)); + emit_signal(SceneStringNames::get_singleton()->changed); +} + +Shader::Mode Shader::get_mode() const { + + return (Mode)VisualServer::get_singleton()->shader_get_mode(shader); +} + +void Shader::set_code( const String& p_vertex, const String& p_fragment, int p_vertex_ofs,int p_fragment_ofs) { + + VisualServer::get_singleton()->shader_set_code(shader,p_vertex,p_fragment,p_vertex_ofs,p_fragment_ofs); + params_cache_dirty=true; + emit_signal(SceneStringNames::get_singleton()->changed); +} + + +String Shader::get_vertex_code() const { + + return VisualServer::get_singleton()->shader_get_vertex_code(shader); +} + +String Shader::get_fragment_code() const { + + return VisualServer::get_singleton()->shader_get_fragment_code(shader); + +} + + +bool Shader::has_param(const StringName& p_param) const { + + if (params_cache_dirty) + get_param_list(NULL); + + return (params_cache.has(p_param)); +} + + +void Shader::get_param_list(List<PropertyInfo> *p_params) const { + + + List<PropertyInfo> local; + VisualServer::get_singleton()->shader_get_param_list(shader,&local); + params_cache.clear(); + params_cache_dirty=false; + + for(List<PropertyInfo>::Element *E=local.front();E;E=E->next()) { + + PropertyInfo pi=E->get(); + pi.name="param/"+pi.name; + params_cache[pi.name]=E->get().name; + if (p_params) { + + //small little hack + if (pi.type==Variant::_RID) + pi.type=Variant::OBJECT; + p_params->push_back(pi); + } + } +} + +RID Shader::get_rid() const { + + return shader; +} + +Dictionary Shader::_get_code() { + + String fs = VisualServer::get_singleton()->shader_get_fragment_code(shader); + String vs = VisualServer::get_singleton()->shader_get_vertex_code(shader); + + Dictionary c; + c["fragment"]=fs; + c["fragment_ofs"]=0; + c["vertex"]=vs; + c["vertex_ofs"]=0; + return c; +} + +void Shader::_set_code(const Dictionary& p_string) { + + ERR_FAIL_COND(!p_string.has("fragment")); + ERR_FAIL_COND(!p_string.has("vertex")); + + set_code(p_string["vertex"],p_string["fragment"]); +} + +void Shader::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Shader::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&Shader::get_mode); + + ObjectTypeDB::bind_method(_MD("set_code","vcode","fcode","vofs","fofs"),&Shader::set_code,DEFVAL(0),DEFVAL(0)); + ObjectTypeDB::bind_method(_MD("get_vertex_code"),&Shader::get_vertex_code); + ObjectTypeDB::bind_method(_MD("get_fragment_code"),&Shader::get_fragment_code); + + ObjectTypeDB::bind_method(_MD("has_param","name"),&Shader::has_param); + + ObjectTypeDB::bind_method(_MD("_set_code","code"),&Shader::_set_code); + ObjectTypeDB::bind_method(_MD("_get_code"),&Shader::_get_code); + + //ObjectTypeDB::bind_method(_MD("get_param_list"),&Shader::get_fragment_code); + + + ADD_PROPERTY( PropertyInfo(Variant::STRING, "_code",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_code"), _SCS("_get_code") ); + + BIND_CONSTANT( MODE_MATERIAL ); + BIND_CONSTANT( MODE_CANVAS_ITEM ); + BIND_CONSTANT( MODE_POST_PROCESS ); + +} + +Shader::Shader() { + + shader = VisualServer::get_singleton()->shader_create(); + params_cache_dirty=true; +} + +Shader::~Shader() { + + VisualServer::get_singleton()->free(shader); +} + + + +/************ Loader from text ***************/ + + + +RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_original_path) { + + String fragment_code; + String vertex_code; + + int mode=-1; + + Error err; + FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); + + + ERR_EXPLAIN("Unable to open shader file: "+p_path); + ERR_FAIL_COND_V(err,RES()); + String base_path = p_path.get_base_dir(); + + + Ref<Shader> shader( memnew( Shader ) ); + + int line=0; + + while(!f->eof_reached()) { + + String l = f->get_line(); + line++; + + if (mode<=0) { + l = l.strip_edges(); + int comment = l.find(";"); + if (comment!=-1) + l=l.substr(0,comment); + } + + if (mode<1) + vertex_code+="\n"; + if (mode<2) + fragment_code+="\n"; + + if (mode < 1 && l=="") + continue; + + if (l.begins_with("[")) { + l=l.strip_edges(); + if (l=="[params]") { + if (mode>=0) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [params] section."); + ERR_FAIL_V(RES()); + } + mode=0; + } else if (l=="[vertex]") { + if (mode>=1) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [vertex] section."); + ERR_FAIL_V(RES()); + } + mode=1; + } else if (l=="[fragment]") { + if (mode>=2) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [fragment] section."); + ERR_FAIL_V(RES()); + } + mode=1; + } else { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Unknown section type: '"+l+"'."); + ERR_FAIL_V(RES()); + } + continue; + } + + if (mode==0) { + + int eqpos = l.find("="); + if (eqpos==-1) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Expected '='."); + ERR_FAIL_V(RES()); + } + + + String right=l.substr(eqpos+1,l.length()).strip_edges(); + if (right=="") { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Expected value after '='."); + ERR_FAIL_V(RES()); + } + + Variant value; + + if (right=="true") { + value = true; + } else if (right=="false") { + value = false; + } else if (right.is_valid_float()) { + //is number + value = right.to_double(); + } else if (right.is_valid_html_color()) { + //is html color + value = Color::html(right); + } else { + //attempt to parse a constructor + int popenpos = right.find("("); + + if (popenpos==-1) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor syntax: "+right); + ERR_FAIL_V(RES()); + } + + int pclosepos = right.find_last(")"); + + if (pclosepos==-1) { + ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor parameter syntax: "+right); + ERR_FAIL_V(RES()); + + } + + String type = right.substr(0,popenpos); + String param = right.substr(popenpos+1,pclosepos-popenpos-1).strip_edges(); + + print_line("type: "+type+" param: "+param); + + if (type=="tex") { + + if (param=="") { + + value=RID(); + } else { + + String path; + + if (param.is_abs_path()) + path=param; + else + path=base_path+"/"+param; + + Ref<Texture> texture = ResourceLoader::load(path); + if (!texture.is_valid()) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Couldn't find icon at path: "+path); + ERR_FAIL_V(RES()); + } + + value=texture; + } + + } else if (type=="vec3") { + + if (param=="") { + value=Vector3(); + } else { + Vector<String> params = param.split(","); + if (params.size()!=3) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for vec3(): '"+right+"'."); + ERR_FAIL_V(RES()); + + } + + Vector3 v; + for(int i=0;i<3;i++) + v[i]=params[i].to_double(); + value=v; + } + + + } else if (type=="xform") { + + if (param=="") { + value=Transform(); + } else { + + Vector<String> params = param.split(","); + if (params.size()!=12) { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for xform(): '"+right+"'."); + ERR_FAIL_V(RES()); + + } + + Transform t; + for(int i=0;i<9;i++) + t.basis[i%3][i/3]=params[i].to_double(); + for(int i=0;i<3;i++) + t.origin[i]=params[i-9].to_double(); + + value=t; + } + + } else { + memdelete(f); + ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor type: '"+type+"'."); + ERR_FAIL_V(RES()); + + } + + } + + String left= l.substr(0,eqpos); + +// shader->set_param(left,value); + } else if (mode==1) { + + vertex_code+=l; + + } else if (mode==2) { + + fragment_code+=l; + } + } + + shader->set_code(vertex_code,fragment_code); + + f->close(); + memdelete(f); + + return shader; +} + +void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("shader"); +} +bool ResourceFormatLoaderShader::handles_type(const String& p_type) const { + + return p_type=="Shader"; +} + + +String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const { + + if (p_path.extension().to_lower()=="shader") + return "Shader"; + return ""; +} + + + + + + + + + + + + + + |