-Demos:
*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:
parent
73f2aa6861
commit
cb7609dcaa
82 changed files with 11188 additions and 413 deletions
134
demos/utils/source/ecs_utils/gfx/buffer.d
Normal file
134
demos/utils/source/ecs_utils/gfx/buffer.d
Normal 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;
|
||||
}
|
||||
102
demos/utils/source/ecs_utils/gfx/config.d
Normal file
102
demos/utils/source/ecs_utils/gfx/config.d
Normal 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);
|
||||
}
|
||||
}
|
||||
198
demos/utils/source/ecs_utils/gfx/material.d
Normal file
198
demos/utils/source/ecs_utils/gfx/material.d
Normal 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;
|
||||
}
|
||||
121
demos/utils/source/ecs_utils/gfx/mesh.d
Normal file
121
demos/utils/source/ecs_utils/gfx/mesh.d
Normal 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;
|
||||
}
|
||||
12
demos/utils/source/ecs_utils/gfx/mesh_module.d
Normal file
12
demos/utils/source/ecs_utils/gfx/mesh_module.d
Normal 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;
|
||||
}
|
||||
29
demos/utils/source/ecs_utils/gfx/render_list.d
Normal file
29
demos/utils/source/ecs_utils/gfx/render_list.d
Normal 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;
|
||||
}
|
||||
}
|
||||
817
demos/utils/source/ecs_utils/gfx/renderer.d
Normal file
817
demos/utils/source/ecs_utils/gfx/renderer.d
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
171
demos/utils/source/ecs_utils/gfx/shader.d
Normal file
171
demos/utils/source/ecs_utils/gfx/shader.d
Normal 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;
|
||||
}
|
||||
11
demos/utils/source/ecs_utils/gfx/sprite.d
Normal file
11
demos/utils/source/ecs_utils/gfx/sprite.d
Normal 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;
|
||||
}
|
||||
118
demos/utils/source/ecs_utils/gfx/texture.d
Normal file
118
demos/utils/source/ecs_utils/gfx/texture.d
Normal 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;
|
||||
}
|
||||
64
demos/utils/source/ecs_utils/gfx/vertex.d
Normal file
64
demos/utils/source/ecs_utils/gfx/vertex.d
Normal 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;
|
||||
}
|
||||
508
demos/utils/source/ecs_utils/imgui_bind.d
Normal file
508
demos/utils/source/ecs_utils/imgui_bind.d
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
module ecs_utils.imgui_bind;
|
||||
|
||||
import bindbc.sdl;
|
||||
import cimgui.cimgui;
|
||||
|
||||
version(WebAssembly)
|
||||
{
|
||||
extern(C):
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version = null);
|
||||
void ImGui_ImplOpenGL3_Shutdown();
|
||||
void ImGui_ImplOpenGL3_NewFrame();
|
||||
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
|
||||
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
|
||||
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
|
||||
void ImGui_ImplSDL2_Shutdown();
|
||||
void ImGui_ImplSDL2_NewFrame(SDL_Window* window);
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
|
||||
}
|
||||
else :
|
||||
|
||||
import bindbc.sdl;
|
||||
|
||||
import glad.gl.gl;
|
||||
|
||||
import cimgui.cimgui;
|
||||
|
||||
extern(C):
|
||||
|
||||
SDL_Window* g_Window;
|
||||
ulong g_Time;
|
||||
bool[3] g_MousePressed;
|
||||
SDL_Cursor*[ImGuiMouseCursor_COUNT] g_MouseCursors;
|
||||
char* g_ClipboardTextData;
|
||||
GLuint g_FontTexture = 0;
|
||||
|
||||
const (char)* ImGuiImplSDL2GetClipboardText(void*)
|
||||
{
|
||||
if (g_ClipboardTextData)
|
||||
SDL_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = SDL_GetClipboardText();
|
||||
return g_ClipboardTextData;
|
||||
}
|
||||
|
||||
void ImGuiImplSDL2SetClipboardText(void*, const char* text)
|
||||
{
|
||||
SDL_SetClipboardText(text);
|
||||
}
|
||||
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (event.wheel.x > 0) io.MouseWheelH += 1;
|
||||
if (event.wheel.x < 0) io.MouseWheelH -= 1;
|
||||
if (event.wheel.y > 0) io.MouseWheel += 1;
|
||||
if (event.wheel.y < 0) io.MouseWheel -= 1;
|
||||
return true;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (event.button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true;
|
||||
return true;
|
||||
}
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
ImGuiIO_AddInputCharactersUTF8(io,event.text.text.ptr);
|
||||
return true;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
int key = event.key.keysym.scancode;
|
||||
//IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
|
||||
io.KeysDown[key] = (event.type == SDL_KEYDOWN);
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
return true;
|
||||
}
|
||||
default:break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGuiImplSDL2Init(SDL_Window* window)
|
||||
{
|
||||
g_Window = window;
|
||||
|
||||
// Setup back-end capabilities flags
|
||||
ImGuiIO* io = igGetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
io.BackendPlatformName = "imgui_impl_sdl";
|
||||
|
||||
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
|
||||
io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_RETURN2;
|
||||
io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
|
||||
io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
|
||||
io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
|
||||
io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
|
||||
io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
|
||||
|
||||
io.SetClipboardTextFn = &ImGuiImplSDL2SetClipboardText;
|
||||
io.GetClipboardTextFn = &ImGuiImplSDL2GetClipboardText;
|
||||
io.ClipboardUserData = null;
|
||||
|
||||
g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
||||
g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
|
||||
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
|
||||
g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
|
||||
|
||||
//#ifdef _WIN32
|
||||
version(WebAssembly)
|
||||
{
|
||||
|
||||
}
|
||||
else version(Windows)
|
||||
{
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version_);
|
||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||
io.ImeWindowHandle = wmInfo.info.win.window;
|
||||
}
|
||||
//#else
|
||||
//(void)window;
|
||||
//#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiImplSDL2InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
|
||||
{
|
||||
//(void)sdl_gl_context; // Viewport branch will need this.
|
||||
return ImGuiImplSDL2Init(window);
|
||||
}
|
||||
|
||||
void ImGuiImplSDL2Shutdown()
|
||||
{
|
||||
g_Window = null;
|
||||
|
||||
// Destroy last known clipboard data
|
||||
if (g_ClipboardTextData)
|
||||
SDL_free(g_ClipboardTextData);
|
||||
g_ClipboardTextData = null;
|
||||
|
||||
// Destroy SDL mouse cursors
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
SDL_FreeCursor(g_MouseCursors[cursor_n]);
|
||||
//memset(g_MouseCursors, 0, sizeof(g_MouseCursors));
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
|
||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
SDL_WarpMouseInWindow(g_Window, cast(int)io.MousePos.x, cast(int)io.MousePos.y);
|
||||
else
|
||||
io.MousePos = ImVec2(-float.max, -float.max);
|
||||
|
||||
int mx, my;
|
||||
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
|
||||
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & (SDL_PRESSED<<(SDL_BUTTON_LEFT-1))) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & (SDL_PRESSED<<(SDL_BUTTON_RIGHT-1))) != 0;
|
||||
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & (SDL_PRESSED<<(SDL_BUTTON_MIDDLE-1))) != 0;
|
||||
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
|
||||
|
||||
//#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
|
||||
/*SDL_Window* focused_window = SDL_GetKeyboardFocus();
|
||||
if (g_Window == focused_window)
|
||||
{
|
||||
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
|
||||
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
|
||||
int wx, wy;
|
||||
SDL_GetWindowPosition(focused_window, &wx, &wy);
|
||||
SDL_GetGlobalMouseState(&mx, &my);
|
||||
mx -= wx;
|
||||
my -= wy;
|
||||
io.MousePos = ImVec2((float)mx, (float)my);
|
||||
}
|
||||
|
||||
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
|
||||
// The function is only supported from SDL 2.0.4 (released Jan 2016)
|
||||
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
|
||||
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
|
||||
//#else*/
|
||||
if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS)
|
||||
io.MousePos = ImVec2(cast(float)mx, cast(float)my);
|
||||
//#endif
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||
return;
|
||||
|
||||
ImGuiMouseCursor imgui_cursor = igGetMouseCursor();
|
||||
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
SDL_ShowCursor(SDL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
SDL_ShowCursor(SDL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDL2_UpdateGamepads()
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
//memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||
return;
|
||||
|
||||
// Get gamepad
|
||||
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
|
||||
if (!game_controller)
|
||||
{
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
return;
|
||||
}
|
||||
|
||||
// Update gamepad inputs
|
||||
/*#define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
|
||||
#define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
|
||||
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
|
||||
MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
|
||||
MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
|
||||
MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
|
||||
MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
|
||||
MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
|
||||
MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
|
||||
MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
|
||||
MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
|
||||
MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||
MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||
MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
|
||||
MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
|
||||
MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
|
||||
MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
|
||||
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
#undef MAP_BUTTON
|
||||
#undef MAP_ANALOG*/
|
||||
}
|
||||
|
||||
|
||||
private long frequency;
|
||||
|
||||
void ImGuiImplSDL2NewFrame(SDL_Window* window)
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
assert(ImFontAtlas_IsBuilt(io.Fonts), "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||
io.DisplaySize = ImVec2(cast(float)w, cast(float)h);
|
||||
if (w > 0 && h > 0)
|
||||
io.DisplayFramebufferScale = ImVec2(cast(float)display_w / w, cast(float)display_h / h);
|
||||
|
||||
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
|
||||
frequency = SDL_GetPerformanceFrequency();
|
||||
long current_time = SDL_GetPerformanceCounter();
|
||||
io.DeltaTime = g_Time > 0 ? cast(float)(cast(double)(current_time - g_Time) / frequency) : cast(float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
ImGui_ImplSDL2_UpdateMousePosAndButtons();
|
||||
ImGui_ImplSDL2_UpdateMouseCursor();
|
||||
|
||||
// Update game controllers (if enabled and available)
|
||||
ImGui_ImplSDL2_UpdateGamepads();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool ImGuiImplOpenGL2Init()
|
||||
{
|
||||
// Setup back-end capabilities flags
|
||||
ImGuiIO* io = igGetIO();
|
||||
io.BackendRendererName = "imgui_impl_opengl2";
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGuiImplOpenGL2Shutdown()
|
||||
{
|
||||
ImGuiImplOpenGL2DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGuiImplOpenGL2NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGuiImplOpenGL2CreateDeviceObjects();
|
||||
}
|
||||
|
||||
static void ImGuiImplOpenGL2SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
||||
{
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
//glDisable(GL_LIGHTING);
|
||||
//glDisable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
||||
// you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function:
|
||||
// GLint last_program;
|
||||
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
// glUseProgram(0);
|
||||
// ImGui_ImplOpenGL2_RenderDrawData(...);
|
||||
// glUseProgram(last_program)
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data.DisplayPos (top left) to draw_data.DisplayPos+data_data.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
glViewport(0, 0, cast(GLsizei)fb_width, cast(GLsizei)fb_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(draw_data.DisplayPos.x, draw_data.DisplayPos.x + draw_data.DisplaySize.x, draw_data.DisplayPos.y + draw_data.DisplaySize.y, draw_data.DisplayPos.y, -1.0f, +1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||
void ImGuiImplOpenGL2RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = cast(int)(draw_data.DisplaySize.x * draw_data.FramebufferScale.x);
|
||||
int fb_height = cast(int)(draw_data.DisplaySize.y * draw_data.FramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
|
||||
// Backup GL state
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint[2] last_polygon_mode; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode.ptr);
|
||||
GLint[4] last_viewport; glGetIntegerv(GL_VIEWPORT, last_viewport.ptr);
|
||||
GLint[4] last_scissor_box; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box.ptr);
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
|
||||
// Setup desired GL state
|
||||
ImGuiImplOpenGL2SetupRenderState(draw_data, fb_width, fb_height);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data.DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = draw_data.FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data.CmdListsCount; n++)
|
||||
{
|
||||
ImDrawList* cmd_list = draw_data.CmdLists[n];
|
||||
ImDrawVert* vtx_buffer = cmd_list.VtxBuffer.Data;
|
||||
ImDrawIdx* idx_buffer = cmd_list.IdxBuffer.Data;
|
||||
glVertexPointer(2, GL_FLOAT, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.pos.offsetof));
|
||||
glTexCoordPointer(2, GL_FLOAT, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.uv.offsetof));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, ImDrawVert.sizeof, cast(const GLvoid*)(cast(const char*)vtx_buffer + ImDrawVert.col.offsetof));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list.CmdBuffer.Data[cmd_i];
|
||||
if (pcmd.UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
/*if (pcmd.UserCallback == &ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
|
||||
else*/
|
||||
pcmd.UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec4 clip_rect = ImVec4(0,0,0,0);
|
||||
clip_rect.x = (pcmd.ClipRect.x - clip_off.x) * clip_scale.x;
|
||||
clip_rect.y = (pcmd.ClipRect.y - clip_off.y) * clip_scale.y;
|
||||
clip_rect.z = (pcmd.ClipRect.z - clip_off.x) * clip_scale.x;
|
||||
clip_rect.w = (pcmd.ClipRect.w - clip_off.y) * clip_scale.y;
|
||||
|
||||
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
|
||||
{
|
||||
// Apply scissor/clipping rectangle
|
||||
glScissor(cast(int)clip_rect.x, cast(int)(fb_height - clip_rect.w), cast(int)(clip_rect.z - clip_rect.x), cast(int)(clip_rect.w - clip_rect.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, cast(GLuint)pcmd.TextureId);
|
||||
glDrawElements(GL_TRIANGLES, cast(GLsizei)pcmd.ElemCount, ImDrawIdx.sizeof == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||
}
|
||||
}
|
||||
idx_buffer += pcmd.ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore modified GL state
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, cast(GLuint)last_texture);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
glPolygonMode(GL_FRONT, cast(GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, cast(GLenum)last_polygon_mode[1]);
|
||||
glViewport(last_viewport[0], last_viewport[1], cast(GLsizei)last_viewport[2], cast(GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], cast(GLsizei)last_scissor_box[2], cast(GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
bool ImGuiImplOpenGL2CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO* io = igGetIO();
|
||||
ubyte* pixels;
|
||||
int width, height;
|
||||
int bpp;
|
||||
ImFontAtlas_GetTexDataAsRGBA32(io.Fonts, &pixels, &width, &height, &bpp); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts.TexID = cast(ImTextureID)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGuiImplOpenGL2DestroyFontsTexture()
|
||||
{
|
||||
if (g_FontTexture)
|
||||
{
|
||||
ImGuiIO* io = igGetIO();
|
||||
glDeleteTextures(1, &g_FontTexture);
|
||||
io.Fonts.TexID = null;
|
||||
g_FontTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiImplOpenGL2CreateDeviceObjects()
|
||||
{
|
||||
return ImGuiImplOpenGL2CreateFontsTexture();
|
||||
}
|
||||
|
||||
void ImGuiImplOpenGL2DestroyDeviceObjects()
|
||||
{
|
||||
ImGuiImplOpenGL2DestroyFontsTexture();
|
||||
}
|
||||
95
demos/utils/source/ecs_utils/imgui_styles.d
Normal file
95
demos/utils/source/ecs_utils/imgui_styles.d
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
module ecs_utils.imgui_styles;
|
||||
|
||||
import cimgui.cimgui;
|
||||
|
||||
void setStyle(uint index)
|
||||
{
|
||||
ImGuiStyle * style = igGetStyle();
|
||||
ImVec4 * colors = style.Colors.ptr;
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
igStyleColorsClassic(style);
|
||||
break;
|
||||
case 1:
|
||||
igStyleColorsDark(style);
|
||||
break;
|
||||
case 2:
|
||||
igStyleColorsLight(style);
|
||||
break;
|
||||
case 3:
|
||||
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
style.PopupRounding = 3;
|
||||
|
||||
style.WindowPadding = ImVec2(4, 4);
|
||||
style.FramePadding = ImVec2(6, 4);
|
||||
style.ItemSpacing = ImVec2(6, 2);
|
||||
|
||||
style.ScrollbarSize = 18;
|
||||
|
||||
style.WindowBorderSize = 1;
|
||||
style.ChildBorderSize = 1;
|
||||
style.PopupBorderSize = 1;
|
||||
style.FrameBorderSize = 0;
|
||||
|
||||
style.WindowRounding = 3;
|
||||
style.ChildRounding = 3;
|
||||
style.FrameRounding = 4;
|
||||
style.ScrollbarRounding = 2;
|
||||
style.GrabRounding = 4;
|
||||
break;
|
||||
default:
|
||||
igStyleColorsClassic(style);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
183
demos/utils/source/ecs_utils/utils.d
Normal file
183
demos/utils/source/ecs_utils/utils.d
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
module ecs_utils.utils;
|
||||
|
||||
extern(C):
|
||||
|
||||
int randomRange(int min, int max)
|
||||
{
|
||||
int range = max - min;
|
||||
return rand() % range - min;
|
||||
}
|
||||
|
||||
float randomf()
|
||||
{
|
||||
const float scale = 1.0 / 32_767.0;
|
||||
return cast(float)(rand() & 0x007FFF) * scale;
|
||||
}
|
||||
|
||||
/*
|
||||
float randomRangef(float min, float max)
|
||||
{
|
||||
//int range = max - min;
|
||||
return rand()%4096;
|
||||
}*/
|
||||
|
||||
extern(C) int printf(scope const char* format, ...) @nogc nothrow @system;
|
||||
extern(C) int rand();
|
||||
|
||||
version(D_BetterC)
|
||||
{
|
||||
version(LDC)
|
||||
{
|
||||
extern(C) bool _d_enter_cleanup(void*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
extern(C) void _d_leave_cleanup(void*)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
extern(C) void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen, size_t elemsz)
|
||||
{
|
||||
import ldc.intrinsics : llvm_memcpy;
|
||||
llvm_memcpy!size_t(dst, src, dstlen * elemsz, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
version(WebAssembly)
|
||||
{
|
||||
|
||||
enum EMSCRIPTEN_RESULT_SUCCESS = 0;
|
||||
enum EMSCRIPTEN_RESULT_DEFERRED = 1;
|
||||
enum EMSCRIPTEN_RESULT_NOT_SUPPORTED = -1;
|
||||
enum EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED = -2;
|
||||
enum EMSCRIPTEN_RESULT_INVALID_TARGET = -3;
|
||||
enum EMSCRIPTEN_RESULT_UNKNOWN_TARGET = -4;
|
||||
enum EMSCRIPTEN_RESULT_INVALID_PARAM = -5;
|
||||
enum EMSCRIPTEN_RESULT_FAILED = -6;
|
||||
enum EMSCRIPTEN_RESULT_NO_DATA = -7;
|
||||
enum EMSCRIPTEN_RESULT_TIMED_OUT = -8;
|
||||
|
||||
alias EMSCRIPTEN_FULLSCREEN_SCALE = int;
|
||||
enum EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT = 0;
|
||||
enum EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH = 1;
|
||||
enum EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT = 2;
|
||||
enum EMSCRIPTEN_FULLSCREEN_SCALE_CENTER = 3;
|
||||
|
||||
alias EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE = int;
|
||||
enum EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE = 0;
|
||||
enum EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF = 1;
|
||||
enum EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF = 2;
|
||||
|
||||
alias EMSCRIPTEN_FULLSCREEN_FILTERING = int;
|
||||
enum EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT = 0;
|
||||
enum EMSCRIPTEN_FULLSCREEN_FILTERING_NEAREST = 1;
|
||||
enum EMSCRIPTEN_FULLSCREEN_FILTERING_BILINEAR = 2;
|
||||
|
||||
alias em_canvasresized_callback_func = extern(C) bool function (int eventType, const void *reserved, void *userData);
|
||||
|
||||
struct EmscriptenFullscreenStrategy {
|
||||
EMSCRIPTEN_FULLSCREEN_SCALE scaleMode;
|
||||
EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE canvasResolutionScaleMode;
|
||||
EMSCRIPTEN_FULLSCREEN_FILTERING filteringMode;
|
||||
em_canvasresized_callback_func canvasResizedCallback;
|
||||
void *canvasResizedCallbackUserData;
|
||||
}
|
||||
|
||||
extern (C) const (char)* emscripten_result_to_string(int result) {
|
||||
if (result == EMSCRIPTEN_RESULT_SUCCESS) return "EMSCRIPTEN_RESULT_SUCCESS";
|
||||
if (result == EMSCRIPTEN_RESULT_DEFERRED) return "EMSCRIPTEN_RESULT_DEFERRED";
|
||||
if (result == EMSCRIPTEN_RESULT_NOT_SUPPORTED) return "EMSCRIPTEN_RESULT_NOT_SUPPORTED";
|
||||
if (result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED) return "EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED";
|
||||
if (result == EMSCRIPTEN_RESULT_INVALID_TARGET) return "EMSCRIPTEN_RESULT_INVALID_TARGET";
|
||||
if (result == EMSCRIPTEN_RESULT_UNKNOWN_TARGET) return "EMSCRIPTEN_RESULT_UNKNOWN_TARGET";
|
||||
if (result == EMSCRIPTEN_RESULT_INVALID_PARAM) return "EMSCRIPTEN_RESULT_INVALID_PARAM";
|
||||
if (result == EMSCRIPTEN_RESULT_FAILED) return "EMSCRIPTEN_RESULT_FAILED";
|
||||
if (result == EMSCRIPTEN_RESULT_NO_DATA) return "EMSCRIPTEN_RESULT_NO_DATA";
|
||||
return "Unknown EMSCRIPTEN_RESULT!";
|
||||
}
|
||||
|
||||
extern (C) alias em_callback_func = void function();
|
||||
extern (C) alias em_arg_callback_func = void function(void*);
|
||||
extern (C) void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop);
|
||||
extern (C) void emscripten_set_main_loop_arg(em_arg_callback_func func, void *arg, int fps, int simulate_infinite_loop);
|
||||
extern (C) int emscripten_set_main_loop_timing(int mode, int value);
|
||||
extern (C) void emscripten_cancel_main_loop();
|
||||
extern (C) int emscripten_request_fullscreen_strategy(const char *target, bool deferUntilInEventHandler, const EmscriptenFullscreenStrategy *fullscreenStrategy);
|
||||
extern (C) int emscripten_enter_soft_fullscreen(const char *target, const EmscriptenFullscreenStrategy *fullscreenStrategy);
|
||||
|
||||
alias int time_t;
|
||||
alias int clockid_t;
|
||||
enum CLOCK_REALTIME = 0;
|
||||
|
||||
struct timespec
|
||||
{
|
||||
time_t tv_sec;
|
||||
int tv_nsec;
|
||||
}
|
||||
|
||||
extern(C) int clock_gettime(clockid_t, timespec*) @nogc nothrow @system;
|
||||
|
||||
struct Time
|
||||
{
|
||||
|
||||
|
||||
static long getUSecTime()
|
||||
{
|
||||
time_t time;
|
||||
timespec spec;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &spec);
|
||||
|
||||
//time = spec.tv_sec;
|
||||
return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000;//time / 1000_000;
|
||||
|
||||
/*LARGE_INTEGER time, freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&time);
|
||||
return time.QuadPart / (freq.QuadPart / 1000_000);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
else version(Windows)
|
||||
{
|
||||
import core.stdc.stdio : printf;
|
||||
import core.sys.windows.windows;
|
||||
struct Time
|
||||
{
|
||||
static long getUSecTime()
|
||||
{
|
||||
LARGE_INTEGER time, freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&time);
|
||||
return time.QuadPart / (freq.QuadPart / 1000_000);
|
||||
}
|
||||
}
|
||||
}
|
||||
else version(Posix)
|
||||
{
|
||||
import core.stdc.stdio : printf;
|
||||
import core.sys.posix.time;
|
||||
struct Time
|
||||
{
|
||||
static long getUSecTime()
|
||||
{
|
||||
time_t time;
|
||||
timespec spec;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &spec);
|
||||
|
||||
//time = spec.tv_sec;
|
||||
return spec.tv_sec * 1000_000 + spec.tv_nsec / 1000;//time / 1000_000;
|
||||
|
||||
/*LARGE_INTEGER time, freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&time);
|
||||
return time.QuadPart / (freq.QuadPart / 1000_000);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue