提问人:Łukasz 提问时间:10/25/2023 更新时间:11/1/2023 访问量:66
片段着色器混合 uv 坐标
Fragment shader mixes uv coordinates
问:
我试着理解着色器是如何工作的,只是第一步。通过一些教程,我制作了视图、顶点着色器和片段着色器。哇。它有效。
但是当我开始玩它时,我发现了一些非常令人惊讶的东西,我不知道如何处理它。以及为什么它的行为是这样的。
有传递给顶点着色器的顶点:
let vertices = [
Vertex(position:vector_float3( 1, 1, 0)),
Vertex(position:vector_float3( 1,-1, 0)),
Vertex(position:vector_float3(-1,-1, 0)),
Vertex(position:vector_float3( 1, 1, 0)),
Vertex(position:vector_float3( -1, 1, 0)),
Vertex(position:vector_float3(-1,-1, 0))
]
我能看到美丽的矩形。哇,如果我从片段着色器返回颜色,没有计算,更改......
但是,当我开始玩着色器时
fragment float4 fragmentShader(RasterizerData input [[stage_in]],
float2 uv [[point_coord]]) {
float2 coord = (uv - float2(0.5)) * 2;
return (sin(coord.x*10)/2)+ 0.5;
}
结果与我预期的不同:
我以为 x 轴上只有窦波。
当我使用顶点顺序时,我可以得到不同的结果:
或
紫外线坐标总是“错”? 怎么了?我错过了什么?
答:
0赞
Spo1ler
10/29/2023
#1
point_coord
是点基元,意思是.对于三角形,它是未定义的。MTLPrimitiveTypePoint
对于三角形,您实际需要的是提供或计算光栅器将在三角形上插值的 UV。UV 是一个 2 分量坐标,分量从 0 到 1,通常用于对纹理进行采样。在您的例子中,UV 将在屏幕的左上角为 (0, 0),在屏幕的右下角为 (1, 1)。
因此,您的代码将如下所示。在桥接头文件中,你会有一个结构
struct Vertex {
vector_float3 position;
vector_float2 texCoord;
}
然后在 Swift 中
let vertices = [
Vertex(position:vector_float3( 1, 1, 0), texCoord:vector_float2(0, 0)),
Vertex(position:vector_float3( 1,-1, 0), texCoord:vector_float2(0, 1)),
Vertex(position:vector_float3(-1,-1, 0), texCoord:vector_float2(1, 1)),
Vertex(position:vector_float3( 1, 1, 0), texCoord:vector_float2(0, 0)),
Vertex(position:vector_float3( -1, 1, 0), position:vector_float2(1, 0)),
Vertex(position:vector_float3(-1,-1, 0), texCoord:vector_float2(1, 1))
]
然后,您需要在 中设置一个顶点属性,然后在顶点着色器中读取该属性,然后片段着色器将如下所示MTLVertexDescriptor
fragment float4 fragmentShader(RasterizerData input [[stage_in]]) {
float2 coord = (input.uv - float2(0.5)) * 2;
return (sin(coord.x*10)/2)+ 0.5;
}
或者,如果你正在尝试做一个全屏片段着色器,你甚至可以只使用预定义的位置和UV数组。请记住,下面的代码段使用了一个覆盖整个屏幕的大三角形,而不是两个较小的相邻三角形,但它很容易修改。vertex_id
constant array<float3, 3> fullscreenTrianglePositions =
{
float3{-1, -1, 0},
float3{-1, 3, 0},
float3{ 3, -1, 0},
};
constant array<float2, 3> fullscreenTriangleTexCoords =
{
float2{0, 1},
float2{0, -1},
float2{2, 1},
};
struct FullscreenVertexOut
{
float4 position [[ position ]];
float2 texCoord;
};
vertex FullscreenVertexOut FullscreenTriangleVertex(ushort vertexId [[ vertex_id ]])
{
FullscreenVertexOut out;
out.position.xyz = fullscreenTrianglePositions[vertexId];
out.position.w = 1;
out.texCoord = fullscreenTriangleTexCoords[vertexId];
return out;
}
评论
0赞
Łukasz
10/31/2023
太好了,但有些东西我不太明白:Vertex(position ..., position:: ....) — 相同的标签和双冒号。错字?C++?我有一个 Swift 结构顶点,其位置定义为vector_float3。
0赞
Spo1ler
11/1/2023
哦,我混淆了我的语法。不好意思。我要编辑我的答案。
评论