*added ImGUI styles
 *added new assets (fonts, shaders)
 *added cimgui.dll
 *added imports for bindbc-sdl (for WASM)
 *added simple demo
 *added demo launcher
 *added snake demo
 *impoved demo utils
 *added cimgui.bc library for WASM
-improved wasm build script
-small change in vector
This commit is contained in:
Mergul 2019-11-12 20:33:31 +01:00
parent 73f2aa6861
commit cb7609dcaa
82 changed files with 11188 additions and 413 deletions

View file

@ -0,0 +1,134 @@
module ecs_utils.gfx.buffer;
import ecs.std;
import glad.gl.gl;
import glad.gl.gles2;
extern(C):
struct Buffer
{
void create() nothrow
{
data = Mallocator.make!Data;
data.gl_handle = 0;
glGenBuffers(1,&data.gl_handle);
data.elem_size = 0;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
void destroy() nothrow
{
if(data.gl_handle)glDeleteBuffers(1,&data.gl_handle);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
void bind(BindTarget target) nothrow
{
//if(vbo != this)glBindBuffer(GL_ARRAY_BUFFER,data.gl_handle);
//vbo = this;
glBindBuffer(target,data.gl_handle);
}
void bindRange(BindTarget target, uint index, uint offset, uint size) nothrow
{
glBindBufferRange(target, index, data.gl_handle, offset, size);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
void bufferData(BindTarget target, uint size, uint count, uint usage, void* data) nothrow
{
bind(target);
this.data.elem_size = size;
glBufferData(target,size*count,data,usage);
}
/*void bufferStorage(uint size, uint count, void* data, uint flags = StorageFlagBits.write)
{
bind(BindTarget.array);
this.data.elem_size = size;
glBufferStorage(GL_ARRAY_BUFFER,size*count,data, flags);
}*/
void bufferSubData(uint size, uint offset, void* data) nothrow
{
bind(BindTarget.array);
glBufferSubData(GL_ARRAY_BUFFER,offset,size,data);
}
void map(BindTarget target) nothrow
{
bind(target);
data.map_ptr = glMapBuffer(target,GL_WRITE_ONLY);
}
void map(uint offset, uint size, BindTarget target, uint flags = MapFlagBits.write | MapFlagBits.flush_explict | MapFlagBits.invalidate_buffer) nothrow
{
bind(target);
data.map_ptr = glMapBufferRange(target,offset,size,flags);
}
void flush(uint offset, uint size, BindTarget target) nothrow
{
glFlushMappedBufferRange(target, offset, size);
}
void unmap(BindTarget target) nothrow
{
bind(target);
glUnmapBuffer(target);
data.map_ptr = null;
}
void* mappedPointer() nothrow
{
return data.map_ptr;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
static void unbind(BindTarget target) nothrow
{
//vbo = 0;
glBindBuffer(target,0);
}
enum BindTarget
{
array = GL_ARRAY_BUFFER,
element_array = GL_ELEMENT_ARRAY_BUFFER,
uniform = GL_UNIFORM_BUFFER,
//shader_storage = GL_SHADER_STORAGE_BUFFER,
//indirect = GL_DRAW_INDIRECT_BUFFER
}
enum MapFlagBits
{
write = GL_MAP_WRITE_BIT,
invalidate_buffer = GL_MAP_INVALIDATE_BUFFER_BIT,
flush_explict = GL_MAP_FLUSH_EXPLICIT_BIT,
//coherent = GL_MAP_COHERENT_BIT,
//persistent = GL_MAP_PERSISTENT_BIT
}
enum StorageFlagBits
{
write = GL_MAP_WRITE_BIT,
//coherent = GL_MAP_COHERENT_BIT,
//persistent = GL_MAP_PERSISTENT_BIT
}
struct Data
{
uint elem_size;
uint gl_handle;
void* map_ptr;
}
Data* data;
}

View file

@ -0,0 +1,102 @@
module ecs_utils.gfx.config;
import bindbc.sdl;
import ecs.std;
import ecs_utils.gfx.material;
import ecs_utils.gfx.mesh;
import ecs_utils.gfx.texture;
//import mutils.serializer.json;
extern(C):
enum LayerType
{
normal,
sorted
}
import ecs.vector;
static struct GfxConfig
{
extern(C):
__gshared:
Vector!LayerType layers;
//Vector!Mesh meshes;
//Vector!Material materials;
Mesh[] meshes;
Material[] materials;
static bool load(const (char)[] path) nothrow
{
struct LoadData
{
struct Str
{
@("malloc") string str;
}
@("malloc") Str[] materials;
@("malloc") Str[] meshes;
int inter;
void dispose() nothrow
{
/*if(blend_mode)Mallocator.instance.dispose(cast(char[])blend_mode);
if(vertex)Mallocator.instance.dispose(cast(char[])vertex);
if(fragment)Mallocator.instance.dispose(cast(char[])fragment);*/
}
}
char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
cpath[0..$-1] = path[0..$];
cpath[$-1] = 0;
SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");
if(file)
{
size_t size = cast(size_t)SDL_RWsize(file);
char[] buffer = Mallocator.makeArray!char(size);
SDL_RWread(file,buffer.ptr,size,1);
LoadData load_data;
scope(exit)load_data.dispose();
/*JSONSerializer serializer = Mallocator.make!JSONSerializer;
scope(exit)Mallocator.dispose(serializer);
serializer.serialize!(Load.yes, true)(load_data,buffer);*/
//if(__ecs_used_backend == Backend.opengl)
{
meshes = Mallocator.makeArray!Mesh(load_data.meshes.length);
foreach(i,ref mesh; meshes)
{
mesh.load(load_data.meshes[i].str);
mesh.uploadData();
}
}
materials = Mallocator.makeArray!Material(load_data.materials.length);
foreach(i,ref material; materials)
{
material.create();
material.load(load_data.materials[i].str);
material.compile();
}
SDL_RWclose(file);
load_data.dispose();
return true;
}
else return false;
}
static int addLayer(LayerType type)
{
layers.add(type);
return cast(int)(layers.length-1);
}
}

View file

@ -0,0 +1,198 @@
module ecs_utils.gfx.material;
import bindbc.sdl;
import ecs.std;
import ecs_utils.gfx.shader;
import glad.gl.gl;
//import mutils.serializer.json;
struct Material
{
void create() nothrow
{
data = Mallocator.make!Data;
}
bool load(const char[] path) nothrow
{
struct LoadData
{
@("malloc") string blend_mode;
@("malloc") string vertex;
@("malloc") string fragment;
void dispose() nothrow
{
//if(blend_mode)Mallocator.instance.dispose(cast(char[])blend_mode);
//if(vertex)Mallocator.instance.dispose(cast(char[])vertex);
//if(fragment)Mallocator.instance.dispose(cast(char[])fragment);
}
}
char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
cpath[0..$-1] = path[0..$];
cpath[$-1] = 0;
SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");
if(file)
{
size_t size = cast(size_t)SDL_RWsize(file);
char[] buffer = Mallocator.makeArray!char(size);
SDL_RWread(file,buffer.ptr,size,1);
LoadData load_data;
scope(exit)load_data.dispose();
/*JSONSerializer serializer = Mallocator.make!JSONSerializer;
scope(exit)Mallocator.dispose(serializer);
serializer.serialize!(Load.yes, true)(load_data,buffer);*/
//if(__ecs_used_backend == Backend.opengl)
{
Shader vsh;
vsh.load(load_data.vertex);
vsh.compile();
Shader fsh;
fsh.load(load_data.fragment);
fsh.compile();
Material.ShaderModule[1] modules = [Material.ShaderModule(vsh,fsh)];
attachModules(modules);
}
SDL_RWclose(file);
load_data.dispose();
return true;
}
else return false;
}
void bind() nothrow
{
glUseProgram(data.modules[0].gl_handle);
}
enum BlendMode
{
opaque,
additive,
mixed
}
enum TransformMode
{
position,
matrix
}
struct ShaderModule
{
Shader fragment_shader;
Shader vertex_shader;
uint gl_handle;
}
void attachModules(scope ShaderModule[] modules) nothrow
{
data.modules = Mallocator.makeArray(modules);
}
bool compile() nothrow
{
foreach(ref module_;data.modules)
{
module_.gl_handle = glCreateProgram();
glAttachShader(module_.gl_handle, module_.vertex_shader.data.gl_handle);
glAttachShader(module_.gl_handle, module_.fragment_shader.data.gl_handle);
}
return true;
}
void bindAttribLocation(const char* name, uint location) nothrow
{
foreach(ref module_;data.modules)
{
glBindAttribLocation(module_.gl_handle, location, name);
}
}
bool link() nothrow
{
foreach(ref module_;data.modules)
{
glLinkProgram(module_.gl_handle);
GLint ok = 0;
glGetProgramiv(module_.gl_handle, GL_LINK_STATUS, &ok);
if(!ok)
{
SDL_Log("Program link error!");
return false;
}
}
return true;
}
int getLocation(const char* name)
{
foreach(ref module_;data.modules)
{
int location = glGetUniformLocation(module_.gl_handle,name);
if(location != -1)return location;
}
return -1;
}
void pushBindings()
{
foreach(i;0..data.bindings.length)
{
glUniform1i(data.bindings[i],cast(int)i);
}
}
void pushUniforms(void* ptr)
{
foreach(ref Uniform uniform; data.uniforms)
{
void* local_ptr = ptr + uniform.offset;
glUniform4fv(uniform.location,1,cast(float*)local_ptr);
}
}
enum Type
{
float_,
float4
}
struct Uniform
{
Type type;
int location;
uint offset;
}
struct Data
{
BlendMode blend_mode = BlendMode.opaque;
ShaderModule[] modules;
TransformMode mode;
Uniform[] uniforms;
int[] bindings;
}
Data* data;
}

View file

@ -0,0 +1,121 @@
module ecs_utils.gfx.mesh;
import bindbc.sdl;
import ecs.std;
import ecs_utils.gfx.buffer;
import glad.gl.gl;
//import mutils.serializer.json;
extern(C):
struct Mesh
{
bool load(const char[] path) nothrow
{
struct LoadData
{
/*struct Vertex
{
struct Binding
{
@("malloc") string type;
uint stride;
}
@("malloc") Binding[] bindings;
}
Vertex vertex;*/
@("malloc") ushort[] indices;
@("malloc") float[] vertices;
//int i;
void dispose() nothrow
{
if(indices)Mallocator.dispose(indices);
if(vertices)Mallocator.dispose(vertices);
/*foreach(binding; vertex.bindings)Mallocator.instance.dispose(cast(char[])binding.type);
if(vertex.bindings)Mallocator.instance.dispose(vertex.bindings);*/
}
}
char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
cpath[0..$-1] = path[0..$];
cpath[$-1] = 0;
SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");//SDL_LoadFile(cpath.ptr,);
if(file)
{
size_t size = cast(size_t)SDL_RWsize(file);
//data.code = Mallocator.instance.makeArray!char(size);
//data.code[$-1] = 0;
char[] buffer = Mallocator.makeArray!char(size);
SDL_RWread(file,buffer.ptr,size,1);
LoadData load_data;
scope(exit)load_data.dispose();
/*JSONSerializer serializer = Mallocator.make!JSONSerializer;
scope(exit)Mallocator.dispose(serializer);
serializer.serialize!(Load.yes, true)(load_data,buffer);*/
indices = Mallocator.makeArray(load_data.indices);
/*vertex.create();
Vertex.Binding[] bindings = (cast(Vertex.Binding*)alloca(Vertex.Binding.sizeof*load_data.vertex.bindings.length))[0..load_data.vertex.bindings.length];
uint vertex_size = 0;
uint alignment = 4;
foreach(i, binding;load_data.vertex.bindings)
{
uint new_size = binding.stride;
bindings[i].stride = binding.stride;
if(binding.type == "float_rg")
{
bindings[i].type = Vertex.Type.float_rg;
new_size += 8;
}
if(new_size > vertex_size)vertex_size = new_size;
//new_size = new_size + (3 - (new_size)%alignment)
}
vertex.data.size = vertex_size;
vertex.attachBindings(bindings);*/
vertices = Mallocator.makeArray(load_data.vertices);
/*vertices = Mallocator.instance.makeArray!ubyte(vertex_size * load_data.vertices.length);
{
foreach()
}*/
SDL_RWclose(file);
load_data.dispose();
return true;
}
else return false;
}
void uploadData() nothrow
{
vbo.create();
vbo.bufferData(Buffer.BindTarget.array,16,cast(uint)vertices.length,GL_STATIC_DRAW,vertices.ptr);
ibo.create();
ibo.bufferData(Buffer.BindTarget.element_array,2,cast(uint)indices.length,GL_STATIC_DRAW,indices.ptr);
}
void bind() nothrow
{
vbo.bind(Buffer.BindTarget.array);
ibo.bind(Buffer.BindTarget.element_array);
glVertexAttribPointer(0,2,GL_FLOAT,false,16,null);
glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)8);
}
float[] vertices;
ushort[] indices;
Buffer vbo;
Buffer ibo;
//Vertex vertex;
}

View file

@ -0,0 +1,12 @@
module ecs_utils.gfx.mesh_module;
import ecs_utils.gfx.material;
import ecs_utils.gfx.texture;
import ecs_utils.gfx.mesh;
struct MeshModule
{
Mesh* mesh;
Material* material;
Texture texture;
}

View file

@ -0,0 +1,29 @@
module ecs_utils.gfx.render_list;
import ecs_utils.gfx.mesh_module;
import ecs_utils.math.vector;
import ecs_utils.math.matrix;
import ecs_utils.gfx.config;
struct RenderList
{
struct Data
{
MeshModule* module_;
uint index;
}
struct LocScale
{
vec2 location;
vec2 scale;
}
struct Layer
{
LayerType type;
Data[] list;
LocScale[] loc_scale;
mat3[] matrices;
}
}

View file

@ -0,0 +1,817 @@
module ecs_utils.gfx.renderer;
import bindbc.sdl;
import ecs.std;
//import ecs_utils.core : Backend;
import ecs_utils.gfx.buffer;
import ecs_utils.gfx.texture;
import ecs_utils.math.vector;
import glad.gl.gl;
version = ver1;
/*version(ver5)version = vv2;
else version(ver6)version = vv2;*/
extern(C) float sinf(float);
extern(C) float cosf(float);
enum RenderTechnique
{
simple,//1
simple_array,//2
vbo_batch,//3
instanced_attrib_divisor,//4
uniform_buffer,//5
uniform_buffer_indexed,//6
uniform_buffer_multi_draw,//7
uniform_buffer_instanced,//8
uniform_buffer_instanced_mapped_gl2,//9
uniform_buffer_instanced_mapped,//10
uniform_buffer_instanced_persistent_mapped,//11
uniform_buffer_instanced_persistent_mapped_coherent,//12
ssbo_instanced,//13
uniform_buffer_draw_indirect,//14
uniform_buffer_multi_draw_indirect,//15
uniform_buffer_multi_draw_indirect_arb_draw_parameters//16
}
struct Renderer
{
//static SDL_Renderer* main_sdl_renderer;
enum MaxObjects = 1024 * 64 * 4;
enum BufferUsage = GL_STATIC_DRAW;
//SDL_Window* sdl_window;
//SDL_Renderer* sdl_renderer;
ivec2 resolution;
vec2 dres;
vec4 sdl_transform;
vec2 view_pos = vec2(-1,-1);
vec2 view_size = vec2(1,1);
//uint[2] time_queries;
Buffer[2] ubos;
int block_alignment = 1;
int block_max_size = 16384;
struct IndirectDraw
{
uint count = 6;
uint instances = 1;
uint first_index = 0;
uint base_vertex = 0;
uint base_instance = 0;
}
Buffer[2] batch_vbo;
Buffer[2] batch_ibo;
float[] batch_vertices;
ushort[] batch_indices;
Buffer indirect_buffer;
IndirectDraw[] indirect_block;
Buffer id_buffer;
int data_offset = 48;
int data_index;
ubyte[] uniform_block;
struct RenderData
{
Texture texture;
uint material_id;
uint mesh_id;
}
RenderData[] render_list;
uint item_id;
uint[] multi_count;
uint[] multi_offset;
alias Technique = RenderTechnique;
__gshared Technique technique = Technique.simple;
void* data_ptr;
//import ecs_utils.core : RenderTechnique;
void initialize()
{
//this.technique = __ecs_used_technique;
__initialize(this);
}
private static void __initialize_gl(ref Renderer this_)
{
with(this_)
{
//glGenQueries(2, time_queries.ptr);
version(WebAssembly)
{
}
else
{
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &block_max_size);
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &block_alignment);
}
//ubos[0].bufferStorage(1,64*MaxObjects,null);
switch(technique)
{
case Technique.simple:
uniform_block = Mallocator.makeArray!ubyte(64*MaxObjects);
data_ptr = uniform_block.ptr;
data_offset = cast(ushort)((data_offset + block_alignment - 1) & (-cast(int) block_alignment));
break;
case Technique.simple_array:
goto case(Technique.simple);
case Technique.vbo_batch:
batch_vbo[0].create();
batch_ibo[0].create();
batch_vbo[0].bufferData(Buffer.BindTarget.array,16,4*MaxObjects,BufferUsage,null);
batch_ibo[0].bufferData(Buffer.BindTarget.element_array,2,6*MaxObjects,BufferUsage,null);
batch_vbo[1].create();
batch_ibo[1].create();
batch_vbo[1].bufferData(Buffer.BindTarget.array,16,4*MaxObjects,BufferUsage,null);
batch_ibo[1].bufferData(Buffer.BindTarget.element_array,2,6*MaxObjects,BufferUsage,null);
batch_vertices = Mallocator.makeArray!float(16*MaxObjects);
batch_indices = Mallocator.makeArray!ushort(6*MaxObjects);
break;
case Technique.instanced_attrib_divisor:
goto case(Technique.uniform_buffer_indexed);
case Technique.uniform_buffer:
ubos[0].create();
ubos[0].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
ubos[1].create();
ubos[1].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
goto case(Technique.simple);
case Technique.uniform_buffer_indexed:
ubos[0].create();
ubos[0].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
ubos[1].create();
ubos[1].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
uniform_block = Mallocator.makeArray!ubyte(64*MaxObjects);
data_ptr = uniform_block.ptr;
break;
/*case Technique.uniform_buffer_multi_draw:
multi_count = Mallocator.makeArray!uint(992,6);
multi_offset = Mallocator.makeArray!uint(992,0);
{
uint[] indices = Mallocator.makeArray!uint(992);
scope(exit)Mallocator.dispose(indices);
foreach(i;0..992)indices[i]=i;
id_buffer.create();
id_buffer.bufferData(uint.sizeof,992,BufferUsage,indices.ptr);
}
goto case(Technique.uniform_buffer_multi_draw_indirect_arb_draw_parameters);*/
case Technique.uniform_buffer_instanced:
goto case(Technique.uniform_buffer_indexed);
case Technique.uniform_buffer_instanced_mapped_gl2:
ubos[0].create();
ubos[0].bufferData(Buffer.BindTarget.uniform,1,512*MaxObjects,BufferUsage,null);
ubos[0].map(Buffer.BindTarget.uniform);
ubos[1].create();
ubos[1].bufferData(Buffer.BindTarget.uniform,1,512*MaxObjects,BufferUsage,null);
ubos[1].map(Buffer.BindTarget.uniform);
data_ptr = ubos[0].mappedPointer();
break;
case Technique.uniform_buffer_instanced_mapped:
ubos[0].create();
ubos[0].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
ubos[0].map(0, 64*MaxObjects, Buffer.BindTarget.uniform);
ubos[1].create();
ubos[1].bufferData(Buffer.BindTarget.uniform,1,64*MaxObjects,BufferUsage,null);
ubos[1].map(0, 64*MaxObjects, Buffer.BindTarget.uniform);
data_ptr = ubos[0].mappedPointer();
break;
/*case Technique.uniform_buffer_instanced_persistent_mapped:
ubos[0].create();
ubos[0].bufferStorage(1,64*MaxObjects,null,Buffer.StorageFlagBits.write|Buffer.StorageFlagBits.persistent);
ubos[0].map(0, 64*MaxObjects, Buffer.BindTarget.uniform, Buffer.MapFlagBits.write | Buffer.MapFlagBits.persistent | Buffer.MapFlagBits.flush_explict);
data_ptr = ubos[0].mappedPointer();
break;
case Technique.uniform_buffer_instanced_persistent_mapped_coherent:
ubos[0].create();
ubos[0].bufferStorage(1,64*MaxObjects,null,Buffer.StorageFlagBits.write|Buffer.StorageFlagBits.persistent|Buffer.StorageFlagBits.coherent);
ubos[0].map(0, 64*MaxObjects, Buffer.BindTarget.uniform, Buffer.MapFlagBits.write | Buffer.MapFlagBits.persistent | Buffer.MapFlagBits.flush_explict | Buffer.MapFlagBits.coherent);
ubos[1].create();
ubos[1].bufferStorage(1,64*MaxObjects,null,Buffer.StorageFlagBits.write|Buffer.StorageFlagBits.persistent|Buffer.StorageFlagBits.coherent);
ubos[1].map(0, 64*MaxObjects, Buffer.BindTarget.uniform, Buffer.MapFlagBits.write | Buffer.MapFlagBits.persistent | Buffer.MapFlagBits.flush_explict | Buffer.MapFlagBits.coherent);
data_ptr = ubos[0].mappedPointer();
break;
case Technique.ssbo_instanced:
goto case(Technique.uniform_buffer_indexed);
case Technique.uniform_buffer_draw_indirect:
indirect_block = Mallocator.makeArray!IndirectDraw(1);
indirect_buffer.create();
indirect_buffer.bufferData(IndirectDraw.sizeof,1,BufferUsage,indirect_block.ptr);
indirect_buffer.bind(Buffer.BindTarget.indirect);
goto case(Technique.uniform_buffer);
case Technique.uniform_buffer_multi_draw_indirect:
goto case(Technique.uniform_buffer_multi_draw_indirect_arb_draw_parameters);
case Technique.uniform_buffer_multi_draw_indirect_arb_draw_parameters:
indirect_block = Mallocator.makeArray!IndirectDraw(992);
foreach(i;0..992)
{
IndirectDraw* idraw = &indirect_block[i];
idraw.base_instance = i;
}
indirect_buffer.create();
indirect_buffer.bufferData(IndirectDraw.sizeof,992,BufferUsage,indirect_block.ptr);
indirect_buffer.bind(Buffer.BindTarget.indirect);
goto case(Technique.uniform_buffer_indexed);*/
default:break;
}//*/
// if(batching)data_offset = cast(ushort)((data_offset + block_alignment - 1) & (-cast(int) block_alignment));
//data_offset = cast(ushort)((data_offset + block_alignment - 1) & (-cast(int) block_alignment));
/*version(ver4){}
else version(ver5){}
else version(ver6){}
else data_offset = cast(ushort)((data_offset + block_alignment - 1) & (-cast(int) block_alignment));//*/
//data_offset = (data_offset + block_alignment - 1) - data_offset % block_alignment;
render_list = Mallocator.makeArray!RenderData(MaxObjects);
SDL_Log("Uniform block alignment: %u",block_alignment);
SDL_Log("Uniform block max size: %u",block_max_size);
SDL_Log("Data offset: %u",data_offset);
}
}
private static void __initialize_sdl(ref Renderer this_)
{
}
void draw(Texture tex, vec2 pos, vec2 size, vec4 coords, float angle = 0, uint material_id = 0, uint mesh_id = 0)
{
__draw(this,tex,pos,size,coords,angle,material_id,mesh_id);
}
private static void __draw_sdl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id)
{
/*with(this_)
{
SDL_Rect rect = SDL_Rect(cast(int)(coords.x*tex.data.size.x),cast(int)(coords.y*tex.data.size.y),cast(int)(coords.z*tex.data.size.x),cast(int)(coords.w*tex.data.size.y));
SDL_Rect rect2 = SDL_Rect(cast(int)((pos.x-size.x*0.5)),
cast(int)(resolution.y - pos.y - size.y*0.5),
cast(int)(size.x),
cast(int)(size.y));
SDL_RenderCopyEx(sdl_renderer,
tex.data.texture,
&rect,
&rect2,
angle*360,
null,
SDL_FLIP_NONE);
}*/
}
private static void __draw_gl(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id)
{
//import core.stdc.string;
with(this_)
{
//pos += view_pos;
size.x *= view_size.x;
size.y *= view_size.y;
pos.x = pos.x * view_size.x + view_pos.x;
pos.y = pos.y * view_size.y + view_pos.y;//*/
/*version(ver6)void* ptr = ubos[0].mappedPointer() + data_index;
else void* ptr = uniform_block.ptr + data_index;*/
if(data_ptr is null)return;
void* ptr = data_ptr + data_index;
if(angle == 0)
{
*cast(float*)ptr = size.x;
*cast(float*)(ptr+4) = 0;
*cast(float*)(ptr+8) = 0;
*cast(float*)(ptr+12) = size.y;
}
else
{
//import core.stdc.math;
float sinn = sinf(angle);
float coss = cosf(angle);
*cast(float*)ptr = coss * size.x;
*cast(float*)(ptr+4) = -sinn * size.y;
*cast(float*)(ptr+8) = sinn * size.x;
*cast(float*)(ptr+12) = coss * size.y;
}
//memcpy(ptr,);
memcpy(ptr+16,pos.data.ptr,8);
memcpy(ptr+32,coords.data.ptr,16);
//render_list[item_id] = RenderData(tex,material_id,mesh_id);
render_list[item_id].texture = tex;
render_list[item_id].material_id = material_id;
render_list[item_id].mesh_id = mesh_id;
data_index += data_offset;
item_id++;
}
}
private static void __draw_gl_vbo_batch(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id)
{
import ecs_utils.gfx.config;
//import core.stdc.string;
with(this_)
{
//pos += view_pos;
size.x *= view_size.x;
size.y *= view_size.y;
pos.x = pos.x * view_size.x + view_pos.x;
pos.y = pos.y * view_size.y + view_pos.y;//*/
/*void* ptr = data_ptr + data_index;
*cast(float*)ptr = size.x;
*cast(float*)(ptr+4) = 0;
*cast(float*)(ptr+8) = 0;
*cast(float*)(ptr+12) = size.y;
//memcpy(ptr,);
memcpy(ptr+16,pos.data.ptr,8);
memcpy(ptr+32,coords.data.ptr,16);*/
if(angle == 0)
{
batch_vertices[item_id*16] = GfxConfig.meshes[mesh_id].vertices[0] * size.x + pos.x;
batch_vertices[item_id*16+1] = GfxConfig.meshes[mesh_id].vertices[1] * size.y + pos.y;
batch_vertices[item_id*16+4] = GfxConfig.meshes[mesh_id].vertices[4] * size.x + pos.x;
batch_vertices[item_id*16+5] = GfxConfig.meshes[mesh_id].vertices[5] * size.y + pos.y;
batch_vertices[item_id*16+8] = GfxConfig.meshes[mesh_id].vertices[8] * size.x + pos.x;
batch_vertices[item_id*16+9] = GfxConfig.meshes[mesh_id].vertices[9] * size.y + pos.y;
batch_vertices[item_id*16+12] = GfxConfig.meshes[mesh_id].vertices[12] * size.x + pos.x;
batch_vertices[item_id*16+13] = GfxConfig.meshes[mesh_id].vertices[13] * size.y + pos.y;
}
else
{
//import core.stdc.math;
float sinn = sinf(angle);
float coss = cosf(angle);
/*batch_vertices[item_id*16] = GfxConfig.meshes[mesh_id].vertices[0] * size.x;
batch_vertices[item_id*16+1] = GfxConfig.meshes[mesh_id].vertices[1] * size.y;
batch_vertices[item_id*16+4] = GfxConfig.meshes[mesh_id].vertices[4] * size.x;
batch_vertices[item_id*16+5] = GfxConfig.meshes[mesh_id].vertices[5] * size.y;
batch_vertices[item_id*16+8] = GfxConfig.meshes[mesh_id].vertices[8] * size.x;
batch_vertices[item_id*16+9] = GfxConfig.meshes[mesh_id].vertices[9] * size.y;
batch_vertices[item_id*16+12] = GfxConfig.meshes[mesh_id].vertices[12] * size.x;
batch_vertices[item_id*16+13] = GfxConfig.meshes[mesh_id].vertices[13] * size.y;*/
batch_vertices[item_id*16] = (GfxConfig.meshes[mesh_id].vertices[0] * coss + GfxConfig.meshes[mesh_id].vertices[1] * sinn) * size.x + pos.x;
batch_vertices[item_id*16+1] = (GfxConfig.meshes[mesh_id].vertices[1] * coss - GfxConfig.meshes[mesh_id].vertices[0] * sinn) * size.y + pos.y;
batch_vertices[item_id*16+4] = (GfxConfig.meshes[mesh_id].vertices[4] * coss + GfxConfig.meshes[mesh_id].vertices[5] * sinn) * size.x + pos.x;
batch_vertices[item_id*16+5] = (GfxConfig.meshes[mesh_id].vertices[5] * coss - GfxConfig.meshes[mesh_id].vertices[4] * sinn) * size.y + pos.y;
batch_vertices[item_id*16+8] = (GfxConfig.meshes[mesh_id].vertices[8] * coss + GfxConfig.meshes[mesh_id].vertices[9] * sinn) * size.x + pos.x;
batch_vertices[item_id*16+9] = (GfxConfig.meshes[mesh_id].vertices[9] * coss - GfxConfig.meshes[mesh_id].vertices[8] * sinn) * size.y + pos.y;
batch_vertices[item_id*16+12] = (GfxConfig.meshes[mesh_id].vertices[12] * coss + GfxConfig.meshes[mesh_id].vertices[13] * sinn) * size.x + pos.x;
batch_vertices[item_id*16+13] = (GfxConfig.meshes[mesh_id].vertices[13] * coss - GfxConfig.meshes[mesh_id].vertices[12] * sinn) * size.y + pos.y;
}
batch_vertices[item_id*16+2] = GfxConfig.meshes[mesh_id].vertices[2] * coords.z + coords.x;
batch_vertices[item_id*16+3] = GfxConfig.meshes[mesh_id].vertices[3] * coords.w + coords.y;
batch_vertices[item_id*16+6] = GfxConfig.meshes[mesh_id].vertices[6] * coords.z + coords.x;
batch_vertices[item_id*16+7] = GfxConfig.meshes[mesh_id].vertices[7] * coords.w + coords.y;
batch_vertices[item_id*16+10] = GfxConfig.meshes[mesh_id].vertices[10] * coords.z + coords.x;
batch_vertices[item_id*16+11] = GfxConfig.meshes[mesh_id].vertices[11] * coords.w + coords.y;
batch_vertices[item_id*16+14] = GfxConfig.meshes[mesh_id].vertices[14] * coords.z + coords.x;
batch_vertices[item_id*16+15] = GfxConfig.meshes[mesh_id].vertices[15] * coords.w + coords.y;
uint ind_id = item_id % 16_384;
batch_indices[item_id*6] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[0] + ind_id*4);
batch_indices[item_id*6+1] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[1] + ind_id*4);
batch_indices[item_id*6+2] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[2] + ind_id*4);
batch_indices[item_id*6+3] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[3] + ind_id*4);
batch_indices[item_id*6+4] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[4] + ind_id*4);
batch_indices[item_id*6+5] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[5] + ind_id*4);
//render_list[item_id] = RenderData(tex,material_id,mesh_id);
render_list[item_id].texture = tex;
render_list[item_id].material_id = material_id;
render_list[item_id].mesh_id = mesh_id;
//data_index += 1;//data_offset;
item_id++;
}
}
void clear()
{
__clear(this);
}
private static void __clear_sdl(ref Renderer this_)
{
//SDL_RenderClear(this_.sdl_renderer);
}
private static void __clear_gl(ref Renderer this_)
{
glClearColor(0,0,0,0);
glViewport(0,0,this_.resolution.x,this_.resolution.y);
glClear(GL_COLOR_BUFFER_BIT);// | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
void present()
{
__present(this);
}
private static void __present_sdl(ref Renderer this_)
{
//+SDL_RenderPresent(this_.sdl_renderer);
}
private static void __present_gl(ref Renderer this_)
{
glViewport(0,0,this_.resolution.x,this_.resolution.y);
//glEnable(GL_ALPHA_TEST);
//glAlphaFunc(GL_GREATER, 0.01);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
import ecs_utils.gfx.config;
with(this_)
{
bool instanced = false;
bool indirect = false;
bool multi_draw = false;
Buffer.BindTarget buffer_target = Buffer.BindTarget.uniform;
switch(technique)
{
case Technique.simple:
break;
case Technique.simple_array:
break;
case Technique.vbo_batch:
//if(data_index){
batch_vbo[0].bufferSubData(item_id*4*16,0,batch_vertices.ptr);
batch_ibo[0].bufferSubData(item_id*6*2,0,batch_indices.ptr);
batch_vbo[0].bind(Buffer.BindTarget.array);
batch_ibo[0].bind(Buffer.BindTarget.element_array);
glVertexAttribPointer(0,2,GL_FLOAT,false,16,null);
glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)8);//}
break;
case Technique.instanced_attrib_divisor:
ubos[0].bufferSubData(data_index,0,uniform_block.ptr);
ubos[0].bind(Buffer.BindTarget.array);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glVertexAttribPointer(2,4,GL_FLOAT,false,48,null);
glVertexAttribPointer(3,4,GL_FLOAT,false,48,cast(void*)16);
glVertexAttribPointer(4,4,GL_FLOAT,false,48,cast(void*)32);
glVertexAttribDivisor(2,1);
glVertexAttribDivisor(3,1);
glVertexAttribDivisor(4,1);
//ubos[0].bindRange(Buffer.BindTarget.uniform,0,0,block_max_size);
break;
case Technique.uniform_buffer:
//ubos[0].bufferData(1,64*MaxObjects,BufferUsage,null);
/*if(data_index)*/ubos[0].bufferSubData(data_index,0,uniform_block.ptr);
break;
case Technique.uniform_buffer_indexed:
ubos[0].bindRange(Buffer.BindTarget.uniform,0,0,block_max_size);
goto case(Technique.uniform_buffer);
case Technique.uniform_buffer_multi_draw:
id_buffer.bind(Buffer.BindTarget.array);
glEnableVertexAttribArray(2);
glVertexAttribIPointer(2,1,GL_UNSIGNED_INT,cast(uint)uint.sizeof,cast(void*)0);
glVertexAttribDivisor(2,1);
multi_draw = true;
goto case(Technique.uniform_buffer_instanced);
case Technique.uniform_buffer_instanced:
instanced = true;
goto case(Technique.uniform_buffer);
case Technique.uniform_buffer_instanced_mapped_gl2:
instanced = true;
ubos[0].unmap(Buffer.BindTarget.uniform);
break;
case Technique.uniform_buffer_instanced_mapped:
instanced = true;
ubos[0].flush(0,data_index,Buffer.BindTarget.uniform);
ubos[0].unmap(Buffer.BindTarget.uniform);
break;
/*case Technique.uniform_buffer_instanced_persistent_mapped:
instanced = true;
ubos[0].flush(0,data_index,Buffer.BindTarget.uniform);
//glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
break;
case Technique.uniform_buffer_instanced_persistent_mapped_coherent:
instanced = true;
break;
//ubos[0].flush(0,data_index,Buffer.BindTarget.uniform);
//goto case(Technique.uniform_buffer_instanced_mapped);
case Technique.ssbo_instanced:
//buffer_target = Buffer.BindTarget.shader_storage;
ubos[0].bindRange(Buffer.BindTarget.shader_storage,0,0,48*MaxObjects);
goto case(Technique.uniform_buffer_instanced);
case Technique.uniform_buffer_draw_indirect:
goto case(Technique.uniform_buffer);
case Technique.uniform_buffer_multi_draw_indirect:
indirect_buffer.bind(Buffer.BindTarget.array);
glEnableVertexAttribArray(2);
glVertexAttribIPointer(2,1,GL_UNSIGNED_INT,cast(uint)IndirectDraw.sizeof,cast(void*)(4*uint.sizeof));
glVertexAttribDivisor(2,1);
goto case(Technique.uniform_buffer_multi_draw_indirect_arb_draw_parameters);
case Technique.uniform_buffer_multi_draw_indirect_arb_draw_parameters:
indirect = true;
goto case(Technique.uniform_buffer_instanced);*/
default:break;
}
data_index = 0;
int mesh_id = -1;
int material_id = -1;
int ubo_start = -1;
Texture texture;
uint item_ubo_id = 0;
/*Buffer tmpb = ubos[0];
ubos[0] = ubos[1];
ubos[1] = tmpb;
tmpb = batch_vbo[0];
batch_vbo[0] = batch_vbo[1];
batch_vbo[1] = tmpb;
tmpb = batch_ibo[0];
batch_ibo[0] = batch_ibo[1];
batch_ibo[1] = tmpb;//*/
//glFinish();
//glBeginQuery(GL_TIME_ELAPSED, time_queries[0]);
if(technique == Technique.vbo_batch)
{
uint items = item_id/16_384+1;
foreach(i; 0..items)
{
if(material_id != render_list[i].material_id)
{
material_id = render_list[i].material_id;
GfxConfig.materials[material_id].bind();
}
if(texture.data != render_list[i].texture.data)
{
texture.data = render_list[i].texture.data;
render_list[i].texture.bind();
}
uint instance_count = 16_384;
if(i*16_384 > item_id)
{
instance_count = i*16_384 - item_id;
}
/*glVertexAttribPointer(0,2,GL_FLOAT,false,16,cast(void*)(i*16_384*4*16));
glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)(i*16_384*4*16+8));
glDrawElements(GL_TRIANGLES,instance_count*6,GL_UNSIGNED_SHORT,cast(void*)(i*16_384*6*2));*/
glDrawElementsBaseVertex(GL_TRIANGLES,instance_count*6,GL_UNSIGNED_SHORT,cast(void*)(i*16_384*6*2),i*16_384*4);
}
}
else if(technique == Technique.ssbo_instanced || technique == Technique.instanced_attrib_divisor)
{
if(mesh_id != render_list[0].mesh_id)
{
mesh_id = render_list[0].mesh_id;
GfxConfig.meshes[mesh_id].bind();
}
if(material_id != render_list[0].material_id)
{
material_id = render_list[0].material_id;
GfxConfig.materials[material_id].bind();
}
if(texture.data != render_list[0].texture.data)
{
texture.data = render_list[0].texture.data;
render_list[0].texture.bind();
}
glDrawArraysInstanced(GL_TRIANGLE_STRIP,0,4,item_id);
//glDrawElementsInstanced(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,null,item_id);
}
else if(instanced)
{
uint items = item_id/992+1;
foreach(i; 0..items)
{
if(mesh_id != render_list[i].mesh_id)
{
mesh_id = render_list[i].mesh_id;
GfxConfig.meshes[mesh_id].bind();
}
if(material_id != render_list[i].material_id)
{
material_id = render_list[i].material_id;
GfxConfig.materials[material_id].bind();
}
if(texture.data != render_list[i].texture.data)
{
texture.data = render_list[0].texture.data;
render_list[i].texture.bind();
}
ubos[0].bindRange(buffer_target,0,data_index,block_max_size);
uint instance_count = 992;
if(i*992 > item_id)
{
instance_count = i*992 - item_id;
}
/*if(indirect)glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, cast(void*)0, instance_count, 0);
else if(multi_draw)glMultiDrawElements(GL_TRIANGLES,cast(int*)multi_count.ptr,GL_UNSIGNED_SHORT,cast(void**)multi_offset.ptr,instance_count);
//glMultiDrawElementsBaseVertex(GL_TRIANGLES,cast(int*)multi_count.ptr,GL_UNSIGNED_SHORT,cast(void**)multi_offset.ptr,instance_count,cast(int*)multi_offset.ptr);
else */glDrawElementsInstanced(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,null,instance_count);
//glDrawArraysInstanced(GL_TRIANGLES,0,6,instance_count);
data_index += data_offset * 992;
}
}
else
foreach(item; render_list[0..item_id])
{
if(mesh_id != item.mesh_id)
{
mesh_id = item.mesh_id;
GfxConfig.meshes[mesh_id].bind();
}
if(material_id != item.material_id)
{
material_id = item.material_id;
GfxConfig.materials[material_id].bind();
GfxConfig.materials[material_id].pushBindings();
}
if(texture.data != item.texture.data)
{
texture.data = render_list[0].texture.data;
item.texture.bind();
}
switch(technique)
{
case Technique.simple:
/*glUniform4f(0, *cast(float*)&uniform_block[data_index], *cast(float*)&uniform_block[data_index+4], *cast(float*)&uniform_block[data_index+8], *cast(float*)&uniform_block[data_index+12]);
glUniform4f(1, *cast(float*)&uniform_block[data_index+16], *cast(float*)&uniform_block[data_index+20], *cast(float*)&uniform_block[data_index+24], *cast(float*)&uniform_block[data_index+28]);
glUniform4f(2, *cast(float*)&uniform_block[data_index+32], *cast(float*)&uniform_block[data_index+36], *cast(float*)&uniform_block[data_index+40], *cast(float*)&uniform_block[data_index+44]);
*/
GfxConfig.materials[material_id].pushUniforms(&uniform_block[data_index]);break;
case Technique.simple_array:
glUniform4fv(0,12,cast(float*)(uniform_block.ptr+data_index));
break;
case Technique.uniform_buffer:
ubos[0].bindRange(Buffer.BindTarget.uniform,0,data_index,data_offset);
break;
/*case Technique.uniform_buffer_draw_indirect:
ubos[0].bindRange(Buffer.BindTarget.uniform,0,data_index,data_offset);
glDrawElementsIndirect(GL_TRIANGLES,GL_UNSIGNED_SHORT,null);
data_index += data_offset;
continue;*/
case Technique.uniform_buffer_indexed:
if(item_ubo_id >= 992)
{
item_ubo_id = 0;
ubo_start = data_index;
ubos[0].bindRange(Buffer.BindTarget.uniform,0,ubo_start,block_max_size);
}
glUniform1i(0,item_ubo_id++);
break;
default:break;
}//*/
/*version(ver3)ubos[0].bindRange(Buffer.BindTarget.uniform,0,data_index,data_offset);
else version(ver1)
{
glUniform4f(0, *cast(float*)&uniform_block[data_index], *cast(float*)&uniform_block[data_index+4], *cast(float*)&uniform_block[data_index+8], *cast(float*)&uniform_block[data_index+12]);
glUniform4f(1, *cast(float*)&uniform_block[data_index+16], *cast(float*)&uniform_block[data_index+20], *cast(float*)&uniform_block[data_index+24], *cast(float*)&uniform_block[data_index+28]);
glUniform4f(2, *cast(float*)&uniform_block[data_index+32], *cast(float*)&uniform_block[data_index+36], *cast(float*)&uniform_block[data_index+40], *cast(float*)&uniform_block[data_index+44]);
}
else version(ver2)glUniform4fv(0,12,cast(float*)(uniform_block.ptr+data_index));
else version(ver4)
{
if(item_ubo_id >= 992)
{
item_ubo_id = 0;
ubo_start = data_index;
ubos[0].bindRange(Buffer.BindTarget.uniform,0,ubo_start,block_max_size);
}
glUniform1i(0,item_ubo_id++);
}//*/
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,null);
//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
data_index += data_offset;
}
//glEndQuery(GL_TIME_ELAPSED);
//uint tmpq = time_queries[0];
//time_queries[0] = time_queries[1];
//time_queries[1] = tmpq;
/*Buffer tmpb = ubos[0];
ubos[0] = ubos[1];
ubos[1] = tmpb;//*/
data_index = 0;
//data_offset = 0;
item_id = 0;
//SDL_GL_SwapWindow(sdl_window);
//glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
//version(ver6)ubos[0].map(0, 64*MaxObjects, Buffer.BindTarget.uniform);
//ubos[0].map(Buffer.BindTarget.uniform);
switch(technique)
{
case Technique.uniform_buffer_instanced_mapped_gl2:
ubos[0].map(Buffer.BindTarget.uniform);
//data_ptr = ubos[0].mappedPointer();
break;
case Technique.uniform_buffer_instanced_mapped:
ubos[0].map(0, 64*MaxObjects, Buffer.BindTarget.uniform);
//data_ptr = ubos[0].mappedPointer();
break;
default:break;
}
if(ubos[0].data && ubos[0].mappedPointer)
{
data_ptr = ubos[0].mappedPointer;
}
/*switch(technique)
{
case Technique.simple:
case Technique.simple_array:
case Technique.uniform_buffer:
case Technique.uniform_buffer_indexed:
case Technique.uniform_buffer_instanced:
case Technique.uniform_buffer_instanced_mapped:
case Technique.uniform_buffer_instanced_persistent_mapped:
default:break;
}*/
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
/*glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);*/
//glDisable(GL_ALPHA_TEST);
}
void resize(ivec2 size)
{
resolution = size;
dres = vec2(1.0/cast(float)size.x,1.0/cast(float)size.y);
}
void view(vec2 pos, vec2 size)
{
view_pos = pos * size - 1;
view_size = vec2(2/size.x,2/size.y);
sdl_transform = vec4(0,0,1.0/size.x,1.0/size.y);
}
static void function(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, float angle, uint material_id, uint mesh_id) __draw;
static void function(ref Renderer this_) __present;
static void function(ref Renderer this_) __clear;
static void function(ref Renderer this_) __initialize;
static void __loadBackend()
{
//this.technique = __ecs_used_technique;
if(technique == Technique.vbo_batch)__draw = &__draw_gl_vbo_batch;
else __draw = &__draw_gl;
__present = &__present_gl;
__clear = &__clear_gl;
__initialize = &__initialize_gl;
}
}

