首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在顶点/碎片着色器(金属)中使用3x32D变换

如何在顶点/碎片着色器(金属)中使用3x32D变换
EN

Stack Overflow用户
提问于 2015-08-10 17:23:49
回答 1查看 922关注 0票数 1

我有一个据说很简单的任务,但显然我仍然不明白投影是如何在阴影中工作的。我需要在纹理四边形(2个三角形)上进行2D透视转换,但在视觉上它看起来不正确(例如,梯形图比CPU版本稍高或更长)。

我有这样的结构:

代码语言:javascript
复制
struct VertexInOut  
{  
  float4 position [[position]];  
  float3 warp0;  
  float3 warp1;  
  float3 warp2;  
  float3 warp3;  
};  

在顶点着色器中,我所做的事情类似于(texCoords是四角的像素同弦,而同形是以像素同弦计算的):

代码语言:javascript
复制
v.warp0 = texCoords[vid] * homographies[0]; 

然后在像这样的片段着色器里:

代码语言:javascript
复制
return intensity.sample(s, inFrag.warp0.xy / inFrag.warp0.z);

结果不是我期望的那样。我花了好几个小时在这件事上,但我想不出来。排气

更新:

这些是CPU的代码和结果(也称为预期结果):

代码语言:javascript
复制
// _image contains the original image
cv::Matx33d h(1.03140473, 0.0778113901, 0.000169219566,
              0.0342947133, 1.06025684, 0.000459250761,
              -0.0364957005, -38.3375587, 0.818259298);
cv::Mat dest(_image.size(), CV_8UC4);
// h is transposed because OpenCV is col major and using backwarping because it is what is used on the GPU, so better for comparison
cv::warpPerspective(_image, dest, h.t(), _image.size(), cv::WARP_INVERSE_MAP | cv::INTER_LINEAR);  

这些是GPU的代码和结果(也称为错误结果):

代码语言:javascript
复制
// constants passed in buffers, image size 320x240
const simd::float4 quadVertices[4] =
{
  { -1.0f,  -1.0f, 0.0f, 1.0f },
  { +1.0f,  -1.0f, 0.0f, 1.0f },
  { -1.0f,  +1.0f, 0.0f, 1.0f },
  { +1.0f,  +1.0f, 0.0f, 1.0f },
};

const simd::float3 textureCoords[4] =
{
  { 0,  IMAGE_HEIGHT, 1.0f },
  { IMAGE_WIDTH, IMAGE_HEIGHT, 1.0f },
  { 0, 0, 1.0f },
  { IMAGE_WIDTH, 0, 1.0f },
};

// vertex shader
vertex VertexInOut homographyVertex(uint vid [[ vertex_id ]],
                                    constant float4 *positions [[ buffer(0) ]],
                                    constant float3 *texCoords [[ buffer(1) ]],
                                    constant simd::float3x3 *homographies [[ buffer(2) ]])
{
  VertexInOut v;
  v.position = positions[vid];

  // example homography
  simd::float3x3 h = {
    {1.03140473, 0.0778113901, 0.000169219566},
    {0.0342947133, 1.06025684, 0.000459250761},
    {-0.0364957005, -38.3375587, 0.818259298}
  };

  v.warp = h * texCoords[vid];

  return v;
}

// fragment shader
fragment int4 homographyFragment(VertexInOut inFrag [[stage_in]],
                                 texture2d<uint, access::sample> intensity [[ texture(1) ]])
{
  constexpr sampler s(coord::pixel, filter::linear, address::clamp_to_zero);
  float4 targetIntensity = intensityRight.sample(s, inFrag.warp.xy / inFrag.warp.z);
  return targetIntensity;
}

原始图像:

更新2:

与一般认为应该在片段着色器中进行透视分割相反,如果在顶点着色器中分割(并且没有扭曲或三角形之间的缝),我得到的结果更相似,但是为什么呢?

更新3:

我得到相同的(错误的)结果,如果:

  • 我将透视图分割到片段着色器
  • 我只需删除代码中的分隔。

奇怪的是,这一分歧似乎并没有发生。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-11 17:48:08

好的,解决方案当然是一个非常小的细节:部门 of simd::float3的行为是绝对疯狂的。事实上,如果我在片段着色器中进行透视分割,如下所示:

代码语言:javascript
复制
float4 targetIntensity = intensityRight.sample(s, inFrag.warp.xy * (1.0 / inFrag.warp.z));

它起作用了!

这让我发现,除以预先分割的浮点数与除以浮点数是不同的。如果有人知道为什么我们能解开这个谜团的话,我仍然不知道原因。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31925583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档