Ios 金属碎片着色器中的随机错误噪声
我的圈子扭曲了,很糟糕 我正在写一个片段着色器来做一些图像转换,我看到一些随机错误噪声,不确定是怎么回事 我正在合并两个纹理,一个是read with.read(gid);使用取样器读取一次。样品(s,uv) 我在Swift中创建了采样器,并将其传递给着色器 以下是我如何将纹理传递到着色器: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>
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);
}