From 6c98fd6658fcf7c0c676ee88f03e364c852e9f1b Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Wed, 14 May 2014 23:19:31 +0200 Subject: Unite nodes shaders. Pass drawtype and material type to shaders. Move shaders generation to startup only. Allow assign shaders per tile. Initial code to support water surface shader. --- src/client.cpp | 4 +- src/mapblock_mesh.cpp | 33 +++---- src/nodedef.cpp | 24 ++++- src/nodedef.h | 5 +- src/shader.cpp | 249 ++++++++++++++++++++++++++------------------------ src/shader.h | 28 +++--- src/tile.h | 38 ++------ 7 files changed, 191 insertions(+), 190 deletions(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index 5f3c3f590..8b89dd63c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2670,9 +2670,9 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font) infostream<<"- Updating node aliases"<updateAliases(m_itemdef); - // Update node textures + // Update node textures and assign shaders to each tile infostream<<"- Updating node textures"<updateTextures(m_tsrc); + m_nodedef->updateTextures(m_tsrc, m_shsrc); // Preload item textures and meshes if configured to if(g_settings->getBool("preload_item_visuals")) diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 73f69c247..bf62fe8b4 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -1106,24 +1106,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): /* Convert MeshCollector to SMesh */ + ITextureSource *tsrc = m_gamedef->tsrc(); + IShaderSource *shdrsrc = m_gamedef->getShaderSource(); + bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); - video::E_MATERIAL_TYPE shadermat1, shadermat2, shadermat3, - shadermat4, shadermat5; - shadermat1 = shadermat2 = shadermat3 = shadermat4 = shadermat5 = - video::EMT_SOLID; - - if (enable_shaders) { - IShaderSource *shdrsrc = m_gamedef->getShaderSource(); - shadermat1 = shdrsrc->getShader("solids_shader").material; - shadermat2 = shdrsrc->getShader("liquids_shader").material; - shadermat3 = shdrsrc->getShader("alpha_shader").material; - shadermat4 = shdrsrc->getShader("leaves_shader").material; - shadermat5 = shdrsrc->getShader("plants_shader").material; - } - for(u32 i = 0; i < collector.prebuffers.size(); i++) { PreMeshBuffer &p = collector.prebuffers[i]; @@ -1135,7 +1124,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): // - Cracks if(p.tile.material_flags & MATERIAL_FLAG_CRACK) { - ITextureSource *tsrc = data->m_gamedef->tsrc(); // Find the texture name plus ^[crack:N: std::ostringstream os(std::ios::binary); os<getTextureName(p.tile.texture_id)<<"^[crack"; @@ -1151,7 +1139,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): // - Texture animation if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { - ITextureSource *tsrc = data->m_gamedef->tsrc(); // Add to MapBlockMesh in order to animate these tiles m_animation_tiles[i] = p.tile; m_animation_frames[i] = 0; @@ -1206,7 +1193,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): material.setTexture(0, p.tile.texture); if (enable_shaders) { - ITextureSource *tsrc = data->m_gamedef->tsrc(); + material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material; + p.tile.applyMaterialOptionsWithShaders(material); material.setTexture(2, tsrc->getTexture("disable_img.png")); if (enable_bumpmapping || enable_parallax_occlusion) { if (tsrc->isKnownSourceImage("override_normal.png")){ @@ -1230,8 +1218,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): } } } - p.tile.applyMaterialOptionsWithShaders(material, - shadermat1, shadermat2, shadermat3, shadermat4, shadermat5); } else { p.tile.applyMaterialOptions(material); } @@ -1360,6 +1346,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first); ITextureSource *tsrc = m_gamedef->getTextureSource(); + IShaderSource *shdrsrc = m_gamedef->getShaderSource(); // Create new texture name from original std::ostringstream os(std::ios::binary); @@ -1367,9 +1354,10 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<getMaterial().setTexture(0, tsrc->getTexture(os.str())); - buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png")); - if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) - { + if (enable_shaders){ + buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png")); + buf->getMaterial().MaterialType = shdrsrc->getShaderInfo(tile.shader_id).material; + if (enable_bumpmapping || enable_parallax_occlusion){ if (tsrc->isKnownSourceImage("override_normal.png")){ buf->getMaterial().setTexture(1, tsrc->getTexture("override_normal.png")); buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png")); @@ -1388,6 +1376,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat } } } + } } // Day-night transition diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 2b6de0461..d009a9523 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -597,7 +597,8 @@ public: } } } - virtual void updateTextures(ITextureSource *tsrc) + virtual void updateTextures(ITextureSource *tsrc, + IShaderSource *shdsrc) { #ifndef SERVER infostream<<"CNodeDefManager::updateTextures(): Updating " @@ -621,6 +622,8 @@ public: } bool is_liquid = false; + bool is_water_surface = false; + u8 material_type; material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA; @@ -676,13 +679,13 @@ public: } } if (f->waving == 1) - material_type = TILE_MATERIAL_LEAVES; + material_type = TILE_MATERIAL_WAVING_LEAVES; break; case NDT_PLANTLIKE: f->solidness = 0; f->backface_culling = false; if (f->waving == 1) - material_type = TILE_MATERIAL_PLANTS; + material_type = TILE_MATERIAL_WAVING_PLANTS; break; case NDT_TORCHLIKE: case NDT_SIGNLIKE: @@ -693,11 +696,22 @@ public: break; } - if (is_liquid) + if (is_liquid){ material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT; + if (f->name == "default:water_source") + is_water_surface = true; + } + u32 tile_shader[6]; + for(u16 j=0; j<6; j++) + tile_shader[j] = shdsrc->getShader("nodes_shader",material_type, f->drawtype); + + if (is_water_surface) + tile_shader[0] = shdsrc->getShader("water_surface_shader",material_type, f->drawtype); // Tiles (fill in f->tiles[]) for(u16 j=0; j<6; j++){ + // Shader + f->tiles[j].shader_id = tile_shader[j]; // Texture f->tiles[j].texture = tsrc->getTexture( tiledef[j].name, @@ -740,6 +754,8 @@ public: } // Special tiles (fill in f->special_tiles[]) for(u16 j=0; jspecial_tiles[j].shader_id = tile_shader[j]; // Texture f->special_tiles[j].texture = tsrc->getTexture( f->tiledef_special[j].name, diff --git a/src/nodedef.h b/src/nodedef.h index d4cd66f80..6845e237d 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapnode.h" #ifndef SERVER #include "tile.h" +#include "shader.h" #endif #include "itemgroup.h" #include "sound.h" // SimpleSoundSpec @@ -35,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class IItemDefManager; class ITextureSource; +class IShaderSource; class IGameDef; typedef std::list > GroupItems; @@ -323,7 +325,8 @@ public: /* Update tile textures to latest return values of TextueSource. */ - virtual void updateTextures(ITextureSource *tsrc)=0; + virtual void updateTextures(ITextureSource *tsrc, + IShaderSource *shdsrc)=0; virtual void serialize(std::ostream &os, u16 protocol_version)=0; virtual void deSerialize(std::istream &is)=0; diff --git a/src/shader.cpp b/src/shader.cpp index 4013add6c..f855a7fe3 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "strfnd.h" // trim() +#include "tile.h" /* A cache from shader name to shader path @@ -210,7 +211,8 @@ public: class MainShaderConstantSetter : public IShaderConstantSetter { public: - MainShaderConstantSetter(IrrlichtDevice *device) + MainShaderConstantSetter(IrrlichtDevice *device): + m_device(device) {} ~MainShaderConstantSetter() {} @@ -254,6 +256,9 @@ public: services->setVertexShaderConstant(world.pointer(), 8, 4); } + +private: + IrrlichtDevice *m_device; }; /* @@ -266,13 +271,6 @@ public: ShaderSource(IrrlichtDevice *device); ~ShaderSource(); - /* - Gets a shader material id from cache or - - if main thread, from getShaderIdDirect - - if other thread, adds to request queue and waits for main thread - */ - u32 getShaderId(const std::string &name); - /* - If shader material specified by name is found from cache, return the cached id. @@ -280,26 +278,23 @@ public: The id 0 points to a null shader. Its material is EMT_SOLID. */ - u32 getShaderIdDirect(const std::string &name); - - // Finds out the name of a cached shader. - std::string getShaderName(u32 id); + u32 getShaderIdDirect(const std::string &name, + const u8 material_type, const u8 drawtype); /* If shader specified by the name pointed by the id doesn't - exist, create it, then return the cached shader. + exist, create it, then return id. Can be called from any thread. If called from some other thread and not found in cache, the call is queued to the main thread for processing. */ - ShaderInfo getShader(u32 id); - - ShaderInfo getShader(const std::string &name) - { - return getShader(getShaderId(name)); - } - + + u32 getShader(const std::string &name, + const u8 material_type, const u8 drawtype); + + ShaderInfo getShaderInfo(u32 id); + // Processes queued shader requests from other threads. // Shall be called from the main thread. void processQueue(); @@ -337,9 +332,7 @@ private: // A shader id is index in this array. // The first position contains a dummy shader. std::vector m_shaderinfo_cache; - // Maps a shader name to an index in the former. - std::map m_name_to_id; - // The two former containers are behind this mutex + // The former container is behind this mutex JMutex m_shaderinfo_cache_mutex; // Queued shader fetches (to be processed by the main thread) @@ -358,7 +351,9 @@ IWritableShaderSource* createShaderSource(IrrlichtDevice *device) /* Generate shader given the shader name. */ -ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, +ShaderInfo generate_shader(std::string name, + u8 material_type, u8 drawtype, + IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback, SourceShaderCache *sourcecache); @@ -381,7 +376,6 @@ ShaderSource::ShaderSource(IrrlichtDevice *device): // Add a dummy ShaderInfo as the first index, named "" m_shaderinfo_cache.push_back(ShaderInfo()); - m_name_to_id[""] = 0; // Add main global constant setter addGlobalConstantSetter(new MainShaderConstantSetter(device)); @@ -398,28 +392,17 @@ ShaderSource::~ShaderSource() m_global_setters.clear(); } -u32 ShaderSource::getShaderId(const std::string &name) +u32 ShaderSource::getShader(const std::string &name, + const u8 material_type, const u8 drawtype) { - //infostream<<"getShaderId(): \""<::iterator n; - n = m_name_to_id.find(name); - if(n != m_name_to_id.end()) - return n->second; - } - /* Get shader */ + if(get_current_thread_id() == m_main_thread){ - return getShaderIdDirect(name); + return getShaderIdDirect(name, material_type, drawtype); } else { - /*errorstream<<"getShaderId(): Queued: name=\""<name == name && info->material_type == material_type && + info->drawtype == drawtype) + return i; + } + /* Calling only allowed from main thread */ @@ -472,25 +464,7 @@ u32 ShaderSource::getShaderIdDirect(const std::string &name) return 0; } - /* - See if shader already exists - */ - { - JMutexAutoLock lock(m_shaderinfo_cache_mutex); - - std::map::iterator n; - n = m_name_to_id.find(name); - if(n != m_name_to_id.end()){ - /*infostream<<"getShaderIdDirect(): \""<second; - } - } - - /*infostream<<"getShaderIdDirect(): \""<= m_shaderinfo_cache.size()){ - errorstream<<"ShaderSource::getShaderName(): id="<= m_shaderinfo_cache.size()=" - < - request = m_get_shader_queue.pop(); + - /**errorstream<<"ShaderSource::processQueue(): " - <<"got shader request with " - <<"name=\""<name != ""){ - *info = generate_shader(info->name, m_device, - m_shader_callback, &m_sourcecache); + *info = generate_shader(info->name, info->material_type, + info->drawtype, m_device, m_shader_callback, &m_sourcecache); } } } @@ -597,29 +544,36 @@ void ShaderSource::onSetConstants(video::IMaterialRendererServices *services, } } -ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, - video::IShaderConstantSetCallBack *callback, +ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype, + IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback, SourceShaderCache *sourcecache) { - /*infostream<<"generate_shader(): " - "\""<getOrLoad(name, "base.txt")); - for(s32 i = 0; video::sBuiltInMaterialTypeNames[i] != 0; i++){ - if(video::sBuiltInMaterialTypeNames[i] == base_material_name){ - shaderinfo.material = (video::E_MATERIAL_TYPE) i; + switch(material_type){ + case TILE_MATERIAL_BASIC: + shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; break; - } + case TILE_MATERIAL_ALPHA: + shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + break; + case TILE_MATERIAL_LIQUID_TRANSPARENT: + shaderinfo.base_material = video::EMT_TRANSPARENT_VERTEX_ALPHA; + break; + case TILE_MATERIAL_LIQUID_OPAQUE: + shaderinfo.base_material = video::EMT_SOLID; + break; + case TILE_MATERIAL_WAVING_LEAVES: + shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + break; + case TILE_MATERIAL_WAVING_PLANTS: + shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + break; } - + bool enable_shaders = g_settings->getBool("enable_shaders"); if(!enable_shaders) return shaderinfo; @@ -645,7 +599,6 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, load_shaders(name, sourcecache, driver->getDriverType(), enable_shaders, vertex_program, pixel_program, geometry_program, is_highlevel); - // Check hardware/driver support if(vertex_program != "" && !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && @@ -678,6 +631,55 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, // Create shaders header std::string shaders_header = "#version 120\n"; + static const char* drawTypes[] = { + "NDT_NORMAL", + "NDT_AIRLIKE", + "NDT_LIQUID", + "NDT_FLOWINGLIQUID", + "NDT_GLASSLIKE", + "NDT_ALLFACES", + "NDT_ALLFACES_OPTIONAL", + "NDT_TORCHLIKE", + "NDT_SIGNLIKE", + "NDT_PLANTLIKE", + "NDT_FENCELIKE", + "NDT_RAILLIKE", + "NDT_NODEBOX", + "NDT_GLASSLIKE_FRAMED" + }; + + for (int i = 0; i < 14; i++){ + shaders_header += "#define "; + shaders_header += drawTypes[i]; + shaders_header += " "; + shaders_header += itos(i); + shaders_header += "\n"; + } + + static const char* materialTypes[] = { + "TILE_MATERIAL_BASIC", + "TILE_MATERIAL_ALPHA", + "TILE_MATERIAL_LIQUID_TRANSPARENT", + "TILE_MATERIAL_LIQUID_OPAQUE", + "TILE_MATERIAL_WAVING_LEAVES", + "TILE_MATERIAL_WAVING_PLANTS" + }; + + for (int i = 0; i < 6; i++){ + shaders_header += "#define "; + shaders_header += materialTypes[i]; + shaders_header += " "; + shaders_header += itos(i); + shaders_header += "\n"; + } + + shaders_header += "#define MATERIAL_TYPE "; + shaders_header += itos(material_type); + shaders_header += "\n"; + shaders_header += "#define DRAW_TYPE "; + shaders_header += itos(drawtype); + shaders_header += "\n"; + if (g_settings->getBool("generate_normalmaps")){ shaders_header += "#define GENERATE_NORMALMAPS\n"; shaders_header += "#define NORMALMAPS_STRENGTH "; @@ -721,7 +723,7 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, shaders_header += "#define USE_NORMALMAPS\n"; if (g_settings->getBool("enable_waving_water")){ - shaders_header += "#define ENABLE_WAVING_WATER\n"; + shaders_header += "#define ENABLE_WAVING_WATER 1\n"; shaders_header += "#define WATER_WAVE_HEIGHT "; shaders_header += ftos(g_settings->getFloat("water_wave_height")); shaders_header += "\n"; @@ -731,13 +733,21 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, shaders_header += "#define WATER_WAVE_SPEED "; shaders_header += ftos(g_settings->getFloat("water_wave_speed")); shaders_header += "\n"; + } else{ + shaders_header += "#define ENABLE_WAVING_WATER 0\n"; } + shaders_header += "#define ENABLE_WAVING_LEAVES "; if (g_settings->getBool("enable_waving_leaves")) - shaders_header += "#define ENABLE_WAVING_LEAVES\n"; + shaders_header += "1\n"; + else + shaders_header += "0\n"; + shaders_header += "#define ENABLE_WAVING_PLANTS "; if (g_settings->getBool("enable_waving_plants")) - shaders_header += "#define ENABLE_WAVING_PLANTS\n"; + shaders_header += "1\n"; + else + shaders_header += "0\n"; if(pixel_program != "") pixel_program = shaders_header + pixel_program; @@ -772,11 +782,10 @@ ShaderInfo generate_shader(std::string name, IrrlichtDevice *device, scene::EPT_TRIANGLES, // Geometry shader input scene::EPT_TRIANGLE_STRIP, // Geometry shader output 0, // Support maximum number of vertices - callback, // Set-constant callback - shaderinfo.material, // Base material - 1 // Userdata passed to callback + callback, // Set-constant callback + shaderinfo.base_material, // Base material + 1 // Userdata passed to callback ); - if(shadermat == -1){ errorstream<<"generate_shader(): " "failed to generate \""<