Add wielded (and CAOs) shader

This commit is contained in:
RealBadAngel 2015-07-21 23:56:41 +02:00
parent 5b0c719171
commit 60350699c7
11 changed files with 224 additions and 40 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,35 @@
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

@ -92,10 +92,9 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
// all other 3D scene nodes and before the GUI. // all other 3D scene nodes and before the GUI.
m_wieldmgr = smgr->createNewSceneManager(); m_wieldmgr = smgr->createNewSceneManager();
m_wieldmgr->addCameraSceneNode(); m_wieldmgr->addCameraSceneNode();
m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, true); m_wieldnode = new WieldMeshSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr, -1, false);
m_wieldnode->setItem(ItemStack(), m_gamedef); m_wieldnode->setItem(ItemStack(), m_gamedef);
m_wieldnode->drop(); // m_wieldmgr grabbed it m_wieldnode->drop(); // m_wieldmgr grabbed it
m_wieldlightnode = m_wieldmgr->addLightSceneNode(NULL, v3f(0.0, 50.0, 0.0));
/* TODO: Add a callback function so these can be updated when a setting /* TODO: Add a callback function so these can be updated when a setting
* changes. At this point in time it doesn't matter (e.g. /set * changes. At this point in time it doesn't matter (e.g. /set
@ -451,11 +450,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime,
m_wieldnode->setPosition(wield_position); m_wieldnode->setPosition(wield_position);
m_wieldnode->setRotation(wield_rotation); m_wieldnode->setRotation(wield_rotation);
// Shine light upon the wield mesh m_wieldnode->setColor(player->light_color);
video::SColor black(255,0,0,0);
m_wieldmgr->setAmbientLight(player->light_color.getInterpolated(black, 0.7));
m_wieldlightnode->getLightData().DiffuseColor = player->light_color.getInterpolated(black, 0.3);
m_wieldlightnode->setPosition(v3f(30+5*sin(2*player->getYaw()*M_PI/180), -50, 0));
// Render distance feedback loop // Render distance feedback loop
updateViewingRange(frametime, busytime); updateViewingRange(frametime, busytime);

View File

@ -159,7 +159,6 @@ private:
scene::ISceneManager* m_wieldmgr; scene::ISceneManager* m_wieldmgr;
WieldMeshSceneNode* m_wieldnode; WieldMeshSceneNode* m_wieldnode;
scene::ILightSceneNode* m_wieldlightnode;
// draw control // draw control
MapDrawControl& m_draw_control; MapDrawControl& m_draw_control;

View File

@ -385,7 +385,8 @@ public:
video::ITexture* getNormalTexture(const std::string &name); video::ITexture* getNormalTexture(const std::string &name);
video::SColor getTextureAverageColor(const std::string &name); video::SColor getTextureAverageColor(const std::string &name);
video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile); video::ITexture *getShaderFlagsTexture(
bool normamap_present, bool tileable_vertical, bool tileable_horizontal);
private: private:
@ -2050,14 +2051,14 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
return c; return c;
} }
video::ITexture *TextureSource::getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)
video::ITexture *TextureSource::getShaderFlagsTexture(
bool normalmap_present, bool tileable_vertical, bool tileable_horizontal)
{ {
std::string tname = "__shaderFlagsTexture"; std::string tname = "__shaderFlagsTexture";
bool normalmap_present = tile->normal_texture ? true : false;
tname += normalmap_present ? "1" : "0"; tname += normalmap_present ? "1" : "0";
tname += tiledef->tileable_horizontal ? "1" : "0"; tname += tileable_horizontal ? "1" : "0";
tname += tiledef->tileable_vertical ? "1" : "0"; tname += tileable_vertical ? "1" : "0";
if (isKnownSourceImage(tname)) { if (isKnownSourceImage(tname)) {
return getTexture(tname); return getTexture(tname);
@ -2069,8 +2070,8 @@ video::ITexture *TextureSource::getShaderFlagsTexture(TileDef *tiledef, TileSpec
video::SColor c( video::SColor c(
255, 255,
normalmap_present ? 255 : 0, normalmap_present ? 255 : 0,
tiledef->tileable_horizontal ? 255 : 0, tileable_horizontal ? 255 : 0,
tiledef->tileable_vertical ? 255 : 0); tileable_vertical ? 255 : 0);
flags_image->setPixel(0, 0, c); flags_image->setPixel(0, 0, c);
insertSourceImage(tname, flags_image); insertSourceImage(tname, flags_image);
flags_image->drop(); flags_image->drop();

View File

@ -113,7 +113,8 @@ public:
const TextureFromMeshParams &params)=0; const TextureFromMeshParams &params)=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0; virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0; virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)=0; virtual video::ITexture *getShaderFlagsTexture(bool normamap_present,
bool tileable_vertical, bool tileable_horizontal)=0;
}; };
class IWritableTextureSource : public ITextureSource class IWritableTextureSource : public ITextureSource
@ -136,7 +137,8 @@ public:
virtual void rebuildImagesAndTextures()=0; virtual void rebuildImagesAndTextures()=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0; virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0; virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(TileDef *tiledef, TileSpec *tile)=0; virtual video::ITexture *getShaderFlagsTexture(bool normamap_present,
bool tileable_vertical, bool tileable_horizontal)=0;
}; };
IWritableTextureSource* createTextureSource(IrrlichtDevice *device); IWritableTextureSource* createTextureSource(IrrlichtDevice *device);

View File

@ -33,6 +33,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY #define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
#endif #endif
static void applyFacesShading(video::SColor& color, float factor)
{
color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
}
scene::IAnimatedMesh* createCubeMesh(v3f scale) scene::IAnimatedMesh* createCubeMesh(v3f scale)
{ {
video::SColor c(255,255,255,255); video::SColor c(255,255,255,255);
@ -165,6 +172,35 @@ void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
} }
} }
void shadeMeshFaces(scene::IMesh *mesh)
{
if (mesh == NULL)
return;
u32 mc = mesh->getMeshBufferCount();
for (u32 j = 0; j < mc; j++) {
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
const u32 stride = getVertexPitchFromType(buf->getVertexType());
u32 vertex_count = buf->getVertexCount();
u8 *vertices = (u8 *)buf->getVertices();
for (u32 i = 0; i < vertex_count; i++) {
video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
video::SColor &vc = vertex->Color;
if (vertex->Normal.Y < -0.5) {
applyFacesShading (vc, 0.447213);
} else if (vertex->Normal.Z > 0.5) {
applyFacesShading (vc, 0.670820);
} else if (vertex->Normal.Z < -0.5) {
applyFacesShading (vc, 0.670820);
} else if (vertex->Normal.X > 0.5) {
applyFacesShading (vc, 0.836660);
} else if (vertex->Normal.X < -0.5) {
applyFacesShading (vc, 0.836660);
}
}
}
}
void setMeshColorByNormalXYZ(scene::IMesh *mesh, void setMeshColorByNormalXYZ(scene::IMesh *mesh,
const video::SColor &colorX, const video::SColor &colorX,
const video::SColor &colorY, const video::SColor &colorY,

View File

@ -48,6 +48,12 @@ void translateMesh(scene::IMesh *mesh, v3f vec);
*/ */
void setMeshColor(scene::IMesh *mesh, const video::SColor &color); void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
/*
Shade mesh faces according to their normals
*/
void shadeMeshFaces(scene::IMesh *mesh);
/* /*
Set the color of all vertices in the mesh. Set the color of all vertices in the mesh.
For each vertex, determine the largest absolute entry in For each vertex, determine the largest absolute entry in

View File

@ -1012,7 +1012,9 @@ void CNodeDefManager::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
if (use_normal_texture) { if (use_normal_texture) {
tile->normal_texture = tsrc->getNormalTexture(tiledef->name); tile->normal_texture = tsrc->getNormalTexture(tiledef->name);
} }
tile->flags_texture = tsrc->getShaderFlagsTexture(tiledef, tile); tile->flags_texture = tsrc->getShaderFlagsTexture(
tile->normal_texture ? true : false,
tiledef->tileable_horizontal, tiledef->tileable_vertical);
// Material flags // Material flags
tile->material_flags = 0; tile->material_flags = 0;

View File

@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define WIELD_SCALE_FACTOR 30.0 #define WIELD_SCALE_FACTOR 30.0
#define WIELD_SCALE_FACTOR_EXTRUDED 40.0 #define WIELD_SCALE_FACTOR_EXTRUDED 40.0
#define MIN_EXTRUSION_MESH_RESOLUTION 32 // not 16: causes too many "holes" #define MIN_EXTRUSION_MESH_RESOLUTION 16
#define MAX_EXTRUSION_MESH_RESOLUTION 512 #define MAX_EXTRUSION_MESH_RESOLUTION 512
static scene::IMesh* createExtrusionMesh(int resolution_x, int resolution_y) static scene::IMesh* createExtrusionMesh(int resolution_x, int resolution_y)
@ -114,6 +114,7 @@ static scene::IMesh* createExtrusionMesh(int resolution_x, int resolution_y)
mesh->addMeshBuffer(buf); mesh->addMeshBuffer(buf);
buf->drop(); buf->drop();
scaleMesh(mesh, scale); // also recalculates bounding box scaleMesh(mesh, scale); // also recalculates bounding box
mesh = (scene::SMesh *)createForsythOptimizedMesh(mesh);
return mesh; return mesh;
} }
@ -281,7 +282,9 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
// Customize material // Customize material
video::SMaterial &material = m_meshnode->getMaterial(0); video::SMaterial &material = m_meshnode->getMaterial(0);
material.setTexture(0, tsrc->getTextureForMesh(imagename)); material.setTexture(0, tsrc->getTexture(imagename));
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
material.setFlag(video::EMF_BACK_FACE_CULLING, true); material.setFlag(video::EMF_BACK_FACE_CULLING, true);
// Enable bi/trilinear filtering only for high resolution textures // Enable bi/trilinear filtering only for high resolution textures
@ -297,31 +300,25 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
material.setFlag(video::EMF_USE_MIP_MAPS, false); material.setFlag(video::EMF_USE_MIP_MAPS, false);
#endif #endif
if (m_enable_shaders) {
#if 0 material.setTexture(2, tsrc->getShaderFlagsTexture(false, true, true));
//// TODO(RealBadAngel): Reactivate when shader is added for wield items }
if (m_enable_shaders)
material.setTexture(2, tsrc->getTexture("disable_img.png"));
#endif
} }
void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef) void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
{ {
ITextureSource *tsrc = gamedef->getTextureSource(); ITextureSource *tsrc = gamedef->getTextureSource();
IItemDefManager *idef = gamedef->getItemDefManager(); IItemDefManager *idef = gamedef->getItemDefManager();
//IShaderSource *shdrsrc = gamedef->getShaderSource(); IShaderSource *shdrsrc = gamedef->getShaderSource();
INodeDefManager *ndef = gamedef->getNodeDefManager(); INodeDefManager *ndef = gamedef->getNodeDefManager();
const ItemDefinition &def = item.getDefinition(idef); const ItemDefinition &def = item.getDefinition(idef);
const ContentFeatures &f = ndef->get(def.name); const ContentFeatures &f = ndef->get(def.name);
content_t id = ndef->getId(def.name); content_t id = ndef->getId(def.name);
#if 0
//// TODO(RealBadAngel): Reactivate when shader is added for wield items
if (m_enable_shaders) { if (m_enable_shaders) {
u32 shader_id = shdrsrc->getShader("nodes_shader", TILE_MATERIAL_BASIC, NDT_NORMAL); u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
m_material_type = shdrsrc->getShaderInfo(shader_id).material; m_material_type = shdrsrc->getShaderInfo(shader_id).material;
} }
#endif
// If wield_image is defined, it overrides everything else // If wield_image is defined, it overrides everything else
if (def.wield_image != "") { if (def.wield_image != "") {
@ -345,8 +342,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
} else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) { } else if (f.drawtype == NDT_NORMAL || f.drawtype == NDT_ALLFACES) {
setCube(f.tiles, def.wield_scale, tsrc); setCube(f.tiles, def.wield_scale, tsrc);
} else { } else {
//// TODO: Change false in the following constructor args to
//// appropriate value when shader is added for wield items (if applicable)
MeshMakeData mesh_make_data(gamedef, false); MeshMakeData mesh_make_data(gamedef, false);
MapNode mesh_make_node(id, 255, 0); MapNode mesh_make_node(id, 255, 0);
mesh_make_data.fillSingleNode(&mesh_make_node); mesh_make_data.fillSingleNode(&mesh_make_node);
@ -376,8 +371,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
material.setTexture(0, f.tiles[i].texture); material.setTexture(0, f.tiles[i].texture);
} }
material.MaterialType = m_material_type; material.MaterialType = m_material_type;
#if 0
//// TODO(RealBadAngel): Reactivate when shader is added for wield items
if (m_enable_shaders) { if (m_enable_shaders) {
if (f.tiles[i].normal_texture) { if (f.tiles[i].normal_texture) {
if (animated) { if (animated) {
@ -386,12 +379,9 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, IGameDef *gamedef)
} else { } else {
material.setTexture(1, f.tiles[i].normal_texture); material.setTexture(1, f.tiles[i].normal_texture);
} }
material.setTexture(2, tsrc->getTexture("enable_img.png"));
} else {
material.setTexture(2, tsrc->getTexture("disable_img.png"));
} }
material.setTexture(2, f.tiles[i].flags_texture);
} }
#endif
} }
return; return;
} }
@ -408,6 +398,7 @@ void WieldMeshSceneNode::setColor(video::SColor color)
{ {
assert(!m_lighting); assert(!m_lighting);
setMeshColor(m_meshnode->getMesh(), color); setMeshColor(m_meshnode->getMesh(), color);
shadeMeshFaces(m_meshnode->getMesh());
} }
void WieldMeshSceneNode::render() void WieldMeshSceneNode::render()

View File

@ -48,6 +48,9 @@ public:
// Must only be used if the constructor was called with lighting = false // Must only be used if the constructor was called with lighting = false
void setColor(video::SColor color); void setColor(video::SColor color);
scene::IMesh *getMesh()
{ return m_meshnode->getMesh(); }
virtual void render(); virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const virtual const core::aabbox3d<f32>& getBoundingBox() const