summaryrefslogtreecommitdiff
path: root/Runtime/Graphics
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Graphics')
-rw-r--r--Runtime/Graphics/Color.h22
-rw-r--r--Runtime/Graphics/Device.cpp78
-rw-r--r--Runtime/Graphics/Device.h82
-rw-r--r--Runtime/Graphics/DeviceDefine.h69
-rw-r--r--Runtime/Graphics/FrameBuffer.cpp12
-rw-r--r--Runtime/Graphics/FrameBuffer.h35
-rw-r--r--Runtime/Graphics/GlyphAtlas.cpp0
-rw-r--r--Runtime/Graphics/GlyphAtlas.h6
-rw-r--r--Runtime/Graphics/GpuDataBuffer.cpp206
-rw-r--r--Runtime/Graphics/GpuDataBuffer.h90
-rw-r--r--Runtime/Graphics/ImageData.cpp0
-rw-r--r--Runtime/Graphics/ImageData.h43
-rw-r--r--Runtime/Graphics/OpenGL.cpp0
-rw-r--r--Runtime/Graphics/OpenGL.h6
-rw-r--r--Runtime/Graphics/Point.cpp0
-rw-r--r--Runtime/Graphics/Point.h0
-rw-r--r--Runtime/Graphics/PolyLine.cpp11
-rw-r--r--Runtime/Graphics/PolyLine.h18
-rw-r--r--Runtime/Graphics/Quad.cpp52
-rw-r--r--Runtime/Graphics/Quad.h25
-rw-r--r--Runtime/Graphics/RenderTexture.cpp0
-rw-r--r--Runtime/Graphics/RenderTexture.h16
-rw-r--r--Runtime/Graphics/Scripting/wrap_Device.cpp0
-rw-r--r--Runtime/Graphics/Scripting/wrap_GL.cpp0
-rw-r--r--Runtime/Graphics/Scripting/wrap_RenderTexture.cpp0
-rw-r--r--Runtime/Graphics/Texture.cpp0
-rw-r--r--Runtime/Graphics/Texture.h59
-rw-r--r--Runtime/Graphics/VertexBuffer.cpp322
-rw-r--r--Runtime/Graphics/VertexBuffer.h103
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