将 Metal Shader 纹理类型从 2D 转换为 2D Multisample
Converting Metal Shader texture type from 2D to 2D Multisample
我正在关注 2etime 在 YouTube 上关于 Apple Metal 图形 API 的教程。一切都按预期工作,但是当我尝试更改视图的样本数时,出现了很多错误。但是,这些错误很容易修复。到目前为止,我已经更改了每个文件中的样本计数,但我仍然停留在着色器上。要更改 view 的 样本计数,您必须更改 texture 样本计数(至少在我的情况下),并更改纹理样本计数,您必须将纹理类型更改为多重采样。这很容易做到。但是,在此更改之后,我从着色器中得到错误。看起来片段着色器使用 texture2d,我需要将其更改为 texture2d_ms,但是当我这样做时,我收到错误提示 'sample' 函数无效。我将 post 代码和错误。我试过在互联网上搜索,但似乎找不到任何东西。
FinalShaders.metal
#include <metal_stdlib>
#include "Shared.metal"
using namespace metal;
struct FinalRasterizerData {
float4 position [[ position ]];
float2 textureCoordinate;
};
vertex FinalRasterizerData final_vertex_shader(const VertexIn vIn [[ stage_in ]]) {
FinalRasterizerData rd;
rd.position = float4(vIn.position, 1.0);
rd.textureCoordinate = vIn.textureCoordinate;
return rd;
}
fragment half4 final_fragment_shader(const FinalRasterizerData rd [[ stage_in ]],
texture2d_ms<float> baseTexture) {
sampler s;
float2 textureCoordinate = rd.textureCoordinate;
textureCoordinate.y = 1 - textureCoordinate.y;
float4 color = baseTexture.sample(s, textureCoordinate);
return half4(color);
}
Shared.metal
#ifndef SHARED_METAL
#define SHARED_METAL
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[ attribute(0) ]];
float4 color [[ attribute(1) ]];
float2 textureCoordinate [[ attribute(2) ]];
float3 normal [[ attribute(3) ]];
float3 tangent [[ attribute(4) ]];
float3 bitangent [[ attribute(5) ]];
};
struct RasterizerData{
float4 position [[ position ]];
float4 color;
float2 textureCoordinate;
float totalGameTime;
float3 worldPosition;
float3 toCameraVector;
float3 surfaceNormal;
float3 surfaceTangent;
float3 surfaceBitangent;
};
struct ModelConstants{
float4x4 modelMatrix;
};
struct SceneConstants{
float totalGameTime;
float4x4 viewMatrix;
float4x4 skyViewMatrix;
float4x4 projectionMatrix;
float3 cameraPosition;
};
struct Material {
float4 color;
bool isLit;
bool useBaseTexture;
bool useNormalMapTexture;
float3 ambient;
float3 diffuse;
float3 specular;
float shininess;
};
struct LightData {
float3 position;
float3 color;
float brightness;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity;
};
#endif
错误:
No member named 'sample' in 'metal::texture2d_ms<float, metal::access::read, void>'
我知道它清楚地表明 'sample' 不存在,但我找不到任何解决方案。当我删除它并用不同的值替换 return 时,我只看到很多 green/yellow 行,没有 3d 对象。感谢您的帮助!
(发生错误的着色器是最终 shaders.metal 中的第一个片段)
以 sample
函数意味着的方式进行采样对于多重采样纹理没有意义。您正在寻找的是在给定的 texcoord 处读取确切的样本值。
如果您查看 Metal Shader Language specification,在第 6.12.8 节中它描述了 2D 多重采样纹理存在哪些函数。
其中包括:
Tv read(uint2 coord, uint sample) const
Tv read(ushort2 coord, ushort sample) const
uint get_width() const
uint get_height() const
uint get_num_samples() const
在read
函数中,coord
表示像素坐标,所以它们在X轴上从0
到get_width()
,从0
到get_height()
在 Y 轴上。 sample
是样本的索引,所以它会从 0
到 get_num_samples()
我正在关注 2etime 在 YouTube 上关于 Apple Metal 图形 API 的教程。一切都按预期工作,但是当我尝试更改视图的样本数时,出现了很多错误。但是,这些错误很容易修复。到目前为止,我已经更改了每个文件中的样本计数,但我仍然停留在着色器上。要更改 view 的 样本计数,您必须更改 texture 样本计数(至少在我的情况下),并更改纹理样本计数,您必须将纹理类型更改为多重采样。这很容易做到。但是,在此更改之后,我从着色器中得到错误。看起来片段着色器使用 texture2d,我需要将其更改为 texture2d_ms,但是当我这样做时,我收到错误提示 'sample' 函数无效。我将 post 代码和错误。我试过在互联网上搜索,但似乎找不到任何东西。
FinalShaders.metal
#include <metal_stdlib>
#include "Shared.metal"
using namespace metal;
struct FinalRasterizerData {
float4 position [[ position ]];
float2 textureCoordinate;
};
vertex FinalRasterizerData final_vertex_shader(const VertexIn vIn [[ stage_in ]]) {
FinalRasterizerData rd;
rd.position = float4(vIn.position, 1.0);
rd.textureCoordinate = vIn.textureCoordinate;
return rd;
}
fragment half4 final_fragment_shader(const FinalRasterizerData rd [[ stage_in ]],
texture2d_ms<float> baseTexture) {
sampler s;
float2 textureCoordinate = rd.textureCoordinate;
textureCoordinate.y = 1 - textureCoordinate.y;
float4 color = baseTexture.sample(s, textureCoordinate);
return half4(color);
}
Shared.metal
#ifndef SHARED_METAL
#define SHARED_METAL
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[ attribute(0) ]];
float4 color [[ attribute(1) ]];
float2 textureCoordinate [[ attribute(2) ]];
float3 normal [[ attribute(3) ]];
float3 tangent [[ attribute(4) ]];
float3 bitangent [[ attribute(5) ]];
};
struct RasterizerData{
float4 position [[ position ]];
float4 color;
float2 textureCoordinate;
float totalGameTime;
float3 worldPosition;
float3 toCameraVector;
float3 surfaceNormal;
float3 surfaceTangent;
float3 surfaceBitangent;
};
struct ModelConstants{
float4x4 modelMatrix;
};
struct SceneConstants{
float totalGameTime;
float4x4 viewMatrix;
float4x4 skyViewMatrix;
float4x4 projectionMatrix;
float3 cameraPosition;
};
struct Material {
float4 color;
bool isLit;
bool useBaseTexture;
bool useNormalMapTexture;
float3 ambient;
float3 diffuse;
float3 specular;
float shininess;
};
struct LightData {
float3 position;
float3 color;
float brightness;
float ambientIntensity;
float diffuseIntensity;
float specularIntensity;
};
#endif
错误:
No member named 'sample' in 'metal::texture2d_ms<float, metal::access::read, void>'
我知道它清楚地表明 'sample' 不存在,但我找不到任何解决方案。当我删除它并用不同的值替换 return 时,我只看到很多 green/yellow 行,没有 3d 对象。感谢您的帮助!
(发生错误的着色器是最终 shaders.metal 中的第一个片段)
以 sample
函数意味着的方式进行采样对于多重采样纹理没有意义。您正在寻找的是在给定的 texcoord 处读取确切的样本值。
如果您查看 Metal Shader Language specification,在第 6.12.8 节中它描述了 2D 多重采样纹理存在哪些函数。
其中包括:
Tv read(uint2 coord, uint sample) const
Tv read(ushort2 coord, ushort sample) const
uint get_width() const
uint get_height() const
uint get_num_samples() const
在read
函数中,coord
表示像素坐标,所以它们在X轴上从0
到get_width()
,从0
到get_height()
在 Y 轴上。 sample
是样本的索引,所以它会从 0
到 get_num_samples()