Shaders support for GLES2. Drop bump mapping, parallax occlusion and normal maps support (#186)

This commit is contained in:
Vitaliy 2020-11-07 21:30:18 +03:00 committed by GitHub
parent c527b25094
commit 24e388f721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 216 additions and 496 deletions

View File

@ -11,15 +11,14 @@ DEST=$(mktemp -d)
echo
echo "=> Creating Assets:"
for dir in builtin textures; do
cp -r ../../$dir $DEST/$dir
for dir in builtin textures client; do
cp -r ../../$dir $DEST/
done
mkdir -p $DEST/fonts
cp ../../fonts/Retron2000.ttf $DEST/fonts/ # no PNG fonts because freetype
#mkdir -p $DEST/media
#cp -r native/deps/Android/Irrlicht/shaders $DEST/media/shaders
cp -r native/deps/Android/Irrlicht/shaders $DEST/client/shaders/Irrlicht
echo
echo "* Converting locale files:"
@ -36,6 +35,10 @@ for lang in *; do
done
popd
find $DEST -type d -name '.git' -print0 | xargs -0 -- rm -r
find $DEST -type f -name '.git*' -delete
find $DEST -type f -name '.DS_Store' -delete
# remove broken languages
for broken_lang in ja ko he; do
find $DEST -type d -name $broken_lang -print0 | xargs -0 -- rm -r

View File

@ -54,6 +54,7 @@ LOCAL_CFLAGS += \
-DUSE_LEVELDB=1 \
-DUSE_LUAJIT=1 \
-DUSE_GETTEXT=1 \
-DENABLE_GLES=1 \
$(GPROF_DEF)
ifdef NDEBUG

View File

@ -8,12 +8,11 @@ fi
FOLDER=$(pwd)
DEST=$(mktemp -d)
for dir in builtin textures; do
cp -r ../../$dir $DEST/$dir
for dir in builtin textures client; do
cp -r ../../$dir $DEST/
done
#mkdir -p $DEST/media
#cp -r deps/irrlicht/shaders $DEST/media/shaders
cp -r deps/irrlicht/shaders $DEST/client/shaders/Irrlicht
mkdir -p $DEST/fonts
cp ../../fonts/Retron2000.ttf $DEST/fonts/ # no PNG fonts because freetype

View File

@ -154,15 +154,18 @@ local function formspec()
"box[8,0;3.75,4.5;#999999]"
local video_driver = core.settings:get("video_driver")
local shaders_supported = video_driver == "opengl"
local shaders_enabled = false
if shaders_supported then
shaders_enabled = core.settings:get_bool("enable_shaders")
local shaders_enabled = core.settings:get_bool("enable_shaders")
if video_driver == "opengl" then
tab_string = tab_string ..
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders") .. ";"
.. tostring(shaders_enabled) .. "]"
elseif video_driver == "ogles2" then
tab_string = tab_string ..
"checkbox[8.25,0;cb_shaders;" .. fgettext("Shaders (experimental)") .. ";"
.. tostring(shaders_enabled) .. "]"
else
core.settings:set_bool("enable_shaders", false)
shaders_enabled = false
tab_string = tab_string ..
"label[8.38,0.2;" .. core.colorize("#888888",
fgettext("Shaders (unavailable)")) .. "]"

View File

@ -511,7 +511,7 @@ display_gamma (Gamma) float 2.2 1.0 3.0
texture_path (Texture path) path
# The rendering back-end for Irrlicht.
video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl
video_driver (Video driver) enum opengl null,software,burningsvideo,direct3d8,direct3d9,opengl,ogles1,ogles2
# Height on which clouds are appearing.
cloud_height (Cloud height) int 120

View File

@ -1,4 +1,6 @@
varying mediump vec4 varColor;
void main(void)
{
gl_FragColor = gl_Color;
gl_FragColor = varColor;
}

View File

@ -1,9 +1,7 @@
uniform mat4 mWorldViewProj;
varying mediump vec4 varColor;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
gl_Position = mWorldViewProj * inVertexPosition;
varColor = inVertexColor;
}

