diff options
Diffstat (limited to 'drivers/gles2/shader_gles2.cpp')
-rw-r--r-- | drivers/gles2/shader_gles2.cpp | 389 |
1 files changed, 383 insertions, 6 deletions
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index baada9331e..146575973f 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -33,7 +33,10 @@ #include "print_string.h" #include "string_builder.h" -//#define DEBUG_OPENGL +#include "rasterizer_gles2.h" +#include "rasterizer_storage_gles2.h" + +// #define DEBUG_OPENGL // #include "shaders/copy.glsl.gen.h" @@ -54,7 +57,7 @@ ShaderGLES2 *ShaderGLES2::active = NULL; -//#define DEBUG_SHADER +// #define DEBUG_SHADER #ifdef DEBUG_SHADER @@ -83,7 +86,10 @@ void ShaderGLES2::bind_uniforms() { continue; } - const Variant &v = E->value(); + Variant v; + + v = E->value(); + _set_uniform_variant(location, v); E = E->next(); } @@ -128,6 +134,28 @@ bool ShaderGLES2::bind() { glUseProgram(version->id); + // find out uniform names and locations + + int count; + glGetProgramiv(version->id, GL_ACTIVE_UNIFORMS, &count); + version->uniform_names.resize(count); + + for (int i = 0; i < count; i++) { + GLchar uniform_name[1024]; + int len = 0; + GLint size = 0; + GLenum type; + + glGetActiveUniform(version->id, i, 1024, &len, &size, &type, uniform_name); + + uniform_name[len] = '\0'; + String name = String((const char *)uniform_name); + + version->uniform_names.write[i] = name; + } + + bind_uniforms(); + DEBUG_TEST_ERROR("use program"); active = this; @@ -228,7 +256,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { } if (!_v) - version_map[conditional_version]; + version_map[conditional_version] = Version(); Version &v = version_map[conditional_version]; @@ -389,6 +417,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { strings.push_back(fragment_code3.get_data()); #ifdef DEBUG_SHADER + + if (cc) { + DEBUG_PRINT("\nFragment Code:\n\n" + String(cc->fragment_globals)); + } DEBUG_PRINT("\nFragment Code:\n\n" + String(code_string.get_data())); #endif @@ -500,9 +532,18 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { } if (cc) { - v.custom_uniform_locations.resize(cc->custom_uniforms.size()); + // uniforms for (int i = 0; i < cc->custom_uniforms.size(); i++) { - v.custom_uniform_locations.write[i] = glGetUniformLocation(v.id, String(cc->custom_uniforms[i]).ascii().get_data()); + StringName native_uniform_name = "m_" + cc->custom_uniforms[i]; + GLint location = glGetUniformLocation(v.id, ((String)native_uniform_name).ascii().get_data()); + v.custom_uniform_locations[cc->custom_uniforms[i]] = location; + } + + // textures + for (int i = 0; i < cc->texture_uniforms.size(); i++) { + StringName native_uniform_name = "m_" + cc->texture_uniforms[i]; + GLint location = glGetUniformLocation(v.id, ((String)native_uniform_name).ascii().get_data()); + v.custom_uniform_locations[cc->texture_uniforms[i]] = location; } } @@ -660,6 +701,7 @@ void ShaderGLES2::set_custom_shader_code(uint32_t p_code_id, cc->light = p_light; cc->custom_uniforms = p_uniforms; cc->custom_defines = p_custom_defines; + cc->texture_uniforms = p_texture_uniforms; cc->version++; } @@ -675,6 +717,341 @@ void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { custom_code_map.erase(p_code_id); } +void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) { + RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material; + + if (!material) { + return; + } + + if (!material->shader) { + return; + } + + Version *v = version_map.getptr(conditional_version); + + CustomCode *cc = NULL; + if (v) { + cc = custom_code_map.getptr(v->code_version); + } + + // bind uniforms + for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) { + + if (E->get().texture_order >= 0) + continue; // this is a texture, doesn't go here + + Map<StringName, Variant>::Element *V = material->params.find(E->key()); + + Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value; + + value.first = E->get().type; + value.second = E->get().default_value; + + if (V) { + value.second = Vector<ShaderLanguage::ConstantNode::Value>(); + value.second.resize(E->get().default_value.size()); + switch (E->get().type) { + case ShaderLanguage::TYPE_BOOL: { + if (value.second.size() < 1) + value.second.resize(1); + value.second.write[0].boolean = V->get(); + } break; + + case ShaderLanguage::TYPE_BVEC2: { + if (value.second.size() < 2) + value.second.resize(2); + int flags = V->get(); + value.second.write[0].boolean = flags & 1; + value.second.write[1].boolean = flags & 2; + } break; + + case ShaderLanguage::TYPE_BVEC3: { + if (value.second.size() < 3) + value.second.resize(3); + int flags = V->get(); + value.second.write[0].boolean = flags & 1; + value.second.write[1].boolean = flags & 2; + value.second.write[2].boolean = flags & 4; + + } break; + + case ShaderLanguage::TYPE_BVEC4: { + if (value.second.size() < 4) + value.second.resize(4); + int flags = V->get(); + value.second.write[0].boolean = flags & 1; + value.second.write[1].boolean = flags & 2; + value.second.write[2].boolean = flags & 4; + value.second.write[3].boolean = flags & 8; + + } break; + + case ShaderLanguage::TYPE_INT: { + if (value.second.size() < 1) + value.second.resize(1); + int val = V->get(); + value.second.write[0].sint = val; + } break; + + case ShaderLanguage::TYPE_IVEC2: { + if (value.second.size() < 2) + value.second.resize(2); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].sint = val[i]; + } + } break; + + case ShaderLanguage::TYPE_IVEC3: { + if (value.second.size() < 3) + value.second.resize(3); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].sint = val[i]; + } + + } break; + + case ShaderLanguage::TYPE_IVEC4: { + if (value.second.size() < 4) + value.second.resize(4); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].sint = val[i]; + } + + } break; + + case ShaderLanguage::TYPE_UINT: { + if (value.second.size() < 1) + value.second.resize(1); + uint32_t val = V->get(); + value.second.write[0].uint = val; + } break; + + case ShaderLanguage::TYPE_UVEC2: { + if (value.second.size() < 2) + value.second.resize(2); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].uint = val[i]; + } + + } break; + + case ShaderLanguage::TYPE_UVEC3: { + if (value.second.size() < 3) + value.second.resize(3); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].uint = val[i]; + } + + } break; + + case ShaderLanguage::TYPE_UVEC4: { + if (value.second.size() < 4) + value.second.resize(4); + PoolIntArray val = V->get(); + for (int i = 0; i < val.size(); i++) { + value.second.write[i].uint = val[i]; + } + + } break; + + case ShaderLanguage::TYPE_FLOAT: { + if (value.second.size() < 1) + value.second.resize(1); + value.second.write[0].real = V->get(); + + } break; + + case ShaderLanguage::TYPE_VEC2: { + if (value.second.size() < 2) + value.second.resize(2); + Vector2 val = V->get(); + value.second.write[0].real = val.x; + value.second.write[1].real = val.y; + } break; + + case ShaderLanguage::TYPE_VEC3: { + if (value.second.size() < 3) + value.second.resize(3); + Vector3 val = V->get(); + value.second.write[0].real = val.x; + value.second.write[1].real = val.y; + value.second.write[2].real = val.z; + } break; + + case ShaderLanguage::TYPE_VEC4: { + if (value.second.size() < 4) + value.second.resize(4); + if (V->get().get_type() == Variant::PLANE) { + Plane val = V->get(); + value.second.write[0].real = val.normal.x; + value.second.write[1].real = val.normal.y; + value.second.write[2].real = val.normal.z; + value.second.write[3].real = val.d; + } else { + Color val = V->get(); + value.second.write[0].real = val.r; + value.second.write[1].real = val.g; + value.second.write[2].real = val.b; + value.second.write[3].real = val.a; + } + + } break; + + case ShaderLanguage::TYPE_MAT2: { + Transform2D val = V->get(); + + // TODO + + } break; + + case ShaderLanguage::TYPE_MAT3: { + Basis val = V->get(); + + // TODO + } break; + + case ShaderLanguage::TYPE_MAT4: { + Transform val = V->get(); + + // TODO + } break; + + case ShaderLanguage::TYPE_SAMPLER2D: { + + } break; + + case ShaderLanguage::TYPE_ISAMPLER2D: { + + } break; + + case ShaderLanguage::TYPE_USAMPLER2D: { + + } break; + + case ShaderLanguage::TYPE_SAMPLERCUBE: { + + } break; + } + } else { + if (value.second.size() == 0) { + // No default value set... weird, let's just use zero for everything + size_t default_arg_size = 1; + bool is_float = false; + switch (E->get().type) { + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: { + default_arg_size = 1; + } break; + + case ShaderLanguage::TYPE_FLOAT: { + default_arg_size = 1; + is_float = true; + } break; + + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: { + default_arg_size = 2; + } break; + + case ShaderLanguage::TYPE_VEC2: { + default_arg_size = 2; + is_float = true; + } break; + + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: { + default_arg_size = 3; + } break; + + case ShaderLanguage::TYPE_VEC3: { + default_arg_size = 3; + is_float = true; + } break; + + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: { + default_arg_size = 4; + } break; + + case ShaderLanguage::TYPE_VEC4: { + default_arg_size = 4; + is_float = true; + } break; + + default: { + // TODO matricies and all that stuff + default_arg_size = 1; + } break; + } + + value.second.resize(default_arg_size); + + for (int i = 0; i < default_arg_size; i++) { + if (is_float) { + value.second.write[i].real = 0.0; + } else { + value.second.write[i].uint = 0; + } + } + } + } + + // GLint location = get_uniform_location(E->key()); + + GLint location; + if (v->custom_uniform_locations.has(E->key())) { + location = v->custom_uniform_locations[E->key()]; + } else { + int idx = v->uniform_names.find(E->key()); // TODO maybe put those in a Map? + if (idx < 0) { + location = -1; + } else { + location = v->uniform_location[idx]; + } + } + + _set_uniform_value(location, value); + } + + // bind textures + int tc = material->textures.size(); + Pair<StringName, RID> *textures = material->textures.ptrw(); + + ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = material->shader->texture_hints.ptrw(); + + for (int i = 0; i < tc; i++) { + + Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value; + value.first = ShaderLanguage::TYPE_INT; + value.second.resize(1); + value.second.write[0].sint = p_num_predef_textures + i; + + // GLint location = get_uniform_location(textures[i].first); + + // if (location < 0) { + // location = material->shader->uniform_locations[textures[i].first]; + // } + GLint location = -1; + if (v->custom_uniform_locations.has(textures[i].first)) { + location = v->custom_uniform_locations[textures[i].first]; + } else { + location = get_uniform_location(textures[i].first); + } + + _set_uniform_value(location, value); + } +} + void ShaderGLES2::set_base_material_tex_index(int p_idx) { } |