View file

@ -0,0 +1,171 @@
module ecs_utils.gfx.shader;
import bindbc.sdl;
import ecs.std;
import glad.gl.gl;
//version = ver1;
struct Shader
{
void create() nothrow
{
data = Mallocator.make!Data;
}
bool load(const char[] path) nothrow
{
if(data is null)data = Mallocator.make!Data;
char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
cpath[0..$-1] = path[0..$];
cpath[$-1] = 0;
int ind = cast(int)path.length - 1;
for(;ind>0;ind--)
{
if(path[ind] == '.')break;
}
if(ind < 0)return false;
ind++;
if(ind + 2 > path.length)return false;
char[2] ext = path[ind .. ind + 2];
if(ext[0] == 'v' && ext[1] == 'p')data.type = Type.vertex;
else if(ext[0] == 'f' && ext[1] == 'p')data.type = Type.fragment;
else return false;
SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");//SDL_LoadFile(cpath.ptr,);
if(file)
{
size_t size = cast(size_t)SDL_RWsize(file);
data.code = Mallocator.makeArray!char(size+1);
data.code[$-1] = 0;
SDL_RWread(file,data.code.ptr,size,1);
SDL_RWclose(file);
return true;
}
else return false;
}
bool compile() nothrow
{
switch(data.type)
{
case Type.vertex:
data.gl_handle = glCreateShader(GL_VERTEX_SHADER);
break;
case Type.fragment:
data.gl_handle = glCreateShader(GL_FRAGMENT_SHADER);
break;
default: return false;
}
version(WebAssembly)const char* glsl = "#version 100\n";
else const char* glsl = "#version 450\n";
const char* buffer = data.code.ptr;
char* ver;
version(WebAssembly)ver = cast(char*)"#define ver1 1\n#define GLES\n".ptr;
else ver = cast(char*)"#define ver1 1\n".ptr;
/*switch(__ecs_used_technique)
{
case RenderTechnique.simple:
ver = cast(char*)"#define ver1 1\n".ptr;
break;
case RenderTechnique.simple_array:
ver = cast(char*)"#define ver2 1\n".ptr;
break;
case RenderTechnique.vbo_batch:
ver = cast(char*)"#define ver10 1\n".ptr;
break;
case RenderTechnique.instanced_attrib_divisor:
ver = cast(char*)"#define ver8 1\n".ptr;
break;
case RenderTechnique.uniform_buffer:
ver = cast(char*)"#define ver3 1\n".ptr;
break;
case RenderTechnique.uniform_buffer_indexed:
ver = cast(char*)"#define ver4 1\n".ptr;
break;
case RenderTechnique.uniform_buffer_multi_draw:
goto case(RenderTechnique.uniform_buffer_multi_draw_indirect);
case RenderTechnique.uniform_buffer_instanced:
ver = cast(char*)"#define ver5 1\n".ptr;
break;
case RenderTechnique.uniform_buffer_instanced_mapped_gl2:
goto case(RenderTechnique.uniform_buffer_instanced);
case RenderTechnique.uniform_buffer_instanced_mapped:
goto case(RenderTechnique.uniform_buffer_instanced);
case RenderTechnique.uniform_buffer_instanced_persistent_mapped:
goto case(RenderTechnique.uniform_buffer_instanced);
case RenderTechnique.uniform_buffer_instanced_persistent_mapped_coherent:
goto case(RenderTechnique.uniform_buffer_instanced);
case RenderTechnique.ssbo_instanced:
ver = cast(char*)"#define ver6 1\n".ptr;
break;
case RenderTechnique.uniform_buffer_draw_indirect:
goto case(RenderTechnique.uniform_buffer);
case RenderTechnique.uniform_buffer_multi_draw_indirect:
ver = cast(char*)"#define ver9 1\n".ptr;
break;
case RenderTechnique.uniform_buffer_multi_draw_indirect_arb_draw_parameters:
ver = cast(char*)"#define ver7 1\n".ptr;
break;
default:break;
}*/
/*version(ver1)const char* ver = "#define ver1 1\n";
version(ver2)const char* ver = "#define ver2 1\n";
version(ver3)const char* ver = "#define ver3 1\n";
version(ver4)const char* ver = "#define ver4 1\n";
version(ver5)const char* ver = "#define ver5 1\n";
version(ver6)const char* ver = "#define ver5 1\n";*/
const char*[3] input = [glsl,ver,buffer];
glShaderSource(data.gl_handle,3,input.ptr,null);
glCompileShader(data.gl_handle);
int compile;
glGetShaderiv(data.gl_handle,GL_COMPILE_STATUS,&compile);
if(compile == GL_FALSE)
{
SDL_Log("Shader compile error! %u %s",data.type,glsl);
return false;
}
return true;
}
void destroy() nothrow
{
if(data)
{
if(data.gl_handle)glDeleteShader(data.gl_handle);
Mallocator.dispose(data);
data = null;
}
}
enum Type
{
vertex,
fragment,
geometry
}
struct Data
{
char[] code;
Type type;
uint gl_handle;
}
Data* data;
}

