3d rendering

This commit is contained in:
John Alanbrook 2023-11-03 13:31:06 +00:00
parent a854764636
commit 366a20e7ed
9 changed files with 173 additions and 41 deletions

View file

@ -104,6 +104,15 @@ component.sprite.impl = {
Object.freeze(sprite); Object.freeze(sprite);
component.model = Object.copy(component, {
path:"",
_enghook: make_model,
});
component.model.impl = {
set path(x) { cmd(149, this.id, x); },
draw() { cmd(150, this.id); },
};
var sprite = component.sprite; var sprite = component.sprite;
sprite.doc = { sprite.doc = {

View file

@ -6,8 +6,11 @@
#include "stb_ds.h" #include "stb_ds.h"
#include "font.h" #include "font.h"
#include "window.h" #include "window.h"
#include "gameobject.h"
#include "libgen.h"
#include "diffuse.sglsl.h" //#include "diffuse.sglsl.h"
#include "unlit.sglsl.h"
#include "render.h" #include "render.h"
@ -39,18 +42,32 @@ static sg_shader model_shader;
static sg_pipeline model_pipe; static sg_pipeline model_pipe;
void model_init() { void model_init() {
model_shader = sg_make_shader(diffuse_shader_desc(sg_query_backend())); /* model_shader = sg_make_shader(diffuse_shader_desc(sg_query_backend()));
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){ model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader, .shader = model_shader,
.layout = { .layout = {
.attrs = { .attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3, [0].format = SG_VERTEXFORMAT_FLOAT3,
[0].buffer_index = 0, /* position */
[1].format = SG_VERTEXFORMAT_USHORT2N, [1].format = SG_VERTEXFORMAT_USHORT2N,
[1].buffer_index = 1, /* tex coords */ },
[2].format = SG_VERTEXFORMAT_UINT10_N2, },
[2].buffer_index = 2, /* normal */ .index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
*/
model_shader = sg_make_shader(unlit_shader_desc(sg_query_backend()));
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
[1].format = SG_VERTEXFORMAT_USHORT2N,
[1].buffer_index = 1,
}, },
}, },
.index_type = SG_INDEXTYPE_UINT16, .index_type = SG_INDEXTYPE_UINT16,
@ -118,6 +135,7 @@ struct model *MakeModel(const char *path) {
struct model *model = calloc(1, sizeof(*model)); struct model *model = calloc(1, sizeof(*model));
/* TODO: Optimize by grouping by material. One material per draw. */ /* TODO: Optimize by grouping by material. One material per draw. */
YughWarn("Model has %d materials.", data->materials_count); YughWarn("Model has %d materials.", data->materials_count);
const char *dir = dirname(path);
float vs[65535*3]; float vs[65535*3];
uint16_t idxs[65535]; uint16_t idxs[65535];
@ -156,19 +174,21 @@ struct model *MakeModel(const char *path) {
} }
if (primitive.material->has_pbr_metallic_roughness && primitive.material->pbr_metallic_roughness.base_color_texture.texture) { if (primitive.material->has_pbr_metallic_roughness && primitive.material->pbr_metallic_roughness.base_color_texture.texture) {
// YughWarn("Texture is %s.", primitive.material->pbr_metallic_roughness.base_color_texture.texture->image->uri); const char *imp = seprint("%s/%s", dir, primitive.material->pbr_metallic_roughness.base_color_texture.texture->image->uri);
YughInfo("Texture is %s.", imp);
model->meshes[j].bind.fs.images[0] = texture_pullfromfile(primitive.material->pbr_metallic_roughness.base_color_texture.texture->image->uri)->id; model->meshes[j].bind.fs.images[0] = texture_pullfromfile(imp)->id;
free(imp);
} else } else
model->meshes[j].bind.fs.images[0] = texture_pullfromfile("k")->id; model->meshes[j].bind.fs.images[0] = texture_pullfromfile("k")->id;
cgltf_texture *tex; model->meshes[j].bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
if (tex = primitive.material->normal_texture.texture) {
model->meshes[j].bind.fs.images[1] = texture_pullfromfile(tex->image->uri)->id;
} else
model->meshes[j].bind.fs.images[1] = texture_pullfromfile("k")->id;
model->meshes[j].bind.fs.images[2] = ddimg; cgltf_texture *tex;
// if (tex = primitive.material->normal_texture.texture) {
// model->meshes[j].bind.fs.images[1] = texture_pullfromfile(tex->image->uri)->id;
// }// else
// model->meshes[j].bind.fs.images[1] = texture_pullfromfile("k")->id;
int has_norm = 0; int has_norm = 0;
@ -184,6 +204,7 @@ struct model *MakeModel(const char *path) {
switch (attribute.type) { switch (attribute.type) {
case cgltf_attribute_type_position: case cgltf_attribute_type_position:
model->meshes[j].bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ model->meshes[j].bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs, .data.ptr = vs,
.data.size = sizeof(float) * n}); .data.size = sizeof(float) * n});
@ -195,9 +216,9 @@ struct model *MakeModel(const char *path) {
for (int i = 0; i < model->meshes[j].face_count; i++) for (int i = 0; i < model->meshes[j].face_count; i++)
packed_norms[i] = pack_int10_n2(vs + i*3); packed_norms[i] = pack_int10_n2(vs + i*3);
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){ // model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = packed_norms, // .data.ptr = packed_norms,
.data.size = sizeof(uint32_t) * model->meshes[j].face_count}); // .data.size = sizeof(uint32_t) * model->meshes[j].face_count});
free (packed_norms); free (packed_norms);
break; break;
@ -243,10 +264,10 @@ struct model *MakeModel(const char *path) {
norms[i*3+j] = packed_norm; norms[i*3+j] = packed_norm;
} }
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){ // model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = norms, // .data.ptr = norms,
.data.size = sizeof(uint32_t) * model->meshes[j].face_count // .data.size = sizeof(uint32_t) * model->meshes[j].face_count
}); // });
} }
} }
} }
@ -256,7 +277,7 @@ struct model *MakeModel(const char *path) {
HMM_Vec3 eye = {50,10,5}; HMM_Vec3 eye = {50,10,5};
void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm) { void draw_model(struct model *model, HMM_Mat4 amodel) {
HMM_Mat4 proj = HMM_Perspective_RH_ZO(45, (float)mainwin.width / mainwin.height, 0.1, 10000); HMM_Mat4 proj = HMM_Perspective_RH_ZO(45, (float)mainwin.width / mainwin.height, 0.1, 10000);
HMM_Vec3 center = {0.f, 0.f, 0.f}; HMM_Vec3 center = {0.f, 0.f, 0.f};
HMM_Vec3 up = {0.f, 1.f, 0.f}; HMM_Vec3 up = {0.f, 1.f, 0.f};
@ -268,23 +289,13 @@ void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm) {
HMM_Vec3 lp = {1, 1, 1}; HMM_Vec3 lp = {1, 1, 1};
HMM_Vec3 dir_dir = HMM_NormV3(HMM_SubV3(center, dirl_pos)); HMM_Vec3 dir_dir = HMM_NormV3(HMM_SubV3(center, dirl_pos));
HMM_Mat4 m2[4]; vs_p_t vs_p;
m2[0] = view; memcpy(vs_p.vp, view.Elements, sizeof(float)*16);
m2[1] = amodel; memcpy(vs_p.model, amodel.Elements, sizeof(float)*16);
m2[2] = proj; memcpy(vs_p.proj, proj.Elements, sizeof(float)*16);
m2[3] = lsm;
HMM_Vec3 f_ubo[5];
f_ubo[0] = lp;
f_ubo[1] = dir_dir;
f_ubo[2] = eye;
f_ubo[3] = eye;
f_ubo[4] = eye;
sg_apply_pipeline(model_pipe); sg_apply_pipeline(model_pipe);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(m2)); sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vs_p));
sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(f_ubo));
for (int i = 0; i < arrlen(model->meshes); i++) { for (int i = 0; i < arrlen(model->meshes); i++) {
sg_apply_bindings(&model->meshes[i].bind); sg_apply_bindings(&model->meshes[i].bind);
@ -292,3 +303,32 @@ void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm) {
} }
} }
struct drawmodel *make_drawmodel(int go)
{
struct drawmodel *dm = malloc(sizeof(struct drawmodel));
dm->model = NULL;
dm->amodel = HMM_M4D(1.f);
dm->go = go;
return dm;
}
void draw_drawmodel(struct drawmodel *dm)
{
if (!dm->model) return;
struct gameobject *go = id2go(dm->go);
cpVect pos = cpBodyGetPosition(go->body);
HMM_Mat4 scale = HMM_Scale(id2go(dm->go)->scale3);
HMM_Mat4 trans = HMM_M4D(1.f);
trans.Elements[3][2] = -pos.x;
trans.Elements[3][1] = pos.y;
HMM_Mat4 rot = HMM_Rotate_RH(cpBodyGetAngle(go->body), vUP);
/* model matrix = trans * rot * scale */
draw_model(dm->model, HMM_MulM4(trans, HMM_MulM4(rot, scale)));
}
void free_drawmodel(struct drawmodel *dm)
{
free(dm);
}

