Webgl 将像素转换为clipspace

Webgl 将像素转换为clipspace,webgl,shader,glsles,Webgl,Shader,Glsles,我宁愿像2D画布上下文那样为着色器提供像素值,而不是为着色器提供-1对1的值。所以根据我读到的,我添加了一个统一的变量,我将它设置为画布的大小,然后我进行了划分 但我肯定错过了什么。渲染太大了 gl_u.resolutionLocation=gl.getUniformLocation(gl_u.program,“u_uresolution”); gl.uniform4f(gl.resolutionLocation,game.w,game.h,game.w,game.h); 我的顶点着色器: 属

我宁愿像2D画布上下文那样为着色器提供像素值,而不是为着色器提供-1对1的值。所以根据我读到的,我添加了一个统一的变量,我将它设置为画布的大小,然后我进行了划分

但我肯定错过了什么。渲染太大了

gl_u.resolutionLocation=gl.getUniformLocation(gl_u.program,“u_uresolution”);
gl.uniform4f(gl.resolutionLocation,game.w,game.h,game.w,game.h);
我的顶点着色器:

属性向量4位置;
属性向量2 texcoord;
均匀vec4 u_分辨率;
均匀mat4u_矩阵;
可变vec3 v_texcoord;
void main(){
vec4 zeroToOne=位置/u_分辨率;
gl_位置=u_矩阵*zeroToOne;
v_texcoord=vec3(texcoord.xy,1)*abs(position.x);
v_texcoord=v_texcoord/u_分辨率.xyz;
}
我的片段着色器:

precision mediump float;
可变vec3 v_texcoord;
均匀采样2d-tex;
均匀浮动α;
void main()
{
gl_FragColor=纹理2dproj(tex,v_texcoord);
gl_FragColor.rgb*=gl_FragColor.a;
}

如果您希望使用与代码类似的代码保持像素,那么您希望在以像素为单位完成所有操作后,将转换应用到剪辑空间

换句话说,代码应该是这样的

 rotatedPixelPosition = rotationMatrix * pixelPosition
 clipSpacePosition = (rotatedPixelPosition / resolution) * 2.0 - 1.0; 
换句话说,你会想要

vec4 rotatedPosition = u_matrix * position;
vec2 zeroToOne = rotatedPosition.xy / u_resolution.xy;
vec2 zeroToTwo = zeroToOne * 2.0;
vec2 minusOneToPlusOne = zeroToTwo - 1.0;
vec2 clipspacePositiveYDown = minusOneToPlusOne * vec2(1, -1);
gl_Position = vec4(clipspacePositiveYDown, 0, 1);
如果您这样做,并将u_矩阵设置为恒等式,那么如果位置以像素为单位,您应该可以在像素位置看到这些位置。如果u_矩阵严格来说是一个旋转矩阵,则位置将围绕左上角旋转,因为旋转总是围绕0发生,并且上面的转换将0置于左上角

但实际上,这里没有理由手动将像素转换为剪辑空间。您可以在同一矩阵中转换和旋转所有矩阵。涵盖了这一过程。它从平移、旋转、缩放和从像素到剪辑空间(没有矩阵)的转换开始,并将其转换为使用单个矩阵组合所有这些功能的东西

有效地

  matrix = scaleYByMinusMatrix *
           subtract1FromXYMatrix *
           scaleXYBy2Matrix *
           scaleXYBy1OverResolutionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;
然后在着色器中,您只需要

gl_Position = u_matrix * vec4(position, 0, 1);  
前4个矩阵很容易计算为单个矩阵,通常称为正交投影,在这种情况下,它简化为

  matrix = projectionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;

还有一种方法可以从WebGL中的canvas2D中复制矩阵堆栈

,如果您希望使用与代码类似的代码保持像素,那么您希望在以像素完成所有操作后将转换应用到剪辑空间

换句话说,代码应该是这样的

 rotatedPixelPosition = rotationMatrix * pixelPosition
 clipSpacePosition = (rotatedPixelPosition / resolution) * 2.0 - 1.0; 
换句话说,你会想要

vec4 rotatedPosition = u_matrix * position;
vec2 zeroToOne = rotatedPosition.xy / u_resolution.xy;
vec2 zeroToTwo = zeroToOne * 2.0;
vec2 minusOneToPlusOne = zeroToTwo - 1.0;
vec2 clipspacePositiveYDown = minusOneToPlusOne * vec2(1, -1);
gl_Position = vec4(clipspacePositiveYDown, 0, 1);
如果您这样做,并将u_矩阵设置为恒等式,那么如果位置以像素为单位,您应该可以在像素位置看到这些位置。如果u_矩阵严格来说是一个旋转矩阵,则位置将围绕左上角旋转,因为旋转总是围绕0发生,并且上面的转换将0置于左上角

但实际上,这里没有理由手动将像素转换为剪辑空间。您可以在同一矩阵中转换和旋转所有矩阵。涵盖了这一过程。它从平移、旋转、缩放和从像素到剪辑空间(没有矩阵)的转换开始,并将其转换为使用单个矩阵组合所有这些功能的东西

有效地

  matrix = scaleYByMinusMatrix *
           subtract1FromXYMatrix *
           scaleXYBy2Matrix *
           scaleXYBy1OverResolutionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;
然后在着色器中,您只需要

gl_Position = u_matrix * vec4(position, 0, 1);  
前4个矩阵很容易计算为单个矩阵,通常称为正交投影,在这种情况下,它简化为

  matrix = projectionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;

还有一种方法可以从WebGL中的canvas2D复制矩阵堆栈

您希望从[0,u_分辨率]映射到[-1,1]->
zeroToOne.xy=2.0*position.xy/u_分辨率.xy-1.0。但是
u_矩阵
做什么呢?这是一种模式转换吗?位置的
z
w
分量是否设置为偶数?u_矩阵用于旋转。不,我只设置x和y,但我使用vec4位置,以便在梯形上正确显示纹理。不太好。不管怎样,我都无法让它工作,但我放弃了,我已经忘记了这个问题。你想从[0,u_分辨率]映射到[-1,1]->
zeroToOne.xy=2.0*position.xy/u_分辨率.xy-1.0。但是
u_矩阵
做什么呢?这是一种模式转换吗?位置的
z
w
分量是否设置为偶数?u_矩阵用于旋转。不,我只设置x和y,但我使用vec4位置,以便在梯形上正确显示纹理。不太好。不管怎样,我都没有让它工作,但我放弃了,我已经忘记了这个问题。谢谢。我将再次阅读这些文章来理解矩阵的内容。与此同时,我试着用你的代码,它有点工作,但梯形再次被打破…只有当梯形在平移或旋转之前水平居中于原点周围时,梯形代码才会工作。谢谢。我将再次阅读这些文章来理解矩阵的内容。与此同时,我尝试了你的代码,它有点工作,但梯形再次被破坏…只有当梯形在平移或旋转之前水平围绕原点居中时,梯形代码才会工作。