View File

@ -2,9 +2,12 @@ uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform vec3 yawVec;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
void main (void)
{
vec2 uv = gl_TexCoord[0].st;
vec2 uv = varTexCoord.st;
//texture sampling rate
const float step = 1.0 / 256.0;
@ -27,6 +30,6 @@ void main (void)
vec3 color = (1.1 * diffuse + 0.05 * height + 0.5 * specular) * base.rgb;
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
col *= varColor;
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@ -1,9 +1,9 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
varTexCoord = inTexCoord0.xy;
gl_Position = mWorldViewProj * inVertexPosition;
varColor = inVertexColor;
}

View File

@ -6,21 +6,14 @@ uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying float area_enable_parallax;
varying vec3 eyeVec;
varying vec3 tsEyeVec;
varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
varying mediump vec3 eyeVec;
const float e = 2.718281828459;
const float BS = 10.0;
const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart);
const float fogShadingParameter = 1.0 / (1.0 - fogStart);
#ifdef ENABLE_TONE_MAPPING
@ -54,148 +47,19 @@ vec4 applyToneMapping(vec4 color)
}
#endif
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture, uv).rgb);
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
float find_intersection(vec2 dp, vec2 ds)
{
float depth = 1.0;
float best_depth = 0.0;
float size = 0.0625;
for (int i = 0; i < 15; i++) {
depth -= size;
float h = texture2D(normalTexture, dp + ds * depth).a;
if (depth <= h) {
best_depth = depth;
break;
}
}
depth = best_depth;
for (int i = 0; i < 4; i++) {
size *= 0.5;
float h = texture2D(normalTexture,dp + ds * depth).a;
if (depth <= h) {
best_depth = depth;
depth += size;
} else {
depth -= size;
}
}
return best_depth;
}
float find_intersectionRGB(vec2 dp, vec2 ds)
{
const float depth_step = 1.0 / 24.0;
float depth = 1.0;
for (int i = 0 ; i < 24 ; i++) {
float h = get_rgb_height(dp + ds * depth);
if (h >= depth)
break;
depth -= depth_step;
}
return depth;
}
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
vec2 uv = varTexCoord.st;
bool use_normalmap = false;
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y);
const float scale = PARALLAX_OCCLUSION_SCALE / PARALLAX_OCCLUSION_ITERATIONS;
const float bias = PARALLAX_OCCLUSION_BIAS / PARALLAX_OCCLUSION_ITERATIONS;
#if PARALLAX_OCCLUSION_MODE == 0
// Parallax occlusion with slope information
if (normalTexturePresent && area_enable_parallax > 0.0) {
for (int i = 0; i < PARALLAX_OCCLUSION_ITERATIONS; i++) {
vec4 normal = texture2D(normalTexture, uv.xy);
float h = normal.a * scale - bias;
uv += h * normal.z * eyeRay;
}
#endif
#if PARALLAX_OCCLUSION_MODE == 1
// Relief mapping
if (normalTexturePresent && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersection(uv, ds);
uv += dist * ds;
#endif
} else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
float dist = find_intersectionRGB(uv, ds);
uv += dist * ds;
}
#endif
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
#endif
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
}
#else
color = base.rgb;
#ifdef USE_DISCARD
if (base.a == 0.0)
discard;
#endif
vec4 col = vec4(color.rgb * gl_Color.rgb, 1.0);
vec4 col = vec4(base.rgb * varColor.rgb, 1.0);
#ifdef ENABLE_TONE_MAPPING
col = applyToneMapping(col);

View File

