[canvas, metal] compute uv coords in shader using uvTransformed computed in canvas backend, using shape bounding box, image dimension, source and dest regions

This commit is contained in:
Martin Fouilleul 2023-02-24 18:50:46 +01:00
parent fd4c4e7be3
commit 5be019d166
5 changed files with 40 additions and 30 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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)};

View File

@ -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;

View File

@ -267,15 +267,10 @@ kernel void RenderKernel(texture2d<float, access::write> 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<float, access::write> 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)