From 5be019d16600980faca5e93071ede446db16e6fd Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Fri, 24 Feb 2023 18:50:46 +0100 Subject: [PATCH] [canvas, metal] compute uv coords in shader using uvTransformed computed in canvas backend, using shape bounding box, image dimension, source and dest regions --- src/graphics.c | 36 ++++++++++++++++++++++++++++-------- src/graphics_internal.h | 7 ++----- src/mtl_canvas.m | 7 ++----- src/mtl_shader.h | 3 +-- src/mtl_shader.metal | 17 +++++++---------- 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/graphics.c b/src/graphics.c index 6782eda..ee58e7f 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -98,6 +98,8 @@ typedef struct mg_canvas_data u32 vertexCount; u32 indexCount; + mg_image currentImage; + mg_resource_pool imagePool; vec2 atlasPos; @@ -605,7 +607,26 @@ u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color) boxMax.y = maximum(boxMax.y, pos.y); } int prevIndex = canvas->nextShapeIndex-1; - *(mp_rect*)(((char*)layout->boxBuffer) + prevIndex*layout->boxStride) = (mp_rect){boxMin.x, boxMin.y, boxMax.x, boxMax.y}; + + vec2 texSize = mg_image_size(canvas->currentImage); + mp_rect srcRegion = {0, 0, texSize.x, texSize.y}; + mp_rect destRegion = {boxMin.x, boxMin.y, boxMax.x - boxMin.x, boxMax.y - boxMin.y}; + + mg_mat2x3 srcRegionToTexture = {1/texSize.x, 0, srcRegion.x/texSize.x, + 0, 1/texSize.y, srcRegion.y/texSize.y}; + mg_mat2x3 destRegionToSrcRegion = {srcRegion.w/destRegion.w, 0, 0, + 0, srcRegion.h/destRegion.h, 0}; + mg_mat2x3 userToDestRegion = {1, 0, -destRegion.x, + 0, 1, -destRegion.y}; + mg_mat2x3 screenToUser = {1, 0, 0, + 0, 1, 0}; + + mg_mat2x3 uvTransform = srcRegionToTexture; + uvTransform = mg_mat2x3_mul_m(uvTransform, destRegionToSrcRegion); + uvTransform = mg_mat2x3_mul_m(uvTransform, userToDestRegion); + uvTransform = mg_mat2x3_mul_m(uvTransform, screenToUser); + + *(mg_mat2x3*)(layout->uvTransformBuffer + prevIndex*layout->uvTransformStride) = uvTransform; } int index = canvas->nextShapeIndex; @@ -617,9 +638,8 @@ u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color) canvas->clip.x + canvas->clip.w - 1, canvas->clip.y + canvas->clip.h - 1}; - *(vec2*)(((char*)layout->uvBuffer) + index*layout->uvStride) = uv; - *(mg_color*)(((char*)layout->colorBuffer) + index*layout->colorStride) = color; *(mp_rect*)(((char*)layout->clipBuffer) + index*layout->clipStride) = clip; + *(mg_color*)(((char*)layout->colorBuffer) + index*layout->colorStride) = color; return(index); @@ -2937,7 +2957,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt 0, 1, 0}; canvas->clip = (mp_rect){-FLT_MAX/2, -FLT_MAX/2, FLT_MAX, FLT_MAX}; - mg_image currentImage = mg_image_nil(); + canvas->currentImage = mg_image_nil(); canvas->backend->begin(canvas->backend); @@ -2951,11 +2971,11 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt mg_primitive* primitive = &(primitives[nextIndex]); nextIndex++; - if(i && primitive->attributes.image.h != currentImage.h) + if(i && primitive->attributes.image.h != canvas->currentImage.h) { - mg_image_data* imageData = mg_image_data_from_handle(canvas, currentImage); + mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->currentImage); mg_flush_batch(canvas, imageData); - currentImage = primitive->attributes.image; + canvas->currentImage = primitive->attributes.image; } switch(primitive->cmd) @@ -3065,7 +3085,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt } exit_command_loop: ; - mg_image_data* imageData = mg_image_data_from_handle(canvas, currentImage); + mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->currentImage); mg_flush_batch(canvas, imageData); canvas->backend->end(canvas->backend); diff --git a/src/graphics_internal.h b/src/graphics_internal.h index cddcbdf..282580d 100644 --- a/src/graphics_internal.h +++ b/src/graphics_internal.h @@ -203,8 +203,8 @@ typedef struct mg_vertex_layout char* cubicBuffer; u32 cubicStride; - char* uvBuffer; - u32 uvStride; + char* uvTransformBuffer; + u32 uvTransformStride; char* colorBuffer; u32 colorStride; @@ -212,9 +212,6 @@ typedef struct mg_vertex_layout char* shapeIndexBuffer; u32 shapeIndexStride; - char* boxBuffer; - u32 boxStride; - char* clipBuffer; u32 clipStride; diff --git a/src/mtl_canvas.m b/src/mtl_canvas.m index 0868af1..2a43f2d 100644 --- a/src/mtl_canvas.m +++ b/src/mtl_canvas.m @@ -271,11 +271,8 @@ void mg_mtl_canvas_update_vertex_layout(mg_mtl_canvas_backend* backend) .colorStride = sizeof(mg_shape), .clipBuffer = shapeBase + offsetof(mg_shape, clip), .clipStride = sizeof(mg_shape), - .uvBuffer = shapeBase + offsetof(mg_shape, uv), - .uvStride = sizeof(mg_shape), - - .boxBuffer = shapeBase + offsetof(mg_shape, box), - .boxStride = sizeof(mg_shape), + .uvTransformBuffer = shapeBase + offsetof(mg_shape, uvTransform), + .uvTransformStride = sizeof(mg_shape), .indexBuffer = indexBase, .indexStride = sizeof(int)}; diff --git a/src/mtl_shader.h b/src/mtl_shader.h index 0e3d86d..c44f617 100644 --- a/src/mtl_shader.h +++ b/src/mtl_shader.h @@ -29,8 +29,7 @@ typedef struct mg_shape { vector_float4 color; vector_float4 clip; - vector_float4 box; - vector_float2 uv; // texture coordinates? + float uvTransform[6]; } mg_shape; diff --git a/src/mtl_shader.metal b/src/mtl_shader.metal index 8f43c0d..6c2ad0b 100644 --- a/src/mtl_shader.metal +++ b/src/mtl_shader.metal @@ -267,15 +267,10 @@ kernel void RenderKernel(texture2d outTexture [[texture(0) int shapeIndex = v0->shapeIndex; float4 color = shapeBuffer[shapeIndex].color; - ///////////////////////////////////////////////////////////////////////// - float4 shapeBox = shapeBuffer[shapeIndex].box * contentsScaling[0]; - - float2 uv0 = (p0 - shapeBox.xy)/(shapeBox.zw - shapeBox.xy); - float2 uv1 = (p1 - shapeBox.xy)/(shapeBox.zw - shapeBox.xy); - float2 uv2 = (p2 - shapeBox.xy)/(shapeBox.zw - shapeBox.xy); - ///////////////////////////////////////////////////////////////////////// - - + const device float* uvTransform2x3 = shapeBuffer[shapeIndex].uvTransform; + matrix_float3x3 uvTransform = {{uvTransform2x3[0], uvTransform2x3[3], 0}, + {uvTransform2x3[1], uvTransform2x3[4], 0}, + {uvTransform2x3[2], uvTransform2x3[5], 1}}; for(int i=0; i<6; i++) { @@ -294,7 +289,9 @@ kernel void RenderKernel(texture2d outTexture [[texture(0) if(((int)w0+bias0) >= 0 && ((int)w1+bias1) >= 0 && ((int)w2+bias2) >= 0) { float4 cubic = (cubic0*w0 + cubic1*w1 + cubic2*w2)/(w0+w1+w2); - float2 uv = (uv0*w0 + uv1*w1 + uv2*w2)/(w0+w1+w2); + + //float2 uv = (uv0*w0 + uv1*w1 + uv2*w2)/(w0+w1+w2); + float2 uv = (uvTransform*(float3(samplePoint.xy/contentsScaling[0], 1))).xy; float4 texColor = float4(1, 1, 1, 1); if(*useTexture)