diff options
Diffstat (limited to 'Runtime/Graphics')
29 files changed, 1255 insertions, 0 deletions
diff --git a/Runtime/Graphics/Color.h b/Runtime/Graphics/Color.h new file mode 100644 index 0000000..461e7af --- /dev/null +++ b/Runtime/Graphics/Color.h @@ -0,0 +1,22 @@ +#ifndef COLOR_H +#define COLOR_H + +#include "../Utilities/Type.h" + +class ColorRGBAf +{ +public: + float r, g, b, a; + +}; + +class ColorRGBA32 +{ +public: + uint8 r, g, b, a; + +}; + +using Color = ColorRGBAf; + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/Device.cpp b/Runtime/Graphics/Device.cpp new file mode 100644 index 0000000..d729a37 --- /dev/null +++ b/Runtime/Graphics/Device.cpp @@ -0,0 +1,78 @@ +#include "Device.h" + +bool deviceInited = false; +Device g_Device; + +Device::Device() +{ + Assert(deviceInited); + deviceInited = true; +} + +void Device::Initialize(DeviceSetting& setting) +{ + GPU::BufferPool::Instance()->Initialize(); +} + +void Device::Enable(DeviceEnable enabled) +{ + +} + +void Device::Disable(DeviceEnable enabled) +{ + +} + +void Device::IsEnable(uint flag) +{ + +} + +void Device::SetDepthTest(DepthTest testing) +{ + +} + +void Device::SetCullFace(CullFace face) +{ + +} + +void Device::SetStencilMask(byte stencilMask) +{ + +} + +void Device::SetStencilOp(StencilOp op) +{ + +} + +void Device::SetAntiAliasing(int level /*= 0*/) +{ + +} + +void Device::Clear(int clearFlag) +{ + +} + +void Device::BeginFrame() +{ + m_IsInsideFrame = true; + +} + +void Device::EndFrame() +{ + GPU::BufferPool::Instance()->OnEndFrame(); + + m_IsInsideFrame = false; +} + +void Device::PresentFrame() +{ +// swap buffers +}
\ No newline at end of file diff --git a/Runtime/Graphics/Device.h b/Runtime/Graphics/Device.h new file mode 100644 index 0000000..4e02b72 --- /dev/null +++ b/Runtime/Graphics/Device.h @@ -0,0 +1,82 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include "../Utilities/NonCopyable.h" +#include "../Utilities/Type.h" +#include "../Utilities/Assert.h" + +#include "Texture.h" +#include "Color.h" +#include "DeviceDefine.h" +#include "VertexBuffer.h" + +struct DeviceSetting +{ + TextureFilter texFilter; + TextureWrap texWrap; +}; + +class Device : public NonCopyable +{ +public: + Device(); + ~Device(); + + void Initialize(DeviceSetting& setting); + + void Enable(DeviceEnable enabled); + void Disable(DeviceEnable enabled); + void IsEnable(uint flag); + + void SetDepthTest(DepthTest testing); + void SetCullFace(CullFace face); + void SetStencilMask(byte stencilMask); + void SetStencilOp(StencilOp op); + + void SetAntiAliasing(int level = 0); + + void Clear(int clearFlag); + + void BeginFrame(); + void EndFrame(); + void PresentFrame(); + + GET(SharedVertexBuffer*, SharedVBO, m_SharedVBO); + + GET_SET(Color, ClearColor, m_ClearColor); + + GET_SET(TextureFilter, TextureFilter, m_TexFilter); + GET_SET(TextureWrap, TextureWrap, m_TexWrap); + + inline bool IsInsideFrame(); + +private: + uint m_EnableFlag; + + // Global texture setting + TextureFilter m_TexFilter; + TextureWrap m_TexWrap; + + Color m_ClearColor; + + DepthTest m_DepthTest; + StencilTest m_StencilTest; + StencilOp m_StencilOp; + byte m_StencilMask; + + SharedVertexBuffer m_SharedVBO; + + bool m_IsInsideFrame; + +}; + +extern Device g_Device; + +#define g_SharedVBO (*g_Device.GetSharedVBO()) + +inline bool Device::IsInsideFrame() +{ + return m_IsInsideFrame; +} + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/DeviceDefine.h b/Runtime/Graphics/DeviceDefine.h new file mode 100644 index 0000000..2f3cb6b --- /dev/null +++ b/Runtime/Graphics/DeviceDefine.h @@ -0,0 +1,69 @@ +#ifndef DEVICE_DEFINE_H +#define DEVICE_DEFINE_H + +enum DeviceEnable +{ + DeviceEnable_DepthTest = 1, + DeviceEnable_DepthWrite = 1 << 1, + DeviceEnable_StencilTest = 1 << 2, + DeviceEnable_StencilWrite = 1 << 3, + DeviceEnable_Cull = 1 << 4, + DeviceEnable_Blend = 1 << 5, + DeviceEnable_AntiAliasing = 1 << 6, +}; + +enum DepthTest +{ + DepthTest_Greater = 1, + DepthTest_GreaterEqual, + DepthTest_Less, + DepthTest_LessEqual, + DepthTest_Equal, + DepthTest_NotEqual, + DepthTest_Always, +}; + +enum StencilTest { + StencilTest_Always, + StencilTest_Never, + StencilTest_Less, + StencilTest_Equal, + StencilTest_NotEqual, + StencilTest_LessEqual, + StencilTest_Greater, + StencilTest_GreaterEqual, +}; + +enum StencilOp { + StencilOp_Keep, + StencilOp_Zero, + StencilOp_Replace, + StencilOp_Incr, + StencilOp_IncrWrap, + StencilOp_Decr, + StencilOp_DecrWrap, + StencilOp_Invert, +}; + +enum DeviceClear +{ + DeviceClear_Depth = 1, + DeviceClear_Stencil = 1 << 1, + DeviceClear_Color = 1 << 2, +}; + +enum CullFace +{ + CullFace_Front = 1, + CullFace_Back = 2, + CullFace_None = 3, + CullFace_All = 4, +}; + +enum BlendMode +{ + BlendMode_Additive = 1, + BlendMode_Substract = 1, +}; + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/FrameBuffer.cpp b/Runtime/Graphics/FrameBuffer.cpp new file mode 100644 index 0000000..e675aab --- /dev/null +++ b/Runtime/Graphics/FrameBuffer.cpp @@ -0,0 +1,12 @@ +#include "FrameBuffer.h" + +// 有些版本的OpenGL不支持绑定多个RT +bool FrameBuffer::BindRenderTexture(RenderTexture* rt, int location /* = 0 */) +{ + +} + +bool FrameBuffer::Blit(FrameBuffer* target) +{ + +} diff --git a/Runtime/Graphics/FrameBuffer.h b/Runtime/Graphics/FrameBuffer.h new file mode 100644 index 0000000..4b9104b --- /dev/null +++ b/Runtime/Graphics/FrameBuffer.h @@ -0,0 +1,35 @@ +#ifndef FRAME_BUFFER_H +#define FRAME_BUFFER_H + +#include "OpenGL.h" +#include "RenderTexture.h" + +// Fbo,所有绑定的texture和renderbuffer的target都是可读写的GL_FRAMEBUFFER +class FrameBuffer +{ +public: + enum FrameBufferUsage + { + FrameBufferUsage_None = 0, + FrameBufferUsage_Depth = 1, + FrameBufferUsage_Stencil = 2, + FrameBufferUsage_DepthStencil = 3, + }; + + FrameBuffer(FrameBufferUsage usage, int width, int height); + ~FrameBuffer(); + + bool Blit(FrameBuffer* target); + + bool BindRenderTexture(RenderTexture* rt, int location = 0); + + GET(int, Width, m_Width); + GET(int, Height, m_Height); + +private: + int m_Width, m_Height; + FrameBufferUsage m_Usage; + +}; + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/GlyphAtlas.cpp b/Runtime/Graphics/GlyphAtlas.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/GlyphAtlas.cpp diff --git a/Runtime/Graphics/GlyphAtlas.h b/Runtime/Graphics/GlyphAtlas.h new file mode 100644 index 0000000..b0ab858 --- /dev/null +++ b/Runtime/Graphics/GlyphAtlas.h @@ -0,0 +1,6 @@ +#ifndef TEXT_ATLAS_H +#define TEXT_ATLAS_H + + + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/GpuDataBuffer.cpp b/Runtime/Graphics/GpuDataBuffer.cpp new file mode 100644 index 0000000..0b3e4ee --- /dev/null +++ b/Runtime/Graphics/GpuDataBuffer.cpp @@ -0,0 +1,206 @@ +#include <math.h> + +#include "GpuDataBuffer.h" + +namespace GPU +{ + + // 修改buffer数据要绑定到这个目标上,其他情况下用GetHandle()绑定到其他目标 + // GL_COPY_READ_BUFFER + static const GLenum kBufferTarget = GL_COPY_WRITE_BUFFER; + + DataBuffer::DataBuffer() + { + glGenBuffers(1, &m_Handle); + } + + DataBuffer::~DataBuffer() + { + glDeleteBuffers(1, &m_Handle); + } + + void DataBuffer::Restore(int size, GLenum usage) + { + RestoreWithData(size, usage, 0); + } + + void DataBuffer::RestoreWithData(int size, GLenum usage, const void* data) + { + glBindBuffer(kBufferTarget, m_Handle); + glBufferData(kBufferTarget, size, data, usage); + glBindBuffer(kBufferTarget, 0); + m_Size = size; + m_Usage = usage; + } + + // glBufferSubData + // glMapBuffer + // glMapBufferRange (best one) + + void DataBuffer::Upload(int offset, int size, const void* data) + { + glBindBuffer(kBufferTarget, m_Handle); + glBufferSubData(kBufferTarget, offset, size, data); + glBindBuffer(kBufferTarget, 0); + } + + void* DataBuffer::Map(uint32 access) + { + glBindBuffer(kBufferTarget, m_Handle); + void* ptr = glMapBuffer(kBufferTarget, access); + glBindBuffer(kBufferTarget, 0); + return ptr; + } + + void* DataBuffer::MapRange(int offset, int size, uint32 access) + { + glBindBuffer(kBufferTarget, m_Handle); + void* ptr = glMapBufferRange(kBufferTarget, offset, size, access); + glBindBuffer(kBufferTarget, 0); + return ptr; + } + + void DataBuffer::FlushMapedRange(int offset, int size) + { + glBindBuffer(kBufferTarget, m_Handle); + glFlushMappedBufferRange(kBufferTarget, offset, size); + glBindBuffer(kBufferTarget, 0); + } + + void DataBuffer::UnMap() + { + glBindBuffer(kBufferTarget, m_Handle); + glUnmapBuffer(kBufferTarget); + glBindBuffer(kBufferTarget, 0); + } + + void DataBuffer::Orphan() + { + glBindBuffer(kBufferTarget, m_Handle); + glBufferData(kBufferTarget, 0, 0, GL_STREAM_DRAW); + glBindBuffer(kBufferTarget, 0); + } + + static bool IsBufferPoolCreated = false; + + BufferPool::BufferPool() + :m_LiveBuffers() + { + Assert(!IsBufferPoolCreated); + IsBufferPoolCreated = true; + } + + BufferPool::~BufferPool() + { + + } + + void BufferPool::Initialize() + { + for(int i = 0; i < kSizeClassCount; ++i) + m_LiveBuffers[i].clear(); + } + + static const float kBufferAllocateWeight = 10.0f; //! Default weight for buffer allocation from scratch. + static const float kBufferSizeWeightFactor = 1.f / 8096.f; //!< Weight factor for size difference. + static const float kBufferUsageDiffWeight = 8.f; //!< Weight factor for usage difference. + + static int ComputeBufferWeight(DataBuffer* buffer, int desiredSize, GLenum desiredUsage) + { + const int bufferSize = buffer->GetSize(); + const GLenum bufferUsage = buffer->GetUsage(); + + if(bufferSize == 0) + return kBufferAllocateWeight; + + const int sizeDiff = std::abs(bufferSize - desiredSize); + + return float(sizeDiff)*kBufferSizeWeightFactor + ((bufferUsage != desiredUsage) ? kBufferUsageDiffWeight : 0.f); + } + + DataBuffer* BufferPool::ClaimBuffer(int size, GLenum usage) + { + const float maxWeight = kBufferAllocateWeight; + const int maxCandidates = 5; // Number of potential candidates to consider actually. + + const int sizeClass = GetSizeClass(size); + int numCandidates = 0; // Number of potential candidates considered + int bestBufferNdx = -1; + float bestWeight = std::numeric_limits<float>::infinity(); + + for (int idx = 0; idx < m_LiveBuffers[sizeClass].size(); ++idx) + { + DataBuffer* buffer = m_LiveBuffers[sizeClass][idx]; + const float weight = ComputeBufferWeight(buffer, size, usage); + + if (weight < maxWeight && weight < bestWeight) + { + bestWeight = weight; + bestBufferNdx = idx; + ++numCandidates; + } + + if(numCandidates >= maxCandidates) + break; // Do not try other buffers, sorry. + } + + if (bestBufferNdx >= 0) + { + DataBuffer* selectedBuffer = m_LiveBuffers[sizeClass][bestBufferNdx]; + + if (bestBufferNdx + 1 != m_LiveBuffers[sizeClass].size()) + std::swap(m_LiveBuffers[sizeClass][bestBufferNdx], m_LiveBuffers[sizeClass].back()); + m_LiveBuffers[sizeClass].pop_back(); + + return selectedBuffer; + } + else + return new DataBuffer(); + + } + + void BufferPool::ReleaseBuffer(DataBuffer* buffer) + { + InsertToLive(buffer); + } + + void BufferPool::OnEndFrame() + { + UpdatePendingBuffersArray(); + } + + void BufferPool::UpdatePendingBuffersArray() + { + + } + + void BufferPool::InsertToLive(DataBuffer* buffer) + { + const int bufferSize = buffer->GetSize(); + const int sizeClass = GetSizeClass(bufferSize); + + m_LiveBuffers[sizeClass].push_back(buffer); + } + + uint BufferPool::GetSizeClass(uint bufferSize) + { + for (int idx = 0; idx < kSizeClassCount; ++idx) + { + if(bufferSize < GetSizeClassLimit(idx)) + return idx; + } + Assert(false); // never reach here + return 0; + } + + DataBuffer* ClaimBuffer(int size = 0, GLenum usage = GL_ARRAY_BUFFER) + { + return BufferPool::Instance()->ClaimBuffer(size, usage); + } + + void ReleaseBuffer(DataBuffer* buffer) + { + BufferPool::Instance()->ReleaseBuffer(buffer); + } + +} diff --git a/Runtime/Graphics/GpuDataBuffer.h b/Runtime/Graphics/GpuDataBuffer.h new file mode 100644 index 0000000..0d65d3d --- /dev/null +++ b/Runtime/Graphics/GpuDataBuffer.h @@ -0,0 +1,90 @@ +#ifndef GPU_DATABUFFER_H +#define GPU_DATABUFFER_H + +#include <vector> + +#include "../Utilities/Type.h" +#include "../Utilities/Singleton.h" +#include "../Utilities/UtilMacros.h" +#include "../Utilities/Assert.h" +#include "OpenGL.h" + +namespace GPU +{ + + class DataBuffer + { + public: + void Upload(int offset, int size, const void* data); + void* Map(uint32 access); + void* MapRange(int offset, int size, uint32 access); // best performance + void FlushMapedRange(int offset, int size); + + void UnMap(); + + void Orphan(); + + // claim storage of size + void Restore(int size, GLenum usage); + // claim storage of size and fill it + void RestoreWithData(int size, GLenum usage, const void* data); + + GET(int, Size, m_Size); + GET(GLenum, Usage, m_Usage); + GET(GLuint, Handle, m_Handle); + + private: + friend class BufferPool; + + DataBuffer(); + ~DataBuffer(); + + GLuint m_Handle; + int m_Size; + GLenum m_Usage; + }; + + // recycle data buffer + class BufferPool : public Singleton<BufferPool> + { + public: + BufferPool(); + ~BufferPool(); + + void Initialize(); + + DataBuffer* ClaimBuffer(int size, GLenum usage); + void ReleaseBuffer(DataBuffer* buffer); + + void OnEndFrame(); + + private: + + inline int GetSizeClassLimit(int classNdx); + + void UpdatePendingBuffersArray(); + void InsertToLive(DataBuffer* buffer); + uint GetSizeClass(uint bufferSize); + + enum { + kSizeClassBaseLog2 = 10, + kSizeClassStepLog2 = 1, + kSizeClassCount = 7 + }; + + std::vector<DataBuffer*> m_LiveBuffers[kSizeClassCount]; + + }; + + inline int BufferPool::GetSizeClassLimit(int classNdx) + { + // (0, 2^10] 2^11 2^12 2^13 2^14 2^15 INT_MAX + return classNdx + 1 < kSizeClassCount ? (1 << (classNdx*kSizeClassStepLog2 + kSizeClassBaseLog2)) : INT_MAX; + } + + DataBuffer* ClaimBuffer(int size = 0, GLenum usage = GL_ARRAY_BUFFER); + void ReleaseBuffer(DataBuffer* buffer); + +} + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/ImageData.cpp b/Runtime/Graphics/ImageData.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/ImageData.cpp diff --git a/Runtime/Graphics/ImageData.h b/Runtime/Graphics/ImageData.h new file mode 100644 index 0000000..cd56e83 --- /dev/null +++ b/Runtime/Graphics/ImageData.h @@ -0,0 +1,43 @@ +#ifndef IMAGE_DATA_H +#define IMAGE_DATA_H + +#include <vector> + +class ImageData +{ +public: + enum ImageFormat + { + ImageFormat_Rgba_Int, + ImageFormat_Rgba_Float, + }; + +private: + void* m_Data; + +}; + +enum ImageDataAsyncError +{ + ImageDataAsyncError_NoFile = 1, + ImageDataAsyncError_ParseFailed = 2, + ImageDataAsyncError_InvalidFormat = 3, +}; + +struct ImageDataRequest +{ + bool isDone, hasError; + int error; + int progress, all; + ImageData* result; + std::vector<ImageData*> results; +}; + +namespace ImageDataUtil +{ + ImageData* Load(const char* path); + ImageDataRequest* LoadAsync(const char* path); + ImageDataRequest* LoadAsync(std::vector<const char*> paths); +} + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/OpenGL.cpp b/Runtime/Graphics/OpenGL.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/OpenGL.cpp diff --git a/Runtime/Graphics/OpenGL.h b/Runtime/Graphics/OpenGL.h new file mode 100644 index 0000000..413b70b --- /dev/null +++ b/Runtime/Graphics/OpenGL.h @@ -0,0 +1,6 @@ +#ifndef OPENGL_H +#define OPENGL_H + +#include "glad/glad.h" + +#endif diff --git a/Runtime/Graphics/Point.cpp b/Runtime/Graphics/Point.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Point.cpp diff --git a/Runtime/Graphics/Point.h b/Runtime/Graphics/Point.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Point.h diff --git a/Runtime/Graphics/PolyLine.cpp b/Runtime/Graphics/PolyLine.cpp new file mode 100644 index 0000000..794819a --- /dev/null +++ b/Runtime/Graphics/PolyLine.cpp @@ -0,0 +1,11 @@ +#include "PolyLine.h" +#include "../Math/Vector3.h" +#include "Color.h" + +struct PolyLineVBOLayout +{ + Vector3 position; + ColorRGBA32 color; +}; + + diff --git a/Runtime/Graphics/PolyLine.h b/Runtime/Graphics/PolyLine.h new file mode 100644 index 0000000..1850e47 --- /dev/null +++ b/Runtime/Graphics/PolyLine.h @@ -0,0 +1,18 @@ +#ifndef POLY_LINE_H +#define POLY_LINE_H + +#include "../Math/Vector3.h" + +class PolyLine +{ +public: + PolyLine(); + ~PolyLine(); + + void Draw(); + +private: + +}; + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/Quad.cpp b/Runtime/Graphics/Quad.cpp new file mode 100644 index 0000000..cbe8b74 --- /dev/null +++ b/Runtime/Graphics/Quad.cpp @@ -0,0 +1,52 @@ +#include "../Math/Vector2.h" +#include "../Math/Vector3.h" +#include "Quad.h" +#include "Device.h" + +struct QuadVBOLayout +{ + Vector3 position; + Vector2 uv; +}; + +void Quad::Draw() +{ + const int nVerts = 4; + const int nIndices = 6; + + float pos[] = { + m_Left, m_Bottom, 0, // left-bottom + m_Right, m_Bottom, 0, // right-bottom + m_Right, m_Top, 0, // right-top + m_Left, m_Top, 0, // top-left + }; + float uv[] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1, + }; + int indices[] = { + 0, 1, 3, // right-top + 1, 2, 3, // left-bottom + }; + + uint8* vb; + uint16* ib; + + uint attrs = Mask(VertexAttr_Position) | Mask(VertexAttr_TexCoord0); + g_SharedVBO.GetChunk(attrs, 4, 6, RenderMode_Triangle, (void**)&vb, (void**)&ib); + + QuadVBOLayout* dst = (QuadVBOLayout*)vb; + for (int i = 0; i < nVerts; ++i) + { + dst[i].position.Set(pos[3 * i], pos[3 * i + 1], pos[3 * i + 2]); + dst[i].uv.Set(uv[2 * i], uv[2 * i + 1]); + } + + for (int i = 0; i < nIndices; ++i) + ib[i] = indices[i]; + + g_SharedVBO.ReleaseChunk(4, 6); + g_SharedVBO.DrawChunk(); +}
\ No newline at end of file diff --git a/Runtime/Graphics/Quad.h b/Runtime/Graphics/Quad.h new file mode 100644 index 0000000..0e38ec4 --- /dev/null +++ b/Runtime/Graphics/Quad.h @@ -0,0 +1,25 @@ +#ifndef QUAD_H +#define QUAD_H + +#include "../Utilities/UtilMacros.h" + +class Quad +{ +public: + Quad(float l, float r, float t, float b); + + void Set(float l, float r, float t, float b); + + GET_SET(float, Left, m_Left); + GET_SET(float, Right, m_Right); + GET_SET(float, Top, m_Top); + GET_SET(float, Bottom, m_Bottom); + + void Draw(); + +private: + float m_Left, m_Right, m_Top, m_Bottom; + +}; + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/RenderTexture.cpp b/Runtime/Graphics/RenderTexture.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/RenderTexture.cpp diff --git a/Runtime/Graphics/RenderTexture.h b/Runtime/Graphics/RenderTexture.h new file mode 100644 index 0000000..74c5602 --- /dev/null +++ b/Runtime/Graphics/RenderTexture.h @@ -0,0 +1,16 @@ +#ifndef RENDER_TEXTURE_H +#define RENDER_TEXTURE_H + +#include "Texture.h" + +// 离屏渲染 +class RenderTexture : public Texture +{ +public: + RenderTexture(TextureFormat format); + +}; + +RenderTexture* CreateRenderTexture(int width, int height, TextureFormat format); + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/Scripting/wrap_Device.cpp b/Runtime/Graphics/Scripting/wrap_Device.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Scripting/wrap_Device.cpp diff --git a/Runtime/Graphics/Scripting/wrap_GL.cpp b/Runtime/Graphics/Scripting/wrap_GL.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Scripting/wrap_GL.cpp diff --git a/Runtime/Graphics/Scripting/wrap_RenderTexture.cpp b/Runtime/Graphics/Scripting/wrap_RenderTexture.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Scripting/wrap_RenderTexture.cpp diff --git a/Runtime/Graphics/Texture.cpp b/Runtime/Graphics/Texture.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Graphics/Texture.cpp diff --git a/Runtime/Graphics/Texture.h b/Runtime/Graphics/Texture.h new file mode 100644 index 0000000..ce05ff7 --- /dev/null +++ b/Runtime/Graphics/Texture.h @@ -0,0 +1,59 @@ +#ifndef TEXTURE_H +#define TEXTURE_H + +#include "../Utilities/UtilMacros.h" +#include "OpenGL.h" +#include "ImageData.h" + +enum TextureFormat +{ + TextureFormat_DepthComponent, + TextureFormat_Red, + TextureFormat_Green, + TextureFormat_Blue, + TextureFormat_Alpha, + TextureFormat_Rgb, + TextureFormat_Rgba, +}; + +enum TextureWrap +{ + TextureWrap_Clamp, + TextureWrap_Repeat, +}; + +enum TextureFilter +{ + TextureFilter_Nearest, + TextureFilter_Bilinear, + TextureFilter_Trilinear, +}; + +class Texture +{ +public: + Texture(ImageData* imgData, TextureFormat format); + Texture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + Texture(); + ~Texture(); + + GET(int, Width, m_Width); + GET(int, Height, m_Height); + + GET(TextureFilter, Filter, m_Filter); + GET(TextureWrap, Wrap, m_Wrap); + + GET(GLint, Handle, m_Handle); + +protected: + GLint m_Handle; + int m_Width, m_Height; + TextureFilter m_Filter; + TextureWrap m_Wrap; + +}; + +Texture* CreateTexture(ImageData* imgData, TextureFormat format); +Texture* CreateTexture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + +#endif
\ No newline at end of file diff --git a/Runtime/Graphics/VertexBuffer.cpp b/Runtime/Graphics/VertexBuffer.cpp new file mode 100644 index 0000000..c9f5164 --- /dev/null +++ b/Runtime/Graphics/VertexBuffer.cpp @@ -0,0 +1,322 @@ +#include "VertexBuffer.h" +#include "../Profiler/FrameStats.h" + +void SetupDefaultVertexArray(const VertexArrayInfo& info); +void InvalidateVertexInputCache(); + +// LUTs of vertex attributes +static const int kVertexAttrSize[VertexAttr_Count] = { + 3 * sizeof(float), // position + 3 * sizeof(float), // normal + 4 * sizeof(float), // tangent + 1 * sizeof(uint32), // color + 2 * sizeof(float), // uv0 + 2 * sizeof(float), // uv1 +}; + +static const int kVertexAttrDimension[VertexAttr_Count] = { + 3, // position + 3, // normal + 4, // tangent + 1, // color + 2, // uv0 + 2 // uv1 +}; + +enum VertexAttrFormat +{ + VertexAttrFormat_Float = 0, // position \ normal \ tangent \ uv0 \ uv1 + VertexAttrFormat_Float16 = 1, + VertexAttrFormat_Color = 2, // color + VertexAttrFormat_Byte = 3, + + VertexAttrFormat_Count = 4 +}; + +// map VertexAttrFormat to OpenGL type +static GLenum kGLVertexAttrFormat [VertexAttr_Count] = { + GL_FLOAT, // VertexAttrFormat_Float + GL_HALF_FLOAT, // VertexAttrFormat_Float16 + GL_UNSIGNED_BYTE, // VertexAttrFormat_Color + GL_BYTE // VertexAttrFormat_Byte +}; + +static bool IsGLVertexAttrNeedNormalized(uint attr, uint format) +{ + if(attr == VertexAttr_Position) + return false; + else // color and byte need to be normalized + return format != VertexAttrFormat_Float && format != VertexAttrFormat_Float16; +} + +static uint GetDefaultShaderChannelFormat(uint attr) +{ +// besides color, other attributes are all composite of float values + return attr == VertexAttr_Color ? VertexAttrFormat_Color : VertexAttrFormat_Float; +} + +static uint32 GetDefaultVertexAttrSize(/*VertexAttr*/ int attr) +{ + return kVertexAttrSize[attr]; +} + +static uint GetDefaultVertexAttrDimension(uint attr) +{ + return kVertexAttrDimension[attr]; +} + +static uint GetDefaultShaderChannelDimension(uint attr) +{ + return attr == VertexAttr_Color ? 4 : GetDefaultVertexAttrDimension(attr); +} + +// index is stored in unsgined short (GL_UNSIGNED_SHORT) +static const int kIndexSize = sizeof(uint16); +static GLenum kGLIndexFormat = GL_UNSIGNED_SHORT; + +// Get size used for vertexAttrMask +static uint32 GetDynamicChunkStride(uint32 vertexAttrMask) +{ + uint32 stride = 0; + for (int i = 0; i < vertexAttrMask; ++i) + { + if (vertexAttrMask & Mask(i)) + stride += GetDefaultVertexAttrSize(i); + } + return stride; +} + +VertexBuffer::VertexBuffer(VertexBufferType type) +{ +} + +VertexBuffer::~VertexBuffer() +{ +} + +SharedVertexBuffer::SharedVertexBuffer() +{ +} + +SharedVertexBuffer::~SharedVertexBuffer() +{ +} + +//GetChunk +//-> ReleaseChunk +//-> DrawChunk + +void SharedVertexBuffer::GetChunk(uint attrsMask, int maxVerts, int maxIndices, RenderMode mode, void **out_vb, void **out_ib) +{ + Assert(out_vb && out_ib); + + uint stride = GetDynamicChunkStride(attrsMask); // data size of single vertex + GLenum usage = GL_STREAM_DRAW; + uint vbufferSize = stride * maxVerts; + uint ibufferSize = kIndexSize * maxIndices; + + const bool mapVertexBuffer = vbufferSize >= DataBufferThreshold; + const bool mapIndexBuffer = ibufferSize >= DataBufferThreshold; + + GPU::DataBuffer* vertexBuffer = mapVertexBuffer ? GPU::ClaimBuffer(vbufferSize, usage) : 0; + GPU::DataBuffer* indexBuffer = mapIndexBuffer ? GPU::ClaimBuffer(ibufferSize, usage) : 0; + + if(vertexBuffer && vertexBuffer->GetSize() < vbufferSize) + vertexBuffer->Restore(vbufferSize, usage); + + if(indexBuffer && indexBuffer->GetSize() < ibufferSize) + indexBuffer->Restore(ibufferSize, usage); + + if(!mapVertexBuffer && m_CurVBData.size() < vbufferSize) + m_CurVBData.resize(vbufferSize); + + if(!mapIndexBuffer && m_CurIBData.size() < ibufferSize) + m_CurIBData.resize(ibufferSize); + + const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + + if (vertexBuffer) + *out_vb = vertexBuffer->MapRange(0, vbufferSize, access); + else + *out_vb = &m_CurVBData[0]; + + if(indexBuffer) + *out_ib = indexBuffer->MapRange(0, ibufferSize, access); + else + *out_ib = &m_CurIBData[0]; + + m_CurVB = vertexBuffer; + m_CurIB = indexBuffer; + m_CurRenderMode = mode; + m_CurAttrMask = attrsMask; + m_CurStride = stride; +} + +void SharedVertexBuffer::ReleaseChunk(int actualVerts, int actualIndices) +{ + int actualVBufferSize = m_CurStride * actualVerts; + int actualIBufferSize = kIndexSize * actualIndices; + + const GLenum usage = GL_STREAM_DRAW; + + if (m_CurVB) + { + m_CurVB->FlushMapedRange(0, actualVBufferSize); + m_CurVB->UnMap(); + } + else if(actualVBufferSize >= DataBufferThreshold) + { + m_CurVB = GPU::ClaimBuffer(actualVBufferSize, usage); + m_CurVB->RestoreWithData(actualVBufferSize, usage, &m_CurVBData[0]); + } + + if (m_CurIB) + { + m_CurIB->FlushMapedRange(0, actualIBufferSize); + m_CurIB->UnMap(); + } + else if (actualIBufferSize >= DataBufferThreshold) + { + m_CurIB = GPU::ClaimBuffer(0, usage); + m_CurIB->RestoreWithData(0, usage, &m_CurIBData[0]); + } + + m_CurVertexCount = actualVerts; + m_CurIndexCount = actualIndices; +} + +void SharedVertexBuffer::DrawChunk() +{ + VertexArrayInfo vertexArray; + FillVertexArrayInfo(vertexArray); + + // bind vertex attributes data + SetupDefaultVertexArray(vertexArray); + + const void* indexPtr = m_CurIB ? 0 : (m_CurIBData.empty() ? 0 : &m_CurIBData[0]); + + if (m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CurIB->GetHandle()); + + switch (m_CurRenderMode) + { + case RenderMode_Triangle: + glDrawElements(GL_TRIANGLES, m_CurIndexCount, kGLIndexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + g_FrameStats.AddTrianglesCount(m_CurIndexCount / 3); + break; + case RenderMode_Line: + glDrawElements(GL_LINE, m_CurIndexCount, kGLIndexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + case RenderMode_Point: + glDrawElements(GL_POINT, m_CurIndexCount, kGLIndexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + } + + if(m_CurIB) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // End draw + Clean(); +} + +void SharedVertexBuffer::FillVertexArrayInfo(VertexArrayInfo& dst) +{ + const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0]; + const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0; + + int attrOffsets[VertexAttr_Count] = {0}; + + { + uint32 curOffset = 0; + for (uint idx = 0; idx < VertexAttr_Count; ++idx) + { + if (m_CurAttrMask & Mask(idx)) + { + attrOffsets[idx] = curOffset; + curOffset += GetDefaultVertexAttrSize(idx); + } + } + } + + for (uint32 attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx) + { + if (m_CurAttrMask & Mask(attrIdx)) + { + dst.buffers[attrIdx] = buffer; + + dst.attributes[attrIdx].pointer = basepointer + attrOffsets[attrIdx]; + dst.attributes[attrIdx].componentType = GetDefaultShaderChannelFormat(attrIdx); + dst.attributes[attrIdx].componentNum = GetDefaultShaderChannelDimension(attrIdx); + dst.attributes[attrIdx].stride = m_CurStride; + + dst.enableMask |= Mask(attrIdx); + } + } +} + +void SharedVertexBuffer::Clean() +{ + if (m_CurVB) + { + GPU::ReleaseBuffer(m_CurVB); + m_CurVB = 0; + } + + if (m_CurIB) + { + GPU::ReleaseBuffer(m_CurIB); + m_CurIB = 0; + } + + m_CurRenderMode = (RenderMode)0; + m_CurAttrMask = 0; + m_CurStride = 0; + m_CurVertexCount = 0; + m_CurIndexCount = 0; + + m_CurVBData.clear(); + m_CurIBData.clear(); +} + +static uint32 sEnabledArrays = 0; + +void SetupDefaultVertexArray(const VertexArrayInfo& info) +{ + GLuint curBoundBuffer = 0; + + for (int attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx) + { + if (info.enableMask & Mask(attrIdx)) + { + if (!sEnabledArrays & Mask(attrIdx)) + glEnableVertexAttribArray(attrIdx); + const GLuint buffer = info.buffers[attrIdx]; + const int numCompo = info.attributes[attrIdx].componentNum; + const GLenum compoType = kGLVertexAttrFormat[info.attributes[attrIdx].componentType]; + const bool normalized = IsGLVertexAttrNeedNormalized(attrIdx, compoType); + const uint stride = info.attributes[attrIdx].stride; + const void* pointer = info.attributes[attrIdx].pointer; + + if (curBoundBuffer != buffer) + { + glBindBuffer(GL_ARRAY_BUFFER, buffer); + curBoundBuffer = buffer; + } + + glVertexAttribPointer(attrIdx, numCompo, compoType, normalized ? GL_TRUE : GL_FALSE, stride, pointer); + } + else if(sEnabledArrays & Mask(attrIdx)) + glDisableVertexAttribArray(attrIdx); + } + sEnabledArrays = info.enableMask; +} + +void InvalidateVertexInputCache() +{ + sEnabledArrays = 0; + for(int attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx) + glDisableVertexAttribArray(attrIdx); +}
\ No newline at end of file diff --git a/Runtime/Graphics/VertexBuffer.h b/Runtime/Graphics/VertexBuffer.h new file mode 100644 index 0000000..33c0783 --- /dev/null +++ b/Runtime/Graphics/VertexBuffer.h @@ -0,0 +1,103 @@ +#ifndef VBO_H +#define VBO_H + +#include <vector> + +#include "../Utilities/UtilMacros.h" +#include "../Shaders/ShaderChannel.h" + +#include "OpenGL.h" +#include "GpuDataBuffer.h" + +enum VertexAttr +{ + VertexAttr_Position = 0, + VertexAttr_Normal = 1, + VertexAttr_Tangent = 2, + VertexAttr_Color = 3, + VertexAttr_TexCoord0 = 4, + VertexAttr_TexCoord1 = 5, + + VertexAttr_Count = 6 +}; + +enum RenderMode +{ + RenderMode_Triangle = 1, + RenderMode_Line = 2, + RenderMode_Point = 3, +}; + +struct VertexInputInfo +{ + const void* pointer; // either cpu memory or gpu memory + uint componentType; // one of VertexAttrFormat + uint componentNum; + uint16 stride; +}; + +// gpu side vertex attributes array +struct VertexArrayInfo +{ + uint32 enableMask; + GLuint buffers[VertexAttr_Count]; + VertexInputInfo attributes[VertexAttr_Count]; +}; + +class VertexBuffer +{ +public: + enum VertexBufferType + { + VertexBufferType_Static, // device + VertexBufferType_Stream, // pinned (best performance) + VertexBufferType_Dynamic,// device + }; + + VertexBuffer(VertexBufferType type); + ~VertexBuffer(); + + void Draw(); + +private: + + VertexBufferType m_Type; + GPU::DataBuffer *m_VB, *m_IB;// vertex buffer and index buffer + +}; + +class SharedVertexBuffer +{ +public: + void GetChunk(uint attrs, int maxVerts, int maxIndices, RenderMode mode, void **out_vb, void **out_ib); + void ReleaseChunk(int actualVerts, int actualIndices); + + void DrawChunk(); + +private: + + void FillVertexArrayInfo(VertexArrayInfo& dst); + + void Clean(); + + // if vertex databuffer size beyond this value, use pinned memory mapping, instead of glBufferData. + enum { DataBufferThreshold = 1024 }; + + // shared vbo and ibo + GPU::DataBuffer *m_CurVB, *m_CurIB; + + // restore vbo and ibo data if not using pinned memory mapping + std::vector<byte> m_CurVBData; + std::vector<uint16> m_CurIBData; + + RenderMode m_CurRenderMode; + + uint m_CurAttrMask; + uint m_CurStride; + + uint m_CurVertexCount; + uint m_CurIndexCount; + +}; + +#endif
\ No newline at end of file |