Use planet shaders for objects, including wield items and players

master
Evert 2018-03-20 20:14:47 +02:00
parent 8e2fe7e957
commit d20b830575
No known key found for this signature in database
GPG Key ID: 1688DA83D222D0B5
9 changed files with 440 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,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;
}

View File

@ -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;

View File

@ -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

View File

@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "wieldmesh.h"
#include <algorithm>
#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"<<std::endl;
@ -592,9 +619,16 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
m_animated_meshnode->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 "<<m_prop.mesh<<std::endl;
@ -1050,6 +1084,9 @@ void GenericCAO::updateTextures(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

@ -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;
}

View File

@ -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;