ShaderPtr Shader::createSimpleConstantShader( float r, float g, float b ) { ShaderPtr shader = Shader::create().attachPS( base::path( "base" ) + "/data/glsl/constant.ps.glsl").attachVS( base::path( "base" ) + "/data/glsl/constant.vs.glsl"); shader->setUniform( "color", math::Vec3f(r, g, b) ); return shader; }
void GL::Program::initFromSource(const char * data) { if (!m_Manager) throw std::runtime_error("resource manager is not available."); std::vector<std::string> lines; for (const char * p = data; ; ) { const char * end = strchr(p, '\n'); if (end) { size_t length = end - p; while (length > 0 && iswhite(p[length - 1])) --length; lines.push_back(std::string(p, length) + "\n"); p = end + 1; } else { size_t length = strlen(p); while (length > 0 && iswhite(p[length - 1])) --length; lines.push_back(std::string(p, length) + "\n"); break; } } std::vector<const char *> vertex; std::vector<const char *> fragment; vertex.reserve(lines.size()); fragment.reserve(lines.size()); bool hasVertex = false, hasFragment = 0; Enum type = GL::NONE; for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it) { if (it->c_str()[0] != '%') { vertex.push_back(type == GL::NONE || type == GL::VERTEX_SHADER ? it->c_str() : ""); fragment.push_back(type == GL::NONE || type == GL::FRAGMENT_SHADER ? it->c_str() : ""); } else { const std::string & str = *it; const char * file = nullptr; vertex.push_back(""); fragment.push_back(""); if (str.length() >= 7 && !memcmp(str.c_str(), "%vertex", 7)) { type = GL::VERTEX_SHADER; file = str.c_str() + 7; } else if (str.length() >= 9 && !memcmp(str.c_str(), "%fragment", 9)) { type = GL::FRAGMENT_SHADER; file = str.c_str() + 9; } else { std::stringstream ss; ss << "invalid directive '" << str << "' in the vertex program."; throw std::runtime_error(ss.str()); } if (file) { while (iswhite(*file)) ++file; if (!*file) file = nullptr; } if (!file) { if (type == GL::VERTEX_SHADER) hasVertex = true; else if (type == GL::FRAGMENT_SHADER) hasFragment = true; } else { std::string filename(file); if (filename.length() > 0 && filename[filename.length() - 1] == '\n') filename.resize(filename.length() - 1); attachShader(m_Manager->getShader(type, filename)); } } } if (hasVertex) { ShaderPtr shader = m_Manager->createShader(GL::VERTEX_SHADER); shader->initFromSource(vertex); attachShader(shader); } if (hasFragment) { ShaderPtr shader = m_Manager->createShader(GL::FRAGMENT_SHADER); shader->initFromSource(fragment); attachShader(shader); } link(); }
bool ShaderProgram::addShader(const ShaderPtr& shader) { glAttachShader(m_programId, shader->getShaderId()); m_linked = false; m_shaders.push_back(shader); return true; }
ShaderPtr ShaderLibrary::CreateShader (const ShaderDesc& desc, const LogFunction& error_log) { try { //проверка корректности аргументов if (!desc.name) throw xtl::make_null_argument_exception ("", "desc.name"); if (!desc.source_code) throw xtl::make_null_argument_exception ("", "desc.source_code"); if (!desc.source_code_size) throw xtl::make_null_argument_exception ("", "desc.source_code_size"); if (!desc.profile) throw xtl::make_null_argument_exception ("", "desc.profile"); const char* options = desc.options ? desc.options : ""; ShaderType type = (ShaderType)-1; struct Profile2ShaderType { const char* profile; ShaderType type; const char* dx_profile; }; static const Profile2ShaderType type_map [] = { {"hlsl.vs", ShaderType_Vertex, "vs_4_0"}, {"hlsl.ps", ShaderType_Pixel, "ps_4_0"}, {"hlsl.gs", ShaderType_Geometry, "gs_4_0"}, {"hlsl.hs", ShaderType_Hull, "hs_4_0"}, {"hlsl.ds", ShaderType_Domain, "ds_4_0"}, {"hlsl.cs", ShaderType_Compute, "cs_4_0"}, }; static const size_t type_map_size = sizeof (type_map) / sizeof (*type_map); const char* dx_profile = ""; for (size_t i=0; i<type_map_size; i++) if (!strcmp (type_map [i].profile, desc.profile)) { type = type_map [i].type; dx_profile = type_map [i].dx_profile; break; } if (type == (ShaderType)-1) throw xtl::make_argument_exception ("", "desc.profile", desc.profile, "Unknown shader profile"); //формирование хэша для поиска в библиотеке size_t source_code_size = desc.source_code_size == (size_t)-1 ? strlen (desc.source_code) : desc.source_code_size, hash = common::crc32 (desc.source_code, source_code_size, common::strhash (options)); //поиск уже существующего шейдера ShaderMap::iterator iter = shaders.find (hash); if (iter != shaders.end ()) return iter->second; //создание нового шейдера ShaderCodePtr code (new ShaderCode (GetDeviceManager (), desc.name, dx_profile, desc.source_code, source_code_size, options, error_log), false); ShaderPtr shader (new Shader (type, code, *this), false); //регистрация шейдера в библиотеке shader->RegisterDestroyHandler (xtl::bind (&ShaderLibrary::RemoveShaderByHash, this, hash), GetTrackable ()); shaders.insert_pair (hash, shader.get ()); return shader; } catch (xtl::exception& e) { e.touch ("render::low_level::dx11::ShaderLibrary::CreateShader"); throw; } }
ShaderPtr Shader::from_file(GLenum type, std::string const& filename, std::vector<std::string> const& defines) { std::ifstream in(filename); if (!in) { throw std::runtime_error((boost::format("%s: failed to open file") % filename).str()); } else { std::vector<std::string> sources; // add version declaration #ifdef HAVE_OPENGLES2 sources.emplace_back("#version 100\n"); #else sources.emplace_back("#version 330 core\n"); #endif { // add custom defines std::ostringstream os; for(auto const& def : defines) { auto equal_pos = def.find('='); if (equal_pos == std::string::npos) { os << "#define " << def << '\n'; } else { os << "#define " << def.substr(0, equal_pos) << ' ' << def.substr(equal_pos+1) << '\n'; } } sources.emplace_back(os.str()); } { // add the actual source file std::regex include_rx("^#\\s*include\\s+\"([^\"]*)\".*$"); int line_count = 0; std::ostringstream os; std::string line; while(std::getline(in, line)) { std::smatch rx_results; if (std::regex_match(line, rx_results, include_rx)) { boost::filesystem::path include_filename(rx_results[1]); if (include_filename.is_absolute()) { include_file(include_filename.string(), os); } else { include_file((boost::filesystem::path(filename).parent_path() / include_filename).string(), os); } os << "#line " << line_count << '\n'; } else { os << line << '\n'; } line_count += 1; } sources.emplace_back(os.str()); } ShaderPtr shader = std::make_shared<Shader>(type); shader->source(sources); shader->compile(); if (!shader->get_compile_status()) { throw std::runtime_error((boost::format("%s: error:\n %s") % filename % shader->get_info_log()).str()); } //log_debug("%s: shader compile successful", filename); return shader; } }
bool GLSprite::DrawShaped( const math::Vector2 &v2Pos, const math::Vector2 &v2Size, const Color& color0, const Color& color1, const Color& color2, const Color& color3, const float angle) { if (v2Size == math::Vector2(0,0)) { return true; } // compute flip parameters that will be sent to the VS math::Vector2 flipMul, flipAdd; GetFlipShaderParameters(flipAdd, flipMul); // centralizes the sprite according to the origin math::Vector2 v2Center = m_normalizedOrigin * v2Size; GLVideo* video = m_video.lock().get(); ShaderPtr pCurrentVS = video->GetVertexShader(); math::Matrix4x4 mRot; if (angle != 0.0f) mRot = math::RotateZ(math::DegreeToRadian(angle)); pCurrentVS->SetMatrixConstant("rotationMatrix", mRot); // rounds up the final position to avoid alpha distortion math::Vector2 v2FinalPos; if (video->IsRoundingUpPosition()) { v2FinalPos.x = floor(v2Pos.x); v2FinalPos.y = floor(v2Pos.y); } else { v2FinalPos = v2Pos; } pCurrentVS->SetConstant("size", v2Size); pCurrentVS->SetConstant("entityPos", v2FinalPos); pCurrentVS->SetConstant("center", v2Center); pCurrentVS->SetConstant("flipMul", flipMul); pCurrentVS->SetConstant("flipAdd", flipAdd); pCurrentVS->SetConstant("bitmapSize", GetBitmapSizeF()); pCurrentVS->SetConstant("scroll", GetScroll()); pCurrentVS->SetConstant("multiply", GetMultiply()); const bool setCameraPos = pCurrentVS->ConstantExist("cameraPos"); if (setCameraPos) pCurrentVS->SetConstant("cameraPos", video->GetCameraPos()); if (m_rect.size.x == 0 || m_rect.size.y == 0) { pCurrentVS->SetConstant("rectSize", GetBitmapSizeF()); pCurrentVS->SetConstant("rectPos", 0, 0); } else { pCurrentVS->SetConstant("rectSize", m_rect.size); pCurrentVS->SetConstant("rectPos", m_rect.pos); } pCurrentVS->SetConstant("color0", color0); pCurrentVS->SetConstant("color1", color1); pCurrentVS->SetConstant("color2", color2); pCurrentVS->SetConstant("color3", color3); if (pCurrentVS->ConstantExist("depth")) pCurrentVS->SetConstant("depth", video->GetSpriteDepth()); // apply textures according to the rendering mode (pixel shaded or not) ShaderPtr pCurrentPS = video->GetPixelShader(); SetDiffuseTexture(pCurrentPS); pCurrentVS->SetShader(); // draw the one-pixel-quad applying the vertex shader video->GetRectRenderer().Draw(m_rectMode); return true; }