View file

@ -0,0 +1,11 @@
module ecs_utils.gfx.sprite;
import ecs_utils.math.matrix;
import ecs_utils.gfx.mesh_module;
struct sprite
{
MeshModule* mesh;
mat3 matrix;
}

View file

@ -0,0 +1,118 @@
module ecs_utils.gfx.texture;
import bindbc.sdl;
import ecs.std;
import ecs_utils.math.vector;
import glad.gl.gl;
extern(C):
struct Texture
{
void create()
{
data = Mallocator.make!Data;
}
bool load(const char[] path)
{
char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
cpath[0..$-1] = path[0..$];
cpath[$-1] = 0;
return __load(this, cpath);
}
/*static bool __load_sdl(ref Texture this_, const char[] path)
{
import ecs_utils.gfx.renderer;
SDL_Surface* surf = IMG_Load(path.ptr);
if(!surf)return false;
this_.data.size = ivec2(surf.w,surf.h);
this_.data.texture = SDL_CreateTextureFromSurface(Renderer.main_sdl_renderer,surf);
if(!this_.data.texture)return false;
//this_.data.texture = surf;
return true;
}*/
static bool __load_gl(ref Texture this_, const char[] path)
{
SDL_Surface* surf = IMG_Load(path.ptr);
if(!surf)return false;
with(this_)
{
data.size = ivec2(surf.w,surf.h);
data.bpp = surf.format.BytesPerPixel;
data.data = Mallocator.makeArray!ubyte(surf.w*surf.h*surf.format.BytesPerPixel);
data.data[0..$] = (cast(ubyte*)surf.pixels)[0..data.data.length];
glGenTextures(1, &data.gl_handle);
glBindTexture(GL_TEXTURE_2D,data.gl_handle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if(data.bpp == 3)glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,surf.w,surf.h,0,GL_RGB,GL_UNSIGNED_BYTE,data.data.ptr);
else if(data.bpp == 4)glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,surf.w,surf.h,0,GL_RGBA,GL_UNSIGNED_BYTE,data.data.ptr);
else return false;
}
return true;
}
void bind()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, data.gl_handle);
}
void destory()
{
if(data)
{
glDeleteTextures(1, &data.gl_handle);
Mallocator.dispose(data);
data = null;
}
}
static bool function(ref Texture this_, const char[] path) __load;
struct Data
{
ubyte[] data;
ivec2 size;
uint bpp;
union
{
SDL_Texture* texture;
uint gl_handle;
}
}
static void __loadBackend()
{
__load = &__load_gl;
/*switch(backend)
{
case Backend.opengl:__load = &__load_gl;break;
case Backend.sdl:__load = &__load_sdl;break;
default:goto case(Backend.opengl);
}*/
}
Data* data;
}

View file

@ -0,0 +1,64 @@
module ecs_utils.gfx.vertex;
import ecs.std;
struct Vertex
{
void create()
{
data = Mallocator.make!Data;
}
void bind()
{
}
void enableStates()
{
}
void attachBindings(scope Binding[] bindings)
{
data.bindings = Mallocator.makeArray(bindings);
}
enum Type
{
byte_r_snorm,
byte_r_unorm,
byte_rg_snorm,
byte_rg_unorm,
byte_rgb_snorm,
byte_rgb_unorm,
byte_rgba_snorm,
byte_rgba_unorm,
short_r_snorm,
short_r_unorm,
short_rg_snorm,
short_rg_unorm,
short_rgb_snorm,
short_rgb_unorm,
short_rgba_snorm,
short_rgba_unorm,
float_r,
float_rg,
float_rgb,
float_rgba
}
struct Binding
{
Type type;
uint stride;
}
struct Data
{
Binding[] bindings;
uint size;
}
Data* data;
}