@ -1,19 +1,11 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
// Color of the light emitted by the sun.
uniform highp mat4 mWorld;
uniform vec3 dayLight;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
varying float area_enable_parallax;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
varying mediump vec3 eyeVec;
// Color of the light emitted by the light sources.
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
@ -41,24 +33,15 @@ float smoothTriangleWave(float x)
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
varTexCoord = inTexCoord0.xy;
//TODO: make offset depending on view angle and parallax uv displacement
//thats for textures that doesnt align vertically, like dirt with grass
//gl_TexCoord[0].y += 0.008;
//Allow parallax/relief mapping only for certain kind of nodes
//Variable is also used to control area of the effect
#if (DRAW_TYPE == NDT_NORMAL || DRAW_TYPE == NDT_LIQUID || DRAW_TYPE == NDT_FLOWINGLIQUID)
area_enable_parallax = 1.0;
#else
area_enable_parallax = 0.0;
#endif
//varTexCoord.y += 0.008;
float disp_x;
float disp_z;
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES) || (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS)
vec4 pos2 = mWorld * gl_Vertex;
vec4 pos2 = mWorld * inVertexPosition;
float tOffset = (pos2.x + pos2.y) * 0.001 + pos2.z * 0.002;
disp_x = (smoothTriangleWave(animationTimer * 23.0 + tOffset) +
smoothTriangleWave(animationTimer * 11.0 + tOffset)) * 0.4;
@ -69,58 +52,29 @@ float disp_z;
#if (MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_OPAQUE) && ENABLE_WAVING_WATER
vec4 pos = gl_Vertex;
vec4 pos = inVertexPosition;
pos.y -= 2.0;
float posYbuf = (pos.z / WATER_WAVE_LENGTH + animationTimer * WATER_WAVE_SPEED * WATER_WAVE_LENGTH);
pos.y -= sin(posYbuf) * WATER_WAVE_HEIGHT + sin(posYbuf / 7.0) * WATER_WAVE_HEIGHT;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES && ENABLE_WAVING_LEAVES
vec4 pos = gl_Vertex;
vec4 pos = inVertexPosition;
pos.x += disp_x;
pos.y += disp_z * 0.1;
pos.z += disp_z;
gl_Position = mWorldViewProj * pos;
#elif MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS && ENABLE_WAVING_PLANTS
vec4 pos = gl_Vertex;
if (gl_TexCoord[0].y < 0.05) {
vec4 pos = inVertexPosition;
if (varTexCoord.y < 0.05) {
pos.x += disp_x;
pos.z += disp_z;
}
gl_Position = mWorldViewProj * pos;
#else
gl_Position = mWorldViewProj * gl_Vertex;
gl_Position = mWorldViewProj * inVertexPosition;
#endif
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
// Don't generate heightmaps when too far from the eye
float dist = distance (vec3(0.0, 0.0, 0.0), vPosition);
if (dist > 150.0) {
area_enable_parallax = 0.0;
}
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
vec3 normal, tangent, binormal;
normal = normalize(gl_NormalMatrix * gl_Normal);
tangent = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
binormal = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz);
vec3 v;
lightVec = sunPosition - worldPosition;
v.x = dot(lightVec, tangent);
v.y = dot(lightVec, binormal);
v.z = dot(lightVec, normal);
tsLightVec = normalize (v);
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
v.x = dot(eyeVec, tangent);
v.y = dot(eyeVec, binormal);
v.z = dot(eyeVec, normal);
tsEyeVec = normalize (v);
eyeVec = -(mWorldView * inVertexPosition).xyz;
// Calculate color.
// Red, green and blue components are pre-multiplied with
@ -129,16 +83,16 @@ float disp_z;
// The pre-baked colors are halved to prevent overflow.
vec4 color;
// The alpha gives the ratio of sunlight in the incoming light.
float nightRatio = 1 - gl_Color.a;
color.rgb = gl_Color.rgb * (gl_Color.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2;
color.a = 1;
float nightRatio = 1.0 - inVertexColor.a;
color.rgb = inVertexColor.rgb * (inVertexColor.a * dayLight.rgb +
nightRatio * artificialLight.rgb) * 2.0;
color.a = 1.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
float brightness = (color.r + color.g + color.b) / 3;
float brightness = (color.r + color.g + color.b) / 3.0;
color.b += max(0.0, 0.021 - abs(0.2 * brightness - 0.021) +
0.07 * brightness);
gl_FrontColor = gl_BackColor = clamp(color, 0.0, 1.0);
varColor = clamp(color, 0.0, 1.0);
}

