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);
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;
sprite.doc = {

View file

@ -6,8 +6,11 @@
#include "stb_ds.h"
#include "font.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"
@ -39,18 +42,14 @@ static sg_shader model_shader;
static sg_pipeline model_pipe;
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){
.shader = model_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
[0].buffer_index = 0, /* position */
[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,
@ -58,6 +57,24 @@ void model_init() {
.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,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
}
struct model *GetExistingModel(const char *path) {
@ -118,6 +135,7 @@ struct model *MakeModel(const char *path) {
struct model *model = calloc(1, sizeof(*model));
/* TODO: Optimize by grouping by material. One material per draw. */
YughWarn("Model has %d materials.", data->materials_count);
const char *dir = dirname(path);
float vs[65535*3];
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) {
// 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
model->meshes[j].bind.fs.images[0] = texture_pullfromfile("k")->id;
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;
model->meshes[j].bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
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;
@ -184,6 +204,7 @@ struct model *MakeModel(const char *path) {
switch (attribute.type) {
case cgltf_attribute_type_position:
model->meshes[j].bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
.data.size = sizeof(float) * n});
@ -194,10 +215,10 @@ struct model *MakeModel(const char *path) {
packed_norms = malloc(model->meshes[j].face_count * sizeof(uint32_t));;
for (int i = 0; i < model->meshes[j].face_count; i++)
packed_norms[i] = pack_int10_n2(vs + i*3);
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = packed_norms,
.data.size = sizeof(uint32_t) * model->meshes[j].face_count});
// model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
// .data.ptr = packed_norms,
// .data.size = sizeof(uint32_t) * model->meshes[j].face_count});
free (packed_norms);
break;
@ -209,7 +230,7 @@ struct model *MakeModel(const char *path) {
packed_coords = malloc(model->meshes[j].face_count * 2 * sizeof(unsigned short));
for (int i = 0; i < model->meshes[j].face_count*2; i++)
packed_coords[i] = pack_short_texcoord(vs[i]);
model->meshes[j].bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
.data.size = sizeof(unsigned short) * 2 * model->meshes[j].face_count});
@ -243,10 +264,10 @@ struct model *MakeModel(const char *path) {
norms[i*3+j] = packed_norm;
}
model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = norms,
.data.size = sizeof(uint32_t) * model->meshes[j].face_count
});
// model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
// .data.ptr = norms,
// .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};
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_Vec3 center = {0.f, 0.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 dir_dir = HMM_NormV3(HMM_SubV3(center, dirl_pos));
HMM_Mat4 m2[4];
m2[0] = view;
m2[1] = amodel;
m2[2] = proj;
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;
vs_p_t vs_p;
memcpy(vs_p.vp, view.Elements, sizeof(float)*16);
memcpy(vs_p.model, amodel.Elements, sizeof(float)*16);
memcpy(vs_p.proj, proj.Elements, sizeof(float)*16);
sg_apply_pipeline(model_pipe);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(m2));
sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(f_ubo));
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vs_p));
for (int i = 0; i < arrlen(model->meshes); i++) {
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;
struct shader;
/* A single mesh */
struct mesh {
sg_bindings bind;
uint32_t face_count;
};
/* A collection of meshes which create a full figure */
struct model {
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 */
struct model *GetExistingModel(const char *path);
@ -28,7 +37,11 @@ void loadmodel(struct model *model);
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);
struct drawmodel *make_drawmodel(int go);
void draw_drawmodel(struct drawmodel *dm);
void free_drawmodel(struct drawmodel *dm);
#endif

View file

@ -542,6 +542,11 @@ static inline HMM_Vec3 HMM_V3(float X, float Y, float Z) {
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) {
HMM_Vec4 Result;

View file

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

View file

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

View file

@ -7,6 +7,7 @@
#include <stdbool.h>
#include <stdio.h>
#include "quickjs/quickjs.h"
#include "HandmadeMath.h"
struct shader;
struct sprite;
@ -16,6 +17,7 @@ struct gameobject {
cpBodyType bodytype;
int next;
float scale;
HMM_Vec3 scale3;
float mass;
float f; /* friction */
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
// the dummy icon will be visible for a short time
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];
NSApp.delegate = _sapp.macos.app_dlg;

View file

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