Use planet shaders for objects, including wield items and players

master
Jeija 2016-09-10 19:12:07 +02:00
parent 493c6bc371
commit dd68d76216
9 changed files with 445 additions and 10 deletions

View File

@ -0,0 +1,114 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
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;
}
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 && 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;
}
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;
#endif
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@ -0,0 +1,82 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
const float e = 2.718281828459;
const float BS = 10.0;
/*
* Complex Number functions
*/
#define cplx vec2
#define cplx_new(re, im) vec2(re, im)
#define cplx_re(z) z.x
#define cplx_im(z) z.y
#define cplx_exp(z) (exp(z.x) * cplx_new(cos(z.y), sin(z.y)))
#define cplx_scale(z, scalar) (z * scalar)
#define cplx_abs(z) (sqrt(z.x * z.x + z.y * z.y))
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
vec4 pos = mWorld * gl_Vertex;
#ifdef ENABLE_PLANET
vec3 camPos = eyePosition.xyz;
float rp = PLANET_RADIUS * BS * 16;
#ifdef PLANET_KEEP_SCALE
// Complex approach
vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
cplx plane = cplx_new(pos.y - camPos.y, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
cplx circle = rp * cplx_exp(cplx_scale(plane, 1.0 / rp)) - cplx_new(rp, 0);
pos.x = cplx_im(circle) * planedir.x + camPos.x;
pos.z = cplx_im(circle) * planedir.y + camPos.z;
pos.y = cplx_re(circle) + camPos.y;
#else
// Naive approach
vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
vec2 plane = vec2(pos.y + rp, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
vec2 circle = plane.x * vec2(cos(plane.y / rp), sin(plane.y / rp)) - vec2(rp, 0);
pos.x = circle.y * planedir.x + camPos.x;
pos.z = circle.y * planedir.y + camPos.z;
pos.y = circle.x;
#endif
// Code for not scaling nodes so that their size close to the player is normal.
// Nodes that are higher up will appear larger (compared to the player).
// Due to distortions you won't be able to dig / build blocks normally though.
//vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
//cplx plane = cplx_new(pos.y, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
//cplx circle = rp * cplx_exp(cplx_scale(plane, 1.0 / rp)) - cplx_new(rp, 0);
//pos.x = cplx_im(circle) * planedir.x + camPos.x;
//pos.z = cplx_im(circle) * planedir.y + camPos.z;
//pos.y = cplx_re(circle);
#endif
gl_Position = mWorldViewProj * mInvWorld * pos;
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;
}

View File

@ -0,0 +1,115 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
uniform vec4 skyBgColor;
uniform float fogDistance;
uniform vec3 eyePosition;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
bool normalTexturePresent = false;
bool texTileableHorizontal = false;
bool texTileableVertical = false;
bool texSeamless = false;
const float e = 2.718281828459;
const float BS = 10.0;
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;
}
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 && 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;
}
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;
#endif
vec4 col = vec4(color.rgb, base.a);
col *= gl_Color;
if (fogDistance != 0.0) {
float d = max(0.0, min(vPosition.z / fogDistance * 1.5 - 0.6, 1.0));
col = mix(col, skyBgColor, d);
}
gl_FragColor = vec4(col.rgb, base.a);
}

View File

@ -0,0 +1,36 @@
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform mat4 mWorld;
uniform float dayNightRatio;
uniform vec3 eyePosition;
uniform float animationTimer;
varying vec3 vPosition;
varying vec3 worldPosition;
varying vec3 eyeVec;
varying vec3 lightVec;
varying vec3 tsEyeVec;
varying vec3 tsLightVec;
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;
}

View File

@ -18,13 +18,60 @@ varying vec3 tsLightVec;
const float e = 2.718281828459;
const float BS = 10.0;
/*
* Complex Number functions
*/
#define cplx vec2
#define cplx_new(re, im) vec2(re, im)
#define cplx_re(z) z.x
#define cplx_im(z) z.y
#define cplx_exp(z) (exp(z.x) * cplx_new(cos(z.y), sin(z.y)))
#define cplx_scale(z, scalar) (z * scalar)
#define cplx_abs(z) (sqrt(z.x * z.x + z.y * z.y))
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = mWorldViewProj * gl_Vertex;
vec4 pos = mWorld * gl_Vertex;
#ifdef ENABLE_PLANET
vec3 camPos = eyePosition.xyz;
float rp = PLANET_RADIUS * BS * 16;
#ifdef PLANET_KEEP_SCALE
// Complex approach
vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
cplx plane = cplx_new(pos.y - camPos.y, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
cplx circle = rp * cplx_exp(cplx_scale(plane, 1.0 / rp)) - cplx_new(rp, 0);
pos.x = cplx_im(circle) * planedir.x + camPos.x;
pos.z = cplx_im(circle) * planedir.y + camPos.z;
pos.y = cplx_re(circle) + camPos.y;
#else
// Naive approach
vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
vec2 plane = vec2(pos.y + rp, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
vec2 circle = plane.x * vec2(cos(plane.y / rp), sin(plane.y / rp)) - vec2(rp, 0);
pos.x = circle.y * planedir.x + camPos.x;
pos.z = circle.y * planedir.y + camPos.z;
pos.y = circle.x;
#endif
// Code for not scaling nodes so that their size close to the player is normal.
// Nodes that are higher up will appear larger (compared to the player).
// Due to distortions you won't be able to dig / build blocks normally though.
//vec2 planedir = normalize(vec2(pos.x - camPos.x, pos.z - camPos.z));
//cplx plane = cplx_new(pos.y, sqrt((pos.x - camPos.x) * (pos.x - camPos.x) + (pos.z - camPos.z) * (pos.z - camPos.z)));
//cplx circle = rp * cplx_exp(cplx_scale(plane, 1.0 / rp)) - cplx_new(rp, 0);
//pos.x = cplx_im(circle) * planedir.x + camPos.x;
//pos.z = cplx_im(circle) * planedir.y + camPos.z;
//pos.y = cplx_re(circle);
#endif
gl_Position = mWorldViewProj * mInvWorld * pos;
vPosition = gl_Position.xyz;
worldPosition = (mWorld * gl_Vertex).xyz;
worldPosition = (mWorld * gl_Vertex).xyz * BS;
vec3 sunPosition = vec3 (0.0, eyePosition.y * BS + 900.0, 0.0);

View File

@ -87,7 +87,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
// all other 3D scene nodes and before the GUI.
m_wieldmgr = smgr->createNewSceneManager();
m_wieldmgr->addCameraSceneNode();
m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, false);
m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, false, true);
m_wieldnode->setItem(ItemStack(), m_gamedef);
m_wieldnode->drop(); // m_wieldmgr grabbed it

