OGLTexture.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../../Precompiled.h"
  4. #include "../../Graphics/Graphics.h"
  5. #include "../../Graphics/Material.h"
  6. #include "../../GraphicsAPI/GraphicsImpl.h"
  7. #include "../../GraphicsAPI/RenderSurface.h"
  8. #include "../../IO/Log.h"
  9. #include "../../Resource/ResourceCache.h"
  10. #include "../../Resource/XMLFile.h"
  11. #include "../../DebugNew.h"
  12. #if URHO3D_GLES3
  13. #define GL_COMPARE_R_TO_TEXTURE GL_COMPARE_REF_TO_TEXTURE
  14. #endif
  15. namespace Urho3D
  16. {
  17. static GLenum glWrapModes[] =
  18. {
  19. GL_REPEAT,
  20. GL_MIRRORED_REPEAT,
  21. GL_CLAMP_TO_EDGE,
  22. #ifndef GL_ES_VERSION_2_0
  23. GL_CLAMP
  24. #else
  25. GL_CLAMP_TO_EDGE
  26. #endif
  27. };
  28. #ifndef GL_ES_VERSION_2_0
  29. static GLenum gl3WrapModes[] =
  30. {
  31. GL_REPEAT,
  32. GL_MIRRORED_REPEAT,
  33. GL_CLAMP_TO_EDGE,
  34. GL_CLAMP_TO_BORDER
  35. };
  36. #endif
  37. static GLenum GetWrapMode(TextureAddressMode mode)
  38. {
  39. #ifndef GL_ES_VERSION_2_0
  40. return Graphics::GetGL3Support() ? gl3WrapModes[mode] : glWrapModes[mode];
  41. #else
  42. return glWrapModes[mode];
  43. #endif
  44. }
  45. void Texture::SetSRGB_OGL(bool enable)
  46. {
  47. if (graphics_)
  48. enable &= graphics_->GetSRGBSupport();
  49. if (enable != sRGB_)
  50. {
  51. sRGB_ = enable;
  52. // If texture had already been created, must recreate it to set the sRGB texture format
  53. if (object_.name_)
  54. Create();
  55. // If texture in use in the framebuffer, mark it dirty
  56. if (graphics_ && graphics_->GetRenderTarget(0) && graphics_->GetRenderTarget(0)->GetParentTexture() == this)
  57. graphics_->MarkFBODirty_OGL();
  58. }
  59. }
  60. void Texture::UpdateParameters_OGL()
  61. {
  62. if (!object_.name_ || !graphics_)
  63. return;
  64. // If texture is multisampled, do not attempt to set parameters as it's illegal, just return
  65. #ifndef GL_ES_VERSION_2_0
  66. if (target_ == GL_TEXTURE_2D_MULTISAMPLE)
  67. {
  68. parametersDirty_ = false;
  69. return;
  70. }
  71. #endif
  72. // Wrapping
  73. glTexParameteri(target_, GL_TEXTURE_WRAP_S, GetWrapMode(addressModes_[COORD_U]));
  74. glTexParameteri(target_, GL_TEXTURE_WRAP_T, GetWrapMode(addressModes_[COORD_V]));
  75. #if defined(URHO3D_GLES3) || (defined(DESKTOP_GRAPHICS) && !defined(__EMSCRIPTEN__))
  76. glTexParameteri(target_, GL_TEXTURE_WRAP_R, GetWrapMode(addressModes_[COORD_W]));
  77. #endif
  78. TextureFilterMode filterMode = filterMode_;
  79. if (filterMode == FILTER_DEFAULT)
  80. filterMode = graphics_->GetDefaultTextureFilterMode();
  81. // Filtering
  82. switch (filterMode)
  83. {
  84. case FILTER_NEAREST:
  85. if (levels_ < 2)
  86. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  87. else
  88. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
  89. glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  90. break;
  91. case FILTER_BILINEAR:
  92. if (levels_ < 2)
  93. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  94. else
  95. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  96. glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  97. break;
  98. case FILTER_ANISOTROPIC:
  99. case FILTER_TRILINEAR:
  100. if (levels_ < 2)
  101. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  102. else
  103. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  104. glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  105. break;
  106. case FILTER_NEAREST_ANISOTROPIC:
  107. if (levels_ < 2)
  108. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  109. else
  110. glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
  111. glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  112. break;
  113. default:
  114. break;
  115. }
  116. #ifndef GL_ES_VERSION_2_0
  117. // Anisotropy
  118. if (graphics_->GetAnisotropySupport())
  119. {
  120. unsigned maxAnisotropy = anisotropy_ ? anisotropy_ : graphics_->GetDefaultTextureAnisotropy();
  121. glTexParameterf(target_, GL_TEXTURE_MAX_ANISOTROPY_EXT,
  122. (filterMode == FILTER_ANISOTROPIC || filterMode == FILTER_NEAREST_ANISOTROPIC) ? (float)maxAnisotropy : 1.0f);
  123. }
  124. glTexParameterfv(target_, GL_TEXTURE_BORDER_COLOR, borderColor_.Data());
  125. #endif
  126. #ifndef URHO3D_GLES2
  127. // Shadow compare
  128. if (shadowCompare_)
  129. {
  130. glTexParameteri(target_, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
  131. glTexParameteri(target_, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  132. }
  133. else
  134. glTexParameteri(target_, GL_TEXTURE_COMPARE_MODE, GL_NONE);
  135. #endif
  136. parametersDirty_ = false;
  137. }
  138. bool Texture::GetParametersDirty_OGL() const
  139. {
  140. return parametersDirty_;
  141. }
  142. bool Texture::IsCompressed_OGL() const
  143. {
  144. return format_ == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format_ == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
  145. format_ == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT || format_ == GL_ETC1_RGB8_OES ||
  146. format_ == GL_ETC2_RGB8_OES || format_ == GL_ETC2_RGBA8_OES ||
  147. format_ == COMPRESSED_RGB_PVRTC_4BPPV1_IMG || format_ == COMPRESSED_RGBA_PVRTC_4BPPV1_IMG ||
  148. format_ == COMPRESSED_RGB_PVRTC_2BPPV1_IMG || format_ == COMPRESSED_RGBA_PVRTC_2BPPV1_IMG ||
  149. format_ == GL_ETC2_RGB8_OES || format_ == GL_ETC2_RGBA8_OES;
  150. }
  151. unsigned Texture::GetRowDataSize_OGL(int width) const
  152. {
  153. switch (format_)
  154. {
  155. case GL_ALPHA:
  156. case GL_LUMINANCE:
  157. return (unsigned)width;
  158. case GL_LUMINANCE_ALPHA:
  159. return (unsigned)(width * 2);
  160. case GL_RGB:
  161. return (unsigned)(width * 3);
  162. case GL_RGBA:
  163. #ifndef GL_ES_VERSION_2_0
  164. case GL_DEPTH24_STENCIL8_EXT:
  165. case GL_RG16:
  166. case GL_RG16F:
  167. case GL_R32F:
  168. #endif
  169. #ifdef GL_ES_VERSION_3_0
  170. case GL_DEPTH24_STENCIL8:
  171. #endif
  172. return (unsigned)(width * 4);
  173. #ifndef GL_ES_VERSION_2_0
  174. case GL_R8:
  175. return (unsigned)width;
  176. case GL_RG8:
  177. case GL_R16F:
  178. return (unsigned)(width * 2);
  179. case GL_RGBA16:
  180. case GL_RGBA16F_ARB:
  181. return (unsigned)(width * 8);
  182. case GL_RGBA32F_ARB:
  183. return (unsigned)(width * 16);
  184. #endif
  185. #ifdef GL_ES_VERSION_3_0
  186. case GL_R8:
  187. return (unsigned) width;
  188. case GL_RG8:
  189. case GL_R16F:
  190. return (unsigned) (width * 2);
  191. case GL_RGBA16F:
  192. return (unsigned) (width * 8);
  193. case GL_RGBA32F:
  194. return (unsigned) (width * 16);
  195. #endif
  196. case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  197. return ((unsigned)(width + 3) >> 2u) * 8;
  198. case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  199. case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  200. return ((unsigned)(width + 3) >> 2u) * 16;
  201. case GL_ETC1_RGB8_OES:
  202. case GL_ETC2_RGB8_OES:
  203. return ((unsigned)(width + 3) >> 2u) * 8;
  204. case GL_ETC2_RGBA8_OES:
  205. return ((unsigned)(width + 3) >> 2u) * 16;
  206. case COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
  207. case COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
  208. return ((unsigned)(width + 3) >> 2u) * 8;
  209. case COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
  210. case COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
  211. return ((unsigned)(width + 7) >> 3u) * 8;
  212. default:
  213. return 0;
  214. }
  215. }
  216. #ifdef GL_ES_VERSION_3_0
  217. #define GL_SRGB_EXT GL_SRGB
  218. #define GL_SRGB_ALPHA_EXT GL_SRGB8_ALPHA8
  219. #endif
  220. unsigned Texture::GetExternalFormat_OGL(unsigned format)
  221. {
  222. #ifndef GL_ES_VERSION_2_0
  223. if (format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32)
  224. return GL_DEPTH_COMPONENT;
  225. else if (format == GL_DEPTH24_STENCIL8_EXT)
  226. return GL_DEPTH_STENCIL_EXT;
  227. else if (format == GL_SLUMINANCE_EXT)
  228. return GL_LUMINANCE;
  229. else if (format == GL_SLUMINANCE_ALPHA_EXT)
  230. return GL_LUMINANCE_ALPHA;
  231. else if (format == GL_R8 || format == GL_R16F || format == GL_R32F)
  232. return GL_RED;
  233. else if (format == GL_RG8 || format == GL_RG16 || format == GL_RG16F || format == GL_RG32F)
  234. return GL_RG;
  235. else if (format == GL_RGBA16 || format == GL_RGBA16F_ARB || format == GL_RGBA32F_ARB || format == GL_SRGB_ALPHA_EXT)
  236. return GL_RGBA;
  237. else if (format == GL_SRGB_EXT)
  238. return GL_RGB;
  239. else
  240. return format;
  241. #else
  242. #if defined(GL_ES_VERSION_3_0)
  243. if (format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32F)
  244. return GL_DEPTH_COMPONENT;
  245. else if (format == GL_DEPTH24_STENCIL8)
  246. return GL_DEPTH_STENCIL;
  247. else if (format == GL_R8 || format == GL_R16F || format == GL_R32F)
  248. return GL_RED;
  249. else if (format == GL_RG8 || format == GL_RG16F || format == GL_RG32F)
  250. return GL_RG;
  251. else if (format == GL_RGBA16F || format == GL_RGBA32F || format == GL_SRGB_ALPHA_EXT)
  252. return GL_RGBA;
  253. else if (format == GL_RG16UI)
  254. return GL_RG_INTEGER;
  255. else if (format == GL_RGBA16UI)
  256. return GL_RGBA_INTEGER;
  257. #endif
  258. return format;
  259. #endif
  260. }
  261. unsigned Texture::GetDataType_OGL(unsigned format)
  262. {
  263. #ifndef GL_ES_VERSION_2_0
  264. if (format == GL_DEPTH24_STENCIL8_EXT)
  265. return GL_UNSIGNED_INT_24_8_EXT;
  266. else if (format == GL_RG16 || format == GL_RGBA16)
  267. return GL_UNSIGNED_SHORT;
  268. else if (format == GL_RGBA32F_ARB || format == GL_RG32F || format == GL_R32F)
  269. return GL_FLOAT;
  270. else if (format == GL_RGBA16F_ARB || format == GL_RG16F || format == GL_R16F)
  271. return GL_HALF_FLOAT_ARB;
  272. else
  273. return GL_UNSIGNED_BYTE;
  274. #else
  275. #if defined(GL_ES_VERSION_3_0)
  276. if (format == GL_DEPTH_COMPONENT24)
  277. return GL_UNSIGNED_INT;
  278. else if (format == GL_DEPTH24_STENCIL8)
  279. return GL_UNSIGNED_INT_24_8;
  280. else if (format == GL_RGBA16UI || format == GL_RG16UI)
  281. return GL_UNSIGNED_SHORT;
  282. else if (format == GL_RGBA16F || format == GL_RG16F)
  283. return GL_HALF_FLOAT;
  284. else if (format == GL_DEPTH_COMPONENT32F || format == GL_RGBA32F || format == GL_RG32F || format == GL_R32F)
  285. return GL_FLOAT;
  286. else if (format == GL_RGBA16F || format == GL_RG16F || format == GL_R16F)
  287. return GL_HALF_FLOAT;
  288. #endif
  289. if (format == GL_DEPTH_COMPONENT24_OES)
  290. return GL_UNSIGNED_INT;
  291. else if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16)
  292. return GL_UNSIGNED_SHORT;
  293. else
  294. return GL_UNSIGNED_BYTE;
  295. #endif
  296. }
  297. unsigned Texture::GetSRGBFormat_OGL(unsigned format)
  298. {
  299. #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
  300. if (!graphics_ || !graphics_->GetSRGBSupport())
  301. return format;
  302. switch (format)
  303. {
  304. case GL_RGB:
  305. return GL_SRGB_EXT;
  306. case GL_RGBA:
  307. return GL_SRGB_ALPHA_EXT;
  308. #ifndef GL_ES_VERSION_3_0
  309. case GL_LUMINANCE:
  310. return GL_SLUMINANCE_EXT;
  311. case GL_LUMINANCE_ALPHA:
  312. return GL_SLUMINANCE_ALPHA_EXT;
  313. case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  314. return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
  315. case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  316. return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
  317. case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  318. return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
  319. #endif
  320. default:
  321. return format;
  322. }
  323. #else
  324. return format;
  325. #endif
  326. }
  327. void Texture::RegenerateLevels_OGL()
  328. {
  329. if (!object_.name_)
  330. return;
  331. #ifndef GL_ES_VERSION_2_0
  332. if (Graphics::GetGL3Support())
  333. glGenerateMipmap(target_);
  334. else
  335. glGenerateMipmapEXT(target_);
  336. #else
  337. glGenerateMipmap(target_);
  338. #endif
  339. levelsDirty_ = false;
  340. }
  341. }