顶点相对于法线的位置 [英] Vertex position relative to normal

查看:141
本文介绍了顶点相对于法线的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在表面着色器中,给定世界的上轴(以及其他轴),世界空间位置和世界空间中的法线,我们如何将世界空间位置旋转到正常吗?

也就是说,给定一个向上矢量和一个非正交的目标向上矢量,我们如何通过旋转其向上矢量来变换位置?

我需要这个,所以我可以使顶点位置仅受对象旋转矩阵的影响,而我没有可以访问.

这是我想做什么的图形化可视化显示:

  • Up是世界向上的载体
  • 目标是世界空间法线
  • Pos是任意的

该图是二维的,但我需要为3D空间解决此问题.

解决方案

似乎您正尝试将 pos 旋转相同的旋转,从而将向上转换为 new_up .

使用找到的旋转矩阵 // Our 3 vectors float3 pos; float3 new_up; float3 up = float3(0,1,0); // Build the rotation matrix using notation from the link above float3 v = cross(up, new_up); float s = length(v); // Sine of the angle float c = dot(up, new_up); // Cosine of the angle float3x3 VX = float3x3( 0, -1 * v.z, v.y, v.z, 0, -1 * v.x, -1 * v.y, v.x, 0 ); // This is the skew-symmetric cross-product matrix of v float3x3 I = float3x3( 1, 0, 0, 0, 1, 0, 0, 0, 1 ); // The identity matrix float3x3 R = I + VX + mul(VX, VX) * (1 - c)/pow(s,2) // The rotation matrix! YAY! // Finally we rotate float3 new_pos = mul(R, pos);

这是假设 new_up 已标准化.

如果正常目标向上"是一个常数,则 R 的计算只能(并且应该)每帧进行一次.我建议在CPU端执行此操作,并将其作为变量传递到着色器中.计算每个顶点/片段的成本很高,请考虑您的实际需求.

如果您的 pos 是一个vector-4,只需对前三个元素执行上述操作,则第四个元素可以保持不变(在此情况下,这实际上并不意味着任何东西)./p>

我不在可以运行着色器代码的机器上,因此,如果我在以上操作中遇到语法错误,请原谅我.

In a surface shader, given the world's up axis (and the others too), a world space position and a normal in world space, how can we rotate the worldspace position into the space of the normal?

That is, given a up vector and a non-orthogonal target-up vector, how can we transform the position by rotating its up vector?

I need this so I can get the vertex position only affected by the object's rotation matrix, which I don't have access to.

Here's a graphical visualization of what I want to do:

  • Up is the world up vector
  • Target is the world space normal
  • Pos is arbitrary

The diagram is bidimensional, but I need to solve this for a 3D space.

解决方案

Looks like you're trying to rotate pos by the same rotation that would transform up to new_up.

Using the rotation matrix found here, we can rotate pos using the following code. This will work either in the surface function or a supplementary vertex function, depending on your application:

// Our 3 vectors
float3 pos;
float3 new_up;
float3 up = float3(0,1,0);

// Build the rotation matrix using notation from the link above
float3 v = cross(up, new_up);
float s = length(v);  // Sine of the angle
float c = dot(up, new_up); // Cosine of the angle
float3x3 VX = float3x3(
    0, -1 * v.z, v.y,
    v.z, 0, -1 * v.x,
    -1 * v.y, v.x, 0
); // This is the skew-symmetric cross-product matrix of v
float3x3 I = float3x3(
    1, 0, 0,
    0, 1, 0,
    0, 0, 1
); // The identity matrix
float3x3 R = I + VX + mul(VX, VX) * (1 - c)/pow(s,2) // The rotation matrix! YAY!

// Finally we rotate
float3 new_pos = mul(R, pos);

This is assuming that new_up is normalized.

If the "target up normal" is a constant, the calculation of R could (and should) only happen once per frame. I'd recommend doing it on the CPU side and passing it into the shader as a variable. Calculating it for every vertex/fragment is costly, consider what it is you actually need.

If your pos is a vector-4, just do the above with the first three elements, the fourth element can remain unchanged (it doesn't really mean anything in this context anyway).

I'm away from a machine where I can run shader code, so if I made any syntactical mistakes in the above, please forgive me.

这篇关于顶点相对于法线的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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