Glsl 在顶点着色器中应用Y旋转时,纹理坐标会移动

Glsl 在顶点着色器中应用Y旋转时,纹理坐标会移动,glsl,shader,webgl,uv-mapping,Glsl,Shader,Webgl,Uv Mapping,我试图从着色器中的两个三角形旋转平面。 一切都很顺利,只是我无法理解当我应用旋转时,UV坐标值会发生什么 如何以预期的结果执行此旋转 这看起来像是为每个三角形插值的独立UV坐标 让pid旋转定位; 设gl=canvas.getContext('webgl'); 让值=document.querySelector('span') let loader=new Image(); loader.crossOrigin=“匿名”; loader.src=”https://i.imgur.com/G

我试图从着色器中的两个三角形旋转平面。 一切都很顺利,只是我无法理解当我应用旋转时,UV坐标值会发生什么

如何以预期的结果执行此旋转

这看起来像是为每个三角形插值的独立UV坐标

让pid旋转定位;
设gl=canvas.getContext('webgl');
让值=document.querySelector('span')
let loader=new Image();
loader.crossOrigin=“匿名”;
loader.src=”https://i.imgur.com/G9H683l.jpg";
loader.onload=函数(){
canvas.width=loader.width;
canvas.height=loader.height;
pid=gl.createProgram();
着色器(`
浮动视角=1.0;
属性向量2坐标;
均匀浮动旋转;
可变vec2紫外线;
真空总管(真空){
mat3 rotY=mat3(vec3(cos(rotateY),0.0,sin(rotateY)),
vec3(0.0,1.0,0.0),
vec3(-sin(rotateY),0.0,cos(rotateY));
vec3p=vec3(coords.xy,0.)*rotY;
uv=coords.xy.xy*0.5+0.5;
gl_位置=vec4(p/(1.0+p.z*透视图),1.0);
}
`,gl.VERTEX_着色器);
着色器(`
高精度浮点;
二维纹理均匀;
可变vec2紫外线;
真空总管(真空){
gl_FragColor=纹理2D(纹理,uv);
}
`,gl.FRAGMENT_SHADER);
总账链接程序(pid);
总帐使用程序(pid);
让数组=新的Float32Array([-1.0,-1.0,1.0,-1.0,-1.0,1.0,
-1.0,  1.0,   1.0, -1.0,    1.0, 1.0]);
gl.bindBuffer(gl.ARRAY_BUFFER,gl.createBuffer());
总账缓冲数据(总账数组缓冲、数组、总账静态绘图);
设al=gl.getAttribLocation(pid,“coords”);
gl.VertexAttribute指针(al,2,gl.FLOAT,false,0,0);
gl.EnableVertexAttributeArray(al);
让纹理=gl.createTexture();
gl.pixelStorei(gl.UNPACK\u FLIP\u Y\u WEBGL,真)
gl.bindTexture(gl.TEXTURE_2D,纹理);
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_字节,加载器);
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MIN\u过滤器,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D、gl.TEXTURE_WRAP_S、gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE\u 2D、gl.TEXTURE\u WRAP\u T、gl.CLAMP\u至边缘);
gl.uniform1i(gl.getuniformlLocation(pid,“纹理”),0;
rotateYlocation=gl.getUniformLocation(pid,“rotateY”);
draw();
}
函数绘图(){
总图视口(0,0,总图drawingBufferWidth,总图drawingBufferHeight);
gl.clearColor(0,0,0,0);
gl.uniform1f(旋转位置,旋转值/1000-0.5)
gl.绘图阵列(gl.三角形,0,6);
values.textContent=`rotateY:${(rotateY.value/1000-0.5).toFixed(3)}`;
}
函数着色器(src,类型){
设sid=gl.createShader(类型);
gl.shaderSource(sid、src);
总帐编译管理员(sid);
var message=gl.getShaderInfoLog(sid);
总账附件(pid、sid);
如果(message.length>0){
console.log(src.split('\n').map(函数(str,i){
return(“+(1+i)).padStart(4,“0”)+”:“+str
}).join('\n');
抛出消息;
}
}



变量以透视正确的方式插入<代码>总图位置
是一个(x,y,z,w)。对于透视正确的插值,必须正确设置坐标

当你这样做的时候

由于坐标仅为a(x,y,z,1),因此无法正确执行透视插值,这导致线性插值,因为w=1。
有关透视正确插值的详细信息,请参见

齐次坐标通过A转换为笛卡尔标准化设备坐标。
您必须设置剪辑空间坐标,即透视分割之前的坐标:

gl_Position=vec4(p,1.0+p.z*透视图);
让pid旋转定位;
设gl=canvas.getContext('webgl');
让值=document.querySelector('span')
let loader=new Image();
loader.crossOrigin=“匿名”;
loader.src=”https://i.imgur.com/G9H683l.jpg";
loader.onload=函数(){
canvas.width=loader.width;
canvas.height=loader.height;
pid=gl.createProgram();
着色器(`
浮动视角=1.0;
属性向量2坐标;
均匀浮动旋转;
可变vec2紫外线;
真空总管(真空){
mat3 rotY=mat3(vec3(cos(rotateY),0.0,sin(rotateY)),
vec3(0.0,1.0,0.0),
vec3(-sin(rotateY),0.0,cos(rotateY));
vec3p=vec3(coords.xy,0.)*rotY;
uv=coords.xy.xy*0.5+0.5;
gl_位置=vec4(p,1.0+p.z*透视图);
}
`,gl.VERTEX_着色器);
着色器(`
高精度浮点;
二维纹理均匀;
可变vec2紫外线;
真空总管(真空){
gl_FragColor=纹理2D(纹理,uv);
}
`,gl.FRAGMENT_SHADER);
总账链接程序(pid);
总帐使用程序(pid);
让数组=新的Float32Array([-1.0,-1.0,1.0,-1.0,-1.0,1.0,
-1.0,  1.0,   1.0, -1.0,    1.0, 1.0]);
gl.bindBuffer(gl.ARRAY_BUFFER,gl.createBuffer());
总账缓冲数据(总账数组缓冲、数组、总账静态绘图);
设al=gl.getAttribLocation(pid,“coords”);
gl.VertexAttribute指针(al,2,gl.FLOAT,false,0,0);
gl.EnableVertexAttributeArray(al);
让纹理=gl.createTexture();
gl.pixelStorei(gl.UNPACK\u FLIP\u Y\u WEBGL,真)
gl.bindTexture(gl.TEXTURE_2D,纹理);
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_字节,加载器);
gl.texParameteri(gl.TEXTURE\u 2D,gl.TEXTURE\u MIN\u过滤器,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D、gl.TEXTURE_WRAP_S、gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE\u 2D、gl.TEXTURE\u WRAP\u T、gl.CLAMP_
gl_Position = vec4(p / (1.0 + p.z * perspective), 1.0)