Handle day-night transition in shader and make light sources brighter when shaders are used

This commit is contained in:
Perttu Ahola 2012-12-02 14:24:58 +02:00
parent 566f7f638a
commit cd1f604ffe
7 changed files with 132 additions and 50 deletions

@ -2,6 +2,7 @@
uniform mat4 mWorldViewProj; uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld; uniform mat4 mInvWorld;
uniform mat4 mTransWorld; uniform mat4 mTransWorld;
uniform float dayNightRatio;
varying vec3 vPosition; varying vec3 vPosition;
@ -11,15 +12,43 @@ void main(void)
vPosition = (mWorldViewProj * gl_Vertex).xyz; vPosition = (mWorldViewProj * gl_Vertex).xyz;
if(gl_Normal.y > 0.5) vec4 color;
gl_FrontColor = gl_BackColor = gl_Color; //color = vec4(1.0, 1.0, 1.0, 1.0);
else
gl_FrontColor = gl_BackColor = gl_Color * 0.7;
/*if(gl_Normal.y > 0.5) float day = gl_Color.r;
gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0); float night = gl_Color.g;
else float light_source = gl_Color.b;
gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0) * 0.7;*/
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 1.0; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
if(gl_Normal.y <= 0.5)
color *= 0.7;
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[0] = gl_MultiTexCoord0;
} }

@ -2,6 +2,7 @@
uniform mat4 mWorldViewProj; uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld; uniform mat4 mInvWorld;
uniform mat4 mTransWorld; uniform mat4 mTransWorld;
uniform float dayNightRatio;
varying vec3 vPosition; varying vec3 vPosition;
@ -13,8 +14,40 @@ void main(void)
vPosition = (mWorldViewProj * gl_Vertex).xyz; vPosition = (mWorldViewProj * gl_Vertex).xyz;
gl_FrontColor = gl_BackColor = gl_Color; vec4 color;
//gl_FrontColor = gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0); //color = vec4(1.0, 1.0, 1.0, 1.0);
float day = gl_Color.r;
float night = gl_Color.g;
float light_source = gl_Color.b;
/*color.r = mix(night, day, dayNightRatio);
color.g = color.r;
color.b = color.r;*/
float rg = mix(night, day, dayNightRatio);
rg += light_source * 1.0; // Make light sources brighter
float b = rg;
// Moonlight is blue
b += (day - night) / 13.0;
rg -= (day - night) / 13.0;
// Emphase blue a bit in darker places
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
b += max(0.0, (1.0 - abs(b - 0.13)/0.17) * 0.025);
// Artificial light is yellow-ish
// See C++ implementation in mapblock_mesh.cpp finalColorBlend()
rg += max(0.0, (1.0 - abs(rg - 0.85)/0.15) * 0.065);
color.r = rg;
color.g = rg;
color.b = b;
color.a = gl_Color.a;
gl_FrontColor = gl_BackColor = color;
gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[0] = gl_MultiTexCoord0;
} }

@ -171,7 +171,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
continue; continue;
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(f.alpha, l); video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
@ -226,7 +226,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Otherwise use the light of this node (the liquid) // Otherwise use the light of this node (the liquid)
else else
l = getInteriorLight(n, 0, data); l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(f.alpha, l); video::SColor c = MapBlock_LightColor(f.alpha, l, decode_light(f.light_source));
// Neighbor liquid levels (key = relative position) // Neighbor liquid levels (key = relative position)
// Includes current node // Includes current node
@ -544,7 +544,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer ap = tile.texture; AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
for(u32 j=0; j<6; j++) for(u32 j=0; j<6; j++)
{ {
@ -604,7 +604,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer pa_leaves = tile_leaves.texture; AtlasPointer pa_leaves = tile_leaves.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
v3f pos = intToFloat(p, BS); v3f pos = intToFloat(p, BS);
aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2); aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
@ -638,7 +638,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer ap = tile.texture; AtlasPointer ap = tile.texture;
video::SColor c(255,255,255,255); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
// Wall at X+ of node // Wall at X+ of node
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
@ -683,7 +684,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer ap = tile.texture; AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
float d = (float)BS/16; float d = (float)BS/16;
// Wall at X+ of node // Wall at X+ of node
@ -730,7 +731,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer ap = tile.texture; AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
for(u32 j=0; j<4; j++) for(u32 j=0; j<4; j++)
{ {
@ -793,7 +794,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
tile.texture.id) + "^[transformR90"); tile.texture.id) + "^[transformR90");
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
const f32 post_rad=(f32)BS/8; const f32 post_rad=(f32)BS/8;
const f32 bar_rad=(f32)BS/16; const f32 bar_rad=(f32)BS/16;
@ -996,7 +997,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer ap = tile.texture; AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
float d = (float)BS/64; float d = (float)BS/64;
@ -1045,7 +1046,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
} }
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
v3f pos = intToFloat(p, BS); v3f pos = intToFloat(p, BS);

