diff --git a/src/PlatformLayer/Batcher.bf b/src/PlatformLayer/Batcher.bf new file mode 100644 index 0000000..dace874 --- /dev/null +++ b/src/PlatformLayer/Batcher.bf @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Strawberry +{ + public class Batcher + { + List batchStack = new System.Collections.List() ~ DeleteContainerAndItems!(_); + + Batch top => batchStack.Count > 0 ? batchStack[batchStack.Count - 1] : null; + + private class Batch + { + + } + } +} diff --git a/src/PlatformLayer/GL.bf b/src/PlatformLayer/GL.bf index 87d9c16..8ce851b 100644 --- a/src/PlatformLayer/GL.bf +++ b/src/PlatformLayer/GL.bf @@ -2,26 +2,6 @@ using System; namespace Strawberry { - class GLTexture : Texture - { - private uint32 handle; - - public this(int width, int height, void* pixels) - { - Width = width; - Height = height; - - GL.glGenTextures(1, &handle); - GL.glBindTexture(GL.GL_TEXTURE_2D, handle); - GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels); - } - - public ~this() - { - GL.glDeleteTextures(1, &handle); - } - } - class GL { public function void* GetProcAddressFunc(StringView procname); diff --git a/src/PlatformLayer/PlatformLayer.bf b/src/PlatformLayer/PlatformLayer.bf index dbf9e02..dd9654d 100644 --- a/src/PlatformLayer/PlatformLayer.bf +++ b/src/PlatformLayer/PlatformLayer.bf @@ -4,12 +4,12 @@ namespace Strawberry public abstract class PlatformLayer { public abstract void Init(); - public abstract bool Closed(); // If the game window has been closed + public abstract bool Closed(); // Returns whether the game window has been closed //Rendering public abstract void RenderBegin(); public abstract void RenderEnd(); - + //Update public abstract uint32 Ticks { get; } // Milliseconds since game launched @@ -20,11 +20,53 @@ namespace Strawberry public abstract bool PollKey(Keys key); public abstract bool PollGamepadButton(int gamepadID, Buttons button); public abstract float PollGamepadAxis(int gamepadID, Axes axis); + + //Graphics + public abstract Texture LoadTexture(String path); } public abstract class Texture { - public int Width { get; protected set; } - public int Height { get; protected set; } + public int Width { get; private set; } + public int Height { get; private set; } + + public virtual this(int width, int height, uint8* pixels) + { + Width = width; + Height = height; + } + } + + public abstract class Shader + { + public bool IsValid { get; protected set; } + + public this(ShaderDef def) + { + + } + } + + public struct ShaderDef + { + public String Vertex; + public String Fragment; + + public this(String vertex, String fragment) + { + Vertex = vertex; + Fragment = fragment; + } + + public this(String[2] str) + { + Vertex = str[0]; + Fragment = str[1]; + } + + static implicit public operator ShaderDef(String[2] str) + { + return ShaderDef(str); + } } } diff --git a/src/PlatformLayer/SDL2PlatformLayer.bf b/src/PlatformLayer/SDL2PlatformLayer.bf index 7dd89b9..d8a7a9f 100644 --- a/src/PlatformLayer/SDL2PlatformLayer.bf +++ b/src/PlatformLayer/SDL2PlatformLayer.bf @@ -10,8 +10,10 @@ namespace Strawberry private SDL.Surface* screen; private SDL.Rect screenRect; private SDL.Renderer* renderer; + private SDL2Shader shader; private SDL.SDL_GLContext glContext; private uint glProgram; + private uint glVertexShader; private SDL.SDL_GameController*[] gamepads; private bool* keyboard; @@ -51,7 +53,55 @@ namespace Strawberry SDL.GL_SetSwapInterval(1); GL.Init(=> SdlGetProcAddress); + shader = new SDL2Shader(String[2] ( + // vertex shader + """ + #version 330 + uniform mat4 u_matrix; + layout(location=0) in vec2 a_position; + layout(location=1) in vec2 a_tex; + layout(location=2) in vec4 a_color; + layout(location=3) in vec3 a_type; + out vec2 v_tex; + out vec4 v_col; + out vec3 v_type; + void main(void) + { + gl_Position = u_matrix * vec4(a_position.xy, 0, 1); + v_tex = a_tex; + v_col = a_color; + v_type = a_type; + } + """, + + // fragment shader + """ + #version 330 + uniform sampler2D u_texture; + in vec2 v_tex; + in vec4 v_col; + in vec3 v_type; + out vec4 o_color; + void main(void) + { + vec4 color = texture(u_texture, v_tex); + o_color = + v_type.x * color * v_col + + v_type.y * color.a * v_col + + v_type.z * v_col; + } + """)); + glProgram = GL.glCreateProgram(); + GL.glAttachShader(glProgram, shader.vertexHandle); + GL.glAttachShader(glProgram, shader.fragmentHandle); + GL.glLinkProgram(glProgram); + + int32 logLen = 0; + char8[1024] log; + GL.glGetProgramInfoLog(glProgram, 1024, &logLen, &log); + if (logLen > 0) + Calc.Log(&log, logLen); } //Audio @@ -76,6 +126,7 @@ namespace Strawberry public ~this() { delete gamepads; + delete shader; GL.glDeleteProgram(glProgram); SDL.GL_DeleteContext(glContext); @@ -103,6 +154,15 @@ namespace Strawberry SDL.GL_SwapWindow(window); } + public override Texture LoadTexture(String path) + { + var surface = SDLImage.Load(path); + var tex = new SDL2Texture(surface.w, surface.h, (uint8*)surface.pixels); + SDL.FreeSurface(surface); + + return tex; + } + public override void UpdateInput() { SDL.PumpEvents(); @@ -141,4 +201,72 @@ namespace Strawberry return val / 32768f; } } + + class SDL2Texture : Texture + { + private uint32 handle; + + public this(int width, int height, uint8* pixels) + : base(width, height, pixels) + { + GL.glGenTextures(1, &handle); + GL.glBindTexture(GL.GL_TEXTURE_2D, handle); + GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels); + } + + public ~this() + { + GL.glDeleteTextures(1, &handle); + } + } + + class SDL2Shader : Shader + { + public uint vertexHandle; + public uint fragmentHandle; + + public this(ShaderDef def) + : base(def) + { + IsValid = true; + int32 logLen = 0; + char8[1024] log; + + vertexHandle = GL.glCreateShader(GL.GL_VERTEX_SHADER); + { + int32 len = (int32)def.Vertex.Length; + char8* data = def.Vertex.CStr(); + GL.glShaderSource(vertexHandle, 1, &data, &len); + GL.glCompileShader(vertexHandle); + GL.glGetShaderInfoLog(vertexHandle, 1024, &logLen, &log); + + if (logLen > 0) + { + Calc.Log(&log, logLen); + IsValid = false; + } + } + + fragmentHandle = GL.glCreateShader(GL.GL_FRAGMENT_SHADER); + { + int32 len = (int32)def.Fragment.Length; + char8* data = def.Fragment.CStr(); + GL.glShaderSource(fragmentHandle, 1, &data, &len); + GL.glCompileShader(fragmentHandle); + GL.glGetShaderInfoLog(fragmentHandle, 1024, &logLen, &log); + + if (logLen > 0) + { + Calc.Log(&log, logLen); + IsValid = false; + } + } + } + + public ~this() + { + GL.glDeleteShader(vertexHandle); + GL.glDeleteShader(fragmentHandle); + } + } } diff --git a/src/Static/Calc.bf b/src/Static/Calc.bf index a9a1f6f..b4c7b4c 100644 --- a/src/Static/Calc.bf +++ b/src/Static/Calc.bf @@ -129,5 +129,12 @@ namespace Strawberry let string = StringArgs(scope String(str), params args); Debug.WriteLine(string); } + + [Inline] + static public void Log(char8* str, int len) + { + String s = scope String(str, len); + Debug.WriteLine(s); + } } }