Ios 金属碎片着色器中的随机错误噪声

Ios 金属碎片着色器中的随机错误噪声,ios,random,fragment-shader,metal,distortion,Ios,Random,Fragment Shader,Metal,Distortion,我的圈子扭曲了,很糟糕 我正在写一个片段着色器来做一些图像转换,我看到一些随机错误噪声,不确定是怎么回事 我正在合并两个纹理,一个是read with.read(gid);使用取样器读取一次。样品(s,uv) 我在Swift中创建了采样器,并将其传递给着色器 以下是我如何将纹理传递到着色器: texture2d<float, access::write> outTexture [[ texture(0) ]], texture2d<float, access::read>

我的圈子扭曲了,很糟糕

我正在写一个片段着色器来做一些图像转换,我看到一些随机错误噪声,不确定是怎么回事

我正在合并两个纹理,一个是read with.read(gid);使用取样器读取一次。样品(s,uv)

我在Swift中创建了采样器,并将其传递给着色器

以下是我如何将纹理传递到着色器:

texture2d<float, access::write> outTexture [[ texture(0) ]],
texture2d<float, access::read> inTextureA [[ texture(1) ]],
texture2d<float, access::sample> inTextureB [[ texture(2) ]]
以下是我看到的:

有人知道发生了什么事吗

更新:

所以我现在已经从一个计算着色器切换到一个片段着色器,并使用一个简单的四边形绘制,下面是它的设置方式:

Swift-Vertecies:

let a = Vertex(x: -1.0, y: -1.0, s: 0.0, t: 0.0)
let b = Vertex(x: 1.0, y: -1.0, s: 1.0, t: 0.0)
let c = Vertex(x: -1.0, y: 1.0, s: 0.0, t: 1.0)
let d = Vertex(x: 1.0, y: 1.0, s: 1.0, t: 1.0)
let verticesArray: Array<Vertex> = [a,b,c,b,c,d]
var vertexData = Array<Float>()
for vertex in verticesArray {
    vertexData += vertex.floatBuffer()
}
let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0])
self.vertexBuffer = metalDevice.makeBuffer(bytes: vertexData, length: dataSize, options: [])!
Swift-取样器:

let samplerDescriptor = MTLSamplerDescriptor()
self.samplerState = metalDevice.makeSamplerState(descriptor: samplerDescriptor)!
Swift-纹理:

let width = CVPixelBufferGetWidth(self.pixelBuffer)
let height = CVPixelBufferGetHeight(self.pixelBuffer)
var cvTextureOut: CVMetalTexture?
CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, self.textureCache!, self.pixelBuffer, nil, .bgra8Unorm, width, height, 0, &cvTextureOut)
guard let cvTexture = cvTextureOut, let inputTexture = CVMetalTextureGetTexture(cvTexture) else {
    print("Failed to create metal texture")
    return nil
}
Swift-呈现:

let commandBuffer = self.commandQueue.makeCommandBuffer()!
guard let currenDrawable: CAMetalDrawable = self.currentDrawable else { return }

let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = currenDrawable.texture

let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)!

var unifroms: [Float] = ...
let uniformBuffer = self.device?.makeBuffer(length: MemoryLayout<Float>.size * unifroms.count, options: [])
let bufferPointer = uniformBuffer?.contents()
memcpy(bufferPointer, &unifroms, MemoryLayout<Float>.size * unifroms.count)
renderCommandEncoder.setFragmentBuffer(uniformBuffer, offset: 0, index: 0)

renderCommandEncoder.setFragmentTexture(currenDrawable.texture, index: 0)
renderCommandEncoder.setFragmentTexture(inputTexture, index: 1)

renderCommandEncoder.setFragmentSamplerState(self.samplerState, index: 0)


renderCommandEncoder.setRenderPipelineState(self.pipelineState)


renderCommandEncoder.setVertexBuffer(self.vertexBuffer, offset: 0, index: 0)
renderCommandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6, instanceCount: 2)


renderCommandEncoder.endEncoding()

