Covellite++  Version: 2.3.0 Revision: ??? Platform: x64 Build: 23:13 04.01.2025
Кроссплатформенный фреймворк для разработки приложений на С++
Загрузка...
Поиск...
Не найдено
OpenGLCommon.Texture.cpp
1
2#include "stdafx.h"
3#include "OpenGLCommon.Texture.hpp"
4
5#ifndef GL_DEPTH_COMPONENT
6# define GL_DEPTH_COMPONENT 0
7#endif
8
9namespace covellite
10{
11
12namespace api
13{
14
15namespace renderer
16{
17
18OpenGLCommon::Texture::Texture(const Component::Texture & _Data) :
19 m_Destination(GetDestination(_Data)),
20 m_Format(GetFormat(_Data.Destination)),
21 m_TextureId(BuildTexture()),
22 m_IsMapping(_Data.IsMapping),
23 m_Capacity(_Data.Capacity)
24{
25 MakeContent(_Data.Width, _Data.Height, _Data.pTextureData);
26}
27
28/*virtual*/ OpenGLCommon::Texture::~Texture(void) noexcept
29{
30 glDeleteTextures(1, &m_TextureId);
31}
32
33// cppcheck-suppress unusedFunction
34void OpenGLCommon::Texture::Bind(const bool _IsActivate) noexcept
35{
36 glBindTexture(GL_TEXTURE_2D, _IsActivate ? m_TextureId : 0);
37}
38
39void OpenGLCommon::Texture::MakeContent(
40 const GLsizei _Width,
41 const GLsizei _Height,
42 const GLvoid * _pData)
43{
44 Bind(true);
45
46# if !defined(GL_RGBA32F)
47# define GL_RGBA32F GL_RGBA
48# endif
49
50# if !defined(GL_RGBA16F)
51# define GL_RGBA16F GL_RGBA
52# endif
53
54# if !defined(GL_HALF_FLOAT)
55# define GL_HALF_FLOAT GL_FLOAT
56# endif
57
58 const GLint InternalFormat =
59 (m_Format == GL_DEPTH_COMPONENT) ? GL_DEPTH_COMPONENT :
60 (m_Capacity == 32) ? GL_RGBA32F :
61 (m_Capacity == 16) ? GL_RGBA16F :
62 GL_RGBA;
63
64 const GLenum Format =
65 (InternalFormat == GL_RGBA) ? GL_UNSIGNED_BYTE :
66 (m_Capacity == 32) ? GL_FLOAT :
67 (m_Capacity == 16) ? GL_HALF_FLOAT :
68 GL_UNSIGNED_BYTE;
69
70 // glTexImage2D копирует переданные данные в видеопамять, поэтому копировать
71 // их в промежуточный буфер не нужно.
72 glTexImage2D(GL_TEXTURE_2D, 0,
73 InternalFormat,
74 _Width, _Height, 0,
75 m_Format,
76 m_Format == GL_DEPTH_COMPONENT ? GL_UNSIGNED_INT : Format,
77 _pData);
78
79 // Это рабочий вариант на Android'e; для подключения этой текстуры
80 // к фреймбуферу нужно использовать GL_DEPTH_STENCIL_ATTACHMENT.
81 //glTexImage2D(GL_TEXTURE_2D, 0,
82 // m_Format == GL_DEPTH_COMPONENT ? GL_DEPTH24_STENCIL8 : GL_RGBA,
83 // _Width, _Height, 0,
84 // m_Format == GL_DEPTH_COMPONENT ? GL_DEPTH_STENCIL : GL_RGBA,
85 // m_Format == GL_DEPTH_COMPONENT ? GL_UNSIGNED_INT_24_8 : GL_UNSIGNED_BYTE,
86 // _pData);
87
88 // Для такой текстуры нужно ставить (иначе в ней будут нули)
89 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
90 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
91 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
92 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
93
94 Bind(false);
95
96 const auto Error = glGetError();
97 if (Error != GL_NO_ERROR)
98 {
99 throw STD_EXCEPTION << "Create texture error: " << Error;
100 }
101
102 if (m_IsMapping)
103 {
104 m_ReadCopyData.resize(static_cast<size_t>(_Width) * _Height * 4, 0x00);
105 }
106}
107
108/*static*/ auto OpenGLCommon::Texture::GetDestination(
109 const Component::Texture & _TextureData) -> Destination_t
110{
111 if (_TextureData.Index >= 0)
112 {
113 using namespace ::alicorn::extension::std;
114
115 const auto Name =
116 string_cast<::std::string, Encoding::Ascii128>(_TextureData.Name);
117 return { _TextureData.Index, Name };
118 }
119
120 if (_TextureData.Destination == uT("diffuse")) return { 0, "TexDiffuse" };
121
122 static const ::std::vector<::std::pair<String_t, const char *>> Destinations =
123 {
124 { uT("albedo"), "TexAlbedo" },
125 { uT("metalness"), "TexMetalness" },
126 { uT("roughness"), "TexRoughness" },
127 { uT("normal"), "TexNormal" },
128 { uT("occlusion"), "TexOcclusion" },
129 { uT("depth"), "TexDepth" },
130 };
131
132 const auto itValue = ::std::find_if(Destinations.cbegin(),
133 Destinations.cend(), [&](const ::std::pair<String_t, const char *> & _Dest)
134 {
135 return (_TextureData.Destination == _Dest.first);
136 });
137 if (itValue == Destinations.cend())
138 {
139 throw STD_EXCEPTION << "Unexpected destination texture: " <<
140 _TextureData.Destination << uT(" [id=???") /*<< _pComponent->Id*/ << uT("].");
141 }
142
143 const auto IndexDestination =
144 static_cast<GLint>(::std::distance(Destinations.cbegin(), itValue));
145 return { IndexDestination, Destinations[IndexDestination].second };
146}
147
148/*static*/ GLint OpenGLCommon::Texture::GetFormat(const String_t & _Destination)
149{
150 return (_Destination == uT("depth")) ? GL_DEPTH_COMPONENT : GL_RGBA;
151}
152
153/*static*/ GLuint OpenGLCommon::Texture::BuildTexture(void) noexcept
154{
155 GLuint TextureId = 0;
156 glGenTextures(1, &TextureId);
157 return TextureId;
158}
159
160} // namespace renderer
161
162} // namespace api
163
164} // namespace covellite