View File

@ -830,6 +830,13 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
u16 shader_id = shdrsrc->getShader("object_shader", 1, 1);
m_spritenode->setMaterialType(shdrsrc->getShaderInfo(shader_id).material);
} else {
m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
}
u8 li = m_last_light;
m_spritenode->setColor(video::SColor(255,li,li,li));
m_spritenode->setSize(m_prop.visual_size*BS);
@ -860,7 +867,13 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
u16 shader_id = shdrsrc->getShader("object_shader", 1, 1);
buf->getMaterial().MaterialType = shdrsrc->getShaderInfo(shader_id).material;
} else {
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
}
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
@ -879,7 +892,13 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
u16 shader_id = shdrsrc->getShader("object_shader", 1, 1);
buf->getMaterial().MaterialType = shdrsrc->getShaderInfo(shader_id).material;
} else {
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
}
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
@ -906,8 +925,15 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
m_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
m_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
u16 shader_id = shdrsrc->getShader("object_shader", 1, 1);
m_meshnode->setMaterialType(shdrsrc->getShaderInfo(shader_id).material);
} else {
m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
}
}
else if(m_prop.visual == "mesh") {
infostream<<"GenericCAO::addToScene(): mesh"<<std::endl;
@ -930,9 +956,16 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
m_animated_meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, backface_culling);
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = m_gamedef->getShaderSource();
u16 shader_id = shdrsrc->getShader("object_shader", 1, 1);
m_animated_meshnode->setMaterialType(shdrsrc->getShaderInfo(shader_id).material);
} else {
m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
}
}
else
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
@ -1372,6 +1405,9 @@ void GenericCAO::updateTextures(const std::string &mod)
.setFlag(video::EMF_BILINEAR_FILTER, use_bilinear_filter);
m_animated_meshnode->getMaterial(i)
.setFlag(video::EMF_ANISOTROPIC_FILTER, use_anisotropic_filter);
if (g_settings->getBool("enable_shaders")) {
m_animated_meshnode->getMaterial(i).setTexture(2, tsrc->getShaderFlagsTexture(false));
}
}
for (u32 i = 0; i < m_prop.colors.size() &&
i < m_animated_meshnode->getMaterialCount(); ++i)

View File

@ -196,12 +196,14 @@ WieldMeshSceneNode::WieldMeshSceneNode(
scene::ISceneNode *parent,
scene::ISceneManager *mgr,
s32 id,
bool lighting
bool lighting,
bool wield_in_hand
):
scene::ISceneNode(parent, mgr, id),
m_meshnode(NULL),
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF),
m_lighting(lighting),
m_wield_in_hand(wield_in_hand),
m_bounding_box(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
{
m_enable_shaders = g_settings->getBool("enable_shaders");
@ -315,7 +317,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
content_t id = ndef->getId(def.name);
if (m_enable_shaders) {
u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
u32 shader_id = shdrsrc->getShader(m_wield_in_hand ? "wielded_hand_shader" : "wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
}

View File

@ -35,7 +35,7 @@ class WieldMeshSceneNode: public scene::ISceneNode
{
public:
WieldMeshSceneNode(scene::ISceneNode *parent, scene::ISceneManager *mgr,
s32 id = -1, bool lighting = false);
s32 id = -1, bool lighting = false, bool wield_in_hand = false);
virtual ~WieldMeshSceneNode();
void setCube(const TileSpec tiles[6],
@ -66,6 +66,9 @@ private:
// True if EMF_LIGHTING should be enabled.
bool m_lighting;
// True if mesh is displayed as the one currently held by the player
bool m_wield_in_hand;
bool m_enable_shaders;
bool m_anisotropic_filter;
bool m_bilinear_filter;