使用纹理方向和纹理速度移动像素/GLSL
Move pixel with texture direction and texture velocity / GLSL
我写了一个小程序来简单地解释我的问题,我尝试用一个纹理改变图片的像素位置,其中分量 x 是方向,另一个代表速度。最后 objective 是使用来自 CPU 的数据,其中计算 NAVIER-STROKE 流体以移动 GLSL 中的像素。 CPU 代码在 Processing java 库中。
我试图理解我的代码中有什么错误,但我不明白像素转换是如何工作的。
首先,我在 CPU 中将值颜色的方向从 0 转换为 255,然后在 GPU 中将其转换为矢量方向,然后将其乘以速度并将其缩放为 1x1,但那不是'行不通...对不起,如果我的解释不是很稳定,但英语不是很流利。
处理中:
PImage tex_velocity, tex_direction ;
PShader warping;
PImage img ;
int grid_w, grid_h ;
void setup() {
size(600,375,P2D);
// img = loadImage("pirate_small.jpg");
img = loadImage("puros_girl_small.jpg");
grid_w = 60 ;
grid_h = 37 ;
tex_velocity = createImage(grid_w,grid_h,RGB);
tex_direction = createImage(grid_w,grid_h,RGB);
warping = loadShader("shader/warp/rope_warp_frag.glsl");
noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
noise_img(tex_direction, 360, .1, .1); // degree direction
}
void draw() {
println(frameRate);
if(frameCount%30 == 0) {
noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
noise_img(tex_direction, 360, .1, .1); // degree direction
}
warping.set("mode", 0) ;
warping.set("texture",img);
warping.set("roof_component_colour",g.colorModeX);
warping.set("wh_ratio",1f/grid_w, 1f/grid_h);
warping.set("vel_texture",tex_velocity);
warping.set("dir_texture",tex_direction);
shader(warping);
image(img,0,0);
resetShader();
image(tex_velocity,5,5);
image(tex_direction,grid_w +15 ,5 );
}
float x_offset, y_offset ;
void noise_img(PImage dst, int max, float ratio_x, float ratio_y) {
noiseSeed((int)random(10000));
for(int x = 0 ; x < dst.width ; x++) {
x_offset += ratio_x ;
for(int y = 0 ; y < dst.height ; y++) {
y_offset += ratio_y ;
float v = map(noise(x_offset,y_offset),0,1,0,max);
v = (int)map(v,0,max,0,g.colorModeX);
int c = color(v,v,v,g.colorModeA) ;
dst.set(x,y,c);
}
}
}
GLSL
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
#define PI 3.1415926535897932384626433832795
varying vec4 vertTexCoord;
uniform sampler2D texture;
uniform int mode;
uniform float roof_component_colour;
uniform sampler2D vel_texture;
uniform sampler2D dir_texture;
uniform vec2 wh_ratio;
float map(float value, float start1, float stop1, float start2, float stop2) {
float result = start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
return result;
}
vec2 cartesian_coord(float angle) {
float x = cos(angle);
float y = sin(angle);
return vec2(x,y);
}
vec2 translate(float fdir, float fvel) {
float angle_in_radian = map(fdir, 0, roof_component_colour, -PI, PI);
vec2 dir_cart = cartesian_coord(angle_in_radian);
return dir_cart *fvel ;
}
void main() {
vec2 ratio = gl_FragCoord.xy *wh_ratio;
vec4 vel = texture2D(vel_texture, ratio);
vec4 dir = texture2D(dir_texture, ratio);
// rendering picture ;
if(mode == 0) {
float direction = dir.x;
float velocity = vel.x;
vec2 translation = translate(direction,velocity);
// not bad, but totaly wrong
// vec2 coord_dest = vertTexCoord.st +translation
vec2 coord_dest = vertTexCoord.st *ratio +translation ;
// not bad, but totaly wrong
vec2 coord_dest = vertTexCoord.st *ratio +translation ;
vec4 tex_colour = texture2D(texture, coord_dest);
gl_FragColor = tex_colour;
}
// velocity
if(mode == 1 ) {
gl_FragColor = texture2D(vel_texture, vertTexCoord.st);;
}
// direction force field
if(mode == 2) {
gl_FragColor = texture2D(dir_texture, vertTexCoord.st);;
}
}
贴图格式为GL_RGBA8
,即每个颜色通道都存储到一个字节中,是一个整数数据类型,范围从0到255。
但是当你从纹理采样器中读取文本时,你会得到一个 0.0 到 1.0 范围内的浮点值。 (参见 glTexImage2D
- GL_RGBA)。
在片段着色器中,您必须将从纹理采样器读取的颜色通道(在 [0, 1] 中)映射到从 -PI 到 PI 的范围。为此,您可以使用 GLSL 函数 mix
,它在两个值之间进行线性插值:
vec2 translate(float fdir, float fvel) // fdir, fvel in [0.0, 1.0]
{
float angle = mix(-PI, PI, fdir);
return vec2(cos(angle), sin(angle)) * fvel;
}
纹理坐标在[0, 1]范围内。您必须将 translation
转换为纹理坐标。为此,您必须知道图像纹理的大小:
vec2 wh_ratio; // 1f/grid_w, 1f/grid_h
vec2 imageTexSize; // size of "texture"
vec2 scale = imageTexSize * wh_ratio;
vec2 coord_dest = vertTexCoord.st + translation / scale;
谢谢你的帮助,现在我知道了 GLSL 中图片的图片尺寸 :) [0,1]
,但这不是预期的工作,我使用渲染尺寸或必须扭曲的图片,所以在我看来 vec2 imageTexSize
是 img.width
并且 img.height
是从 Processing for imageTexSize
传递过来的
uniform vec2 imageTexSize;
.../...
vec2 scale = imageTexSize * wh_ratio;
vec2 coord_dest = vertTexCoord.st + translation / scale;
结果是顶部图像
当我尝试此代码时
vec2 ratio = gl_FragCoord.xy *wh_ratio;
vec2 coord_dest = vertTexCoord.st +translation / ratio ;
结果是中间的图
当我尝试这个时
vec2 coord_dest = vertTexCoord.st +translation / wh_ratio ;
结果为底图
抱歉,我 post 一张图片,因为我无法 post 多张以我的初学者声誉拍摄的照片 :)
我修复了完整 window 显示的显示错误,但现在是 y 坐标是平移的反向,这很奇怪,因为纹理速度和方向在 y 中没有反向,反向 y效果在于解释。这发生在 3 模式上。我试着像那样反转coord_dest.y
float coord_dest_y = mix(coord_dest.y, vertTexCoord.t, 0);
gl_FragColor = texture2D(texture, vec2(coord_dest.x, coord_dest_y));
但这并没有改变什么。
我尝试了:float coord_dest_y = mix(coord_dest.y, 0, vertTexCoord.t);
但是这让事情变得很奇怪,所以这也行不通...
这里是完整的 GLSL 代码
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
#define PI 3.1415926535897932384626433832795
varying vec4 vertTexCoord;
uniform sampler2D texture;
uniform int mode;
uniform sampler2D vel_texture;
uniform sampler2D dir_texture;
uniform vec2 wh_grid_ratio;
uniform vec2 wh_renderer_ratio;
vec2 cartesian_coord(float angle) {
float x = cos(angle);
float y = sin(angle);
return vec2(x,y);
}
vec2 translate(float fdir, float fvel) {
//float angle = mix(PI, -PI,fdir);
float angle = mix(fdir, PI, -PI);
return cartesian_coord(angle) *fvel ;
}
void main() {
vec2 ratio = gl_FragCoord.xy *wh_renderer_ratio;
vec4 vel = texture2D(vel_texture, ratio);
vec4 dir = texture2D(dir_texture, ratio);
float direction = dir.x;
float velocity = vel.x;
vec2 translation = translate(direction,velocity);
// mode 0 perfect
// mode 1 interesting
// mode 2 bizarre, but fun
// mode 500 warp image direction
// mode 501 warp image velocity
// perfect
if(mode == 0) {
vec2 scale = gl_FragCoord.xy *wh_renderer_ratio;
vec2 coord_dest = vertTexCoord.st +translation /scale;
float coord_dest_y = mix(coord_dest.y, vertTexCoord.t, 0);
// float coord_dest_y = mix(coord_dest.y, 0, vertTexCoord.t);
gl_FragColor = texture2D(texture, vec2(coord_dest.x, coord_dest_y));
// gl_FragColor = texture2D(texture, coord_dest);
}
// interesting
if(mode == 1) {
vec2 scale = gl_FragCoord.xy *wh_grid_ratio;
vec2 coord_dest = vertTexCoord.st +translation /scale ;
gl_FragColor = texture2D(texture, coord_dest);
}
// bizarre
if(mode == 2) {
vec2 coord_dest = vertTexCoord.st +translation /wh_grid_ratio;
gl_FragColor = texture2D(texture, coord_dest);
}
// velocity
if(mode == 500 ) {
vec4 tex_colour = texture2D(vel_texture, vertTexCoord.st);;
gl_FragColor = tex_colour;
}
// direction force field
if(mode == 501) {
vec4 tex_colour = texture2D(dir_texture, vertTexCoord.st);;
gl_FragColor = tex_colour;
}
}
和这里的图片结果,最后warping看到光标错误y
enter image description here
我写了一个小程序来简单地解释我的问题,我尝试用一个纹理改变图片的像素位置,其中分量 x 是方向,另一个代表速度。最后 objective 是使用来自 CPU 的数据,其中计算 NAVIER-STROKE 流体以移动 GLSL 中的像素。 CPU 代码在 Processing java 库中。 我试图理解我的代码中有什么错误,但我不明白像素转换是如何工作的。 首先,我在 CPU 中将值颜色的方向从 0 转换为 255,然后在 GPU 中将其转换为矢量方向,然后将其乘以速度并将其缩放为 1x1,但那不是'行不通...对不起,如果我的解释不是很稳定,但英语不是很流利。
处理中:
PImage tex_velocity, tex_direction ;
PShader warping;
PImage img ;
int grid_w, grid_h ;
void setup() {
size(600,375,P2D);
// img = loadImage("pirate_small.jpg");
img = loadImage("puros_girl_small.jpg");
grid_w = 60 ;
grid_h = 37 ;
tex_velocity = createImage(grid_w,grid_h,RGB);
tex_direction = createImage(grid_w,grid_h,RGB);
warping = loadShader("shader/warp/rope_warp_frag.glsl");
noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
noise_img(tex_direction, 360, .1, .1); // degree direction
}
void draw() {
println(frameRate);
if(frameCount%30 == 0) {
noise_img(tex_velocity, 20, .1, .1); // max translate for the pixel
noise_img(tex_direction, 360, .1, .1); // degree direction
}
warping.set("mode", 0) ;
warping.set("texture",img);
warping.set("roof_component_colour",g.colorModeX);
warping.set("wh_ratio",1f/grid_w, 1f/grid_h);
warping.set("vel_texture",tex_velocity);
warping.set("dir_texture",tex_direction);
shader(warping);
image(img,0,0);
resetShader();
image(tex_velocity,5,5);
image(tex_direction,grid_w +15 ,5 );
}
float x_offset, y_offset ;
void noise_img(PImage dst, int max, float ratio_x, float ratio_y) {
noiseSeed((int)random(10000));
for(int x = 0 ; x < dst.width ; x++) {
x_offset += ratio_x ;
for(int y = 0 ; y < dst.height ; y++) {
y_offset += ratio_y ;
float v = map(noise(x_offset,y_offset),0,1,0,max);
v = (int)map(v,0,max,0,g.colorModeX);
int c = color(v,v,v,g.colorModeA) ;
dst.set(x,y,c);
}
}
}
GLSL
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
#define PI 3.1415926535897932384626433832795
varying vec4 vertTexCoord;
uniform sampler2D texture;
uniform int mode;
uniform float roof_component_colour;
uniform sampler2D vel_texture;
uniform sampler2D dir_texture;
uniform vec2 wh_ratio;
float map(float value, float start1, float stop1, float start2, float stop2) {
float result = start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
return result;
}
vec2 cartesian_coord(float angle) {
float x = cos(angle);
float y = sin(angle);
return vec2(x,y);
}
vec2 translate(float fdir, float fvel) {
float angle_in_radian = map(fdir, 0, roof_component_colour, -PI, PI);
vec2 dir_cart = cartesian_coord(angle_in_radian);
return dir_cart *fvel ;
}
void main() {
vec2 ratio = gl_FragCoord.xy *wh_ratio;
vec4 vel = texture2D(vel_texture, ratio);
vec4 dir = texture2D(dir_texture, ratio);
// rendering picture ;
if(mode == 0) {
float direction = dir.x;
float velocity = vel.x;
vec2 translation = translate(direction,velocity);
// not bad, but totaly wrong
// vec2 coord_dest = vertTexCoord.st +translation
vec2 coord_dest = vertTexCoord.st *ratio +translation ;
// not bad, but totaly wrong
vec2 coord_dest = vertTexCoord.st *ratio +translation ;
vec4 tex_colour = texture2D(texture, coord_dest);
gl_FragColor = tex_colour;
}
// velocity
if(mode == 1 ) {
gl_FragColor = texture2D(vel_texture, vertTexCoord.st);;
}
// direction force field
if(mode == 2) {
gl_FragColor = texture2D(dir_texture, vertTexCoord.st);;
}
}
贴图格式为GL_RGBA8
,即每个颜色通道都存储到一个字节中,是一个整数数据类型,范围从0到255。
但是当你从纹理采样器中读取文本时,你会得到一个 0.0 到 1.0 范围内的浮点值。 (参见 glTexImage2D
- GL_RGBA)。
在片段着色器中,您必须将从纹理采样器读取的颜色通道(在 [0, 1] 中)映射到从 -PI 到 PI 的范围。为此,您可以使用 GLSL 函数 mix
,它在两个值之间进行线性插值:
vec2 translate(float fdir, float fvel) // fdir, fvel in [0.0, 1.0]
{
float angle = mix(-PI, PI, fdir);
return vec2(cos(angle), sin(angle)) * fvel;
}
纹理坐标在[0, 1]范围内。您必须将 translation
转换为纹理坐标。为此,您必须知道图像纹理的大小:
vec2 wh_ratio; // 1f/grid_w, 1f/grid_h
vec2 imageTexSize; // size of "texture"
vec2 scale = imageTexSize * wh_ratio;
vec2 coord_dest = vertTexCoord.st + translation / scale;
谢谢你的帮助,现在我知道了 GLSL 中图片的图片尺寸 :) [0,1]
,但这不是预期的工作,我使用渲染尺寸或必须扭曲的图片,所以在我看来 vec2 imageTexSize
是 img.width
并且 img.height
是从 Processing for imageTexSize
uniform vec2 imageTexSize;
.../...
vec2 scale = imageTexSize * wh_ratio;
vec2 coord_dest = vertTexCoord.st + translation / scale;
结果是顶部图像
当我尝试此代码时
vec2 ratio = gl_FragCoord.xy *wh_ratio;
vec2 coord_dest = vertTexCoord.st +translation / ratio ;
结果是中间的图
当我尝试这个时
vec2 coord_dest = vertTexCoord.st +translation / wh_ratio ;
结果为底图
抱歉,我 post 一张图片,因为我无法 post 多张以我的初学者声誉拍摄的照片 :)
我修复了完整 window 显示的显示错误,但现在是 y 坐标是平移的反向,这很奇怪,因为纹理速度和方向在 y 中没有反向,反向 y效果在于解释。这发生在 3 模式上。我试着像那样反转coord_dest.y
float coord_dest_y = mix(coord_dest.y, vertTexCoord.t, 0);
gl_FragColor = texture2D(texture, vec2(coord_dest.x, coord_dest_y));
但这并没有改变什么。
我尝试了:float coord_dest_y = mix(coord_dest.y, 0, vertTexCoord.t);
但是这让事情变得很奇怪,所以这也行不通...
这里是完整的 GLSL 代码
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
#define PI 3.1415926535897932384626433832795
varying vec4 vertTexCoord;
uniform sampler2D texture;
uniform int mode;
uniform sampler2D vel_texture;
uniform sampler2D dir_texture;
uniform vec2 wh_grid_ratio;
uniform vec2 wh_renderer_ratio;
vec2 cartesian_coord(float angle) {
float x = cos(angle);
float y = sin(angle);
return vec2(x,y);
}
vec2 translate(float fdir, float fvel) {
//float angle = mix(PI, -PI,fdir);
float angle = mix(fdir, PI, -PI);
return cartesian_coord(angle) *fvel ;
}
void main() {
vec2 ratio = gl_FragCoord.xy *wh_renderer_ratio;
vec4 vel = texture2D(vel_texture, ratio);
vec4 dir = texture2D(dir_texture, ratio);
float direction = dir.x;
float velocity = vel.x;
vec2 translation = translate(direction,velocity);
// mode 0 perfect
// mode 1 interesting
// mode 2 bizarre, but fun
// mode 500 warp image direction
// mode 501 warp image velocity
// perfect
if(mode == 0) {
vec2 scale = gl_FragCoord.xy *wh_renderer_ratio;
vec2 coord_dest = vertTexCoord.st +translation /scale;
float coord_dest_y = mix(coord_dest.y, vertTexCoord.t, 0);
// float coord_dest_y = mix(coord_dest.y, 0, vertTexCoord.t);
gl_FragColor = texture2D(texture, vec2(coord_dest.x, coord_dest_y));
// gl_FragColor = texture2D(texture, coord_dest);
}
// interesting
if(mode == 1) {
vec2 scale = gl_FragCoord.xy *wh_grid_ratio;
vec2 coord_dest = vertTexCoord.st +translation /scale ;
gl_FragColor = texture2D(texture, coord_dest);
}
// bizarre
if(mode == 2) {
vec2 coord_dest = vertTexCoord.st +translation /wh_grid_ratio;
gl_FragColor = texture2D(texture, coord_dest);
}
// velocity
if(mode == 500 ) {
vec4 tex_colour = texture2D(vel_texture, vertTexCoord.st);;
gl_FragColor = tex_colour;
}
// direction force field
if(mode == 501) {
vec4 tex_colour = texture2D(dir_texture, vertTexCoord.st);;
gl_FragColor = tex_colour;
}
}
和这里的图片结果,最后warping看到光标错误y enter image description here