View file

@ -8,15 +8,24 @@
extern HMM_Vec3 eye; extern HMM_Vec3 eye;
struct shader; struct shader;
/* A single mesh */
struct mesh { struct mesh {
sg_bindings bind; sg_bindings bind;
uint32_t face_count; uint32_t face_count;
}; };
/* A collection of meshes which create a full figure */
struct model { struct model {
struct mesh *meshes; struct mesh *meshes;
}; };
/* A model with draw information */
struct drawmodel {
struct model *model;
HMM_Mat4 amodel;
int go;
};
/* Get the model at a path, or create and return if it doesn't exist */ /* Get the model at a path, or create and return if it doesn't exist */
struct model *GetExistingModel(const char *path); struct model *GetExistingModel(const char *path);
@ -28,7 +37,11 @@ void loadmodel(struct model *model);
void model_init(); void model_init();
void draw_model(struct model *model, HMM_Mat4 amodel, HMM_Mat4 lsm); void draw_model(struct model *model, HMM_Mat4 amodel);
void draw_models(struct model *model, struct shader *shader); void draw_models(struct model *model, struct shader *shader);
struct drawmodel *make_drawmodel(int go);
void draw_drawmodel(struct drawmodel *dm);
void free_drawmodel(struct drawmodel *dm);
#endif #endif

