From af7bdaa10ee71a319dc55c3c7556fa43a95c9dc9 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 2 Apr 2019 21:45:33 +0800 Subject: *misc --- .../modules/asura-core/graphics/binding/_image.cpp | 26 +-- source/modules/asura-core/graphics/canvas.cpp | 34 +++- source/modules/asura-core/graphics/canvas.h | 3 +- source/modules/asura-core/graphics/gl.cpp | 18 +- source/modules/asura-core/graphics/gl.h | 40 ++-- source/modules/asura-core/graphics/image.cpp | 54 +++++- source/modules/asura-core/graphics/image.h | 17 +- .../modules/asura-core/graphics/matrix_stack.cpp | 61 +++++++ source/modules/asura-core/graphics/matrix_stack.h | 82 +++++++++ source/modules/asura-core/graphics/shader.cpp | 136 ++++++++++++-- source/modules/asura-core/graphics/shader.h | 12 +- source/modules/asura-core/graphics/shader_source.h | 11 +- source/modules/asura-core/graphics/texture.cpp | 14 +- .../modules/asura-utils/exceptions/exception.cpp | 9 +- source/modules/asura-utils/exceptions/exception.h | 14 -- source/modules/asura-utils/io/binding/_file.cpp | 2 +- .../asura-utils/io/binding/_file_system.cpp | 4 +- source/modules/asura-utils/io/file.cpp | 8 +- source/modules/asura-utils/io/file.h | 12 +- source/modules/asura-utils/io/file_data.h | 2 +- source/modules/asura-utils/io/file_system.cpp | 8 +- source/modules/asura-utils/io/file_system.h | 10 +- source/modules/asura-utils/io/io_task.h | 2 +- source/modules/asura-utils/io/renewable.h | 8 +- source/modules/asura-utils/math/matrix44.cpp | 203 +++++++++++++++++++++ source/modules/asura-utils/math/matrix44.h | 152 ++++++++++++++- source/modules/asura-utils/math/rect.hpp | 2 +- source/modules/asura-utils/type.h | 13 +- 28 files changed, 811 insertions(+), 146 deletions(-) create mode 100644 source/modules/asura-core/graphics/matrix_stack.cpp create mode 100644 source/modules/asura-core/graphics/matrix_stack.h (limited to 'source/modules') diff --git a/source/modules/asura-core/graphics/binding/_image.cpp b/source/modules/asura-core/graphics/binding/_image.cpp index 407ada7..913bf5c 100644 --- a/source/modules/asura-core/graphics/binding/_image.cpp +++ b/source/modules/asura-core/graphics/binding/_image.cpp @@ -13,11 +13,10 @@ namespace AsuraEngine LUAX_REGISTER_METHODS(state, { "New", _New }, - { "Refresh", _Refresh }, + { "Renew", _Renew }, { "GetWidth", _GetWidth }, { "GetHeight", _GetHeight }, { "GetSize", _GetSize }, - { "GetPixel", _GetPixel }, { "Render", _Render } ); } @@ -35,15 +34,12 @@ namespace AsuraEngine return 1; } - // successed = image:Refresh(imgData) - LUAX_IMPL_METHOD(Image, _Refresh) + // successed = image:Renew(imgData) + LUAX_IMPL_METHOD(Image, _Renew) { LUAX_PREPARE(L, Image); ImageData* imgData = state.CheckUserdata(2); - bool successed = self->Refresh(imgData); - if (successed) - self->SetLuaxMemberRef(state, self->mImageDataRef, 2); - state.Push(successed); + state.Push(self->Renew(imgData)); return 1; } @@ -74,20 +70,6 @@ namespace AsuraEngine return 2; } - // color32 = image:GetPixel(x, y) - LUAX_IMPL_METHOD(Image, _GetPixel) - { - LUAX_PREPARE(L, Image); - - uint x, y; - x = state.CheckValue(2); - y = state.CheckValue(3); - Color32* c32 = new Color32(); - c32->Set(self->GetPixel(x, y)); - c32->PushLuaxUserdata(state); - return 1; - } - // image:Render() LUAX_IMPL_METHOD(Image, _Render) { diff --git a/source/modules/asura-core/graphics/canvas.cpp b/source/modules/asura-core/graphics/canvas.cpp index 89be45c..0543461 100644 --- a/source/modules/asura-core/graphics/canvas.cpp +++ b/source/modules/asura-core/graphics/canvas.cpp @@ -8,21 +8,41 @@ namespace AsuraEngine Canvas::Canvas() : mWidth(0) , mHeight(0) + , mFBO(0) { - glGenFramebuffers(1, &mFBO); - GLint current_fbo; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTex, 0); - glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); + // Fix: 等设置大小初始化时再申请framebuffer资源。 + //glGenFramebuffers(1, &mFBO); + //GLint current_fbo; + //glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo); + //glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTex, 0); + //glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); } void Canvas::SetSize(uint w, uint h) { + if (mFBO == 0) + { + glGenFramebuffers(1, &mFBO); + if (mFBO == 0) + throw Exception("OpenGL glGenFramebuffers cannot generate frame buffer object."); + // 申请纹理 + if (mTex == 0) + { + glGenTextures(1, &mTex); + if (mTex == 0) + throw Exception("OpenGL glGenTextures cannot generate texture."); + } + GLint current_fbo; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTex, 0); + glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); + } GLint current_tex; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex); glBindTexture(GL_TEXTURE_2D, mTex); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, current_tex); } diff --git a/source/modules/asura-core/graphics/canvas.h b/source/modules/asura-core/graphics/canvas.h index f0b71e2..6af81d7 100644 --- a/source/modules/asura-core/graphics/canvas.h +++ b/source/modules/asura-core/graphics/canvas.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "gl.h" #include "texture.h" @@ -32,7 +33,7 @@ namespace AsuraEngine /// /// 设置render texture的大小 /// - void SetSize(uint w, uint h); + void SetSize(uint w, uint h) asura_throw(Exception); void Clear(const Color& col = Color::Black) override; diff --git a/source/modules/asura-core/graphics/gl.cpp b/source/modules/asura-core/graphics/gl.cpp index 9ffe010..e199a41 100644 --- a/source/modules/asura-core/graphics/gl.cpp +++ b/source/modules/asura-core/graphics/gl.cpp @@ -1,7 +1,9 @@ #include #include "../core_config.h" + #include "gl.h" +#include "shader.h" using namespace AEMath; @@ -10,15 +12,16 @@ namespace AsuraEngine namespace Graphics { - bool OpenGL::instantiated = false; + static bool _instantiated = false; // 单例 OpenGL gl; OpenGL::OpenGL() { - ASSERT(!instantiated); - instantiated = true; + // 不要创建第二个实例 + ASSERT(!_instantiated); + _instantiated = true; } OpenGL::~OpenGL() @@ -38,7 +41,16 @@ namespace AsuraEngine return state.viewport; } + void OpenGL::UseShader(Shader* shader) + { + glUseProgram(shader->GetGLProgramHandle()); + state.shader = shader; + } + void OpenGL::UnuseShader() + { + state.shader = nullptr; + } } } \ No newline at end of file diff --git a/source/modules/asura-core/graphics/gl.h b/source/modules/asura-core/graphics/gl.h index 4d21a5a..9ca1f44 100644 --- a/source/modules/asura-core/graphics/gl.h +++ b/source/modules/asura-core/graphics/gl.h @@ -1,21 +1,28 @@ #ifndef __ASURA_ENGINE_OPENGL_H__ #define __ASURA_ENGINE_OPENGL_H__ -#include +#include #include +#include +#include + +#include "matrix_stack.h" + namespace AsuraEngine { namespace Graphics { class Profiler; + class Shader; /// - /// 用来做一些opengl状态的追踪。在编辑器多窗口环境下,一个窗口对应一个hwnd,一个hdc,以及 - /// 数个opengl context,如果使用wglMakeCurrent(hdc, glc)指定当前线程耳朵渲染窗口hdc和 - /// opengl上下文glc,gl中记录的就是任意一个线程的任意一个窗口的任意一个opengl上下文的状态, + /// OpenGL上下文,用来做一些opengl状态的追踪。在编辑器多窗口环境下,一个窗口对应一个hwnd, + /// 一个hdc,以及数个opengl context,如果使用wglMakeCurrent(hdc, glc)指定当前线程耳朵 + /// 渲染窗口hdc和opengl上下文glc,gl中记录的就是任意一个线程的任意一个窗口的任意一个OpenGL + /// 上下文的状态, /// class OpenGL { @@ -26,23 +33,28 @@ namespace AsuraEngine void SetViewport(const AEMath::Recti viewport); AEMath::Recti GetViewport(); - private: - - friend class Profiler; + void UseShader(Shader* shader); + void UnuseShader(); - /// - /// 控制opengl单例。 /// - static bool instantiated; - - /// - /// 记录opengl状态。 + /// OpenGL3.0以后由用户管理矩阵变换、视口、shader等参数,这里保存一些OpenGL状态。注意 + /// 似乎全进程的,也就是说,Asura不支持多线程渲染。OpenGL上下文的创建使得一个上下 + /// 文绑定在一个HDC\窗口上,由于窗口是在特定线程创建的,所以OpenGL上下文也绑定了一个 + /// 特定的线程。同一个线程的不同HDC\窗口可以共享同一个OpenGL上下文。共享上下文是为了 + /// 共享上下文中创建的textuer\shader等handle。 /// struct { - AEMath::Recti viewport; + Shader* shader; ///< 当前使用的shader + AEMath::Recti viewport; ///< 当前的视区,在切换HDC或者本窗口大小改变或者部分刷新时变动 + MatrixStack projectionMatrix; ///< 投影矩阵 + MatrixStack modelViewMatrix; ///< 变换矩阵 } state; + private: + + friend class Profiler; + }; /// diff --git a/source/modules/asura-core/graphics/image.cpp b/source/modules/asura-core/graphics/image.cpp index 2b274c2..530ea97 100644 --- a/source/modules/asura-core/graphics/image.cpp +++ b/source/modules/asura-core/graphics/image.cpp @@ -1,3 +1,5 @@ +#include + #include "../core_config.h" #include "image.h" @@ -18,12 +20,19 @@ namespace AsuraEngine { } - bool Image::Refresh(DecodedData* data) + bool Image::Renew(DecodedData* data) { - ASSERT(data); - + if (!data) return false; ImageData* imgData = static_cast(data); - ASSERT(imgData); + if (!imgData) return false; + + // 如果没有纹理资源,申请一个 + if (mTex == 0) + { + glGenTextures(1, &mTex); + if (mTex == 0) + throw Exception("OpenGL glGenTextures failed."); + } glBindTexture(GL_TEXTURE_2D, mTex); imgData->Lock(); @@ -40,8 +49,43 @@ namespace AsuraEngine , tf.type , imgData->pixels ); - mImageData = imgData; + mWidth = imgData->width; + mHeight = imgData->height; + imgData->Unlock(); + GLenum err = glGetError(); + if (err != GL_NO_ERROR) + throw Exception("OpenGL glTexImage2D cause error, error code=%d", err); + glBindTexture(GL_TEXTURE_2D, 0); + + return true; + } + + bool Image::Renew(AEIO::DecodedData* data, const AEMath::Vector2i& pos) + { + if (!data) return false; + ImageData* imgData = static_cast(data); + if (!imgData) return false; + + glBindTexture(GL_TEXTURE_2D, mTex); + imgData->Lock(); + int width = imgData->width; + int height = imgData->height; + TextureFormat tf = ConvertColorFormat(imgData->format); + glTexSubImage2D( + GL_TEXTURE_2D + , 0 + , pos.x + , pos.y + , imgData->width + , imgData->height + , tf.externalformat + , tf.type + , imgData->pixels + ); imgData->Unlock(); + GLenum err = glGetError(); + if (err != GL_NO_ERROR) + throw Exception("OpenGL glTexSubImage2D cause error, error code=%d", err); glBindTexture(GL_TEXTURE_2D, 0); return true; diff --git a/source/modules/asura-core/graphics/image.h b/source/modules/asura-core/graphics/image.h index 7795c08..d60bd24 100644 --- a/source/modules/asura-core/graphics/image.h +++ b/source/modules/asura-core/graphics/image.h @@ -44,12 +44,11 @@ namespace AsuraEngine /// 将解析后的图像数据提交到GPU,更新像素信息。用来重新构建image,使用glTexImage2D重 /// 新提交image的像素数据。 /// - bool Refresh(AEIO::DecodedData* decodeData) override; - bool Refresh(AEIO::DecodedData* decodeData, const AEMath::Recti& rect); + bool Renew(AEIO::DecodedData* decodeData) override; + bool Renew(AEIO::DecodedData* decodeData, const AEMath::Vector2i& pos); - uint GetWidth(); - uint GetHeight(); - Color32 GetPixel(uint x, uint y); + uint GetWidth(); + uint GetHeight(); void Render(const RenderTarget* rt, const RenderState& state) override {}; void Render(const RenderTarget* rt, const Math::Rectf& quad, const RenderState& state) override {}; @@ -59,7 +58,7 @@ namespace AsuraEngine //----------------------------------------------------------------------------// LUAX_DECL_METHOD(_New); - LUAX_DECL_METHOD(_Refresh); + LUAX_DECL_METHOD(_Renew); LUAX_DECL_METHOD(_GetWidth); LUAX_DECL_METHOD(_GetHeight); LUAX_DECL_METHOD(_GetSize); @@ -68,11 +67,7 @@ namespace AsuraEngine //----------------------------------------------------------------------------// - /// - /// 一张图片保存一个像素数据的引用。 - /// - ImageData* mImageData; - Luax::LuaxMemberRef mImageDataRef; + uint32 mWidth, mHeight; }; diff --git a/source/modules/asura-core/graphics/matrix_stack.cpp b/source/modules/asura-core/graphics/matrix_stack.cpp new file mode 100644 index 0000000..72ffb7d --- /dev/null +++ b/source/modules/asura-core/graphics/matrix_stack.cpp @@ -0,0 +1,61 @@ +#include "matrix_stack.h" + +namespace AsuraEngine +{ + namespace Graphics + { + + MatrixStack::MatrixStack() + : top(0) + { + // 栈的最下面初始就是栈顶,并用此保证栈永远非空(即可以取值) + mStack[top].SetIdentity(); + } + + MatrixStack::~MatrixStack() + { + } + + void MatrixStack::LoadIdentity() + { + mStack[top].SetIdentity(); + } + + bool MatrixStack::Push() + { + if (top == ASURA_MAX_MATRIX_STACK_DEPTH - 1) + return false; + ++top; + mStack[top] = mStack[top - 1]; + return true; + } + + bool MatrixStack::Pop() + { + if (top == 0) + return false; + --top; + return true; + } + + AEMath::Matrix44& MatrixStack::GetTop() + { + return mStack[top]; + } + + uint MatrixStack::GetTopIndex() + { + return top; + } + + uint MatrixStack::GetCapacity() + { + return ASURA_MAX_MATRIX_STACK_DEPTH; + } + + void MatrixStack::Ortho(float left, float right, float bottom, float top, float near, float far) + { + } + + } +} \ No newline at end of file diff --git a/source/modules/asura-core/graphics/matrix_stack.h b/source/modules/asura-core/graphics/matrix_stack.h new file mode 100644 index 0000000..1923b30 --- /dev/null +++ b/source/modules/asura-core/graphics/matrix_stack.h @@ -0,0 +1,82 @@ +#ifndef __ASURA_MATRIX_STACK_H__ +#define __ASURA_MATRIX_STACK_H__ + +#include +#include + +namespace AsuraEngine +{ + namespace Graphics + { + + /// + /// 栈的矩阵深度。 + /// +#define ASURA_MAX_MATRIX_STACK_DEPTH 32 // 2KB + + /// + /// 保存栈状态,用来恢复之前的状态。栈中的一个矩阵stack[i]的值是stack[0]*..*stack[i-1] + /// 的值,并附加一系列transform。 + /// + /// TODO: template MatrixStack + /// + class MatrixStack + { + public: + + MatrixStack(); + ~MatrixStack(); + + /// + /// 对栈顶元素的操作只能通过以下函数实现 + /// + void LoadIdentity(); + bool Push(); + bool Pop(); + + AEMath::Matrix44& GetTop(); + void GetTop(asura_out AEMath::Matrix44& mat44); + + void LoadMatrix(const AEMath::Matrix44& mat44); + void MultMatrix(const AEMath::Matrix44& mat44); + + /// + /// 仿射变换 + /// + void Rotate(float angle, float x, float y, float z); + void Translate(float x, float y, float z); + void Scale(float x, float y, float z); + + /// + /// 投影变换 + /// + void Ortho(float left, float right, float bottom, float top, float near, float far); + //void Perspective(float fov, float aspect, float near, float far); + //void Frustum(float left, float right, float top, float bottom, float near, float far); + //void LookAt(float x, float y, float z, float cx, float cy, float cz, float ux, float uy, float uz); + + /// + /// 获得栈顶的索引,范围在0~ASURA_MAX_MATRIX_STACK_DEPTH-1 + /// + uint GetTopIndex(); + + /// + /// 获得最大栈容量,即ASURA_MAX_MATRIX_STACK_DEPTH + /// + uint GetCapacity(); + + private: + + AEMath::Matrix44 mStack[ASURA_MAX_MATRIX_STACK_DEPTH]; + + /// + /// 栈顶索引,0~ASURA_MAX_MATRIX_STACK_DEPTH-1 + /// + uint8 top; + + }; + + } +} + +#endif \ No newline at end of file diff --git a/source/modules/asura-core/graphics/shader.cpp b/source/modules/asura-core/graphics/shader.cpp index f33fd1a..a4738cd 100644 --- a/source/modules/asura-core/graphics/shader.cpp +++ b/source/modules/asura-core/graphics/shader.cpp @@ -1,4 +1,9 @@ -#include "Shader.h" +#include + +#include "shader_source.h" +#include "shader.h" + +using namespace std; namespace AsuraEngine { @@ -7,17 +12,76 @@ namespace AsuraEngine Shader::Shader() { - + mProgram = glCreateProgram(); + if (mProgram == 0) + throw Exception("Cannot create OpenGL shader program."); + + mVertShader = glCreateShader(GL_VERTEX_SHADER); + if (mVertShader == 0) + { + glDeleteProgram(mProgram); + throw Exception("Cannot create OpenGL vertex shader."); + } + + mFragShader = glCreateShader(GL_FRAGMENT_SHADER); + if (mFragShader == 0) + { + glDeleteProgram(mProgram); + glDeleteShader(mVertShader); + throw Exception("Cannot create OpenGL fragment shader."); + } } Shader::~Shader() { - + glDeleteShader(mVertShader); + glDeleteShader(mFragShader); + glDeleteProgram(mProgram); } - bool Shader::Refresh(AEIO::DecodedData* db) + bool Shader::Renew(AEIO::DecodedData* db) { - return false; + if (!db) return false; + ShaderSouce* shaderSource = static_cast(db); + if (!shaderSource) return false; + + GLenum err = GL_NO_ERROR; + const GLchar* source; + GLint success; + string warnning = ""; + + // Compile vertex shader. + source = shaderSource->mVert.c_str(); + glShaderSource(mVertShader, 1, &source, NULL); + glCompileShader(mVertShader); + glGetShaderiv(mVertShader, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) + { + warnning = GetShaderWarnings(mVertShader); + throw Exception("Compile vertex shader failed:\n%s", warnning.c_str()); + } + + // Compile fragment shader. + source = shaderSource->mFrag.c_str(); + glShaderSource(mFragShader, 1, &source, NULL); + glCompileShader(mFragShader); + glGetShaderiv(mFragShader, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) + { + warnning = GetShaderWarnings(mFragShader); + throw Exception("Compile fragment shader failed:\n%s", warnning.c_str()); + } + + // Link program. + glAttachShader(mProgram, mVertShader); + glAttachShader(mProgram, mFragShader); + glLinkProgram(mProgram); + glGetProgramiv(mProgram, GL_LINK_STATUS, &success); + if (success == GL_FALSE) + { + warnning = GetProgramWarnings(); + throw Exception("Link shader program failed:\n%s", warnning.c_str()); + } } uint Shader::GetUniformLocation(const std::string& uniform) @@ -32,37 +96,45 @@ namespace AsuraEngine void Shader::Use() { - + if (mProgram != 0) + { + gl.UseShader(this); + } } void Shader::Unuse() { - + gl.UnuseShader(); } void Shader::SetUniformFloat(uint loc, float value) { - + if(gl.state.shader == this) + glUniform1f(loc, value); } void Shader::SetUniformTexture(uint loc, const Texture& texture) { - + if (gl.state.shader == this) + glUniform1i(loc, texture.GetGLTextureHandle()); } void Shader::SetUniformVector2(uint loc, const Math::Vector2f& vec2) { - + if (gl.state.shader == this) + glUniform2f(loc, vec2.x, vec2.y); } void Shader::SetUniformVector3(uint loc, const Math::Vector3f& vec3) { - + if (gl.state.shader == this) + glUniform3f(loc, vec3.x, vec3.y, vec3.z); } void Shader::SetUniformVector4(uint loc, const Math::Vector4f& vec4) { - + if (gl.state.shader == this) + glUniform4f(loc, vec4.x, vec4.y, vec4.z, vec4.w); } uint Shader::GetGLTextureUnitCount() @@ -72,5 +144,45 @@ namespace AsuraEngine return (uint)maxTextureUnits; } + std::string Shader::GetProgramWarnings() + { + GLint strsize, nullpos; + glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &strsize); + + if (strsize == 0) + return ""; + + char *tempstr = new char[strsize]; + + memset(tempstr, '\0', strsize); + glGetProgramInfoLog(mProgram, strsize, &nullpos, tempstr); + tempstr[nullpos] = '\0'; + + std::string warnings(tempstr); + delete[] tempstr; + + return warnings; + } + + std::string Shader::GetShaderWarnings(GLuint shader) + { + GLint strsize, nullpos; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &strsize); + + if (strsize == 0) + return ""; + + char *tempstr = new char[strsize]; + + memset(tempstr, '\0', strsize); + glGetShaderInfoLog(shader, strsize, &nullpos, tempstr); + tempstr[nullpos] = '\0'; + + std::string warnings(tempstr); + delete[] tempstr; + + return warnings; + } + } } \ No newline at end of file diff --git a/source/modules/asura-core/graphics/shader.h b/source/modules/asura-core/graphics/shader.h index ae24548..9077599 100644 --- a/source/modules/asura-core/graphics/shader.h +++ b/source/modules/asura-core/graphics/shader.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -36,7 +37,7 @@ namespace AsuraEngine LUAX_DECL_FACTORY(Shader); - Shader(); + Shader() asura_throw(Exception); ~Shader(); @@ -44,8 +45,7 @@ namespace AsuraEngine /// 从代码编译shader,编译时会先检测是否有上次缓存的uniforms location map。使用 /// glAttachShader重新编译生成着色器,不会重新申请着色器程序。 /// - //bool Load(const std::string& vertexShader, const std::string& fragmentShader); - bool Refresh(AEIO::DecodedData* decodeData) override; + bool Renew(AEIO::DecodedData* decodeData) override; /// /// 将当期shader设置为活动 @@ -98,6 +98,8 @@ namespace AsuraEngine /// OpenGL shader program handle. /// GLuint mProgram; + GLuint mVertShader; + GLuint mFragShader; Luax::LuaxMemberRef mCodeRef; @@ -109,6 +111,7 @@ namespace AsuraEngine LUAX_DECL_METHOD(_Use); LUAX_DECL_METHOD(_Unuse); LUAX_DECL_METHOD(_Load); + LUAX_DECL_METHOD(_Renew); LUAX_DECL_METHOD(_HasUniform); LUAX_DECL_METHOD(_GetUniformLocation); LUAX_DECL_METHOD(_SetBuiltInUniforms); @@ -121,6 +124,9 @@ namespace AsuraEngine //----------------------------------------------------------------------------// + std::string GetProgramWarnings(); + std::string GetShaderWarnings(GLuint shader); + }; } diff --git a/source/modules/asura-core/graphics/shader_source.h b/source/modules/asura-core/graphics/shader_source.h index b3e815c..eedbe53 100644 --- a/source/modules/asura-core/graphics/shader_source.h +++ b/source/modules/asura-core/graphics/shader_source.h @@ -10,15 +10,24 @@ namespace AsuraEngine namespace Graphics { + class Shader; + /// /// Asura Engine使用的shader源代码,基于GLSL。 /// class ShaderSouce : public AEIO::DecodedData { public: - void Decode(AEIO::DataBuffer& buffer) override; + + void Decode(AEIO::DataBuffer& vert, AEIO::DataBuffer& frag); + void Load(const std::string& vert, const std::string& frag); private: + + friend class Shader; + + void Decode(AEIO::DataBuffer& buffer) override; + std::string mVert; std::string mFrag; diff --git a/source/modules/asura-core/graphics/texture.cpp b/source/modules/asura-core/graphics/texture.cpp index 4db6ad3..38a75d7 100644 --- a/source/modules/asura-core/graphics/texture.cpp +++ b/source/modules/asura-core/graphics/texture.cpp @@ -1,3 +1,5 @@ +#include + #include "Texture.h" namespace AsuraEngine @@ -8,13 +10,17 @@ namespace AsuraEngine Texture::Texture() : mTex(0) { - // 申请GL texture - glGenTextures(1, &mTex); + // Fix: 等需要的时候再申请纹理资源 + //glGenTextures(1, &mTex); + //if(mTex == 0) + // throw Exception("Cannot create texture."); } Texture::~Texture() { - glDeleteTextures(1, &mTex); + // 释放纹理资源 + if(mTex != 0) + glDeleteTextures(1, &mTex); } GLuint Texture::GetGLTextureHandle() const @@ -37,6 +43,8 @@ namespace AsuraEngine t.externalformat = GL_RGBA; t.type = GL_FLOAT; break; + default: + ASSERT(false); // cant reach here } return t; } diff --git a/source/modules/asura-utils/exceptions/exception.cpp b/source/modules/asura-utils/exceptions/exception.cpp index dbb36ca..5240c49 100644 --- a/source/modules/asura-utils/exceptions/exception.cpp +++ b/source/modules/asura-utils/exceptions/exception.cpp @@ -20,17 +20,10 @@ namespace AsuraEngine size_out = vsnprintf(buffer, size_buffer, fmt, args); va_end(args); - // see http://perfec.to/vsnprintf/pasprintf.c - // if size_out ... - // == -1 --> output was truncated - // == size_buffer --> output was truncated - // == size_buffer-1 --> ambiguous, /may/ have been truncated - // > size_buffer --> output was truncated, and size_out - // bytes would have been written if (size_out == size_buffer || size_out == -1 || size_out == size_buffer - 1) size_buffer *= 2; else if (size_out > size_buffer) - size_buffer = size_out + 2; // to avoid the ambiguous case + size_buffer = size_out + 2; else break; diff --git a/source/modules/asura-utils/exceptions/exception.h b/source/modules/asura-utils/exceptions/exception.h index 57c9ed6..9873a38 100644 --- a/source/modules/asura-utils/exceptions/exception.h +++ b/source/modules/asura-utils/exceptions/exception.h @@ -7,27 +7,13 @@ namespace AsuraEngine { - /** - * A convenient vararg-enabled exception class. - **/ class Exception : public std::exception { public: - /** - * Creates a new Exception according to printf-rules. - * - * See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/ - * - * @param fmt The format string (see printf). - **/ Exception(const char *fmt, ...); virtual ~Exception() throw(); - /** - * Returns a string containing reason for the exception. - * @return A description of the exception. - **/ inline virtual const char *what() const throw() { return message.c_str(); diff --git a/source/modules/asura-utils/io/binding/_file.cpp b/source/modules/asura-utils/io/binding/_file.cpp index c44bc90..2de7882 100644 --- a/source/modules/asura-utils/io/binding/_file.cpp +++ b/source/modules/asura-utils/io/binding/_file.cpp @@ -186,7 +186,7 @@ namespace AsuraEngine LUAX_PREPARE(L, File); size_t size = 0; - BufferMode mode = self->GetBuffer(ASURA_OUT size); + BufferMode mode = self->GetBuffer(asura_out size); state.Push((int)size); state.Push((int)mode); return 2; diff --git a/source/modules/asura-utils/io/binding/_file_system.cpp b/source/modules/asura-utils/io/binding/_file_system.cpp index 3843451..2efc4f6 100644 --- a/source/modules/asura-utils/io/binding/_file_system.cpp +++ b/source/modules/asura-utils/io/binding/_file_system.cpp @@ -113,7 +113,7 @@ namespace AsuraEngine cc8* path = state.CheckValue(1); std::string mp; - if (fs->GetMountPoint(path, ASURA_OUT mp)) + if (fs->GetMountPoint(path, asura_out mp)) state.Push(mp); else state.PushNil(); @@ -246,7 +246,7 @@ namespace AsuraEngine cc8* path = state.CheckValue(1); std::vector items; - if(fs->GetDirectoryItems(path, ASURA_OUT items)) + if(fs->GetDirectoryItems(path, asura_out items)) { lua_newtable(L); // item list for (int i = 0; i < items.size(); ++i) diff --git a/source/modules/asura-utils/io/file.cpp b/source/modules/asura-utils/io/file.cpp index 9e89c85..690f405 100644 --- a/source/modules/asura-utils/io/file.cpp +++ b/source/modules/asura-utils/io/file.cpp @@ -118,7 +118,7 @@ namespace AsuraEngine return PHYSFS_fileLength(mFileHandle); } - size_t File::Read(ASURA_OUT DataBuffer* dst, size_t length) + size_t File::Read(asura_out DataBuffer* dst, size_t length) { ASSERT(dst); @@ -140,7 +140,7 @@ namespace AsuraEngine return size; } - size_t File::ReadAll(ASURA_OUT DataBuffer* dst) + size_t File::ReadAll(asura_out DataBuffer* dst) { ASSERT(dst); @@ -192,7 +192,7 @@ namespace AsuraEngine return mFileHandle != nullptr && PHYSFS_seek(mFileHandle, pos) != 0; } - bool File::Write(ASURA_REF DataBuffer* src) + bool File::Write(asura_ref DataBuffer* src) { if (!mFileHandle || (mMode != FILE_MODE_APPEND && mMode != FILE_MODE_WRITE)) throw Exception("File is not opened for writing."); @@ -264,7 +264,7 @@ namespace AsuraEngine return true; } - File::BufferMode File::GetBuffer(ASURA_OUT size_t& size) + File::BufferMode File::GetBuffer(asura_out size_t& size) { size = mBufferSize; return mBufferMode; diff --git a/source/modules/asura-utils/io/file.h b/source/modules/asura-utils/io/file.h index 56077e0..9af8919 100644 --- a/source/modules/asura-utils/io/file.h +++ b/source/modules/asura-utils/io/file.h @@ -57,9 +57,9 @@ namespace AsuraEngine /// /// 读取到data buffer里,并返回读入的内容 /// - size_t Read(ASURA_OUT DataBuffer* dst, size_t length); - size_t ReadAll(ASURA_OUT DataBuffer* dst); - size_t ReadAsync(ASURA_OUT DataBuffer* dst); + size_t Read(asura_out DataBuffer* dst, size_t length); + size_t ReadAll(asura_out DataBuffer* dst); + size_t ReadAsync(asura_out DataBuffer* dst); /// /// 是否读到了文件结尾 @@ -69,12 +69,12 @@ namespace AsuraEngine /// /// 将data buffer中的内容写入,并返回是否成功 /// - bool Write(ASURA_REF DataBuffer* src); + bool Write(asura_ref DataBuffer* src); /// /// 异步写文件,将写文件task加入thread的队列。 /// - bool WriteAsync(ASURA_REF DataBuffer* src, AEThreading::Thread* thread); + bool WriteAsync(asura_ref DataBuffer* src, AEThreading::Thread* thread); /// /// 如果开启了缓冲,强制清空缓冲区,写入文件。 @@ -99,7 +99,7 @@ namespace AsuraEngine /// /// 获取缓冲区大小和模式 /// - BufferMode GetBuffer(ASURA_OUT size_t& size); + BufferMode GetBuffer(asura_out size_t& size); const std::string& GetFileName(); const std::string& GetName(); diff --git a/source/modules/asura-utils/io/file_data.h b/source/modules/asura-utils/io/file_data.h index cd69477..f5a6085 100644 --- a/source/modules/asura-utils/io/file_data.h +++ b/source/modules/asura-utils/io/file_data.h @@ -49,7 +49,7 @@ namespace AsuraEngine /// /// Data buffer不会再filedata析构时销毁,当lua引用计数为0时由lua调用GC销毁。创建mData时会添加一个成员引用。 /// - ASURA_REF DataBuffer* mData; + asura_ref DataBuffer* mData; Luax::LuaxMemberRef mDataRef; std::string mFileName; ///< 包含扩展名的文件名 diff --git a/source/modules/asura-utils/io/file_system.cpp b/source/modules/asura-utils/io/file_system.cpp index 20f3cb2..30e7861 100644 --- a/source/modules/asura-utils/io/file_system.cpp +++ b/source/modules/asura-utils/io/file_system.cpp @@ -83,7 +83,7 @@ namespace AsuraEngine } } - bool Filesystem::GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint) + bool Filesystem::GetMountPoint(const std::string& locpath, asura_out std::string& mountpoint) { if (!mInited) return false; @@ -125,7 +125,7 @@ namespace AsuraEngine return true; } - bool Filesystem::Write(const std::string& name, ASURA_REF DataBuffer* buffer) + bool Filesystem::Write(const std::string& name, asura_ref DataBuffer* buffer) { File file(name); file.Open(File::FILE_MODE_WRITE); @@ -133,7 +133,7 @@ namespace AsuraEngine throw Exception("Data could not be written."); } - bool Filesystem::Append(const std::string& name, ASURA_REF DataBuffer* buffer) + bool Filesystem::Append(const std::string& name, asura_ref DataBuffer* buffer) { File file(name); file.Open(File::FILE_MODE_APPEND); @@ -170,7 +170,7 @@ namespace AsuraEngine return true; } - bool Filesystem::GetFileInfo(const std::string& filepath, ASURA_OUT FileInfo* info) + bool Filesystem::GetFileInfo(const std::string& filepath, asura_out FileInfo* info) { if (!mInited) return false; diff --git a/source/modules/asura-utils/io/file_system.h b/source/modules/asura-utils/io/file_system.h index 849cbb6..3a33504 100644 --- a/source/modules/asura-utils/io/file_system.h +++ b/source/modules/asura-utils/io/file_system.h @@ -59,20 +59,20 @@ namespace AsuraEngine bool Unmount(const std::string& locpath); bool Unmount(DataBuffer* db); - bool GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint); + bool GetMountPoint(const std::string& locpath, asura_out std::string& mountpoint); void SetWriteDirectory(const std::string locpath); std::string GetWriteDirectory(); File* NewFile(const std::string& name); bool NewDirectory(const std::string& path); - bool Write(const std::string& path, ASURA_REF DataBuffer* buffer); - bool Append(const std::string& path, ASURA_REF DataBuffer* buffer); + bool Write(const std::string& path, asura_ref DataBuffer* buffer); + bool Append(const std::string& path, asura_ref DataBuffer* buffer); bool Remove(const std::string& path); FileData* Read(const std::string& path); - bool GetFileInfo(const std::string& path, ASURA_OUT FileInfo* info); + bool GetFileInfo(const std::string& path, asura_out FileInfo* info); - bool GetDirectoryItems(const std::string& path, ASURA_OUT std::vector& items) { return false; }; + bool GetDirectoryItems(const std::string& path, asura_out std::vector& items) { return false; }; private: diff --git a/source/modules/asura-utils/io/io_task.h b/source/modules/asura-utils/io/io_task.h index 8f04142..09c8798 100644 --- a/source/modules/asura-utils/io/io_task.h +++ b/source/modules/asura-utils/io/io_task.h @@ -46,7 +46,7 @@ namespace AsuraEngine std::string mPath; IOTaskType mType; - ASURA_REF DataBuffer* mBuffer; + asura_ref DataBuffer* mBuffer; Luax::LuaxMemberRef mBufferRef; }; diff --git a/source/modules/asura-utils/io/renewable.h b/source/modules/asura-utils/io/renewable.h index 282106d..a624c2c 100644 --- a/source/modules/asura-utils/io/renewable.h +++ b/source/modules/asura-utils/io/renewable.h @@ -21,12 +21,12 @@ namespace AsuraEngine virtual ~Renewable() {}; /// - /// 继承Renewable的需要提供一个Refresh方法 + /// 继承Renewable的需要提供一个Renew方法 /// - /// 依据Effective C++条款09.应该禁止在构造函数中调用virtual方法,所以这里的Refresh - /// 被从构造函数中抽离,需要手动调用Refresh。 + /// 依据Effective C++条款09.应该禁止在构造函数中调用virtual方法,所以这里的Renew + /// 被从构造函数中抽离,需要手动调用Renew。 /// - virtual bool Refresh(AEIO::DecodedData* decode_data) = 0; + virtual bool Renew(AEIO::DecodedData* decode_data) = 0; }; diff --git a/source/modules/asura-utils/math/matrix44.cpp b/source/modules/asura-utils/math/matrix44.cpp index e69de29..10c9ece 100644 --- a/source/modules/asura-utils/math/matrix44.cpp +++ b/source/modules/asura-utils/math/matrix44.cpp @@ -0,0 +1,203 @@ +#include "matrix44.h" + +#include // memcpy +#include + +namespace AsuraEngine +{ + namespace Math + { + + const Matrix44 Matrix44::Identity; + + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + Matrix44::Matrix44() + { + SetIdentity(); + } + + Matrix44::Matrix44(const Matrix44& m) + { + memcpy(&e, &m.e, 16 * sizeof(float)); + } + + Matrix44::~Matrix44() + { + } + + void Matrix44::operator = (const Matrix44& m) + { + memcpy(&e, &m.e, 16 * sizeof(float)); + } + + void Matrix44::SetOrtho(float l, float r, float b, float t, float n, float f) + { + SetIdentity(); + float w = r - l; + float h = t - b; + float z = f - n; + e[0] = 2 / w; + e[5] = 2 / h; + e[10] = -2 / z; + e[12] = -(r + l) / w; + e[13] = -(t + b) / h; + e[14] = -(f + n) / z; + e[15] = 1; + } + + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + Matrix44 Matrix44::operator * (const Matrix44 & m) const + { + Matrix44 t; + + t.e[0] = (e[0] * m.e[0]) + (e[4] * m.e[1]) + (e[8] * m.e[2]) + (e[12] * m.e[3]); + t.e[4] = (e[0] * m.e[4]) + (e[4] * m.e[5]) + (e[8] * m.e[6]) + (e[12] * m.e[7]); + t.e[8] = (e[0] * m.e[8]) + (e[4] * m.e[9]) + (e[8] * m.e[10]) + (e[12] * m.e[11]); + t.e[12] = (e[0] * m.e[12]) + (e[4] * m.e[13]) + (e[8] * m.e[14]) + (e[12] * m.e[15]); + + t.e[1] = (e[1] * m.e[0]) + (e[5] * m.e[1]) + (e[9] * m.e[2]) + (e[13] * m.e[3]); + t.e[5] = (e[1] * m.e[4]) + (e[5] * m.e[5]) + (e[9] * m.e[6]) + (e[13] * m.e[7]); + t.e[9] = (e[1] * m.e[8]) + (e[5] * m.e[9]) + (e[9] * m.e[10]) + (e[13] * m.e[11]); + t.e[13] = (e[1] * m.e[12]) + (e[5] * m.e[13]) + (e[9] * m.e[14]) + (e[13] * m.e[15]); + + t.e[2] = (e[2] * m.e[0]) + (e[6] * m.e[1]) + (e[10] * m.e[2]) + (e[14] * m.e[3]); + t.e[6] = (e[2] * m.e[4]) + (e[6] * m.e[5]) + (e[10] * m.e[6]) + (e[14] * m.e[7]); + t.e[10] = (e[2] * m.e[8]) + (e[6] * m.e[9]) + (e[10] * m.e[10]) + (e[14] * m.e[11]); + t.e[14] = (e[2] * m.e[12]) + (e[6] * m.e[13]) + (e[10] * m.e[14]) + (e[14] * m.e[15]); + + t.e[3] = (e[3] * m.e[0]) + (e[7] * m.e[1]) + (e[11] * m.e[2]) + (e[15] * m.e[3]); + t.e[7] = (e[3] * m.e[4]) + (e[7] * m.e[5]) + (e[11] * m.e[6]) + (e[15] * m.e[7]); + t.e[11] = (e[3] * m.e[8]) + (e[7] * m.e[9]) + (e[11] * m.e[10]) + (e[15] * m.e[11]); + t.e[15] = (e[3] * m.e[12]) + (e[7] * m.e[13]) + (e[11] * m.e[14]) + (e[15] * m.e[15]); + + return t; + } + + void Matrix44::operator *= (const Matrix44 & m) + { + Matrix44 t = (*this) * m; + memcpy((void*)this->e, (void*)t.e, sizeof(float) * 16); + } + + const float * Matrix44::GetElements() const + { + return e; + } + + void Matrix44::SetIdentity() + { + memset(e, 0, sizeof(float) * 16); + e[0] = e[5] = e[10] = e[15] = 1; + } + + void Matrix44::SetTranslation(float x, float y) + { + SetIdentity(); + e[12] = x; + e[13] = y; + } + + void Matrix44::SetRotation(float rad) + { + SetIdentity(); + float c = cos(rad), s = sin(rad); + e[0] = c; e[4] = -s; + e[1] = s; e[5] = c; + } + + void Matrix44::SetScale(float sx, float sy) + { + SetIdentity(); + e[0] = sx; + e[5] = sy; + } + + void Matrix44::SetShear(float kx, float ky) + { + SetIdentity(); + e[1] = ky; + e[4] = kx; + } + + void Matrix44::SetTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy) + { + memset(e, 0, sizeof(float) * 16); // zero out matrix + float c = cos(angle), s = sin(angle); + // matrix multiplication carried out on paper: + // |1 x| |c -s | |sx | |1 -ox| + // | 1 y| |s c | | sy | | 1 -oy| + // | 1 | | 1 | | 1 | | 1 | + // | 1| | 1| | 1| | 1 | + // move rotate scale origin + e[10] = e[15] = 1.0f; + e[0] = c * sx; // = a + e[1] = s * sx; // = b + e[4] = -s * sy; // = c + e[5] = c * sy; // = d + e[12] = x - ox * e[0] - oy * e[4]; + e[13] = y - ox * e[1] - oy * e[5]; + } + + void Matrix44::Translate(float x, float y) + { + Matrix44 t; + t.SetTranslation(x, y); + this->operator *=(t); + } + + void Matrix44::Rotate(float rad) + { + Matrix44 t; + t.SetRotation(rad); + this->operator *=(t); + } + + void Matrix44::Scale(float sx, float sy) + { + Matrix44 t; + t.SetScale(sx, sy); + this->operator *=(t); + } + + void Matrix44::Shear(float kx, float ky) + { + Matrix44 t; + t.SetShear(kx, ky); + this->operator *=(t); + } + + // | x | + // | y | + // | 0 | + // | 1 | + // | e0 e4 e8 e12 | + // | e1 e5 e9 e13 | + // | e2 e6 e10 e14 | + // | e3 e7 e11 e15 | + + //void Matrix44::transform(Graphics::Vertex* dst, const Graphics::Vertex* src, int size) const + //{ + // for (int i = 0; i