From 707c8c1e95d8db2d84909e7957b4dc9138e05599 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sun, 25 Oct 2020 20:01:03 +0300 Subject: Shaders for Android (GLES 2) (#10506) Shader support for OpenGL ES 2 devices (Android) Co-authored-by: sfan5 --- src/client/shader.cpp | 182 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/client/shader.cpp b/src/client/shader.cpp index e2eeb4ab0..f2aa00246 100644 --- a/src/client/shader.cpp +++ b/src/client/shader.cpp @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "client/tile.h" +#include "config.h" #if ENABLE_GLES #ifdef _IRR_COMPILE_WITH_OGLES1_ @@ -230,11 +231,24 @@ class MainShaderConstantSetter : public IShaderConstantSetter { CachedVertexShaderSetting m_world_view_proj; CachedVertexShaderSetting m_world; +#if ENABLE_GLES + // Modelview matrix + CachedVertexShaderSetting m_world_view; + // Texture matrix + CachedVertexShaderSetting m_texture; + // Normal matrix + CachedVertexShaderSetting m_normal; +#endif public: MainShaderConstantSetter() : - m_world_view_proj("mWorldViewProj"), - m_world("mWorld") + m_world_view_proj("mWorldViewProj") + , m_world("mWorld") +#if ENABLE_GLES + , m_world_view("mWorldView") + , m_texture("mTexture") + , m_normal("mNormal") +#endif {} ~MainShaderConstantSetter() = default; @@ -244,23 +258,42 @@ public: video::IVideoDriver *driver = services->getVideoDriver(); sanity_check(driver); + // Set world matrix + core::matrix4 world = driver->getTransform(video::ETS_WORLD); + if (is_highlevel) + m_world.set(*reinterpret_cast(world.pointer()), services); + else + services->setVertexShaderConstant(world.pointer(), 4, 4); + // Set clip matrix + core::matrix4 worldView; + worldView = driver->getTransform(video::ETS_VIEW); + worldView *= world; core::matrix4 worldViewProj; worldViewProj = driver->getTransform(video::ETS_PROJECTION); - worldViewProj *= driver->getTransform(video::ETS_VIEW); - worldViewProj *= driver->getTransform(video::ETS_WORLD); + worldViewProj *= worldView; if (is_highlevel) m_world_view_proj.set(*reinterpret_cast(worldViewProj.pointer()), services); else services->setVertexShaderConstant(worldViewProj.pointer(), 0, 4); - // Set world matrix - core::matrix4 world = driver->getTransform(video::ETS_WORLD); - if (is_highlevel) - m_world.set(*reinterpret_cast(world.pointer()), services); - else - services->setVertexShaderConstant(world.pointer(), 4, 4); - +#if ENABLE_GLES + if (is_highlevel) { + core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0); + m_world_view.set(*reinterpret_cast(worldView.pointer()), services); + m_texture.set(*reinterpret_cast(texture.pointer()), services); + + core::matrix4 normal; + worldView.getTransposed(normal); + sanity_check(normal.makeInverse()); + float m[9] = { + normal[0], normal[1], normal[2], + normal[4], normal[5], normal[6], + normal[8], normal[9], normal[10], + }; + m_normal.set(m, services); + } +#endif } }; @@ -620,15 +653,62 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp return shaderinfo; // Create shaders header - std::string shaders_header = "#version 120\n"; - + bool use_gles = false; +#if ENABLE_GLES + use_gles = driver->getDriverType() == video::EDT_OGLES2; +#endif + std::string shaders_header, vertex_header, pixel_header; // geometry shaders aren’t supported in GLES<3 + if (use_gles) { + shaders_header = + "#version 100\n" + ; + vertex_header = R"( + uniform highp mat4 mWorldView; + uniform highp mat4 mWorldViewProj; + uniform mediump mat4 mTexture; + uniform mediump mat3 mNormal; + + attribute highp vec4 inVertexPosition; + attribute lowp vec4 inVertexColor; + attribute mediump vec4 inTexCoord0; + attribute mediump vec3 inVertexNormal; + attribute mediump vec4 inVertexTangent; + attribute mediump vec4 inVertexBinormal; + )"; + pixel_header = R"( + precision mediump float; + )"; + } else { + shaders_header = R"( + #version 120 + #define lowp + #define mediump + #define highp + )"; + vertex_header = R"( + #define mWorldView gl_ModelViewMatrix + #define mWorldViewProj gl_ModelViewProjectionMatrix + #define mTexture (gl_TextureMatrix[0]) + #define mNormal gl_NormalMatrix + + #define inVertexPosition gl_Vertex + #define inVertexColor gl_Color + #define inTexCoord0 gl_MultiTexCoord0 + #define inVertexNormal gl_Normal + #define inVertexTangent gl_MultiTexCoord1 + #define inVertexBinormal gl_MultiTexCoord2 + )"; + } + + bool use_discard = use_gles; #ifdef __unix__ // For renderers that should use discard instead of GL_ALPHA_TEST const char* gl_renderer = (const char*)glGetString(GL_RENDERER); - if (strstr(gl_renderer, "GC7000")) { - shaders_header += "#define USE_DISCARD\n"; - } + if (strstr(gl_renderer, "GC7000")) + use_discard = true; #endif + if (use_discard && shaderinfo.base_material != video::EMT_SOLID) + shaders_header += "#define USE_DISCARD\n"; static const char* drawTypes[] = { "NDT_NORMAL", @@ -654,7 +734,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += drawTypes[i]; shaders_header += " "; - shaders_header += itos(i); + shaders_header += std::to_string(i); shaders_header += "\n"; } @@ -677,27 +757,27 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define "; shaders_header += materialTypes[i]; shaders_header += " "; - shaders_header += itos(i); + shaders_header += std::to_string(i); shaders_header += "\n"; } shaders_header += "#define MATERIAL_TYPE "; - shaders_header += itos(material_type); + shaders_header += std::to_string(material_type); shaders_header += "\n"; shaders_header += "#define DRAW_TYPE "; - shaders_header += itos(drawtype); + shaders_header += std::to_string(drawtype); shaders_header += "\n"; if (g_settings->getBool("enable_waving_water")){ shaders_header += "#define ENABLE_WAVING_WATER 1\n"; shaders_header += "#define WATER_WAVE_HEIGHT "; - shaders_header += ftos(g_settings->getFloat("water_wave_height")); + shaders_header += std::to_string(g_settings->getFloat("water_wave_height")); shaders_header += "\n"; shaders_header += "#define WATER_WAVE_LENGTH "; - shaders_header += ftos(g_settings->getFloat("water_wave_length")); + shaders_header += std::to_string(g_settings->getFloat("water_wave_length")); shaders_header += "\n"; shaders_header += "#define WATER_WAVE_SPEED "; - shaders_header += ftos(g_settings->getFloat("water_wave_speed")); + shaders_header += std::to_string(g_settings->getFloat("water_wave_speed")); shaders_header += "\n"; } else{ shaders_header += "#define ENABLE_WAVING_WATER 0\n"; @@ -719,7 +799,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp shaders_header += "#define ENABLE_TONE_MAPPING\n"; shaders_header += "#define FOG_START "; - shaders_header += ftos(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); + shaders_header += std::to_string(rangelim(g_settings->getFloat("fog_start"), 0.0f, 0.99f)); shaders_header += "\n"; // Call addHighLevelShaderMaterial() or addShaderMaterial() @@ -727,11 +807,11 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp const c8* pixel_program_ptr = 0; const c8* geometry_program_ptr = 0; if (!vertex_program.empty()) { - vertex_program = shaders_header + vertex_program; + vertex_program = shaders_header + vertex_header + vertex_program; vertex_program_ptr = vertex_program.c_str(); } if (!pixel_program.empty()) { - pixel_program = shaders_header + pixel_program; + pixel_program = shaders_header + pixel_header + pixel_program; pixel_program_ptr = pixel_program.c_str(); } if (!geometry_program.empty()) { @@ -813,27 +893,37 @@ void load_shaders(const std::string &name, SourceShaderCache *sourcecache, geometry_program = ""; is_highlevel = false; - if(enable_shaders){ - // Look for high level shaders - if(drivertype == video::EDT_DIRECT3D9){ - // Direct3D 9: HLSL - // (All shaders in one file) - vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl"); - pixel_program = vertex_program; - geometry_program = vertex_program; - } - else if(drivertype == video::EDT_OPENGL){ - // OpenGL: GLSL - vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl"); - pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl"); - geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl"); - } - if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){ - is_highlevel = true; - return; - } - } + if (!enable_shaders) + return; + + // Look for high level shaders + switch (drivertype) { + case video::EDT_DIRECT3D9: + // Direct3D 9: HLSL + // (All shaders in one file) + vertex_program = sourcecache->getOrLoad(name, "d3d9.hlsl"); + pixel_program = vertex_program; + geometry_program = vertex_program; + break; + + case video::EDT_OPENGL: +#if ENABLE_GLES + case video::EDT_OGLES2: +#endif + // OpenGL: GLSL + vertex_program = sourcecache->getOrLoad(name, "opengl_vertex.glsl"); + pixel_program = sourcecache->getOrLoad(name, "opengl_fragment.glsl"); + geometry_program = sourcecache->getOrLoad(name, "opengl_geometry.glsl"); + break; + default: + // e.g. OpenGL ES 1 (with no shader support) + break; + } + if (!vertex_program.empty() || !pixel_program.empty() || !geometry_program.empty()){ + is_highlevel = true; + return; + } } void dumpShaderProgram(std::ostream &output_stream, -- cgit v1.2.3