View file

@ -542,6 +542,11 @@ static inline HMM_Vec3 HMM_V3(float X, float Y, float Z) {
return Result; return Result;
} }
static inline HMM_Vec3 HMM_V3i(float i)
{
return (HMM_Vec3){i,i,i};
}
static inline HMM_Vec4 HMM_V4(float X, float Y, float Z, float W) { static inline HMM_Vec4 HMM_V4(float X, float Y, float Z, float W) {
HMM_Vec4 Result; HMM_Vec4 Result;

View file

@ -650,6 +650,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 36: case 36:
id2go(js2int(argv[1]))->scale = js2number(argv[2]); id2go(js2int(argv[1]))->scale = js2number(argv[2]);
id2go(js2int(argv[1]))->scale3 = HMM_V3i(js2number(argv[2]));
gameobject_apply(id2go(js2int(argv[1]))); gameobject_apply(id2go(js2int(argv[1])));
cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body); cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body);
break; break;
@ -1123,6 +1124,14 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 148: case 148:
ret = color2js(id2sprite(js2int(argv[1]))->color); ret = color2js(id2sprite(js2int(argv[1]))->color);
break; break;
case 149:
((struct drawmodel *)js2ptr(argv[1]))->model = GetExistingModel(js2str(argv[2]));
break;
case 150:
draw_drawmodel(js2ptr(argv[1]));
break;
} }
if (str) if (str)
@ -1491,6 +1500,15 @@ JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCon
return circleval; return circleval;
} }
JSValue duk_make_model(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
{
int go = js2int(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
return ret;
}
JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int cmd = js2int(argv[0]); int cmd = js2int(argv[0]);
struct phys2d_circle *circle = js2ptr(argv[1]); struct phys2d_circle *circle = js2ptr(argv[1]);
@ -1675,6 +1693,7 @@ void ffi_load() {
DUK_FUNC(cmd_poly2d, 6) DUK_FUNC(cmd_poly2d, 6)
DUK_FUNC(make_edge2d, 3) DUK_FUNC(make_edge2d, 3)
DUK_FUNC(cmd_edge2d, 6) DUK_FUNC(cmd_edge2d, 6)
DUK_FUNC(make_model,2);
DUK_FUNC(make_timer, 3) DUK_FUNC(make_timer, 3)
DUK_FUNC(cmd_points, 5); DUK_FUNC(cmd_points, 5);

View file

@ -144,6 +144,7 @@ static void gameobject_setpickcolor(struct gameobject *go) {
int MakeGameobject() { int MakeGameobject() {
struct gameobject go = { struct gameobject go = {
.scale = 1.f, .scale = 1.f,
.scale3 = (HMM_Vec3){1.f,1.f,1.f},
.bodytype = CP_BODY_TYPE_STATIC, .bodytype = CP_BODY_TYPE_STATIC,
.mass = 1.f, .mass = 1.f,
.next = -1, .next = -1,

View file

@ -7,6 +7,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include "quickjs/quickjs.h" #include "quickjs/quickjs.h"
#include "HandmadeMath.h"
struct shader; struct shader;
struct sprite; struct sprite;
@ -16,6 +17,7 @@ struct gameobject {
cpBodyType bodytype; cpBodyType bodytype;
int next; int next;
float scale; float scale;
HMM_Vec3 scale3;
float mass; float mass;
float f; /* friction */ float f; /* friction */
float e; /* elasticity */ float e; /* elasticity */

View file

@ -3471,6 +3471,50 @@ _SOKOL_PRIVATE void _sapp_macos_run(const sapp_desc* desc) {
// set the application dock icon as early as possible, otherwise // set the application dock icon as early as possible, otherwise
// the dummy icon will be visible for a short time // the dummy icon will be visible for a short time
sapp_set_icon(&_sapp.desc.icon); sapp_set_icon(&_sapp.desc.icon);
NSMenu* menu_bar = [[NSMenu alloc] init];
NSMenuItem* app_menu_item = [[NSMenuItem alloc] init];
[menu_bar addItem:app_menu_item];
NSApp.mainMenu = menu_bar;
NSMenu* app_menu = [[NSMenu alloc] init];
NSString* window_title_as_nsstring = [NSString stringWithUTF8String:desc->window_title];
NSString* quit_title = [@"Quit " stringByAppendingString:window_title_as_nsstring];
NSMenuItem* quit_menu_item = [[NSMenuItem alloc]
initWithTitle:quit_title
action:@selector(terminate:)
keyEquivalent:@"q"];
NSString* hide_title = [@"Hide " stringByAppendingString:window_title_as_nsstring];
NSMenuItem* hide_menu_item = [[NSMenuItem alloc]
initWithTitle:hide_title
action:@selector(hide:)
keyEquivalent:@"h"];
NSMenuItem* hide_others_item = [[NSMenuItem alloc]
initWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"];
[hide_others_item setKeyEquivalentModifierMask: NSEventModifierFlagOption];
NSMenuItem* show_all_item = [[NSMenuItem alloc]
initWithTitle:@"Show All"
action:@selector(unhideAllApplications:)
keyEquivalent:@""];
[app_menu addItem:hide_menu_item];
[app_menu addItem:hide_others_item];
[app_menu addItem:show_all_item];
[app_menu addItem:[NSMenuItem separatorItem]];
[app_menu addItem:quit_menu_item];
app_menu_item.submenu = app_menu;
_SAPP_OBJC_RELEASE(window_title_as_nsstring);
_SAPP_OBJC_RELEASE(app_menu);
_SAPP_OBJC_RELEASE(app_menu_item);
_SAPP_OBJC_RELEASE(menu_bar);
_sapp.macos.app_dlg = [[_sapp_macos_app_delegate alloc] init]; _sapp.macos.app_dlg = [[_sapp_macos_app_delegate alloc] init];
NSApp.delegate = _sapp.macos.app_dlg; NSApp.delegate = _sapp.macos.app_dlg;

View file

@ -8,7 +8,6 @@ out vec3 normal;
out vec3 frag_pos; out vec3 frag_pos;
out vec4 frag_pos_light; out vec4 frag_pos_light;
uniform vs_p { uniform vs_p {
uniform mat4 vp; uniform mat4 vp;
uniform mat4 model; uniform mat4 model;