circle shader

This commit is contained in:
2025-01-11 16:43:17 -06:00
parent 4753ef3a9b
commit 034ef8ac94
25 changed files with 172 additions and 156 deletions

View File

@@ -12,8 +12,6 @@ function make_point_obj(o, p) {
};
};
function sprite_addbucket(sprite) {
if (!sprite.image) return;
var layer = sprite.z_value();

View File

@@ -10,10 +10,11 @@ var cur = {};
cur.images = [];
cur.samplers = [];
var tbuffer;
function full_upload(buffers)
{
var cmds = render._main.acquire_cmd_buffer();
render._main.upload(cmds, buffers);
tbuffer = render._main.upload(cmds, buffers, tbuffer);
cmds.submit();
}
@@ -116,13 +117,8 @@ sprite_pipeline.target = {
var rect_pipeline = Object.create(sprite_pipeline)
rect_pipeline.fragment = "rectangle.frag"
var line_pipeline = Object.create(rect_pipeline);
line_pipeline.primitive = "line"
var dbgline_pipeline = Object.create(base_pipeline);
dbgline_pipeline.vertex = "dbgline.vert.hlsl"
dbgline_pipeline.fragment = "dbgline.frag.hlsl"
dbgline_pipeline.primitive = "line"
var circle_pipeline = Object.create(sprite_pipeline)
circle_pipeline.fragment = "circle.frag"
function get_pipeline_ubo_slot(pipeline, name)
{
@@ -519,7 +515,6 @@ try{
cmds.push_debug_group("draw")
for (var group of render_queue) {
var add;
if (pipeline != group.pipeline) {
pipeline = group.pipeline;
bind_pipeline(pass, pipeline);
@@ -545,40 +540,13 @@ try{
img.sampler = std_sampler;
bind_mat(pass,pipeline,{diffuse:img});
}
pass.draw_indexed(group.num_indices, 1, group.first_index, 0, 0);
}
cmds.pop_debug_group()
cmds.push_debug_group("sprites")
var buckets = component.sprite_buckets();
bind_pipeline(pass,sprite_pipeline);
var camslot = get_pipeline_ubo_slot(pipeline, 'TransformBuffer');
if (typeof camslot !== 'undefined')
cmds.hud(camera.size, camslot);
modelslot = get_pipeline_ubo_slot(pipeline, "model");
if (typeof modelslot !== 'undefined') {
var ubo = ubo_obj_to_array(pipeline, 'model', sprite_model_ubo);
cmds.push_vertex_uniform_data(modelslot, ubo);
}
for (var l in buckets) {
var layer = buckets[l];
for (var img in layer) {
var sparray = layer[img];
if (sparray.length === 0) continue;
ss.baseinstance = render.make_sprite_ssbo(sparray, sprite_ssbo);
render.use_mat(ss);
render.draw(shape.quad, sprite_ssbo, sparray.length);
}
}
cmds.pop_debug_group()
cmds.push_debug_group("hud")
pipeline = undefined;
for (var group of hud_queue) {
if (pipeline != group.pipeline) {
pipeline = group.pipeline;
@@ -695,11 +663,20 @@ prosperon.camera.screen2hud = function(pos)
return cam;
}
prosperon.camera.screen2world = function(pos)
{
var hud = this.screen2hud(pos);
hud.x += this.transform.pos.x - this.size.x/2;
hud.y += this.transform.pos.y - this.size.y/2;
return hud;
}
var swaps = [];
function gpupresent()
{
try{
var cmds = render._main.acquire_cmd_buffer();
render_queue = sprites_to_queue(component.sprite_buckets()).concat(render_queue);
render_camera(cmds, prosperon.camera);
} catch(e) { console.error(e); } finally {
var swapchain_tex = cmds.acquire_swapchain();
@@ -766,21 +743,31 @@ render.draw_hud = true;
render.draw_gui = true;
render.draw_gizmos = true;
function draw_sprites()
function sprites_to_queue(sprites, ysort = false)
{
var buckets = component.sprite_buckets();
if (buckets.length === 0) return;
for (var l in buckets) {
var layer = buckets[l];
for (var img in layer) {
var sparray = layer[img];
if (sparray.length === 0) continue;
var geometry = render._main.make_sprite_mesh(sparray);
var queue = [];
for (var l in sprites) {
var layer = sprites[l]
for (var image in layer) {
var sparr = layer[image]
if (sparr.length === 0) continue;
var mesh = render._main.make_sprite_mesh(sparr);
queue.push({
type: 'geometry',
mesh,
pipeline:sprite_pipeline,
image:sparr[0].image,
first_index:0,
num_indices:mesh.num_indices
});
}
}
return queue;
}
render.circle = function render_circle(pos, radius, color, inner_radius = 1) {
render.circle = function render_circle(pos, radius, color, inner_radius = 1, pipeline = circle_pipeline) {
render.rectangle({x:pos.x, y:pos.y, width:radius*2,height:radius*2}, color, circle_pipeline);
return;
if (inner_radius >= 1) inner_radius = inner_radius / radius;
else if (inner_radius < 0) inner_radius = 1.0;
@@ -806,9 +793,15 @@ render.poly = function render_poly(points, color, transform) {
};
// render.line has uv and can be texture mapped; dbg_line is hardware standard lines
render.line = function render_line(points, color = Color.white, thickness = 1, pipeline = line_pipeline) {
var mesh = os.make_line_prim(points);
// render._main.line(points, color);
render.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) {
var mesh = os.make_line_prim(points,thickness, 0,0,color);
current_queue.push({
type: 'geometry',
mesh,
pipeline,
first_index:0,
num_indices:mesh.num_indices
});
};
render.dbg_line = function(points, color = Color.white)
@@ -1039,8 +1032,6 @@ render.get_font = function get_font(path,size)
return fontcache[fontstr];
}
render.doc = "Draw shapes in screen space.";
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
@@ -1252,16 +1243,19 @@ prosperon.process = function process() {
var dt = now - last_frame_time;
if (dt < waittime) os.sleep(waittime-dt);
last_frame_time = profile.now();
try {
layout.newframe();
// check for hot reloading
if (dmon) dmon.poll(dmon_cb);
var dt = last_frame_time - frame_t;
frame_t = last_frame_time;
try {
game.engine_input(e => {
prosperon[e.type]?.(e);
});
} catch(e) { console.error(e); }
try { prosperon.appupdate(dt); } catch(e) { console.error(e) }
input.procdown();
@@ -1288,13 +1282,10 @@ try {
try { prosperon.draw(); } catch(e) { console.error(e) }
current_queue = hud_queue;
try { prosperon.hud(); } catch(e) { console.error(e) }
try { imgui_fn(); } catch(e) { console.error(e) }
render._main.present();
} catch(e) {
console.error(e)
}
tracy.end_frame();
};

10
shaders/circle.frag.hlsl Normal file
View File

@@ -0,0 +1,10 @@
#include "common/pixel.hlsl"
#include "common/sdf.hlsl"
// Pixel shader main function
float4 main(PSInput input) : SV_TARGET
{
float4 color = input.color;
color.a = abs(sdf.circle(input.uv, 1)) <= 0.05 ? 1:0 ;
return color;
}

41
shaders/common/sdf.hlsl Normal file
View File

@@ -0,0 +1,41 @@
struct SDF {
float dot2(float2 a)
{
return dot(a,a);
}
float circle(float2 p, float r)
{
return length(p) - r;
}
// p = uv point
// b = width,height
// r = roundedness of the 4 corners
float rounded_box(float2 p, float2 b, float4 r)
{
r.xy = (p.x>0.0)?r.xy : r.zw;
r.x = (p.y>0.0)?r.x : r.y;
float2 q = abs(p)-b+r.x;
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x;
}
float box(float2 p, float2 b)
{
float2 d = abs(p)-b;
return length(max(d,0)) + min(max(d.x,d.y),0);
}
float heart( in float2 p )
{
p.x = abs(p.x);
if( p.y+p.x>1.0 )
return sqrt(dot2(p-float2(0.25,0.75))) - sqrt(2.0)/4.0;
return sqrt(min(dot2(p-float2(0.00,1.00)), dot2(p-0.5*max(p.x+p.y,0.0)))) * sign(p.x-p.y);
}
};
SDF sdf;

View File

@@ -8,42 +8,48 @@ mkdir -p reflection
# Vertex shaders
for filename in *.vert.hlsl; do
if [ -f "$filename" ]; then echo "compiling ${filename}"
# Produce SPIR-V
dxc -spirv -T vs_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
# Produce DXIL + PDB
dxc -Zi -Fd "dxil/${filename/.hlsl/.pdb}" -T vs_6_0 -Fo "dxil/${filename/.hlsl/.dxil}" "$filename"
# Convert SPIR-V to Metal Shader Language
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
# Generate reflection
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
if [ -f "$filename" ]; then
outSpv="spv/${filename/.hlsl/.spv}"
outDxil="dxil/${filename/.hlsl/.dxil}"
outMsl="msl/${filename/.hlsl/.msl}"
outReflect="reflection/${filename/.hlsl/.json}"
# Produce SPIR-V
dxc -spirv -T vs_6_0 -Fo "$outSpv" "$filename"
# Produce DXIL with embedded debug info (example)
shadercross "$filename" -o "$outDxil"
# dxc -Zi -Qembed_debug -T vs_6_0 -Fo "$outDxil" "$filename"
# Convert SPIR-V to Metal Shader Language
spirv-cross "$outSpv" --msl > "$outMsl"
# Generate reflection
spirv-cross "$outSpv" --reflect > "$outReflect"
fi
done
# Fragment shaders
for filename in *.frag.hlsl; do
if [ -f "$filename" ]; then echo "compiling ${filename}"
# Produce SPIR-V
dxc -spirv -T ps_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
# Produce DXIL + PDB
dxc -Zi -Fd "dxil/${filename/.hlsl/.pdb}" -T ps_6_0 -Fo "dxil/${filename/.hlsl/.dxil}" "$filename"
# Convert SPIR-V to Metal Shader Language
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
# Generate reflection
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
if [ -f "$filename" ]; then
outSpv="spv/${filename/.hlsl/.spv}"
outDxil="dxil/${filename/.hlsl/.dxil}"
outMsl="msl/${filename/.hlsl/.msl}"
outReflect="reflection/${filename/.hlsl/.json}"
dxc -spirv -T ps_6_0 -Fo "$outSpv" "$filename"
shadercross "$filename" -o "$outDxil"
# dxc -Zi -Qembed_debug -T ps_6_0 -Fo "$outDxil" "$filename"
spirv-cross "$outSpv" --msl > "$outMsl"
spirv-cross "$outSpv" --reflect > "$outReflect"
fi
done
# Compute shaders
for filename in *.comp.hlsl; do
if [ -f "$filename" ]; then echo "compiling ${filename}"
# Produce SPIR-V
dxc -spirv -T cs_6_0 -Fo "spv/${filename/.hlsl/.spv}" "$filename"
# Produce DXIL + PDB
dxc -Zi -Fd "dxil/${filename/.hlsl/.pdb}" -T cs_6_0 -Fo "dxil/${filename/.hlsl/.dxil}" "$filename"
# Convert SPIR-V to Metal Shader Language
spirv-cross "spv/${filename/.hlsl/.spv}" --msl > "msl/${filename/.hlsl/.msl}"
# Generate reflection
spirv-cross "spv/${filename/.hlsl/.spv}" --reflect > "reflection/${filename/.hlsl/.json}"
if [ -f "$filename" ]; then
outSpv="spv/${filename/.hlsl/.spv}"
outDxil="dxil/${filename/.hlsl/.dxil}"
outMsl="msl/${filename/.hlsl/.msl}"
outReflect="reflection/${filename/.hlsl/.json}"
dxc -spirv -T cs_6_0 -Fo "$outSpv" "$filename"
dxc -Zi -Qembed_debug -T cs_6_0 -Fo "$outDxil" "$filename"
spirv-cross "$outSpv" --msl > "$outMsl"
spirv-cross "$outSpv" --reflect > "$outReflect"
fi
done

View File

@@ -1,3 +1,5 @@
#include "common/common.hlsl"
struct VSOutput
{
float4 pos : SV_POSITION;

View File

@@ -17,5 +17,6 @@ VSOutput main(VSInput input)
VSOutput output;
output.pos = mul(float4(input.pos, 1.0f), world_to_projection);
output.color = input.color;
output.color.r = frac(time);
return output;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -34,8 +34,10 @@ struct main0_in
vertex main0_out main0(main0_in in [[stage_in]], constant type_TransformBuffer& TransformBuffer [[buffer(0)]])
{
main0_out out = {};
float4 _28 = in.in_var_color;
_28.x = fract(TransformBuffer.time);
out.gl_Position = float4(in.in_var_pos, 1.0) * TransformBuffer.world_to_projection;
out.out_var_COLOR = in.in_var_color;
out.out_var_COLOR = _28;
return out;
}

View File

@@ -6,7 +6,7 @@
}
],
"types" : {
"_6" : {
"_7" : {
"name" : "type.TransformBuffer",
"members" : [
{
@@ -101,7 +101,7 @@
],
"ubos" : [
{
"type" : "_6",
"type" : "_7",
"name" : "type.TransformBuffer",
"block_size" : 316,
"set" : 1,

View File

@@ -1,35 +0,0 @@
struct SDF {
float circle(vec2 p, float r)
{
return length(p) - r;
}
// p = uv point
// b = width,height
// r = roundedness of the 4 corners
float rounded_box(vec2 p, vec2 b, vec4 r)
{
r.xy = (p.x>0.0)?r.xy : r.zw;
r.x = (p.y>0.0)?r.x : r.y;
vec2 q = abs(p)-b+r.x;
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x;
}
float box(vec2 p, vec2 b)
{
vec2 d = abs(p)-b;
return length(max(d,0)) + min(max(d.x,d.y),0);
}
float heart( in vec2 p )
{
p.x = abs(p.x);
if( p.y+p.x>1.0 )
return sqrt(dot2(p-vec2(0.25,0.75))) - sqrt(2.0)/4.0;
return sqrt(min(dot2(p-vec2(0.00,1.00)), dot2(p-0.5*max(p.x+p.y,0.0)))) * sign(p.x-p.y);
}
}
SDF sdf;

View File

@@ -1,7 +1,2 @@
#include "common/vertex.hlsl"
// Vertex shader
output vertex(output i)
{
return i;
}

Binary file not shown.

View File

@@ -280,6 +280,7 @@ JSValue make_gpu_buffer(JSContext *js, void *data, size_t size, int type, int el
tstack[0] = JS_NewArrayBuffer(js,data,size,free_gpu_buffer, NULL, 0);
JSValue ret = JS_NewTypedArray(js, 3, tstack, type);
JS_SetPropertyStr(js,ret,"stride", number2js(js,typed_array_bytes(type)*elements));
JS_SetPropertyStr(js,ret,"elen", number2js(js,typed_array_bytes(type)));
JS_SetPropertyStr(js,ret,"index", JS_NewBool(js,index));
JS_FreeValue(js,tstack[0]);
return ret;
@@ -1154,6 +1155,7 @@ static inline HMM_Mat3 js2transform_mat3(JSContext *js, JSValue v)
return transform2mat3(T);
}
// Unpacks a typed array javascript object. If it has a gpu property, returns it, too. Otherwise, if requested, makes one.
void *gpu_buffer_unpack(JSContext *js, SDL_GPUDevice *device, JSValue buffer, size_t *size, void **send_data, SDL_GPUBuffer **send_gpu)
{
size_t o, len, bytes, msize;
@@ -1162,12 +1164,12 @@ void *gpu_buffer_unpack(JSContext *js, SDL_GPUDevice *device, JSValue buffer, si
JS_FreeValue(js,buf);
if (size) *size = msize;
if (send_gpu) {
JSValue idx = JS_GetPropertyStr(js,buffer, "index");
Uint32 usage = JS_ToBool(js,idx) ? SDL_GPU_BUFFERUSAGE_INDEX : SDL_GPU_BUFFERUSAGE_VERTEX;
JS_FreeValue(js,idx);
JSValue gpu = JS_GetPropertyStr(js,buffer,"gpu");
*send_gpu = js2SDL_GPUBuffer(js,gpu);
if (!*send_gpu) {
JSValue idx = JS_GetPropertyStr(js,buffer, "index");
Uint32 usage = JS_ToBool(js,idx) ? SDL_GPU_BUFFERUSAGE_INDEX : SDL_GPU_BUFFERUSAGE_VERTEX;
JS_FreeValue(js,idx);
*send_gpu = SDL_CreateGPUBuffer(device, &(SDL_GPUBufferCreateInfo) { .usage=usage,.size=msize});
if (!*send_gpu) printf("COULDN'T MAKE GPU BUFFER: %s\n", SDL_GetError());
JS_SetPropertyStr(js, buffer, "gpu", SDL_GPUBuffer2js(js,*send_gpu));
@@ -1393,7 +1395,7 @@ int js_print_exception(JSContext *js, JSValue v)
const char *name = JS_ToCString(js, js_getpropertystr(js,ex, "name"));
const char *msg = JS_ToCString(js, js_getpropertystr(js,ex, "message"));
const char *stack = JS_ToCString(js, js_getpropertystr(js,ex, "stack"));
printf("%s :: %s\n%s", name, msg, stack);
printf("%s :: %s\n%s\n", name, msg, stack);
JS_FreeCString(js, name);
JS_FreeCString(js, msg);
@@ -2594,7 +2596,9 @@ JSC_CCALL(game_engine_input,
gui_input(&event);
#endif
JSValue e = event2js(js,event);
JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
js_print_exception(js,ret);
JS_FreeValue(js,ret);
}
)
@@ -3400,16 +3404,14 @@ JSC_CCALL(gpu_load_texture,
SDL_Surface *surf = js2SDL_Surface(js, argv[0]);
if (!surf) return JS_ThrowReferenceError(js, "Surface was not a surface.");
int compression_level = 0;
if (argc > 1)
compression_level = JS_ToBool(js,argv[1]);
compression_level = 2; // use DXT highqual if available
int compression_level = js2number(js,argv[1]);
if (compression_level < 0) compression_level = 0;
if (compression_level > 2) compression_level = 2;
int dofree = 0;
SDL_PixelFormat sfmt = surf->format;
const SDL_PixelFormatDetails *pdetails = SDL_GetPixelFormatDetails(sfmt);
SDL_PixelFormat sfmt = surf->format;
const SDL_PixelFormatDetails *pdetails = SDL_GetPixelFormatDetails(sfmt);
if (!pdetails) {
// If we can't get pixel format details, fall back to converting to RGBA8888
@@ -3588,8 +3590,8 @@ SDL_GPUCopyPass *copypass = SDL_BeginGPUCopyPass(uploadcmd);
SDL_UploadToGPUTexture(
copypass,
&(SDL_GPUTextureTransferInfo) {
.transfer_buffer = tex_buffer,
.offset = 0
.transfer_buffer = tex_buffer,
.offset = 0
},
&(SDL_GPUTextureRegion) {
.texture = tex,
@@ -4360,7 +4362,11 @@ JSC_CCALL(renderpass_bind_index_buffer,
SDL_GPUBufferBinding bind;
bind.offset = 0;
gpu_buffer_unpack(js,global_gpu,argv[0], NULL, NULL, &bind.buffer);
SDL_BindGPUIndexBuffer(pass,&bind,SDL_GPU_INDEXELEMENTSIZE_16BIT);
int elen;
JSValue b = argv[0];
JS_GETPROP(js, elen, b, elen, number)
SDL_BindGPUIndexBuffer(pass,&bind,elen == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT);
)
JSC_CCALL(renderpass_end,
@@ -4624,7 +4630,6 @@ JSC_CCALL(cmd_camera,
data.viewport_size = (HMM_Vec2){0.5,0.5};
data.viewport_offset = (HMM_Vec2){0,0};
data.time = SDL_GetTicksNS() / 1000000000.0f;
SDL_PushGPUVertexUniformData(cmds, js2number(js,argv[1]), &data, sizeof(data));
)
@@ -6136,14 +6141,14 @@ JSC_SCALL(os_gltf_skin,
cgltf_free(data);
)
JSC_CCALL(os_make_color_buffer,
int count = js2number(js,argv[1]);
HMM_Vec4 color = js2vec4(js,argv[0]);
HMM_Vec4 *buffer = malloc(sizeof(HMM_Vec4) * count);
for (int i = 0; i < count; i++)
memcpy(buffer+i, &color, sizeof(HMM_Vec4));
ret = make_gpu_buffer(js,buffer,sizeof(HMM_Vec4)*count,JS_TYPED_ARRAY_FLOAT32,4,0,0);
)
JSValue make_color_buffer(JSContext *js, colorf c, int verts)
{
HMM_Vec4 *colordata = malloc(sizeof(*colordata)*verts);
for (int i = 0; i < verts; i++)
colordata[i] = c;
return make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, JS_TYPED_ARRAY_FLOAT32, 4, 0, 0);
}
JSC_CCALL(os_make_line_prim,
JSValue prim = JS_NewObject(js);
@@ -6177,6 +6182,7 @@ JSC_CCALL(os_make_line_prim,
JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), JS_TYPED_ARRAY_FLOAT32,2,1,0));
JS_SetPropertyStr(js,prim,"vertices", number2js(js,m->num_vertices));
JS_SetPropertyStr(js,prim,"color",make_color_buffer(js,js2color(js,argv[4]), m->num_vertices));
JS_SetPropertyStr(js,prim,"num_indices", number2js(js,m->num_triangles*3));
JS_SetPropertyStr(js,prim,"first_index", number2js(js,0));
@@ -6401,7 +6407,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, turbulence, 4),
MIST_FUNC_DEF(os, model_buffer, 1),
MIST_FUNC_DEF(os, fbm, 4),
MIST_FUNC_DEF(os, make_color_buffer, 2),
MIST_FUNC_DEF(os, ridge, 5),
MIST_FUNC_DEF(os, perlin, 3),
MIST_FUNC_DEF(os, rectpack, 3),
@@ -6421,7 +6426,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_cursor, 1),
MIST_FUNC_DEF(os, make_font, 2),
MIST_FUNC_DEF(os, make_transform, 0),
MIST_FUNC_DEF(os, make_line_prim, 4),
MIST_FUNC_DEF(os, make_line_prim, 5),
MIST_FUNC_DEF(os, make_cylinder, 2),
MIST_FUNC_DEF(os, make_cone, 2),
MIST_FUNC_DEF(os, make_disk, 2),