Minor refactoring
This commit is contained in:
1 parent
0a5a3b653d
commit
592e008914
43 files changed
+3589
-3594
No files matched your search
@@ -0,0 +1,49 @@
|
||||
#include "FrameBuffer.h"
|
||||
#include <iostream>
|
||||
#include "Environment.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
FrameBuffer::FrameBuffer(int w, int h) : width(w), height(h) {
|
||||
// 1. Ñîçäàåì FBO
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
// 2. Ñîçäàåì òåêñòóðó, êóäà áóäåì "ôîòîãðàôèðîâàòü"
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
// Óñòàíàâëèâàåì ïàðàìåòðû òåêñòóðû
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
// 3. Ïðèâÿçûâàåì òåêñòóðó ê FBO
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
|
||||
|
||||
// Ïðîâåðêà ãîòîâíîñòè
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
std::cerr << "Error: Framebuffer is not complete!" << std::endl;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
FrameBuffer::~FrameBuffer() {
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
glDeleteTextures(1, &textureID);
|
||||
}
|
||||
|
||||
void FrameBuffer::Bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glViewport(0, 0, width, height); // Âàæíî: óñòàíàâëèâàåì âüþïîðò ïîä ðàçìåð òåêñòóðû
|
||||
}
|
||||
|
||||
void FrameBuffer::Unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
// Çäåñü æåëàòåëüíî âîçâðàùàòü âüþïîðò ê ðàçìåðàì ýêðàíà,
|
||||
// íàïðèìåð, ÷åðåç Environment::width/height
|
||||
glViewport(0, 0, Environment::width, Environment::height);
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "OpenGlExtensions.h"
|
||||
#include <memory>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
class FrameBuffer {
|
||||
private:
|
||||
GLuint fbo = 0;
|
||||
GLuint textureID = 0;
|
||||
int width, height;
|
||||
|
||||
public:
|
||||
FrameBuffer(int w, int h);
|
||||
~FrameBuffer();
|
||||
|
||||
// Çàïðåùàåì êîïèðîâàíèå, êàê â VBOHolder
|
||||
FrameBuffer(const FrameBuffer&) = delete;
|
||||
FrameBuffer& operator=(const FrameBuffer&) = delete;
|
||||
|
||||
void Bind(); // Íà÷àòü ðåíäåð â ýòîò áóôåð
|
||||
void Unbind(); // Âåðíóòüñÿ ê îáû÷íîìó ðåíäåðó â ýêðàí
|
||||
|
||||
GLuint getTextureID() const { return textureID; }
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
@@ -0,0 +1,335 @@
|
||||
#include "OpenGlExtensions.h"
|
||||
|
||||
#include "utils/Utils.h"
|
||||
#include <iostream>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
//====================================================
|
||||
//===================== GLSL Shaders =================
|
||||
//====================================================
|
||||
|
||||
//Requires GL_VERSION_2_0
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram = NULL;
|
||||
PFNGLDELETEPROGRAMPROC glDeleteProgram = NULL;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram = NULL;
|
||||
PFNGLVALIDATEPROGRAMPROC glValidateProgram = NULL;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram = NULL;
|
||||
PFNGLGETPROGRAMIVPROC glGetProgramiv = NULL;
|
||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = NULL;
|
||||
PFNGLCREATESHADERPROC glCreateShader = NULL;
|
||||
PFNGLDELETESHADERPROC glDeleteShader = NULL;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource = NULL;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader = NULL;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = NULL;
|
||||
PFNGLDETACHSHADERPROC glDetachShader = NULL;
|
||||
PFNGLGETSHADERIVPROC glGetShaderiv = NULL;
|
||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = NULL;
|
||||
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = NULL;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = NULL;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = NULL;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = NULL;
|
||||
PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv = NULL;
|
||||
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = NULL;
|
||||
PFNGLUNIFORM1IPROC glUniform1i = NULL;
|
||||
PFNGLUNIFORM1FVPROC glUniform1fv = NULL;
|
||||
PFNGLUNIFORM3FVPROC glUniform2fv = NULL;
|
||||
PFNGLUNIFORM3FVPROC glUniform3fv = NULL;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv = NULL;
|
||||
PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f = NULL;
|
||||
PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f = NULL;
|
||||
PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f = NULL;
|
||||
PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = NULL;
|
||||
PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv = NULL;
|
||||
PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv = NULL;
|
||||
PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv = NULL;
|
||||
PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib = NULL;
|
||||
PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform = NULL;
|
||||
|
||||
|
||||
//=======================================
|
||||
//=========== Multitexture ==============
|
||||
//=======================================
|
||||
|
||||
//Requires GL version 1.3
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture = NULL;
|
||||
|
||||
//=======================================
|
||||
//========== Vertex buffer ==============
|
||||
//=======================================
|
||||
|
||||
//Requires GL_VERSION_1_5
|
||||
PFNGLGENBUFFERSPROC glGenBuffers = NULL;
|
||||
PFNGLDELETEBUFFERSPROC glDeleteBuffers = NULL;
|
||||
PFNGLBINDBUFFERPROC glBindBuffer = NULL;
|
||||
PFNGLBUFFERDATAPROC glBufferData = NULL;
|
||||
PFNGLBUFFERSUBDATAPROC glBufferSubData = NULL;
|
||||
PFNGLMAPBUFFERPROC glMapBuffer = NULL;
|
||||
PFNGLUNMAPBUFFERPROC glUnmapBuffer = NULL;
|
||||
|
||||
//=========================================
|
||||
//============ Frame buffer ===============
|
||||
//=========================================
|
||||
|
||||
//Requires GL_ARB_framebuffer_object
|
||||
PFNGLISRENDERBUFFERPROC glIsRenderbuffer = NULL;
|
||||
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = NULL;
|
||||
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = NULL;
|
||||
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = NULL;
|
||||
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = NULL;
|
||||
PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = NULL;
|
||||
PFNGLISFRAMEBUFFERPROC glIsFramebuffer = NULL;
|
||||
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL;
|
||||
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL;
|
||||
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = NULL;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = NULL;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = NULL;
|
||||
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
|
||||
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
|
||||
PFNGLGENERATEMIPMAPPROC glGenerateMipmap = NULL;
|
||||
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
|
||||
|
||||
|
||||
|
||||
//===========================================
|
||||
//============ Uniform buffer ===============
|
||||
//===========================================
|
||||
|
||||
//Requires GL_ARB_uniform_buffer_object
|
||||
PFNGLGETUNIFORMINDICESPROC glGetUniformIndices = NULL;
|
||||
PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv = NULL;
|
||||
PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName = NULL;
|
||||
PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = NULL;
|
||||
PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv = NULL;
|
||||
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = NULL;
|
||||
PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = NULL;
|
||||
PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
|
||||
|
||||
|
||||
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
|
||||
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
|
||||
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArray = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
namespace ZL {
|
||||
|
||||
bool BindOpenGlFunctions()
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
//char* extensionList = (char*)glGetString(GL_EXTENSIONS);
|
||||
char* glVersion = (char*)glGetString(GL_VERSION);
|
||||
bool ok = true;
|
||||
|
||||
//Requires OpenGL 2.0 or above
|
||||
if (glVersion[0] >= '2')
|
||||
{
|
||||
|
||||
glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
|
||||
|
||||
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
|
||||
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
|
||||
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
|
||||
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
|
||||
glBufferSubData = (PFNGLBUFFERSUBDATAPROC)wglGetProcAddress("glBufferSubData");
|
||||
glMapBuffer = (PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer");
|
||||
glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)wglGetProcAddress("glUnmapBuffer");
|
||||
|
||||
glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
|
||||
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)wglGetProcAddress("glDeleteProgram");
|
||||
glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
|
||||
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)wglGetProcAddress("glValidateProgram");
|
||||
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
|
||||
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
|
||||
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog");
|
||||
glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
|
||||
|
||||
|
||||
glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader");
|
||||
glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
|
||||
glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
|
||||
glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
|
||||
glDetachShader = (PFNGLDETACHSHADERPROC)wglGetProcAddress("glDetachShader");
|
||||
glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
|
||||
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
|
||||
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)wglGetProcAddress("glGetAttribLocation");
|
||||
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
|
||||
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
|
||||
|
||||
glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glDisableVertexAttribArray");
|
||||
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
|
||||
glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)wglGetProcAddress("glUniformMatrix3fv");
|
||||
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
|
||||
glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
|
||||
glUniform1fv = (PFNGLUNIFORM1FVPROC)wglGetProcAddress("glUniform1fv");
|
||||
glUniform2fv = (PFNGLUNIFORM2FVPROC)wglGetProcAddress("glUniform2fv");
|
||||
glUniform3fv = (PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv");
|
||||
glUniform4fv = (PFNGLUNIFORM4FVPROC)wglGetProcAddress("glUniform4fv");
|
||||
|
||||
glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)wglGetProcAddress("glVertexAttrib1f");
|
||||
glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)wglGetProcAddress("glVertexAttrib2f");
|
||||
glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)wglGetProcAddress("glVertexAttrib3f");
|
||||
glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)wglGetProcAddress("glVertexAttrib4f");
|
||||
glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)wglGetProcAddress("glVertexAttrib2fv");
|
||||
glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)wglGetProcAddress("glVertexAttrib3fv");
|
||||
glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)wglGetProcAddress("glVertexAttrib4fv");
|
||||
glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)wglGetProcAddress("glGetActiveAttrib");
|
||||
glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)wglGetProcAddress("glGetActiveUniform");
|
||||
|
||||
|
||||
if (glActiveTexture == NULL ||
|
||||
glGenBuffers == NULL ||
|
||||
glDeleteBuffers == NULL ||
|
||||
glBindBuffer == NULL ||
|
||||
glBufferData == NULL ||
|
||||
glBufferSubData == NULL ||
|
||||
glMapBuffer == NULL ||
|
||||
glCreateProgram == NULL ||
|
||||
glDeleteProgram == NULL ||
|
||||
glLinkProgram == NULL ||
|
||||
glValidateProgram == NULL ||
|
||||
glUseProgram == NULL ||
|
||||
glGetProgramiv == NULL ||
|
||||
glGetProgramInfoLog == NULL ||
|
||||
glCreateShader == NULL ||
|
||||
glDeleteShader == NULL ||
|
||||
glShaderSource == NULL ||
|
||||
glCompileShader == NULL ||
|
||||
glAttachShader == NULL ||
|
||||
glDetachShader == NULL ||
|
||||
glGetShaderiv == NULL ||
|
||||
glGetShaderInfoLog == NULL ||
|
||||
glGetAttribLocation == NULL ||
|
||||
glVertexAttribPointer == NULL ||
|
||||
glEnableVertexAttribArray == NULL ||
|
||||
glDisableVertexAttribArray == NULL ||
|
||||
glGetUniformLocation == NULL ||
|
||||
glUniformMatrix3fv == NULL ||
|
||||
glUniformMatrix4fv == NULL ||
|
||||
glUniform1i == NULL ||
|
||||
glUniform1fv == NULL ||
|
||||
glUniform2fv == NULL ||
|
||||
glUniform3fv == NULL ||
|
||||
glUniform4fv == NULL ||
|
||||
glEnableVertexAttribArray == NULL ||
|
||||
glVertexAttrib1f == NULL ||
|
||||
glVertexAttrib2f == NULL ||
|
||||
glVertexAttrib3f == NULL ||
|
||||
glVertexAttrib4f == NULL ||
|
||||
glVertexAttrib2fv == NULL ||
|
||||
glVertexAttrib3fv == NULL ||
|
||||
glVertexAttrib4fv == NULL ||
|
||||
glGetActiveAttrib == NULL ||
|
||||
glGetActiveUniform == NULL)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer");
|
||||
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer");
|
||||
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffers");
|
||||
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers");
|
||||
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorage");
|
||||
glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameteriv");
|
||||
glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebuffer");
|
||||
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer");
|
||||
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers");
|
||||
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers");
|
||||
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus");
|
||||
glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1D");
|
||||
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D");
|
||||
glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3D");
|
||||
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbuffer");
|
||||
glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameteriv");
|
||||
glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress("glBlitFramebuffer");
|
||||
glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)wglGetProcAddress("glRenderbufferStorageMultisample");
|
||||
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap");
|
||||
glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)wglGetProcAddress("glFramebufferTextureLayer");
|
||||
|
||||
if (glIsRenderbuffer == NULL ||
|
||||
glBindRenderbuffer == NULL ||
|
||||
glDeleteRenderbuffers == NULL ||
|
||||
glGenRenderbuffers == NULL ||
|
||||
glRenderbufferStorage == NULL ||
|
||||
glGetRenderbufferParameteriv == NULL ||
|
||||
glIsFramebuffer == NULL ||
|
||||
glBindFramebuffer == NULL ||
|
||||
glDeleteFramebuffers == NULL ||
|
||||
glGenFramebuffers == NULL ||
|
||||
glCheckFramebufferStatus == NULL ||
|
||||
glFramebufferTexture1D == NULL ||
|
||||
glFramebufferTexture2D == NULL ||
|
||||
glFramebufferTexture3D == NULL ||
|
||||
glFramebufferRenderbuffer == NULL ||
|
||||
glGetFramebufferAttachmentParameteriv == NULL ||
|
||||
glBlitFramebuffer == NULL ||
|
||||
glRenderbufferStorageMultisample == NULL ||
|
||||
glGenerateMipmap == NULL ||
|
||||
glFramebufferTextureLayer == NULL)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)wglGetProcAddress("glGetUniformIndices");
|
||||
glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)wglGetProcAddress("glGetActiveUniformsiv");
|
||||
glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)wglGetProcAddress("glGetActiveUniformName");
|
||||
glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)wglGetProcAddress("glGetUniformBlockIndex");
|
||||
glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)wglGetProcAddress("glGetActiveUniformBlockiv");
|
||||
glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)wglGetProcAddress("glGetActiveUniformBlockName");
|
||||
glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)wglGetProcAddress("glUniformBlockBinding");
|
||||
glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)wglGetProcAddress("glBindBufferBase");
|
||||
|
||||
if (glGetUniformIndices == NULL ||
|
||||
glGetActiveUniformsiv == NULL ||
|
||||
glGetActiveUniformName == NULL ||
|
||||
glGetUniformBlockIndex == NULL ||
|
||||
glGetActiveUniformBlockiv == NULL ||
|
||||
glGetActiveUniformBlockName == NULL ||
|
||||
glUniformBlockBinding == NULL ||
|
||||
glBindBufferBase == NULL)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
|
||||
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
|
||||
glDeleteVertexArray = (PFNGLDELETEVERTEXARRAYSPROC)wglGetProcAddress("glBindVertexArray");
|
||||
|
||||
if (glGenVertexArrays == NULL ||
|
||||
glBindVertexArray == NULL ||
|
||||
glDeleteVertexArray == NULL)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
return ok;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CheckGlError()
|
||||
{
|
||||
size_t error = glGetError();
|
||||
if (error != GL_NO_ERROR)
|
||||
{
|
||||
throw std::runtime_error("Gl error");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "SDL.h"
|
||||
#ifdef EMSCRIPTEN
|
||||
//#define GL_GLEXT_PROTOTYPES 1
|
||||
//#define EGL_EGLEXT_PROTOTYPES 1
|
||||
//#include <SDL2/SDL_opengl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include "emscripten.h"
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||
|
||||
//#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include "gl/gl.h"
|
||||
#include "gl/glu.h"
|
||||
#include "gl/glext.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
//Requires GL_VERSION_2_0
|
||||
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||
extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||
extern PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||
extern PFNGLVALIDATEPROGRAMPROC glValidateProgram;
|
||||
extern PFNGLUSEPROGRAMPROC glUseProgram;
|
||||
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
||||
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||
extern PFNGLCREATESHADERPROC glCreateShader;
|
||||
extern PFNGLDELETESHADERPROC glDeleteShader;
|
||||
extern PFNGLSHADERSOURCEPROC glShaderSource;
|
||||
extern PFNGLCOMPILESHADERPROC glCompileShader;
|
||||
extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||
extern PFNGLDETACHSHADERPROC glDetachShader;
|
||||
extern PFNGLGETSHADERIVPROC glGetShaderiv;
|
||||
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||
extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
|
||||
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
||||
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||
extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
|
||||
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
||||
extern PFNGLUNIFORM1IPROC glUniform1i;
|
||||
extern PFNGLUNIFORM1FVPROC glUniform1fv;
|
||||
extern PFNGLUNIFORM3FVPROC glUniform2fv;
|
||||
extern PFNGLUNIFORM3FVPROC glUniform3fv;
|
||||
extern PFNGLUNIFORM4FVPROC glUniform4fv;
|
||||
extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
|
||||
extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f;
|
||||
extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f;
|
||||
extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
|
||||
extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv;
|
||||
extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv;
|
||||
extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv;
|
||||
extern PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
|
||||
extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
|
||||
|
||||
|
||||
//=======================================
|
||||
//=========== Multitexture ==============
|
||||
//=======================================
|
||||
|
||||
//Requires GL version 1.3
|
||||
extern PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||
|
||||
//=======================================
|
||||
//========== Vertex buffer ==============
|
||||
//=======================================
|
||||
|
||||
//Requires GL_VERSION_1_5
|
||||
extern PFNGLGENBUFFERSPROC glGenBuffers;
|
||||
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
|
||||
extern PFNGLBINDBUFFERPROC glBindBuffer;
|
||||
extern PFNGLBUFFERDATAPROC glBufferData;
|
||||
extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
|
||||
extern PFNGLMAPBUFFERPROC glMapBuffer;
|
||||
extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
|
||||
|
||||
//=========================================
|
||||
//============ Frame buffer ===============
|
||||
//=========================================
|
||||
|
||||
//Requires GL_ARB_framebuffer_object
|
||||
extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
|
||||
extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
|
||||
extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
|
||||
extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
|
||||
extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
|
||||
extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
|
||||
extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
|
||||
extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||
extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
|
||||
extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
|
||||
extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
|
||||
extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
|
||||
extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
|
||||
extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
|
||||
|
||||
|
||||
|
||||
//===========================================
|
||||
//============ Uniform buffer ===============
|
||||
//===========================================
|
||||
|
||||
//Requires GL_ARB_uniform_buffer_object
|
||||
extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices;
|
||||
extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv;
|
||||
extern PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName;
|
||||
extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
|
||||
extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv;
|
||||
extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName;
|
||||
extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
|
||||
extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
|
||||
|
||||
|
||||
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
||||
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArray;
|
||||
#else
|
||||
|
||||
#endif
|
||||
namespace ZL {
|
||||
|
||||
|
||||
|
||||
bool BindOpenGlFunctions();
|
||||
|
||||
void CheckGlError();
|
||||
}
|
||||
@@ -0,0 +1,833 @@
|
||||
#include "render/Renderer.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
VBOHolder::VBOHolder()
|
||||
{
|
||||
glGenBuffers(1, &Buffer);
|
||||
}
|
||||
|
||||
VBOHolder::~VBOHolder()
|
||||
{
|
||||
glDeleteBuffers(1, &Buffer);
|
||||
}
|
||||
|
||||
GLuint VBOHolder::getBuffer()
|
||||
{
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
VAOHolder::VAOHolder()
|
||||
{
|
||||
#ifndef EMSCRIPTEN
|
||||
glGenVertexArrays(1, &vao);
|
||||
#endif
|
||||
}
|
||||
|
||||
VAOHolder::~VAOHolder()
|
||||
{
|
||||
#ifndef EMSCRIPTEN
|
||||
|
||||
#ifdef __linux__
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
#else
|
||||
//Windows
|
||||
glDeleteVertexArray(1, &vao);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
GLuint VAOHolder::getBuffer()
|
||||
{
|
||||
return vao;
|
||||
}
|
||||
|
||||
|
||||
VertexDataStruct CreateRect2D(Vector2f center, Vector2f halfWidthHeight, float zLevel)
|
||||
{
|
||||
Vector2f posFrom = center - halfWidthHeight;
|
||||
|
||||
Vector2f posTo = center + halfWidthHeight;
|
||||
|
||||
Vector3f pos1 = { posFrom.v[0], posFrom.v[1], zLevel };
|
||||
Vector3f pos2 = { posFrom.v[0], posTo.v[1], zLevel };
|
||||
Vector3f pos3 = { posTo.v[0], posTo.v[1], zLevel };
|
||||
Vector3f pos4 = { posTo.v[0], posFrom.v[1], zLevel };
|
||||
|
||||
|
||||
Vector2f texCoordPos1 = { 0.0f, 0.0f };
|
||||
Vector2f texCoordPos2 = { 0.0f, 1.0f };
|
||||
Vector2f texCoordPos3 = { 1.0f, 1.0f };
|
||||
Vector2f texCoordPos4 = { 1.0f, 0.0f };
|
||||
|
||||
VertexDataStruct result;
|
||||
|
||||
result.PositionData.push_back(pos1);
|
||||
result.PositionData.push_back(pos2);
|
||||
result.PositionData.push_back(pos3);
|
||||
result.PositionData.push_back(pos3);
|
||||
result.PositionData.push_back(pos4);
|
||||
result.PositionData.push_back(pos1);
|
||||
|
||||
result.TexCoordData.push_back(texCoordPos1);
|
||||
result.TexCoordData.push_back(texCoordPos2);
|
||||
result.TexCoordData.push_back(texCoordPos3);
|
||||
result.TexCoordData.push_back(texCoordPos3);
|
||||
result.TexCoordData.push_back(texCoordPos4);
|
||||
result.TexCoordData.push_back(texCoordPos1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VertexDataStruct CreateRectHorizontalSections2D(Vector2f center, Vector2f halfWidthHeight, float zLevel, size_t sectionCount)
|
||||
{
|
||||
Vector2f posFrom = center - halfWidthHeight;
|
||||
|
||||
Vector2f posTo = center + halfWidthHeight;
|
||||
|
||||
float sectionWidth = halfWidthHeight.v[0] * 2.f;
|
||||
|
||||
VertexDataStruct result;
|
||||
|
||||
for (size_t i = 0; i < sectionCount; i++)
|
||||
{
|
||||
Vector3f pos1 = { posFrom.v[0]+sectionWidth*i, posFrom.v[1], zLevel };
|
||||
Vector3f pos2 = { posFrom.v[0] + sectionWidth * i, posTo.v[1], zLevel };
|
||||
Vector3f pos3 = { posTo.v[0] + sectionWidth * i, posTo.v[1], zLevel };
|
||||
Vector3f pos4 = { posTo.v[0] + sectionWidth * i, posFrom.v[1], zLevel };
|
||||
|
||||
result.PositionData.push_back(pos1);
|
||||
result.PositionData.push_back(pos2);
|
||||
result.PositionData.push_back(pos3);
|
||||
result.PositionData.push_back(pos3);
|
||||
result.PositionData.push_back(pos4);
|
||||
result.PositionData.push_back(pos1);
|
||||
|
||||
Vector2f texCoordPos1 = { 0.0f, 0.0f };
|
||||
Vector2f texCoordPos2 = { 0.0f, 1.0f };
|
||||
Vector2f texCoordPos3 = { 1.0f, 1.0f };
|
||||
Vector2f texCoordPos4 = { 1.0f, 0.0f };
|
||||
|
||||
result.TexCoordData.push_back(texCoordPos1);
|
||||
result.TexCoordData.push_back(texCoordPos2);
|
||||
result.TexCoordData.push_back(texCoordPos3);
|
||||
result.TexCoordData.push_back(texCoordPos3);
|
||||
result.TexCoordData.push_back(texCoordPos4);
|
||||
result.TexCoordData.push_back(texCoordPos1);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
VertexDataStruct CreateCube3D(float scale)
|
||||
{
|
||||
|
||||
std::array<std::array<Vector3f, 4>, 6> cubeSides;
|
||||
|
||||
std::array<Vector3f, 6> cubeColors;
|
||||
|
||||
|
||||
cubeSides[0][0] = { -1, -1, -1 };
|
||||
cubeSides[0][1] = { -1, 1, -1 };
|
||||
cubeSides[0][2] = { 1, 1, -1 };
|
||||
cubeSides[0][3] = { 1, -1, -1 };
|
||||
|
||||
cubeSides[1][0] = { -1, -1, 1 };
|
||||
cubeSides[1][1] = { -1, 1, 1 };
|
||||
cubeSides[1][2] = { 1, 1, 1 };
|
||||
cubeSides[1][3] = { 1, -1, 1 };
|
||||
|
||||
//------------
|
||||
|
||||
cubeSides[2][0] = { -1, -1, -1 };
|
||||
cubeSides[2][1] = { -1, -1, 1 };
|
||||
cubeSides[2][2] = { 1, -1, 1 };
|
||||
cubeSides[2][3] = { 1, -1, -1 };
|
||||
|
||||
cubeSides[3][0] = { -1, 1, -1 };
|
||||
cubeSides[3][1] = { -1, 1, 1 };
|
||||
cubeSides[3][2] = { 1, 1, 1 };
|
||||
cubeSides[3][3] = { 1, 1, -1 };
|
||||
|
||||
//------------
|
||||
cubeSides[4][0] = { -1, -1, -1 };
|
||||
cubeSides[4][1] = { -1, -1, 1 };
|
||||
cubeSides[4][2] = { -1, 1, 1 };
|
||||
cubeSides[4][3] = { -1, 1, -1 };
|
||||
|
||||
cubeSides[5][0] = { 1, -1, -1 };
|
||||
cubeSides[5][1] = { 1, -1, 1 };
|
||||
cubeSides[5][2] = { 1, 1, 1 };
|
||||
cubeSides[5][3] = { 1, 1, -1 };
|
||||
|
||||
//-----------
|
||||
|
||||
cubeColors[0] = Vector3f{ 1, 0, 0 };
|
||||
cubeColors[1] = Vector3f{ 0, 1, 0 };
|
||||
cubeColors[2] = Vector3f{ 0, 0, 1 };
|
||||
cubeColors[3] = Vector3f{ 1, 1, 0 };
|
||||
cubeColors[4] = Vector3f{ 0, 1, 1 };
|
||||
cubeColors[5] = Vector3f{ 1, 0, 1 };
|
||||
|
||||
//-----------
|
||||
|
||||
VertexDataStruct result;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
result.PositionData.push_back(cubeSides[i][0] * scale);
|
||||
result.PositionData.push_back(cubeSides[i][1] * scale);
|
||||
result.PositionData.push_back(cubeSides[i][2] * scale);
|
||||
result.PositionData.push_back(cubeSides[i][2] * scale);
|
||||
result.PositionData.push_back(cubeSides[i][3] * scale);
|
||||
result.PositionData.push_back(cubeSides[i][0] * scale);
|
||||
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
result.ColorData.push_back(cubeColors[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VertexDataStruct CreateCubemap(float scale)
|
||||
{
|
||||
VertexDataStruct cubemapVertexDataStruct;
|
||||
|
||||
// +x
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, scale });
|
||||
|
||||
// -x
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, scale });
|
||||
|
||||
|
||||
// +y
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, scale });
|
||||
|
||||
|
||||
// -y
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, scale });
|
||||
|
||||
|
||||
// +z
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, scale });
|
||||
|
||||
// -z
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, -scale });
|
||||
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, -scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ scale, scale, -scale });
|
||||
cubemapVertexDataStruct.PositionData.push_back({ -scale, scale, -scale });
|
||||
|
||||
return cubemapVertexDataStruct;
|
||||
|
||||
}
|
||||
|
||||
void VertexRenderStruct::RefreshVBO()
|
||||
{
|
||||
//Check if main thread, check if data is not empty...
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
if (!vao)
|
||||
{
|
||||
vao = std::make_shared<VAOHolder>();
|
||||
}
|
||||
|
||||
glBindVertexArray(vao->getBuffer());
|
||||
#endif
|
||||
if (!positionVBO)
|
||||
{
|
||||
positionVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, positionVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.PositionData.size() * 12, &data.PositionData[0], GL_STATIC_DRAW);
|
||||
|
||||
if (data.TexCoordData.size() > 0)
|
||||
{
|
||||
if (!texCoordVBO)
|
||||
{
|
||||
texCoordVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, texCoordVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.TexCoordData.size() * 8, &data.TexCoordData[0], GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
if (data.NormalData.size() > 0)
|
||||
{
|
||||
if (!normalVBO)
|
||||
{
|
||||
normalVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, normalVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.NormalData.size() * 12, &data.NormalData[0], GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
if (data.TangentData.size() > 0)
|
||||
{
|
||||
if (!tangentVBO)
|
||||
{
|
||||
tangentVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tangentVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.TangentData.size() * 12, &data.TangentData[0], GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
if (data.BinormalData.size() > 0)
|
||||
{
|
||||
if (!binormalVBO)
|
||||
{
|
||||
binormalVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, binormalVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.BinormalData.size() * 12, &data.BinormalData[0], GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
if (data.ColorData.size() > 0)
|
||||
{
|
||||
if (!colorVBO)
|
||||
{
|
||||
colorVBO = std::make_shared<VBOHolder>();
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, colorVBO->getBuffer());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.ColorData.size() * 12, &data.ColorData[0], GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDataStruct::Scale(float scale)
|
||||
{
|
||||
for (int i = 0; i < PositionData.size(); i++)
|
||||
{
|
||||
PositionData[i] = PositionData[i] * scale;
|
||||
}
|
||||
}
|
||||
void VertexDataStruct::Move(Vector3f diff)
|
||||
{
|
||||
for (int i = 0; i < PositionData.size(); i++)
|
||||
{
|
||||
PositionData[i] = PositionData[i] + diff;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDataStruct::SwapZandY()
|
||||
{
|
||||
for (int i = 0; i < PositionData.size(); i++)
|
||||
{
|
||||
auto value = PositionData[i].v[1];
|
||||
PositionData[i].v[1] = PositionData[i].v[2];
|
||||
PositionData[i].v[2] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VertexDataStruct::RotateByMatrix(Matrix3f m)
|
||||
{
|
||||
|
||||
for (int i = 0; i < PositionData.size(); i++)
|
||||
{
|
||||
PositionData[i] = MultVectorMatrix(PositionData[i], m);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NormalData.size(); i++)
|
||||
{
|
||||
NormalData[i] = MultVectorMatrix(NormalData[i], m);
|
||||
}
|
||||
|
||||
for (int i = 0; i < TangentData.size(); i++)
|
||||
{
|
||||
TangentData[i] = MultVectorMatrix(TangentData[i], m);
|
||||
}
|
||||
|
||||
for (int i = 0; i < BinormalData.size(); i++)
|
||||
{
|
||||
BinormalData[i] = MultVectorMatrix(BinormalData[i], m);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexRenderStruct::AssignFrom(const VertexDataStruct& v)
|
||||
{
|
||||
data = v;
|
||||
RefreshVBO();
|
||||
}
|
||||
|
||||
void Renderer::InitOpenGL()
|
||||
{
|
||||
ModelviewMatrixStack.push(Matrix4f::Identity());
|
||||
ProjectionMatrixStack.push(Matrix4f::Identity());
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
#endif
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
CheckGlError();
|
||||
}
|
||||
|
||||
void Renderer::PushProjectionMatrix(float width, float height, float zNear, float zFar)
|
||||
{
|
||||
Matrix4f m = MakeOrthoMatrix(width, height, zNear, zFar);
|
||||
ProjectionMatrixStack.push(m);
|
||||
SetMatrix();
|
||||
|
||||
if (ProjectionMatrixStack.size() > CONST_MATRIX_STACK_SIZE)
|
||||
{
|
||||
throw std::runtime_error("Projection matrix stack overflow!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::PushProjectionMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar)
|
||||
{
|
||||
Matrix4f m = MakeOrthoMatrix(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||
ProjectionMatrixStack.push(m);
|
||||
SetMatrix();
|
||||
|
||||
if (ProjectionMatrixStack.size() > CONST_MATRIX_STACK_SIZE)
|
||||
{
|
||||
throw std::runtime_error("Projection matrix stack overflow!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar)
|
||||
{
|
||||
Matrix4f m = MakePerspectiveMatrix(fovY, aspectRatio, zNear, zFar);
|
||||
ProjectionMatrixStack.push(m);
|
||||
SetMatrix();
|
||||
|
||||
if (ProjectionMatrixStack.size() > CONST_MATRIX_STACK_SIZE)
|
||||
{
|
||||
throw std::runtime_error("Projection matrix stack overflow!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::PopProjectionMatrix()
|
||||
{
|
||||
if (ProjectionMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Projection matrix stack underflow!!!!");
|
||||
}
|
||||
ProjectionMatrixStack.pop();
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
Matrix4f Renderer::GetProjectionModelViewMatrix()
|
||||
{
|
||||
return ProjectionModelViewMatrix;
|
||||
}
|
||||
|
||||
Matrix4f Renderer::GetCurrentModelViewMatrix()
|
||||
{
|
||||
return ModelviewMatrixStack.top();
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetMatrix()
|
||||
{
|
||||
if (ProjectionMatrixStack.size() <= 0)
|
||||
{
|
||||
throw std::runtime_error("Projection matrix stack out!");
|
||||
}
|
||||
|
||||
if (ModelviewMatrixStack.size() <= 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack out!");
|
||||
}
|
||||
|
||||
Matrix4f& modelViewMatrix = ModelviewMatrixStack.top();
|
||||
ProjectionModelViewMatrix = ProjectionMatrixStack.top() * modelViewMatrix;
|
||||
|
||||
static const std::string ProjectionModelViewMatrixName = "ProjectionModelViewMatrix";
|
||||
|
||||
RenderUniformMatrix4fv(ProjectionModelViewMatrixName, false, &ProjectionModelViewMatrix.m[0]);
|
||||
|
||||
static const std::string ModelViewMatrixName = "ModelViewMatrix";
|
||||
|
||||
RenderUniformMatrix4fv(ModelViewMatrixName, false, &modelViewMatrix.m[0]);
|
||||
|
||||
}
|
||||
|
||||
void Renderer::PushMatrix()
|
||||
{
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.push(ModelviewMatrixStack.top());
|
||||
|
||||
if (ModelviewMatrixStack.size() > CONST_MATRIX_STACK_SIZE)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack overflow!!!!");
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::LoadIdentity()
|
||||
{
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(Matrix4f::Identity());
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::TranslateMatrix(const Vector3f& p)
|
||||
{
|
||||
|
||||
Matrix4f m = Matrix4f::Identity();
|
||||
m.m[12] = p.v[0];
|
||||
m.m[13] = p.v[1];
|
||||
m.m[14] = p.v[2];
|
||||
|
||||
m = ModelviewMatrixStack.top() * m;
|
||||
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(m);
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::ScaleMatrix(float scale)
|
||||
{
|
||||
Matrix4f m = Matrix4f::Identity();
|
||||
m.m[0] = scale;
|
||||
m.m[5] = scale;
|
||||
m.m[10] = scale;
|
||||
|
||||
m = ModelviewMatrixStack.top() * m;
|
||||
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(m);
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::ScaleMatrix(const Vector3f& scale)
|
||||
{
|
||||
Matrix4f m = Matrix4f::Identity();
|
||||
m.m[0] = scale.v[0];
|
||||
m.m[5] = scale.v[1];
|
||||
m.m[10] = scale.v[2];
|
||||
|
||||
m = ModelviewMatrixStack.top() * m;
|
||||
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(m);
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::RotateMatrix(const Vector4f& q)
|
||||
{
|
||||
|
||||
Matrix3f m3 = QuatToMatrix(q);
|
||||
Matrix4f m = Matrix4f::Identity();
|
||||
m.m[0] = m3.m[0];
|
||||
m.m[1] = m3.m[1];
|
||||
m.m[2] = m3.m[2];
|
||||
|
||||
m.m[4] = m3.m[3];
|
||||
m.m[5] = m3.m[4];
|
||||
m.m[6] = m3.m[5];
|
||||
|
||||
m.m[8] = m3.m[6];
|
||||
m.m[9] = m3.m[7];
|
||||
m.m[10] = m3.m[8];
|
||||
|
||||
m = ModelviewMatrixStack.top() * m;
|
||||
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(m);
|
||||
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::RotateMatrix(const Matrix3f& m3)
|
||||
{
|
||||
Matrix4f m = Matrix4f::Identity();
|
||||
m.m[0] = m3.m[0];
|
||||
m.m[1] = m3.m[1];
|
||||
m.m[2] = m3.m[2];
|
||||
|
||||
m.m[4] = m3.m[3];
|
||||
m.m[5] = m3.m[4];
|
||||
m.m[6] = m3.m[5];
|
||||
|
||||
m.m[8] = m3.m[6];
|
||||
m.m[9] = m3.m[7];
|
||||
m.m[10] = m3.m[8];
|
||||
|
||||
m = ModelviewMatrixStack.top() * m;
|
||||
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
|
||||
ModelviewMatrixStack.pop();
|
||||
ModelviewMatrixStack.push(m);
|
||||
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
void Renderer::PushSpecialMatrix(const Matrix4f& m)
|
||||
{
|
||||
if (ModelviewMatrixStack.size() > 64)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack overflow!!!!");
|
||||
}
|
||||
ModelviewMatrixStack.push(m);
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
|
||||
void Renderer::PopMatrix()
|
||||
{
|
||||
if (ModelviewMatrixStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Modelview matrix stack underflow!!!!");
|
||||
}
|
||||
ModelviewMatrixStack.pop();
|
||||
|
||||
SetMatrix();
|
||||
}
|
||||
|
||||
|
||||
void Renderer::EnableVertexAttribArray(const std::string& attribName)
|
||||
{
|
||||
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
if (shader->attribList.find(attribName) != shader->attribList.end())
|
||||
glEnableVertexAttribArray(shader->attribList[attribName]);
|
||||
}
|
||||
|
||||
void Renderer::DisableVertexAttribArray(const std::string& attribName)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
if (shader->attribList.find(attribName) != shader->attribList.end())
|
||||
glDisableVertexAttribArray(shader->attribList[attribName]);
|
||||
}
|
||||
|
||||
void Renderer::RenderUniformMatrix3fv(const std::string& uniformName, bool transpose, const float* value)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
|
||||
auto uniform = shader->uniformList.find(uniformName);
|
||||
|
||||
if (uniform != shader->uniformList.end())
|
||||
{
|
||||
glUniformMatrix3fv(uniform->second, 1, transpose, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::RenderUniformMatrix4fv(const std::string& uniformName, bool transpose, const float* value)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
|
||||
auto uniform = shader->uniformList.find(uniformName);
|
||||
|
||||
if (uniform != shader->uniformList.end())
|
||||
{
|
||||
glUniformMatrix4fv(uniform->second, 1, transpose, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderUniform3fv(const std::string& uniformName, const float* value)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
|
||||
auto uniform = shader->uniformList.find(uniformName);
|
||||
|
||||
if (uniform != shader->uniformList.end())
|
||||
{
|
||||
glUniform3fv(uniform->second, 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderUniform1i(const std::string& uniformName, const int value)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
|
||||
auto uniform = shader->uniformList.find(uniformName);
|
||||
|
||||
if (uniform != shader->uniformList.end())
|
||||
{
|
||||
glUniform1i(uniform->second, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::RenderUniform1f(const std::string& uniformName, float value)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
|
||||
auto uniform = shader->uniformList.find(uniformName);
|
||||
|
||||
if (uniform != shader->uniformList.end())
|
||||
{
|
||||
glUniform1fv(uniform->second, 1, &value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Renderer::VertexAttribPointer2fv(const std::string& attribName, int stride, const char* pointer)
|
||||
{
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
if (shader->attribList.find(attribName) != shader->attribList.end())
|
||||
glVertexAttribPointer(shader->attribList[attribName], 2, GL_FLOAT, GL_FALSE, stride, pointer);
|
||||
|
||||
}
|
||||
|
||||
void Renderer::VertexAttribPointer3fv(const std::string& attribName, int stride, const char* pointer)
|
||||
{
|
||||
|
||||
auto shader = shaderManager.GetCurrentShader();
|
||||
if (shader->attribList.find(attribName) != shader->attribList.end())
|
||||
glVertexAttribPointer(shader->attribList[attribName], 3, GL_FLOAT, GL_FALSE, stride, pointer);
|
||||
}
|
||||
|
||||
void Renderer::DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct)
|
||||
{
|
||||
static const std::string vNormal("vNormal");
|
||||
static const std::string vTangent("vTangent");
|
||||
static const std::string vBinormal("vBinormal");
|
||||
static const std::string vColor("vColor");
|
||||
static const std::string vTexCoord("vTexCoord");
|
||||
static const std::string vPosition("vPosition");
|
||||
|
||||
//glBindVertexArray(VertexRenderStruct.vao->getBuffer());
|
||||
|
||||
//Check if main thread, check if data is not empty...
|
||||
if (VertexRenderStruct.data.NormalData.size() > 0)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.normalVBO->getBuffer());
|
||||
VertexAttribPointer3fv(vNormal, 0, NULL);
|
||||
}
|
||||
if (VertexRenderStruct.data.TangentData.size() > 0)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.tangentVBO->getBuffer());
|
||||
VertexAttribPointer3fv(vTangent, 0, NULL);
|
||||
}
|
||||
if (VertexRenderStruct.data.BinormalData.size() > 0)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.binormalVBO->getBuffer());
|
||||
VertexAttribPointer3fv(vBinormal, 0, NULL);
|
||||
}
|
||||
if (VertexRenderStruct.data.ColorData.size() > 0)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.colorVBO->getBuffer());
|
||||
VertexAttribPointer3fv(vColor, 0, NULL);
|
||||
}
|
||||
if (VertexRenderStruct.data.TexCoordData.size() > 0)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.texCoordVBO->getBuffer());
|
||||
VertexAttribPointer2fv(vTexCoord, 0, NULL);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexRenderStruct.positionVBO->getBuffer());
|
||||
VertexAttribPointer3fv(vPosition, 0, NULL);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(VertexRenderStruct.data.PositionData.size()));
|
||||
|
||||
}
|
||||
|
||||
void worldToScreenCoordinates(Vector3f objectPos,
|
||||
Matrix4f projectionModelView,
|
||||
int screenWidth, int screenHeight,
|
||||
int& screenX, int& screenY) {
|
||||
|
||||
Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f };
|
||||
Vector4f clipCoords = MultMatrixVector(projectionModelView, inx);
|
||||
|
||||
float ndcX = clipCoords.v[0] / clipCoords.v[3];
|
||||
float ndcY = clipCoords.v[1] / clipCoords.v[3];
|
||||
|
||||
screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth);
|
||||
screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
|
||||
#include "OpenGlExtensions.h"
|
||||
#include "utils/ZLMath.h"
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include "ShaderManager.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
constexpr size_t CONST_MATRIX_STACK_SIZE = 64;
|
||||
|
||||
class VBOHolder {
|
||||
GLuint Buffer;
|
||||
|
||||
public:
|
||||
VBOHolder();
|
||||
|
||||
VBOHolder(const VBOHolder& v) = delete;
|
||||
|
||||
VBOHolder& operator=(const VBOHolder& v) = delete;
|
||||
|
||||
~VBOHolder();
|
||||
|
||||
GLuint getBuffer();
|
||||
};
|
||||
|
||||
class VAOHolder {
|
||||
GLuint vao;
|
||||
|
||||
public:
|
||||
VAOHolder();
|
||||
|
||||
VAOHolder(const VAOHolder& v) = delete;
|
||||
|
||||
VAOHolder& operator=(const VAOHolder& v) = delete;
|
||||
|
||||
~VAOHolder();
|
||||
|
||||
GLuint getBuffer();
|
||||
};
|
||||
|
||||
struct VertexDataStruct
|
||||
{
|
||||
std::vector<Vector3f> PositionData;
|
||||
std::vector<Vector2f> TexCoordData;
|
||||
std::vector<Vector3f> NormalData;
|
||||
std::vector<Vector3f> TangentData;
|
||||
std::vector<Vector3f> BinormalData;
|
||||
std::vector<Vector3f> ColorData;
|
||||
|
||||
void RotateByMatrix(Matrix3f m);
|
||||
|
||||
void Scale(float scale);
|
||||
void Move(Vector3f diff);
|
||||
void SwapZandY();
|
||||
};
|
||||
|
||||
struct VertexRenderStruct
|
||||
{
|
||||
VertexDataStruct data;
|
||||
|
||||
std::shared_ptr<VAOHolder> vao;
|
||||
std::shared_ptr<VBOHolder> positionVBO;
|
||||
std::shared_ptr<VBOHolder> texCoordVBO;
|
||||
std::shared_ptr<VBOHolder> normalVBO;
|
||||
std::shared_ptr<VBOHolder> tangentVBO;
|
||||
std::shared_ptr<VBOHolder> binormalVBO;
|
||||
std::shared_ptr<VBOHolder> colorVBO;
|
||||
void RefreshVBO();
|
||||
|
||||
void AssignFrom(const VertexDataStruct& v);
|
||||
};
|
||||
|
||||
VertexDataStruct CreateRect2D(Vector2f center, Vector2f halfWidthHeight, float zLevel);
|
||||
VertexDataStruct CreateRectHorizontalSections2D(Vector2f center, Vector2f halfWidthHeight, float zLevel, size_t sectionCount);
|
||||
VertexDataStruct CreateCube3D(float scale);
|
||||
VertexDataStruct CreateCubemap(float scale = 1000.f);
|
||||
|
||||
|
||||
class Renderer
|
||||
{
|
||||
protected:
|
||||
std::stack<Matrix4f> ProjectionMatrixStack;
|
||||
std::stack<Matrix4f> ModelviewMatrixStack;
|
||||
|
||||
Matrix4f ProjectionModelViewMatrix;
|
||||
|
||||
public:
|
||||
|
||||
ShaderManager shaderManager;
|
||||
|
||||
void InitOpenGL();
|
||||
|
||||
void PushProjectionMatrix(float width, float height, float zNear = 0.f, float zFar = 1.f);
|
||||
void PushProjectionMatrix(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar);
|
||||
void PushPerspectiveProjectionMatrix(float fovY, float aspectRatio, float zNear, float zFar);
|
||||
void PopProjectionMatrix();
|
||||
|
||||
void PushMatrix();
|
||||
void LoadIdentity();
|
||||
void TranslateMatrix(const Vector3f& p);
|
||||
void ScaleMatrix(float scale);
|
||||
void ScaleMatrix(const Vector3f& scale);
|
||||
void RotateMatrix(const Vector4f& q);
|
||||
void RotateMatrix(const Matrix3f& m3);
|
||||
void PushSpecialMatrix(const Matrix4f& m);
|
||||
void PopMatrix();
|
||||
|
||||
|
||||
Matrix4f GetProjectionModelViewMatrix();
|
||||
Matrix4f GetCurrentModelViewMatrix();
|
||||
|
||||
void SetMatrix();
|
||||
|
||||
|
||||
|
||||
void EnableVertexAttribArray(const std::string& attribName);
|
||||
|
||||
void DisableVertexAttribArray(const std::string& attribName);
|
||||
|
||||
|
||||
void RenderUniformMatrix3fv(const std::string& uniformName, bool transpose, const float* value);
|
||||
void RenderUniformMatrix4fv(const std::string& uniformName, bool transpose, const float* value);
|
||||
void RenderUniform1i(const std::string& uniformName, const int value);
|
||||
void RenderUniform3fv(const std::string& uniformName, const float* value);
|
||||
void RenderUniform1f(const std::string& uniformName, float value);
|
||||
|
||||
void VertexAttribPointer2fv(const std::string& attribName, int stride, const char* pointer);
|
||||
|
||||
void VertexAttribPointer3fv(const std::string& attribName, int stride, const char* pointer);
|
||||
|
||||
void DrawVertexRenderStruct(const VertexRenderStruct& VertexRenderStruct);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void worldToScreenCoordinates(Vector3f objectPos,
|
||||
Matrix4f projectionModelView,
|
||||
int screenWidth, int screenHeight,
|
||||
int& screenX, int& screenY);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,215 @@
|
||||
#include "ShaderManager.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace ZL {
|
||||
|
||||
ShaderResource::ShaderResource(const std::string& vertexCode, const std::string& fragmentCode)
|
||||
{
|
||||
|
||||
const int CONST_INFOLOG_LENGTH = 256;
|
||||
|
||||
char infoLog[CONST_INFOLOG_LENGTH];
|
||||
int infoLogLength;
|
||||
char infoLog2[CONST_INFOLOG_LENGTH];
|
||||
int infoLogLength2;
|
||||
|
||||
int vertexShaderCompiled;
|
||||
int fragmentShaderCompiled;
|
||||
int programLinked;
|
||||
|
||||
GLuint vertexShader;
|
||||
GLuint fragmentShader;
|
||||
|
||||
int vertexCodeLength = static_cast<int>(strlen(vertexCode.c_str()));
|
||||
int fragmentCodeLength = static_cast<int>(strlen(fragmentCode.c_str()));
|
||||
|
||||
const char* vc = &vertexCode[0];
|
||||
const char* fc = &fragmentCode[0];
|
||||
|
||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
|
||||
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
|
||||
|
||||
glCompileShader(vertexShader);
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
|
||||
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
||||
|
||||
glCompileShader(fragmentShader);
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
|
||||
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength2, infoLog2);
|
||||
|
||||
|
||||
if (!vertexShaderCompiled)
|
||||
{
|
||||
throw std::runtime_error("Failed to compile vertex shader code!");
|
||||
}
|
||||
|
||||
if (!fragmentShaderCompiled)
|
||||
{
|
||||
throw std::runtime_error("Failed to compile fragment shader code!");
|
||||
}
|
||||
|
||||
shaderProgram = glCreateProgram();
|
||||
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
|
||||
glLinkProgram(shaderProgram);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked);
|
||||
glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
||||
|
||||
if (!programLinked)
|
||||
{
|
||||
shaderProgram = 0;
|
||||
throw std::runtime_error("Failed to link shader program!");
|
||||
}
|
||||
|
||||
|
||||
int dummySize; //Dummy
|
||||
int dummyLen; //Dummy
|
||||
GLenum dummyEnum;
|
||||
|
||||
|
||||
//================= Parsing all uniforms ================
|
||||
|
||||
int activeUniforms;
|
||||
|
||||
const int CONST_UNIFORM_NAME_LENGTH = 256;
|
||||
char uniformName[CONST_UNIFORM_NAME_LENGTH];
|
||||
|
||||
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
|
||||
|
||||
for (int i = 0; i < activeUniforms; i++)
|
||||
{
|
||||
glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, uniformName);
|
||||
|
||||
uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName);
|
||||
}
|
||||
|
||||
//================= Parsing all attributes ================
|
||||
int activeAttribs;
|
||||
|
||||
const int CONST_ATTRIB_NAME_LENGTH = 256;
|
||||
char attribName[CONST_ATTRIB_NAME_LENGTH];
|
||||
|
||||
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
|
||||
|
||||
for (int i = 0; i < activeAttribs; i++)
|
||||
{
|
||||
glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, attribName);
|
||||
attribList[attribName] = glGetAttribLocation(shaderProgram, attribName);
|
||||
}
|
||||
}
|
||||
|
||||
ShaderResource::~ShaderResource()
|
||||
{
|
||||
if (shaderProgram != 0)
|
||||
{
|
||||
glDeleteProgram(shaderProgram);
|
||||
|
||||
shaderProgram = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint ShaderResource::getShaderProgram()
|
||||
{
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
|
||||
void ShaderManager::AddShaderFromFiles(const std::string& shaderName, const std::string& vertexShaderFileName, const std::string& fragmentShaderFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
|
||||
std::string vertexShader;
|
||||
std::string fragmentShader;
|
||||
|
||||
if (!ZIPFileName.empty()){
|
||||
|
||||
std::vector<char> vertexShaderData;
|
||||
std::vector<char> fragmentShaderData;
|
||||
|
||||
vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName);
|
||||
fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName);
|
||||
|
||||
vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end());
|
||||
fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end());
|
||||
|
||||
}else{
|
||||
vertexShader = readTextFile(vertexShaderFileName);
|
||||
fragmentShader = readTextFile(fragmentShaderFileName);
|
||||
}
|
||||
///std::cout << "Shader: "<< vertexShader << std::endl;
|
||||
shaderResourceMap[shaderName] = std::make_shared<ShaderResource>(vertexShader, fragmentShader);
|
||||
}
|
||||
|
||||
void ShaderManager::PushShader(const std::string& shaderName)
|
||||
{
|
||||
if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE)
|
||||
{
|
||||
throw std::runtime_error("Shader stack overflow!");
|
||||
}
|
||||
|
||||
if (shaderResourceMap.find(shaderName) == shaderResourceMap.end())
|
||||
{
|
||||
throw std::runtime_error("Shader does not exist!");
|
||||
}
|
||||
|
||||
shaderStack.push(shaderName);
|
||||
|
||||
glUseProgram(shaderResourceMap[shaderName]->getShaderProgram());
|
||||
}
|
||||
|
||||
|
||||
void ShaderManager::PopShader()
|
||||
{
|
||||
if (shaderStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Shader stack underflow!");
|
||||
}
|
||||
|
||||
shaderStack.pop();
|
||||
|
||||
if (shaderStack.size() == 0)
|
||||
{
|
||||
glUseProgram(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderResource> ShaderManager::GetCurrentShader()
|
||||
{
|
||||
if (shaderStack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("Shader stack underflow!");
|
||||
}
|
||||
|
||||
|
||||
return shaderResourceMap[shaderStack.top()];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ShaderSetter::ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName)
|
||||
: shaderManager(shaderManager)
|
||||
{
|
||||
shaderManager.PushShader(shaderName);
|
||||
}
|
||||
|
||||
ShaderSetter::~ShaderSetter()
|
||||
{
|
||||
shaderManager.PopShader();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include "OpenGlExtensions.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
|
||||
constexpr size_t CONST_MAX_SHADER_STACK_SIZE = 16;
|
||||
|
||||
class ShaderResource
|
||||
{
|
||||
protected:
|
||||
GLuint shaderProgram;
|
||||
|
||||
std::unordered_map<std::string, GLuint> uniformList;
|
||||
|
||||
//std::unordered_map<std::string, std::pair<bool, size_t>> UniformList;
|
||||
std::map<std::string, GLuint> attribList;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
GLuint getShaderProgram();
|
||||
|
||||
ShaderResource(const std::string& vertexCode, const std::string& fragmentCode);
|
||||
~ShaderResource();
|
||||
|
||||
public:
|
||||
friend class ShaderManager;
|
||||
friend class Renderer;
|
||||
};
|
||||
|
||||
class ShaderManager {
|
||||
protected:
|
||||
std::unordered_map<std::string, std::shared_ptr<ShaderResource>> shaderResourceMap;
|
||||
|
||||
std::stack<std::string> shaderStack;
|
||||
|
||||
public:
|
||||
void AddShaderFromFiles(const std::string& shaderName, const std::string& vertexShaderFileName, const std::string& fragmentShaderFileName, const std::string& ZIPFileName = "");
|
||||
|
||||
void PushShader(const std::string& shaderName);
|
||||
void PopShader();
|
||||
|
||||
std::shared_ptr<ShaderResource> GetCurrentShader();
|
||||
};
|
||||
|
||||
|
||||
class ShaderSetter
|
||||
{
|
||||
protected:
|
||||
|
||||
ShaderManager& shaderManager;
|
||||
|
||||
public:
|
||||
ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName);
|
||||
|
||||
~ShaderSetter();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
#include "render/TextureManager.h"
|
||||
#include "render/OpenGlExtensions.h"
|
||||
#ifdef PNG_ENABLED
|
||||
#include "png.h"
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
|
||||
Texture::Texture(const TextureDataStruct& texData)
|
||||
{
|
||||
|
||||
width = texData.width;
|
||||
height = texData.height;
|
||||
|
||||
glGenTextures(1, &texID);
|
||||
|
||||
if (texID == 0)
|
||||
{
|
||||
throw std::runtime_error("glGenTextures did not work");
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texID);
|
||||
|
||||
CheckGlError();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
CheckGlError();
|
||||
|
||||
//This should be only for Windows
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
|
||||
CheckGlError();
|
||||
|
||||
if (texData.bitSize == TextureDataStruct::BS_24BIT)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, static_cast<GLsizei>(texData.width), static_cast<GLsizei>(texData.height), 0, GL_RGB, GL_UNSIGNED_BYTE, &texData.data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(texData.width), static_cast<GLsizei>(texData.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData.data[0]);
|
||||
}
|
||||
|
||||
CheckGlError();
|
||||
|
||||
}
|
||||
|
||||
Texture::Texture(const std::array<TextureDataStruct, 6>& texDataArray)
|
||||
{
|
||||
// Ïðîâåðêà, ÷òî âñå ãðàíè èìåþò îäèíàêîâûå ðàçìåðû
|
||||
width = texDataArray[0].width;
|
||||
height = texDataArray[0].height;
|
||||
|
||||
for (size_t i = 1; i < 6; ++i) {
|
||||
if (texDataArray[i].width != width || texDataArray[i].height != height) {
|
||||
throw std::runtime_error("Cubemap faces must have the same dimensions");
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, &texID);
|
||||
|
||||
if (texID == 0)
|
||||
{
|
||||
throw std::runtime_error("glGenTextures did not work for cubemap");
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, texID);
|
||||
|
||||
CheckGlError();
|
||||
|
||||
// Íàñòðîéêà ïàðàìåòðîâ äëÿ Cubemap
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// Èñïîëüçóåì GL_LINEAR äëÿ MIN_FILTER, òàê êàê ìèïìàïû çäåñü íå ãåíåðèðóþòñÿ
|
||||
// Åñëè áû èñïîëüçîâàëèñü ìèïìàïû (e.g., GL_LINEAR_MIPMAP_LINEAR), íóæíî áûëî áû âûçâàòü glGenerateMipmap.
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// Îáÿçàòåëüíûå ïàðàìåòðû îáåðòêè äëÿ Cubemap
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// GL_TEXTURE_WRAP_R íå ïîääåðæèâàåòñÿ â WebGL 1.0/OpenGL ES 2.0 è âûçûâàåò îøèáêó.
|
||||
// Îãðàíè÷èâàåì åãî âûçîâ òîëüêî äëÿ íàñòîëüíûõ ïëàòôîðì.
|
||||
#ifndef EMSCRIPTEN
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
#endif
|
||||
|
||||
CheckGlError(); // Ïðîâåðêà ïîñëå óñòàíîâêè ïàðàìåòðîâ
|
||||
|
||||
// Çàãðóçêà äàííûõ äëÿ êàæäîé èç 6 ãðàíåé
|
||||
// GL_TEXTURE_CUBE_MAP_POSITIVE_X + i äàåò ãðàíè: +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
GLint internalFormat;
|
||||
GLenum format;
|
||||
|
||||
// Â WebGL 1.0/OpenGL ES 2.0 âíóòðåííèé ôîðìàò (internalFormat)
|
||||
// äîëæåí ñòðîãî ñîîòâåòñòâîâàòü ôîðìàòó äàííûõ (format).
|
||||
if (texDataArray[i].bitSize == TextureDataStruct::BS_24BIT)
|
||||
{
|
||||
internalFormat = GL_RGB; // internalFormat
|
||||
format = GL_RGB; // format
|
||||
}
|
||||
else // BS_32BIT
|
||||
{
|
||||
internalFormat = GL_RGBA; // internalFormat
|
||||
format = GL_RGBA; // format
|
||||
}
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, // Öåëåâàÿ ãðàíü
|
||||
0, // Óðîâåíü MIP-òåêñòóðû
|
||||
internalFormat, // Âíóòðåííèé ôîðìàò (äîëæåí ñîâïàäàòü ñ ôîðìàòîì)
|
||||
static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height),
|
||||
0, // Ãðàíèöà (âñåãäà 0)
|
||||
format, // Ôîðìàò èñõîäíûõ äàííûõ
|
||||
GL_UNSIGNED_BYTE, // Òèï äàííûõ
|
||||
texDataArray[i].data.data() // Óêàçàòåëü íà äàííûå
|
||||
);
|
||||
CheckGlError();
|
||||
}
|
||||
|
||||
// Ñíèìàåì ïðèâÿçêó äëÿ ÷èñòîòû
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
glDeleteTextures(1, &texID);
|
||||
texID = 0;
|
||||
}
|
||||
|
||||
GLuint Texture::getTexID()
|
||||
{
|
||||
return texID;
|
||||
}
|
||||
|
||||
size_t Texture::getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
size_t Texture::getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextureDataStruct CreateTextureDataFromBmp24(const std::string& fullFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
|
||||
TextureDataStruct texData;
|
||||
std::vector<char> fileArr;
|
||||
|
||||
fileArr = !ZIPFileName.empty() ? readFileFromZIP(fullFileName, ZIPFileName) : readFile(fullFileName);
|
||||
|
||||
size_t fileSize = fileArr.size();
|
||||
|
||||
if (fileSize < 22)
|
||||
{
|
||||
throw std::runtime_error("File is too short or not correct!");
|
||||
}
|
||||
|
||||
//This refers to BITMAPV5HEADER
|
||||
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
|
||||
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
|
||||
|
||||
texData.bitSize = TextureDataStruct::BS_24BIT;
|
||||
|
||||
size_t dataSize = texData.width * texData.height * 3;
|
||||
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
size_t pos = *reinterpret_cast<uint32_t*>(&fileArr[10]);
|
||||
size_t x = 0;
|
||||
|
||||
for (size_t i = 0; i < texData.width; i++)
|
||||
for (size_t j = 0; j < texData.height; j++)
|
||||
{
|
||||
|
||||
if (pos + 3 > fileSize)
|
||||
{
|
||||
throw std::runtime_error("File is too short!");
|
||||
}
|
||||
|
||||
|
||||
x = (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j);
|
||||
|
||||
texData.data[x + 2] = fileArr[pos++];
|
||||
texData.data[x + 1] = fileArr[pos++];
|
||||
texData.data[x + 0] = fileArr[pos++];
|
||||
|
||||
}
|
||||
|
||||
return texData;
|
||||
}
|
||||
|
||||
TextureDataStruct CreateTextureDataFromBmp32(const std::string& fullFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
|
||||
TextureDataStruct texData;
|
||||
std::vector<char> fileArr;
|
||||
|
||||
fileArr = !ZIPFileName.empty() ? readFileFromZIP(fullFileName, ZIPFileName) : readFile(fullFileName);
|
||||
|
||||
size_t fileSize = fileArr.size();
|
||||
|
||||
if (fileSize < 22)
|
||||
{
|
||||
throw std::runtime_error("File is too short or not correct!");
|
||||
}
|
||||
|
||||
//This refers to BITMAPV5HEADER
|
||||
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
|
||||
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
|
||||
|
||||
texData.bitSize = TextureDataStruct::BS_32BIT;
|
||||
|
||||
size_t dataSize = texData.width * texData.height * 4;
|
||||
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
size_t pos = *reinterpret_cast<uint32_t*>(&fileArr[10]);
|
||||
size_t x = 0;
|
||||
|
||||
for (size_t i = 0; i < texData.width; i++)
|
||||
for (size_t j = 0; j < texData.height; j++)
|
||||
{
|
||||
|
||||
if (pos + 4 > fileSize)
|
||||
{
|
||||
throw std::runtime_error("File is too short!");
|
||||
}
|
||||
|
||||
|
||||
x = (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j) + (i * texData.height + j);
|
||||
|
||||
texData.data[x + 2] = fileArr[pos++];
|
||||
texData.data[x + 1] = fileArr[pos++];
|
||||
texData.data[x + 0] = fileArr[pos++];
|
||||
texData.data[x + 3] = fileArr[pos++];
|
||||
|
||||
}
|
||||
|
||||
return texData;
|
||||
}
|
||||
|
||||
#ifdef PNG_ENABLED
|
||||
|
||||
// Ñòðóêòóðà äëÿ õðàíåíèÿ äàííûõ î ôàéëå/ìàññèâå è òåêóùåé ïîçèöèè ÷òåíèÿ
|
||||
struct png_data_t {
|
||||
const char* data;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
// Ïîëüçîâàòåëüñêàÿ ôóíêöèÿ ÷òåíèÿ äëÿ libpng
|
||||
// 'png_ptr' - óêàçàòåëü íà ñòðóêòóðó png
|
||||
// 'out_ptr' - êóäà çàïèñûâàòü ïðî÷èòàííûå äàííûå
|
||||
// 'bytes_to_read' - ñêîëüêî áàéò íóæíî ïðî÷èòàòü
|
||||
void user_read_data(png_structp png_ptr, png_bytep out_ptr, png_size_t bytes_to_read) {
|
||||
// Ïîëó÷àåì óêàçàòåëü íà íàøó ñòðóêòóðó png_data_t, êîòîðóþ ìû óñòàíîâèëè ñ ïîìîùüþ png_set_read_fn
|
||||
png_data_t* data = (png_data_t*)png_get_io_ptr(png_ptr);
|
||||
|
||||
if (data->offset + bytes_to_read > data->size) {
|
||||
// Ïîïûòêà ïðî÷èòàòü áîëüøå, ÷åì åñòü â ìàññèâå.
|
||||
// Âìåñòî âûçîâà ñòàíäàðòíîé îøèáêè, ìû ìîæåì ïðîñòî ïðî÷èòàòü îñòàòîê èëè âûçâàòü îøèáêó.
|
||||
//  ýòîì ñëó÷àå ìû âûçîâåì îøèáêó libpng.
|
||||
png_error(png_ptr, "PNG Read Error: Attempted to read past end of data buffer.");
|
||||
bytes_to_read = data->size - data->offset; // Óñòàíàâëèâàåì, ÷òîáû ïðî÷èòàòü îñòàâøååñÿ
|
||||
}
|
||||
|
||||
// Êîïèðóåì äàííûå èç íàøåãî ìàññèâà â áóôåð libpng
|
||||
std::memcpy(out_ptr, data->data + data->offset, bytes_to_read);
|
||||
|
||||
// Îáíîâëÿåì ñìåùåíèå
|
||||
data->offset += bytes_to_read;
|
||||
}
|
||||
|
||||
// Ïîëüçîâàòåëüñêàÿ ôóíêöèÿ ïðåäóïðåæäåíèé (ïî æåëàíèþ, ìîæíî èñïîëüçîâàòü nullptr)
|
||||
void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) {
|
||||
// Çäåñü ìîæíî ðåàëèçîâàòü ëîãèðîâàíèå ïðåäóïðåæäåíèé
|
||||
//throw std::runtime_error();
|
||||
std::cout << "PNG Warning: " << warning_msg << std::endl;
|
||||
}
|
||||
|
||||
// Ïîëüçîâàòåëüñêàÿ ôóíêöèÿ îøèáîê (îáÿçàòåëüíà äëÿ setjmp)
|
||||
void user_error_fn(png_structp png_ptr, png_const_charp error_msg) {
|
||||
// Çäåñü ìîæíî ðåàëèçîâàòü ëîãèðîâàíèå îøèáîê
|
||||
std::cout << "PNG Error: " << error_msg << std::endl;
|
||||
// Îáÿçàòåëüíî âûçûâàåì longjmp äëÿ âûõîäà èç ïðîöåññà ÷òåíèÿ/çàïèñè PNG
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
TextureDataStruct CreateTextureDataFromPng(const std::vector<char>& fileArr)
|
||||
{
|
||||
TextureDataStruct texData;
|
||||
|
||||
// Ñòðóêòóðà äëÿ óïðàâëåíèÿ ÷òåíèåì èç ìàññèâà
|
||||
png_data_t png_data = { fileArr.data(), fileArr.size(), 0 };
|
||||
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png) {
|
||||
throw std::runtime_error("Could not create PNG read structure");
|
||||
}
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
png_destroy_read_struct(&png, nullptr, nullptr);
|
||||
throw std::runtime_error("Could not create PNG info structure");
|
||||
}
|
||||
|
||||
// === Óñòàíîâêà ïîëüçîâàòåëüñêèõ ôóíêöèé ÷òåíèÿ è îáðàáîòêè îøèáîê ===
|
||||
// 1. Óñòàíîâêà îáðàáîò÷èêà îøèáîê è longjmp
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
throw std::runtime_error("Error during PNG read (longjmp was executed)");
|
||||
}
|
||||
|
||||
// 2. Óñòàíîâêà ïîëüçîâàòåëüñêèõ ôóíêöèé äëÿ îáðàáîòêè îøèáîê è ïðåäóïðåæäåíèé
|
||||
// Âìåñòî nullptr â error_ptr è warning_ptr ìîæíî ïåðåäàòü óêàçàòåëü íà ñâîþ ñòðóêòóðó äàííûõ, åñëè íåîáõîäèìî
|
||||
png_set_error_fn(png, nullptr, user_error_fn, user_warning_fn);
|
||||
|
||||
// 3. Óñòàíîâêà ïîëüçîâàòåëüñêîé ôóíêöèè ÷òåíèÿ è ïåðåäà÷à åé íàøåé ñòðóêòóðû png_data
|
||||
png_set_read_fn(png, &png_data, user_read_data);
|
||||
// ===================================================================
|
||||
|
||||
png_read_info(png, info);
|
||||
|
||||
texData.width = png_get_image_width(png, info);
|
||||
texData.height = png_get_image_height(png, info);
|
||||
png_byte color_type = png_get_color_type(png, info);
|
||||
png_byte bit_depth = png_get_bit_depth(png, info);
|
||||
|
||||
// === Áëîê ïðåîáðàçîâàíèé (îñòàâëåí áåç èçìåíåíèé) ===
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
// ====================================================
|
||||
|
||||
// === ×òåíèå ïèêñåëåé (îñòàâëåí áåç èçìåíåíèé) ===
|
||||
png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * texData.height);
|
||||
for (int y = 0; y < texData.height; y++) {
|
||||
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
|
||||
}
|
||||
|
||||
png_read_image(png, row_pointers);
|
||||
|
||||
bool has_alpha = (color_type & PNG_COLOR_MASK_ALPHA) || (png_get_valid(png, info, PNG_INFO_tRNS));
|
||||
|
||||
size_t dataSize;
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
texData.bitSize = TextureDataStruct::BS_32BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
texData.bitSize = TextureDataStruct::BS_24BIT;
|
||||
}
|
||||
|
||||
int channels = has_alpha ? 4 : 3;
|
||||
|
||||
dataSize = texData.width * texData.height * channels;
|
||||
texData.data.resize(dataSize);
|
||||
|
||||
|
||||
for (int y = texData.height - 1; y >= 0; y--) {
|
||||
png_bytep row = row_pointers[texData.height - 1 - y];
|
||||
for (int x = 0; x < texData.width; x++) {
|
||||
png_bytep px = &(row[x * 4]);
|
||||
texData.data[(y * texData.width + x) * channels + 0] = px[0]; // R
|
||||
texData.data[(y * texData.width + x) * channels + 1] = px[1]; // G
|
||||
texData.data[(y * texData.width + x) * channels + 2] = px[2]; // B
|
||||
if (has_alpha) {
|
||||
texData.data[(y * texData.width + x) * channels + 3] = px[3]; // A
|
||||
}
|
||||
}
|
||||
free(row_pointers[texData.height - 1 - y]);
|
||||
}
|
||||
free(row_pointers);
|
||||
// ==================================================
|
||||
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
|
||||
return texData;
|
||||
}
|
||||
|
||||
|
||||
TextureDataStruct CreateTextureDataFromPng(const std::string& fullFileName, const std::string& ZIPFileName)
|
||||
{
|
||||
std::vector<char> fileArr;
|
||||
|
||||
fileArr = !ZIPFileName.empty() ? readFileFromZIP(fullFileName, ZIPFileName) : readFile(fullFileName);
|
||||
|
||||
if (fileArr.empty()) {
|
||||
throw std::runtime_error("Could not read file data into memory");
|
||||
}
|
||||
|
||||
// Âûçûâàåì íîâóþ ôóíêöèþ, êîòîðàÿ ðàáîòàåò ñ ìàññèâîì áàéò
|
||||
return CreateTextureDataFromPng(fileArr);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "OpenGlExtensions.h"
|
||||
#include "utils/Utils.h"
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#define PNG_ENABLED
|
||||
#endif
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
|
||||
struct TextureDataStruct
|
||||
{
|
||||
size_t width;
|
||||
size_t height;
|
||||
std::vector<char> data;
|
||||
enum BitSize {
|
||||
BS_24BIT,
|
||||
BS_32BIT
|
||||
};
|
||||
|
||||
BitSize bitSize;
|
||||
};
|
||||
|
||||
class Texture
|
||||
{
|
||||
size_t width = 0;
|
||||
size_t height = 0;
|
||||
GLuint texID = 0;
|
||||
|
||||
public:
|
||||
|
||||
Texture(const TextureDataStruct& texData);
|
||||
|
||||
//Cubemap texture:
|
||||
Texture(const std::array<TextureDataStruct, 6>& texDataArray);
|
||||
|
||||
~Texture();
|
||||
|
||||
GLuint getTexID();
|
||||
|
||||
size_t getWidth();
|
||||
size_t getHeight();
|
||||
|
||||
|
||||
};
|
||||
|
||||
TextureDataStruct CreateTextureDataFromBmp24(const std::string& fullFileName, const std::string& ZIPFileName="");
|
||||
TextureDataStruct CreateTextureDataFromBmp32(const std::string& fullFileName, const std::string& ZIPFileName="");
|
||||
#ifdef PNG_ENABLED
|
||||
TextureDataStruct CreateTextureDataFromPng(const std::string& fullFileName, const std::string& ZIPFileName = "");
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user