mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-10 05:57:48 +00:00
Initial commit of current work on Prime World Editor
This commit is contained in:
136
OpenGL/CDynamicVertexBuffer.cpp
Normal file
136
OpenGL/CDynamicVertexBuffer.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "CDynamicVertexBuffer.h"
|
||||
#include "CVertexArrayManager.h"
|
||||
|
||||
static const u32 gskAttribSize[] = {
|
||||
0xC, 0xC, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8
|
||||
};
|
||||
|
||||
CDynamicVertexBuffer::CDynamicVertexBuffer()
|
||||
{
|
||||
mAttribFlags = eNoAttributes;
|
||||
mBufferedFlags = eNoAttributes;
|
||||
mNumVertices = 0;
|
||||
}
|
||||
|
||||
CDynamicVertexBuffer::~CDynamicVertexBuffer()
|
||||
{
|
||||
CVertexArrayManager::DeleteAllArraysForVBO(this);
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::SetVertexCount(u32 NumVerts)
|
||||
{
|
||||
ClearBuffers();
|
||||
mNumVertices = NumVerts;
|
||||
InitBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::Bind()
|
||||
{
|
||||
CVertexArrayManager::Current()->BindVAO(this);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::Unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::SetActiveAttribs(u32 AttribFlags)
|
||||
{
|
||||
ClearBuffers();
|
||||
mAttribFlags = (EVertexDescription) AttribFlags;
|
||||
InitBuffers();
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::BufferAttrib(EVertexDescription Attrib, const void *pData)
|
||||
{
|
||||
u32 Index;
|
||||
|
||||
switch (Attrib)
|
||||
{
|
||||
case ePosition: Index = 0; break;
|
||||
case eNormal: Index = 1; break;
|
||||
case eColor0: Index = 2; break;
|
||||
case eColor1: Index = 3; break;
|
||||
case eTex0: Index = 4; break;
|
||||
case eTex1: Index = 5; break;
|
||||
case eTex2: Index = 6; break;
|
||||
case eTex3: Index = 7; break;
|
||||
case eTex4: Index = 8; break;
|
||||
case eTex5: Index = 9; break;
|
||||
case eTex6: Index = 10; break;
|
||||
case eTex7: Index = 11; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[Index]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, gskAttribSize[Index] * mNumVertices, pData);
|
||||
}
|
||||
|
||||
void CDynamicVertexBuffer::ClearBuffers()
|
||||
{
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
u8 Bit = 1 << iAttrib;
|
||||
|
||||
if (mBufferedFlags & Bit)
|
||||
glDeleteBuffers(1, &mAttribBuffers[iAttrib]);
|
||||
}
|
||||
|
||||
mBufferedFlags = eNoAttributes;
|
||||
}
|
||||
|
||||
GLuint CDynamicVertexBuffer::CreateVAO()
|
||||
{
|
||||
GLuint VertexArray;
|
||||
glGenVertexArrays(1, &VertexArray);
|
||||
glBindVertexArray(VertexArray);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
|
||||
|
||||
if (HasAttrib)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
GLuint NumComponents;
|
||||
GLenum DataType;
|
||||
|
||||
if ((iAttrib == 2) || (iAttrib == 3))
|
||||
{
|
||||
NumComponents = 4;
|
||||
DataType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumComponents = gskAttribSize[iAttrib] / 4;
|
||||
DataType = GL_FLOAT;
|
||||
}
|
||||
|
||||
glVertexAttribPointer(iAttrib, NumComponents, DataType, GL_FALSE, 0, (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
return VertexArray;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CDynamicVertexBuffer::InitBuffers()
|
||||
{
|
||||
if (mBufferedFlags) ClearBuffers();
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
|
||||
|
||||
if (HasAttrib)
|
||||
{
|
||||
glGenBuffers(1, &mAttribBuffers[iAttrib]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, gskAttribSize[iAttrib] * mNumVertices, NULL, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
}
|
||||
mBufferedFlags = mAttribFlags;
|
||||
}
|
||||
32
OpenGL/CDynamicVertexBuffer.h
Normal file
32
OpenGL/CDynamicVertexBuffer.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CDYNAMICVERTEXBUFFER_H
|
||||
#define CDYNAMICVERTEXBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
#include <Common/CVector2f.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <Resource/model/EVertexDescription.h>
|
||||
#include <vector>
|
||||
|
||||
class CDynamicVertexBuffer
|
||||
{
|
||||
EVertexDescription mAttribFlags;
|
||||
EVertexDescription mBufferedFlags;
|
||||
u32 mNumVertices;
|
||||
GLuint mAttribBuffers[12];
|
||||
|
||||
public:
|
||||
CDynamicVertexBuffer();
|
||||
~CDynamicVertexBuffer();
|
||||
void SetVertexCount(u32 NumVerts);
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void SetActiveAttribs(u32 AttribFlags);
|
||||
void BufferAttrib(EVertexDescription Attrib, const void *pData);
|
||||
void ClearBuffers();
|
||||
GLuint CreateVAO();
|
||||
private:
|
||||
void InitBuffers();
|
||||
};
|
||||
|
||||
#endif // CDYNAMICVERTEXBUFFER_H
|
||||
111
OpenGL/CFramebuffer.cpp
Normal file
111
OpenGL/CFramebuffer.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "CFramebuffer.h"
|
||||
#include <iostream>
|
||||
|
||||
CFramebuffer::CFramebuffer()
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mpRenderbuffer = nullptr;
|
||||
mpTexture = nullptr;
|
||||
}
|
||||
|
||||
CFramebuffer::CFramebuffer(u32 Width, u32 Height)
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mpRenderbuffer = nullptr;
|
||||
mpTexture = nullptr;
|
||||
Resize(Width, Height);
|
||||
}
|
||||
|
||||
CFramebuffer::~CFramebuffer()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
glDeleteFramebuffers(1, &mFramebuffer);
|
||||
delete mpRenderbuffer;
|
||||
delete mpTexture;
|
||||
}
|
||||
}
|
||||
|
||||
void CFramebuffer::Init()
|
||||
{
|
||||
if (!smStaticsInitialized)
|
||||
{
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &smDefaultFramebuffer);
|
||||
smStaticsInitialized = true;
|
||||
}
|
||||
|
||||
if (!mInitialized)
|
||||
{
|
||||
glGenFramebuffers(1, &mFramebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
|
||||
mpRenderbuffer = new CRenderbuffer(mWidth, mHeight);
|
||||
mpRenderbuffer->Bind();
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
|
||||
);
|
||||
|
||||
mpTexture = new CTexture(mWidth, mHeight);
|
||||
mpTexture->Bind(0);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0
|
||||
);
|
||||
|
||||
mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
if (mStatus != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cout << "\rError: Framebuffer not complete\n";
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CFramebuffer::Bind()
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
}
|
||||
|
||||
void CFramebuffer::Resize(u32 Width, u32 Height)
|
||||
{
|
||||
if ((mWidth != Width) || (mHeight != Height))
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
|
||||
if (mInitialized)
|
||||
{
|
||||
mpRenderbuffer->Resize(Width, Height);
|
||||
mpTexture->Resize(Width, Height);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||
mpRenderbuffer->Bind();
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mpRenderbuffer->BufferID()
|
||||
);
|
||||
|
||||
mpTexture->Bind(0);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->TextureID(), 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTexture* CFramebuffer::Texture()
|
||||
{
|
||||
return mpTexture;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
void CFramebuffer::BindDefaultFramebuffer()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, smDefaultFramebuffer);
|
||||
}
|
||||
|
||||
GLint CFramebuffer::smDefaultFramebuffer;
|
||||
bool CFramebuffer::smStaticsInitialized;
|
||||
32
OpenGL/CFramebuffer.h
Normal file
32
OpenGL/CFramebuffer.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef CFRAMEBUFFER_H
|
||||
#define CFRAMEBUFFER_H
|
||||
|
||||
#include "CRenderbuffer.h"
|
||||
#include <Resource/CTexture.h>
|
||||
#include <gl/glew.h>
|
||||
|
||||
class CFramebuffer
|
||||
{
|
||||
GLuint mFramebuffer;
|
||||
CRenderbuffer *mpRenderbuffer;
|
||||
CTexture *mpTexture;
|
||||
u32 mWidth, mHeight;
|
||||
bool mInitialized;
|
||||
GLenum mStatus;
|
||||
|
||||
static GLint smDefaultFramebuffer;
|
||||
static bool smStaticsInitialized;
|
||||
|
||||
public:
|
||||
CFramebuffer();
|
||||
CFramebuffer(u32 Width, u32 Height);
|
||||
~CFramebuffer();
|
||||
void Init();
|
||||
void Bind();
|
||||
void Resize(u32 Width, u32 Height);
|
||||
CTexture* Texture();
|
||||
static void BindDefaultFramebuffer();
|
||||
|
||||
};
|
||||
|
||||
#endif // CFRAMEBUFFER_H
|
||||
41
OpenGL/CGL.cpp
Normal file
41
OpenGL/CGL.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "CGL.h"
|
||||
|
||||
// ************ PUBLIC ************
|
||||
void CGL::SetBlendMode(EBlendFactor Source, EBlendFactor Dest)
|
||||
{
|
||||
glBlendFuncSeparate(Source, Dest, eBlendZero, eBlendZero);
|
||||
mBlendSrcFac = Source;
|
||||
mBlendDstFac = Dest;
|
||||
}
|
||||
|
||||
void CGL::SetOpaqueBlend()
|
||||
{
|
||||
SetBlendMode(eBlendOne, eBlendZero);
|
||||
}
|
||||
|
||||
void CGL::SetAlphaBlend()
|
||||
{
|
||||
SetBlendMode(eBlendSrcAlpha, eBlendInvSrcAlpha);
|
||||
}
|
||||
|
||||
void CGL::SetAdditiveBlend()
|
||||
{
|
||||
SetBlendMode(eBlendOne, eBlendOne);
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CGL::Init()
|
||||
{
|
||||
if (!mInitialized)
|
||||
{
|
||||
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
mBlendSrcFac = eBlendOne;
|
||||
mBlendDstFac = eBlendZero;
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
bool CGL::mInitialized;
|
||||
EBlendFactor CGL::mBlendSrcFac;
|
||||
EBlendFactor CGL::mBlendDstFac;
|
||||
26
OpenGL/CGL.h
Normal file
26
OpenGL/CGL.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CGL_H
|
||||
#define CGL_H
|
||||
|
||||
#include "GLCommon.h"
|
||||
#include <Common/types.h>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class CGL
|
||||
{
|
||||
public:
|
||||
void SetBlendMode(EBlendFactor Source, EBlendFactor Dest);
|
||||
void SetOpaqueBlend();
|
||||
void SetAlphaBlend();
|
||||
void SetAdditiveBlend();
|
||||
|
||||
private:
|
||||
static void Init();
|
||||
|
||||
static bool mInitialized;
|
||||
static EBlendFactor mBlendSrcFac, mBlendDstFac;
|
||||
static u8 mColorMask;
|
||||
static bool mDepthMask;
|
||||
static bool mStencilMask;
|
||||
};
|
||||
|
||||
#endif // CGL_H
|
||||
156
OpenGL/CIndexBuffer.cpp
Normal file
156
OpenGL/CIndexBuffer.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "CIndexBuffer.h"
|
||||
|
||||
CIndexBuffer::CIndexBuffer()
|
||||
{
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
CIndexBuffer::CIndexBuffer(GLenum type)
|
||||
{
|
||||
mPrimitiveType = type;
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
CIndexBuffer::~CIndexBuffer()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
}
|
||||
|
||||
void CIndexBuffer::AddIndex(u16 idx)
|
||||
{
|
||||
mIndices.push_back(idx);
|
||||
}
|
||||
|
||||
void CIndexBuffer::AddIndices(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count);
|
||||
for (u32 i = 0; i < count; i++)
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Reserve(u32 size)
|
||||
{
|
||||
mIndices.reserve(mIndices.size() + size);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Clear()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
|
||||
mBuffered = false;
|
||||
mIndices.clear();
|
||||
}
|
||||
|
||||
void CIndexBuffer::Buffer()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(1, &mIndexBuffer);
|
||||
|
||||
glGenBuffers(1, &mIndexBuffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndices.size() * sizeof(u16), mIndices.data(), GL_STATIC_DRAW);
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CIndexBuffer::Bind()
|
||||
{
|
||||
if (!mBuffered) Buffer();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
|
||||
}
|
||||
|
||||
void CIndexBuffer::Unbind()
|
||||
{
|
||||
}
|
||||
|
||||
void CIndexBuffer::DrawElements()
|
||||
{
|
||||
Bind();
|
||||
glDrawElements(mPrimitiveType, mIndices.size(), GL_UNSIGNED_SHORT, (void*) 0);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CIndexBuffer::DrawElements(u32 Offset, u32 Size)
|
||||
{
|
||||
Bind();
|
||||
glDrawElements(mPrimitiveType, Size, GL_UNSIGNED_SHORT, (void*) (Offset * 2));
|
||||
Unbind();
|
||||
}
|
||||
|
||||
bool CIndexBuffer::IsBuffered()
|
||||
{
|
||||
return mBuffered;
|
||||
}
|
||||
|
||||
u32 CIndexBuffer::GetSize()
|
||||
{
|
||||
return mIndices.size();
|
||||
}
|
||||
|
||||
GLenum CIndexBuffer::GetPrimitiveType()
|
||||
{
|
||||
return mPrimitiveType;
|
||||
}
|
||||
|
||||
void CIndexBuffer::SetPrimitiveType(GLenum type)
|
||||
{
|
||||
mPrimitiveType = type;
|
||||
}
|
||||
|
||||
void CIndexBuffer::TrianglesToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count + (count / 3));
|
||||
|
||||
for (u32 i = 0; i < count; i += 3)
|
||||
{
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(*indicesPtr++);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
void CIndexBuffer::FansToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve(count);
|
||||
u16 FirstIndex = *indicesPtr;
|
||||
|
||||
for (u32 i = 2; i < count; i += 3)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(indicesPtr[i]);
|
||||
mIndices.push_back(FirstIndex);
|
||||
if (i + 1 < count)
|
||||
mIndices.push_back(indicesPtr[i + 1]);
|
||||
if (i + 2 < count)
|
||||
mIndices.push_back(indicesPtr[i + 2]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
void CIndexBuffer::QuadsToStrips(u16 *indicesPtr, u32 count)
|
||||
{
|
||||
Reserve((u32) (count * 1.25));
|
||||
|
||||
u32 i = 3;
|
||||
for (; i < count; i += 4)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 2]);
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(indicesPtr[i - 3]);
|
||||
mIndices.push_back(indicesPtr[i]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
|
||||
// if there's three indices present that indicates a single triangle
|
||||
if (i == count)
|
||||
{
|
||||
mIndices.push_back(indicesPtr[i - 3]);
|
||||
mIndices.push_back(indicesPtr[i - 2]);
|
||||
mIndices.push_back(indicesPtr[i - 1]);
|
||||
mIndices.push_back(0xFFFF);
|
||||
}
|
||||
|
||||
}
|
||||
39
OpenGL/CIndexBuffer.h
Normal file
39
OpenGL/CIndexBuffer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef CINDEXBUFFER_H
|
||||
#define CINDEXBUFFER_H
|
||||
|
||||
#include <Common/types.h>
|
||||
#include <Common/CVector3f.h>
|
||||
#include <gl/glew.h>
|
||||
|
||||
class CIndexBuffer
|
||||
{
|
||||
GLuint mIndexBuffer;
|
||||
std::vector<u16> mIndices;
|
||||
GLenum mPrimitiveType;
|
||||
bool mBuffered;
|
||||
|
||||
public:
|
||||
CIndexBuffer();
|
||||
CIndexBuffer(GLenum type);
|
||||
~CIndexBuffer();
|
||||
void AddIndex(u16 idx);
|
||||
void AddIndices(u16 *indicesPtr, u32 count);
|
||||
void Reserve(u32 size);
|
||||
void Clear();
|
||||
void Buffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void DrawElements();
|
||||
void DrawElements(u32 Offset, u32 Size);
|
||||
bool IsBuffered();
|
||||
|
||||
u32 GetSize();
|
||||
GLenum GetPrimitiveType();
|
||||
void SetPrimitiveType(GLenum type);
|
||||
|
||||
void TrianglesToStrips(u16 *indicesPtr, u32 count);
|
||||
void FansToStrips(u16 *indicesPtr, u32 count);
|
||||
void QuadsToStrips(u16 *indicesPtr, u32 count);
|
||||
};
|
||||
|
||||
#endif // CINDEXBUFFER_H
|
||||
52
OpenGL/CRenderbuffer.cpp
Normal file
52
OpenGL/CRenderbuffer.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "CRenderbuffer.h"
|
||||
|
||||
CRenderbuffer::CRenderbuffer()
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
|
||||
CRenderbuffer::CRenderbuffer(u32 Width, u32 Height)
|
||||
{
|
||||
mInitialized = false;
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
}
|
||||
|
||||
CRenderbuffer::~CRenderbuffer()
|
||||
{
|
||||
if (mInitialized)
|
||||
glDeleteRenderbuffers(1, &mRenderbuffer);
|
||||
}
|
||||
|
||||
void CRenderbuffer::Init()
|
||||
{
|
||||
glGenRenderbuffers(1, &mRenderbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
void CRenderbuffer::Resize(u32 Width, u32 Height)
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
|
||||
if (mInitialized)
|
||||
{
|
||||
Bind();
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mWidth, mHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderbuffer::Bind()
|
||||
{
|
||||
if (!mInitialized) Init();
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
|
||||
}
|
||||
|
||||
void CRenderbuffer::Unbind()
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
31
OpenGL/CRenderbuffer.h
Normal file
31
OpenGL/CRenderbuffer.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef CRENDERBUFFER_H
|
||||
#define CRENDERBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
class CRenderbuffer
|
||||
{
|
||||
GLuint mRenderbuffer;
|
||||
u32 mWidth, mHeight;
|
||||
bool mInitialized;
|
||||
|
||||
public:
|
||||
CRenderbuffer();
|
||||
CRenderbuffer(u32 Width, u32 Height);
|
||||
~CRenderbuffer();
|
||||
void Init();
|
||||
void Resize(u32 Width, u32 Height);
|
||||
void Bind();
|
||||
void Unbind();
|
||||
|
||||
// Getters
|
||||
GLuint BufferID();
|
||||
};
|
||||
|
||||
inline GLuint CRenderbuffer::BufferID()
|
||||
{
|
||||
return mRenderbuffer;
|
||||
}
|
||||
|
||||
#endif // CRENDERBUFFER_H
|
||||
263
OpenGL/CShader.cpp
Normal file
263
OpenGL/CShader.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#include "CShader.h"
|
||||
#include <Common/types.h>
|
||||
#include <Core/CGraphics.h>
|
||||
#include <FileIO/CTextInStream.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
bool gDebugDumpShaders = false;
|
||||
u64 gFailedCompileCount = 0;
|
||||
u64 gSuccessfulCompileCount = 0;
|
||||
|
||||
CShader* CShader::spCurrentShader = nullptr;
|
||||
|
||||
CShader::CShader()
|
||||
{
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
mProgramExists = false;
|
||||
}
|
||||
|
||||
CShader::CShader(const char *kpVertexSource, const char *kpPixelSource)
|
||||
{
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
mProgramExists = false;
|
||||
|
||||
CompileVertexSource(kpVertexSource);
|
||||
CompilePixelSource(kpPixelSource);
|
||||
LinkShaders();
|
||||
}
|
||||
|
||||
CShader::~CShader()
|
||||
{
|
||||
if (mVertexShaderExists) glDeleteShader(mVertexShader);
|
||||
if (mPixelShaderExists) glDeleteShader(mPixelShader);
|
||||
if (mProgramExists) glDeleteProgram(mProgram);
|
||||
|
||||
if (spCurrentShader == this) spCurrentShader = 0;
|
||||
}
|
||||
|
||||
bool CShader::CompileVertexSource(const char* kpSource)
|
||||
{
|
||||
mVertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(mVertexShader, 1, (const GLchar**) &kpSource, NULL);
|
||||
glCompileShader(mVertexShader);
|
||||
|
||||
// Shader should be compiled - check for errors
|
||||
GLint CompileStatus;
|
||||
glGetShaderiv(mVertexShader, GL_COMPILE_STATUS, &CompileStatus);
|
||||
|
||||
if (CompileStatus == GL_FALSE)
|
||||
{
|
||||
std::string Out = "dump/BadVS_" + std::to_string(gFailedCompileCount) + ".txt";
|
||||
std::cout << "ERROR: Unable to compile vertex shader; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mVertexShader, Out);
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteShader(mVertexShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Debug dump
|
||||
else if (gDebugDumpShaders == true)
|
||||
{
|
||||
std::string Out = "dump/VS_" + std::to_string(gSuccessfulCompileCount) + ".txt";
|
||||
std::cout << "Debug shader dumping enabled; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mVertexShader, Out);
|
||||
|
||||
gSuccessfulCompileCount++;
|
||||
}
|
||||
|
||||
mVertexShaderExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::CompilePixelSource(const char* kpSource)
|
||||
{
|
||||
mPixelShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(mPixelShader, 1, (const GLchar**) &kpSource, NULL);
|
||||
glCompileShader(mPixelShader);
|
||||
|
||||
// Shader should be compiled - check for errors
|
||||
GLint CompileStatus;
|
||||
glGetShaderiv(mPixelShader, GL_COMPILE_STATUS, &CompileStatus);
|
||||
|
||||
if (CompileStatus == GL_FALSE)
|
||||
{
|
||||
std::string Out = "dump/BadPS_" + std::to_string(gFailedCompileCount) + ".txt";
|
||||
std::cout << "ERROR: Unable to compile pixel shader; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mPixelShader, Out);
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteShader(mPixelShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Debug dump
|
||||
else if (gDebugDumpShaders == true)
|
||||
{
|
||||
std::string Out = "dump/PS_" + std::to_string(gSuccessfulCompileCount) + ".txt";
|
||||
std::cout << "Debug shader dumping enabled; dumped to " << Out << "\n";
|
||||
DumpShaderSource(mPixelShader, Out);
|
||||
|
||||
gSuccessfulCompileCount++;
|
||||
}
|
||||
|
||||
mPixelShaderExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::LinkShaders()
|
||||
{
|
||||
if ((!mVertexShaderExists) || (!mPixelShaderExists)) return false;
|
||||
|
||||
mProgram = glCreateProgram();
|
||||
glAttachShader(mProgram, mVertexShader);
|
||||
glAttachShader(mProgram, mPixelShader);
|
||||
glLinkProgram(mProgram);
|
||||
|
||||
glDeleteShader(mVertexShader);
|
||||
glDeleteShader(mPixelShader);
|
||||
mVertexShaderExists = false;
|
||||
mPixelShaderExists = false;
|
||||
|
||||
// Shader should be linked - check for errors
|
||||
GLint LinkStatus;
|
||||
glGetProgramiv(mProgram, GL_LINK_STATUS, &LinkStatus);
|
||||
|
||||
if (LinkStatus == GL_FALSE)
|
||||
{
|
||||
std::string Out = "dump/BadLink_" + std::to_string(gFailedCompileCount) + ".txt";
|
||||
std::cout << "ERROR: Unable to link shaders. Dumped error log to " << Out << "\n";
|
||||
|
||||
GLint LogLen;
|
||||
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &LogLen);
|
||||
GLchar *InfoLog = new GLchar[LogLen];
|
||||
glGetProgramInfoLog(mProgram, LogLen, NULL, InfoLog);
|
||||
|
||||
std::ofstream LinkOut;
|
||||
LinkOut.open(Out.c_str());
|
||||
|
||||
if (LogLen > 0)
|
||||
LinkOut << InfoLog;
|
||||
|
||||
LinkOut.close();
|
||||
delete[] InfoLog;
|
||||
|
||||
gFailedCompileCount++;
|
||||
glDeleteProgram(mProgram);
|
||||
return false;
|
||||
}
|
||||
|
||||
mMVPBlockIndex = GetUniformBlockIndex("MVPBlock");
|
||||
mVertexBlockIndex = GetUniformBlockIndex("VertexBlock");
|
||||
mPixelBlockIndex = GetUniformBlockIndex("PixelBlock");
|
||||
mLightBlockIndex = GetUniformBlockIndex("LightBlock");
|
||||
|
||||
mProgramExists = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CShader::IsValidProgram()
|
||||
{
|
||||
return mProgramExists;
|
||||
}
|
||||
|
||||
GLuint CShader::GetProgramID()
|
||||
{
|
||||
return mProgram;
|
||||
}
|
||||
|
||||
GLuint CShader::GetUniformLocation(const char* Uniform)
|
||||
{
|
||||
return glGetUniformLocation(mProgram, Uniform);
|
||||
}
|
||||
|
||||
GLuint CShader::GetUniformBlockIndex(const char* UniformBlock)
|
||||
{
|
||||
return glGetUniformBlockIndex(mProgram, UniformBlock);
|
||||
}
|
||||
|
||||
void CShader::SetCurrent()
|
||||
{
|
||||
if (spCurrentShader != this)
|
||||
{
|
||||
glUseProgram(mProgram);
|
||||
spCurrentShader = this;
|
||||
|
||||
glUniformBlockBinding(mProgram, mMVPBlockIndex, CGraphics::MVPBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mVertexBlockIndex, CGraphics::VertexBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mPixelBlockIndex, CGraphics::PixelBlockBindingPoint());
|
||||
glUniformBlockBinding(mProgram, mLightBlockIndex, CGraphics::LightBlockBindingPoint());
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CShader* CShader::FromResourceFile(std::string ShaderName)
|
||||
{
|
||||
std::string VertexShaderFilename = "../resources/shaders/" + ShaderName + ".vs";
|
||||
std::string PixelShaderFilename = "../resources/shaders/" + ShaderName + ".ps";
|
||||
CTextInStream VertexShaderFile(VertexShaderFilename);
|
||||
CTextInStream PixelShaderFile(PixelShaderFilename);
|
||||
|
||||
if (!VertexShaderFile.IsValid())
|
||||
std::cout << "Error: Couldn't load vertex shader file for " << ShaderName << "\n";
|
||||
if (!PixelShaderFile.IsValid())
|
||||
std::cout << "Error: Couldn't load pixel shader file for " << ShaderName << "\n";
|
||||
if ((!VertexShaderFile.IsValid()) || (!PixelShaderFile.IsValid())) return nullptr;
|
||||
|
||||
std::stringstream VertexShader;
|
||||
while (!VertexShaderFile.EoF())
|
||||
VertexShader << VertexShaderFile.GetString();
|
||||
|
||||
std::stringstream PixelShader;
|
||||
while (!PixelShaderFile.EoF())
|
||||
PixelShader << PixelShaderFile.GetString();
|
||||
|
||||
CShader *pShader = new CShader();
|
||||
pShader->CompileVertexSource(VertexShader.str().c_str());
|
||||
pShader->CompilePixelSource(PixelShader.str().c_str());
|
||||
pShader->LinkShaders();
|
||||
return pShader;
|
||||
}
|
||||
|
||||
CShader* CShader::CurrentShader()
|
||||
{
|
||||
return spCurrentShader;
|
||||
}
|
||||
|
||||
void CShader::KillCachedShader()
|
||||
{
|
||||
spCurrentShader = 0;
|
||||
}
|
||||
|
||||
// ************ PRIVATE ************
|
||||
void CShader::DumpShaderSource(GLuint Shader, std::string Out)
|
||||
{
|
||||
GLint SourceLen;
|
||||
glGetShaderiv(Shader, GL_SHADER_SOURCE_LENGTH, &SourceLen);
|
||||
GLchar *Source = new GLchar[SourceLen];
|
||||
glGetShaderSource(Shader, SourceLen, NULL, Source);
|
||||
|
||||
GLint LogLen;
|
||||
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &LogLen);
|
||||
GLchar *InfoLog = new GLchar[LogLen];
|
||||
glGetShaderInfoLog(Shader, LogLen, NULL, InfoLog);
|
||||
|
||||
std::ofstream ShaderOut;
|
||||
ShaderOut.open(Out.c_str());
|
||||
|
||||
if (SourceLen > 0)
|
||||
ShaderOut << Source;
|
||||
if (LogLen > 0)
|
||||
ShaderOut << InfoLog;
|
||||
|
||||
ShaderOut.close();
|
||||
|
||||
delete[] Source;
|
||||
delete[] InfoLog;
|
||||
}
|
||||
45
OpenGL/CShader.h
Normal file
45
OpenGL/CShader.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef CSHADER_H
|
||||
#define CSHADER_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
#include <string>
|
||||
|
||||
class CShader
|
||||
{
|
||||
bool mVertexShaderExists;
|
||||
bool mPixelShaderExists;
|
||||
bool mProgramExists;
|
||||
GLuint mVertexShader;
|
||||
GLuint mPixelShader;
|
||||
GLuint mProgram;
|
||||
|
||||
GLuint mMVPBlockIndex;
|
||||
GLuint mVertexBlockIndex;
|
||||
GLuint mPixelBlockIndex;
|
||||
GLuint mLightBlockIndex;
|
||||
|
||||
static CShader* spCurrentShader;
|
||||
|
||||
public:
|
||||
CShader();
|
||||
CShader(const char* kpVertexSource, const char* kpPixelSource);
|
||||
~CShader();
|
||||
bool CompileVertexSource(const char* kpSource);
|
||||
bool CompilePixelSource(const char* kpSource);
|
||||
bool LinkShaders();
|
||||
bool IsValidProgram();
|
||||
GLuint GetProgramID();
|
||||
GLuint GetUniformLocation(const char* Uniform);
|
||||
GLuint GetUniformBlockIndex(const char* UniformBlock);
|
||||
void SetCurrent();
|
||||
|
||||
// Static
|
||||
static CShader* FromResourceFile(std::string ShaderName);
|
||||
static CShader* CurrentShader();
|
||||
static void KillCachedShader();
|
||||
|
||||
private:
|
||||
void DumpShaderSource(GLuint Shader, std::string Out);
|
||||
};
|
||||
|
||||
#endif // CSHADER_H
|
||||
445
OpenGL/CShaderGenerator.cpp
Normal file
445
OpenGL/CShaderGenerator.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <gl/glew.h>
|
||||
#include "CShaderGenerator.h"
|
||||
|
||||
const std::string gkCoordSrc[] = {
|
||||
"RawPosition.xyz",
|
||||
"RawNormal.xyz",
|
||||
"0.0, 0.0, 0.0",
|
||||
"0.0, 0.0, 0.0",
|
||||
"RawTex0.xy, 1.0",
|
||||
"RawTex1.xy, 1.0",
|
||||
"RawTex2.xy, 1.0",
|
||||
"RawTex3.xy, 1.0",
|
||||
"RawTex4.xy, 1.0",
|
||||
"RawTex5.xy, 1.0",
|
||||
"RawTex6.xy, 1.0",
|
||||
"RawTex7.xy, 1.0"
|
||||
};
|
||||
|
||||
const std::string gkRasSel[] = {
|
||||
"vec4(COLOR0A0.rgb, 1.0)",
|
||||
"vec4(COLOR1A1.rgb, 1.0)",
|
||||
"vec4(0.0, 0.0, 0.0, COLOR0A0.a)",
|
||||
"vec4(0.0, 0.0, 0.0, COLOR1A1.a)",
|
||||
"COLOR0A0",
|
||||
"COLOR1A1",
|
||||
"vec4(0.0, 0.0, 0.0, 0.0)"
|
||||
};
|
||||
|
||||
const std::string gkKonstColor[] = {
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.875, 0.875, 0.875",
|
||||
"0.75, 0.75, 0.75",
|
||||
"0.625, 0.625, 0.625",
|
||||
"0.5, 0.5, 0.5",
|
||||
"0.375, 0.375, 0.375",
|
||||
"0.25, 0.25, 0.25",
|
||||
"0.125, 0.125, 0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].rgb",
|
||||
"KonstColors[1].rgb",
|
||||
"KonstColors[2].rgb",
|
||||
"KonstColors[3].rgb",
|
||||
"KonstColors[0].rrr",
|
||||
"KonstColors[1].rrr",
|
||||
"KonstColors[2].rrr",
|
||||
"KonstColors[3].rrr",
|
||||
"KonstColors[0].ggg",
|
||||
"KonstColors[1].ggg",
|
||||
"KonstColors[2].ggg",
|
||||
"KonstColors[3].ggg",
|
||||
"KonstColors[0].bbb",
|
||||
"KonstColors[1].bbb",
|
||||
"KonstColors[2].bbb",
|
||||
"KonstColors[3].bbb",
|
||||
"KonstColors[0].aaa",
|
||||
"KonstColors[1].aaa",
|
||||
"KonstColors[2].aaa",
|
||||
"KonstColors[3].aaa"
|
||||
};
|
||||
|
||||
const std::string gkKonstAlpha[] = {
|
||||
"1.0",
|
||||
"0.875",
|
||||
"0.75",
|
||||
"0.625",
|
||||
"0.5",
|
||||
"0.375",
|
||||
"0.25",
|
||||
"0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].r",
|
||||
"KonstColors[1].r",
|
||||
"KonstColors[2].r",
|
||||
"KonstColors[3].r",
|
||||
"KonstColors[0].g",
|
||||
"KonstColors[1].g",
|
||||
"KonstColors[2].g",
|
||||
"KonstColors[3].g",
|
||||
"KonstColors[0].b",
|
||||
"KonstColors[1].b",
|
||||
"KonstColors[2].b",
|
||||
"KonstColors[3].b",
|
||||
"KonstColors[0].a",
|
||||
"KonstColors[1].a",
|
||||
"KonstColors[2].a",
|
||||
"KonstColors[3].a"
|
||||
};
|
||||
|
||||
const std::string gkTevColor[] = {
|
||||
"Prev.rgb",
|
||||
"Prev.aaa",
|
||||
"C0.rgb",
|
||||
"C0.aaa",
|
||||
"C1.rgb",
|
||||
"C1.aaa",
|
||||
"C2.rgb",
|
||||
"C2.aaa",
|
||||
"Tex.rgb",
|
||||
"Tex.aaa",
|
||||
"Ras.rgb",
|
||||
"Ras.aaa",
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.5, 0.5, 0.5",
|
||||
"Konst.rgb",
|
||||
"0.0, 0.0, 0.0"
|
||||
};
|
||||
|
||||
const std::string gkTevAlpha[] = {
|
||||
"Prev.a",
|
||||
"C0.a",
|
||||
"C1.a",
|
||||
"C2.a",
|
||||
"Tex.a",
|
||||
"Ras.a",
|
||||
"Konst.a",
|
||||
"0.0"
|
||||
};
|
||||
|
||||
const std::string gkTevRigid[] = {
|
||||
"Prev",
|
||||
"C0",
|
||||
"C1",
|
||||
"C2"
|
||||
};
|
||||
|
||||
CShaderGenerator::CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
CShaderGenerator::~CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreateVertexShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n";
|
||||
|
||||
// Input
|
||||
ShaderCode << "// Input\n";
|
||||
EVertexDescription VtxDesc = Mat.VtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "layout(location = 0) in vec3 RawPosition;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "layout(location = 1) in vec3 RawNormal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "layout(location = 2) in vec4 RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "layout(location = 3) in vec4 RawColor1;\n";
|
||||
if (VtxDesc & eTex0) ShaderCode << "layout(location = 4) in vec2 RawTex0;\n";
|
||||
if (VtxDesc & eTex1) ShaderCode << "layout(location = 5) in vec2 RawTex1;\n";
|
||||
if (VtxDesc & eTex2) ShaderCode << "layout(location = 6) in vec2 RawTex2;\n";
|
||||
if (VtxDesc & eTex3) ShaderCode << "layout(location = 7) in vec2 RawTex3;\n";
|
||||
if (VtxDesc & eTex4) ShaderCode << "layout(location = 8) in vec2 RawTex4;\n";
|
||||
if (VtxDesc & eTex5) ShaderCode << "layout(location = 9) in vec2 RawTex5;\n";
|
||||
if (VtxDesc & eTex6) ShaderCode << "layout(location = 10) in vec2 RawTex6;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Output
|
||||
ShaderCode << "// Output\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "out vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "out vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "out vec4 Color1;\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < Mat.PassCount(); iPass++)
|
||||
if (Mat.Pass(iPass)->TexCoordSource() != 0xFF)
|
||||
ShaderCode << "out vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "out vec4 COLOR0A0;\n"
|
||||
<< "out vec4 COLOR1A1;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Uniforms
|
||||
ShaderCode << "// Uniforms\n"
|
||||
<< "layout(std140) uniform MVPBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 ModelMtx;\n"
|
||||
<< " mat4 ViewMtx;\n"
|
||||
<< " mat4 ProjMtx;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform VertexBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 TexMtx[10];\n"
|
||||
<< " mat4 PostMtx[20];\n"
|
||||
<< " vec4 COLOR0_Amb;\n"
|
||||
<< " vec4 COLOR0_Mat;\n"
|
||||
<< " vec4 COLOR1_Amb;\n"
|
||||
<< " vec4 COLOR1_Mat;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "struct GXLight\n"
|
||||
<< "{\n"
|
||||
<< " vec4 Position;\n"
|
||||
<< " vec4 Direction;\n"
|
||||
<< " vec4 Color;\n"
|
||||
<< " vec4 DistAtten;\n"
|
||||
<< " vec4 AngleAtten;\n"
|
||||
<< "};\n"
|
||||
<< "layout(std140) uniform LightBlock {\n"
|
||||
<< " GXLight Lights[8];\n"
|
||||
<< "};\n"
|
||||
<< "uniform int NumLights;\n"
|
||||
<< "\n";
|
||||
|
||||
// Main
|
||||
ShaderCode << "// Main\n"
|
||||
<< "void main()\n"
|
||||
<< "{\n"
|
||||
<< " mat4 MVP = ModelMtx * ViewMtx * ProjMtx;\n"
|
||||
<< " mat4 MV = ModelMtx * ViewMtx;\n";
|
||||
|
||||
if (VtxDesc & ePosition) ShaderCode << " gl_Position = vec4(RawPosition, 1) * MVP;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << " Normal = normalize(RawNormal.xyz * inverse(transpose(mat3(MV))));\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << " Color0 = RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << " Color1 = RawColor1;\n";
|
||||
|
||||
// Per-vertex lighting
|
||||
ShaderCode << "\n"
|
||||
<< " // Dynamic Lighting\n";
|
||||
|
||||
// This bit could do with some cleaning up
|
||||
// It took a lot of experimentation to get dynamic lights working and I never went back and cleaned it up after
|
||||
if (Mat.IsLightingEnabled())
|
||||
{
|
||||
ShaderCode << " vec4 Illum = vec4(0.0);\n"
|
||||
<< " vec3 PositionMV = vec3(vec4(RawPosition, 1.0) * MV);\n"
|
||||
<< " \n"
|
||||
<< " for (int iLight = 0; iLight < NumLights; iLight++)\n"
|
||||
<< " {\n"
|
||||
<< " vec3 LightPosMV = vec3(Lights[iLight].Position * ViewMtx);\n"
|
||||
<< " vec3 LightDirMV = normalize(Lights[iLight].Direction.xyz * inverse(transpose(mat3(ViewMtx))));\n"
|
||||
<< " vec3 LightDist = LightPosMV.xyz - PositionMV.xyz;\n"
|
||||
<< " float DistSquared = dot(LightDist, LightDist);\n"
|
||||
<< " float Dist = sqrt(DistSquared);\n"
|
||||
<< " LightDist /= Dist;\n"
|
||||
<< " vec3 AngleAtten = Lights[iLight].AngleAtten.xyz;\n"
|
||||
<< " AngleAtten = vec3(AngleAtten.x, AngleAtten.y, AngleAtten.z);\n"
|
||||
<< " float Atten = max(0, dot(LightDist, LightDirMV.xyz));\n"
|
||||
<< " Atten = max(0, dot(AngleAtten, vec3(1.0, Atten, Atten * Atten))) / dot(Lights[iLight].DistAtten.xyz, vec3(1.0, Dist, DistSquared));\n"
|
||||
<< " float DiffuseAtten = max(0, dot(Normal, LightDist));\n"
|
||||
<< " Illum += (Atten * DiffuseAtten * Lights[iLight].Color);\n"
|
||||
<< " }\n"
|
||||
<< " COLOR0A0 = COLOR0_Mat * (Illum + COLOR0_Amb);\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat * (Illum + COLOR1_Amb);\n"
|
||||
<< " \n";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ShaderCode << " COLOR0A0 = COLOR0_Mat;\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat;\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Texture coordinate generation
|
||||
ShaderCode << " \n"
|
||||
<< " // TexGen\n";
|
||||
|
||||
u32 PassCount = Mat.PassCount();
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
{
|
||||
CMaterialPass *pPass = Mat.Pass(iPass);
|
||||
if (pPass->TexCoordSource() == 0xFF) continue;
|
||||
|
||||
EUVAnimMode AnimMode = pPass->AnimMode();
|
||||
|
||||
if (AnimMode == eNoUVAnim) // No animation
|
||||
ShaderCode << " Tex" << iPass << " = vec3(" << gkCoordSrc[pPass->TexCoordSource()] << ");\n";
|
||||
|
||||
else // Animation used - texture matrix at least, possibly normalize/post-transform
|
||||
{
|
||||
// Texture Matrix
|
||||
ShaderCode << " Tex" << iPass << " = vec3(vec4(" << gkCoordSrc[pPass->TexCoordSource()] << ", 1.0) * TexMtx[" << iPass << "]).xyz;\n";
|
||||
|
||||
if ((AnimMode < 2) || (AnimMode > 5))
|
||||
{
|
||||
// Normalization + Post-Transform
|
||||
ShaderCode << " Tex" << iPass << " = normalize(Tex" << iPass << ");\n";
|
||||
ShaderCode << " Tex" << iPass << " = vec3(vec4(Tex" << iPass << ", 1.0) * PostMtx[" << iPass << "]).xyz;\n";
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode << "\n";
|
||||
}
|
||||
ShaderCode << "}\n\n";
|
||||
|
||||
|
||||
// Done!
|
||||
return mShader->CompileVertexSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreatePixelShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n"
|
||||
<< "#extension GL_ARB_shading_language_420pack : enable\n" // Needed to set texture binding layouts
|
||||
<< "\n";
|
||||
|
||||
EVertexDescription VtxDesc = Mat.VtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "in vec3 Position;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "in vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "in vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "in vec4 Color1;\n";
|
||||
|
||||
u32 PassCount = Mat.PassCount();
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
if (Mat.Pass(iPass)->TexCoordSource() != 0xFF)
|
||||
ShaderCode << "in vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "in vec4 COLOR0A0;\n"
|
||||
<< "in vec4 COLOR1A1;\n"
|
||||
<< "\n"
|
||||
<< "out vec4 PixelColor;\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform PixelBlock {\n"
|
||||
<< " vec4 KonstColors[4];\n"
|
||||
<< " vec4 TevColor;\n"
|
||||
<< " vec4 TintColor;\n"
|
||||
<< "};\n\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
if (Mat.Pass(iPass)->Texture() != nullptr)
|
||||
ShaderCode << "layout(binding = " << iPass << ") uniform sampler2D Texture" << iPass << ";\n";
|
||||
|
||||
ShaderCode <<"\n";
|
||||
|
||||
ShaderCode << "void main()\n"
|
||||
<< "{\n"
|
||||
<< " vec4 TevInA = vec4(0, 0, 0, 0), TevInB = vec4(0, 0, 0, 0), TevInC = vec4(0, 0, 0, 0), TevInD = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Prev = vec4(0, 0, 0, 0), C0 = TevColor, C1 = C0, C2 = C0;\n"
|
||||
<< " vec4 Ras = vec4(0, 0, 0, 1), Tex = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Konst = vec4(1, 1, 1, 1);\n";
|
||||
|
||||
ShaderCode << " vec2 TevCoord = vec2(0, 0);\n"
|
||||
<< " \n";
|
||||
|
||||
bool Lightmap = false;
|
||||
for (u32 iPass = 0; iPass < PassCount; iPass++)
|
||||
{
|
||||
const CMaterialPass *pPass = Mat.Pass(iPass);
|
||||
CFourCC PassType = pPass->Type();
|
||||
|
||||
ShaderCode << " // TEV Stage " << iPass << " - " << PassType.ToString() << "\n";
|
||||
if (pPass->Type() == "DIFF") Lightmap = true;
|
||||
|
||||
if (!pPass->IsEnabled())
|
||||
{
|
||||
ShaderCode << " // Pass is disabled\n\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pPass->TexCoordSource() != 0xFF)
|
||||
ShaderCode << " TevCoord = (Tex" << iPass << ".z == 0.0 ? Tex" << iPass << ".xy : Tex" << iPass << ".xy / Tex" << iPass << ".z);\n";
|
||||
|
||||
if (pPass->Texture() != nullptr)
|
||||
ShaderCode << " Tex = texture(Texture" << iPass << ", TevCoord)";
|
||||
|
||||
// A couple pass types require special swizzles to access different texture color channels as alpha
|
||||
if ((PassType == "TRAN") || (PassType == "INCA") || (PassType == "BLOI"))
|
||||
ShaderCode << ".rgbr";
|
||||
else if (PassType == "BLOL")
|
||||
ShaderCode << ".rgbg";
|
||||
|
||||
ShaderCode << ";\n";
|
||||
|
||||
ShaderCode << " Konst = vec4(" << gkKonstColor[pPass->KColorSel()] << ", " << gkKonstAlpha[pPass->KAlphaSel()] << ");\n";
|
||||
|
||||
if (pPass->RasSel() != eRasColorNull)
|
||||
ShaderCode << " Ras = " << gkRasSel[pPass->RasSel()] << ";\n";
|
||||
|
||||
for (u8 iInput = 0; iInput < 4; iInput++)
|
||||
{
|
||||
char TevChar = iInput + 0x41; // the current stage number represented as an ASCII letter; eg 0 is 'A'
|
||||
|
||||
ShaderCode << " TevIn" << TevChar << " = vec4("
|
||||
<< gkTevColor[pPass->ColorInput(iInput) & 0xF]
|
||||
<< ", "
|
||||
<< gkTevAlpha[pPass->AlphaInput(iInput) & 0x7]
|
||||
<< ");\n";
|
||||
}
|
||||
|
||||
ShaderCode << " // RGB Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->ColorOutput()]
|
||||
<< ".rgb = ";
|
||||
|
||||
ShaderCode << "clamp(vec3(TevInD.rgb + ((1.0 - TevInC.rgb) * TevInA.rgb + TevInC.rgb * TevInB.rgb))";
|
||||
if ((PassType == "CLR ") && (Lightmap)) ShaderCode << "* 2.0"; // Apply tevscale 2.0 on the color pass if lightmap is present
|
||||
ShaderCode << ", vec3(0, 0, 0), vec3(1.0, 1.0, 1.0));\n";
|
||||
|
||||
ShaderCode << " // Alpha Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->AlphaOutput()]
|
||||
<< ".a = ";
|
||||
|
||||
ShaderCode << "clamp(TevInD.a + ((1.0 - TevInC.a) * TevInA.a + TevInC.a * TevInB.a), 0.0, 1.0);\n\n";
|
||||
}
|
||||
|
||||
if (Mat.Options() & CMaterial::ePunchthrough)
|
||||
{
|
||||
if (Mat.Version() < eCorruptionProto)
|
||||
{
|
||||
ShaderCode << " if (Prev.a <= 0.25) discard;\n"
|
||||
<< " else Prev.a = 1.0;\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode << " if (Prev.a <= 0.75) discard;\n"
|
||||
" else Prev.a = 0.0;\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode << " PixelColor = Prev.rgba;\n"
|
||||
<< "}\n\n";
|
||||
|
||||
// Done!
|
||||
return mShader->CompilePixelSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
CShader* CShaderGenerator::GenerateShader(const CMaterial& Mat)
|
||||
{
|
||||
CShaderGenerator Generator;
|
||||
Generator.mShader = new CShader();
|
||||
|
||||
bool Success = Generator.CreateVertexShader(Mat);
|
||||
if (Success) Success = Generator.CreatePixelShader(Mat);
|
||||
|
||||
Generator.mShader->LinkShaders();
|
||||
return Generator.mShader;
|
||||
}
|
||||
445
OpenGL/CShaderGenerator.cpp.bW5112
Normal file
445
OpenGL/CShaderGenerator.cpp.bW5112
Normal file
@@ -0,0 +1,445 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <gl/glew.h>
|
||||
#include "CShaderGenerator.h"
|
||||
|
||||
const std::string gkCoordSrc[] = {
|
||||
"RawPosition.xyz",
|
||||
"RawNormal.xyz",
|
||||
"0.0, 0.0, 0.0",
|
||||
"0.0, 0.0, 0.0",
|
||||
"RawTex0.xy, 1.0",
|
||||
"RawTex1.xy, 1.0",
|
||||
"RawTex2.xy, 1.0",
|
||||
"RawTex3.xy, 1.0",
|
||||
"RawTex4.xy, 1.0",
|
||||
"RawTex5.xy, 1.0",
|
||||
"RawTex6.xy, 1.0",
|
||||
"RawTex7.xy, 1.0"
|
||||
};
|
||||
|
||||
const std::string gkKonstColor[] = {
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.875, 0.875, 0.875",
|
||||
"0.75, 0.75, 0.75",
|
||||
"0.625, 0.625, 0.625",
|
||||
"0.5, 0.5, 0.5",
|
||||
"0.375, 0.375, 0.375",
|
||||
"0.25, 0.25, 0.25",
|
||||
"0.125, 0.125, 0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].rgb",
|
||||
"KonstColors[1].rgb",
|
||||
"KonstColors[2].rgb",
|
||||
"KonstColors[3].rgb",
|
||||
"KonstColors[0].rrr",
|
||||
"KonstColors[1].rrr",
|
||||
"KonstColors[2].rrr",
|
||||
"KonstColors[3].rrr",
|
||||
"KonstColors[0].ggg",
|
||||
"KonstColors[1].ggg",
|
||||
"KonstColors[2].ggg",
|
||||
"KonstColors[3].ggg",
|
||||
"KonstColors[0].bbb",
|
||||
"KonstColors[1].bbb",
|
||||
"KonstColors[2].bbb",
|
||||
"KonstColors[3].bbb",
|
||||
"KonstColors[0].aaa",
|
||||
"KonstColors[1].aaa",
|
||||
"KonstColors[2].aaa",
|
||||
"KonstColors[3].aaa"
|
||||
};
|
||||
|
||||
const std::string gkKonstAlpha[] = {
|
||||
"1.0",
|
||||
"0.875",
|
||||
"0.75",
|
||||
"0.625",
|
||||
"0.5",
|
||||
"0.375",
|
||||
"0.25",
|
||||
"0.125",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"KonstColors[0].r",
|
||||
"KonstColors[1].r",
|
||||
"KonstColors[2].r",
|
||||
"KonstColors[3].r",
|
||||
"KonstColors[0].g",
|
||||
"KonstColors[1].g",
|
||||
"KonstColors[2].g",
|
||||
"KonstColors[3].g",
|
||||
"KonstColors[0].b",
|
||||
"KonstColors[1].b",
|
||||
"KonstColors[2].b",
|
||||
"KonstColors[3].b",
|
||||
"KonstColors[0].a",
|
||||
"KonstColors[1].a",
|
||||
"KonstColors[2].a",
|
||||
"KonstColors[3].a"
|
||||
};
|
||||
|
||||
const std::string gkTevColor[] = {
|
||||
"Prev.rgb",
|
||||
"Prev.aaa",
|
||||
"C0.rgb",
|
||||
"C0.aaa",
|
||||
"C1.rgb",
|
||||
"C1.aaa",
|
||||
"C2.rgb",
|
||||
"C2.aaa",
|
||||
"Tex.rgb",
|
||||
"Tex.aaa",
|
||||
"Ras.rgb",
|
||||
"Ras.aaa",
|
||||
"1.0, 1.0, 1.0",
|
||||
"0.5, 0.5, 0.5",
|
||||
"Konst.rgb",
|
||||
"0, 0, 0"
|
||||
};
|
||||
|
||||
const std::string gkTevAlpha[] = {
|
||||
"Prev.a",
|
||||
"C0.a",
|
||||
"C1.a",
|
||||
"C2.a",
|
||||
"Tex.a",
|
||||
"Ras.a",
|
||||
"Konst.a",
|
||||
"0"
|
||||
};
|
||||
|
||||
const std::string gkTevRigid[] = {
|
||||
"Prev",
|
||||
"C0",
|
||||
"C1",
|
||||
"C2"
|
||||
};
|
||||
|
||||
CShaderGenerator::CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
CShaderGenerator::~CShaderGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreateVertexShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n";
|
||||
|
||||
// Input
|
||||
ShaderCode << "// Input\n";
|
||||
EVertexDescription VtxDesc = Mat.GetVtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "layout(location = 0) in vec3 RawPosition;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "layout(location = 1) in vec3 RawNormal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "layout(location = 2) in vec4 RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "layout(location = 3) in vec4 RawColor1;\n";
|
||||
if (VtxDesc & eTex0) ShaderCode << "layout(location = 4) in vec2 RawTex0;\n";
|
||||
if (VtxDesc & eTex1) ShaderCode << "layout(location = 5) in vec2 RawTex1;\n";
|
||||
if (VtxDesc & eTex2) ShaderCode << "layout(location = 6) in vec2 RawTex2;\n";
|
||||
if (VtxDesc & eTex3) ShaderCode << "layout(location = 7) in vec2 RawTex3;\n";
|
||||
if (VtxDesc & eTex4) ShaderCode << "layout(location = 8) in vec2 RawTex4;\n";
|
||||
if (VtxDesc & eTex5) ShaderCode << "layout(location = 9) in vec2 RawTex5;\n";
|
||||
if (VtxDesc & eTex6) ShaderCode << "layout(location = 10) in vec2 RawTex6;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Output
|
||||
ShaderCode << "// Output\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "out vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "out vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "out vec4 Color1;\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < Mat.mPasses.size(); iPass++)
|
||||
if (Mat.mPasses[iPass].TexCoordSource != 0xFF)
|
||||
ShaderCode << "out vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "out vec4 COLOR0A0;\n"
|
||||
<< "out vec4 COLOR1A1;\n";
|
||||
ShaderCode << "\n";
|
||||
|
||||
// Uniforms
|
||||
ShaderCode << "// Uniforms\n"
|
||||
<< "layout(std140) uniform MVPBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 ModelMtx;\n"
|
||||
<< " mat4 ViewMtx;\n"
|
||||
<< " mat4 ProjMtx;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform VertexBlock\n"
|
||||
<< "{\n"
|
||||
<< " mat4 TexMtx[10];\n"
|
||||
<< " mat4 PostMtx[20];\n"
|
||||
<< " vec4 COLOR0_Amb;\n"
|
||||
<< " vec4 COLOR0_Mat;\n"
|
||||
<< " vec4 COLOR1_Amb;\n"
|
||||
<< " vec4 COLOR1_Mat;\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "struct GXLight\n"
|
||||
<< "{\n"
|
||||
<< " vec4 Position;\n"
|
||||
<< " vec4 Direction;\n"
|
||||
<< " vec4 Color;\n"
|
||||
<< " vec4 DistAtten;\n"
|
||||
<< " vec4 AngleAtten;\n"
|
||||
<< "};\n"
|
||||
<< "layout(std140) uniform LightBlock {\n"
|
||||
<< " GXLight Lights[8];\n"
|
||||
<< "};\n"
|
||||
<< "uniform int NumLights;\n"
|
||||
<< "\n";
|
||||
|
||||
// Main
|
||||
ShaderCode << "// Main\n"
|
||||
<< "void main()\n"
|
||||
<< "{\n"
|
||||
<< " mat4 MVP = ModelMtx * ViewMtx * ProjMtx;\n"
|
||||
<< " mat4 MV = ModelMtx * ViewMtx;\n";
|
||||
|
||||
if (VtxDesc & ePosition) ShaderCode << " gl_Position = vec4(RawPosition, 1) * MVP;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << " Normal = normalize(RawNormal.xyz * inverse(transpose(mat3(MV))));\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << " Color1 = RawColor0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << " Color2 = RawColor1;\n";
|
||||
|
||||
// Per-vertex lighting
|
||||
ShaderCode << "\n"
|
||||
<< " // Dynamic Lighting\n";
|
||||
|
||||
// The 0x1 bit on the flag determines whether lighting is enabled for COLOR0
|
||||
if (Mat.mChanCtrlFlags & 0x1)
|
||||
{
|
||||
u8 DiffuseFunction = (Mat.mChanCtrlFlags >> 11) & 0x3;
|
||||
|
||||
if (Mat.mChanCount > 0)
|
||||
{
|
||||
ShaderCode << " vec4 Illum = vec4(0.0);\n"
|
||||
<< " vec3 PositionMV = vec3(vec4(RawPosition, 1.0) * MV);\n"
|
||||
<< " \n"
|
||||
<< " for (int iLight = 0; iLight < NumLights; iLight++)\n"
|
||||
<< " {\n"
|
||||
<< " vec3 LightPosMV = vec3(Lights[iLight].Position * ViewMtx);\n"
|
||||
<< " vec3 LightDirMV = normalize(Lights[iLight].Direction.xyz * inverse(transpose(mat3(ViewMtx))));\n"
|
||||
<< " vec3 LightDist = LightPosMV.xyz - PositionMV.xyz;\n"
|
||||
<< " float DistSquared = dot(LightDist, LightDist);\n"
|
||||
<< " float Dist = sqrt(DistSquared);\n"
|
||||
<< " LightDist /= Dist;\n"
|
||||
<< " vec3 AngleAtten = Lights[iLight].AngleAtten.xyz;\n"
|
||||
<< " AngleAtten = vec3(AngleAtten.x, AngleAtten.y, AngleAtten.z);\n"
|
||||
<< " float Atten = max(0, dot(LightDist, LightDirMV.xyz));\n"
|
||||
<< " Atten = max(0, dot(AngleAtten, vec3(1.0, Atten, Atten * Atten))) / dot(Lights[iLight].DistAtten.xyz, vec3(1.0, Dist, DistSquared));\n";
|
||||
|
||||
if (DiffuseFunction == 2) ShaderCode << " float DiffuseAtten = max(0, dot(Normal, LightDist));\n";
|
||||
else if (DiffuseFunction == 1) ShaderCode << " float DiffuseAtten = dot(Normal, LightDist);\n";
|
||||
else ShaderCode << " float DiffuseAtten = 1.0;\n";
|
||||
|
||||
ShaderCode << " Illum += (Atten * DiffuseAtten * Lights[iLight].Color);\n"
|
||||
<< " }\n"
|
||||
<< " COLOR0A0 = COLOR0_Mat * (Illum + COLOR0_Amb);\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat * (Illum + COLOR1_Amb);\n"
|
||||
<< " \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode << " COLOR0A0 = COLOR0_Mat;\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat;\n";
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ShaderCode << " COLOR0A0 = COLOR0_Mat;\n"
|
||||
<< " COLOR1A1 = COLOR1_Mat;\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Texture coordinate generation
|
||||
ShaderCode << " \n"
|
||||
<< " // TexGen\n";
|
||||
|
||||
for (u32 iCoord = 0; iCoord < Mat.mPasses.size(); iCoord++)
|
||||
{
|
||||
if (Mat.mPasses[iCoord].TexCoordSource == 0xFF) continue;
|
||||
|
||||
s32 AnimType = Mat.mPasses[iCoord].AnimMode;
|
||||
|
||||
// Texture Matrix
|
||||
if (AnimType == -1) // No animation
|
||||
ShaderCode << " Tex" << iCoord << " = vec3(" << gkCoordSrc[Mat.mPasses[iCoord].TexCoordSource] << ");\n";
|
||||
|
||||
else // Animation used - texture matrix at least, possibly normalization/post-transform
|
||||
{
|
||||
// Texture Matrix
|
||||
ShaderCode << " Tex" << iCoord << " = vec3(vec4(" << gkCoordSrc[Mat.mPasses[iCoord].TexCoordSource] << ", 1.0) * TexMtx[" << iCoord << "]).xyz;\n";
|
||||
|
||||
if ((AnimType < 2) || (AnimType > 5))
|
||||
{
|
||||
// Normalization + Post-Transform
|
||||
ShaderCode << " Tex" << iCoord << " = normalize(Tex" << iCoord << ");\n";
|
||||
ShaderCode << " Tex" << iCoord << " = vec3(vec4(Tex" << iCoord << ", 1.0) * PostMtx[" << iCoord << "]).xyz;\n";
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode << "\n";
|
||||
}
|
||||
ShaderCode << "}\n\n";
|
||||
|
||||
|
||||
// Done!
|
||||
return mShader->CompileVertexSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
bool CShaderGenerator::CreatePixelShader(const CMaterial& Mat)
|
||||
{
|
||||
std::stringstream ShaderCode;
|
||||
ShaderCode << "#version 330 core\n"
|
||||
<< "\n"
|
||||
<< "#extension GL_ARB_shading_language_420pack : enable\n" // Needed to set texture binding layouts
|
||||
<< "\n";
|
||||
|
||||
EVertexDescription VtxDesc = Mat.GetVtxDesc();
|
||||
if (VtxDesc & ePosition) ShaderCode << "in vec3 Position;\n";
|
||||
if (VtxDesc & eNormal) ShaderCode << "in vec3 Normal;\n";
|
||||
if (VtxDesc & eColor0) ShaderCode << "in vec4 Color0;\n";
|
||||
if (VtxDesc & eColor1) ShaderCode << "in vec4 Color1;\n";
|
||||
|
||||
for (u32 iPass = 0; iPass < Mat.mPasses.size(); iPass++)
|
||||
if (Mat.mPasses[iPass].TexCoordSource != 0xFF)
|
||||
ShaderCode << "in vec3 Tex" << iPass << ";\n";
|
||||
|
||||
ShaderCode << "in vec4 COLOR0A0;\n"
|
||||
<< "in vec4 COLOR1A1;\n"
|
||||
<< "\n"
|
||||
<< "out vec4 PixelColor;\n"
|
||||
<< "\n"
|
||||
<< "layout(std140) uniform PixelBlock {\n"
|
||||
<< " vec4 KonstColors[4];\n"
|
||||
<< " vec4 TevColor;\n"
|
||||
<< " vec4 TintColor;\n"
|
||||
<< "};\n\n";
|
||||
|
||||
for (u32 iTex = 0; iTex < Mat.mPasses.size(); iTex++)
|
||||
if (Mat.mPasses[iTex].pTexture != nullptr)
|
||||
ShaderCode << "layout(binding = " << iTex << ") uniform sampler2D Texture" << iTex << ";\n";
|
||||
|
||||
ShaderCode <<"\n";
|
||||
|
||||
ShaderCode << "void main()\n"
|
||||
<< "{\n"
|
||||
<< " vec4 TevInA = vec4(0, 0, 0, 0), TevInB = vec4(0, 0, 0, 0), TevInC = vec4(0, 0, 0, 0), TevInD = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Prev = vec4(0, 0, 0, 0), C0 = TevColor, C1 = C0, C2 = C0;\n"
|
||||
<< " vec4 Ras = vec4(0, 0, 0, 1), Tex = vec4(0, 0, 0, 0);\n"
|
||||
<< " vec4 Konst = vec4(1, 1, 1, 1);\n";
|
||||
|
||||
ShaderCode << " vec2 TevCoord = vec2(0, 0);\n"
|
||||
<< " \n";
|
||||
|
||||
for (u32 iPass = 0; iPass < Mat.mPasses.size(); iPass++)
|
||||
{
|
||||
ShaderCode << " // TEV Stage " << iPass << "\n";
|
||||
const CMaterial::SPass *pPass = &Mat.mPasses[iPass];
|
||||
|
||||
if (pPass->Hidden)
|
||||
{
|
||||
ShaderCode << " // Pass is hidden\n\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pPass->TexCoordSource != 0xFF)
|
||||
ShaderCode << " TevCoord = (Tex" << iPass << ".z == 0.0 ? Tex" << iPass << ".xy : Tex" << iPass << ".xy / Tex" << iPass << ".z);\n";
|
||||
|
||||
if (pPass->pTexture != nullptr)
|
||||
ShaderCode << " Tex = texture(Texture" << iPass << ", TevCoord);\n";
|
||||
|
||||
ShaderCode << " Konst = vec4(" << gkKonstColor[pPass->KonstColorSel] << ", " << gkKonstAlpha[pPass->KonstAlphaSel] << ");\n";
|
||||
|
||||
if (pPass->RasSel != 0xFF)
|
||||
{
|
||||
if (pPass->RasSel == 0x0) ShaderCode << " Ras = vec4(COLOR0A0.xyz, 1.0);\n";
|
||||
else if (pPass->RasSel == 0x1) ShaderCode << " Ras = vec4(COLOR1A1.xyz, 1.0);\n";
|
||||
else if (pPass->RasSel == 0x2) ShaderCode << " Ras = vec4(0.0, 0.0, 0.0, COLOR0A0.w);\n";
|
||||
else if (pPass->RasSel == 0x3) ShaderCode << " Ras = vec4(0.0, 0.0, 0.0, COLOR1A1.w);\n";
|
||||
else if (pPass->RasSel == 0x4) ShaderCode << " Ras = COLOR0A0;\n";
|
||||
else if (pPass->RasSel == 0x5) ShaderCode << " Ras = COLOR1A1;\n";
|
||||
else if (pPass->RasSel == 0x6) ShaderCode << " Ras = vec4(0.0, 0.0, 0.0, 0.0);\n";
|
||||
}
|
||||
|
||||
for (u8 iInput = 0; iInput < 4; iInput++)
|
||||
{
|
||||
u8 TevCharacter = iInput + 0x41; // the current stage number represented as an ASCII letter; eg 0 is 'A'
|
||||
|
||||
ShaderCode << " TevIn" << TevCharacter << " = vec4("
|
||||
<< gkTevColor[Mat.GetTevColorIn(iPass, iInput) & 0xF]
|
||||
<< ", "
|
||||
<< gkTevAlpha[Mat.GetTevAlphaIn(iPass, iInput) & 0x7]
|
||||
<< ");\n";
|
||||
}
|
||||
|
||||
// Applying TRAN and BLOL (opacity and bloom maps) in Corruption require accessing specific color channels
|
||||
// This feels hacky and might not be the best way to implement this
|
||||
if (pPass->Type == "TRAN")
|
||||
{
|
||||
ShaderCode << " // TRAN Combine\n"
|
||||
<< " Prev.a = 1.0 - Tex.r;\n\n";
|
||||
}
|
||||
/*else if (pPass->Type == "BLOL")
|
||||
{
|
||||
ShaderCode << " // BLOL Combine\n"
|
||||
<< " C0.rgb += vec3(Tex.g, Tex.g, Tex.g);\n\n";
|
||||
}*/
|
||||
|
||||
else
|
||||
{
|
||||
ShaderCode << " // RGB Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->ColorOutputRegister]
|
||||
<< ".rgb = ";
|
||||
|
||||
ShaderCode << "clamp(vec3(TevInD.rgb + ((1.0 - TevInC.rgb) * TevInA.rgb + TevInC.rgb * TevInB.rgb)), vec3(0, 0, 0), vec3(1.0, 1.0, 1.0));\n";
|
||||
|
||||
ShaderCode << " // Alpha Combine\n"
|
||||
<< " "
|
||||
<< gkTevRigid[pPass->AlphaOutputRegister]
|
||||
<< ".a = ";
|
||||
|
||||
ShaderCode << "clamp(TevInD.a + ((1.0 - TevInC.a) * TevInA.a + TevInC.a * TevInB.a), 0.0, 1.0);\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (Mat.GetOptions() & ePunchthrough) {
|
||||
ShaderCode << " if (Prev.a <= 0.25) discard;\n"
|
||||
<< " else Prev.a = 1.0;\n";
|
||||
}
|
||||
|
||||
ShaderCode << " PixelColor = Prev.rgba * TintColor;\n"
|
||||
<< "}\n\n";
|
||||
|
||||
// Done!
|
||||
return mShader->CompilePixelSource(ShaderCode.str().c_str());
|
||||
}
|
||||
|
||||
CShader* CShaderGenerator::GenerateShader(const CMaterial& Mat)
|
||||
{
|
||||
CShaderGenerator Generator;
|
||||
Generator.mShader = new CShader();
|
||||
|
||||
bool success = Generator.CreateVertexShader(Mat);
|
||||
if (success) success = Generator.CreatePixelShader(Mat);
|
||||
|
||||
Generator.mShader->LinkShaders();
|
||||
return Generator.mShader;
|
||||
}
|
||||
22
OpenGL/CShaderGenerator.h
Normal file
22
OpenGL/CShaderGenerator.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SHADERGEN_H
|
||||
#define SHADERGEN_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
|
||||
#include "CShader.h"
|
||||
#include <Resource/CMaterial.h>
|
||||
|
||||
class CShaderGenerator
|
||||
{
|
||||
CShader *mShader;
|
||||
|
||||
CShaderGenerator();
|
||||
~CShaderGenerator();
|
||||
bool CreateVertexShader(const CMaterial& Mat);
|
||||
bool CreatePixelShader(const CMaterial& Mat);
|
||||
|
||||
public:
|
||||
static CShader* GenerateShader(const CMaterial& Mat);
|
||||
};
|
||||
|
||||
#endif // SHADERGEN_H
|
||||
60
OpenGL/CUniformBuffer.cpp
Normal file
60
OpenGL/CUniformBuffer.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "CUniformBuffer.h"
|
||||
|
||||
CUniformBuffer::CUniformBuffer()
|
||||
{
|
||||
glGenBuffers(1, &mUniformBuffer);
|
||||
SetBufferSize(0);
|
||||
}
|
||||
|
||||
CUniformBuffer::CUniformBuffer(u32 Size)
|
||||
{
|
||||
glGenBuffers(1, &mUniformBuffer);
|
||||
SetBufferSize(Size);
|
||||
}
|
||||
|
||||
CUniformBuffer::~CUniformBuffer()
|
||||
{
|
||||
glDeleteBuffers(1, &mUniformBuffer);
|
||||
}
|
||||
|
||||
void CUniformBuffer::InitializeBuffer()
|
||||
{
|
||||
Bind();
|
||||
glBufferData(GL_UNIFORM_BUFFER, mBufferSize, 0, GL_DYNAMIC_DRAW);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
|
||||
}
|
||||
|
||||
void CUniformBuffer::Unbind()
|
||||
{
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void CUniformBuffer::BindBase(GLuint index)
|
||||
{
|
||||
Bind();
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, index, mUniformBuffer);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::Buffer(void *pData)
|
||||
{
|
||||
Bind();
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, mBufferSize, pData);
|
||||
Unbind();
|
||||
}
|
||||
|
||||
void CUniformBuffer::SetBufferSize(u32 Size)
|
||||
{
|
||||
mBufferSize = Size;
|
||||
InitializeBuffer();
|
||||
}
|
||||
|
||||
u32 CUniformBuffer::GetBufferSize()
|
||||
{
|
||||
return mBufferSize;
|
||||
}
|
||||
28
OpenGL/CUniformBuffer.h
Normal file
28
OpenGL/CUniformBuffer.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CUNIFORMBUFFER_H
|
||||
#define CUNIFORMBUFFER_H
|
||||
|
||||
#include <gl/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
class CUniformBuffer
|
||||
{
|
||||
GLuint mUniformBuffer;
|
||||
u32 mBufferSize;
|
||||
|
||||
public:
|
||||
CUniformBuffer();
|
||||
CUniformBuffer(u32 Size);
|
||||
~CUniformBuffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
void BindBase(GLuint index);
|
||||
void Buffer(void *pData);
|
||||
|
||||
void SetBufferSize(u32 Size);
|
||||
u32 GetBufferSize();
|
||||
|
||||
private:
|
||||
void InitializeBuffer();
|
||||
};
|
||||
|
||||
#endif // CUNIFORMBUFFER_H
|
||||
105
OpenGL/CVertexArrayManager.cpp
Normal file
105
OpenGL/CVertexArrayManager.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "CVertexArrayManager.h"
|
||||
|
||||
// ************ STATIC MEMBER INITIALIZATION ************
|
||||
std::vector<CVertexArrayManager*> CVertexArrayManager::sVAManagers;
|
||||
CVertexArrayManager *CVertexArrayManager::spCurrentManager;
|
||||
|
||||
// ************ CONSTRUCTORS/DESTRUCTORS ************
|
||||
CVertexArrayManager::CVertexArrayManager()
|
||||
{
|
||||
mVectorIndex = sVAManagers.size();
|
||||
sVAManagers.push_back(this);
|
||||
}
|
||||
|
||||
CVertexArrayManager::~CVertexArrayManager()
|
||||
{
|
||||
for (auto it = mVBOMap.begin(); it != mVBOMap.end(); it = mVBOMap.begin())
|
||||
DeleteVAO(it->first);
|
||||
|
||||
for (auto it = mDynamicVBOMap.begin(); it != mDynamicVBOMap.end(); it = mDynamicVBOMap.begin())
|
||||
DeleteVAO(it->first);
|
||||
|
||||
sVAManagers.erase(sVAManagers.begin() + mVectorIndex);
|
||||
|
||||
if (sVAManagers.size() > mVectorIndex)
|
||||
for (auto it = sVAManagers.begin() + mVectorIndex; it != sVAManagers.end(); it++)
|
||||
(*it)->mVectorIndex--;
|
||||
}
|
||||
|
||||
// ************ PUBLIC ************
|
||||
void CVertexArrayManager::SetCurrent()
|
||||
{
|
||||
spCurrentManager = this;
|
||||
}
|
||||
|
||||
void CVertexArrayManager::BindVAO(CVertexBuffer *pVBO)
|
||||
{
|
||||
auto it = mVBOMap.find(pVBO);
|
||||
|
||||
if (it != mVBOMap.end())
|
||||
glBindVertexArray(it->second);
|
||||
|
||||
else
|
||||
{
|
||||
GLuint VAO = pVBO->CreateVAO();
|
||||
mVBOMap[pVBO] = VAO;
|
||||
glBindVertexArray(VAO);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::BindVAO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
// Overload for CDynamicVertexBuffer
|
||||
auto it = mDynamicVBOMap.find(pVBO);
|
||||
|
||||
if (it != mDynamicVBOMap.end())
|
||||
glBindVertexArray(it->second);
|
||||
|
||||
else
|
||||
{
|
||||
GLuint VAO = pVBO->CreateVAO();
|
||||
mDynamicVBOMap[pVBO] = VAO;
|
||||
glBindVertexArray(VAO);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteVAO(CVertexBuffer *pVBO)
|
||||
{
|
||||
auto it = mVBOMap.find(pVBO);
|
||||
|
||||
if (it != mVBOMap.end())
|
||||
{
|
||||
glDeleteVertexArrays(1, &it->second);
|
||||
mVBOMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteVAO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
// Overload for CDynamicVertexBuffer
|
||||
auto it = mDynamicVBOMap.find(pVBO);
|
||||
|
||||
if (it != mDynamicVBOMap.end())
|
||||
{
|
||||
glDeleteVertexArrays(1, &it->second);
|
||||
mDynamicVBOMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CVertexArrayManager* CVertexArrayManager::Current()
|
||||
{
|
||||
return spCurrentManager;
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteAllArraysForVBO(CVertexBuffer *pVBO)
|
||||
{
|
||||
for (u32 iVAM = 0; iVAM < sVAManagers.size(); iVAM++)
|
||||
sVAManagers[iVAM]->DeleteVAO(pVBO);
|
||||
}
|
||||
|
||||
void CVertexArrayManager::DeleteAllArraysForVBO(CDynamicVertexBuffer *pVBO)
|
||||
{
|
||||
for (u32 iVAM = 0; iVAM < sVAManagers.size(); iVAM++)
|
||||
sVAManagers[iVAM]->DeleteVAO(pVBO);
|
||||
}
|
||||
34
OpenGL/CVertexArrayManager.h
Normal file
34
OpenGL/CVertexArrayManager.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CVERTEXARRAYMANAGER_H
|
||||
#define CVERTEXARRAYMANAGER_H
|
||||
|
||||
#include "CDynamicVertexBuffer.h"
|
||||
#include "CVertexBuffer.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class CVertexArrayManager
|
||||
{
|
||||
std::unordered_map<CVertexBuffer*, GLuint> mVBOMap;
|
||||
std::unordered_map<CDynamicVertexBuffer*, GLuint> mDynamicVBOMap;
|
||||
u32 mVectorIndex;
|
||||
|
||||
static std::vector<CVertexArrayManager*> sVAManagers;
|
||||
static CVertexArrayManager *spCurrentManager;
|
||||
|
||||
public:
|
||||
CVertexArrayManager();
|
||||
~CVertexArrayManager();
|
||||
void SetCurrent();
|
||||
void BindVAO(CVertexBuffer *pVBO);
|
||||
void BindVAO(CDynamicVertexBuffer *pVBO);
|
||||
void DeleteVAO(CVertexBuffer *pVBO);
|
||||
void DeleteVAO(CDynamicVertexBuffer *pVBO);
|
||||
|
||||
static CVertexArrayManager* Current();
|
||||
static void DeleteAllArraysForVBO(CVertexBuffer *pVBO);
|
||||
static void DeleteAllArraysForVBO(CDynamicVertexBuffer *pVBO);
|
||||
};
|
||||
|
||||
#endif // CVERTEXARRAYMANAGER_H
|
||||
230
OpenGL/CVertexBuffer.cpp
Normal file
230
OpenGL/CVertexBuffer.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "CVertexBuffer.h"
|
||||
#include "CVertexArrayManager.h"
|
||||
#include <Core/CGraphics.h>
|
||||
|
||||
CVertexBuffer::CVertexBuffer()
|
||||
{
|
||||
mBuffered = false;
|
||||
SetVertexDesc(ePosition | eNormal | eTex0 | eTex1 | eTex2 | eTex3 | eTex4 | eTex5 | eTex6 | eTex7);
|
||||
}
|
||||
|
||||
CVertexBuffer::CVertexBuffer(EVertexDescription Desc)
|
||||
{
|
||||
mBuffered = false;
|
||||
SetVertexDesc(Desc);
|
||||
}
|
||||
|
||||
CVertexBuffer::~CVertexBuffer()
|
||||
{
|
||||
CVertexArrayManager::DeleteAllArraysForVBO(this);
|
||||
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
}
|
||||
|
||||
u16 CVertexBuffer::AddVertex(const CVertex& Vert)
|
||||
{
|
||||
if (mPositions.size() == 0xFFFF) throw std::overflow_error("VBO contains too many vertices");
|
||||
|
||||
if (mVtxDesc & ePosition) mPositions.push_back(Vert.Position);
|
||||
if (mVtxDesc & eNormal) mNormals.push_back(Vert.Normal);
|
||||
if (mVtxDesc & eColor0) mColors[0].push_back(Vert.Color[0]);
|
||||
if (mVtxDesc & eColor1) mColors[1].push_back(Vert.Color[1]);
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if (mVtxDesc & (eTex0 << (iTex * 2))) mTexCoords[iTex].push_back(Vert.Tex[iTex]);
|
||||
|
||||
for (u32 iMtx = 0; iMtx < 8; iMtx++)
|
||||
if (mVtxDesc & (ePosMtx << iMtx)) mTexCoords[iMtx].push_back(Vert.MatrixIndices[iMtx]);
|
||||
|
||||
return (mPositions.size() - 1);
|
||||
}
|
||||
|
||||
u16 CVertexBuffer::AddIfUnique(const CVertex& Vert, u16 Start)
|
||||
{
|
||||
if (Start < mPositions.size())
|
||||
{
|
||||
for (u16 iVert = Start; iVert < mPositions.size(); iVert++)
|
||||
{
|
||||
// I use a bool because "continue" doesn't work properly within the iTex loop
|
||||
bool Unique = false;
|
||||
|
||||
if (mVtxDesc & ePosition)
|
||||
if (Vert.Position != mPositions[iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eNormal))
|
||||
if (Vert.Normal != mNormals[iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eColor0))
|
||||
if (Vert.Color[0] != mColors[0][iVert]) Unique = true;
|
||||
|
||||
if ((!Unique) && (mVtxDesc & eColor1))
|
||||
if (Vert.Color[1] != mColors[1][iVert]) Unique = true;
|
||||
|
||||
if (!Unique)
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if ((mVtxDesc & (eTex0 << (iTex * 2))))
|
||||
if (Vert.Tex[iTex] != mTexCoords[iTex][iVert])
|
||||
{
|
||||
Unique = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Unique) return iVert;
|
||||
}
|
||||
}
|
||||
|
||||
return AddVertex(Vert);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Reserve(u16 size)
|
||||
{
|
||||
u32 ReserveSize = mPositions.size() + size;
|
||||
|
||||
if (mVtxDesc & ePosition)
|
||||
mPositions.reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eNormal)
|
||||
mNormals.reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eColor0)
|
||||
mColors[0].reserve(ReserveSize);
|
||||
|
||||
if (mVtxDesc & eColor1)
|
||||
mColors[1].reserve(ReserveSize);
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
if (mVtxDesc & (eTex0 << (iTex * 2)))
|
||||
mTexCoords[iTex].reserve(ReserveSize);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Clear()
|
||||
{
|
||||
if (mBuffered)
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
|
||||
mBuffered = false;
|
||||
mPositions.clear();
|
||||
mNormals.clear();
|
||||
mColors[0].clear();
|
||||
mColors[1].clear();
|
||||
|
||||
for (u32 iTex = 0; iTex < 8; iTex++)
|
||||
mTexCoords[iTex].clear();
|
||||
}
|
||||
|
||||
void CVertexBuffer::Buffer()
|
||||
{
|
||||
// Make sure we don't end up with two buffers for the same data...
|
||||
if (mBuffered)
|
||||
{
|
||||
glDeleteBuffers(12, mAttribBuffers);
|
||||
mBuffered = false;
|
||||
}
|
||||
|
||||
// Generate buffers
|
||||
glGenBuffers(12, mAttribBuffers);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
int Attrib = (ePosition << (iAttrib * 2));
|
||||
bool HasAttrib = ((mVtxDesc & Attrib) != 0);
|
||||
if (!HasAttrib) continue;
|
||||
|
||||
if (iAttrib < 2)
|
||||
{
|
||||
std::vector<CVector3f> *pBuffer = (iAttrib == 0) ? &mPositions : &mNormals;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, pBuffer->size() * sizeof(CVector3f), pBuffer->data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
else if (iAttrib < 4)
|
||||
{
|
||||
u8 idx = (u8) (iAttrib - 2);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, mColors[idx].size() * sizeof(CColor), mColors[idx].data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
u8 idx = (u8) (iAttrib - 4);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glBufferData(GL_ARRAY_BUFFER, mTexCoords[idx].size() * sizeof(CVector2f), mTexCoords[idx].data(), GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
mBuffered = true;
|
||||
}
|
||||
|
||||
void CVertexBuffer::Bind()
|
||||
{
|
||||
if (!mBuffered) Buffer();
|
||||
CVertexArrayManager::Current()->BindVAO(this);
|
||||
}
|
||||
|
||||
void CVertexBuffer::Unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
bool CVertexBuffer::IsBuffered()
|
||||
{
|
||||
return mBuffered;
|
||||
}
|
||||
|
||||
EVertexDescription CVertexBuffer::VertexDesc()
|
||||
{
|
||||
return mVtxDesc;
|
||||
}
|
||||
|
||||
void CVertexBuffer::SetVertexDesc(EVertexDescription Desc)
|
||||
{
|
||||
Clear();
|
||||
mVtxDesc = Desc;
|
||||
}
|
||||
|
||||
u32 CVertexBuffer::Size()
|
||||
{
|
||||
return mPositions.size();
|
||||
}
|
||||
|
||||
GLuint CVertexBuffer::CreateVAO()
|
||||
{
|
||||
GLuint VertexArray;
|
||||
glGenVertexArrays(1, &VertexArray);
|
||||
glBindVertexArray(VertexArray);
|
||||
|
||||
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
|
||||
{
|
||||
int Attrib = (ePosition << (iAttrib * 2));
|
||||
bool HasAttrib = ((mVtxDesc & Attrib) != 0);
|
||||
if (!HasAttrib) continue;
|
||||
|
||||
if (iAttrib < 2)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(CVector3f), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
|
||||
else if (iAttrib < 4)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(CColor), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
|
||||
glVertexAttribPointer(iAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(CVector2f), (void*) 0);
|
||||
glEnableVertexAttribArray(iAttrib);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
return VertexArray;
|
||||
}
|
||||
37
OpenGL/CVertexBuffer.h
Normal file
37
OpenGL/CVertexBuffer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef CVERTEXBUFFER_H
|
||||
#define CVERTEXBUFFER_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Resource/model/CVertex.h>
|
||||
#include <Resource/model/EVertexDescription.h>
|
||||
#include <vector>
|
||||
|
||||
class CVertexBuffer
|
||||
{
|
||||
EVertexDescription mVtxDesc; // Flags that indicate what vertex attributes are enabled on this vertex buffer
|
||||
GLuint mAttribBuffers[12]; // Separate GL buffer for each attribute to allow not tracking unused attribs. No support for matrix indices currently.
|
||||
std::vector<CVector3f> mPositions; // Vector of vertex positions
|
||||
std::vector<CVector3f> mNormals; // Vector of vertex normals
|
||||
std::vector<CColor> mColors[2]; // Vectors of vertex colors
|
||||
std::vector<CVector2f> mTexCoords[8]; // Vectors of texture coordinates
|
||||
bool mBuffered; // Bool value that indicates whether the attributes have been buffered.
|
||||
|
||||
public:
|
||||
CVertexBuffer();
|
||||
CVertexBuffer(EVertexDescription Desc);
|
||||
~CVertexBuffer();
|
||||
u16 AddVertex(const CVertex& vtx);
|
||||
u16 AddIfUnique(const CVertex& vtx, u16 start);
|
||||
void Reserve(u16 size);
|
||||
void Clear();
|
||||
void Buffer();
|
||||
void Bind();
|
||||
void Unbind();
|
||||
bool IsBuffered();
|
||||
EVertexDescription VertexDesc();
|
||||
void SetVertexDesc(EVertexDescription Desc);
|
||||
u32 Size();
|
||||
GLuint CreateVAO();
|
||||
};
|
||||
|
||||
#endif // CVERTEXBUFFER_H
|
||||
37
OpenGL/GLCommon.cpp
Normal file
37
OpenGL/GLCommon.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "GLCommon.h"
|
||||
#include <stdexcept>
|
||||
|
||||
GLenum glBlendFactor[] = {
|
||||
GL_ZERO, // GX_BL_ZERO
|
||||
GL_ONE, // GX_BL_ONE
|
||||
GL_SRC_COLOR, // GX_BL_SRCCLR / GX_BL_DSTCLR
|
||||
GL_ONE_MINUS_SRC_COLOR, // GX_BL_INVSRCCLR / GX_BL_INVDSTCLR
|
||||
GL_SRC_ALPHA, // GX_BL_SRCALPHA
|
||||
GL_ONE_MINUS_SRC_ALPHA, // GX_BL_INVSRCALPHA
|
||||
GL_DST_ALPHA, // GX_BL_DSTALPHA
|
||||
GL_ONE_MINUS_DST_ALPHA // GX_BL_INVDSTALPHA
|
||||
};
|
||||
|
||||
|
||||
GLenum glZMode[] = {
|
||||
GL_NEVER, // GX_NEVER
|
||||
GL_LESS, // GX_LESS
|
||||
GL_EQUAL, // GX_EQUAL
|
||||
GL_LEQUAL, // GX_LEQUAL
|
||||
GL_GREATER, // GX_GREATER
|
||||
GL_NOTEQUAL, // GX_NEQUAL
|
||||
GL_ALWAYS // GX_ALWAYS
|
||||
};
|
||||
|
||||
GLenum GXPrimToGLPrim(EGXPrimitiveType t) {
|
||||
switch (t) {
|
||||
case eGX_Quads: return GL_TRIANGLE_STRIP; // Quads are converted to strips
|
||||
case eGX_Triangles: return GL_TRIANGLE_STRIP; // Triangles are converted to strips
|
||||
case eGX_TriangleStrip: return GL_TRIANGLE_STRIP;
|
||||
case eGX_TriangleFan: return GL_TRIANGLE_STRIP; // Fans are converted to strips
|
||||
case eGX_Lines: return GL_LINES;
|
||||
case eGX_LineStrip: return GL_LINE_STRIP;
|
||||
case eGX_Points: return GL_POINTS;
|
||||
default: throw std::invalid_argument("Invalid GX primitive type");
|
||||
}
|
||||
}
|
||||
34
OpenGL/GLCommon.h
Normal file
34
OpenGL/GLCommon.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef GLCOMMON_H
|
||||
#define GLCOMMON_H
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <Common/types.h>
|
||||
|
||||
enum EBlendFactor
|
||||
{
|
||||
eBlendZero = GL_ZERO,
|
||||
eBlendOne = GL_ONE,
|
||||
eBlendSrcColor = GL_SRC_COLOR,
|
||||
eBlendInvSrcColor = GL_ONE_MINUS_SRC_COLOR,
|
||||
eBlendSrcAlpha = GL_SRC_ALPHA,
|
||||
eBlendInvSrcAlpha = GL_ONE_MINUS_SRC_ALPHA,
|
||||
eBlendDstAlpha = GL_DST_ALPHA,
|
||||
eBlendInvDstAlpha = GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
enum EGXPrimitiveType
|
||||
{
|
||||
eGX_Quads = 0x80,
|
||||
eGX_Triangles = 0x90,
|
||||
eGX_TriangleStrip = 0x98,
|
||||
eGX_TriangleFan = 0xA0,
|
||||
eGX_Lines = 0xA8,
|
||||
eGX_LineStrip = 0xB0,
|
||||
eGX_Points = 0xB8
|
||||
};
|
||||
|
||||
extern GLenum glBlendFactor[];
|
||||
extern GLenum glZMode[];
|
||||
GLenum GXPrimToGLPrim(EGXPrimitiveType t);
|
||||
|
||||
#endif // GLCOMMON_H
|
||||
18
OpenGL/SMeshPointer.h
Normal file
18
OpenGL/SMeshPointer.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef SMESHPOINTER_H
|
||||
#define SMESHPOINTER_H
|
||||
|
||||
#include <Common/CAABox.h>
|
||||
#include <Common/types.h>
|
||||
#include <Core/ERenderCommand.h>
|
||||
#include <Scene/CSceneNode.h>
|
||||
#include <Resource/CMaterial.h>
|
||||
|
||||
struct SMeshPointer
|
||||
{
|
||||
CSceneNode *pNode;
|
||||
u32 Asset;
|
||||
CAABox AABox;
|
||||
ERenderCommand Command;
|
||||
};
|
||||
|
||||
#endif // SMESHPOINTER_H
|
||||
Reference in New Issue
Block a user