金属着色器在 iOS Swift 中应用灰度滤镜时垂直拉伸相机预览

问题描述 投票:0回答:1

我正在构建一个 iOS 应用程序,在其中使用 Metal 着色器将灰度滤镜应用于实时摄像机源。灰度效果效果很好,但是当我应用它时,相机预览会垂直拉伸。下面是我的 Metal 着色器和相机预览设置的代码。

着色器.金属

#include <metal_stdlib>
using namespace metal;

typedef struct {
    float4 renderedCoordinate [[position]];
    float2 textureCoordinate;
} TextureMappingVertex;

vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[vertex_id]]) {
    float4x4 renderedCoordinates = float4x4(
        float4( -1.0, -1.0, 0.0, 1.0 ),
        float4(  1.0, -1.0, 0.0, 1.0 ),
        float4( -1.0,  1.0, 0.0, 1.0 ),
        float4(  1.0,  1.0, 0.0, 1.0 )
    );

    float4x2 textureCoordinates = float4x2(
        float2( 0.0, 1.0 ),
        float2( 1.0, 1.0 ),
        float2( 0.0, 0.0 ),
        float2( 1.0, 0.0 )
    );

    TextureMappingVertex outVertex;
    outVertex.renderedCoordinate = renderedCoordinates[vertex_id];
    outVertex.textureCoordinate = textureCoordinates[vertex_id];
    
    return outVertex;
}

fragment half4 displayTexture(TextureMappingVertex mappingVertex [[stage_in]],
                              texture2d<float, access::sample> texture [[texture(0)]]) {
    constexpr sampler s(address::clamp_to_edge, filter::linear);
    float4 color = texture.sample(s, mappingVertex.textureCoordinate);
    float grayscale = (color.r + color.g + color.b) / 3.0;
    return half4(grayscale, grayscale, grayscale, color.a);
}

问题:

  • 着色器正确地将相机输入转换为灰度。
  • 但是,相机预览会垂直拉伸,从而导致图像扭曲。
  • 映射纹理时,相机馈送的长宽比似乎被忽略。

附加信息:

  • 我使用相机提要作为纹理。
  • 除了垂直拉伸之外,代码工作正常。
  • 我认为问题在于纹理坐标如何映射到屏幕,我需要帮助解决这个问题。

目标:

  • 我希望纹理适合屏幕而不拉伸,保持正确的宽高比。
  • 如何修改顶点着色器以确保纹理正确缩放以适应屏幕而不失真?
ios camera shader metal aspect-ratio
1个回答
1
投票

您可以根据屏幕高度和屏幕宽度设置float4x2纹理坐标的大小 只需将其传递给着色器顶点函数,然后根据屏幕的纵横比更改 float4x2 纹理坐标

float screenWidth = screenParams.screenWidth;
float screenHeight =  screenParams.screenHeight;
float screenAspectRatio = (screenWidth / screenHeight) + 0.3;

float2 topLeft = float2(0.0, 1.0);
float2 topRight = float2(1.0, 1.0);
float2 bottomLeft = float2(0.0, 0.0);
float2 bottomRight = float2(1.0, 0.0);

topLeft.x *= screenAspectRatio;
topRight.x *= screenAspectRatio;
bottomLeft.x *= screenAspectRatio;
bottomRight.x *= screenAspectRatio;

float4x2 textureCoordinates = float4x2(topLeft, topRight, bottomLeft, bottomRight);

此后就不会再拉伸了

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.