mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Shaders for Android (GLES 2) (#10506)
Shader support for OpenGL ES 2 devices (Android) Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
parent
33b2c5f5b1
commit
707c8c1e95
17 changed files with 233 additions and 120 deletions
|
@ -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,16 +258,6 @@ public:
|
|||
video::IVideoDriver *driver = services->getVideoDriver();
|
||||
sanity_check(driver);
|
||||
|
||||
// Set clip matrix
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
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)
|
||||
|
@ -261,6 +265,35 @@ public:
|
|||
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 *= worldView;
|
||||
if (is_highlevel)
|
||||
m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
|
||||
else
|
||||
services->setVertexShaderConstant(worldViewProj.pointer(), 0, 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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue