diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 32db9cc..c0e9c7f 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -24,12 +24,40 @@ cpSpace *space = NULL; float phys2d_gravity = -50.f; -float dbg_color[3] = {0.836f, 1.f, 0.45f}; -float trigger_color[3] = {0.278f, 0.953f, 1.f}; -float disabled_color[3] = {0.58f, 0.58f, 0.58f}; -float dynamic_color[3] = {255 / 255, 70 / 255, 46 / 255}; -float kinematic_color[3] = {255 / 255, 206 / 255, 71 / 255}; -float static_color[3] = {0.22f, 0.271f, 1.f}; +struct rgba color_white = {255,255,255,255}; +struct rgba color_black = {0,0,0,255}; + +struct rgba dbg_color = { + .r = 0.836*255, + .g = 255, + .b = 0.45*255, + .a = 255 +}; +struct rgba trigger_color = { + .r = 0.278*255, + .g = 0.953*255, + .b = 255, + .a = 255 +}; +struct rgba disabled_color = { + .r = 0.58*255, + .g = 0.58*255, + .b = 0.58*255, + .a = 255 +}; +struct rgba dynamic_color = { + .r = 255, + .g = 70, + .b = 46, + .a = 255 +}; +struct rgba kinematic_color = {255, 206, 71, 255}; +struct rgba static_color = { + .r = 0.22*255, + .g = 0.271*255, + .b = 255, + .a = 255 +}; unsigned int category_masks[32]; @@ -37,20 +65,6 @@ void set_cat_mask(int cat, unsigned int mask) { category_masks[cat] = mask; } -void color2float(struct color color, float *fcolor) { - fcolor[0] = (float)color.r / 255; - fcolor[1] = (float)color.g / 255; - fcolor[2] = (float)color.b / 255; -} - -struct color float2color(float *fcolor) { - struct color new; - new.r = fcolor[0] * 255; - new.b = fcolor[1] * 255; - new.g = fcolor[2] * 255; - return new; -} - cpShape *phys2d_query_pos(cpVect pos) { cpShapeFilter filter; filter.group = CP_NO_GROUP; @@ -153,7 +167,7 @@ int cpshape_enabled(cpShape *c) { return 1; } -float *shape_outline_color(cpShape *shape) { +struct rgba shape_outline_color(cpShape *shape) { switch (cpBodyGetType(cpShapeGetBody(shape))) { case CP_BODY_TYPE_DYNAMIC: return dynamic_color; @@ -168,7 +182,7 @@ float *shape_outline_color(cpShape *shape) { return static_color; } -float *shape_color(cpShape *shape) { +struct rgba shape_color(cpShape *shape) { if (!cpshape_enabled(shape)) return disabled_color; if (cpShapeGetSensor(shape)) return trigger_color; @@ -176,13 +190,8 @@ float *shape_color(cpShape *shape) { return dbg_color; } -struct color shape_color_s(cpShape *shape) { - float *c = shape_color(shape); - struct color col; - col.r = c[0] * 255; - col.g = c[1] * 255; - col.b = c[2] * 255; - return col; +struct rgba shape_color_s(cpShape *shape) { + return shape_color(shape); } void phys2d_init() { @@ -416,7 +425,7 @@ void phys2d_applypoly(struct phys2d_poly *poly) { cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape)); } void phys2d_dbgdrawpoly(struct phys2d_poly *poly) { - float *color = shape_color(poly->shape.shape); + struct rgba color = shape_color(poly->shape.shape); if (arrlen(poly->points) >= 3) { int n = cpPolyShapeGetCount(poly->shape.shape); @@ -549,7 +558,7 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge) { drawpoints[i] = bodytransformpoint(cpShapeGetBody(edge->shapes[0]), drawpoints[i]); } - draw_edge(drawpoints, arrlen(edge->points), shape_color_s(edge->shapes[0]), edge->thickness * 2); + draw_edge(drawpoints, arrlen(edge->points), shape_color_s(edge->shapes[0]), edge->thickness * 2, 0,0); draw_points(drawpoints, arrlen(edge->points), 2, kinematic_color); } diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 120b7c4..c3cc076 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -10,12 +10,24 @@ extern float phys2d_gravity; extern int physOn; extern cpSpace *space; -extern float dbg_color[3]; -extern float trigger_color[3]; -extern float disabled_color[3]; -extern float dynamic_color[3]; -extern float kinematic_color[3]; -extern float static_color[3]; +struct rgba { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; +}; + +extern struct rgba color_white; +extern struct rgba color_black; + + +extern struct rgba dbg_color; +extern struct rgba trigger_color; +extern struct rgba disabled_color; +extern struct rgba dynamic_color; +extern struct rgba kinematic_color; +extern struct rgba static_color; + struct phys2d_shape { cpShape *shape; @@ -126,15 +138,7 @@ int shape_is_enabled(struct phys2d_shape *shape); void shape_set_sensor(struct phys2d_shape *shape, int sensor); int shape_get_sensor(struct phys2d_shape *shape); -struct color { - unsigned char r; - unsigned char g; - unsigned char b; -}; - -void color2float(struct color, float *fcolor); -struct color float2color(float *fcolor); -struct color shape_color_s(cpShape *shape); +struct rgba shape_color_s(cpShape *shape); void shape_gui(struct phys2d_shape *shape); void phys2d_setup_handlers(int go); diff --git a/source/engine/debug/debugdraw.c b/source/engine/debug/debugdraw.c index 968514d..ec59826 100644 --- a/source/engine/debug/debugdraw.c +++ b/source/engine/debug/debugdraw.c @@ -16,28 +16,42 @@ #include "font.h" +static sg_shader point_shader; +static sg_pipeline point_pipe; +static sg_bindings point_bind; +struct point_vertex { + cpVect pos; + struct rgba color; + float radius; +}; +static int point_c = 0; + static sg_pipeline grid_pipe; static sg_bindings grid_bind; static sg_shader grid_shader; static int grid_c = 0; -static sg_pipeline rect_pipe; -static sg_bindings rect_bind; -static sg_shader rect_shader; -static int rect_c = 0; - static sg_pipeline poly_pipe; static sg_bindings poly_bind; static sg_shader poly_shader; static int poly_c = 0; static int poly_v = 0; -static int poly_vc = 7; +struct poly_vertex { + float pos[2]; + float uv[2]; + struct rgba color; +}; static sg_pipeline circle_pipe; static sg_bindings circle_bind; static sg_shader csg; static int circle_count = 0; static int circle_vert_c = 7; +struct circle_vertex { + float pos[2]; + float radius; + struct rgba color; +}; void debug_flush() { @@ -48,18 +62,18 @@ void debug_flush() sg_draw(0,4,circle_count); circle_count = 0; - sg_apply_pipeline(rect_pipe); - sg_apply_bindings(&rect_bind); - sg_apply_uniforms(SG_SHADERSTAGE_VS,0,SG_RANGE_REF(projection)); - sg_draw(0,rect_c*2,1); - rect_c = 0; - sg_apply_pipeline(poly_pipe); sg_apply_bindings(&poly_bind); sg_apply_uniforms(SG_SHADERSTAGE_VS,0,SG_RANGE_REF(projection)); sg_draw(0,poly_c,1); poly_c = 0; poly_v = 0; + + sg_apply_pipeline(point_pipe); + sg_apply_bindings(&point_bind); + sg_apply_uniforms(SG_SHADERSTAGE_VS,0,SG_RANGE_REF(projection)); + sg_draw(0,point_c,1); + point_c = 0; } static sg_shader_uniform_block_desc projection_ubo = { @@ -69,8 +83,41 @@ static sg_shader_uniform_block_desc projection_ubo = { } }; +sg_blend_state blend_trans = { + .enabled = true, + .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, + .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + .src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA, + .src_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA +}; + + void debugdraw_init() { + point_shader = sg_make_shader(&(sg_shader_desc){ + .vs.source = slurp_text("shaders/point_v.glsl"), + .fs.source = slurp_text("shaders/point_f.glsl"), + .vs.uniform_blocks[0] = projection_ubo + }); + + point_pipe = sg_make_pipeline(&(sg_pipeline_desc){ + .shader = point_shader, + .layout = { + .attrs = { + [0].format = SG_VERTEXFORMAT_FLOAT2, /* pos */ + [1].format = SG_VERTEXFORMAT_UBYTE4N, /* color */ + [2].format = SG_VERTEXFORMAT_FLOAT /* radius */ + } + }, + .primitive_type = SG_PRIMITIVETYPE_POINTS, + .colors[0].blend = blend_trans + }); + + point_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ + .size = sizeof(struct point_vertex)*5000, + .usage = SG_USAGE_STREAM + }); + csg = sg_make_shader(&(sg_shader_desc){ .vs.source = slurp_text("shaders/circlevert.glsl"), .fs.source = slurp_text("shaders/circlefrag.glsl"), @@ -83,21 +130,15 @@ void debugdraw_init() .attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2, [0].buffer_index = 1, - [1].format = SG_VERTEXFORMAT_FLOAT3, - [2].format = SG_VERTEXFORMAT_FLOAT2, - [3].format = SG_VERTEXFORMAT_FLOAT + [1].format = SG_VERTEXFORMAT_FLOAT2, + [2].format = SG_VERTEXFORMAT_FLOAT, + [3].format = SG_VERTEXFORMAT_UBYTE4N }, .buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE, }, .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, .cull_mode = SG_CULLMODE_BACK, - .colors[0].blend = { - .enabled = true, - .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, - .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, - .src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA, - .src_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA - }, + .colors[0].blend = blend_trans, .label = "circle pipeline" }); @@ -117,8 +158,7 @@ void debugdraw_init() .data = SG_RANGE(circleverts), .usage = SG_USAGE_IMMUTABLE, }); - - + grid_shader = sg_make_shader(&(sg_shader_desc){ .vs.source = slurp_text("shaders/gridvert.glsl"), .fs.source = slurp_text("shaders/gridfrag.glsl"), @@ -127,88 +167,55 @@ void debugdraw_init() .size = sizeof(float)*2, .uniforms = { [0] = { .name = "offset", .type = SG_UNIFORMTYPE_FLOAT2 } } }, .fs.uniform_blocks[0] = { - .size = sizeof(float)*5, + .size = sizeof(float)*6, .uniforms = { [0] = { .name = "thickness", .type = SG_UNIFORMTYPE_FLOAT }, [1] = { .name = "span", .type = SG_UNIFORMTYPE_FLOAT }, - [2] = { .name = "color", .type = SG_UNIFORMTYPE_FLOAT3 }, + [2] = { .name = "color", .type = SG_UNIFORMTYPE_FLOAT4 }, } }, }); + grid_pipe = sg_make_pipeline(&(sg_pipeline_desc){ .shader = grid_shader, .layout = { .attrs = { - [0].format = SG_VERTEXFORMAT_FLOAT2 + [0].format = SG_VERTEXFORMAT_FLOAT2, /* pos */ } }, .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, -// .cull_mode = SG_CULLMODE_BACK, +// .cull_mode = sg_cullmode_back, .label = "grid pipeline", - .colors[0] = { - .blend = { - .enabled = true, - .src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, - .dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, - .op_rgb = SG_BLENDOP_ADD, - .src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA, - .dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, - .op_alpha = SG_BLENDOP_ADD - }, - }, + .colors[0].blend = blend_trans, }); - + grid_bind.vertex_buffers[0] = circle_bind.vertex_buffers[1]; - - rect_shader = sg_make_shader(&(sg_shader_desc){ - .vs.source = slurp_text("shaders/linevert.glsl"), - .fs.source = slurp_text("shaders/linefrag.glsl"), - .vs.uniform_blocks[0] = projection_ubo - }); - - rect_pipe = sg_make_pipeline(&(sg_pipeline_desc){ - .shader = rect_shader, - .layout = { - .attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2 } - }, - .primitive_type = SG_PRIMITIVETYPE_LINES - }); - - rect_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(float)*2*10000, - .usage = SG_USAGE_STREAM - }); poly_shader = sg_make_shader(&(sg_shader_desc){ .vs.source = slurp_text("shaders/poly_v.glsl"), .fs.source = slurp_text("shaders/poly_f.glsl"), - .vs.uniform_blocks[0] = projection_ubo, + .vs.uniform_blocks[0] = projection_ubo }); poly_pipe = sg_make_pipeline(&(sg_pipeline_desc){ .shader = poly_shader, .layout = { - .attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2, - [1].format = SG_VERTEXFORMAT_FLOAT2, - [2].format = SG_VERTEXFORMAT_FLOAT3 + .attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2, /* pos */ + [1].format = SG_VERTEXFORMAT_FLOAT2, /* uv */ + [2].format = SG_VERTEXFORMAT_UBYTE4N /* color rgba */ } }, - .index_type = SG_INDEXTYPE_UINT32 + .index_type = SG_INDEXTYPE_UINT32, + .colors[0].blend = blend_trans, }); poly_bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(float)*poly_vc*1000, + .size = sizeof(struct poly_vertex)*1000, .usage = SG_USAGE_STREAM, .type = SG_BUFFERTYPE_VERTEXBUFFER, }); -/* poly_bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(float)*1000, - .usage = SG_USAGE_STREAM, - }); -*/ - poly_bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){ .size = sizeof(uint32_t)*6*1000, .usage = SG_USAGE_STREAM, @@ -216,7 +223,7 @@ void debugdraw_init() }); } -void draw_line(cpVect s, cpVect e, float *color) +void draw_line(cpVect s, cpVect e, struct rgba color) { cpVect verts[2] = {s, e}; draw_poly(verts, 2, color); @@ -287,156 +294,11 @@ void inflatepoints(cpVect *r, cpVect *p, float d, int n) r[i+1] = inflatepoint(p[i],p[i+1],p[i+2], d); } -void draw_edge(cpVect *points, int n, struct color color, int thickness) -{ - return; - static_assert(sizeof(cpVect) == 2*sizeof(float)); - - float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; - - /* TODO: Should be dashed, and filled. Use a texture. */ - - parsl_position par_v[n]; - - for (int i = 0; i < n; i++) { - par_v[i].x = points[i].x; - par_v[i].y = points[i].y; - } - - uint16_t spine_lens[] = {n}; - - parsl_context *par_ctx = parsl_create_context((parsl_config){ - .thickness = thickness - }); - - parsl_mesh *mesh = parsl_mesh_from_lines(par_ctx, (parsl_spine_list){ - .num_vertices = n, - .num_spines = 1, - .vertices = points, - .spine_lengths = spine_lens, - }); - - sg_range pt = { - .ptr = mesh->positions, - .size = sizeof(float)*2*mesh->num_vertices - }; - - for (int i = 0; i < mesh->num_triangles*3; i++) - mesh->triangle_indices[i] += poly_v; - - float mesh_colors[3*mesh->num_vertices]; - - for (int i = 0; i < 3*mesh->num_vertices; i+=3) - for (int j = 0; j < 3; j++) - mesh_colors[i+j] = col[j]; - - - sg_range it = { - .ptr = mesh->triangle_indices, - .size = sizeof(uint32_t)*mesh->num_triangles*3 - }; - - sg_range ct = { - .ptr = mesh_colors, - .size = sizeof(float)*mesh->num_vertices*3 - }; - - sg_append_buffer(poly_bind.vertex_buffers[0], &pt); - sg_append_buffer(poly_bind.index_buffer, &it); - sg_append_buffer(poly_bind.vertex_buffers[1], &ct); - - poly_c += mesh->num_triangles*3; - poly_v += mesh->num_vertices; - - parsl_destroy_context(par_ctx); -} - -void draw_circle(int x, int y, float radius, int pixels, float *color, int fill) -{ - float cv[circle_vert_c]; - cv[0] = color[0]; - cv[1] = color[1]; - cv[2] = color[2]; - cv[3] = x; - cv[4] = y; - cv[5] = radius; - cv[6] = fill; - sg_append_buffer(circle_bind.vertex_buffers[0], SG_RANGE_REF(cv)); - circle_count++; -} - -void draw_rect(int x, int y, int w, int h, float *color) -{ - float hw = w / 2.f; - float hh = h / 2.f; - - cpVect verts[4] = { - { .x = x-hw, .y = y-hh }, - { .x = x+hw, .y = y-hh }, - { .x = x+hw, .y = y+hh }, - { .x = x-hw, .y = y+hh } - }; - - draw_poly(verts, 4, color); -} - -void draw_box(struct cpVect c, struct cpVect wh, struct color color) -{ - float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; - draw_rect(c.x, c.y, wh.x, wh.y, col); -} - -void draw_arrow(struct cpVect start, struct cpVect end, struct color color, int capsize) -{ - float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; - draw_line(start, end, col); - - draw_cppoint(end, capsize, color); -} - -void draw_grid(int width, int span) -{ - cpVect offset = cam_pos(); - offset = cpvmult(offset, 1/cam_zoom()); - offset.x -= mainwin->width/2; - offset.y -= mainwin->height/2; - - sg_apply_pipeline(grid_pipe); - sg_apply_bindings(&grid_bind); - - float col[3] = { 0.3, 0.5, 0.8}; - - float fubo[5]; - fubo[0] = width; - fubo[1] = span; - fubo[2] = col; - - sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection)); - sg_apply_uniforms(SG_SHADERSTAGE_VS, 1, SG_RANGE_REF(offset)); - sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(fubo)); - - sg_draw(0,4,1); -} - -void draw_point(int x, int y, float r, float *color) -{ - draw_circle(x,y,r,r,color,1); -} - -void draw_cppoint(struct cpVect point, float r, struct color color) -{ - float col[3] = {(float)color.r/255, (float)color.g/255, (float)color.b/255}; - draw_point(point.x, point.y, r, col); -} - -void draw_points(struct cpVect *points, int n, float size, float *color) -{ - for (int i = 0; i < n; i++) - draw_point(points[i].x, points[i].y, size, color); -} - -void draw_poly(cpVect *points, int n, float *color) +void draw_edge(cpVect *points, int n, struct rgba color, int thickness, int closed, int flags) { + static_assert(sizeof(cpVect) == 2*sizeof(float)); + /* todo: should be dashed, and filled. use a texture. */ + /* draw polygon outline */ parsl_position par_v[n]; for (int i = 0; i < n; i++) { @@ -456,7 +318,7 @@ void draw_poly(cpVect *points, int n, float *color) .num_spines = 1, .vertices = par_v, .spine_lengths = spine_lens, - .closed = true + .closed = closed }); for (int i = 0; i < mesh->num_triangles*3; i++) @@ -467,32 +329,164 @@ void draw_poly(cpVect *points, int n, float *color) .size = sizeof(uint32_t)*mesh->num_triangles*3 }; - float vertices[poly_vc*mesh->num_vertices]; + struct poly_vertex vertices[mesh->num_vertices]; - for (int i = 0, vert = 0; i < mesh->num_vertices; i++, vert+=poly_vc) { - vertices[vert] = mesh->positions[i].x; - vertices[vert+1] = mesh->positions[i].y; - vertices[vert+2] = mesh->annotations[i].u_along_curve; - vertices[vert+3] = mesh->annotations[i].v_across_curve; - vertices[vert+4] = color[0]; - vertices[vert+5] = color[1]; - vertices[vert+6] = color[2]; + for (int i = 0; i < mesh->num_vertices; i++) { + vertices[i].pos[0] = mesh->positions[i].x; + vertices[i].pos[1] = mesh->positions[i].y; + vertices[i].uv[0] = mesh->annotations[i].u_along_curve; + vertices[i].uv[1] = mesh->annotations[i].v_across_curve; + vertices[i].color = color; } - + sg_range vvt = { .ptr = vertices, - .size = sizeof(float)*poly_vc*mesh->num_vertices + .size = sizeof(struct poly_vertex)*mesh->num_vertices }; sg_append_buffer(poly_bind.vertex_buffers[0], &vvt); sg_append_buffer(poly_bind.index_buffer, &it); poly_c += mesh->num_triangles*3; - poly_v += mesh->num_vertices; + poly_v += mesh->num_vertices; parsl_destroy_context(par_ctx); +} + +void draw_circle(int x, int y, float radius, int pixels, struct rgba color, int fill) +{ + struct circle_vertex cv; + cv.pos[0] = x; + cv.pos[1] = y; + cv.radius = radius; + cv.color = color; + sg_append_buffer(circle_bind.vertex_buffers[0], SG_RANGE_REF(cv)); + circle_count++; +} + +void draw_rect(int x, int y, int w, int h, struct rgba color) +{ + float hw = w / 2.f; + float hh = h / 2.f; + + cpVect verts[4] = { + { .x = x-hw, .y = y-hh }, + { .x = x+hw, .y = y-hh }, + { .x = x+hw, .y = y+hh }, + { .x = x-hw, .y = y+hh } + }; + + draw_poly(verts, 4, color); +} + +void draw_box(struct cpVect c, struct cpVect wh, struct rgba color) +{ + draw_rect(c.x, c.y, wh.x, wh.y, color); +} + +void draw_arrow(struct cpVect start, struct cpVect end, struct rgba color, int capsize) +{ + draw_line(start, end, color); + draw_cppoint(end, capsize, color); +} + +void draw_grid(int width, int span, struct rgba color) +{ + cpVect offset = cam_pos(); + offset = cpvmult(offset, 1/cam_zoom()); + offset.x -= mainwin->width/2; + offset.y -= mainwin->height/2; + + sg_apply_pipeline(grid_pipe); + sg_apply_bindings(&grid_bind); - return; + float col[4] = { color.r/255.0 ,color.g/255.0 ,color.b/255.0 ,color.a/255.0 }; + + float fubo[6]; + fubo[0] = 1; + fubo[1] = span; + memcpy(&fubo[2], col, sizeof(float)*4); + sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection)); + sg_apply_uniforms(SG_SHADERSTAGE_VS, 1, SG_RANGE_REF(offset)); + sg_apply_uniforms(SG_SHADERSTAGE_FS, 0, SG_RANGE_REF(fubo)); + sg_draw(0,4,1); +} + +void draw_point(int x, int y, float r, struct rgba color) +{ + struct point_vertex p; + p.pos.x = x; + p.pos.y = y; + p.color = color; + p.radius = r; + + sg_range pt = { + .ptr = &p, + .size = sizeof(p) + }; + + sg_append_buffer(point_bind.vertex_buffers[0], &pt); + point_c++; +} + +void draw_cppoint(struct cpVect point, float r, struct rgba color) +{ + draw_point(point.x, point.y, r, color); +} + +void draw_points(struct cpVect *points, int n, float size, struct rgba color) +{ + for (int i = 0; i < n; i++) + draw_point(points[i].x, points[i].y, size, color); +} + +void draw_poly(cpVect *points, int n, struct rgba color) +{ + draw_edge(points,n,color,1,1,0); + + color.a = 40; + + /* Find polygon mesh */ + int tric = n - 2; + + if (n < 1) return; + + uint32_t tridxs[tric*3]; + + for (int i = 2, ti = 0; i < n; i++, ti+=3) { + tridxs[ti] = 0; + tridxs[ti+1] = i-1; + tridxs[ti+2] = i; + } + + for (int i = 0; i < tric*3; i++) + tridxs[i] += poly_v; + + sg_range trip = { + .ptr = tridxs, + .size = sizeof(uint32_t)*3*tric + }; + + struct poly_vertex polyverts[n]; + + for (int i = 0; i < n; i++) { + polyverts[i].pos[0] = points[i].x; + polyverts[i].pos[1] = points[i].y; + polyverts[i].uv[0] = 0.0; + polyverts[i].uv[1] = 0.0; + polyverts[i].color = color; + } + + sg_range ppp = { + .ptr = polyverts, + .size = sizeof(struct poly_vertex)*n + }; + + sg_append_buffer(poly_bind.vertex_buffers[0], &ppp); + sg_append_buffer(poly_bind.index_buffer, &trip); + + poly_c += tric*3; + poly_v += n; } void debugdraw_flush() diff --git a/source/engine/debug/debugdraw.h b/source/engine/debug/debugdraw.h index 5934ffa..fce199a 100644 --- a/source/engine/debug/debugdraw.h +++ b/source/engine/debug/debugdraw.h @@ -2,20 +2,20 @@ #define DEBUGDRAW_H #include -struct color; +struct rgba; void debugdraw_init(); -void draw_line(cpVect s, cpVect e, float *color); -void draw_edge(struct cpVect *points, int n, struct color color, int thickness); -void draw_points(struct cpVect *points, int n, float size, float *color); -void draw_arrow(struct cpVect start, struct cpVect end, struct color, int capsize); -void draw_circle(int x, int y, float radius, int pixels, float *color, int fill); -void draw_grid(int width, int span); -void draw_rect(int x, int y, int w, int h, float *color); -void draw_box(struct cpVect c, struct cpVect wh, struct color color); -void draw_point(int x, int y, float r, float *color); -void draw_cppoint(struct cpVect point, float r, struct color color); -void draw_poly(cpVect *points, int n, float *color); +void draw_line(cpVect s, cpVect e, struct rgba color); +void draw_edge(struct cpVect *points, int n, struct rgba color, int thickness, int closed, int flags); +void draw_points(struct cpVect *points, int n, float size, struct rgba color); +void draw_arrow(struct cpVect start, struct cpVect end, struct rgba, int capsize); +void draw_circle(int x, int y, float radius, int pixels, struct rgba color, int fill); +void draw_grid(int width, int span, struct rgba color); +void draw_rect(int x, int y, int w, int h, struct rgba color); +void draw_box(struct cpVect c, struct cpVect wh, struct rgba color); +void draw_point(int x, int y, float r, struct rgba color); +void draw_cppoint(struct cpVect point, float r, struct rgba color); +void draw_poly(cpVect *points, int n, struct rgba color); void debug_flush(); diff --git a/source/engine/ffi.c b/source/engine/ffi.c index b0e49b4..2f76b03 100644 --- a/source/engine/ffi.c +++ b/source/engine/ffi.c @@ -116,11 +116,14 @@ int js_arrlen(JSValue v) { JS_ToInt32(js, &len, JS_GetPropertyStr(js, v, "length")); return len; } -struct color js2color(JSValue v) { - struct color color = {0, 0, 0}; - color.r = js2int(js_arridx(v, 0)); - color.g = js2int(js_arridx(v, 1)); - color.b = js2int(js_arridx(v, 2)); + +struct rgba js2color(JSValue v) { + struct rgba color = { + .r = js2int(js_arridx(v, 0)), + .g = js2int(js_arridx(v, 1)), + .b = js2int(js_arridx(v, 2)), + .a = 255 + }; return color; } @@ -189,8 +192,7 @@ JSValue duk_gui_text(JSContext *js, JSValueConst this, int argc, JSValueConst *a cpVect pos = js2vec2(argv[1]); float size = js2number(argv[2]); - const float white[3] = {1.f, 1.f, 1.f}; - renderText(s, &pos, size, white, 500, -1); + renderText(s, &pos, size, color_white, 500, -1); JS_FreeCString(js, s); return JS_NULL; } @@ -200,10 +202,9 @@ JSValue duk_ui_text(JSContext *js, JSValueConst this, int argc, JSValueConst *ar cpVect pos = js2vec2(argv[1]); float size = js2number(argv[2]); - struct color c = js2color(argv[3]); - const float col[3] = {(float)c.r / 255, (float)c.g / 255, (float)c.b / 255}; + struct rgba c = js2color(argv[3]); int wrap = js2int(argv[4]); - JSValue ret = JS_NewInt64(js, renderText(s, &pos, size, col, wrap, -1)); + JSValue ret = JS_NewInt64(js, renderText(s, &pos, size, c, wrap, -1)); JS_FreeCString(js, s); return ret; } @@ -213,11 +214,10 @@ JSValue duk_cursor_text(JSContext *js, JSValueConst this, int argc, JSValueConst cpVect pos = js2vec2(argv[1]); float size = js2number(argv[2]); - struct color c = js2color(argv[3]); - const float col[3] = {(float)c.r / 255, (float)c.g / 255, (float)c.b / 255}; + struct rgba c = js2color(argv[3]); int wrap = js2int(argv[5]); int cursor = js2int(argv[4]); - renderText(s, &pos, size, col, wrap, cursor); + renderText(s, &pos, size, c, wrap, cursor); JS_FreeCString(js, s); return JS_NULL; } @@ -598,11 +598,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 16: - color2float(js2color(argv[1]), dbg_color); + dbg_color = js2color(argv[1]); break; case 17: - color2float(js2color(argv[1]), trigger_color); + trigger_color = js2color(argv[1]); break; case 18: @@ -719,7 +719,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) return JS_NULL; case 47: - draw_grid(js2int(argv[1]), js2int(argv[2])); + draw_grid(js2int(argv[1]), js2int(argv[2]), color_white); return JS_NULL; case 48: @@ -853,7 +853,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) return JS_NULL; case 83: - draw_edge(js2cpvec2arr(argv[1]), 2, js2color(argv[2]), 1); + draw_edge(js2cpvec2arr(argv[1]), 2, js2color(argv[2]), 1, 0, 0); return JS_NULL; case 84: @@ -909,7 +909,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 96: - color2float(js2color(argv[2]), id2sprite(js2int(argv[1]))->color); +// id2sprite(js2int(argv[1]))->color = js2color(argv[2]); break; case 97: diff --git a/source/engine/ffi.h b/source/engine/ffi.h index df0f1ed..7ef1d62 100644 --- a/source/engine/ffi.h +++ b/source/engine/ffi.h @@ -3,6 +3,7 @@ #include "quickjs/quickjs.h" #include +#include "2dphysics.h" void ffi_load(); @@ -12,7 +13,7 @@ cpVect js2vec2(JSValue v); JSValue bitmask2js(cpBitmask mask); cpBitmask js2bitmask(JSValue v); -struct color js2color(JSValue v); +struct rgba js2color(JSValue v); double js2number(JSValue v); JSValue num2js(double g); JSValue int2js(int i); diff --git a/source/engine/font.c b/source/engine/font.c index debedfc..23b801b 100644 --- a/source/engine/font.c +++ b/source/engine/font.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include "2dphysics.h" #include "openglrender.h" @@ -18,6 +20,7 @@ struct sFont *font; +#define max_chars 40000 unsigned char *slurp_file(const char *filename) { FILE *f = fopen(filename, "rb"); @@ -36,7 +39,11 @@ unsigned char *slurp_file(const char *filename) { char *slurp_text(const char *filename) { FILE *f = fopen(filename, "r'"); - if (!f) return NULL; + + if (!f) { + YughWarn("File %s doesn't exist.", filename); + return NULL; + } char *buf; long int fsize; @@ -64,10 +71,15 @@ int slurp_write(const char *txt, const char *filename) { static sg_shader fontshader; static sg_bindings bind_text; static sg_pipeline pipe_text; +struct text_vert { + cpVect pos; + cpVect wh; + struct uv_n uv; + struct uv_n st; + struct rgba color; +}; -static float text_buffer[16 * 40000]; -static uint16_t text_idx_buffer[6 * 40000]; -static float color_buffer[3 * 40000]; +static struct text_vert text_buffer[max_chars]; void font_init(struct shader *textshader) { fontshader = sg_make_shader(&(sg_shader_desc){ @@ -85,35 +97,37 @@ void font_init(struct shader *textshader) { .shader = fontshader, .layout = { .attrs = { - [0].format = SG_VERTEXFORMAT_FLOAT2, - [0].buffer_index = 0, - [1].format = SG_VERTEXFORMAT_FLOAT2, - [1].buffer_index = 0, - [2].format = SG_VERTEXFORMAT_FLOAT3, - [2].buffer_index = 1, + [0].format = SG_VERTEXFORMAT_FLOAT2, /* verts */ + [0].buffer_index = 1, + [1].format = SG_VERTEXFORMAT_FLOAT2, /* pos */ + [2].format = SG_VERTEXFORMAT_FLOAT2, /* width and height */ + [3].format = SG_VERTEXFORMAT_USHORT2N, /* uv pos */ + [4].format = SG_VERTEXFORMAT_USHORT2N, /* uv width and height */ + [5].format = SG_VERTEXFORMAT_UBYTE4N, /* color */ }, + .buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE }, - .label = "text pipeline", - .index_type = SG_INDEXTYPE_UINT16}); + .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, + }); + + float text_verts[8] = { + 0,0, + 0,1, + 1,0, + 1,1 + }; + + bind_text.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){ + .data = SG_RANGE(text_verts), + .usage = SG_USAGE_IMMUTABLE + }); bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(float) * 16 * 40000, + .size = sizeof(struct text_vert)*max_chars, .type = SG_BUFFERTYPE_VERTEXBUFFER, .usage = SG_USAGE_STREAM, .label = "text buffer"}); - bind_text.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(float) * 3 * 4 * 40000, - .type = SG_BUFFERTYPE_VERTEXBUFFER, - .usage = SG_USAGE_STREAM, - .label = "text color buffer"}); - - bind_text.index_buffer = sg_make_buffer(&(sg_buffer_desc){ - .size = sizeof(uint16_t) * 6 * 40000, - .type = SG_BUFFERTYPE_INDEXBUFFER, - .usage = SG_USAGE_STREAM, - .label = "text index buffer"}); - font = MakeFont("LessPerfectDOSVGA.ttf", 16); bind_text.fs_images[0] = font->texID; } @@ -205,66 +219,31 @@ void text_flush() { sg_range verts; verts.ptr = text_buffer; - verts.size = sizeof(float) * 16 * curchar; + verts.size = sizeof(struct text_vert) * curchar; sg_update_buffer(bind_text.vertex_buffers[0], &verts); - - sg_range idxs; - idxs.ptr = text_idx_buffer; - idxs.size = sizeof(uint16_t) * 6 * curchar; - sg_update_buffer(bind_text.index_buffer, &idxs); - sg_range c = { - .ptr = color_buffer, - .size = sizeof(float) * 3 * 4 * curchar}; - - sg_update_buffer(bind_text.vertex_buffers[1], &c); - - sg_draw(0, 6 * curchar, 1); + sg_draw(0, 4, curchar); curchar = 0; } -void fill_charverts(float *verts, float cursor[2], float scale, struct Character c, float *offset) { - float w = c.Size[0] * scale; - float h = c.Size[1] * scale; - - float xpos = cursor[0] + (c.Bearing[0] + offset[0]) * scale; - float ypos = cursor[1] - (c.Bearing[1] + offset[1]) * scale; - - float v[16] = { - xpos, ypos, c.rect.s0, c.rect.t1, - xpos + w, ypos, c.rect.s1, c.rect.t1, - xpos, ypos + h, c.rect.s0, c.rect.t0, - xpos + w, ypos + h, c.rect.s1, c.rect.t0}; - - memcpy(verts, v, sizeof(float) * 16); -} - static int drawcaret = 0; -void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, float color[3]) { - float shadowcolor[3] = {0.f, 0.f, 0.f}; - float shadowcursor[2]; - - float verts[16]; +void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct rgba color) { float offset[2] = {-1, 1}; + + struct text_vert vert; + + vert.wh.x = c.Size[0] * scale; + vert.wh.y = c.Size[1] * scale; + vert.pos.x = cursor[0] - (c.Bearing[0] + offset[0]) * scale; + vert.pos.y = cursor[1] - (c.Bearing[1] + offset[1]) * scale; + vert.uv.u = c.rect.s0*USHRT_MAX; + vert.uv.v = c.rect.t0*USHRT_MAX; + vert.st.u = (c.rect.s1-c.rect.s0)*USHRT_MAX; + vert.st.v = (c.rect.t1-c.rect.t0)*USHRT_MAX; + vert.color = color; - fill_charverts(verts, cursor, scale, c, offset); - - /* Check if the vertex is off screen */ - if (verts[5] < -window_i(0)->width / 2.f || verts[9] < -window_i(0)->height / 2.f || verts[0] > window_i(0)->width / 2.f || verts[1] > window_i(0)->height / 2.f) - return; - - uint16_t pts[6] = { - 0, 1, 2, - 2, 1, 3}; - - for (int i = 0; i < 6; i++) - pts[i] += curchar * 4; - - memcpy(text_buffer + (16 * curchar), verts, sizeof(verts)); - for (int i = 0; i < 4; i++) - memcpy(color_buffer + (12 * curchar) + (3 * i), color, sizeof(color)); - memcpy(text_idx_buffer + (6 * curchar), pts, sizeof(pts)); + memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert)); curchar++; return; @@ -291,17 +270,13 @@ void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, float c fill_charverts(verts, cursor, scale, c, offset); sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts)); */ - offset[0] = offset[1] = 0; - fill_charverts(verts, cursor, scale, c, offset); - - sg_update_buffer(bind_text.vertex_buffers[0], SG_RANGE_REF(verts)); } void text_settype(struct sFont *mfont) { font = mfont; } -int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw, int caret) { +int renderText(const char *text, mfloat_t pos[2], float scale, struct rgba color, float lw, int caret) { int len = strlen(text); drawcaret = caret; @@ -312,7 +287,7 @@ int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3] const unsigned char *line, *wordstart, *drawstart; line = drawstart = (unsigned char *)text; - float *usecolor = color; + struct rgba usecolor = color; while (*line != '\0') { if (isblank(*line)) { diff --git a/source/engine/font.h b/source/engine/font.h index 9848b90..5ecc241 100644 --- a/source/engine/font.h +++ b/source/engine/font.h @@ -4,6 +4,7 @@ #include "mathc.h" #include "sokol/sokol_gfx.h" #include "texture.h" +#include "2dphysics.h" struct shader; struct window; @@ -25,9 +26,9 @@ struct sFont { void font_init(struct shader *s); struct sFont *MakeFont(const char *fontfile, int height); -void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, float color[3]); +void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale, struct rgba color); void text_settype(struct sFont *font); -int renderText(const char *text, mfloat_t pos[2], float scale, mfloat_t color[3], float lw, int caret); +int renderText(const char *text, mfloat_t pos[2], float scale, struct rgba color, float lw, int caret); // void text_frame(); void text_flush(); diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index ce502e0..f99eedb 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -321,7 +321,12 @@ void gameobject_draw_debug(int go) { if (!g || !g->body) return; cpVect pos = cpBodyGetPosition(g->body); - float color[3] = {0.76f, 0.38f, 1.f}; + struct rgba color = { + .r = 0.76*255, + .b = 0.38*255, + .g = 255, + .a = 255 + }; draw_point(pos.x, pos.y, 3.f, color); cpBodyEachShape(g->body, body_draw_shapes_dbg, NULL); } diff --git a/source/engine/openglrender.c b/source/engine/openglrender.c index 052b757..457ee18 100644 --- a/source/engine/openglrender.c +++ b/source/engine/openglrender.c @@ -291,7 +291,7 @@ void openglRender(struct window *window) { if (debugDrawPhysics) gameobject_draw_debugs(); - float c[3] = {0.3,0.5,0.7}; + struct rgba c = {100,130,200,255}; draw_circle(100,100,40,2,c,0); call_debugs(); debug_flush(); diff --git a/source/engine/render.h b/source/engine/render.h index 9da0947..7cbe3e8 100644 --- a/source/engine/render.h +++ b/source/engine/render.h @@ -4,4 +4,15 @@ #define GLFW_INCLUDE_NONE #include + +struct uv_n { + unsigned short u; + unsigned short v; +}; + +struct st_n { + struct uv_n s; + struct uv_n t; +}; + #endif diff --git a/source/shaders/circlefrag.glsl b/source/shaders/circlefrag.glsl index 3619794..d0d5cd3 100644 --- a/source/shaders/circlefrag.glsl +++ b/source/shaders/circlefrag.glsl @@ -4,7 +4,7 @@ in vec2 coords; out vec4 color; in float radius; -in vec3 fcolor; +in vec4 fcolor; in vec2 pos; void main() @@ -19,9 +19,9 @@ void main() float dist = sqrt(dot(coords, coords)); if (dist >= R2 && dist <= R1) - color = vec4(fcolor, 1.f); + color = fcolor; else if (dist < R2) - color = vec4(fcolor, 0.1f); + color = vec4(fcolor.xyz, 0.1f); else discard; } diff --git a/source/shaders/circlevert.glsl b/source/shaders/circlevert.glsl index ab82619..d9dad03 100644 --- a/source/shaders/circlevert.glsl +++ b/source/shaders/circlevert.glsl @@ -1,14 +1,14 @@ #version 330 core layout (location = 0) in vec2 vertex; -layout (location = 1) in vec3 acolor; -layout (location = 2) in vec2 apos; -layout (location = 3) in float aradius; +layout (location = 1) in vec2 apos; +layout (location = 2) in float aradius; +layout (location = 3) in vec4 acolor; //layout (location = 4) in float afill; out vec2 coords; out float radius; -out vec3 fcolor; +out vec4 fcolor; uniform mat4 proj; diff --git a/source/shaders/gridfrag.glsl b/source/shaders/gridfrag.glsl index c59a941..339d788 100644 --- a/source/shaders/gridfrag.glsl +++ b/source/shaders/gridfrag.glsl @@ -2,15 +2,16 @@ out vec4 frag_color; in vec2 apos; -vec2 bpos; + uniform float thickness; /* thickness in pixels */ uniform float span; -uniform vec3 color; +uniform vec4 color; void main(void) { float t = thickness / span; t /= 2.0; + vec2 bpos; bpos.x = mod(apos.x, span) / span; bpos.y = mod(apos.y, span) / span; bpos.x -= t; @@ -23,5 +24,5 @@ void main(void) comp += t; - frag_color = vec4(color, 1.0); + frag_color = color; } diff --git a/source/shaders/point_f.glsl b/source/shaders/point_f.glsl new file mode 100644 index 0000000..5c6cfb7 --- /dev/null +++ b/source/shaders/point_f.glsl @@ -0,0 +1,13 @@ +#version 330 core +in vec4 fcolor; + +out vec4 color; + +void main() +{ + float d = length(gl_PointCoord - vec2(0.5,0.5)); + if (d >= 0.47) + discard; + + color = fcolor; +} diff --git a/source/shaders/point_v.glsl b/source/shaders/point_v.glsl new file mode 100644 index 0000000..9cbf9fe --- /dev/null +++ b/source/shaders/point_v.glsl @@ -0,0 +1,16 @@ +#version 330 core + +layout (location = 0) in vec2 apos; +layout (location = 1) in vec4 acolor; +layout (location = 2) in float radius; + +uniform mat4 proj; + +out vec4 fcolor; + +void main() +{ + gl_Position = proj * vec4(apos, 0.0, 1.0); + fcolor = acolor; + gl_PointSize = radius; +} diff --git a/source/shaders/poly_f.glsl b/source/shaders/poly_f.glsl index 7f5abce..78f486d 100644 --- a/source/shaders/poly_f.glsl +++ b/source/shaders/poly_f.glsl @@ -1,10 +1,10 @@ #version 330 core out vec4 fcolor; -in vec3 color; +in vec4 color; in vec2 uv; void main() { - fcolor = vec4(color,1.0); + fcolor = color; } diff --git a/source/shaders/poly_v.glsl b/source/shaders/poly_v.glsl index 4eb4b20..6ae212f 100644 --- a/source/shaders/poly_v.glsl +++ b/source/shaders/poly_v.glsl @@ -1,9 +1,9 @@ #version 330 core in vec2 apos; in vec2 auv; -in vec3 acolor; +in vec4 acolor; -out vec3 color; +out vec4 color; out vec2 uv; uniform mat4 proj; diff --git a/source/shaders/textfrag.glsl b/source/shaders/textfrag.glsl index b0ade18..8cb4101 100644 --- a/source/shaders/textfrag.glsl +++ b/source/shaders/textfrag.glsl @@ -1,6 +1,6 @@ #version 330 core in vec2 TexCoords; -in vec3 fColor; +in vec4 fColor; out vec4 color; @@ -8,8 +8,11 @@ uniform sampler2D text; void main() { - color = vec4(fColor.xyz, texture(text, TexCoords).r); + float lettera = texture(text,TexCoords).r; + // color = vec4(1.f, 1.f, 1.f, texture(text, TexCoords).r); - if (color.a <= 0.1f) - discard; + if (lettera <= 0.1f) + discard; + + color = vec4(fColor.xyz, lettera * fColor.a); } diff --git a/source/shaders/textvert.glsl b/source/shaders/textvert.glsl index ce798ad..8ab2c35 100644 --- a/source/shaders/textvert.glsl +++ b/source/shaders/textvert.glsl @@ -1,17 +1,21 @@ #version 330 core -layout (location = 0) in vec2 vertex; -layout (location = 1) in vec2 rect; -layout (location = 2) in vec3 vColor; +layout (location = 0) in vec2 vert; +layout (location = 1) in vec2 pos; +layout (location = 2) in vec2 wh; +layout (location = 3) in vec2 uv; +layout (location = 4) in vec2 st; +layout (location = 5) in vec4 vColor; out vec2 TexCoords; -out vec3 fColor; +out vec4 fColor; uniform mat4 projection; void main() { - gl_Position = projection * vec4(vertex, 0.0, 1.0); - TexCoords = rect; + gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0); + + TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y); fColor = vColor; }