From adab18298bef209c1ac1d1030f95cc4a64f8798b Mon Sep 17 00:00:00 2001 From: Robert Konrad Date: Sun, 9 Jun 2024 21:05:38 +0200 Subject: [PATCH] Add a new, preliminary g2 port --- Sources/kinc/graphics2/colored_painter.c.h | 270 +++++++++ Sources/kinc/graphics2/g2unit.c | 7 + Sources/kinc/graphics2/graphics.c.h | 672 +++++++++++++++++++++ Sources/kinc/graphics2/graphics.h | 52 ++ Sources/kinc/graphics2/graphics_soft.c | 4 + Sources/kinc/graphics2/image_painter.c.h | 251 ++++++++ Sources/kinc/graphics2/text_painter.c.h | 269 +++++++++ Sources/kinc/math/matrix.h | 10 + 8 files changed, 1535 insertions(+) create mode 100644 Sources/kinc/graphics2/colored_painter.c.h create mode 100644 Sources/kinc/graphics2/g2unit.c create mode 100644 Sources/kinc/graphics2/graphics.c.h create mode 100644 Sources/kinc/graphics2/image_painter.c.h create mode 100644 Sources/kinc/graphics2/text_painter.c.h diff --git a/Sources/kinc/graphics2/colored_painter.c.h b/Sources/kinc/graphics2/colored_painter.c.h new file mode 100644 index 000000000..f5e7d0b64 --- /dev/null +++ b/Sources/kinc/graphics2/colored_painter.c.h @@ -0,0 +1,270 @@ +#include +#include +#include +#include + +#include + +static kinc_matrix4x4_t colored_projection_matrix; + +// static var standardColorPipeline : PipelineCache = null; +// static VertexStructure structure; + +static int colored_rect_buffer_size = 1000; +static int colored_rect_buffer_index; +static kinc_g4_vertex_buffer_t colored_rect_vertex_buffer; +static kinc_g2_colored_vertex_in *colored_rect_vertices; +static kinc_g4_index_buffer_t colored_rect_index_buffer; + +static int colored_triangle_buffer_size = 1000; +static int colored_triangle_buffer_index; +static kinc_g4_vertex_buffer_t colored_triangle_vertex_buffer; +static kinc_g2_colored_vertex_in *colored_triangle_vertices; +static kinc_g4_index_buffer_t colored_triangle_index_buffer; + +static kinc_g2_constants_type_buffer colored_constants; + +// var myPipeline : PipelineCache = null; + +static void colored_init_shaders(void); +static void colored_init_buffers(void); +static void colored_end_tris(bool rectsDone); +static void colored_end_rects(bool trisDone); + +static void colored_init(void) { + colored_rect_buffer_index = 0; + colored_triangle_buffer_index = 0; + colored_init_shaders(); + // myPipeline = standardColorPipeline; + colored_init_buffers(); +} + +// function get_pipeline() : PipelineCache { +// return myPipeline; +// } + +// function set_pipeline(pipe : PipelineCache) : PipelineCache { +// myPipeline = pipe != null ? pipe : standardColorPipeline; +// return myPipeline; +// } + +static void colored_set_projection(kinc_matrix4x4_t matrix) { + colored_projection_matrix = matrix; +} + +static void colored_init_shaders(void) { + // if (structure == NULL) { + // structure = Graphics2.createColoredVertexStructure(); + // } + // if (standardColorPipeline == null) { + // var pipeline = Graphics2.createColoredPipeline(structure); + // standardColorPipeline = new PerFramebufferPipelineCache(pipeline, false); + // } +} + +static bool colored_buffers_initialized = false; + +static void colored_init_buffers(void) { + if (!colored_buffers_initialized) { + kinc_g4_vertex_buffer_init(&colored_rect_vertex_buffer, colored_rect_buffer_size * 4, &kinc_g2_colored_vertex_in_structure, KINC_G4_USAGE_DYNAMIC, 0); + colored_rect_vertices = (kinc_g2_colored_vertex_in *)kinc_g4_vertex_buffer_lock_all(&colored_rect_vertex_buffer); + + kinc_g4_index_buffer_init(&colored_rect_index_buffer, colored_rect_buffer_size * 3 * 2, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC); + int *indices = (int *)kinc_g4_index_buffer_lock_all(&colored_rect_index_buffer); + for (int i = 0; i < colored_rect_buffer_size; ++i) { + indices[i * 3 * 2 + 0] = i * 4 + 0; + indices[i * 3 * 2 + 1] = i * 4 + 1; + indices[i * 3 * 2 + 2] = i * 4 + 2; + indices[i * 3 * 2 + 3] = i * 4 + 0; + indices[i * 3 * 2 + 4] = i * 4 + 2; + indices[i * 3 * 2 + 5] = i * 4 + 3; + } + kinc_g4_index_buffer_unlock_all(&colored_rect_index_buffer); + + kinc_g4_vertex_buffer_init(&colored_triangle_vertex_buffer, colored_triangle_buffer_size * 3, &kinc_g2_colored_vertex_in_structure, + KINC_G4_USAGE_DYNAMIC, 0); + colored_triangle_vertices = (kinc_g2_colored_vertex_in *)kinc_g4_vertex_buffer_lock_all(&colored_triangle_vertex_buffer); + + kinc_g4_index_buffer_init(&colored_triangle_index_buffer, colored_triangle_buffer_size * 3, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC); + int *tri_indices = (int *)kinc_g4_index_buffer_lock_all(&colored_rect_index_buffer); + for (int i = 0; i < colored_triangle_buffer_size; ++i) { + tri_indices[i * 3 + 0] = i * 3 + 0; + tri_indices[i * 3 + 1] = i * 3 + 1; + tri_indices[i * 3 + 2] = i * 3 + 2; + } + kinc_g4_index_buffer_unlock_all(&colored_triangle_index_buffer); + + kinc_g2_constants_type_buffer_init(&colored_constants); + + colored_buffers_initialized = true; + } +} + +static void colored_set_rect_vertices(float bottomleftx, float bottomlefty, float topleftx, float toplefty, float toprightx, float toprighty, + float bottomrightx, float bottomrighty) { + int base_index = colored_rect_buffer_index * 4; + + colored_rect_vertices[base_index + 0].pos.x = bottomleftx; + colored_rect_vertices[base_index + 0].pos.y = bottomlefty; + colored_rect_vertices[base_index + 0].pos.z = -5.0f; + + colored_rect_vertices[base_index + 1].pos.x = topleftx; + colored_rect_vertices[base_index + 1].pos.y = toplefty; + colored_rect_vertices[base_index + 1].pos.z = -5.0f; + + colored_rect_vertices[base_index + 2].pos.x = toprightx; + colored_rect_vertices[base_index + 2].pos.y = toprighty; + colored_rect_vertices[base_index + 2].pos.z = -5.0f; + + colored_rect_vertices[base_index + 3].pos.x = bottomrightx; + colored_rect_vertices[base_index + 3].pos.y = bottomrighty; + colored_rect_vertices[base_index + 3].pos.z = -5.0f; +} + +static void colored_set_rect_colors(float opacity, uint32_t color) { + int base_index = colored_rect_buffer_index * 4; + + float color_components[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + + float a = opacity * color_components[0]; + float r = a * color_components[1]; + float g = a * color_components[2]; + float b = a * color_components[3]; + + for (int i = 0; i < 4; ++i) { + colored_rect_vertices[base_index + i].col.x = r; + colored_rect_vertices[base_index + i].col.y = g; + colored_rect_vertices[base_index + i].col.z = b; + colored_rect_vertices[base_index + i].col.w = a; + } +} + +static void colored_set_tri_vertices(float x1, float y1, float x2, float y2, float x3, float y3) { + int base_index = colored_triangle_buffer_index * 3; + + colored_triangle_vertices[base_index + 0].pos.x = x1; + colored_triangle_vertices[base_index + 0].pos.y = y1; + colored_triangle_vertices[base_index + 0].pos.z = -5.0f; + + colored_triangle_vertices[base_index + 1].pos.x = x2; + colored_triangle_vertices[base_index + 1].pos.y = y2; + colored_triangle_vertices[base_index + 1].pos.z = -5.0f; + + colored_triangle_vertices[base_index + 2].pos.x = x3; + colored_triangle_vertices[base_index + 2].pos.y = y3; + colored_triangle_vertices[base_index + 2].pos.z = -5.0f; +} + +static void colored_set_tri_colors(float opacity, uint32_t color) { + int base_index = colored_triangle_buffer_index * 3; + + float color_components[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + + float a = opacity * color_components[0]; + float r = a * color_components[1]; + float g = a * color_components[2]; + float b = a * color_components[3]; + + for (int i = 0; i < 4; ++i) { + colored_triangle_vertices[base_index + i].col.x = r; + colored_triangle_vertices[base_index + i].col.y = g; + colored_triangle_vertices[base_index + i].col.z = b; + colored_triangle_vertices[base_index + i].col.w = a; + } +} + +static void colored_draw_rect_buffer(bool trisDone) { + if (colored_rect_buffer_index == 0) { + return; + } + + if (!trisDone) { + colored_end_tris(true); + } + + kinc_g2_constants_type *constants_data = kinc_g2_constants_type_buffer_lock(&colored_constants); + constants_data->projection = colored_projection_matrix; + kinc_g2_constants_type_buffer_unlock(&colored_constants); + + kinc_g4_vertex_buffer_unlock(&colored_rect_vertex_buffer, colored_rect_buffer_index * 4); + // PipelineState pipeline = myPipeline.get(null, Depth24Stencil8); + kinc_g4_set_pipeline(&kinc_g2_colored_pipeline); + kinc_g4_set_vertex_buffer(&colored_rect_vertex_buffer); + kinc_g4_set_index_buffer(&colored_rect_index_buffer); + kinc_g2_constants_type_buffer_set(&colored_constants); + + kinc_g4_draw_indexed_vertices_from_to(0, colored_rect_buffer_index * 2 * 3); + + colored_rect_buffer_index = 0; + colored_rect_vertices = (kinc_g2_colored_vertex_in *)kinc_g4_vertex_buffer_lock_all(&colored_rect_vertex_buffer); +} + +static void colored_draw_tri_buffer(bool rectsDone) { + if (!rectsDone) { + colored_end_rects(true); + } + + kinc_g2_constants_type *constants_data = kinc_g2_constants_type_buffer_lock(&colored_constants); + constants_data->projection = colored_projection_matrix; + kinc_g2_constants_type_buffer_unlock(&colored_constants); + + kinc_g4_vertex_buffer_unlock(&colored_triangle_vertex_buffer, colored_triangle_buffer_index * 3); + // PipelineState pipeline = myPipeline.get(null, Depth24Stencil8); + kinc_g4_set_pipeline(&kinc_g2_colored_pipeline); + kinc_g4_set_vertex_buffer(&colored_triangle_vertex_buffer); + kinc_g4_set_index_buffer(&colored_triangle_index_buffer); + kinc_g2_constants_type_buffer_set(&colored_constants); + + kinc_g4_draw_indexed_vertices_from_to(0, colored_triangle_buffer_index * 3); + + colored_triangle_buffer_index = 0; + colored_triangle_vertices = (kinc_g2_colored_vertex_in *)kinc_g4_vertex_buffer_lock_all(&colored_triangle_vertex_buffer); +} + +static void colored_fill_rect(float opacity, uint32_t color, float bottomleftx, float bottomlefty, float topleftx, float toplefty, float toprightx, + float toprighty, float bottomrightx, float bottomrighty) { + if (colored_triangle_buffer_index > 0) { + colored_draw_tri_buffer(true); // Flush other buffer for right render order + } + + if (colored_rect_buffer_index + 1 >= colored_rect_buffer_size) { + colored_draw_rect_buffer(false); + } + + colored_set_rect_colors(opacity, color); + colored_set_rect_vertices(bottomleftx, bottomlefty, topleftx, toplefty, toprightx, toprighty, bottomrightx, bottomrighty); + ++colored_rect_buffer_index; +} + +static void colored_fill_triangle(float opacity, uint32_t color, float x1, float y1, float x2, float y2, float x3, float y3) { + if (colored_rect_buffer_index > 0) { + colored_draw_rect_buffer(true); // Flush other buffer for right render order + } + + if (colored_triangle_buffer_index + 1 >= colored_triangle_buffer_size) { + colored_draw_tri_buffer(false); + } + + colored_set_tri_colors(opacity, color); + colored_set_tri_vertices(x1, y1, x2, y2, x3, y3); + ++colored_triangle_buffer_index; +} + +static void colored_end_tris(bool rectsDone) { + if (colored_triangle_buffer_index > 0) { + colored_draw_tri_buffer(rectsDone); + } +} + +static void colored_end_rects(bool trisDone) { + if (colored_rect_buffer_index > 0) { + colored_draw_rect_buffer(trisDone); + } +} + +static void colored_end(void) { + colored_end_tris(false); + colored_end_rects(false); +} diff --git a/Sources/kinc/graphics2/g2unit.c b/Sources/kinc/graphics2/g2unit.c new file mode 100644 index 000000000..612f64053 --- /dev/null +++ b/Sources/kinc/graphics2/g2unit.c @@ -0,0 +1,7 @@ +#ifdef KINC_KONG +#include "colored_painter.c.h" +#include "image_painter.c.h" +#include "text_painter.c.h" + +#include "graphics.c.h" +#endif diff --git a/Sources/kinc/graphics2/graphics.c.h b/Sources/kinc/graphics2/graphics.c.h new file mode 100644 index 000000000..6dc9b0f59 --- /dev/null +++ b/Sources/kinc/graphics2/graphics.c.h @@ -0,0 +1,672 @@ +#include "graphics.h" + +#include +#include +#include + +#include +#include +#include +#include + +/*typedef struct internal_pipeline { + PipelineState *pipeline; + ConstantLocation projectionLocation; + TextureUnit textureLocation; +} internal_pipeline; + +void init_internal_pipeline(internal_pipeline *internal_pipe, PipelineState *pipeline, ConstantLocation projectionLocation, TextureUnit textureLocation) { + internal_pipe->pipeline = pipeline; + internal_pipe->projectionLocation = projectionLocation; + internal_pipe->textureLocation = textureLocation; +} + +interface PipelineCache { + function get(colorFormat : Array, depthStencilFormat : DepthStencilFormat) : InternalPipeline; +} + +class SimplePipelineCache implements PipelineCache { + var pipeline : InternalPipeline; + +public + function new(pipeline : PipelineState, texture : Bool) { + var projectionLocation : ConstantLocation = null; + try { + projectionLocation = pipeline.getConstantLocation("projectionMatrix"); + } catch (x : Dynamic) { + trace(x); + } + + var textureLocation : TextureUnit = null; + if (texture) { + try { + textureLocation = pipeline.getTextureUnit("tex"); + } catch (x : Dynamic) { + trace(x); + } + } + + this.pipeline = new InternalPipeline(pipeline, projectionLocation, textureLocation); + } + +public + function get(colorFormats : Array, depthStencilFormat : DepthStencilFormat) : InternalPipeline { + return pipeline; + } +} + +class PerFramebufferPipelineCache implements PipelineCache { + var pipelines : Array = []; + +public + function new(pipeline : PipelineState, texture : Bool) { + pipeline.compile(); + + var projectionLocation : ConstantLocation = null; + try { + projectionLocation = pipeline.getConstantLocation("projectionMatrix"); + } catch (x : Dynamic) { + trace(x); + } + + var textureLocation : TextureUnit = null; + if (texture) { + try { + textureLocation = pipeline.getTextureUnit("tex"); + } catch (x : Dynamic) { + trace(x); + } + } + + pipelines.push(new InternalPipeline(pipeline, projectionLocation, textureLocation)); + } + +public + function get(colorFormats : Array, depthStencilFormat : DepthStencilFormat) : InternalPipeline { + return pipelines[hash(colorFormats, depthStencilFormat)]; + } + + function hash(colorFormats : Array, depthStencilFormat : DepthStencilFormat) { + return 0; + } +}*/ + +static uint32_t my_color; +// static Font *myFont; +static kinc_matrix4x4_t projection_matrix; + +// PipelineState videoPipeline; + +static kinc_matrix3x3_t transformations[16]; +static uint8_t transformations_size; +static uint8_t transformation_index; +static float opacities[16]; +static uint8_t opacities_size; +static int my_font_size; + +static void set_projection(void); + +void kinc_g2_init(void) { + transformations[0] = kinc_matrix3x3_identity(); + transformations_size = 1; + transformation_index = 0; + opacities[0] = 1; + opacities_size = 1; + my_font_size = 12; + // pipe = NULL; + + my_color = 0xffffffff; + image_init(); + colored_init(); + // init_g2_text_painter(); + // textPainter.fontSize = fontSize; + projection_matrix = kinc_matrix4x4_identity(); + set_projection(); + + /*if (videoPipeline == null) { + videoPipeline = createImagePipeline(createImageVertexStructure()); + videoPipeline.fragmentShader = Shaders.painter_video_frag; + videoPipeline.vertexShader = Shaders.painter_video_vert; + videoPipeline.compile(); + }*/ +} + +static uint32_t upper_power_of_two(uint32_t v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +static kinc_matrix4x4_t orthogonal_projection(float left, float right, float bottom, float top, float zn, float zf) { + float tx = -(right + left) / (right - left); + float ty = -(top + bottom) / (top - bottom); + float tz = -(zf + zn) / (zf - zn); + + kinc_matrix4x4_t m; + m.m[0] = 2 / (right - left); + m.m[1] = 0; + m.m[2] = 0; + m.m[3] = tx; + m.m[4] = 0; + m.m[5] = 2.0f / (top - bottom); + m.m[6] = 0; + m.m[7] = ty; + m.m[8] = 0; + m.m[9] = 0; + m.m[10] = -2 / (zf - zn); + m.m[11] = tz; + m.m[12] = 0; + m.m[13] = 0; + m.m[14] = 0; + m.m[15] = 1; + return m; +} + +#define CANVAS_WIDTH 1024 +#define CANVAS_HEIGHT 768 + +static void set_projection(void) { + int width = CANVAS_WIDTH; + int height = CANVAS_HEIGHT; + // if (Std.isOfType(canvas, Framebuffer)) { + projection_matrix = orthogonal_projection(0, (float)width, (float)height, 0, 0.1f, 1000.0f); + //} + /*else { + if (!Image.nonPow2Supported) { + width = upperPowerOfTwo(width); + height = upperPowerOfTwo(height); + } + if (Image.renderTargetsInvertedY()) { + projectionMatrix.setFrom(FastMatrix4.orthogonalProjection(0, width, 0, height, 0.1, 1000)); + } + else { + projectionMatrix.setFrom(FastMatrix4.orthogonalProjection(0, width, height, 0, 0.1, 1000)); + } + }*/ + image_set_projection(projection_matrix); + colored_set_projection(projection_matrix); + // textPainter.setProjection(projectionMatrix); +} + +/*function drawImage(img : kha.Image, x : FastFloat, y : FastFloat) : Void { + coloredPainter.end(); + textPainter.end(); + var xw : FastFloat = x + img.width; + var yh : FastFloat = y + img.height; + + var xx = Float32x4.loadFast(x, x, xw, xw); + var yy = Float32x4.loadFast(yh, y, y, yh); + + var _00 = Float32x4.loadAllFast(transformation._00); + var _01 = Float32x4.loadAllFast(transformation._01); + var _02 = Float32x4.loadAllFast(transformation._02); + var _10 = Float32x4.loadAllFast(transformation._10); + var _11 = Float32x4.loadAllFast(transformation._11); + var _12 = Float32x4.loadAllFast(transformation._12); + var _20 = Float32x4.loadAllFast(transformation._20); + var _21 = Float32x4.loadAllFast(transformation._21); + var _22 = Float32x4.loadAllFast(transformation._22); + + // matrix multiply + var w = Float32x4.add(Float32x4.add(Float32x4.mul(_02, xx), Float32x4.mul(_12, yy)), _22); + var px = Float32x4.div(Float32x4.add(Float32x4.add(Float32x4.mul(_00, xx), Float32x4.mul(_10, yy)), _20), w); + var py = Float32x4.div(Float32x4.add(Float32x4.add(Float32x4.mul(_01, xx), Float32x4.mul(_11, yy)), _21), w); + + imagePainter.drawImage(img, Float32x4.get(px, 0), Float32x4.get(py, 0), Float32x4.get(px, 1), Float32x4.get(py, 1), Float32x4.get(px, 2), + Float32x4.get(py, 2), Float32x4.get(px, 3), Float32x4.get(py, 3), opacity, this.color); +}*/ + +static kinc_vector2_t multiply_matrix_vector(kinc_matrix3x3_t m, kinc_vector2_t vec) { + float w = kinc_matrix3x3_get(&m, 0, 2) * vec.x + kinc_matrix3x3_get(&m, 1, 2) * vec.y + kinc_matrix3x3_get(&m, 2, 2) * 1; + + kinc_vector2_t ret; + ret.x = (kinc_matrix3x3_get(&m, 0, 0) * vec.x + kinc_matrix3x3_get(&m, 1, 0) * vec.y + kinc_matrix3x3_get(&m, 2, 0) * 1) / w; + ret.y = (kinc_matrix3x3_get(&m, 0, 1) * vec.x + kinc_matrix3x3_get(&m, 1, 1) * vec.y + kinc_matrix3x3_get(&m, 2, 1) * 1) / w; + + return ret; +} + +static kinc_vector2_t kinc_vector2_create(float x, float y) { + kinc_vector2_t vec; + vec.x = x; + vec.y = y; + return vec; +} + +void kinc_g2_draw_image(kinc_g4_texture_t *img, float x, float y) { + colored_end(); + // textPainter.end(); + float xw = x + img->tex_width; + float yh = y + img->tex_height; + kinc_vector2_t p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x, yh)); + kinc_vector2_t p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x, y)); + kinc_vector2_t p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(xw, y)); + kinc_vector2_t p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(xw, yh)); + image_draw_image(img, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, kinc_g2_get_opacity(), kinc_g2_get_color()); +} + +void kinc_g2_draw_scaled_sub_image(kinc_g4_texture_t *img, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh) { + colored_end(); + // textPainter.end(); + kinc_vector2_t p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(dx, dy + dh)); + kinc_vector2_t p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(dx, dy)); + kinc_vector2_t p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(dx + dw, dy)); + kinc_vector2_t p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(dx + dw, dy + dh)); + image_draw_image2(img, sx, sy, sw, sh, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, kinc_g2_get_opacity(), kinc_g2_get_color()); +} + +void kinc_g2_draw_sub_image(kinc_g4_texture_t *img, float x, float y, float sx, float sy, float sw, float sh) { + kinc_g2_draw_scaled_sub_image(img, sx, sy, sw, sh, x, y, sw, sh); +} + +void kinc_g2_draw_scaled_image(kinc_g4_texture_t *img, float dx, float dy, float dw, float dh) { + kinc_g2_draw_scaled_sub_image(img, 0, 0, (float)img->tex_width, (float)img->tex_height, dx, dy, dw, dh); +} + +uint32_t kinc_g2_get_color(void) { + return my_color; +} + +void kinc_g2_set_color(uint32_t color) { + my_color = color; +} + +void kinc_g2_draw_rect(float x, float y, float width, float height, float strength /*= 1.0*/) { + image_end(); + // textPainter.end(); + + kinc_vector2_t p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y + strength / 2)); // bottom-left + kinc_vector2_t p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y - strength / 2)); // top-left + kinc_vector2_t p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y - strength / 2)); // top-right + kinc_vector2_t p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y + strength / 2)); // bottom-right + colored_fill_rect(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); // top + + p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y + height - strength / 2)); + p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y + strength / 2)); + p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + strength / 2, y + strength / 2)); + p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + strength / 2, y + height - strength / 2)); + colored_fill_rect(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); // left + + p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y + height + strength / 2)); + p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x - strength / 2, y + height - strength / 2)); + p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y + height - strength / 2)); + p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y + height + strength / 2)); + colored_fill_rect(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); // bottom + + p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width - strength / 2, y + height - strength / 2)); + p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width - strength / 2, y + strength / 2)); + p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y + strength / 2)); + p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width + strength / 2, y + height - strength / 2)); + colored_fill_rect(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); // right +} + +void kinc_g2_fill_rect(float x, float y, float width, float height) { + image_end(); + // textPainter.end(); + + kinc_vector2_t p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x, y + height)); + kinc_vector2_t p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x, y)); + kinc_vector2_t p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width, y)); + kinc_vector2_t p4 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x + width, y + height)); + colored_fill_rect(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); +} + +/*void draw_string(const char *text, float x, float y) { + imagePainter.end(); + coloredPainter.end(); + + textPainter.drawString(text, opacity, color, x, y, transformation); +}*/ + +/*void drawCharacters(const char *text, int start, int length, float x, float y) { + imagePainter.end(); + coloredPainter.end(); + + textPainter.drawCharacters(text, start, length, opacity, color, x, y, transformation); +}*/ + +/*override function get_font() : Font { + return myFont; +} + +override function set_font(font : Font) : Font { + textPainter.setFont(font); + return myFont = font; +} + +override function set_fontSize(value : Int) : Int { + return super.fontSize = textPainter.fontSize = value; +}*/ + +static kinc_vector2_t sub_vectors(kinc_vector2_t a, kinc_vector2_t b) { + return kinc_vector2_create(a.x - b.x, a.y - b.y); +} + +static float get_vector_length(kinc_vector2_t vec) { + return sqrtf(vec.x * vec.x + vec.y * vec.y); +} + +static void set_vector_length(kinc_vector2_t *vec, float length) { + float currentLength = get_vector_length(*vec); + if (currentLength == 0) { + return; + } + float mul = length / currentLength; + vec->x *= mul; + vec->y *= mul; +} + +void kinc_g2_draw_line(float x1, float y1, float x2, float y2, float strength /*= 1.0*/) { + image_end(); + // textPainter.end(); + + kinc_vector2_t vec; + if (y2 == y1) { + vec.x = 0.0f; + vec.y = -1.0f; + } + else { + vec.x = 1.0f; + vec.y = -(x2 - x1) / (y2 - y1); + } + set_vector_length(&vec, strength); + kinc_vector2_t p1; + p1.x = x1 + 0.5f * vec.x; + p1.y = y1 + 0.5f * vec.y; + kinc_vector2_t p2; + p2.x = x2 + 0.5f * vec.x; + p2.y = y2 + 0.5f * vec.y; + kinc_vector2_t p3 = sub_vectors(p1, vec); + kinc_vector2_t p4 = sub_vectors(p2, vec); + + p1 = multiply_matrix_vector(kinc_g2_get_transformation(), p1); + p2 = multiply_matrix_vector(kinc_g2_get_transformation(), p2); + p3 = multiply_matrix_vector(kinc_g2_get_transformation(), p3); + p4 = multiply_matrix_vector(kinc_g2_get_transformation(), p4); + + colored_fill_triangle(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + colored_fill_triangle(kinc_g2_get_opacity(), kinc_g2_get_color(), p3.x, p3.y, p2.x, p2.y, p4.x, p4.y); +} + +void kinc_g2_fill_triangle(float x1, float y1, float x2, float y2, float x3, float y3) { + image_end(); + // textPainter.end(); + + kinc_vector2_t p1 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x1, y1)); + kinc_vector2_t p2 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x2, y2)); + kinc_vector2_t p3 = multiply_matrix_vector(kinc_g2_get_transformation(), kinc_vector2_create(x3, y3)); + colored_fill_triangle(kinc_g2_get_opacity(), kinc_g2_get_color(), p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); +} + +static kinc_g2_image_scale_quality myImageScaleQuality = KINC_G2_IMAGE_SCALE_QUALITY_LOW; + +kinc_g2_image_scale_quality kinc_g2_get_image_scale_quality(void) { + return myImageScaleQuality; +} + +void kinc_g2_set_image_scale_quality(kinc_g2_image_scale_quality value) { + if (value == myImageScaleQuality) { + return; + } + image_set_bilinear_filter(value == KINC_G2_IMAGE_SCALE_QUALITY_HIGH); + // textPainter.setBilinearFilter(value == ImageScaleQuality.High); + myImageScaleQuality = value; +} + +static kinc_g2_image_scale_quality myMipmapScaleQuality = KINC_G2_IMAGE_SCALE_QUALITY_LOW; + +kinc_g2_image_scale_quality kinc_g2_get_mipmap_scale_quality(void) { + return myMipmapScaleQuality; +} + +void kinc_g2_set_mipmap_scale_quality(kinc_g2_image_scale_quality value) { + image_set_bilinear_mipmap_filter(value == KINC_G2_IMAGE_SCALE_QUALITY_HIGH); + // textPainter.setBilinearMipmapFilter(value == ImageScaleQuality.High); // TODO (DK) implement for fonts as well? + myMipmapScaleQuality = value; +} + +// var pipelineCache = new Map(); +// var lastPipeline : PipelineState = null; + +/*override function setPipeline(pipeline : PipelineState) : Void { + if (pipeline == lastPipeline) { + return; + } + lastPipeline = pipeline; + flush(); + if (pipeline == null) { + imagePainter.pipeline = null; + coloredPainter.pipeline = null; + textPainter.pipeline = null; + } + else { + var cache = pipelineCache[pipeline]; + if (cache == null) { + cache = new SimplePipelineCache(pipeline, true); + pipelineCache[pipeline] = cache; + } + imagePainter.pipeline = cache; + coloredPainter.pipeline = cache; + textPainter.pipeline = cache; + } +}*/ + +static bool scissorEnabled = false; +static int scissorX = -1; +static int scissorY = -1; +static int scissorW = -1; +static int scissorH = -1; + +void kinc_g2_scissor(int x, int y, int width, int height) { + // if (!scissorEnabled || x != scissorX || y != scissorY || width != scissorW || height != scissorH) { + scissorEnabled = true; + scissorX = x; + scissorY = y; + scissorW = width; + scissorH = height; + kinc_g2_flush(); + kinc_g4_scissor(x, y, width, height); + // } +} + +void kinc_g2_disable_scissor(void) { + // if (scissorEnabled) { + scissorEnabled = false; + kinc_g2_flush(); + kinc_g4_disable_scissor(); + // } +} + +void kinc_g2_begin(bool clear /*= true*/, uint32_t clear_color) { + /*if (current == NULL) { + current = this; + } + else { + // End before you begin + assert(false); + }*/ + + kinc_g4_begin(0); + if (clear) { + kinc_g2_clear(clear_color); + } + set_projection(); +} + +void kinc_g2_clear(uint32_t color) { + kinc_g2_flush(); + kinc_g4_clear(KINC_G4_CLEAR_COLOR, color, 0.0f, 0); +} + +void kinc_g2_flush(void) { + image_end(); + // textPainter.end(); + colored_end(); +} + +void kinc_g2_end(void) { + kinc_g2_flush(); + kinc_g4_end(0); + + /*if (current == this) { + current = null; + } + else { + // Begin before you end + assert(false); + }*/ +} + +// void draw_video_internal(Video *video, float x, float y, float width, float height) {} + +/*void draw_video(Video *video, float x, float y, float width, float height) { + setPipeline(videoPipeline); + drawVideoInternal(video, x, y, width, height); + setPipeline(null); +}*/ + +// font_t *get_font(void) { +// return NULL; +// } + +// void set_font(font_t *font) {} + +// int get_font_size(void) { +// return myFontSize; +// } + +// void set_font_size(int size) { +// myFontSize = size; +// } + +static int font_glyphs[256]; // [for (i in 32...256) i] + +kinc_matrix3x3_t kinc_g2_get_transformation(void) { + return transformations[transformation_index]; +} + +void kinc_g2_set_transformation(kinc_matrix3x3_t transformation) { + transformations[transformation_index] = transformation; +} + +void kinc_g2_push_transformation(kinc_matrix3x3_t trans) { + transformation_index++; + assert(transformation_index < transformations_size); + transformations[transformation_index] = trans; +} + +kinc_matrix3x3_t kinc_g2_pop_transformation() { + transformation_index--; + assert(transformation_index != -1); + return transformations[transformation_index + 1]; +} + +static kinc_matrix3x3_t scale(float x, float y) { + kinc_matrix3x3_t m; + m.m[0] = x; + m.m[1] = 0; + m.m[2] = 0; + m.m[3] = 0; + m.m[4] = y; + m.m[5] = 0; + m.m[6] = 0; + m.m[7] = 0; + m.m[8] = 1; + return m; +} + +void kinc_g2_scale(float x, float y) { + kinc_matrix3x3_t m1 = scale(x, y); + kinc_matrix3x3_t m2 = kinc_g2_get_transformation(); + kinc_g2_set_transformation(kinc_matrix3x3_multiply(&m1, &m2)); +} + +void kinc_g2_push_scale(float x, float y) { + kinc_matrix3x3_t m1 = scale(x, y); + kinc_matrix3x3_t m2 = kinc_g2_get_transformation(); + kinc_matrix3x3_t mat = kinc_matrix3x3_multiply(&m1, &m2); + kinc_g2_push_transformation(mat); +} + +kinc_matrix3x3_t kinc_g2_translation(float tx, float ty) { + kinc_matrix3x3_t m1 = kinc_matrix3x3_translation(tx, ty); + kinc_matrix3x3_t m2 = kinc_g2_get_transformation(); + return kinc_matrix3x3_multiply(&m1, &m2); +} + +void kinc_g2_translate(float tx, float ty) { + kinc_g2_set_transformation(kinc_g2_translation(tx, ty)); +} + +void kinc_g2_push_translation(float tx, float ty) { + kinc_g2_push_transformation(kinc_g2_translation(tx, ty)); +} + +static kinc_matrix3x3_t rotation(float alpha) { + kinc_matrix3x3_t m; + m.m[0] = cosf(alpha); + m.m[1] = -sinf(alpha); + m.m[2] = 0; + m.m[3] = sinf(alpha); + m.m[4] = cosf(alpha); + m.m[5] = 0; + m.m[6] = 0; + m.m[7] = 0; + m.m[8] = 1; + return m; +} + +kinc_matrix3x3_t kinc_g2_rotation(float angle, float centerx, float centery) { + kinc_matrix3x3_t m1 = kinc_matrix3x3_translation(centerx, centery); + kinc_matrix3x3_t m2 = rotation(angle); + kinc_matrix3x3_t m3 = kinc_matrix3x3_translation(-centerx, -centery); + kinc_matrix3x3_t m4 = kinc_g2_get_transformation(); + + kinc_matrix3x3_t m = kinc_matrix3x3_multiply(&m1, &m2); + m = kinc_matrix3x3_multiply(&m, &m3); + m = kinc_matrix3x3_multiply(&m, &m4); + return m; +} + +void kinc_g2_rotate(float angle, float centerx, float centery) { + kinc_g2_set_transformation(kinc_g2_rotation(angle, centerx, centery)); +} + +void kinc_g2_push_rotation(float angle, float centerx, float centery) { + kinc_g2_push_transformation(kinc_g2_rotation(angle, centerx, centery)); +} + +void kinc_g2_push_opacity(float opacity) { + opacities[opacities_size] = opacity; + opacities_size += 1; +} + +float kinc_g2_pop_opacity() { + opacities_size -= 1; + float ret = opacities[opacities_size]; + return ret; +} + +float kinc_g2_get_opacity() { + return opacities[opacities_size - 1]; +} + +void kinc_g2_set_opacity(float opacity) { + opacities[opacities_size - 1] = opacity; +} + +// PipelineState *pipe; + +// PipelineState *get_pipeline(void) { +// return pipe; +// } + +// void set_pipeline(PipelineState *pipeline) { +// setPipeline(pipeline); +// return pipe = pipeline; +// } diff --git a/Sources/kinc/graphics2/graphics.h b/Sources/kinc/graphics2/graphics.h index 4ce0ccab7..9358c28c1 100644 --- a/Sources/kinc/graphics2/graphics.h +++ b/Sources/kinc/graphics2/graphics.h @@ -13,6 +13,56 @@ extern "C" { #endif +#ifdef KINC_KONG + +typedef enum kinc_g2_image_scale_quality { + KINC_G2_IMAGE_SCALE_QUALITY_LOW, // usually point filter + KINC_G2_IMAGE_SCALE_QUALITY_HIGH // usually bilinear filter +} kinc_g2_image_scale_quality; + +// enum HorTextAlignment { TextLeft, TextCenter, TextRight }; +// enum VerTextAlignment { TextTop, TextMiddle, TextBottom }; + +void kinc_g2_init(void); +void kinc_g2_draw_image(kinc_g4_texture_t *img, float x, float y); +void kinc_g2_draw_scaled_sub_image(kinc_g4_texture_t *img, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); +void kinc_g2_draw_sub_image(kinc_g4_texture_t *img, float x, float y, float sx, float sy, float sw, float sh); +void kinc_g2_draw_scaled_image(kinc_g4_texture_t *img, float dx, float dy, float dw, float dh); +uint32_t kinc_g2_get_color(void); +void kinc_g2_set_color(uint32_t color); +void kinc_g2_draw_rect(float x, float y, float width, float height, float strength /*= 1.0*/); +void kinc_g2_fill_rect(float x, float y, float width, float height); +void kinc_g2_draw_line(float x1, float y1, float x2, float y2, float strength /*= 1.0*/); +void kinc_g2_fill_triangle(float x1, float y1, float x2, float y2, float x3, float y3); +kinc_g2_image_scale_quality kinc_g2_get_image_scale_quality(void); +void kinc_g2_set_image_scale_quality(kinc_g2_image_scale_quality value); +kinc_g2_image_scale_quality kinc_g2_get_mipmap_scale_quality(void); +void kinc_g2_set_mipmap_scale_quality(kinc_g2_image_scale_quality value); +void kinc_g2_scissor(int x, int y, int width, int height); +void kinc_g2_disable_scissor(void); +void kinc_g2_begin(bool clear /*= true*/, uint32_t clear_color); +void kinc_g2_clear(uint32_t color); +void kinc_g2_flush(void); +void kinc_g2_end(void); +kinc_matrix3x3_t kinc_g2_get_transformation(void); +void kinc_g2_set_transformation(kinc_matrix3x3_t transformation); +void kinc_g2_push_transformation(kinc_matrix3x3_t trans); +kinc_matrix3x3_t kinc_g2_pop_transformation(); +void kinc_g2_scale(float x, float y); +void kinc_g2_push_scale(float x, float y); +kinc_matrix3x3_t kinc_g2_translation(float tx, float ty); +void kinc_g2_translate(float tx, float ty); +void kinc_g2_push_translation(float tx, float ty); +kinc_matrix3x3_t kinc_g2_rotation(float angle, float centerx, float centery); +void kinc_g2_rotate(float angle, float centerx, float centery); +void kinc_g2_push_rotation(float angle, float centerx, float centery); +void kinc_g2_push_opacity(float opacity); +float kinc_g2_pop_opacity(); +float kinc_g2_get_opacity(); +void kinc_g2_set_opacity(float opacity); + +#else + void kinc_g2_init(int screen_width, int screen_height); void kinc_g2_begin(void); void kinc_g2_end(void); @@ -21,6 +71,8 @@ void kinc_g2_draw_image(kinc_image_t *img, float x, float y); // void drawScaledSubImage(Graphics4::Texture *img, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); void kinc_g2_set_rotation(float angle, float centerx, float centery); +#endif + #ifdef __cplusplus } #endif diff --git a/Sources/kinc/graphics2/graphics_soft.c b/Sources/kinc/graphics2/graphics_soft.c index 5e1baefe8..ea3dca83d 100644 --- a/Sources/kinc/graphics2/graphics_soft.c +++ b/Sources/kinc/graphics2/graphics_soft.c @@ -1,5 +1,7 @@ #include "graphics.h" +#ifndef KINC_KONG + #include #include #include @@ -283,3 +285,5 @@ void kinc_g2_set_rotation(float angle, float centerx, float centery) { kinc_matrix3x3_t transformation1 = kinc_matrix3x3_multiply(&translation1, &rotation); transform = kinc_matrix3x3_multiply(&transformation1, &translation2); } + +#endif diff --git a/Sources/kinc/graphics2/image_painter.c.h b/Sources/kinc/graphics2/image_painter.c.h new file mode 100644 index 000000000..de0376da1 --- /dev/null +++ b/Sources/kinc/graphics2/image_painter.c.h @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include + +// #include + +static kinc_matrix4x4_t image_projection_matrix; + +// static var standardImagePipeline : PipelineCache = null; +static int image_buffer_size = 1500; +static int image_vertex_size = 6; +static int image_buffer_start; +static int image_buffer_index; +static kinc_g4_vertex_buffer_t image_vertex_buffer; +static kinc_g2_image_vertex_in *image_vertices; +static kinc_g4_index_buffer_t image_index_buffer; +static kinc_g4_texture_t *image_last_texture = NULL; + +static kinc_g2_constants_type_buffer image_constants; + +static bool image_bilinear = false; +static bool image_bilinear_mipmaps = false; +// var myPipeline : PipelineCache = null; + +static void image_init_shaders(void); +static void image_init_buffers(void); + +static void image_init(void) { + image_buffer_start = 0; + image_buffer_index = 0; + image_init_shaders(); + // myPipeline = standardImagePipeline; + image_init_buffers(); +} + +// function get_pipeline() : PipelineCache { +// return myPipeline; +// } + +// function set_pipeline(pipe : PipelineCache) : PipelineCache { +// myPipeline = pipe != null ? pipe : standardImagePipeline; +// return myPipeline; +// } + +static void image_set_projection(kinc_matrix4x4_t matrix) { + image_projection_matrix = matrix; +} + +static void image_init_shaders(void) { + // if (structure == NULL) { + // structure = Graphics2.createImageVertexStructure(); + // } + // if (standardImagePipeline == null) { + // var pipeline = Graphics2.createImagePipeline(structure); + // standardImagePipeline = new PerFramebufferPipelineCache(pipeline, true); + // } +} + +static bool image_buffers_initialized = false; + +static void image_init_buffers(void) { + if (!image_buffers_initialized) { + kinc_g4_vertex_buffer_init(&image_vertex_buffer, image_buffer_size * 4, &kinc_g2_image_vertex_in_structure, KINC_G4_USAGE_DYNAMIC, 0); + image_vertices = (kinc_g2_image_vertex_in *)kinc_g4_vertex_buffer_lock_all(&image_vertex_buffer); + + kinc_g4_index_buffer_init(&image_index_buffer, image_buffer_size * 3 * 2, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC); + int *indices = (int *)kinc_g4_index_buffer_lock_all(&image_index_buffer); + for (int i = 0; i < image_buffer_size; ++i) { + indices[i * 3 * 2 + 0] = i * 4 + 0; + indices[i * 3 * 2 + 1] = i * 4 + 1; + indices[i * 3 * 2 + 2] = i * 4 + 2; + indices[i * 3 * 2 + 3] = i * 4 + 0; + indices[i * 3 * 2 + 4] = i * 4 + 2; + indices[i * 3 * 2 + 5] = i * 4 + 3; + } + kinc_g4_index_buffer_unlock_all(&image_index_buffer); + + image_buffers_initialized = true; + } +} + +static void image_set_vertices(float bottomleftx, float bottomlefty, float topleftx, float toplefty, float toprightx, float toprighty, float bottomrightx, + float bottomrighty) { + int base_index = (image_buffer_index - image_buffer_start) * 4; + + image_vertices[base_index + 0].pos.x = bottomleftx; + image_vertices[base_index + 0].pos.y = bottomlefty; + image_vertices[base_index + 0].pos.z = -5.0f; + + image_vertices[base_index + 1].pos.x = topleftx; + image_vertices[base_index + 1].pos.y = toplefty; + image_vertices[base_index + 1].pos.z = -5.0f; + + image_vertices[base_index + 2].pos.x = toprightx; + image_vertices[base_index + 2].pos.y = toprighty; + image_vertices[base_index + 2].pos.z = -5.0f; + + image_vertices[base_index + 3].pos.x = bottomrightx; + image_vertices[base_index + 3].pos.y = bottomrighty; + image_vertices[base_index + 3].pos.z = -5.0f; +} + +static void image_set_tex_coords(float left, float top, float right, float bottom) { + int base_index = (image_buffer_index - image_buffer_start) * 4; + + image_vertices[base_index + 0].tex.x = left; + image_vertices[base_index + 0].tex.y = bottom; + + image_vertices[base_index + 1].tex.x = left; + image_vertices[base_index + 1].tex.y = top; + + image_vertices[base_index + 2].tex.x = right; + image_vertices[base_index + 2].tex.y = top; + + image_vertices[base_index + 3].tex.x = right; + image_vertices[base_index + 3].tex.y = bottom; +} + +static void image_set_color(float r, float g, float b, float a) { + int base_index = (image_buffer_index - image_buffer_start) * 4; + + for (int i = 0; i < 4; ++i) { + image_vertices[base_index + i].col.x = r; + image_vertices[base_index + i].col.y = g; + image_vertices[base_index + i].col.z = b; + image_vertices[base_index + i].col.w = a; + } +} + +static void image_draw_buffer(bool end) { + if (image_buffer_index - image_buffer_start == 0) { + return; + } + + kinc_g2_constants_type *constants_data = kinc_g2_constants_type_buffer_lock(&image_constants); + constants_data->projection = image_projection_matrix; + kinc_g2_constants_type_buffer_unlock(&image_constants); + + kinc_g4_vertex_buffer_unlock(&image_vertex_buffer, (image_buffer_index - image_buffer_start) * 4); + // PipelineState *pipeline = myPipeline.get(NULL, Depth24Stencil8); + kinc_g4_set_pipeline(&kinc_g2_image_pipeline); + kinc_g4_set_vertex_buffer(&image_vertex_buffer); + kinc_g4_set_index_buffer(&image_index_buffer); + kinc_g2_constants_type_buffer_set(&image_constants); + kinc_g4_set_texture(kinc_g2_texture, image_last_texture); + // kinc_g4_set_texture_minification_filter(kinc_g2_texture, image_bilinear ? KINC_G4_TEXTURE_FILTER_LINEAR : KINC_G4_TEXTURE_FILTER_POINT); + // kinc_g4_set_texture_magnification_filter(kinc_g2_texture, image_bilinear ? KINC_G4_TEXTURE_FILTER_LINEAR : KINC_G4_TEXTURE_FILTER_POINT); + // kinc_g4_set_texture_mipmap_filter(kinc_g2_texture, image_bilinear_mipmaps ? KINC_G4_MIPMAP_FILTER_LINEAR : KINC_G4_MIPMAP_FILTER_POINT); + + kinc_g4_draw_indexed_vertices_from_to(image_buffer_start * 2 * 3, (image_buffer_index - image_buffer_start) * 2 * 3); + + kinc_g4_set_texture(kinc_g2_texture, NULL); + + if (end || (image_buffer_start + image_buffer_index + 1) * 4 >= image_buffer_size) { + image_buffer_start = 0; + image_buffer_index = 0; + image_vertices = (kinc_g2_image_vertex_in *)kinc_g4_vertex_buffer_lock_all(&image_vertex_buffer); + } + else { + image_buffer_start = image_buffer_index; + image_vertices = (kinc_g2_image_vertex_in *)kinc_g4_vertex_buffer_lock(&image_vertex_buffer, image_buffer_start * 4, + kinc_g4_vertex_buffer_count(&image_vertex_buffer) - image_buffer_start * 4); + } +} + +static void image_set_bilinear_filter(bool bilinear) { + image_draw_buffer(false); + image_last_texture = NULL; + image_bilinear = bilinear; +} + +static void image_set_bilinear_mipmap_filter(bool bilinear) { + image_draw_buffer(false); + image_last_texture = NULL; + image_bilinear_mipmaps = bilinear; +} + +static void image_draw_image(kinc_g4_texture_t *tex, float bottomleftx, float bottomlefty, float topleftx, float toplefty, float toprightx, float toprighty, + float bottomrightx, float bottomrighty, float opacity, uint32_t color) { + if (image_buffer_start + image_buffer_index + 1 >= image_buffer_size || (image_last_texture != NULL && tex != image_last_texture)) { + image_draw_buffer(false); + } + + float color_components[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + + float a = opacity * color_components[0]; + float r = a * color_components[1]; + float g = a * color_components[2]; + float b = a * color_components[3]; + + image_set_tex_coords(0, 0, (float)tex->tex_width, (float)tex->tex_height); + image_set_color(r, g, b, a * opacity); + image_set_vertices(bottomleftx, bottomlefty, topleftx, toplefty, toprightx, toprighty, bottomrightx, bottomrighty); + + ++image_buffer_index; + image_last_texture = tex; +} + +static void image_draw_image2(kinc_g4_texture_t *tex, float sx, float sy, float sw, float sh, float bottomleftx, float bottomlefty, float topleftx, + float toplefty, float toprightx, float toprighty, float bottomrightx, float bottomrighty, float opacity, uint32_t color) { + if (image_buffer_start + image_buffer_index + 1 >= image_buffer_size || (image_last_texture != NULL && tex != image_last_texture)) { + image_draw_buffer(false); + } + + float color_components[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + + float a = opacity * color_components[0]; + float r = a * color_components[1]; + float g = a * color_components[2]; + float b = a * color_components[3]; + + image_set_tex_coords(sx / tex->tex_width, sy / tex->tex_height, (sx + sw) / tex->tex_width, (sy + sh) / tex->tex_height); + image_set_color(r, g, b, a * opacity); + image_set_vertices(bottomleftx, bottomlefty, topleftx, toplefty, toprightx, toprighty, bottomrightx, bottomrighty); + + ++image_buffer_index; + image_last_texture = tex; +} + +static void image_draw_image_scale(kinc_g4_texture_t *tex, float sx, float sy, float sw, float sh, float left, float top, float right, float bottom, + float opacity, uint32_t color) { + if (image_buffer_start + image_buffer_index + 1 >= image_buffer_size || (image_last_texture != NULL && tex != image_last_texture)) { + image_draw_buffer(false); + } + + float color_components[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + + float a = opacity * color_components[0]; + float r = a * color_components[1]; + float g = a * color_components[2]; + float b = a * color_components[3]; + + image_set_tex_coords(sx / tex->tex_width, sy / tex->tex_height, (sx + sw) / tex->tex_width, (sy + sh) / tex->tex_height); + image_set_color(r, g, b, a * opacity); + image_set_vertices(left, bottom, left, top, right, top, right, bottom); + + ++image_buffer_index; + image_last_texture = tex; +} + +static void image_end(void) { + if (image_buffer_index > 0) { + image_draw_buffer(true); + } + image_last_texture = NULL; +} diff --git a/Sources/kinc/graphics2/text_painter.c.h b/Sources/kinc/graphics2/text_painter.c.h new file mode 100644 index 000000000..658a613e3 --- /dev/null +++ b/Sources/kinc/graphics2/text_painter.c.h @@ -0,0 +1,269 @@ +/*class TextShaderPainter { + var projectionMatrix : FastMatrix4; + + static var standardTextPipeline : PipelineCache = null; + static var structure : VertexStructure = null; + static inline var bufferSize : Int = 1000; + static var bufferIndex : Int; + static var rectVertexBuffer : VertexBuffer; + static var rectVertices : Float32Array; + static var indexBuffer : IndexBuffer; + + var font : Kravur; + + static var lastTexture : Image; + + var g : Graphics; + var myPipeline : PipelineCache = null; + +public + var pipeline(get, set) : PipelineCache; +public + var fontSize : Int; + + var bilinear : Bool = false; + +public + function new(g4 : Graphics) { + this.g = g4; + bufferIndex = 0; + initShaders(); + myPipeline = standardTextPipeline; + initBuffers(); + } + + function get_pipeline() : PipelineCache { + return myPipeline; + } + + function set_pipeline(pipe : PipelineCache) : PipelineCache { + myPipeline = pipe != null ? pipe : standardTextPipeline; + return myPipeline; + } + +public + function setProjection(projectionMatrix : FastMatrix4) : Void { + this.projectionMatrix = projectionMatrix; + } + + static function initShaders() : Void { + if (structure == null) { + structure = Graphics2.createTextVertexStructure(); + } + if (standardTextPipeline == null) { + var pipeline = Graphics2.createTextPipeline(structure); + standardTextPipeline = new PerFramebufferPipelineCache(pipeline, true); + } + } + + function initBuffers() : Void { + if (rectVertexBuffer == null) { + rectVertexBuffer = new VertexBuffer(bufferSize * 4, structure, Usage.DynamicUsage); + rectVertices = rectVertexBuffer.lock(); + + indexBuffer = new IndexBuffer(bufferSize * 3 * 2, Usage.StaticUsage); + var indices = indexBuffer.lock(); + for (i in 0...bufferSize) { + indices[i * 3 * 2 + 0] = i * 4 + 0; + indices[i * 3 * 2 + 1] = i * 4 + 1; + indices[i * 3 * 2 + 2] = i * 4 + 2; + indices[i * 3 * 2 + 3] = i * 4 + 0; + indices[i * 3 * 2 + 4] = i * 4 + 2; + indices[i * 3 * 2 + 5] = i * 4 + 3; + } + indexBuffer.unlock(); + } + } + + function setRectVertices(bottomleftx + : Float, bottomlefty + : Float, topleftx + : Float, toplefty + : Float, toprightx + : Float, toprighty + : Float, bottomrightx + : Float, bottomrighty + : Float) + : Void { + var baseIndex : Int = bufferIndex * 9 * 4; + rectVertices.set(baseIndex + 0, bottomleftx); + rectVertices.set(baseIndex + 1, bottomlefty); + rectVertices.set(baseIndex + 2, -5.0); + + rectVertices.set(baseIndex + 9, topleftx); + rectVertices.set(baseIndex + 10, toplefty); + rectVertices.set(baseIndex + 11, -5.0); + + rectVertices.set(baseIndex + 18, toprightx); + rectVertices.set(baseIndex + 19, toprighty); + rectVertices.set(baseIndex + 20, -5.0); + + rectVertices.set(baseIndex + 27, bottomrightx); + rectVertices.set(baseIndex + 28, bottomrighty); + rectVertices.set(baseIndex + 29, -5.0); + } + + function setRectTexCoords(left : Float, top : Float, right : Float, bottom : Float) : Void { + var baseIndex : Int = bufferIndex * 9 * 4; + rectVertices.set(baseIndex + 3, left); + rectVertices.set(baseIndex + 4, bottom); + + rectVertices.set(baseIndex + 12, left); + rectVertices.set(baseIndex + 13, top); + + rectVertices.set(baseIndex + 21, right); + rectVertices.set(baseIndex + 22, top); + + rectVertices.set(baseIndex + 30, right); + rectVertices.set(baseIndex + 31, bottom); + } + + function setRectColors(opacity : FastFloat, color : Color) : Void { + var baseIndex : Int = bufferIndex * 9 * 4; + var a : FastFloat = opacity * color.A; + rectVertices.set(baseIndex + 5, color.R); + rectVertices.set(baseIndex + 6, color.G); + rectVertices.set(baseIndex + 7, color.B); + rectVertices.set(baseIndex + 8, a); + + rectVertices.set(baseIndex + 14, color.R); + rectVertices.set(baseIndex + 15, color.G); + rectVertices.set(baseIndex + 16, color.B); + rectVertices.set(baseIndex + 17, a); + + rectVertices.set(baseIndex + 23, color.R); + rectVertices.set(baseIndex + 24, color.G); + rectVertices.set(baseIndex + 25, color.B); + rectVertices.set(baseIndex + 26, a); + + rectVertices.set(baseIndex + 32, color.R); + rectVertices.set(baseIndex + 33, color.G); + rectVertices.set(baseIndex + 34, color.B); + rectVertices.set(baseIndex + 35, a); + } + + function drawBuffer() : Void { + if (bufferIndex == 0) { + return; + } + + rectVertexBuffer.unlock(bufferIndex * 4); + var pipeline = myPipeline.get(null, Depth24Stencil8); + g.setPipeline(pipeline.pipeline); + g.setVertexBuffer(rectVertexBuffer); + g.setIndexBuffer(indexBuffer); + g.setMatrix(pipeline.projectionLocation, projectionMatrix); + g.setTexture(pipeline.textureLocation, lastTexture); + g.setTextureParameters(pipeline.textureLocation, TextureAddressing.Clamp, TextureAddressing.Clamp, + bilinear ? TextureFilter.LinearFilter : TextureFilter.PointFilter, + bilinear ? TextureFilter.LinearFilter : TextureFilter.PointFilter, MipMapFilter.NoMipFilter); + + g.drawIndexedVertices(0, bufferIndex * 2 * 3); + + g.setTexture(pipeline.textureLocation, null); + bufferIndex = 0; + rectVertices = rectVertexBuffer.lock(); + } + +public + function setBilinearFilter(bilinear : Bool) : Void { + end(); + this.bilinear = bilinear; + } + +public + function setFont(font : Font) : Void { + this.font = cast(font, Kravur); + } + + static function findIndex(charCode : Int) : Int { + // var glyphs = kha.graphics2.Graphics.fontGlyphs; + var blocks = Kravur.KravurImage.charBlocks; + var offset = 0; + for (i in 0...Std.int(blocks.length / 2)) { + var start = blocks[i * 2]; + var end = blocks[i * 2 + 1]; + if (charCode >= start && charCode <= end) + return offset + charCode - start; + offset += end - start + 1; + } + return 0; + } + + var bakedQuadCache = new kha.Kravur.AlignedQuad(); + +public + function drawString(text : String, opacity : FastFloat, color : Color, x : Float, y : Float, transformation : FastMatrix3) : Void { + var font = this.font._get(fontSize); + var tex = font.getTexture(); + if (lastTexture != null && tex != lastTexture) + drawBuffer(); + lastTexture = tex; + + var xpos = x; + var ypos = y; + for (i in 0...text.length) { + var charCode = StringTools.fastCodeAt(text, i); + var q = font.getBakedQuad(bakedQuadCache, findIndex(charCode), xpos, ypos); + if (q != null) { + if (bufferIndex + 1 >= bufferSize) + drawBuffer(); + setRectColors(opacity, color); + setRectTexCoords(q.s0 * tex.width / tex.realWidth, q.t0 * tex.height / tex.realHeight, q.s1 * tex.width / tex.realWidth, + q.t1 * tex.height / tex.realHeight); + var p0 = transformation.multvec(new FastVector2(q.x0, q.y1)); // bottom-left + var p1 = transformation.multvec(new FastVector2(q.x0, q.y0)); // top-left + var p2 = transformation.multvec(new FastVector2(q.x1, q.y0)); // top-right + var p3 = transformation.multvec(new FastVector2(q.x1, q.y1)); // bottom-right + setRectVertices(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + xpos += q.xadvance; + ++bufferIndex; + } + } + } + +public + function drawCharacters(text + : Array, start + : Int, length + : Int, opacity + : FastFloat, color + : Color, x + : Float, y + : Float, transformation + : FastMatrix3) + : Void { + var font = this.font._get(fontSize); + var tex = font.getTexture(); + if (lastTexture != null && tex != lastTexture) + drawBuffer(); + lastTexture = tex; + + var xpos = x; + var ypos = y; + for (i in start... start + length) { + var q = font.getBakedQuad(bakedQuadCache, findIndex(text[i]), xpos, ypos); + if (q != null) { + if (bufferIndex + 1 >= bufferSize) + drawBuffer(); + setRectColors(opacity, color); + setRectTexCoords(q.s0 * tex.width / tex.realWidth, q.t0 * tex.height / tex.realHeight, q.s1 * tex.width / tex.realWidth, + q.t1 * tex.height / tex.realHeight); + var p0 = transformation.multvec(new FastVector2(q.x0, q.y1)); // bottom-left + var p1 = transformation.multvec(new FastVector2(q.x0, q.y0)); // top-left + var p2 = transformation.multvec(new FastVector2(q.x1, q.y0)); // top-right + var p3 = transformation.multvec(new FastVector2(q.x1, q.y1)); // bottom-right + setRectVertices(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); + xpos += q.xadvance; + ++bufferIndex; + } + } + } + +public + function end() : Void { + if (bufferIndex > 0) + drawBuffer(); + lastTexture = null; + } +}*/ diff --git a/Sources/kinc/math/matrix.h b/Sources/kinc/math/matrix.h index 88c6ea08a..0bc220954 100644 --- a/Sources/kinc/math/matrix.h +++ b/Sources/kinc/math/matrix.h @@ -34,6 +34,7 @@ typedef struct kinc_matrix4x4 { KINC_FUNC float kinc_matrix4x4_get(kinc_matrix4x4_t *matrix, int x, int y); KINC_FUNC void kinc_matrix4x4_set(kinc_matrix4x4_t *matrix, int x, int y, float value); KINC_FUNC void kinc_matrix4x4_transpose(kinc_matrix4x4_t *matrix); +KINC_FUNC kinc_matrix4x4_t kinc_matrix4x4_identity(void); KINC_FUNC kinc_matrix4x4_t kinc_matrix4x4_multiply(kinc_matrix4x4_t *a, kinc_matrix4x4_t *b); #ifdef KINC_IMPLEMENTATION_MATH @@ -178,6 +179,15 @@ void kinc_matrix4x4_transpose(kinc_matrix4x4_t *matrix) { memcpy(matrix->m, transposed.m, sizeof(transposed.m)); } +kinc_matrix4x4_t kinc_matrix4x4_identity(void) { + kinc_matrix4x4_t m; + memset(m.m, 0, sizeof(m.m)); + for (unsigned x = 0; x < 4; ++x) { + kinc_matrix4x4_set(&m, x, x, 1.0f); + } + return m; +} + kinc_matrix4x4_t kinc_matrix4x4_multiply(kinc_matrix4x4_t *a, kinc_matrix4x4_t *b) { kinc_matrix4x4_t result; for (unsigned x = 0; x < 4; ++x)