作为学习片段着色器/矢量数学的练习,我正在尝试编写一个后处理着色器,根据矢量PC的角度(以弧度表示),在P和中心之间为屏幕上的每个点P着色。屏幕C.
为了简单起见,我将以灰度方式进行此操作,但可以在这里看到我想要的效果的一个很好的例证,随着角度的变化色调变化,色调形成一个循环。
http://demosthenes.info/assets/images/hsl-color-wheel-trans.png
我四处搜寻,寻找有关找到矢量之间角度的信息,从这些例子中我已经到了这里:
#version 110
uniform sampler2D tex0; //Color info
void main()
{
vec2 ScreenCenter = vec2(0.5 , 0.5);
vec2 texCoord = gl_TexCoord[0].st;
vec2 deltaTexCoord = ( texCoord - ScreenCenter.xy);
float angle = dot(deltaTexCoord , vec2(0,-1));
//I've made attempts here to mess with acos as well as angle=pow(angle, somefloat) and
//have not gotten desired results
gl_FragColor = vec4( angle , angle, angle, 1.0 );
}
但是这段代码会产生线性渐变而不是我想要的效果。
答案 0 :(得分:3)
最简单的方法是使用带有两个参数的内置GLSL函数atan()
:
float angle = atan(deltaTexCoord.y, deltaTexCoord.x);
这对应于您可能从C / C ++中熟悉的atan2 function。与使用acos()
相比,主要优势在于它为您提供了全范围的角度[-pi,pi],而由acos()
生成的角度仅在[0,pi]范围内,因此对于圆圈的下半部分是不正确的。使用atan(y, x)
时,也无需规范化输入值。
答案 1 :(得分:0)
你几乎就在那里。两个向量的内积(也称为标量或点积)是向量之间的角度乘以向量长度乘积的余弦。因此,为了回到角度,你将点积映射到余弦的倒数,并首先对矢量进行归一化(0,1)已经是单位长度。
float angle = acos( dot(normalize(deltaTexCoord), vec2(0, -1)) );
请注意,角度以弧度为单位报告,从0到2pi。