summaryrefslogtreecommitdiff
path: root/src/client/shader.cpp
diff options
context:
space:
mode:
authorVitaliy <numzer0@yandex.ru>2020-10-25 20:01:03 +0300
committerGitHub <noreply@github.com>2020-10-25 18:01:03 +0100
commit707c8c1e95d8db2d84909e7957b4dc9138e05599 (patch)
tree84604fc1868c7b8ca8e977d5dd0485498500cdfe /src/client/shader.cpp
parent33b2c5f5b1c565171296f26395d803b08f4575e9 (diff)
downloadminetest-707c8c1e95d8db2d84909e7957b4dc9138e05599.tar.gz
minetest-707c8c1e95d8db2d84909e7957b4dc9138e05599.tar.bz2
minetest-707c8c1e95d8db2d84909e7957b4dc9138e05599.zip
Shaders for Android (GLES 2) (#10506)
Shader support for OpenGL ES 2 devices (Android) Co-authored-by: sfan5 <sfan5@live.de>
Diffstat (limited to 'src/client/shader.cpp')
-rw-r--r--src/client/shader.cpp182
1 files changed, 136 insertions, 46 deletions
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<float, 16> m_world_view_proj;
CachedVertexShaderSetting<float, 16> m_world;
+#if ENABLE_GLES
+ // Modelview matrix
+ CachedVertexShaderSetting<float, 16> m_world_view;
+ // Texture matrix
+ CachedVertexShaderSetting<float, 16> m_texture;
+ // Normal matrix
+ CachedVertexShaderSetting<float, 9> 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<float(*)[16]>(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<float(*)[16]>(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<float(*)[16]>(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<float(*)[16]>(worldView.pointer()), services);
+ m_texture.set(*reinterpret_cast<float(*)[16]>(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,