From d20b830575f50a07b5e47f81623bcc59b0b83a59 Mon Sep 17 00:00:00 2001 From: Evert Date: Tue, 20 Mar 2018 20:14:47 +0200 Subject: [PATCH] Use planet shaders for objects, including wield items and players --- .../object_shader/opengl_fragment.glsl | 114 +++++++++++++++++ .../shaders/object_shader/opengl_vertex.glsl | 82 +++++++++++++ .../wielded_hand_shader/opengl_fragment.glsl | 115 ++++++++++++++++++ .../wielded_hand_shader/opengl_vertex.glsl | 32 +++++ .../shaders/wielded_shader/opengl_vertex.glsl | 48 +++++++- src/camera.cpp | 2 +- src/content_cao.cpp | 45 ++++++- src/wieldmesh.cpp | 7 +- src/wieldmesh.h | 5 +- 9 files changed, 440 insertions(+), 10 deletions(-) create mode 100644 client/shaders/object_shader/opengl_fragment.glsl create mode 100644 client/shaders/object_shader/opengl_vertex.glsl create mode 100644 client/shaders/wielded_hand_shader/opengl_fragment.glsl create mode 100644 client/shaders/wielded_hand_shader/opengl_vertex.glsl diff --git a/client/shaders/object_shader/opengl_fragment.glsl b/client/shaders/object_shader/opengl_fragment.glsl new file mode 100644 index 00000000..75dd1b67 --- /dev/null +++ b/client/shaders/object_shader/opengl_fragment.glsl @@ -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); +} diff --git a/client/shaders/object_shader/opengl_vertex.glsl b/client/shaders/object_shader/opengl_vertex.glsl new file mode 100644 index 00000000..d980d84a --- /dev/null +++ b/client/shaders/object_shader/opengl_vertex.glsl @@ -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; +} diff --git a/client/shaders/wielded_hand_shader/opengl_fragment.glsl b/client/shaders/wielded_hand_shader/opengl_fragment.glsl new file mode 100644 index 00000000..b39bb01f --- /dev/null +++ b/client/shaders/wielded_hand_shader/opengl_fragment.glsl @@ -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); +} + diff --git a/client/shaders/wielded_hand_shader/opengl_vertex.glsl b/client/shaders/wielded_hand_shader/opengl_vertex.glsl new file mode 100644 index 00000000..9f05b833 --- /dev/null +++ b/client/shaders/wielded_hand_shader/opengl_vertex.glsl @@ -0,0 +1,32 @@ +uniform mat4 mWorldViewProj; +uniform 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; + +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; +} diff --git a/client/shaders/wielded_shader/opengl_vertex.glsl b/client/shaders/wielded_shader/opengl_vertex.glsl index 9f05b833..b5f38b8d 100644 --- a/client/shaders/wielded_shader/opengl_vertex.glsl +++ b/client/shaders/wielded_shader/opengl_vertex.glsl @@ -15,10 +15,56 @@ 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 * pos; vPosition = gl_Position.xyz; worldPosition = (mWorld * gl_Vertex).xyz; diff --git a/src/camera.cpp b/src/camera.cpp index 09ff9388..fd49818f 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -56,7 +56,7 @@ Camera::Camera(MapDrawControl &draw_control, Client *client): // all other 3D scene nodes and before the GUI. m_wieldmgr = smgr->createNewSceneManager(); m_wieldmgr->addCameraSceneNode(); - m_wieldnode = new WieldMeshSceneNode(m_wieldmgr, -1, false); + m_wieldnode = new WieldMeshSceneNode(m_wieldmgr, -1, false, true); m_wieldnode->setItem(ItemStack(), m_client); m_wieldnode->drop(); // m_wieldmgr grabbed it diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 2e9f8f39..0ed04316 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "wieldmesh.h" #include #include "client/renderingengine.h" +#include "shader.h" class Settings; struct ToolCapabilities; @@ -487,6 +488,13 @@ void GenericCAO::addToScene(ITextureSource *tsrc) 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_client->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); @@ -517,7 +525,13 @@ void GenericCAO::addToScene(ITextureSource *tsrc) 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_client->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(); @@ -536,7 +550,13 @@ void GenericCAO::addToScene(ITextureSource *tsrc) 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_client->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(); @@ -563,8 +583,15 @@ void GenericCAO::addToScene(ITextureSource *tsrc) 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_client->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"<setMaterialFlag(video::EMF_LIGHTING, true); 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_client->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 "<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) diff --git a/src/wieldmesh.cpp b/src/wieldmesh.cpp index dd97bc08..e7e4bf9b 100644 --- a/src/wieldmesh.cpp +++ b/src/wieldmesh.cpp @@ -192,10 +192,11 @@ private: ExtrusionMeshCache *g_extrusion_mesh_cache = NULL; -WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting): +WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting, bool wield_in_hand): scene::ISceneNode(mgr->getRootSceneNode(), mgr, id), m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF), - m_lighting(lighting) + m_lighting(lighting), + m_wield_in_hand(wield_in_hand) { m_enable_shaders = g_settings->getBool("enable_shaders"); m_anisotropic_filter = g_settings->getBool("anisotropic_filter"); @@ -345,7 +346,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client) scene::SMesh *mesh = nullptr; 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; } diff --git a/src/wieldmesh.h b/src/wieldmesh.h index 0908d3ac..817f9585 100644 --- a/src/wieldmesh.h +++ b/src/wieldmesh.h @@ -74,7 +74,7 @@ struct ItemMesh class WieldMeshSceneNode : public scene::ISceneNode { public: - WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1, bool lighting = false); + WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1, bool lighting = false, bool wield_in_hand = false); virtual ~WieldMeshSceneNode(); void setCube(const ContentFeatures &f, v3f wield_scale); @@ -102,6 +102,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;