-moved C stdlib function definitions to ecs_utils.utils -added function to calculate mix(linear interpolation) and rsqrt(fast inverse sqrt) -added some math to vec2 (length, normalize...) -improved renderer with possibility to use multiple materials (one per block, not perfect solution for parallel compute, but works with some requirements) -added blending support for material (opaque, additive, mixed) -added Android support -added gprahical representation for mouse tools (tool_circle.d) -added initial support for editing template components variables -better Component and Templates listing -added possibility to add/removes components using mouse -move CLocation to game_core.basic and reuse in every test -moved tools code from demos to App (now code is fully separated from demos!) -some improvement and fixes in Snake demo, with additional systems to handle adding and removing entities -added new demo: Particles. By now demo has several particles to spawn and support for attractors and vortexes (calculation is made as every attractor with every entity) -fixed bug with window hover and tools -improved tool behaviour -added new material -now window is always opened as maximized windowed mode -some minor fixes and improvements
219 lines
No EOL
5 KiB
D
219 lines
No EOL
5 KiB
D
module ecs_utils.gfx.material;
|
|
|
|
import bindbc.sdl;
|
|
|
|
import bubel.ecs.std;
|
|
|
|
import ecs_utils.gfx.shader;
|
|
|
|
version(WebAssembly)import glad.gl.gles2;
|
|
else version(Android)import glad.gl.gles2;
|
|
else 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
|
|
{
|
|
final switch(data.blend_mode)
|
|
{
|
|
case BlendMode.mixed:
|
|
glDepthMask(0);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
break;
|
|
case BlendMode.opaque:
|
|
glDepthMask(1);
|
|
glDisable(GL_BLEND);
|
|
break;
|
|
case BlendMode.additive:
|
|
glDepthMask(0);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
//glBlendFunc(GL_ONE, GL_ONE);
|
|
break;
|
|
}
|
|
|
|
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;
|
|
} |