summaryrefslogtreecommitdiff
path: root/drivers/gles2/shader_gles2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles2/shader_gles2.cpp')
-rw-r--r--drivers/gles2/shader_gles2.cpp389
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) {
}