51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <fstream>
+#include <iterator>
#include "shader.h"
#include "irrlichttypes_extrabloated.h"
#include "debug.h"
-#include "main.h" // for g_settings
#include "filesys.h"
#include "util/container.h"
#include "util/thread.h"
#include "settings.h"
-#include <iterator>
#include <ICameraSceneNode.h>
#include <IGPUProgrammingServices.h>
#include <IMaterialRenderer.h>
class SourceShaderCache
{
public:
- void insert(const std::string &name_of_shader,
- const std::string &filename,
- const std::string &program,
- bool prefer_local)
+ void insert(const std::string &name_of_shader, const std::string &filename,
+ const std::string &program, bool prefer_local)
{
std::string combined = name_of_shader + DIR_DELIM + filename;
// Try to use local shader instead if asked to
}
m_programs[combined] = program;
}
+
std::string get(const std::string &name_of_shader,
- const std::string &filename)
+ const std::string &filename)
{
std::string combined = name_of_shader + DIR_DELIM + filename;
- std::map<std::string, std::string>::iterator n;
- n = m_programs.find(combined);
- if(n != m_programs.end())
+ StringMap::iterator n = m_programs.find(combined);
+ if (n != m_programs.end())
return n->second;
return "";
}
+
// Primarily fetches from cache, secondarily tries to read from filesystem
std::string getOrLoad(const std::string &name_of_shader,
- const std::string &filename)
+ const std::string &filename)
{
std::string combined = name_of_shader + DIR_DELIM + filename;
- std::map<std::string, std::string>::iterator n;
- n = m_programs.find(combined);
- if(n != m_programs.end())
+ StringMap::iterator n = m_programs.find(combined);
+ if (n != m_programs.end())
return n->second;
std::string path = getShaderPath(name_of_shader, filename);
- if(path == ""){
- infostream<<"SourceShaderCache::getOrLoad(): No path found for \""
- <<combined<<"\""<<std::endl;
+ if (path == "") {
+ infostream << "SourceShaderCache::getOrLoad(): No path found for \""
+ << combined << "\"" << std::endl;
return "";
}
- infostream<<"SourceShaderCache::getOrLoad(): Loading path \""<<path
- <<"\""<<std::endl;
+ infostream << "SourceShaderCache::getOrLoad(): Loading path \""
+ << path << "\"" << std::endl;
std::string p = readFile(path);
- if(p != ""){
+ if (p != "") {
m_programs[combined] = p;
return p;
}
return "";
}
private:
- std::map<std::string, std::string> m_programs;
+ StringMap m_programs;
+
std::string readFile(const std::string &path)
{
std::ifstream is(path.c_str(), std::ios::binary);
virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 userData)
{
video::IVideoDriver *driver = services->getVideoDriver();
- assert(driver);
+ sanity_check(driver != NULL);
bool is_highlevel = userData;
bool is_highlevel)
{
video::IVideoDriver *driver = services->getVideoDriver();
- assert(driver);
+ sanity_check(driver);
// set inverted world matrix
core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
The id 0 points to a null shader. Its material is EMT_SOLID.
*/
- u32 getShaderIdDirect(const std::string &name,
+ 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 id.
+ 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.
*/
-
+
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();
// The first position contains a dummy shader.
std::vector<ShaderInfo> m_shaderinfo_cache;
// The former container is behind this mutex
- JMutex m_shaderinfo_cache_mutex;
+ Mutex m_shaderinfo_cache_mutex;
// Queued shader fetches (to be processed by the main thread)
RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
ShaderSource::ShaderSource(IrrlichtDevice *device):
m_device(device)
{
- assert(m_device);
+ assert(m_device); // Pre-condition
m_shader_callback = new ShaderCallback(this, "default");
- m_main_thread = get_current_thread_id();
+ m_main_thread = thr_get_current_thread_id();
// Add a dummy ShaderInfo as the first index, named ""
m_shaderinfo_cache.push_back(ShaderInfo());
ShaderSource::~ShaderSource()
{
for (std::vector<IShaderConstantSetter*>::iterator iter = m_global_setters.begin();
- iter != m_global_setters.end(); iter++) {
+ iter != m_global_setters.end(); ++iter) {
delete *iter;
}
m_global_setters.clear();
}
}
-u32 ShaderSource::getShader(const std::string &name,
+u32 ShaderSource::getShader(const std::string &name,
const u8 material_type, const u8 drawtype)
{
/*
Get shader
*/
- if(get_current_thread_id() == m_main_thread){
+ if (thr_is_current_thread(m_main_thread)) {
return getShaderIdDirect(name, material_type, drawtype);
} else {
/*errorstream<<"getShader(): Queued: name=\""<<name<<"\""<<std::endl;*/
/*
This method generates all the shaders
*/
-u32 ShaderSource::getShaderIdDirect(const std::string &name,
+u32 ShaderSource::getShaderIdDirect(const std::string &name,
const u8 material_type, const u8 drawtype)
{
//infostream<<"getShaderIdDirect(): name=\""<<name<<"\""<<std::endl;
/*
Calling only allowed from main thread
*/
- if(get_current_thread_id() != m_main_thread){
+ if (!thr_is_current_thread(m_main_thread)) {
errorstream<<"ShaderSource::getShaderIdDirect() "
"called not from main thread"<<std::endl;
return 0;
Add shader to caches (add dummy shaders too)
*/
- JMutexAutoLock lock(m_shaderinfo_cache_mutex);
+ MutexAutoLock lock(m_shaderinfo_cache_mutex);
u32 id = m_shaderinfo_cache.size();
m_shaderinfo_cache.push_back(info);
ShaderInfo ShaderSource::getShaderInfo(u32 id)
{
- JMutexAutoLock lock(m_shaderinfo_cache_mutex);
+ MutexAutoLock lock(m_shaderinfo_cache_mutex);
if(id >= m_shaderinfo_cache.size())
return ShaderInfo();
void ShaderSource::processQueue()
{
-
+
}
"name_of_shader=\""<<name_of_shader<<"\", "
"filename=\""<<filename<<"\""<<std::endl;*/
- assert(get_current_thread_id() == m_main_thread);
+ sanity_check(thr_is_current_thread(m_main_thread));
m_sourcecache.insert(name_of_shader, filename, program, true);
}
void ShaderSource::rebuildShaders()
{
- JMutexAutoLock lock(m_shaderinfo_cache_mutex);
+ MutexAutoLock lock(m_shaderinfo_cache_mutex);
/*// Oh well... just clear everything, they'll load sometime.
m_shaderinfo_cache.clear();
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
break;
}
-
+
bool enable_shaders = g_settings->getBool("enable_shaders");
if(!enable_shaders)
return shaderinfo;
video::IVideoDriver* driver = device->getVideoDriver();
- assert(driver);
+ sanity_check(driver);
video::IGPUProgrammingServices *gpu = driver->getGPUProgrammingServices();
if(!gpu){
"NDT_FIRELIKE",
"NDT_GLASSLIKE_FRAMED_OPTIONAL"
};
-
+
for (int i = 0; i < 14; i++){
shaders_header += "#define ";
shaders_header += drawTypes[i];
shaders_header += itos(drawtype);
shaders_header += "\n";
- if (g_settings->getBool("generate_normalmaps")){
- shaders_header += "#define GENERATE_NORMALMAPS\n";
- shaders_header += "#define NORMALMAPS_STRENGTH ";
- shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
- shaders_header += "\n";
- float sample_step;
- int smooth = (int)g_settings->getFloat("normalmaps_smooth");
- switch (smooth){
- case 0:
- sample_step = 0.0078125; // 1.0 / 128.0
- break;
- case 1:
- sample_step = 0.00390625; // 1.0 / 256.0
- break;
- case 2:
- sample_step = 0.001953125; // 1.0 / 512.0
- break;
- default:
- sample_step = 0.0078125;
- break;
- }
- shaders_header += "#define SAMPLE_STEP ";
- shaders_header += ftos(sample_step);
- shaders_header += "\n";
+ if (g_settings->getBool("generate_normalmaps")) {
+ shaders_header += "#define GENERATE_NORMALMAPS 1\n";
+ } else {
+ shaders_header += "#define GENERATE_NORMALMAPS 0\n";
+ }
+ shaders_header += "#define NORMALMAPS_STRENGTH ";
+ shaders_header += ftos(g_settings->getFloat("normalmaps_strength"));
+ shaders_header += "\n";
+ float sample_step;
+ int smooth = (int)g_settings->getFloat("normalmaps_smooth");
+ switch (smooth){
+ case 0:
+ sample_step = 0.0078125; // 1.0 / 128.0
+ break;
+ case 1:
+ sample_step = 0.00390625; // 1.0 / 256.0
+ break;
+ case 2:
+ sample_step = 0.001953125; // 1.0 / 512.0
+ break;
+ default:
+ sample_step = 0.0078125;
+ break;
}
+ shaders_header += "#define SAMPLE_STEP ";
+ shaders_header += ftos(sample_step);
+ shaders_header += "\n";
if (g_settings->getBool("enable_bumpmapping"))
shaders_header += "#define ENABLE_BUMPMAPPING\n";
if (g_settings->getBool("enable_parallax_occlusion")){
+ int mode = g_settings->getFloat("parallax_occlusion_mode");
+ float scale = g_settings->getFloat("parallax_occlusion_scale");
+ float bias = g_settings->getFloat("parallax_occlusion_bias");
+ int iterations = g_settings->getFloat("parallax_occlusion_iterations");
shaders_header += "#define ENABLE_PARALLAX_OCCLUSION\n";
+ shaders_header += "#define PARALLAX_OCCLUSION_MODE ";
+ shaders_header += itos(mode);
+ shaders_header += "\n";
shaders_header += "#define PARALLAX_OCCLUSION_SCALE ";
- shaders_header += ftos(g_settings->getFloat("parallax_occlusion_scale"));
+ shaders_header += ftos(scale);
shaders_header += "\n";
shaders_header += "#define PARALLAX_OCCLUSION_BIAS ";
- shaders_header += ftos(g_settings->getFloat("parallax_occlusion_bias"));
+ shaders_header += ftos(bias);
+ shaders_header += "\n";
+ shaders_header += "#define PARALLAX_OCCLUSION_ITERATIONS ";
+ shaders_header += itos(iterations);
shaders_header += "\n";
}
+ shaders_header += "#define USE_NORMALMAPS ";
if (g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion"))
- shaders_header += "#define USE_NORMALMAPS\n";
+ shaders_header += "1\n";
+ else
+ shaders_header += "0\n";
if (g_settings->getBool("enable_waving_water")){
shaders_header += "#define ENABLE_WAVING_WATER 1\n";
shaders_header += "#define ENABLE_WAVING_LEAVES ";
if (g_settings->getBool("enable_waving_leaves"))
shaders_header += "1\n";
- else
+ else
shaders_header += "0\n";
- shaders_header += "#define ENABLE_WAVING_PLANTS ";
+ shaders_header += "#define ENABLE_WAVING_PLANTS ";
if (g_settings->getBool("enable_waving_plants"))
shaders_header += "1\n";
else
vertex_program = shaders_header + vertex_program;
if(geometry_program != "")
geometry_program = shaders_header + geometry_program;
-
// Call addHighLevelShaderMaterial() or addShaderMaterial()
const c8* vertex_program_ptr = 0;
const c8* pixel_program_ptr = 0;