commandBuffer.present(currenDrawable)
commandBuffer.commit()
让commandBuffer=self.commandQueue.makeCommandBuffer()!
guard let currenDrawable:CAMetalDrawable=self.currentDrawable else{return}
让renderPassDescriptor=MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0]。纹理=currenDrawable.texture
让renderCommandEncoder=commandBuffer.MakerRenderCommandEncoder(描述符:renderPassDescriptor)!
变量unifroms:[浮点]=。。。
让uniformBuffer=self.device?.makeBuffer(长度:MemoryLayout.size*unifroms.count,选项:[])
设bufferPointer=uniformBuffer?.contents()
memcpy(bufferPointer,&unifroms,MemoryLayout.size*unifroms.count)
renderCommandEncoder.setFragmentBuffer(uniformBuffer,偏移量:0,索引:0)
renderCommandEncoder.setFragmentTexture(currenDrawable.texture,索引:0)
renderCommandEncoder.setFragmentTexture(inputTexture,索引:1)
renderCommandEncoder.setFragmentSamplerState(self.samplerState,索引:0)
renderCommandEncoder.setRenderPipelineState(self.pipelineState)
renderCommandEncoder.setVertexBuffer(self.vertexBuffer,偏移量:0,索引:0)
renderCommandEncoder.drawPrimitives(类型:.triangle,vertexStart:0,vertexCount:6,instanceCount:2)
renderCommandEncoder.endencode()
commandBuffer.present(currenDrawable)
commandBuffer.commit()
金属-顶点着色器:

#include <metal_stdlib>
using namespace metal;

struct VertexIn{
    packed_float2 position;
    packed_float2 texCoord;
};

struct VertexOut{
    float4 position [[position]];
    float2 texCoord;
};