View File

@ -1,9 +1,12 @@
uniform sampler2D baseTexture;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
void main(void)
{
vec2 uv = gl_TexCoord[0].st;
vec2 uv = varTexCoord.st;
vec4 color = texture2D(baseTexture, uv);
color.rgb *= gl_Color.rgb;
color.rgb *= varColor.rgb;
gl_FragColor = color;
}

View File

@ -1,9 +1,9 @@
uniform mat4 mWorldViewProj;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
varTexCoord = inTexCoord0.xy;
gl_Position = mWorldViewProj * inVertexPosition;
varColor = inVertexColor;
}

View File

@ -6,11 +6,9 @@ uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
varying mediump vec3 eyeVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
@ -20,96 +18,19 @@ bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
const float fogStart = FOG_START;
const float fogShadingParameter = 1 / ( 1 - fogStart);
void get_texture_flags()
{
vec4 flags = texture2D(textureFlags, vec2(0.0, 0.0));
if (flags.r > 0.5) {
normalTexturePresent = true;
}
if (flags.g > 0.5) {
texTileableHorizontal = true;
}
if (flags.b > 0.5) {
texTileableVertical = true;
}
if (texTileableHorizontal && texTileableVertical) {
texSeamless = true;
}
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height(vec2 uv)
{
if (texSeamless) {
return intensity(texture2D(baseTexture, uv).rgb);
} else {
return intensity(texture2D(baseTexture, clamp(uv, 0.0, 0.999)).rgb);
}
}
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 - 1.0);
return bump;
}
const float fogShadingParameter = 1.0 / (1.0 - fogStart);
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
get_texture_flags();
#if USE_NORMALMAPS == 1
if (normalTexturePresent) {
bump = get_normal_map(uv);
use_normalmap = true;
}
#endif
#if GENERATE_NORMALMAPS == 1
if (normalTexturePresent == false) {
float tl = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y + SAMPLE_STEP));
float t = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y - SAMPLE_STEP));
float tr = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y + SAMPLE_STEP));
float r = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y));
float br = get_rgb_height(vec2(uv.x + SAMPLE_STEP, uv.y - SAMPLE_STEP));
float b = get_rgb_height(vec2(uv.x, uv.y - SAMPLE_STEP));
float bl = get_rgb_height(vec2(uv.x -SAMPLE_STEP, uv.y - SAMPLE_STEP));
float l = get_rgb_height(vec2(uv.x - SAMPLE_STEP, uv.y));
float dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
float dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
bump = vec4(normalize(vec3 (dX, dY, NORMALMAPS_STRENGTH)), 1.0);
use_normalmap = true;
}
#endif
vec2 uv = varTexCoord.st;
vec4 base = texture2D(baseTexture, uv).rgba;
#ifdef ENABLE_BUMPMAPPING
if (use_normalmap) {
vec3 L = normalize(lightVec);
vec3 E = normalize(eyeVec);
float specular = pow(clamp(dot(reflect(L, bump.xyz), E), 0.0, 1.0), 1.0);
float diffuse = dot(-E,bump.xyz);
color = (diffuse + 0.1 * specular) * base.rgb;
} else {
color = base.rgb;
}
#else
color = base.rgb;
#ifdef USE_DISCARD
if (base.a == 0.0)
discard;
#endif
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
vec4 col = base;
col *= varColor;
// Due to a bug in some (older ?) graphics stacks (possibly in the glsl compiler ?),
// the fog will only be rendered correctly if the last operation before the
// clamp() is an addition. Else, the clamp() seems to be ignored.

View File

@ -1,32 +1,16 @@
uniform mat4 mWorldViewProj;
uniform mat4 mWorld;
uniform highp mat4 mWorld;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
varying mediump vec4 varColor;
varying mediump vec2 varTexCoord;
varying mediump vec3 eyeVec;
const float e = 2.718281828459;
const float BS = 10.0;
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);
lightVec = sunPosition - worldPosition;
eyeVec = -(gl_ModelViewMatrix * gl_Vertex).xyz;
gl_FrontColor = gl_BackColor = gl_Color;
varTexCoord = inTexCoord0.xy;
gl_Position = mWorldViewProj * inVertexPosition;
eyeVec = -(mWorldView * inVertexPosition).xyz;
varColor = inVertexColor;
}

