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