Fix relief mapping issues

This commit is contained in:
RealBadAngel 2015-07-16 15:36:48 +02:00
parent b30e8d8ec6
commit 655fc6010f
15 changed files with 206 additions and 70 deletions

View File

@ -1,6 +1,6 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
@ -16,18 +16,72 @@ varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
float intensity (vec3 color)
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;
}
}
vec2 validate_displacement(vec2 uv, vec2 ds, float dist)
{
if (texSeamless) {
uv += dist * ds;
} else if (texTileableVertical == false) {
vec2 uv2 = uv + dist * ds;
// limit vertical texure displacement
if ((uv.y + uv2.y) < 0.0) {
uv.y = 0.0;
} else if ((uv.y + uv2.y) > 1.999) {
uv.y = 0.999;
} else {
uv.y = uv2.y;
}
uv.x = uv2.x;
} else {
vec2 uv2 = uv + dist * ds;
// limit horizontal texure displacement
if ((uv.x + uv2.x) < 0.0) {
uv.x = 0.0;
} else if ((uv.x + uv2.x) > 1.999) {
uv.x = 0.999;
} else {
uv.x = uv2.x;
}
uv.y = uv2.y;
}
return uv;
}
float intensity(vec3 color)
{
return (color.r + color.g + color.b) / 3.0;
}
float get_rgb_height (vec2 uv)
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture,uv).rgb);
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)
@ -50,7 +104,8 @@ float find_intersection(vec2 dp, vec2 ds)
return depth;
}
float find_intersectionRGB(vec2 dp, vec2 ds) {
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++) {
@ -62,18 +117,13 @@ float find_intersectionRGB(vec2 dp, vec2 ds) {
return depth;
}
void main (void)
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#if USE_NORMALMAPS == 1
if (texture2D(useNormalmap,vec2(1.0, 1.0)).r > 0.0) {
normalTexturePresent = true;
}
#endif
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
vec2 eyeRay = vec2 (tsEyeVec.x, -tsEyeVec.y);
@ -89,17 +139,23 @@ void main (void)
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;
// offset the texture by maximum possible displacement,
// this will help align seamless and non seamless textures
uv -= ds;
float dist = find_intersection(uv, ds);
uv += dist * ds;
uv = validate_displacement(uv, ds, dist);
#endif
} else if (GENERATE_NORMALMAPS == 1 && area_enable_parallax > 0.0) {
vec2 ds = eyeRay * PARALLAX_OCCLUSION_SCALE;
uv -= ds;
float dist = find_intersectionRGB(uv, ds);
uv += dist * ds;
uv = validate_displacement(uv, ds, dist);
}
#endif
@ -110,7 +166,7 @@ void main (void)
}
#endif
if (GENERATE_NORMALMAPS == 1 && use_normalmap == false) {
if (GENERATE_NORMALMAPS == 1 && 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));

View File

