llmaterial.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /**
  2. * @file llmaterial.cpp
  3. * @brief Material definition
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewergpl$
  6. *
  7. * Copyright (c) 2012, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llmaterial.h"
  34. #include "hbxxh.h"
  35. // Materials cap parameters
  36. #define MAT_CAP_NORMAL_MAP_FIELD "NormMap"
  37. #define MAT_CAP_NORMAL_MAP_OFFSET_X_FIELD "NormOffsetX"
  38. #define MAT_CAP_NORMAL_MAP_OFFSET_Y_FIELD "NormOffsetY"
  39. #define MAT_CAP_NORMAL_MAP_REPEAT_X_FIELD "NormRepeatX"
  40. #define MAT_CAP_NORMAL_MAP_REPEAT_Y_FIELD "NormRepeatY"
  41. #define MAT_CAP_NORMAL_MAP_ROTATION_FIELD "NormRotation"
  42. #define MAT_CAP_SPECULAR_MAP_FIELD "SpecMap"
  43. #define MAT_CAP_SPECULAR_MAP_OFFSET_X_FIELD "SpecOffsetX"
  44. #define MAT_CAP_SPECULAR_MAP_OFFSET_Y_FIELD "SpecOffsetY"
  45. #define MAT_CAP_SPECULAR_MAP_REPEAT_X_FIELD "SpecRepeatX"
  46. #define MAT_CAP_SPECULAR_MAP_REPEAT_Y_FIELD "SpecRepeatY"
  47. #define MAT_CAP_SPECULAR_MAP_ROTATION_FIELD "SpecRotation"
  48. #define MAT_CAP_SPECULAR_COLOR_FIELD "SpecColor"
  49. #define MAT_CAP_SPECULAR_EXP_FIELD "SpecExp"
  50. #define MAT_CAP_ENV_INTENSITY_FIELD "EnvIntensity"
  51. #define MAT_CAP_ALPHA_MASK_CUTOFF_FIELD "AlphaMaskCutoff"
  52. #define MAT_CAP_DIFFUSE_ALPHA_MODE_FIELD "DiffuseAlphaMode"
  53. const LLColor4U LLMaterial::DEFAULT_SPECULAR_LIGHT_COLOR(255, 255, 255, 255);
  54. const LLMaterial LLMaterial::null;
  55. constexpr F32 MAT_MULTIPLIER = 10000.f;
  56. // Helper functions
  57. template<typename T> T getMaterialField(const LLSD& data,
  58. const std::string& field,
  59. const LLSD::Type field_type)
  60. {
  61. if (data.has(field) && field_type == data[field].type())
  62. {
  63. return (T)data[field];
  64. }
  65. llwarns << "Missing or mistyped field '" << field
  66. << "' in material definition" << llendl;
  67. return (T)LLSD();
  68. }
  69. // GCC did not like the generic form above for some reason
  70. template<> LLUUID getMaterialField(const LLSD& data, const std::string& field,
  71. const LLSD::Type field_type)
  72. {
  73. if (data.has(field) && field_type == data[field].type())
  74. {
  75. return data[field].asUUID();
  76. }
  77. llwarns << "Missing or mistyped field '" << field
  78. << "' in material definition" << llendl;
  79. return LLUUID::null;
  80. }
  81. ///////////////////////////////////////////////////////////////////////////////
  82. // LLMaterial class proper
  83. ///////////////////////////////////////////////////////////////////////////////
  84. LLMaterial::LLMaterial()
  85. {
  86. // IMPORTANT: since we use the hash of the member variables memory block of
  87. // this class to detect changes, we must ensure that this block (and its
  88. // padding bytes) have been zeroed out. But of course, we must leave the
  89. // LLRefCount member variable untouched (and skip it when hashing). HB
  90. constexpr size_t offset = sizeof(LLRefCount);
  91. memset((void*)((const char*)this + offset), 0, sizeof(*this) - offset);
  92. // Now that we zeroed out our member variables, we can set the ones that
  93. // should not be zero to their default value. HB
  94. mNormalRepeatX = mNormalRepeatY = 1.f;
  95. mSpecularRepeatX = mSpecularRepeatY = 1.f;
  96. mSpecularLightColor = DEFAULT_SPECULAR_LIGHT_COLOR;
  97. mSpecularLightExponent = DEFAULT_SPECULAR_LIGHT_EXPONENT;
  98. mEnvironmentIntensity = DEFAULT_ENV_INTENSITY;
  99. mDiffuseAlphaMode = DIFFUSE_ALPHA_MODE_BLEND;
  100. #if 0
  101. mNormalOffsetX = mNormalOffsetY = mNormalRotation = 0.f;
  102. mSpecularOffsetX = mSpecularOffsetY = mSpecularRotation = 0.f;
  103. #endif
  104. }
  105. LLMaterial::LLMaterial(const LLSD& material_data)
  106. {
  107. fromLLSD(material_data);
  108. }
  109. LLUUID LLMaterial::getHash() const
  110. {
  111. // *HACK: hash the bytes of this object but do not include the ref count
  112. // Note: this does work properly only because the padding bytes between our
  113. // member variables have been zeroed in the constructor. HB
  114. constexpr size_t offset = sizeof(LLRefCount);
  115. return HBXXH128::digest((const void*)((const char*)this + offset),
  116. sizeof(*this) - offset);
  117. }
  118. LLSD LLMaterial::asLLSD() const
  119. {
  120. LLSD material_data;
  121. material_data[MAT_CAP_NORMAL_MAP_FIELD] = mNormalID;
  122. material_data[MAT_CAP_NORMAL_MAP_OFFSET_X_FIELD] =
  123. ll_round(mNormalOffsetX * MAT_MULTIPLIER);
  124. material_data[MAT_CAP_NORMAL_MAP_OFFSET_Y_FIELD] =
  125. ll_round(mNormalOffsetY * MAT_MULTIPLIER);
  126. material_data[MAT_CAP_NORMAL_MAP_REPEAT_X_FIELD] =
  127. ll_round(mNormalRepeatX * MAT_MULTIPLIER);
  128. material_data[MAT_CAP_NORMAL_MAP_REPEAT_Y_FIELD] =
  129. ll_round(mNormalRepeatY * MAT_MULTIPLIER);
  130. material_data[MAT_CAP_NORMAL_MAP_ROTATION_FIELD] =
  131. ll_round(mNormalRotation * MAT_MULTIPLIER);
  132. material_data[MAT_CAP_SPECULAR_MAP_FIELD] = mSpecularID;
  133. material_data[MAT_CAP_SPECULAR_MAP_OFFSET_X_FIELD] =
  134. ll_round(mSpecularOffsetX * MAT_MULTIPLIER);
  135. material_data[MAT_CAP_SPECULAR_MAP_OFFSET_Y_FIELD] =
  136. ll_round(mSpecularOffsetY * MAT_MULTIPLIER);
  137. material_data[MAT_CAP_SPECULAR_MAP_REPEAT_X_FIELD] =
  138. ll_round(mSpecularRepeatX * MAT_MULTIPLIER);
  139. material_data[MAT_CAP_SPECULAR_MAP_REPEAT_Y_FIELD] =
  140. ll_round(mSpecularRepeatY * MAT_MULTIPLIER);
  141. material_data[MAT_CAP_SPECULAR_MAP_ROTATION_FIELD] =
  142. ll_round(mSpecularRotation * MAT_MULTIPLIER);
  143. material_data[MAT_CAP_SPECULAR_COLOR_FIELD] =
  144. mSpecularLightColor.getValue();
  145. material_data[MAT_CAP_SPECULAR_EXP_FIELD] = mSpecularLightExponent;
  146. material_data[MAT_CAP_ENV_INTENSITY_FIELD] = mEnvironmentIntensity;
  147. material_data[MAT_CAP_DIFFUSE_ALPHA_MODE_FIELD] = mDiffuseAlphaMode;
  148. material_data[MAT_CAP_ALPHA_MASK_CUTOFF_FIELD] = mAlphaMaskCutoff;
  149. return material_data;
  150. }
  151. void LLMaterial::fromLLSD(const LLSD& material_data)
  152. {
  153. mNormalID = getMaterialField<LLSD::UUID>(material_data,
  154. MAT_CAP_NORMAL_MAP_FIELD,
  155. LLSD::TypeUUID);
  156. mNormalOffsetX =
  157. (F32)getMaterialField<LLSD::Integer>(material_data,
  158. MAT_CAP_NORMAL_MAP_OFFSET_X_FIELD,
  159. LLSD::TypeInteger) / MAT_MULTIPLIER;
  160. mNormalOffsetY =
  161. (F32)getMaterialField<LLSD::Integer>(material_data,
  162. MAT_CAP_NORMAL_MAP_OFFSET_Y_FIELD,
  163. LLSD::TypeInteger) / MAT_MULTIPLIER;
  164. mNormalRepeatX =
  165. (F32)getMaterialField<LLSD::Integer>(material_data,
  166. MAT_CAP_NORMAL_MAP_REPEAT_X_FIELD,
  167. LLSD::TypeInteger) / MAT_MULTIPLIER;
  168. mNormalRepeatY =
  169. (F32)getMaterialField<LLSD::Integer>(material_data,
  170. MAT_CAP_NORMAL_MAP_REPEAT_Y_FIELD,
  171. LLSD::TypeInteger) / MAT_MULTIPLIER;
  172. mNormalRotation =
  173. (F32)getMaterialField<LLSD::Integer>(material_data,
  174. MAT_CAP_NORMAL_MAP_ROTATION_FIELD,
  175. LLSD::TypeInteger) / MAT_MULTIPLIER;
  176. mSpecularID =
  177. getMaterialField<LLSD::UUID>(material_data,
  178. MAT_CAP_SPECULAR_MAP_FIELD,
  179. LLSD::TypeUUID);
  180. mSpecularOffsetX =
  181. (F32)getMaterialField<LLSD::Integer>(material_data,
  182. MAT_CAP_SPECULAR_MAP_OFFSET_X_FIELD,
  183. LLSD::TypeInteger) / MAT_MULTIPLIER;
  184. mSpecularOffsetY =
  185. (F32)getMaterialField<LLSD::Integer>(material_data,
  186. MAT_CAP_SPECULAR_MAP_OFFSET_Y_FIELD,
  187. LLSD::TypeInteger) / MAT_MULTIPLIER;
  188. mSpecularRepeatX =
  189. (F32)getMaterialField<LLSD::Integer>(material_data,
  190. MAT_CAP_SPECULAR_MAP_REPEAT_X_FIELD,
  191. LLSD::TypeInteger) / MAT_MULTIPLIER;
  192. mSpecularRepeatY =
  193. (F32)getMaterialField<LLSD::Integer>(material_data,
  194. MAT_CAP_SPECULAR_MAP_REPEAT_Y_FIELD,
  195. LLSD::TypeInteger) / MAT_MULTIPLIER;
  196. mSpecularRotation =
  197. (F32)getMaterialField<LLSD::Integer>(material_data,
  198. MAT_CAP_SPECULAR_MAP_ROTATION_FIELD,
  199. LLSD::TypeInteger) / MAT_MULTIPLIER;
  200. mSpecularLightColor.setValue(getMaterialField<LLSD>(material_data,
  201. MAT_CAP_SPECULAR_COLOR_FIELD,
  202. LLSD::TypeArray));
  203. mSpecularLightExponent =
  204. (U8)getMaterialField<LLSD::Integer>(material_data,
  205. MAT_CAP_SPECULAR_EXP_FIELD,
  206. LLSD::TypeInteger);
  207. mEnvironmentIntensity =
  208. (U8)getMaterialField<LLSD::Integer>(material_data,
  209. MAT_CAP_ENV_INTENSITY_FIELD,
  210. LLSD::TypeInteger);
  211. mDiffuseAlphaMode =
  212. (U8)getMaterialField<LLSD::Integer>(material_data,
  213. MAT_CAP_DIFFUSE_ALPHA_MODE_FIELD,
  214. LLSD::TypeInteger);
  215. mAlphaMaskCutoff =
  216. (U8)getMaterialField<LLSD::Integer>(material_data,
  217. MAT_CAP_ALPHA_MASK_CUTOFF_FIELD,
  218. LLSD::TypeInteger);
  219. }
  220. bool LLMaterial::isNull() const
  221. {
  222. return *this == null;
  223. }
  224. bool LLMaterial::operator==(const LLMaterial& rhs) const
  225. {
  226. return mNormalID == rhs.mNormalID &&
  227. mNormalOffsetX == rhs.mNormalOffsetX &&
  228. mNormalOffsetY == rhs.mNormalOffsetY &&
  229. mNormalRepeatX == rhs.mNormalRepeatX &&
  230. mNormalRepeatY == rhs.mNormalRepeatY &&
  231. mNormalRotation == rhs.mNormalRotation &&
  232. mSpecularID == rhs.mSpecularID &&
  233. mSpecularOffsetX == rhs.mSpecularOffsetX &&
  234. mSpecularOffsetY == rhs.mSpecularOffsetY &&
  235. mSpecularRepeatX == rhs.mSpecularRepeatX &&
  236. mSpecularRepeatY == rhs.mSpecularRepeatY &&
  237. mSpecularRotation == rhs.mSpecularRotation &&
  238. mSpecularLightColor == rhs.mSpecularLightColor &&
  239. mSpecularLightExponent == rhs.mSpecularLightExponent &&
  240. mEnvironmentIntensity == rhs.mEnvironmentIntensity &&
  241. mDiffuseAlphaMode == rhs.mDiffuseAlphaMode &&
  242. mAlphaMaskCutoff == rhs.mAlphaMaskCutoff;
  243. }
  244. bool LLMaterial::operator!=(const LLMaterial& rhs) const
  245. {
  246. return !(*this == rhs);
  247. }
  248. // NEVER incorporate this value into the message system: this function will
  249. // vary depending on viewer implementation
  250. U32 LLMaterial::getShaderMask(U32 alpha_mode, bool is_alpha)
  251. {
  252. U32 ret = 0;
  253. // Two least significant bits are "diffuse alpha mode"
  254. if (alpha_mode != DIFFUSE_ALPHA_MODE_DEFAULT)
  255. {
  256. ret = alpha_mode;
  257. }
  258. else
  259. {
  260. ret = getDiffuseAlphaMode();
  261. if (ret == DIFFUSE_ALPHA_MODE_BLEND && !is_alpha)
  262. {
  263. ret = DIFFUSE_ALPHA_MODE_NONE;
  264. }
  265. }
  266. llassert(ret < SHADER_COUNT);
  267. // Next bit is whether or not specular map is present
  268. constexpr U32 SPEC_BIT = 0x4;
  269. if (getSpecularID().notNull())
  270. {
  271. ret |= SPEC_BIT;
  272. }
  273. llassert(ret < SHADER_COUNT);
  274. // Next bit is whether or not normal map is present
  275. constexpr U32 NORM_BIT = 0x8;
  276. if (getNormalID().notNull())
  277. {
  278. ret |= NORM_BIT;
  279. }
  280. llassert(ret < SHADER_COUNT);
  281. return ret;
  282. }