如何获得给定像素在世界坐标中的颜色? [英] How to get the color of a given pixel in world coordinates?

查看:17
本文介绍了如何获得给定像素在世界坐标中的颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是戈多的碎片着色器。我可以获得当前像素的世界坐标,如下所示:

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
假设我将Pixel_world_pos.y增加10,我想知道该像素是什么颜色。我怎么才能弄清楚这一点呢?

我知道信息存储在UV中,但我使用的是世界坐标,而不是UV坐标.

推荐答案

让我们仔细看看这行:

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;

这里,您使用VERTEX,它将位于视图空间中。用w坐标上的1.0将其增加为vec4。然后使用CAMERA_MATRIX进行转换。

CAMERA_MATRIXvec4从视图空间带到世界空间(即CAMERA_MATRIX是逆视图矩阵)。然后从其中提取vec3,丢弃w


好的,下面假设您这样修改y坐标:

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;

您想知道它在视图空间的什么位置。Well…我们做我们做过的事情,但情况正好相反。

我们做的最后一件事是丢弃w。我们需要向后添加w

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
vec4 tmp = vec4(pixel_world_pos, 1.0);

这是在假定CAMERA_MATRIX是3D仿射变换的情况下工作的。

您之前做的事情是使用CAMERA_MATRIX转换向量。要撤消此操作,我们需要用CAMERA_MATRIX(也称为视图矩阵)。戈多将其提供为INV_CAMERA_MATRIX。因此,我们可以通过以下方式进行转换:

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
vec4 tmp = INV_CAMERA_MATRIX * vec4(pixel_world_pos, 1.0);
你做的第一件事就是增加向量。因此,我们现在放弃w

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
vec3 pixel_view_pos = (INV_CAMERA_MATRIX * vec4(pixel_world_pos, 1.0)).xyz;

就这样了。


哦,等等,您想读取像素。所以我们需要紫外线。下一步是使用PROJECTION_MATRIX

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
mat4 WORLD_TO_CLIP_MATRIX = PROJECTION_MATRIX * INV_CAMERA_MATRIX;
这里我将视图矩阵(INV_CAMERA_MATRIX)与投影矩阵(PROJECTION_MATRIX)组合在一起,这样我们就可以直接从世界空间转换到剪辑空间。也就是说,INV_CAMERA_MATRIX将我们从世界空间带到视图空间,而PROJECTION_MATRIX将我们从视图空间带到剪辑空间。

在我们进一步讨论之前,我们需要处理PROJECTION_MATRIX保持投影变换(令人惊讶!)这一事实,它不是仿射变换。因此,我们不应该添加和删除w,而是执行以下操作:

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
mat4 WORLD_TO_CLIP_MATRIX = PROJECTION_MATRIX * INV_CAMERA_MATRIX;
vec4 pixel_clip_pos = WORLD_TO_CLIP_MATRIX * vec4(pixel_world_pos, 1.0);
vec3 pixel_nds_pos = pixel_clip_pos.xyz / pixel_clip_pos.w;
这里的dns代表标准化的设备空间。我们现在可以放弃z

vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
pixel_world_pos.y = pixel_world_pos.y + 10.0;
mat4 WORLD_TO_CLIP_MATRIX = PROJECTION_MATRIX * INV_CAMERA_MATRIX;
vec4 pixel_clip_pos = WORLD_TO_CLIP_MATRIX * vec4(pixel_world_pos, 1.0);
vec2 uv = (pixel_clip_pos.xyz / pixel_clip_pos.w).xy * 0.5 + vec2(0.5, 0.5);
但是,结果是,如果我们简单地做(pixel_clip_pos.xyz / pixel_clip_pos.w).xy,我们就会得到原点在屏幕中心的坐标。所以我们需要缩放和偏移它们,使它们从左下角的0变为右上角的1。这就是屏蔽UV的工作方式。

顺便说一句,如果您要计算深度,z我们丢弃的z会很有用。


我们完成了:

shader_type spatial;
render_mode unshaded;

void fragment()
{
    vec3 pixel_world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz;
    pixel_world_pos.y = pixel_world_pos.y + 10.0;
    mat4 WORLD_TO_CLIP_MATRIX = PROJECTION_MATRIX * INV_CAMERA_MATRIX;
    vec4 pixel_clip_pos = WORLD_TO_CLIP_MATRIX * vec4(pixel_world_pos, 1.0);
    vec2 uv = (pixel_clip_pos.xyz / pixel_clip_pos.w).xy * 0.5 + vec2(0.5, 0.5);
    ALBEDO = texture(SCREEN_TEXTURE, uv).rgb;
}

顺便说一下,您需要注意您计算的uv可能超出SCREEN_TEXTURE的边缘。

这篇关于如何获得给定像素在世界坐标中的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