【寒江雪】UV+Depth信息计算世界坐标

最近要实现Depth反计算世界坐标的效果,于是看了其他网友的博客,实现如下

	float d = texture(depthStencilTexture,TexCoords).r;
	vec4 NDC = vec4(TexCoords.x*2.0 - 1.0, TexCoords.y*2.0 - 1.0, d*2.0 - 1, 1.0);
	vec4 worldPos = inv_view * inv_proj * NDC;
	worldPos /= worldPos.w;

原世界坐标(左半窗口)和计算出来的世界坐标(右半窗口)如下所示

在这里插入图片描述

背景本来应该是黑的,右边出新了背景,这是不正确的,出现的原因是由于深度超出了摄像机的限制却还是算出了一个坐标,没有被剔除,正常情况下他们应该被剔除的,所以这里我们简单判断一下计算出来的坐标到摄像机的距离,看看是否有超出最大限制就行,这样判断可能会存在不精确的情况,但是做实验应该足够了。

这里最远距离是100,如果直接与100比,在中心会出现一个圆形的点剔除不掉,所以我选择和99做比较

	float d = texture(depthStencilTexture,TexCoords).r;
	vec4 NDC = vec4(TexCoords.x*2.0 - 1.0, TexCoords.y*2.0 - 1.0, d*2.0 - 1, 1.0);
	vec4 worldPos = inv_view * inv_proj * NDC;
	worldPos /= worldPos.w;	
	if(length(vec3(worldPos)-ViewPos)>=99.0)discard;
	//	To do other operation

结果可以发现左右两部分没用什么区别了

在这里插入图片描述

示例代码shader部分

void main()
{
	vec4 FragPos = texture(positionTexture,TexCoords);
	float d = texture(depthStencilTexture,TexCoords).r;
	vec4 NDC = vec4(TexCoords.x * 2.0 - 1.0, TexCoords.y * 2.0 - 1.0, d * 2.0 - 1, 1.0);
	vec4 worldPos = inv_view * inv_proj * NDC;
	worldPos /= worldPos.w;
	if(length(vec3(worldPos)-ViewPos)>=99.0)discard;
	if(gl_FragCoord.x>400)
		FragColor = worldPos;
	else
		FragColor = FragPos;
}

输出验证可以用worldPos-FragPos,如果得到全黑的窗口说明计算结果与原坐标完全一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用一个长宽不等的osg::Texture2D纹理时,需要计算每个顶点对应纹理的UV坐标。这可以通过以下公式来计算: 对于一个顶点的纹理坐标(u,v),其中u和v的值都应该在0到1之间,可以使用以下公式: u = (vertex.x - min_x) / (max_x - min_x) v = (vertex.y - min_y) / (max_y - min_y) 其中,vertex是当前顶点的位置,min_x、min_y、max_x和max_y是纹理在x和y方向上的最小和最大坐标。这些值可以通过osg::Texture2D::getImage()方法获得,然后使用getImage()->s()和getImage()->t()方法分别获得图像的宽度和高度。 代码示例: ``` osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D(); texture->setImage(image); float min_x = 0.0f, min_y = 0.0f, max_x = (float)image->s(), max_y = (float)image->t(); // 计算每个顶点对应的纹理坐标 osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); osg::Vec2Array* texcoords = new osg::Vec2Array(vertices->size()); for(int i = 0; i < vertices->size(); i++) { osg::Vec3& vertex = (*vertices)[i]; (*texcoords)[i].set((vertex.x() - min_x) / (max_x - min_x), (vertex.y() - min_y) / (max_y - min_y)); } geometry->setTexCoordArray(0, texcoords); ``` 在上述示例中,geometry是一个osg::Geometry对象,它包含了需要进行纹理映射的顶点信息。我们首先使用osg::Texture2D::setImage()方法将纹理图像设置到纹理对象中,然后通过getImage()方法获取纹理图像的宽度和高度。接着,我们使用osg::Geometry对象的getVertexArray()方法获取顶点数组,并通过计算得到每个顶点对应的纹理坐标,最后将纹理坐标数组设置到geometry对象中的第0个纹理单元中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值