ogre_material_generator.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <rve_render_server/ogre_material_generator.h>
00031 #include <rve_render_server/material.h>
00032 #include <rve_render_server/texture.h>
00033 #include <rve_render_server/render_target.h>
00034 #include <rve_render_server/render_texture.h>
00035 #include <rve_render_server/renderer.h>
00036 #include <rve_render_server/texture_resource.h>
00037 #include <rve_msgs/Material.h>
00038 
00039 #include <rve_common/parse_resource_uri.h>
00040 
00041 #include <resource_retriever/retriever.h>
00042 #include <boost/filesystem.hpp>
00043 
00044 #include <sstream>
00045 
00046 #include <OGRE/OgreMaterialManager.h>
00047 #include <OGRE/OgreTextureManager.h>
00048 #include <OGRE/OgreTexture.h>
00049 #include <OGRE/OgreGpuProgramManager.h>
00050 #include <OGRE/OgreHighLevelGpuProgramManager.h>
00051 #include <OGRE/OgreTechnique.h>
00052 #include <OGRE/OgrePass.h>
00053 
00054 namespace fs = boost::filesystem;
00055 
00056 namespace rve_render_server
00057 {
00058 
00059 void loadTexture(const std::string& resource_path)
00060 {
00061   if (!Ogre::TextureManager::getSingleton().resourceExists(resource_path))
00062   {
00063     resource_retriever::Retriever retriever;
00064     resource_retriever::MemoryResource res;
00065     try
00066     {
00067       res = retriever.get(resource_path);
00068     }
00069     catch (resource_retriever::Exception& e)
00070     {
00071       ROS_ERROR("%s", e.what());
00072     }
00073 
00074     if (res.size != 0)
00075     {
00076       Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(res.data.get(), res.size));
00077       Ogre::Image image;
00078       std::string extension = fs::extension(fs::path(resource_path));
00079 
00080       if (extension[0] == '.')
00081       {
00082         extension = extension.substr(1, extension.size() - 1);
00083       }
00084 
00085       try
00086       {
00087         image.load(stream, extension);
00088         Ogre::TextureManager::getSingleton().loadImage(resource_path, ROS_PACKAGE_NAME, image);
00089       }
00090       catch (Ogre::Exception& e)
00091       {
00092         ROS_ERROR("Could not load texture [%s]: %s", resource_path.c_str(), e.what());
00093       }
00094     }
00095   }
00096 }
00097 
00098 void applyUniforms(const Ogre::HighLevelGpuProgramPtr& program, const V_ShaderUniform& uniforms)
00099 {
00100   const Ogre::GpuProgramParametersSharedPtr& params = program->getDefaultParameters();
00101   V_ShaderUniform::const_iterator it = uniforms.begin();
00102   V_ShaderUniform::const_iterator end = uniforms.end();
00103   for (; it != end; ++it)
00104   {
00105     const ShaderUniform& uniform = *it;
00106     try
00107     {
00108       params->setNamedAutoConstant(uniform.name, (Ogre::GpuProgramParameters::AutoConstantType)uniform.auto_constant_type, uniform.extra);
00109     }
00110     catch (Ogre::Exception& e)
00111     {
00112       ROS_DEBUG("%s", e.what());
00113     }
00114   }
00115 
00116   try
00117   {
00118     params->setNamedAutoConstant("worldviewproj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
00119   }
00120   catch (Ogre::Exception&)
00121   {}
00122 
00123   try
00124   {
00125     params->setNamedAutoConstant("worldview", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
00126   }
00127   catch (Ogre::Exception&)
00128   {}
00129 }
00130 
00131 static void emitInputs(std::stringstream& ss, const V_ShaderParameter& inputs, bool& first_parameter, bool geom_shader)
00132 {
00133   V_ShaderParameter::const_iterator it = inputs.begin();
00134   V_ShaderParameter::const_iterator end = inputs.end();
00135   for (; it != end; ++it)
00136   {
00137     const ShaderParameter& param = *it;
00138     if (!first_parameter)
00139     {
00140       ss << " ,";
00141     }
00142 
00143     first_parameter = false;
00144     if (geom_shader)
00145     {
00146       ss << " AttribArray<" << param.type << "> in_" << param.name << " : " << param.semantic << std::endl;
00147     }
00148     else
00149     {
00150       ss << " " << param.type << " in_" << param.name << " : " << param.semantic << std::endl;
00151     }
00152   }
00153 }
00154 
00155 static void emitOutputs(std::stringstream& ss, const V_ShaderParameter& outputs, bool& first_parameter)
00156 {
00157   V_ShaderParameter::const_iterator it = outputs.begin();
00158   V_ShaderParameter::const_iterator end = outputs.end();
00159   for (; it != end; ++it)
00160   {
00161     const ShaderParameter& param = *it;
00162 
00163     if (!first_parameter)
00164     {
00165       ss << " ,";
00166     }
00167 
00168     first_parameter = false;
00169 
00170     ss << " out " << param.type << " out_" << param.name << " : " << param.semantic << std::endl;
00171   }
00172 }
00173 
00174 static void emitUniforms(std::stringstream& ss, const V_ShaderUniform& uniforms, bool& first_parameter)
00175 {
00176   V_ShaderUniform::const_iterator it = uniforms.begin();
00177   V_ShaderUniform::const_iterator end = uniforms.end();
00178   for (; it != end; ++it)
00179   {
00180     const ShaderUniform& uniform = *it;
00181 
00182     if (!first_parameter)
00183     {
00184       ss << " ,";
00185     }
00186 
00187     first_parameter = false;
00188 
00189     ss << " uniform " << uniform.type << " " << uniform.name << std::endl;
00190   }
00191 }
00192 
00193 static void emitSamplers(std::stringstream& ss, const V_ShaderSampler& samplers, bool& first_parameter)
00194 {
00195   V_ShaderSampler::const_iterator it = samplers.begin();
00196   V_ShaderSampler::const_iterator end = samplers.end();
00197   for (; it != end; ++it)
00198   {
00199     const ShaderSampler& samp = *it;
00200 
00201     if (!first_parameter)
00202     {
00203       ss << " ,";
00204     }
00205 
00206     first_parameter = false;
00207 
00208     ss << " uniform sampler sampler_" << samp.name << " : register(s" << samp.reg << ")" << std::endl;
00209   }
00210 }
00211 
00212 static void emitIncludes(std::stringstream& ss, const V_string& includes)
00213 {
00214   V_string::const_iterator it = includes.begin();
00215   V_string::const_iterator end = includes.end();
00216   for (; it != end; ++it)
00217   {
00218     ss << "#include \"" << *it << "\"" << std::endl;
00219   }
00220 }
00221 
00222 Ogre::GpuProgramPtr generateVertexShader(const ShaderDefinition& def, const std::string& base_name)
00223 {
00224   std::stringstream ss;
00225 
00226   emitIncludes(ss, def.includes);
00227   ss << std::endl;
00228   ss << "void vp(" << std::endl;
00229   bool first_parameter = true;
00230   emitInputs(ss, def.inputs, first_parameter, false);
00231   emitOutputs(ss, def.outputs, first_parameter);
00232   emitUniforms(ss, def.uniforms, first_parameter);
00233   emitSamplers(ss, def.samplers, first_parameter);
00234 
00235   ss << ")\n";
00236   ss << "{\n";
00237 
00238   ss << def.body;
00239   ss << "\n";
00240 
00241   ss << "}" << std::endl;
00242 
00243   std::string program_source = ss.str();
00244   std::string program_name = base_name + "_VP";
00245 
00246   ROS_DEBUG("%s", program_source.c_str());
00247 
00248   // Create shader object
00249   Ogre::HighLevelGpuProgramPtr program =
00250       Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(program_name, ROS_PACKAGE_NAME, "cg",
00251                                                                      Ogre::GPT_VERTEX_PROGRAM);
00252   program->setSource(program_source);
00253   program->setParameter("entry_point", "vp");
00254   program->setParameter("profiles", "vs_1_1 arbvp1");
00255 
00256   applyUniforms(program, def.uniforms);
00257 
00258   program->load();
00259 
00260   return Ogre::GpuProgramPtr(program);
00261 }
00262 
00263 Ogre::GpuProgramPtr generateFragmentShader(const ShaderDefinition& in_def, bool transparent, bool shaded, const std::string& base_name)
00264 {
00265   ShaderDefinition def = in_def;
00266   std::stringstream ss;
00267 
00268   if (transparent)
00269   {
00270     def.include("camera_light.cg");
00271   }
00272 
00273   def.output("float4", "color0", "COLOR0");
00274   def.output("float4", "color1", "COLOR1");
00275   def.uniform("float", "far_distance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
00276 
00277   emitIncludes(ss, def.includes);
00278   ss << std::endl;
00279   ss << "void fp(" << std::endl;
00280   bool first_parameter = true;
00281   emitInputs(ss, def.inputs, first_parameter, false);
00282   emitOutputs(ss, def.outputs, first_parameter);
00283   emitUniforms(ss, def.uniforms, first_parameter);
00284   emitSamplers(ss, def.samplers, first_parameter);
00285 
00286   ss << " )\n";
00287   ss << "{\n";
00288 
00289   ss << def.body;
00290   ss << "\n";
00291 
00292   if (transparent)
00293   {
00294     if (shaded)
00295     {
00296       ss << "float3 gooch_color = camera_light(color.rgb, normal, float3(0.0, 0.0, 1.0));\n";
00297       ss << "out_color0 = float4(gooch_color * color.a, color.a);\n";
00298     }
00299     else
00300     {
00301       ss << "out_color0 = float4(color.rgb * color.a, color.a);";
00302     }
00303 
00304     ss << "out_color1 = float4(1.0, 0.0, 0.0, 0.0);\n";
00305   }
00306   else
00307   {
00308     ss << " out_color0 = float4(color.rgb, 1.0);\n";
00309     if (!shaded)
00310     {
00311       ss << " out_color0.a = 0.0;";
00312     }
00313 
00314     //ss << " out_color0 = float4(in_uv0, 0.0, 1.0);\n";
00315     ss << " out_color1.rgb = normal;\n";
00316     ss << " out_color1.a = length(in_view_pos) / far_distance;\n";
00317   }
00318 
00319   ss << "}" << std::endl;
00320 
00321   std::string program_source = ss.str();
00322   std::string program_name = base_name + "_FP";
00323 
00324   ROS_DEBUG("%s", program_source.c_str());
00325 
00326   // Create shader object
00327   Ogre::HighLevelGpuProgramPtr program =
00328       Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(program_name, ROS_PACKAGE_NAME, "cg",
00329                                                                      Ogre::GPT_FRAGMENT_PROGRAM);
00330   program->setSource(program_source);
00331   program->setParameter("entry_point", "fp");
00332   program->setParameter("profiles", "ps_2_0 arbfp1");
00333 
00334   applyUniforms(program, def.uniforms);
00335 
00336   program->load();
00337 
00338   return Ogre::GpuProgramPtr(program);
00339 }
00340 
00341 Ogre::GpuProgramPtr generatePickingFragmentShader(const ShaderDefinition& in_def, const std::string& base_name)
00342 {
00343   ShaderDefinition def = in_def;
00344   std::stringstream ss;
00345 
00346   def.output("float4", "object_id", "COLOR0");
00347   def.output("float4", "object_extra", "COLOR1");
00348 
00349   emitIncludes(ss, def.includes);
00350   ss << std::endl;
00351   ss << "void fp(" << std::endl;
00352   bool first_parameter = true;
00353   emitInputs(ss, def.inputs, first_parameter, false);
00354   emitOutputs(ss, def.outputs, first_parameter);
00355   emitUniforms(ss, def.uniforms, first_parameter);
00356   emitSamplers(ss, def.samplers, first_parameter);
00357 
00358   ss << " )\n";
00359   ss << "{\n";
00360 
00361   if (!def.body.empty())
00362   {
00363     ss << def.body;
00364     ss << "\n";
00365   }
00366   else
00367   {
00368     ss << " float4 object_id = float4(0.0, 0.0, 0.0, 0.0);\n";
00369     ss << " float4 object_extra = float4(0.0, 0.0, 0.0, 0.0);\n";
00370   }
00371 
00372   ss << " out_object_id = object_id;\n";
00373   ss << " out_object_extra = object_extra;\n";
00374 
00375   ss << "}" << std::endl;
00376 
00377   std::string program_source = ss.str();
00378   std::string program_name = base_name + "_FP_Pick";
00379 
00380   ROS_DEBUG("%s", program_source.c_str());
00381 
00382   // Create shader object
00383   Ogre::HighLevelGpuProgramPtr program =
00384       Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(program_name, ROS_PACKAGE_NAME, "cg",
00385                                                                      Ogre::GPT_FRAGMENT_PROGRAM);
00386   program->setSource(program_source);
00387   program->setParameter("entry_point", "fp");
00388   program->setParameter("profiles", "ps_2_0 arbfp1");
00389 
00390   applyUniforms(program, def.uniforms);
00391 
00392   program->load();
00393 
00394   return Ogre::GpuProgramPtr(program);
00395 }
00396 
00397 Ogre::GpuProgramPtr generateGeometryShader(const ShaderDefinition& def, const std::string& base_name)
00398 {
00399   std::stringstream ss;
00400 
00401   emitIncludes(ss, def.includes);
00402   ss << std::endl;
00403   ss << def.geom_input << " " << def.geom_output << " void gp(" << std::endl;
00404   bool first_parameter = true;
00405   emitInputs(ss, def.inputs, first_parameter, true);
00406   emitUniforms(ss, def.uniforms, first_parameter);
00407   emitSamplers(ss, def.samplers, first_parameter);
00408 
00409   ss << ")\n";
00410   ss << "{\n";
00411 
00412   ss << def.body;
00413   ss << "\n";
00414 
00415   ss << "}" << std::endl;
00416 
00417   std::string program_source = ss.str();
00418   std::string program_name = base_name + "_GP";
00419 
00420   ROS_DEBUG("%s", program_source.c_str());
00421 
00422   // Create shader object
00423   Ogre::HighLevelGpuProgramPtr program =
00424       Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(program_name, ROS_PACKAGE_NAME, "cg",
00425                                                                      Ogre::GPT_GEOMETRY_PROGRAM);
00426   program->setSource(program_source);
00427   program->setParameter("entry_point", "gp");
00428   program->setParameter("profiles", "gpu_gp gp4_gp");
00429 
00430   applyUniforms(program, def.uniforms);
00431 
00432   program->load();
00433 
00434   return Ogre::GpuProgramPtr(program);
00435 }
00436 
00437 Ogre::MaterialPtr generateOgreMaterial(const MaterialDefinition& def)
00438 {
00439   if (Ogre::MaterialManager::getSingleton().resourceExists(def.name))
00440   {
00441     return Ogre::MaterialManager::getSingleton().getByName(def.name);
00442   }
00443 
00444   Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(def.name, ROS_PACKAGE_NAME);
00445 
00446   if (def.transparent)
00447   {
00448     mat->getTechnique(0)->setSchemeName("WeightedAverageAlpha");
00449     mat->setSceneBlending(Ogre::SBT_ADD);
00450     mat->setDepthWriteEnabled(false);
00451   }
00452   else
00453   {
00454     mat->getTechnique(0)->setSchemeName("GBuffer");
00455   }
00456 
00457   Ogre::Pass* pass = mat->getTechnique(0)->getPass(0);
00458   pass->setLightingEnabled(false);
00459 
00460   V_string::const_iterator it = def.textures.begin();
00461   V_string::const_iterator end = def.textures.end();
00462   for (; it != end; ++it)
00463   {
00464     const std::string& tex_path = *it;
00465     Ogre::TextureUnitState* tu = pass->createTextureUnitState();
00466 
00467     std::string tex_name = tex_path;
00468 
00469     if (!lookupTextureResource(tex_path, tex_name))
00470     {
00471       loadTexture(tex_path);
00472     }
00473 
00474     tu->setTextureName(tex_name);
00475   }
00476 
00477   Ogre::GpuProgramPtr vertex_program = generateVertexShader(def.vertex_def, def.name);
00478   Ogre::GpuProgramPtr fragment_program = generateFragmentShader(def.fragment_def, def.transparent, !def.disable_shading, def.name);
00479   pass->setVertexProgram(vertex_program->getName());
00480   pass->setFragmentProgram(fragment_program->getName());
00481 
00482   Ogre::GpuProgramPtr geometry_program;
00483   if (def.has_geometry_shader)
00484   {
00485     geometry_program = generateGeometryShader(def.geometry_def, def.name);
00486     pass->setGeometryProgram(geometry_program->getName());
00487   }
00488 
00489   {
00490     // Generate the picking technique
00491     Ogre::GpuProgramPtr picking_fragment_program = generatePickingFragmentShader(def.picking_fragment_def, def.name);
00492     Ogre::Technique* tech = mat->createTechnique();
00493     tech->setSchemeName("Pick");
00494     Ogre::Pass* pass = tech->createPass();
00495     pass->setVertexProgram(vertex_program->getName());
00496     pass->setFragmentProgram(picking_fragment_program->getName());
00497 
00498     if (!geometry_program.isNull())
00499     {
00500       pass->setGeometryProgram(geometry_program->getName());
00501     }
00502 
00503     pass->setLightingEnabled(false);
00504   }
00505 
00506   Ogre::CullingMode cull_mode;
00507   switch (def.cull_mode)
00508   {
00509     case rve_msgs::Material::CULL_COUNTERCLOCKWISE:
00510       cull_mode = Ogre::CULL_ANTICLOCKWISE;
00511       break;
00512     case rve_msgs::Material::CULL_CLOCKWISE:
00513       cull_mode = Ogre::CULL_CLOCKWISE;
00514       break;
00515     default:
00516       cull_mode = Ogre::CULL_NONE;
00517   }
00518   mat->setCullingMode(cull_mode);
00519 
00520   return mat;
00521 }
00522 
00527 // rve_msgs::Material version
00528 
00529 std::string materialToStringID(const rve_msgs::Material& input_mat)
00530 {
00531   std::stringstream ss;
00532   ss << "Gen_";
00533 
00534   if (input_mat.has_color)
00535   {
00536     ss << "Color";
00537   }
00538 
00539   if (input_mat.has_texture)
00540   {
00541     ss << "Texture_" << input_mat.texture;
00542   }
00543 
00544   if (input_mat.has_normal_map)
00545   {
00546     ss << "NormalMap_" << input_mat.normal_map;
00547   }
00548 
00549   bool transparent = input_mat.opacity < 0.99;
00550   if (transparent)
00551   {
00552     ss << "Alpha";
00553   }
00554 
00555   return ss.str();
00556 }
00557 
00558 static std::string toString(uint32_t i)
00559 {
00560   std::stringstream ss;
00561   ss << i;
00562   return ss.str();
00563 }
00564 
00565 void fillVertexShaderDefinition(const rve_msgs::Material& input_mat, ShaderDefinition& def)
00566 {
00567   def.input("float4", "position", "POSITION");
00568   def.input("float3", "normal", "NORMAL");
00569 
00570   uint32_t num_tex_coords = input_mat.has_texture ? 1 : 0;
00571   uint32_t tex_coord_num = 2;
00572   for (uint32_t i = 0; i < num_tex_coords; i++)
00573   {
00574     def.input("float2", "uv" + toString(i), "TEXCOORD" + toString(i));
00575     def.output("float2", "uv" + toString(i), "TEXCOORD" + toString(tex_coord_num));
00576     ++tex_coord_num;
00577   }
00578 
00579   if (input_mat.has_normal_map)
00580   {
00581     def.input("float3", "tangent", "TANGENT0");
00582   }
00583 
00584   def.output("float4", "position", "POSITION");
00585   def.output("float3", "view_pos", "TEXCOORD0");
00586   def.output("float3", "normal", "TEXCOORD1");
00587 
00588   if (input_mat.has_normal_map)
00589   {
00590     def.output("float3", "tangent", "TEXCOORD" + toString(tex_coord_num++));
00591     def.output("float3", "binormal", "TEXCOORD" + toString(tex_coord_num++));
00592   }
00593 
00594   def.uniform("float4x4", "worldviewproj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX, 0);
00595   def.uniform("float4x4", "worldview", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
00596 
00597   std::stringstream ss;
00598   ss << " out_position = mul(worldviewproj, in_position);" << std::endl;
00599   ss << " out_normal = mul(worldview, float4(in_normal,0)).xyz;" << std::endl;
00600 
00601   ss << " out_view_pos = mul(worldview, in_position).xyz;" << std::endl;
00602 
00603   if (input_mat.has_normal_map)
00604   {
00605     ss << " out_tangent = mul(worldview, float4(in_tangent, 0)).xyz;" << std::endl;
00606     ss << " out_binormal = cross(out_normal, out_tangent);" << std::endl;
00607   }
00608 
00609   for (uint32_t i = 0; i < num_tex_coords; i++)
00610   {
00611     ss << " out_uv" << i << " = in_uv" << i << ';' << std::endl;
00612   }
00613 
00614   def.body = ss.str();
00615 }
00616 
00617 void fillFragmentShaderDefinition(const rve_msgs::Material& input_mat, ShaderDefinition& def)
00618 {
00619   if (input_mat.has_normal_map)
00620   {
00621     def.include("normal_mapping.cg");
00622   }
00623 
00624   def.input("float3", "view_pos", "TEXCOORD0");
00625   def.input("float3", "normal", "TEXCOORD1");
00626 
00627   uint32_t num_tex_coords = input_mat.has_texture ? 1 : 0;
00628   uint32_t tex_coord_num = 2;
00629   for (uint32_t i = 0; i < num_tex_coords; i++)
00630   {
00631     def.input("float2", "uv" + toString(i), "TEXCOORD" + toString(tex_coord_num));
00632     ++tex_coord_num;
00633   }
00634 
00635   if (input_mat.has_normal_map)
00636   {
00637     def.input("float3", "tangent", "TEXCOORD" + toString(tex_coord_num++));
00638     def.input("float3", "binormal", "TEXCOORD" + toString(tex_coord_num++));
00639   }
00640 
00641   uint32_t sampler_num = 0;
00642   if (input_mat.has_texture)
00643   {
00644     def.sampler("tex", sampler_num++);
00645   }
00646 
00647   if (input_mat.has_normal_map)
00648   {
00649     def.sampler("normal_map", sampler_num++);
00650   }
00651 
00652   def.uniform("float4", "color", Ogre::GpuProgramParameters::ACT_CUSTOM, Material::CustomParam_Color);
00653   def.uniform("float4x4", "worldview", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
00654 
00655   std::stringstream ss;
00656   if (input_mat.has_texture)
00657   {
00658 #if 0
00659     if (input_mat.has_color)
00660     {
00661       ss << " color = color * tex2D(sampler_tex, in_uv0);\n";
00662     }
00663     else
00664 #endif
00665     {
00666       ss << " float4 tmp = tex2D(sampler_tex, in_uv0);\n";
00667       ss << " color = float4(tmp.rgb, tmp.a * color.a);\n";
00668     }
00669   }
00670 
00671   if (input_mat.has_normal_map)
00672   {
00673     ss << " float3 normal = extractNormalFromMap(sampler_normal_map, in_uv0, in_normal, in_tangent, in_binormal);" << std::endl;
00674   }
00675   else
00676   {
00677     ss << " float3 normal = normalize(in_normal);" << std::endl;
00678   }
00679 
00680   def.body = ss.str();
00681 }
00682 
00683 void fillPickingFragmentShaderDefinition(const rve_msgs::Material& input_mat, ShaderDefinition& def)
00684 {
00685   def.uniform("float4", "object_id", Ogre::GpuProgramParameters::ACT_CUSTOM, Material::CustomParam_ObjectID);
00686 
00687   std::stringstream ss;
00688   // object_id is taken care of by the uniform
00689   ss << " float4 object_extra = float4(0.0, 0.0, 0.0, 0.0);\n";
00690   def.body = ss.str();
00691 }
00692 
00693 Ogre::MaterialPtr generateOgreMaterial(const rve_msgs::Material& input_mat)
00694 {
00695   MaterialDefinition def;
00696   def.name = materialToStringID(input_mat);
00697   def.transparent = input_mat.opacity < 0.99;
00698   def.disable_shading = input_mat.disable_shading;
00699 
00700   def.cull_mode = input_mat.cull_mode;
00701 
00702   if (input_mat.has_texture)
00703   {
00704     def.textures.push_back(input_mat.texture);
00705   }
00706 
00707   if (input_mat.has_normal_map)
00708   {
00709     def.textures.push_back(input_mat.normal_map);
00710   }
00711 
00712   fillVertexShaderDefinition(input_mat, def.vertex_def);
00713   fillFragmentShaderDefinition(input_mat, def.fragment_def);
00714   fillPickingFragmentShaderDefinition(input_mat, def.picking_fragment_def);
00715   return generateOgreMaterial(def);
00716 }
00717 
00718 } // namespace rve_render_server


rve_render_server
Author(s): Josh Faust
autogenerated on Wed Dec 11 2013 14:31:15