vertex VertexOut basic_vertex(const device VertexIn* vertex_array [[ buffer(0) ]],
                              unsigned int vid [[ vertex_id ]]) {

    VertexIn vertexIn = vertex_array[vid];

    VertexOut vertexOut;
    vertexOut.position = float4(vertexIn.position[0], vertexIn.position[1], 0, 1);
    vertexOut.texCoord = vertexIn.texCoord;

    return vertexOut;
}
#包括
使用金属;
结构蛋白{
2位填料;
包装浮标2德士古;
};
结构顶点输出{
浮动4位[[位]];
2特克斯库德;
};
顶点顶点输出基本顶点(常数设备顶点*顶点数组[[缓冲区(0)],
无符号整数vid[[vertex_id]]{
VertexIn VertexIn=顶点数组[vid];
顶点输出顶点输出;
vertexOut.position=float4(顶点位置[0],顶点位置[1],0,1);
vertexOut.texCoord=vertexIn.texCoord;
返回顶点;
}
金属碎片着色器:

#include <metal_stdlib>
using namespace metal;

struct VertexOut{
    float4 position [[position]];
    float2 texCoord;
};

struct Uniforms{
    float rot;
    float tx;
    float ty;
    float sx;
    float sy;
};

fragment float4 transform(VertexOut out [[stage_in]],
                          texture2d<float>  inTex [[ texture(0) ]],
                          const device Uniforms& in [[ buffer(0) ]],
                          sampler s [[ sampler(0) ]]) {

    float pi = 3.14159265359;

    float u = out.texCoord[0];
    float v = out.texCoord[1];

    float2 size = float2(in.sx, in.sy);

    float ang = atan2(v - 0.5 - in.ty, u - 0.5 - in.tx) + (-in.rot / 360) * pi * 2;
    float amp = sqrt(pow(u - 0.5 - in.tx, 2) + pow(v - 0.5 - in.ty, 2));
    float2 uv = float2(cos(ang) * amp, sin(ang) * amp) / size + 0.5;
    float4 c = inTex.sample(s, uv);

    float r = c.r;
    float g = c.g;
    float b = c.b;

    return float4(r, g, b, 1.0);
}
#包括
使用金属;
结构顶点输出{
浮动4位[[位]];
2特克斯库德;
};
结构制服{
漂浮腐烂;
浮动发送;
浮雕;
浮动sx;
漂浮物;
};
片段浮动4变换(顶点输出[[stage_in]],
纹理2D inTex[[纹理(0)],
常量设备制服和在[[缓冲区(0)]]中,
取样器s[[取样器(0)]){
浮点数pi=3.14159265359;
float u=out.texCoord[0];
float v=out.texCoord[1];
float2大小=float2(in.sx,in.sy);
浮子ang=atan2(v-0.5-in.ty,u-0.5-in.tx)+(-in.rot/360)*π*2;
浮动放大器=平方管(功率(u-0.5-in.tx,2)+功率(v-0.5-in.ty,2));
float2 uv=float2(cos(ang)*amp,sin(ang)*amp)/大小+0.5;
float4 c=内部样品(s,uv);
浮点数r=c.r;
浮球g=c.g;
浮动b=c.b;
返回浮点数4(r、g、b、1.0);
}
这就是一切

即使我做了这个巨大的重构,我所剩下的只是我的圈子以一种新的方式扭曲了:

顺便说一句,我运行了大部分代码两次,一次用于创建圆(该着色器工作),两次用于变换圆(上面的着色器)

有人看到我犯了什么错误吗

我真的希望我的圆圈是圆的

最终更新:

我知道了

我试着变得聪明,在“Swift-Render:”部分中循环了两次,而现在,我在所有部分中循环了两次,并将当前可绘制纹理作为纹理输入传递给.setFragmentTexture,现在效果很好。所以几乎相同的代码只是一种不同的执行方式


我的圆现在是圆的。

碎片着色器中的
gid
是什么?(对于计算着色器,我可能会假设它是一个使用
thread\u position\u in_grid
属性限定的参数,但这不适用于片段着色器。)@kenthomass我从教程中获得了“gid”,它的声明如下:“uint2 gid[[thread\u position\u in_grid]]”,这就是我获得xy坐标的方式,不确定是否有其他方法获取uv坐标?那么您使用的不是片段着色器,而是计算着色器。另外,网格相对于这三种纹理有多大?它们的大小都一样吗?哦,好吧,我很惊讶它能工作,我应该切换到片段着色器。我所有的纹理都是1024x1024。我想你需要展示更多的代码。显示您一直使用的整个着色器函数。另外,使用每个线程组的线程值和每个网格的线程组值显示分派调用。片段着色器中的
gid
是什么?(对于计算着色器,我可能会假设它是一个使用
thread\u position\u in_grid
属性限定的参数,但这不适用于片段着色器。)@kenthomass我从教程中获得了“gid”,它的声明如下:“uint2 gid[[thread\u position\u in_grid]]”,这就是我获得xy坐标的方式,不确定是否有其他方法获取uv坐标?那么您使用的不是片段着色器,而是计算着色器。另外,网格相对于这三种纹理有多大?它们的大小都一样吗?哦,好吧,我很惊讶它能工作,我应该切换到片段着色器。我所有的纹理都是1024x1024。我想是的
#include <metal_stdlib>
using namespace metal;

struct VertexIn{
    packed_float2 position;
    packed_float2 texCoord;
};

struct VertexOut{
    float4 position [[position]];
    float2 texCoord;
};

vertex VertexOut basic_vertex(const device VertexIn* vertex_array [[ buffer(0) ]],
                              unsigned int vid [[ vertex_id ]]) {

    VertexIn vertexIn = vertex_array[vid];

    VertexOut vertexOut;
    vertexOut.position = float4(vertexIn.position[0], vertexIn.position[1], 0, 1);
    vertexOut.texCoord = vertexIn.texCoord;

    return vertexOut;
}
#include <metal_stdlib>
using namespace metal;

struct VertexOut{
    float4 position [[position]];
    float2 texCoord;
};

struct Uniforms{
    float rot;
    float tx;
    float ty;
    float sx;
    float sy;
};

fragment float4 transform(VertexOut out [[stage_in]],
                          texture2d<float>  inTex [[ texture(0) ]],
                          const device Uniforms& in [[ buffer(0) ]],
                          sampler s [[ sampler(0) ]]) {

    float pi = 3.14159265359;

    float u = out.texCoord[0];
    float v = out.texCoord[1];

    float2 size = float2(in.sx, in.sy);

    float ang = atan2(v - 0.5 - in.ty, u - 0.5 - in.tx) + (-in.rot / 360) * pi * 2;
    float amp = sqrt(pow(u - 0.5 - in.tx, 2) + pow(v - 0.5 - in.ty, 2));
    float2 uv = float2(cos(ang) * amp, sin(ang) * amp) / size + 0.5;
    float4 c = inTex.sample(s, uv);

    float r = c.r;
    float g = c.g;
    float b = c.b;

    return float4(r, g, b, 1.0);
}