View File

@ -591,7 +591,7 @@ bool ClientLauncher::create_engine_device()
params.PrivateData = porting::app_global;
#endif
params.OGLES2ShaderPath = std::string(porting::path_share + DIR_DELIM +
"media" + DIR_DELIM + "shaders" + DIR_DELIM).c_str();
"client" + DIR_DELIM + "shaders" + DIR_DELIM + "Irrlicht" + DIR_DELIM).c_str();
#endif
device = createDeviceEx(params);

View File

@ -804,11 +804,12 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
else if (waving == 2)
special_material = TILE_MATERIAL_WAVING_LEAVES;
}
u32 special_shader = shdsrc->getShader("nodes_shader", special_material, drawtype);
// Special tiles (fill in f->special_tiles[])
for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
fillTileAttribs(tsrc, &special_tiles[j].layers[0], &tdef_spec[j],
tile_shader, tsettings.use_normal_texture,
special_shader, tsettings.use_normal_texture,
tdef_spec[j].backface_culling, special_material);
}

View File

@ -36,6 +36,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"
/*
A cache from shader name to shader path
@ -208,13 +209,19 @@ public:
class MainShaderConstantSetter : public IShaderConstantSetter
{
CachedVertexShaderSetting<float, 16> m_world_view_proj;
CachedVertexShaderSetting<float, 16> m_world;
#if ENABLE_GLES
CachedVertexShaderSetting<float, 16> m_world_view;
CachedVertexShaderSetting<float, 16> m_world_view_proj;
#endif
public:
MainShaderConstantSetter() :
m_world_view_proj("mWorldViewProj"),
m_world("mWorld")
MainShaderConstantSetter()
: m_world("mWorld")
#if ENABLE_GLES
, m_world_view_proj("mWorldViewProj")
, m_world_view("mWorldView")
#endif
{}
~MainShaderConstantSetter() {}
@ -224,23 +231,16 @@ 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)
m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
else
services->setVertexShaderConstant(world.pointer(), 4, 4);
m_world.set(*reinterpret_cast<float(*)[16]>(world.pointer()), services);
#if ENABLE_GLES
core::matrix4 worldView = driver->getTransform(video::ETS_VIEW) * world;
core::matrix4 worldViewProj = driver->getTransform(video::ETS_PROJECTION) * worldView;
m_world_view_proj.set(*reinterpret_cast<float(*)[16]>(worldViewProj.pointer()), services);
m_world_view.set(*reinterpret_cast<float(*)[16]>(worldView.pointer()), services);
#endif
}
};
@ -341,7 +341,7 @@ IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
Generate shader given the shader name.
*/
ShaderInfo generate_shader(const std::string &name,
u8 material_type, u8 drawtype,
int material_type, int drawtype,
IrrlichtDevice *device, std::vector<ShaderCallback *> &callbacks,
const std::vector<IShaderConstantSetterFactory*> &setter_factories,
SourceShaderCache *sourcecache);
@ -349,10 +349,9 @@ ShaderInfo generate_shader(const std::string &name,
/*
Load shader programs
*/
void load_shaders(std::string name, SourceShaderCache *sourcecache,
video::E_DRIVER_TYPE drivertype, bool enable_shaders,
std::string &vertex_program, std::string &pixel_program,
std::string &geometry_program, bool &is_highlevel);
bool load_shaders(std::string name, SourceShaderCache *sourcecache,
video::E_DRIVER_TYPE drivertype,
std::string &vertex_program, std::string &pixel_program);
ShaderSource::ShaderSource(IrrlichtDevice *device):
m_device(device)
@ -525,7 +524,7 @@ void ShaderSource::rebuildShaders()
}
ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtype,
ShaderInfo generate_shader(const std::string &name, int material_type, int drawtype,
IrrlichtDevice *device, std::vector<ShaderCallback *> &callbacks,
const std::vector<IShaderConstantSetterFactory*> &setter_factories,
SourceShaderCache *sourcecache)
@ -571,11 +570,9 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
// Then load shaders
std::string vertex_program;
std::string pixel_program;
std::string geometry_program;
bool is_highlevel;
load_shaders(name, sourcecache, driver->getDriverType(),
enable_shaders, vertex_program, pixel_program,
geometry_program, is_highlevel);
if (!load_shaders(name, sourcecache, driver->getDriverType(), vertex_program, pixel_program))
return shaderinfo;
// Check hardware/driver support
if(vertex_program != "" &&
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
@ -593,20 +590,46 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
<<std::endl;
pixel_program = "";
}
if(geometry_program != "" &&
!driver->queryFeature(video::EVDF_GEOMETRY_SHADER)){
infostream<<"generate_shader(): geometry shaders disabled "
"because of missing driver/hardware support."
<<std::endl;
geometry_program = "";
}
// If no shaders are used, don't make a separate material type
if(vertex_program == "" && pixel_program == "" && geometry_program == "")
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 arent supported in GLES<3
if (use_gles) {
shaders_header =
"#version 100\n"
;
vertex_header = R"(
uniform highp mat4 mWorldView;
uniform highp mat4 mWorldViewProj;
attribute highp vec4 inVertexPosition;
attribute lowp vec4 inVertexColor;
attribute mediump vec4 inTexCoord0;
)";
pixel_header = R"(
precision mediump float;
)";
if (shaderinfo.base_material != video::EMT_SOLID)
pixel_header += "#define USE_DISCARD\n";
} else {
shaders_header = R"(
#version 120
#define lowp
#define mediump
#define highp
)";
vertex_header = R"(
#define mWorldView gl_ModelViewMatrix
#define mWorldViewProj gl_ModelViewProjectionMatrix
#define inVertexPosition gl_Vertex
#define inVertexColor gl_Color
#define inTexCoord0 gl_MultiTexCoord0
)";
}
static const char* drawTypes[] = {
"NDT_NORMAL",
@ -632,7 +655,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";
}
@ -650,15 +673,15 @@ 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("generate_normalmaps")) {
@ -667,7 +690,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
shaders_header += "#define GENERATE_NORMALMAPS 0\n";
}
shaders_header += "#define NORMALMAPS_STRENGTH ";
shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
shaders_header += std::to_string(g_settings->getFloat("normalmaps_strength"));
shaders_header += "\n";
float sample_step;
int smooth = (int)g_settings->getFloat("normalmaps_smooth");
@ -686,7 +709,7 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
break;
}
shaders_header += "#define SAMPLE_STEP ";
shaders_header += ftos(sample_step);
shaders_header += std::to_string(sample_step);
shaders_header += "\n";
if (g_settings->getBool("enable_bumpmapping"))
@ -699,16 +722,16 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
int iterations = g_settings->getFloat("parallax_occlusion_iterations");
shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
shaders_header += itos(mode);
shaders_header += std::to_string(mode);
shaders_header += "\n";
shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
shaders_header += ftos(scale);
shaders_header += std::to_string(scale);
shaders_header += "\n";
shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
shaders_header += ftos(bias);
shaders_header += std::to_string(bias);
shaders_header += "\n";
shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
shaders_header += itos(iterations);
shaders_header += std::to_string(iterations);
shaders_header += "\n";
}
@ -721,13 +744,13 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
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";
@ -749,7 +772,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()
@ -757,70 +780,43 @@ 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()) {
geometry_program = shaders_header + geometry_program;
geometry_program_ptr = geometry_program.c_str();
}
ShaderCallback *cb = new ShaderCallback(setter_factories);
s32 shadermat = -1;
if(is_highlevel){
infostream<<"Compiling high level shaders for "<<name<<std::endl;
shadermat = gpu->addHighLevelShaderMaterial(
vertex_program_ptr, // Vertex shader program
"vertexMain", // Vertex shader entry point
video::EVST_VS_1_1, // Vertex shader version
pixel_program_ptr, // Pixel shader program
"pixelMain", // Pixel shader entry point
video::EPST_PS_1_2, // Pixel shader version
geometry_program_ptr, // Geometry shader program
"geometryMain", // Geometry shader entry point
video::EGST_GS_4_0, // Geometry shader version
scene::EPT_TRIANGLES, // Geometry shader input
scene::EPT_TRIANGLE_STRIP, // Geometry shader output
0, // Support maximum number of vertices
cb, // Set-constant callback
shaderinfo.base_material, // Base material
1 // Userdata passed to callback
);
if(shadermat == -1){
errorstream<<"generate_shader(): "
"failed to generate \""<<name<<"\", "
"addHighLevelShaderMaterial failed."
<<std::endl;
dumpShaderProgram(warningstream, "Vertex", vertex_program);
dumpShaderProgram(warningstream, "Pixel", pixel_program);
dumpShaderProgram(warningstream, "Geometry", geometry_program);
delete cb;
return shaderinfo;
}
}
else{
infostream<<"Compiling assembly shaders for "<<name<<std::endl;
shadermat = gpu->addShaderMaterial(
vertex_program_ptr, // Vertex shader program
pixel_program_ptr, // Pixel shader program
cb, // Set-constant callback
shaderinfo.base_material, // Base material
0 // Userdata passed to callback
);
if(shadermat == -1){
errorstream<<"generate_shader(): "
"failed to generate \""<<name<<"\", "
"addShaderMaterial failed."
<<std::endl;
dumpShaderProgram(warningstream, "Vertex", vertex_program);
dumpShaderProgram(warningstream,"Pixel", pixel_program);
delete cb;
return shaderinfo;
}
infostream<<"Compiling high level shaders for "<<name<<std::endl;
shadermat = gpu->addHighLevelShaderMaterial(
vertex_program_ptr, // Vertex shader program
"vertexMain", // Vertex shader entry point
video::EVST_VS_1_1, // Vertex shader version
pixel_program_ptr, // Pixel shader program
"pixelMain", // Pixel shader entry point
video::EPST_PS_1_2, // Pixel shader version
geometry_program_ptr, // Geometry shader program
"geometryMain", // Geometry shader entry point
video::EGST_GS_4_0, // Geometry shader version
scene::EPT_TRIANGLES, // Geometry shader input
scene::EPT_TRIANGLE_STRIP, // Geometry shader output
0, // Support maximum number of vertices
cb, // Set-constant callback
shaderinfo.base_material, // Base material
1 // Userdata passed to callback
);
if(shadermat == -1){
errorstream<<"generate_shader(): "
"failed to generate \""<<name<<"\", "
"addHighLevelShaderMaterial failed."
<<std::endl;
dumpShaderProgram(warningstream, "Vertex", vertex_program);
dumpShaderProgram(warningstream, "Pixel", pixel_program);
delete cb;
return shaderinfo;
}
callbacks.push_back(cb);
@ -833,37 +829,25 @@ ShaderInfo generate_shader(const std::string &name, u8 material_type, u8 drawtyp
return shaderinfo;
}
void load_shaders(std::string name, SourceShaderCache *sourcecache,
video::E_DRIVER_TYPE drivertype, bool enable_shaders,
std::string &vertex_program, std::string &pixel_program,
std::string &geometry_program, bool &is_highlevel)
bool load_shaders(std::string name, SourceShaderCache *sourcecache,
video::E_DRIVER_TYPE drivertype,
std::string &vertex_program, std::string &pixel_program)
{
vertex_program = "";
pixel_program = "";
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 != "" || pixel_program != "" || geometry_program != ""){
is_highlevel = true;
return;
}
switch (drivertype) {
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");
break;
default:
return false;
}
return !vertex_program.empty() && !pixel_program.empty();
}
void dumpShaderProgram(std::ostream &output_stream,