@ -841,13 +841,15 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
Sky *m_sky; Sky *m_sky;
bool *m_force_fog_off; bool *m_force_fog_off;
f32 *m_fog_range; f32 *m_fog_range;
Client *m_client;
public: public:
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off, GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
f32 *fog_range): f32 *fog_range, Client *client):
m_sky(sky), m_sky(sky),
m_force_fog_off(force_fog_off), m_force_fog_off(force_fog_off),
m_fog_range(fog_range) m_fog_range(fog_range),
m_client(client)
{} {}
~GameGlobalShaderConstantSetter() {} ~GameGlobalShaderConstantSetter() {}
@ -873,10 +875,12 @@ public:
if(*m_force_fog_off) if(*m_force_fog_off)
fog_distance = 10000*BS; fog_distance = 10000*BS;
services->setPixelShaderConstant("fogDistance", &fog_distance, 1); services->setPixelShaderConstant("fogDistance", &fog_distance, 1);
}
private: // Day-night ratio
IrrlichtDevice *m_device; u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
float daynight_ratio_f = (float)daynight_ratio / 1000.0;
services->setPixelShaderConstant("dayNightRatio", &daynight_ratio_f, 1);
}
}; };
void the_game( void the_game(
@ -1307,8 +1311,8 @@ void the_game(
/* /*
Shader constants Shader constants
*/ */
shsrc->addGlobalConstantSetter( shsrc->addGlobalConstantSetter(new GameGlobalShaderConstantSetter(
new GameGlobalShaderConstantSetter(sky, &force_fog_off, &fog_range)); sky, &force_fog_off, &fog_range, &client));
/* /*
Main loop Main loop

@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tile.h" #include "tile.h"
#endif #endif
#include "log.h" #include "log.h"
#include "main.h" // g_settings
#include "settings.h"
#include "util/serialize.h" #include "util/serialize.h"
#include "util/container.h" #include "util/container.h"
#include "util/thread.h" #include "util/thread.h"
@ -356,7 +358,10 @@ public:
scene::IMesh *node_mesh = mapblock_mesh.getMesh(); scene::IMesh *node_mesh = mapblock_mesh.getMesh();
assert(node_mesh); assert(node_mesh);
setMeshColor(node_mesh, video::SColor(255, 255, 255, 255)); video::SColor c(255, 255, 255, 255);
if(g_settings->getS32("enable_shaders") != 0)
c = MapBlock_LightColor(255, 0xffff, decode_light(f.light_source));
setMeshColor(node_mesh, c);
/* /*
Scale and translate the mesh so it's a unit cube Scale and translate the mesh so it's a unit cube

@ -435,7 +435,7 @@ struct FastFace
}; };
static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3, static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
v3f p, v3s16 dir, v3f scale, core::array<FastFace> &dest) v3f p, v3s16 dir, v3f scale, u8 light_source, core::array<FastFace> &dest)
{ {
FastFace face; FastFace face;
@ -477,16 +477,16 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
float h = tile.texture.size.Y; float h = tile.texture.size.Y;
face.vertices[0] = video::S3DVertex(vertex_pos[0], normal, face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
MapBlock_LightColor(alpha, li0), MapBlock_LightColor(alpha, li0, light_source),
core::vector2d<f32>(x0+w*abs_scale, y0+h)); core::vector2d<f32>(x0+w*abs_scale, y0+h));
face.vertices[1] = video::S3DVertex(vertex_pos[1], normal, face.vertices[1] = video::S3DVertex(vertex_pos[1], normal,
MapBlock_LightColor(alpha, li1), MapBlock_LightColor(alpha, li1, light_source),
core::vector2d<f32>(x0, y0+h)); core::vector2d<f32>(x0, y0+h));
face.vertices[2] = video::S3DVertex(vertex_pos[2], normal, face.vertices[2] = video::S3DVertex(vertex_pos[2], normal,
MapBlock_LightColor(alpha, li2), MapBlock_LightColor(alpha, li2, light_source),
core::vector2d<f32>(x0, y0)); core::vector2d<f32>(x0, y0));
face.vertices[3] = video::S3DVertex(vertex_pos[3], normal, face.vertices[3] = video::S3DVertex(vertex_pos[3], normal,
MapBlock_LightColor(alpha, li3), MapBlock_LightColor(alpha, li3, light_source),
core::vector2d<f32>(x0+w*abs_scale, y0)); core::vector2d<f32>(x0+w*abs_scale, y0));
face.tile = tile; face.tile = tile;
@ -658,7 +658,8 @@ static void getTileInfo(
v3s16 &p_corrected, v3s16 &p_corrected,
v3s16 &face_dir_corrected, v3s16 &face_dir_corrected,
u16 *lights, u16 *lights,
TileSpec &tile TileSpec &tile,
u8 &light_source
) )
{ {
VoxelManipulator &vmanip = data->m_vmanip; VoxelManipulator &vmanip = data->m_vmanip;
@ -688,12 +689,14 @@ static void getTileInfo(
tile = tile0; tile = tile0;
p_corrected = p; p_corrected = p;
face_dir_corrected = face_dir; face_dir_corrected = face_dir;
light_source = ndef->get(n0).light_source;
} }
else else
{ {
tile = tile1; tile = tile1;
p_corrected = p + face_dir; p_corrected = p + face_dir;
face_dir_corrected = -face_dir; face_dir_corrected = -face_dir;
light_source = ndef->get(n1).light_source;
} }
// eg. water and glass // eg. water and glass
@ -743,9 +746,10 @@ static void updateFastFaceRow(
v3s16 face_dir_corrected; v3s16 face_dir_corrected;
u16 lights[4] = {0,0,0,0}; u16 lights[4] = {0,0,0,0};
TileSpec tile; TileSpec tile;
u8 light_source = 0;
getTileInfo(data, p, face_dir, getTileInfo(data, p, face_dir,
makes_face, p_corrected, face_dir_corrected, makes_face, p_corrected, face_dir_corrected,
lights, tile); lights, tile, light_source);
for(u16 j=0; j<MAP_BLOCKSIZE; j++) for(u16 j=0; j<MAP_BLOCKSIZE; j++)
{ {
@ -759,6 +763,7 @@ static void updateFastFaceRow(
v3s16 next_face_dir_corrected; v3s16 next_face_dir_corrected;
u16 next_lights[4] = {0,0,0,0}; u16 next_lights[4] = {0,0,0,0};
TileSpec next_tile; TileSpec next_tile;
u8 next_light_source = 0;
// If at last position, there is nothing to compare to and // If at last position, there is nothing to compare to and
// the face must be drawn anyway // the face must be drawn anyway
@ -769,7 +774,7 @@ static void updateFastFaceRow(
getTileInfo(data, p_next, face_dir, getTileInfo(data, p_next, face_dir,
next_makes_face, next_p_corrected, next_makes_face, next_p_corrected,
next_face_dir_corrected, next_lights, next_face_dir_corrected, next_lights,
next_tile); next_tile, next_light_source);
if(next_makes_face == makes_face if(next_makes_face == makes_face
&& next_p_corrected == p_corrected + translate_dir && next_p_corrected == p_corrected + translate_dir
@ -778,7 +783,8 @@ static void updateFastFaceRow(
&& next_lights[1] == lights[1] && next_lights[1] == lights[1]
&& next_lights[2] == lights[2] && next_lights[2] == lights[2]
&& next_lights[3] == lights[3] && next_lights[3] == lights[3]
&& next_tile == tile) && next_tile == tile
&& next_light_source == light_source)
{ {
next_is_different = false; next_is_different = false;
} }
@ -854,7 +860,7 @@ static void updateFastFaceRow(
} }
makeFastFace(tile, lights[0], lights[1], lights[2], lights[3], makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
sp, face_dir_corrected, scale, sp, face_dir_corrected, scale, light_source,
dest); dest);
g_profiler->avg("Meshgen: faces drawn by tiling", 0); g_profiler->avg("Meshgen: faces drawn by tiling", 0);
@ -873,6 +879,7 @@ static void updateFastFaceRow(
lights[2] = next_lights[2]; lights[2] = next_lights[2];
lights[3] = next_lights[3]; lights[3] = next_lights[3];
tile = next_tile; tile = next_tile;
light_source = next_light_source;
} }
p = p_next; p = p_next;
@ -1058,7 +1065,9 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0"; os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0";
p.tile.texture = tsrc->getTexture(os.str()); p.tile.texture = tsrc->getTexture(os.str());
} }
// - Lighting // - Classic lighting (shaders handle this by themselves)
if(!enable_shaders)
{
for(u32 j = 0; j < p.vertices.size(); j++) for(u32 j = 0; j < p.vertices.size(); j++)
{ {
video::SColor &vc = p.vertices[j].Color; video::SColor &vc = p.vertices[j].Color;
@ -1068,7 +1077,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
if(day != night) if(day != night)
m_daynight_diffs[i][j] = std::make_pair(day, night); m_daynight_diffs[i][j] = std::make_pair(day, night);
} }
}
// Create material // Create material
video::SMaterial material; video::SMaterial material;

@ -160,9 +160,10 @@ struct MeshCollector
// alpha in the A channel of the returned SColor // alpha in the A channel of the returned SColor
// day light (0-255) in the R channel of the returned SColor // day light (0-255) in the R channel of the returned SColor
// night light (0-255) in the G channel of the returned SColor // night light (0-255) in the G channel of the returned SColor
inline video::SColor MapBlock_LightColor(u8 alpha, u16 light) // light source (0-255) in the B channel of the returned SColor
inline video::SColor MapBlock_LightColor(u8 alpha, u16 light, u8 light_source=0)
{ {
return video::SColor(alpha, (light & 0xff), (light >> 8), 0); return video::SColor(alpha, (light & 0xff), (light >> 8), light_source);
} }
// Compute light at node // Compute light at node