@ -94,7 +94,7 @@ void main(void)
// Don't generate heightmaps when too far from the eye
float dist = distance (vec3(0.0, 0.0 ,0.0), vPosition);
if (dist > 120.0) {
if (dist > 300.0) {
area_enable_parallax = 0.0;
}

View File

@ -1,6 +1,6 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D useNormalmap;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
@ -15,37 +15,55 @@ varying vec3 lightVec;
varying vec3 tsLightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
float intensity (vec3 color){
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){
float get_rgb_height(vec2 uv)
{
return intensity(texture2D(baseTexture,uv).rgb);
}
vec4 get_normal_map(vec2 uv){
vec4 get_normal_map(vec2 uv)
{
vec4 bump = texture2D(normalTexture, uv).rgba;
bump.xyz = normalize(bump.xyz * 2.0 -1.0);
bump.y = -bump.y;
return bump;
}
void main (void)
void main(void)
{
vec3 color;
vec4 bump;
vec2 uv = gl_TexCoord[0].st;
bool use_normalmap = false;
#ifdef USE_NORMALMAPS
if (texture2D(useNormalmap,vec2(1.0,1.0)).r > 0.0) {
normalTexturePresent = true;
}
#endif
get_texture_flags();
#ifdef ENABLE_PARALLAX_OCCLUSION
if (normalTexturePresent) {

View File

@ -3058,8 +3058,13 @@ Definition tables
### Tile definition
* `"image.png"`
* `{name="image.png", animation={Tile Animation definition}}`
* `{name="image.png", backface_culling=bool}`
* backface culling only supported in special tiles
* `{name="image.png", backface_culling=bool, tileable_vertical=bool,
tileable_horizontal=bool}`
* backface culling only supported in special tiles.
* tileable flags are info for shaders, how they should treat texture
when displacement mapping is used
Directions are from the point of view of the tile texture,
not the node it's on
* deprecated, yet still supported field names:
* `image` (name)

View File

@ -722,7 +722,9 @@ minetest.register_node("default:stone_with_iron", {
minetest.register_node("default:dirt_with_grass", {
description = "Dirt with grass",
tiles ={"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
tiles ={"default_grass.png", "default_dirt.png",
{name = "default_dirt.png^default_grass_side.png",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
drop = 'default:dirt',
sounds = default.node_sound_dirt_defaults({
@ -732,7 +734,9 @@ minetest.register_node("default:dirt_with_grass", {
minetest.register_node("default:dirt_with_grass_footsteps", {
description = "Dirt with grass and footsteps",
tiles ={"default_grass_footsteps.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
tiles ={"default_grass_footsteps.png", "default_dirt.png",
{name = "default_dirt.png^default_grass_side.png",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
drop = 'default:dirt',
sounds = default.node_sound_dirt_defaults({

View File

@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/string.h" // for parseColorString()
#include "imagefilters.h"
#include "guiscalingfilter.h"
#include "nodedef.h"
#ifdef __ANDROID__
#include <GLES/gl.h>
@ -330,7 +332,7 @@ public:
*/
video::ITexture* getTexture(u32 id);
video::ITexture* getTexture(const std::string &name, u32 *id);
video::ITexture* getTexture(const std::string &name, u32 *id = NULL);
/*
Get a texture specifically intended for mesh
@ -383,6 +385,7 @@ public:
video::ITexture* getNormalTexture(const std::string &name);
video::SColor getTextureAverageColor(const std::string &name);
video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile);
private:
@ -1992,9 +1995,8 @@ void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
video::ITexture* TextureSource::getNormalTexture(const std::string &name)
{
u32 id;
if (isKnownSourceImage("override_normal.png"))
return getTexture("override_normal.png", &id);
return getTexture("override_normal.png");
std::string fname_base = name;
std::string normal_ext = "_normal.png";
size_t pos = fname_base.find(".");
@ -2006,7 +2008,7 @@ video::ITexture* TextureSource::getNormalTexture(const std::string &name)
fname_base.replace(i, 4, normal_ext);
i += normal_ext.length();
}
return getTexture(fname_base, &id);
return getTexture(fname_base);
}
return NULL;
}
@ -2015,8 +2017,7 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
{
video::IVideoDriver *driver = m_device->getVideoDriver();
video::SColor c(0, 0, 0, 0);
u32 id;
video::ITexture *texture = getTexture(name, &id);
video::ITexture *texture = getTexture(name);
video::IImage *image = driver->createImage(texture,
core::position2d<s32>(0, 0),
texture->getOriginalSize());
@ -2048,3 +2049,31 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
c.setAlpha(255);
return c;
}
video::ITexture *TextureSource::getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)
{
std::string tname = "__shaderFlagsTexture";
bool normalmap_present = tile->normal_texture ? true : false;
tname += normalmap_present ? "1" : "0";
tname += tiledef->tileable_horizontal ? "1" : "0";
tname += tiledef->tileable_vertical ? "1" : "0";
if (isKnownSourceImage(tname)) {
return getTexture(tname);
} else {
video::IVideoDriver *driver = m_device->getVideoDriver();
video::IImage *flags_image = driver->createImage(
video::ECF_A8R8G8B8, core::dimension2d<u32>(1, 1));
sanity_check(flags_image != NULL);
video::SColor c(
255,
normalmap_present ? 255 : 0,
tiledef->tileable_horizontal ? 255 : 0,
tiledef->tileable_vertical ? 255 : 0);
flags_image->setPixel(0, 0, c);
insertSourceImage(tname, flags_image);
flags_image->drop();
return getTexture(tname);
}
}

View File

@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
class IGameDef;
struct TileSpec;
struct TileDef;
/*
tile.{h,cpp}: Texture handling stuff.
@ -111,6 +113,7 @@ public:
const TextureFromMeshParams &params)=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)=0;
};
class IWritableTextureSource : public ITextureSource
@ -133,6 +136,7 @@ public:
virtual void rebuildImagesAndTextures()=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)=0;
};
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
@ -172,12 +176,14 @@ struct FrameSpec
FrameSpec():
texture_id(0),
texture(NULL),
normal_texture(NULL)
normal_texture(NULL),
flags_texture(NULL)
{
}
u32 texture_id;
video::ITexture *texture;
video::ITexture *normal_texture;
video::ITexture *flags_texture;
};
struct TileSpec
@ -186,6 +192,7 @@ struct TileSpec
texture_id(0),
texture(NULL),
normal_texture(NULL),
flags_texture(NULL),
alpha(255),
material_type(TILE_MATERIAL_BASIC),
material_flags(
@ -252,6 +259,7 @@ struct TileSpec
u32 texture_id;
video::ITexture *texture;
video::ITexture *normal_texture;
video::ITexture *flags_texture;
// Vertex alpha (when MATERIAL_ALPHA_VERTEX is used)
u8 alpha;
@ -266,5 +274,4 @@ struct TileSpec
u8 rotation;
};
#endif

View File

@ -878,11 +878,11 @@ public:
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
services->setPixelShaderConstant("baseTexture" , (irr::f32 *)&layer0, 1);
services->setPixelShaderConstant("normalTexture" , (irr::f32 *)&layer1, 1);
services->setPixelShaderConstant("useNormalmap" , (irr::f32 *)&layer2, 1);
services->setPixelShaderConstant("textureFlags" , (irr::f32 *)&layer2, 1);
#else
services->setPixelShaderConstant("baseTexture" , (irr::s32 *)&layer0, 1);
services->setPixelShaderConstant("normalTexture" , (irr::s32 *)&layer1, 1);
services->setPixelShaderConstant("useNormalmap" , (irr::s32 *)&layer2, 1);
services->setPixelShaderConstant("textureFlags" , (irr::s32 *)&layer2, 1);
#endif
}
};
@ -4352,13 +4352,9 @@ void the_game(bool *kill,
}
} catch (SerializationError &e) {
error_message = strgettext("A serialization error occurred:")
+ "\n" + e.what();
if (!simple_singleplayer_mode) {
error_message += "\n\n"
+ strgettext("The server is probably running a different version of")
+ " " PROJECT_NAME_C ".";
}
error_message = std::string("A serialization error occurred:\n")
+ e.what() + "\n\nThe server is probably "
" running a different version of " PROJECT_NAME_C ".";
errorstream << error_message << std::endl;
} catch (ServerError &e) {
error_message = e.what();

View File

@ -1213,10 +1213,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
p.tile.applyMaterialOptionsWithShaders(material);
if (p.tile.normal_texture) {
material.setTexture(1, p.tile.normal_texture);
material.setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
} else {
material.setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
}
material.setTexture(2, p.tile.flags_texture);
} else {
p.tile.applyMaterialOptions(material);
}
@ -1349,10 +1347,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
if (m_enable_shaders) {
if (animation_frame.normal_texture) {
buf->getMaterial().setTexture(1, animation_frame.normal_texture);
buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
} else {
buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
}
buf->getMaterial().setTexture(2, animation_frame.flags_texture);
}
}

View File

@ -130,6 +130,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
presentation
Add TOCLIENT_AUTH_ACCEPT to accept connection from client
Rename GENERIC_CMD_SET_ATTACHMENT to GENERIC_CMD_ATTACH_TO
PROTOCOL_VERSION 26:
Add TileDef tileable_horizontal, tileable_vertical flags
*/
#define LATEST_PROTOCOL_VERSION 25

View File

@ -120,7 +120,9 @@ void NodeBox::deSerialize(std::istream &is)
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
{
if(protocol_version >= 17)
if (protocol_version >= 26)
writeU8(os, 2);
else if (protocol_version >= 17)
writeU8(os, 1);
else
writeU8(os, 0);
@ -129,8 +131,12 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
writeU16(os, animation.aspect_w);
writeU16(os, animation.aspect_h);
writeF1000(os, animation.length);
if(protocol_version >= 17)
if (protocol_version >= 17)
writeU8(os, backface_culling);
if (protocol_version >= 26) {
writeU8(os, tileable_horizontal);
writeU8(os, tileable_vertical);
}
}
void TileDef::deSerialize(std::istream &is)
@ -141,10 +147,15 @@ void TileDef::deSerialize(std::istream &is)
animation.aspect_w = readU16(is);
animation.aspect_h = readU16(is);
animation.length = readF1000(is);
if(version >= 1)
if (version >= 1)
backface_culling = readU8(is);
if (version >= 2) {
tileable_horizontal = readU8(is);
tileable_vertical = readU8(is);
}
}
/*
SimpleSoundSpec serialization
*/
@ -183,6 +194,7 @@ void ContentFeatures::reset()
solidness = 2;
visual_solidness = 0;
backface_culling = true;
#endif
has_on_construct = false;
has_on_destruct = false;
@ -996,9 +1008,11 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
tile->alpha = alpha;
tile->material_type = material_type;
// Normal texture
if (use_normal_texture)
// Normal texture and shader flags texture
if (use_normal_texture) {
tile->normal_texture = tsrc->getNormalTexture(tiledef->name);
}
tile->flags_texture = tsrc->getShaderFlagsTexture(tiledef, tile);
// Material flags
tile->material_flags = 0;
@ -1038,6 +1052,7 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
frame.texture = tsrc->getTextureForMesh(os.str(), &frame.texture_id);
if (tile->normal_texture)
frame.normal_texture = tsrc->getNormalTexture(os.str());
frame.flags_texture = tile->flags_texture;
tile->frames[i] = frame;
}
}

View File

@ -113,6 +113,8 @@ struct TileDef
{
std::string name;
bool backface_culling; // Takes effect only in special cases
bool tileable_horizontal;
bool tileable_vertical;
struct{
enum TileAnimationType type;
int aspect_w; // width for aspect ratio
@ -124,6 +126,8 @@ struct TileDef
{
name = "";
backface_culling = true;
tileable_horizontal = true;
tileable_vertical = true;
animation.type = TAT_NONE;
animation.aspect_w = 1;
animation.aspect_h = 1;

View File

@ -277,20 +277,24 @@ TileDef read_tiledef(lua_State *L, int index)
getstringfield(L, index, "name", tiledef.name);
getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
tiledef.backface_culling = getboolfield_default(
L, index, "backface_culling", true);
L, index, "backface_culling", true);
tiledef.tileable_horizontal = getboolfield_default(
L, index, "tileable_horizontal", true);
tiledef.tileable_vertical = getboolfield_default(
L, index, "tileable_vertical", true);
// animation = {}
lua_getfield(L, index, "animation");
if(lua_istable(L, -1)){
// {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
tiledef.animation.type = (TileAnimationType)
getenumfield(L, -1, "type", es_TileAnimationType,
TAT_NONE);
getenumfield(L, -1, "type", es_TileAnimationType,
TAT_NONE);
tiledef.animation.aspect_w =
getintfield_default(L, -1, "aspect_w", 16);
getintfield_default(L, -1, "aspect_w", 16);
tiledef.animation.aspect_h =
getintfield_default(L, -1, "aspect_h", 16);
getintfield_default(L, -1, "aspect_h", 16);
tiledef.animation.length =
getfloatfield_default(L, -1, "length", 1.0);
getfloatfield_default(L, -1, "length", 1.0);
}
lua_pop(L, 1);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B