Я пытаюсь найти правильную математику для поворота и перевода кривой, отображаемой в фрагментном шейдере.
Что я пытаюсь сделать, это определить кривую, например, синусоидальную, влокальная система координат, поверните ее и переведите.Примерно так:
Это было сделано в MATLAB со следующим кодом:
dens = 1080;
x = linspace(-1.0, 1.0, dens);
y = 0.1*sin(25.0*x);
imax = 25;
for i = 1:imax
%transformation matrix:
ang = (i/imax)*0.5*3.14;
c = cos(ang); s = sin(ang);
T = [c,-s;s,c];
%translation:
P = [0.5;0.5];
%transformed coordinates:
xt = T(1,:)*[x;y] + P(1);
yt = T(2,:)*[x;y] + P(2);
plot(xt,yt);
xlim([0 1.0]); ylim([0 1.0]); drawnow;
end
Для теста GLSL I 'm с помощью Book of Shaders Editor со следующим кодом (также можно посмотреть в интерактивном режиме здесь ):
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform float u_time;
uniform vec2 u_resolution;
// Plot a line on Y using a value between 0.0-1.0
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
float plotTransformed(vec2 st, float pct, vec2 transl, float ang){
float c = cos(ang); float s = sin(ang);
mat2 trans = mat2(c,-s,s,c);
st = trans * st;
st -= transl;
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
void main(void) {
bool use_plot_function = true;
float mx = max(u_resolution.x, u_resolution.y);
vec2 uv = gl_FragCoord.xy /mx;
vec3 color = vec3(0.4,0.4,0.4);
//some screen position:
vec2 p = vec2(0.5, 0.5);
//the curve:
vec2 cp = vec2(
uv.x,
0.08*sin(uv.x*40.0)
);
//the angle to rotate:
float ang = -0.4 * 3.14 * sin(u_time);
//Transform coordinates:
float c = cos(ang); float s = sin(ang);
mat2 trans = mat2(c,-s,s,c);
vec2 cp_t = trans * cp;
cp_t +=p;
if(use_plot_function){
//Attempt 1: plot unrotated original curve translated upwards:
float curve1 = plot(uv, cp.y + p.y);
color.g *= curve1;
//Attemp 2: plot the transformed curve using plotTransformed, rotates first, then translates:
float curve2 = plotTransformed(uv, cp.y, p, ang);
color.r *= curve2;
//Attempt 3: curve is transformed first then ploted:
float curve3 = plot(uv, cp_t.y);
color.b *= curve3;
}
else{
float plotThk = 0.02;
//Attempt 1: change color based on distance from unrotated original curve:
float dist = distance(uv, cp + vec2(0.0, p.y));
if(dist < plotThk)
color.g *= (1.0 -dist)/plotThk;
//Attempt 2: change color based on distance from transformed coordinates:
dist = distance(uv, cp_t);
if(dist < plotThk)
color.r *= (1.0 -dist)/plotThk;
}
gl_FragColor = vec4(color,1.0);
}
В приведенном выше коде есть два режимакоторый можно переключать с use_plot_function
, установленным на false
или true
.
Первый режим пытается построить график с использованием функций plot(
) & plotTransformed()
.Второй режим устанавливает цвет фрагмента на основе расстояния от вычисленных координат кривой.
Результат первого режима с use_plot_function
, установленным на true
:
Результат второго режима с use_plot_function
, установленным на false
:
Очевидно, я не понимаю, какэто должно быть сделано в фрагментном шейдере.
Как правильно определить преобразованную кривую в шейдерном фрагменте GLSL?