3#include "OpenGLCommonShader.hpp"
4#include <glm/glm.force.hpp>
5#include <alicorn/std/vector.hpp>
6#include <alicorn/std.fast/unordered-map.hpp>
7#include <Covellite/Api/Vertex.hpp>
8#include <Covellite/Api/Defines.hpp>
9#include "OpenGLCommon.Texture.hpp"
10#include "Shaders/Shaders.hpp"
11#include "GraphicApi.Constants.hpp"
22inline GLuint glGetProgramId(
void)
25 glGetIntegerv(GL_CURRENT_PROGRAM, &iProgramId);
26 return static_cast<GLuint
>(iProgramId);
29inline void CheckError(
const int _Line)
31 const auto Error = glGetError();
32 if (Error != GL_NO_ERROR)
34 throw EXCEPTION_NO_FILE_LINE(::std::runtime_error) <<
35 _Line <<
": error " << Error;
46class Support<::Camera>
49 static const GLuint Index = COVELLITE_BUFFER_INDEX_CAMERA;
53 const GLuint _ProgramId,
54 const ::Camera & _Matrices,
55 const ::std::string & _BufferName)
57 const auto MatrixProjectionId =
58 glGetUniformLocation(_ProgramId, (_BufferName +
".Projection").c_str());
59 const auto MatrixViewId =
60 glGetUniformLocation(_ProgramId, (_BufferName +
".View").c_str());
61 const auto MatrixViewInverseId =
62 glGetUniformLocation(_ProgramId, (_BufferName +
".ViewInverse").c_str());
64 glUniformMatrix4fv(MatrixProjectionId, 1, GL_FALSE,
65 ::glm::value_ptr(_Matrices.Projection));
66 glUniformMatrix4fv(MatrixViewId, 1, GL_FALSE,
67 ::glm::value_ptr(_Matrices.View));
68 glUniformMatrix4fv(MatrixViewInverseId, 1, GL_FALSE,
69 ::glm::value_ptr(_Matrices.ViewInverse));
73 static void Update(
const GLuint _ProgramId, const ::Camera & _Matrices)
75 Update(_ProgramId, _Matrices,
"MatricesData");
76 Update(_ProgramId, _Matrices,
"CameraData");
81class Support<::Object>
84 static const GLuint Index = COVELLITE_BUFFER_INDEX_OBJECT;
87 static void Update(
const GLuint _ProgramId, const ::Object & _Object)
89 const auto MatrixWorldId =
90 glGetUniformLocation(_ProgramId,
"ObjectData.World");
91 glUniformMatrix4fv(MatrixWorldId, 1, GL_FALSE,
92 ::glm::value_ptr(_Object.World));
100 static const GLuint Index = COVELLITE_BUFFER_INDEX_USER;
103class OpenGLCommonShader::Buffer
106 inline void Bind(
const bool _IsActivate =
true)
const
108 glBindBuffer(m_Type, _IsActivate ? m_BufferId : 0);
111 inline void UpdateData(
const void * _pData,
const size_t _Size)
const
113 glBufferSubData(m_Type, 0,
static_cast<GLsizeiptr
>(_Size), _pData);
116 inline void UpdateData(const ::std::string & _UniformBufferName,
117 const void * _pData,
const size_t _Size)
const
119 const auto ProgramId = glGetProgramId();
121 const auto BlockIndex = glGetUniformBlockIndex(
122 ProgramId, _UniformBufferName.c_str());
128 if (BlockIndex == GL_INVALID_INDEX)
return;
131 UpdateData(_pData, _Size);
134 glBindBufferBase(m_Type, m_Index, m_BufferId);
135 glUniformBlockBinding(ProgramId, BlockIndex, m_Index);
138 void SetVertexInputData(
void)
const
149 const auto ProgramId = glGetProgramId();
151 const auto hPosition =
static_cast<GLuint
>(
152 glGetAttribLocation(ProgramId,
"Covellite_VertexPosition"));
155 glEnableVertexAttribArray(hPosition);
156 glVertexAttribPointer(hPosition, 4, GL_FLOAT, GL_FALSE,
158 glVertexAttribDivisor(hPosition, 0);
161 const auto hTexCoord =
static_cast<GLuint
>(
162 glGetAttribLocation(ProgramId,
"Covellite_VertexTexCoord"));
165 glEnableVertexAttribArray(hTexCoord);
166 glVertexAttribPointer(hTexCoord, 2, GL_FLOAT, GL_FALSE,
168 glVertexAttribDivisor(hTexCoord, 0);
171 const auto hExtra =
static_cast<GLuint
>(
172 glGetAttribLocation(ProgramId,
"Covellite_VertexExtra"));
175 glEnableVertexAttribArray(hExtra);
176 glVertexAttribPointer(hExtra, 4, GL_FLOAT, GL_FALSE,
178 glVertexAttribDivisor(hExtra, 0);
182 void SetInstanceData(
185 const GLsizei _Stride)
187 using AttributeTypes_t = ::alicorn::extension::std::fast::unordered_map<
188 ::std::string, ::std::pair<GLint, GLenum>>;
190 constexpr auto BlockSize =
sizeof(float) * 4;
191 const auto BlockCount = _Stride / BlockSize;
194 UpdateData(_pData, _Size);
196 const auto ProgramId = glGetProgramId();
198 const auto GetAttributeTypes = [&](void) -> AttributeTypes_t
204 constexpr GLsizei NameBufferSize = 255;
205 GLsizei NameLength = 0;
207 GLchar ValueName[NameBufferSize] = { 0 };
209 GLint AttributeCount = 0;
210 glGetProgramiv(ProgramId, GL_ACTIVE_ATTRIBUTES, &AttributeCount);
212 AttributeTypes_t Result;
214 for (GLuint i = 0; i < static_cast<GLuint>(AttributeCount); i++)
216 auto iType =
static_cast<GLenum
>(-1);
217 glGetActiveAttrib(ProgramId, i, NameBufferSize, &NameLength,
218 &ValueSize, &iType, ValueName);
220 Result[ValueName] = { i,
221 (iType == GL_FLOAT_VEC4) ? GL_FLOAT :
222 (iType == GL_INT_VEC4) ? GL_INT : iType };
232 auto AttributeTypes = GetAttributeTypes();
234 for (::std::size_t i = 0; i < BlockCount; i++)
236 const auto Name =
"iValue" + ::std::to_string(i + 1);
238 const auto hInstance =
static_cast<GLuint
>(
239 glGetAttribLocation(ProgramId, Name.c_str()));
240 if (hInstance == -1)
continue;
242 glEnableVertexAttribArray(hInstance);
243 glVertexAttribPointer(hInstance, 4, AttributeTypes[Name].second,
244 GL_FALSE, _Stride, (
void*)(BlockSize * i));
245 glVertexAttribDivisor(hInstance, 1);
253 const GLuint m_Index;
260 const ::std::size_t _Size,
262 const GLuint _Index =
static_cast<GLuint
>(-1)) :
266 glGenBuffers(1, &m_BufferId);
268 glBufferData(m_Type,
static_cast<GLsizeiptr
>(_Size), _pData, _Usage);
271 const auto Error = glGetError();
272 if (Error != GL_NO_ERROR)
274 throw STD_EXCEPTION <<
"Create buffer error: " << Error;
279 Buffer(
const T * _pData, const ::std::size_t _Size) :
280 Buffer(GL_UNIFORM_BUFFER, _pData, _Size, GL_DYNAMIC_DRAW, Support<T>::Index)
285 Buffer(
const Buffer &) =
delete;
286 Buffer(Buffer &&) =
delete;
287 Buffer & operator= (
const Buffer &) =
delete;
288 Buffer & operator= (Buffer &&) =
delete;
290 ~Buffer(
void)
noexcept
292 glDeleteBuffers(1, &m_BufferId);
297class OpenGLCommonShader::ConstantBuffer :
298 public GraphicApi::Constants::Data<T>
301 void Update(
void)
const override
303 const auto ProgramId = glGetProgramId();
305 Support<T>::Update(ProgramId, Constants::Data<T>::m_Data);
308 TODO(
"Использование uniform-буфера");
335OpenGLCommonShader::OpenGLCommonShader(
336 const Data_t & _Data,
337 const String_t & _PreVersion,
338 const ::std::string & _ShaderHeader) :
339 OpenGLCommon{ _Data, _PreVersion },
340 m_pPrograms{ ::std::make_shared<Programs>(_ShaderHeader) }
342 MakeConstants<ConstantBuffer>();
345auto OpenGLCommonShader::GetUsingApi(
void)
const -> String_t
347 const auto UsingApi = OpenGLCommon::GetUsingApi();
349 LOGGER(Info) <<
"GL_VENDOR: " <<
350 (
const char *)glGetString(GL_VENDOR);
351 LOGGER(Info) <<
"GL_RENDERER: " <<
352 (
const char *)glGetString(GL_RENDERER);
353 LOGGER(Info) <<
"GL_SHADING_LANGUAGE_VERSION: " <<
354 (
const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
356 GLint ExtensionCount = 0;
357 glGetIntegerv(GL_NUM_EXTENSIONS, &ExtensionCount);
359 for (GLint i = 0; i < ExtensionCount; i++)
361 LOGGER(Info) <<
"GL_EXTENSIONS: " <<
362 (
const char *)glGetStringi(GL_EXTENSIONS,
static_cast<GLuint
>(i));
368void OpenGLCommonShader::PresentFrame(
void)
370 OpenGLCommon::PresentFrame();
375auto OpenGLCommonShader::CreateCamera(
const ComponentPtr_t & _pComponent) -> Render_t
377 const auto CameraRender = (_pComponent->Kind == uT(
"Perspective")) ?
378 GetCameraPerspective(_pComponent) : GetCameraOrthographic(_pComponent);
380 const auto CameraId = _pComponent->Id;
391 inline void Bind(
void)
const
393 GLint CurrentFrameBufferId = 0;
394 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &CurrentFrameBufferId);
395 m_CurrentFrameBufferId =
static_cast<GLuint
>(CurrentFrameBufferId);
397 glBindFramebuffer(GL_FRAMEBUFFER, m_Id);
400 inline void Unbind(
void)
const
402 glBindFramebuffer(GL_FRAMEBUFFER, m_CurrentFrameBufferId);
407 mutable GLuint m_CurrentFrameBufferId = 0;
410 FrameBuffer(
void)
noexcept
412 glGenFramebuffers(1, &m_Id);
414 FrameBuffer(
const FrameBuffer &) =
delete;
415 FrameBuffer(FrameBuffer &&) =
delete;
416 FrameBuffer & operator= (
const FrameBuffer &) =
delete;
417 FrameBuffer & operator= (FrameBuffer &&) =
delete;
418 ~FrameBuffer(
void)
noexcept
420 glDeleteFramebuffers(1, &m_Id);
424auto OpenGLCommonShader::CreateBkSurface(
425 const ComponentPtr_t & _pComponent) -> Render_t
428 using Size_t = ::std::pair<GLint, GLint>;
429 using fnBkSurfaceSize_t = ::std::function<Size_t(
void)>;
431 const auto pBkSurface = _pComponent;
433 const fnBkSurfaceSize_t GetBkSurfaceSize = [=](void)
435 GLint Viewport[4] = { 0 };
436 glGetIntegerv(GL_VIEWPORT, Viewport);
438 const int Width =
static_cast<int>(Viewport[2]);
439 const int Height =
static_cast<int>(Viewport[3]);
441 (*pBkSurface)[uT(
"width")] = Width;
442 (*pBkSurface)[uT(
"height")] = Height;
444 return Size_t{
static_cast<GLint
>(Width),
static_cast<GLint
>(Height) };
447 const auto Size = GetBkSurfaceSize();
448 const auto Width = Size.first;
449 const auto Height = Size.second;
451 const auto pFrameBuffer = ::std::make_shared<FrameBuffer>();
452 pFrameBuffer->Bind();
454 ::std::vector<GLenum> AttachmentIndexes;
455 ::std::vector<::std::pair<ComponentPtr_t, Texture::Ptr_t>> Textures;
457 const auto DoDataTexture = [&](
const ComponentPtr_t & _pDataTexture)
459 (*_pDataTexture)[uT(
"width")] = Width;
460 (*_pDataTexture)[uT(
"height")] = Height;
462 const Component::Texture TextureData{ *_pDataTexture, uT(
"diffuse") };
464 const auto pTexture = ::std::make_shared<Texture>(TextureData);
465 Textures.push_back({ _pDataTexture, pTexture });
467 if (pTexture->m_Format != GL_DEPTH_COMPONENT)
469 const auto Attachment = GL_COLOR_ATTACHMENT0 +
470 static_cast<unsigned int>(AttachmentIndexes.size());
471 AttachmentIndexes.push_back(Attachment);
472 glFramebufferTexture2D(GL_FRAMEBUFFER, Attachment, GL_TEXTURE_2D,
473 pTexture->m_TextureId, 0);
477 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
478 GL_TEXTURE_2D, pTexture->m_TextureId, 0);
481 (*_pDataTexture)[uT(
"entity")].Default(pTexture);
484 CapturingServiceComponent::Process(_pComponent,
485 { { uT(
"Texture"), DoDataTexture } });
487 const auto FramebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
488 pFrameBuffer->Unbind();
490 if (FramebufferStatus != GL_FRAMEBUFFER_COMPLETE)
492 throw STD_EXCEPTION <<
"Create Framebuffer fail: " << _pComponent->Id;
497 const auto [Width, Height] = GetBkSurfaceSize();
499 if (m_IsResizeWindow)
501 for (
const auto & Texture : Textures)
503 (*Texture.first)[uT(
"width")] = Width;
504 (*Texture.first)[uT(
"height")] = Height;
505 Texture.second->MakeContent(Width, Height,
nullptr);
509 pFrameBuffer->Bind();
510 glDrawBuffers(
static_cast<GLsizei
>(AttachmentIndexes.size()),
511 AttachmentIndexes.data());
515auto OpenGLCommonShader::CreateState(
const ComponentPtr_t & _pComponent) -> Render_t
517 if (_pComponent->Kind == uT(
"AlphaTest"))
return nullptr;
519 return OpenGLCommon::CreateState(_pComponent);
522auto OpenGLCommonShader::CreateTexture(
const ComponentPtr_t & _pComponent) -> Render_t
524 using BufferMapper_t = cbBufferMap_t<const void>;
526 const auto pTextureDataComponent = CapturingServiceComponent::Get(_pComponent,
527 { { uT(
"Texture"), _pComponent } })[0];
529 const auto pTextureData =
530 ::std::make_shared<Component::Texture>(*pTextureDataComponent, uT(
"diffuse"));
532 ::std::function<GLint(
void)> GetTexMinFilter =
533 [=](void) {
return m_TexParameters.MinFilter; };
535 Texture::Ptr_t pTexture =
536 (*pTextureDataComponent)[uT(
"entity")].Default(Texture::Ptr_t{});
537 if (pTexture ==
nullptr)
539 pTexture = ::std::make_shared<Texture>(*pTextureData);
541 if (pTextureData->IsUsingMipmapping)
543 GetTexMinFilter = [](void) {
return GL_LINEAR_MIPMAP_LINEAR; };
546 glGenerateMipmap(GL_TEXTURE_2D);
547 pTexture->Bind(
false);
552 (*pTextureDataComponent)[uT(
"entity")] = Texture::Ptr_t{};
555 const Render_t TextureRender = [=](void)
557 const auto Index = pTexture->m_Destination.first;
559 glActiveTexture(GL_TEXTURE0 + Index);
562 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GetTexMinFilter());
563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_TexParameters.MagFilter);
564 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_TexParameters.WrapS);
565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_TexParameters.WrapT);
567 const auto ProgramId = glGetProgramId();
569 const auto LocationId = glGetUniformLocation(ProgramId,
570 pTexture->m_Destination.second.c_str());
574 if (LocationId == -1)
return;
576 glUniform1i(LocationId, Index);
579 if (!(*pTextureDataComponent)[uT(
"mapper")].IsType<const BufferMapper_t &>())
581 return TextureRender;
584 const BufferMapper_t cbBufferMapper =
585 (*pTextureDataComponent)[uT(
"mapper")].Default(BufferMapper_t{});
586 const auto pFrameBuffer = ::std::make_shared<FrameBuffer>();
590 if (cbBufferMapper(
nullptr))
592 pFrameBuffer->Bind();
593 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
594 GL_TEXTURE_2D, pTexture->m_TextureId, 0);
596 auto * pData =
reinterpret_cast<uint32_t *
>(pTexture->m_ReadCopyData.data());
598 glReadPixels(0, 0, pTextureData->Width, pTextureData->Height, GL_RGBA,
599 GL_UNSIGNED_BYTE, pData);
602 for (
int y = 0; y < pTextureData->Height / 2; y++)
605 pData + (
static_cast<size_t>(y) * pTextureData->Width);
607 pData + ((
static_cast<size_t>(pTextureData->Height) - y - 1) * pTextureData->Width);
609 for (
int x = 0; x < pTextureData->Width; x++)
611 auto & Up = *(pLineUp + x);
612 auto & Down = *(pLineDown + x);
614 ::std::swap(Up, Down);
618 cbBufferMapper(pData);
619 pFrameBuffer->Unbind();
626class OpenGLCommonShader::Programs final
631 void Link(
const GLuint _VsShaderId,
const GLuint & _PsShaderId)
633 glAttachShader(Id, _VsShaderId);
634 glAttachShader(Id, _PsShaderId);
637 GLint Result = GL_FALSE;
638 glGetProgramiv(Id, GL_LINK_STATUS, &Result);
639 if (Result == GL_FALSE)
641 char InfoLog[512] = { 0 };
642 glGetProgramInfoLog(Id,
sizeof(InfoLog), NULL, InfoLog);
644 throw STD_EXCEPTION <<
"Link program fail: " << InfoLog;
652 Program(
void) noexcept :
653 Id{ glCreateProgram() }
656 Program(
const Program &) =
delete;
657 Program(Program &&) =
delete;
658 Program & operator= (
const Program &) =
delete;
659 Program & operator= (Program &&) =
delete;
660 ~Program(
void)
noexcept
673 GLint Result = GL_FALSE;
674 glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
675 if (Result == GL_FALSE)
683 ::std::vector<GLchar> InfoLog(512, 0x00);
684 glGetShaderInfoLog(Id, InfoLog.size(),
nullptr, InfoLog.data());
686 throw STD_EXCEPTION <<
"Compile shader fail "
687 <<
"[header line: " << GetHeaderLines(m_Header) <<
"]: "
693 static ::std::size_t GetHeaderLines(const ::std::string & _Header)
695 ::std::size_t Result = 0;
697 auto itPosition = _Header.cbegin();
700 itPosition = ::std::find(itPosition, _Header.cend(),
'\n');
701 if (itPosition == _Header.cend())
break;
711 Programs & m_Programs;
714 const ::std::string m_Header;
717 Shader(Programs & _Programs,
const GLenum _Type,
718 const GLchar * _Header,
const GLchar * _Body) :
719 m_Programs{ _Programs },
721 Id{ glCreateShader(_Type) },
724 const auto FullShaderBody = ::std::string{ _Header } +_Body;
725 auto pFullShaderBody = FullShaderBody.c_str();
726 glShaderSource(Id, 1, &pFullShaderBody,
nullptr);
728 Shader(
const Shader &) =
delete;
729 Shader(Shader &&) =
delete;
730 Shader & operator= (
const Shader &) =
delete;
731 Shader & operator= (Shader &&) =
delete;
732 ~Shader(
void)
noexcept
734 m_Programs.Clear(Id);
739 using ProgramPtr_t = ::std::shared_ptr<Program>;
740 using Programs_t = ::std::map<GLuint, ::std::map<GLuint, ProgramPtr_t>>;
741 using ShaderPtr_t = ::std::shared_ptr<Shader>;
744 ShaderPtr_t MakeVertex(
const Component::Shader & _ShaderData)
746 using namespace ::alicorn::extension::std;
748 const auto HeaderShaderText =
751 _ShaderData.GetInstanceInput(::Input);
753 const auto BodyShaderText = _ShaderData.Data;
755 return ::std::make_shared<Shader>(*
this, GL_VERTEX_SHADER,
757 "#define COVELLITE_SHADER_VERTEX\r\n" +
758 ::std::string{ ::std::begin(HeaderShaderText), ::std::end(HeaderShaderText) }).c_str(),
759 (::std::string{ ::std::begin(BodyShaderText), ::std::end(BodyShaderText) } +
760 "out Pixel PixelValue;\r\n"
763 " Vertex InputData;\r\n"
764 " InputData.Position = Covellite_VertexPosition;\r\n"
765 " InputData.TexCoord = Covellite_VertexTexCoord;\r\n"
766 " InputData.Extra = Covellite_VertexExtra;\r\n" +
767 _ShaderData.GetInstanceCopyData() +
768 " PixelValue = " + _ShaderData.Entry +
"(InputData);\r\n"
769 " gl_Position = PixelValue.ScreenPos;\r\n"
773 ShaderPtr_t MakePixel(
const Component::Shader & _ShaderData)
775 using namespace ::alicorn::extension::std;
777 const auto HeaderShaderText = ::Predefined + ::Data + ::Input;
778 const auto BodyShaderText = ::std::string{
779 _ShaderData.Data.cbegin(), _ShaderData.Data.cend() };
783 if (_ShaderData.ReturnType ==
"float4" ||
784 _ShaderData.ReturnType ==
"vec4")
787 "out vec4 Covellite_OutPixelColor;\r\n"
790 " Covellite_OutPixelColor = " + _ShaderData.Entry +
"(PixelValue);\r\n"
793 else if (_ShaderData.ReturnType ==
"void")
798 " " + _ShaderData.Entry +
"(PixelValue);\r\n"
806 " Covellite_MultiOutPixelColor = " + _ShaderData.Entry +
"(PixelValue).Target;\r\n"
810 return ::std::make_shared<Shader>(*
this, GL_FRAGMENT_SHADER,
812 "#define COVELLITE_SHADER_PIXEL\r\n" +
813 ::std::string{ ::std::begin(HeaderShaderText), ::std::end(HeaderShaderText) }).c_str(),
815 "in Pixel PixelValue;\r\n" +
819 void Activate(
const ShaderPtr_t & _pShader)
821 if (_pShader->Type == GL_VERTEX_SHADER) m_VsShaderId = _pShader->Id;
822 if (_pShader->Type == GL_FRAGMENT_SHADER) m_PsShaderId = _pShader->Id;
823 if (m_VsShaderId == InvalidId || m_PsShaderId == InvalidId)
return;
825 auto & pProgram = m_Programs[m_VsShaderId][m_PsShaderId];
827 if (pProgram ==
nullptr)
829 pProgram = ::std::make_shared<Program>();
830 pProgram->Link(m_VsShaderId, m_PsShaderId);
833 glUseProgram(pProgram->Id);
836 void Clear(
const GLuint _ShaderId)
838 for (
auto & VertexPrograms : m_Programs)
840 if (VertexPrograms.first == _ShaderId)
842 for (
auto & PixelPrograms : VertexPrograms.second)
844 PixelPrograms.second.reset();
850 for (
auto & PixelPrograms : VertexPrograms.second)
852 if (PixelPrograms.first == _ShaderId)
854 PixelPrograms.second.reset();
861 const ::std::string m_ShaderHeader;
862 const GLuint InvalidId =
static_cast<GLuint
>(-1);
863 GLuint m_VsShaderId = InvalidId;
864 GLuint m_PsShaderId = InvalidId;
865 const uint8_t Align[4] = { 0 };
866 Programs_t m_Programs;
869 explicit Programs(const ::std::string & _ShaderHeader) :
870 m_ShaderHeader(_ShaderHeader +
"#define COVELLITE_SHADER_GLSL\r\n")
874 Programs(
const Programs &) =
delete;
875 Programs(Programs &&) =
delete;
876 Programs & operator= (
const Programs &) =
delete;
877 Programs & operator= (Programs &&) =
delete;
878 ~Programs(
void) =
default;
881auto OpenGLCommonShader::CreateShader(
const ComponentPtr_t & _pComponent) -> Render_t
883 const auto pShaderDataComponent = CapturingServiceComponent::Get(_pComponent,
884 { { uT(
"Shader"), _pComponent } })[0];
886 const Component::Shader ShaderData{ *pShaderDataComponent, ::Default };
888 if (ShaderData.Kind == uT(
"Vertex"))
890 const auto pShader = m_pPrograms->MakeVertex(ShaderData);
895 m_pPrograms->Activate(pShader);
898 else if (ShaderData.Kind == uT(
"Pixel"))
900 const auto pShader = m_pPrograms->MakePixel(ShaderData);
905 m_pPrograms->Activate(pShader);
908# define TEST_CALL_IF(n)
911 TEST_CALL_IF(1) m_pConstants->Update<::Camera>();
920auto OpenGLCommonShader::CreateBuffer(
const ComponentPtr_t & _pBuffer) -> Render_t
922 const auto pBufferData = CapturingServiceComponent::Get(_pBuffer,
923 { { uT(
"Buffer"), _pBuffer } })[0];
925 auto CreateConstantUserBuffer = [&](void) -> Render_t
927 using Type_t = cbBufferMap_t<void>;
929 if (!(*_pBuffer)[uT(
"mapper")].IsType<const Type_t &>())
931 throw STD_EXCEPTION <<
"Unexpected buffer format [" <<
932 "id: " << _pBuffer->Id <<
", " <<
933 "type: " << _pBuffer->Type <<
", " <<
934 "kind: " << _pBuffer->Kind <<
"].";
937 const Type_t cbBufferMapper =
938 (*_pBuffer)[uT(
"mapper")].Default(Type_t{});
941 throw STD_EXCEPTION <<
"Unexpected empty mapper: " << _pBuffer->Id;
944 const ::std::size_t BufferSize =
945 (*_pBuffer)[uT(
"size")].Default((::std::size_t)0);
948 throw STD_EXCEPTION <<
"Unexpected zero size: " << _pBuffer->Id;
951 const ::std::string cbName =
952 (*_pBuffer)[uT(
"name")].Default(::std::string{
"cbUserData" });
955 ::std::make_shared<BinaryData_t>(BufferSize, (uint8_t)0x00);
957 ::std::make_shared<Buffer>(pData->data(), pData->size());
961 cbBufferMapper(pData->data());
962 pBuffer->UpdateData(cbName, pData->data(), pData->size());
966 const auto CreateVertexBuffer = [&](void) -> Render_t
969 using BufferMapper_t = cbBufferMap_t<Type_t>;
971 if (!(*pBufferData)[uT(
"content")].IsType<Buffer_t<Type_t>>())
973 return CreateConstantUserBuffer();
976 const Component::Buffer<Type_t> Info{ *pBufferData };
978 const BufferMapper_t & cbBufferMapper =
979 (*_pBuffer)[uT(
"mapper")].Default(BufferMapper_t{});
981 if (cbBufferMapper ==
nullptr)
983 const auto pBuffer = ::std::make_shared<Buffer>(GL_ARRAY_BUFFER,
984 Info.Data.data(), Info.Data.size() *
sizeof(Type_t), GL_STATIC_DRAW);
989 pBuffer->SetVertexInputData();
990 pBuffer->Bind(
false);
994 const auto pBuffer = ::std::make_shared<Buffer>(GL_ARRAY_BUFFER,
995 Info.Data.data(), Info.Data.size() *
sizeof(Type_t), GL_DYNAMIC_DRAW);
997 const auto pData = ::std::make_shared<Buffer_t<Type_t>>(Info.Data);
1003 const auto IsDirty = cbBufferMapper(
nullptr);
1006 cbBufferMapper(pData->data());
1008 pBuffer->UpdateData(pData->data(),
1009 static_cast<size_t>(pData->size() *
sizeof(Type_t)));
1012 pBuffer->SetVertexInputData();
1013 pBuffer->Bind(
false);
1017 return CreateVertexBuffer();
1020auto OpenGLCommonShader::CreateTransform(
const ComponentPtr_t & _pComponent) -> Render_t
1022 using TransformRender_t = ::std::function<void(
void)>;
1024 const auto GetPreRenderDefaultGeometry = [&](void) -> TransformRender_t
1026 const auto TransformRender = GetPreRenderGeometry(_pComponent);
1030 auto & World = m_pConstants->Get<::Object>().World;
1031 World = ::glm::identity<::glm::mat4>();
1032 TransformRender(World);
1033 World = ::glm::transpose(World);
1037 const auto GetPreRenderStaticGeometry = [&](void) -> TransformRender_t
1039 ::glm::mat4 World = ::glm::identity<::glm::mat4>();
1040 GetPreRenderGeometry(_pComponent)(World);
1041 World = ::glm::transpose(World);
1045 m_pConstants->Get<::Object>().World = World;
1049 const auto GetPreRenderBillboardGeometry = [&](void) -> TransformRender_t
1051 const auto TransformRender =
1052 OpenGLCommonShader::GetPreRenderBillboardGeometry(_pComponent);
1056 auto & World = m_pConstants->Get<::Object>().World;
1057 World = m_pConstants->Get<::Camera>().View;
1058 TransformRender(World);
1059 World = ::glm::transpose(World);
1064 TODO(
"Тест Transform.Static не проверяет, что матрица меняется у РАЗНЫХ объектов");
1067 const auto TransformRender =
1068 (_pComponent->Kind == uT(
"Unknown")) ? GetPreRenderDefaultGeometry() :
1069 (_pComponent->Kind == uT(
"Static")) ? GetPreRenderStaticGeometry() :
1070 (_pComponent->Kind == uT(
"Billboard")) ? GetPreRenderBillboardGeometry() :
1071 throw STD_EXCEPTION <<
"Unexpected transform component: " <<
1072 " [id=" << _pComponent->Id <<
", kind=" << _pComponent->Kind <<
"].";
1077 m_pConstants->Update<::Object>();
1081auto OpenGLCommonShader::CreatePresentBuffer(
const ComponentPtr_t & _pComponent) -> Render_t
1083 using BufferMapperMaxCount_t = ::std::function<bool(
void *)>;
1084 using BufferMapperChangeCount_t = ::std::function<bool(
void *, ::std::size_t &)>;
1086 ComponentPtr_t pIndexBufferData = _pComponent;
1087 ComponentPtr_t pInstanceBufferData =
nullptr;
1089 const auto SaveBuffer = [&](
const ComponentPtr_t & _pBufferData)
1091 if ((*_pBufferData)[uT(
"content")].IsType<Buffer_t<int>>())
1093 pIndexBufferData = _pBufferData;
1095 else if ((*_pBufferData)[uT(
"mapper")].IsType<const BufferMapperMaxCount_t &>())
1097 pInstanceBufferData = _pBufferData;
1099 else if ((*_pBufferData)[uT(
"mapper")].IsType<const BufferMapperChangeCount_t &>())
1101 pInstanceBufferData = _pBufferData;
1105 throw STD_EXCEPTION <<
"Unexpected Presend data component: id = " <<
1110 CapturingServiceComponent::Process(_pComponent,
1112 { uT(
"Buffer"), SaveBuffer },
1115 const Component::Buffer<int> IndexBufferData{ *pIndexBufferData };
1117 const auto pIndexBuffer = ::std::make_shared<Buffer>(GL_ELEMENT_ARRAY_BUFFER,
1118 IndexBufferData.Data.data(), IndexBufferData.Data.size() *
sizeof(
int), GL_STATIC_DRAW);
1119 const auto IndexCount =
static_cast<GLsizei
>(IndexBufferData.Data.size());
1121 if (pInstanceBufferData ==
nullptr)
1125 pIndexBuffer->Bind();
1126 glDrawElements(GL_TRIANGLES, IndexCount, GL_UNSIGNED_INT,
nullptr);
1127 pIndexBuffer->Bind(
false);
1131 const ::std::size_t BufferSize = (*pInstanceBufferData)[uT(
"size")];
1132 if (BufferSize % 16 != 0)
1134 throw STD_EXCEPTION << _pComponent->Id <<
": size % 16 != 0";
1137 const ::std::size_t MaxInstanceCount = (*pInstanceBufferData)[uT(
"count")];
1138 if (BufferSize % MaxInstanceCount != 0)
1140 throw STD_EXCEPTION << _pComponent->Id <<
": size % count != 0";
1143 const auto Stride =
static_cast<GLsizei
>(BufferSize / MaxInstanceCount);
1146 ::std::make_shared<BinaryData_t>(BufferSize, (uint8_t)0x00);
1147 const auto pInstanceBuffer = ::std::make_shared<Buffer>(GL_ARRAY_BUFFER,
1148 nullptr, BufferSize, GL_DYNAMIC_DRAW);
1150 if ((*pInstanceBufferData)[uT(
"mapper")].IsType<BufferMapperMaxCount_t>())
1152 const BufferMapperMaxCount_t cbBufferMapper =
1153 (*pInstanceBufferData)[uT(
"mapper")];
1157 const auto IsDirty = cbBufferMapper(
nullptr);
1160 cbBufferMapper(pData->data());
1161 pInstanceBuffer->SetInstanceData(pData->data(), pData->size(), Stride);
1164 pIndexBuffer->Bind();
1165 glDrawElementsInstanced(GL_TRIANGLES, IndexCount, GL_UNSIGNED_INT,
nullptr,
1166 static_cast<GLsizei
>(MaxInstanceCount));
1167 pIndexBuffer->Bind(
false);
1171 const BufferMapperChangeCount_t cbBufferMapper =
1172 (*pInstanceBufferData)[uT(
"mapper")];
1176 auto InstanceCount = MaxInstanceCount;
1178 const auto IsDirty = cbBufferMapper(
nullptr, InstanceCount);
1181 cbBufferMapper(pData->data(), InstanceCount);
1182 pInstanceBuffer->SetInstanceData(pData->data(), pData->size(), Stride);
1185 InstanceCount = ::std::min(InstanceCount, MaxInstanceCount);
1187 pIndexBuffer->Bind();
1188 glDrawElementsInstanced(GL_TRIANGLES, IndexCount, GL_UNSIGNED_INT,
nullptr,
1189 static_cast<GLsizei
>(InstanceCount));
1190 pIndexBuffer->Bind(
false);
1194auto OpenGLCommonShader::GetCameraCommon(
const ComponentPtr_t & _pComponent) -> Render_t
1196 const auto DisableDepthRender = GetDepthRender(
false,
false,
false);
1198 using Size_t = ::std::tuple<GLint, GLint>;
1199 using fnBkSurfaceSize_t = ::std::function<Size_t(
void)>;
1201 const auto pCamera = _pComponent;
1203 const fnBkSurfaceSize_t GetScaleBkSurfaceSize = [=](void)
1205 const float Scale = (*pCamera)[uT(
"scale")];
1207 const auto Width =
static_cast<GLint
>(Scale * m_Width);
1208 const auto Height =
static_cast<GLint
>(Scale * (m_Height - m_Top));
1210 return Size_t{ Width, Height };
1213 const fnBkSurfaceSize_t GetWindowBkSurfaceSize = [=](void)
1215 return Size_t{ m_Width, m_Height - m_Top };
1218 const fnBkSurfaceSize_t GetUserBkSurfaceSize = [=](void)
1220 const int Width = (*pCamera)[uT(
"width")];
1221 const int Height = (*pCamera)[uT(
"height")];
1223 return Size_t{
static_cast<GLint
>(Width),
static_cast<GLint
>(Height) };
1226 const auto IsScaleBkSurfaceSize =
1227 (*pCamera)[uT(
"scale")].IsType<
float>();
1228 const auto IsUserBkSurfaceSize =
1229 (*pCamera)[uT(
"width")].IsType<
int>() &&
1230 (*pCamera)[uT(
"height")].IsType<
int>();
1232 const auto GetBkSurfaceSize =
1233 (IsScaleBkSurfaceSize) ? GetScaleBkSurfaceSize :
1234 (IsUserBkSurfaceSize) ? GetUserBkSurfaceSize :
1235 GetWindowBkSurfaceSize;
1237 const auto [Width, Height] = GetBkSurfaceSize();
1242 glViewport(0, 0, Width, Height);
1246 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1248 DisableDepthRender();
1250 glDisable(GL_BLEND);
1251 glDisable(GL_DITHER);
1253 glEnable(GL_CULL_FACE);
1254 glCullFace(GL_BACK);
1255 glFrontFace(GL_CCW);
1257 const auto [Width, Height] = GetBkSurfaceSize();
1259 glViewport(0, 0, Width, Height);
1263auto OpenGLCommonShader::GetCameraOrthographic(
1264 const ComponentPtr_t & _pComponent) -> Render_t
1266 const auto CommonRender = GetCameraCommon(_pComponent);
1268 const auto ServiceComponents = CapturingServiceComponent::Get(_pComponent,
1270 { uT(
"Position"), api::Component::Make({}) },
1277 GLfloat Viewport[4] = { 0 };
1278 glGetFloatv(GL_VIEWPORT, Viewport);
1281 TODO(
"Тест не проверяет возможность изменения смещения во время работы программы");
1282 const Component::Position Offset{ *ServiceComponents[0] };
1284 auto & Matrix = m_pConstants->Get<::Camera>();
1286 Matrix.Projection = ::glm::transpose(::glm::ortho(
1287 Viewport[0] + Offset.X,
1288 Viewport[0] + Viewport[2] + Offset.X,
1289 Viewport[1] + Viewport[3] + Offset.Y,
1290 Viewport[1] + Offset.Y,
1292 Matrix.View = ::glm::transpose(::glm::identity<::glm::mat4>());
1293 Matrix.ViewInverse = ::glm::transpose(
1294 ::glm::inverse(::glm::identity<::glm::mat4>()));
1296 (*_pComponent)[uT(
"view")] = Matrix.View;
1297 (*_pComponent)[uT(
"projection")] = Matrix.Projection;
1301auto OpenGLCommonShader::GetCameraPerspective(
1302 const ComponentPtr_t & _pComponent) -> Render_t
1304 const auto CommonRender = GetCameraCommon(_pComponent);
1306 const auto ServiceComponents = CapturingServiceComponent::Get(_pComponent,
1308 { uT(
"Position"), api::Component::Make({}) },
1309 { uT(
"Rotation"), api::Component::Make({}) },
1316 GLfloat Viewport[4] = { 0 };
1317 glGetFloatv(GL_VIEWPORT, Viewport);
1319 auto & Matrix = m_pConstants->Get<::Camera>();
1323 const auto AngleY = (float)(*_pComponent)[uT(
"fov")].Default(90.0f) *
1324 ::alicorn::extension::cpp::math::Constant<float>::DegreeToRadian;
1325 const float zNear = (*_pComponent)[uT(
"znear")].Default(0.01f);
1326 const float zFar = (*_pComponent)[uT(
"zfar")].Default(200.0f);
1328 Matrix.Projection = ::glm::transpose(::glm::perspectiveFovRH(AngleY,
1329 Viewport[2], Viewport[3], zFar, zNear));
1334 const Component::Position Look{ *ServiceComponents[0] };
1336 const auto GetEye = [&](void) -> ::glm::vec3
1339 const float Distance = (*_pComponent)[uT(
"distance")].Default(0.0f);
1344 const Component::Position Rot{ *ServiceComponents[1] };
1346 ::glm::mat4 Transform = ::glm::identity<::glm::mat4>();
1348 Transform = ::glm::translate(Transform,
1349 ::glm::vec3{ Look.X, Look.Y, Look.Z });
1350 Transform = ::glm::rotate(Transform,
1351 Rot.Z, ::glm::vec3{ 0.0f, 0.0f, 1.0f });
1352 Transform = ::glm::rotate(Transform,
1353 Rot.Y, ::glm::vec3{ 0.0f, 1.0f, 0.0f });
1354 Transform = ::glm::rotate(Transform,
1355 Rot.X, ::glm::vec3{ 1.0f, 0.0f, 0.0f });
1357 return Transform * ::glm::vec4{ Distance + 0.1f, 0.0f, 0.0f, 1.0f };
1360 const auto View = ::glm::lookAtRH(
1362 ::glm::vec3{ Look.X, Look.Y, Look.Z },
1363 ::glm::vec3{ 0.0f, 0.0f, 1.0f });
1365 Matrix.View = ::glm::transpose(View);
1366 Matrix.ViewInverse = ::glm::transpose(::glm::inverse(View));
1368 (*_pComponent)[uT(
"view")] = Matrix.View;
1369 (*_pComponent)[uT(
"projection")] = Matrix.Projection;
Класс входит в проект Covellite.Api Класс формата вертексного буфера.
Definition Vertex.hpp:34