【问题标题】:converting pixels to clipspace将像素转换为剪辑空间
【发布时间】:2019-07-19 22:08:56
【问题描述】:

与其给我的着色器提供 -1 到 1 的值,我更愿意给它们提供像素值,就像 2D 画布上下文一样。所以根据我阅读的内容,我确实添加了一个统一变量,我将其设置为画布的大小,然后进行划分。

但我一定错过了什么。渲染图太大了……

gl_.resolutionLocation = gl.getUniformLocation( gl_.program , "u_resolution" );
gl.uniform4f(gl_.resolutionLocation , game.w , game.h , game.w , game.h );

我的顶点着色器:

attribute vec4 position;
attribute vec2 texcoord;
uniform vec4 u_resolution;
uniform mat4 u_matrix;
varying vec3 v_texcoord;

void main() {
    vec4 zeroToOne = position / u_resolution ;
    gl_Position = u_matrix * zeroToOne ;
    v_texcoord = vec3(texcoord.xy, 1) * abs(position.x);
    v_texcoord = v_texcoord/u_resolution.xyz ;
}

我的片段着色器:

precision mediump float;
varying vec3 v_texcoord;
uniform sampler2D tex;
uniform float alpha;

void main()
{
    gl_FragColor = texture2DProj(tex, v_texcoord);
    gl_FragColor.rgb *= gl_FragColor.a ;
}

【问题讨论】:

  • 你想从 [0, u_resolution] 映射到 [-1, 1] -> zeroToOne.xy = 2.0*position.xy/u_resolution.xy - 1.0;。但是u_matrix 做了什么?是模型转换吗?位置的zw 组件是否已设置?
  • u_matrix 用于旋转。不,我只设置了 x 和 y,但我使用 vec4 位置来使纹理正确显示在梯形上。 (stackoverflow.com/questions/56915103/…)
  • 并非如此。无论如何,我没有让它工作,但我放弃了,我忘记了这个问题。

标签: webgl shader glsles


【解决方案1】:

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

换句话说,代码类似于

 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_matrix 设置为标识,那么如果位置以像素为单位,您应该在像素位置看到这些位置。如果 u_matrix 是严格的旋转矩阵,则位置将围绕左上角旋转,因为旋转总是围绕 0 进行,并且上面的转换将 0 放在左上角。

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

有效

  matrix = scaleYByMinusMatrix *
           subtract1FromXYMatrix *
           scaleXYBy2Matrix *
           scaleXYBy1OverResolutionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;

然后在你的着色器中你只需要

gl_Position = u_matrix * vec4(position, 0, 1);  

前 4 个矩阵很容易计算为单个矩阵,通常称为正交投影,在这种情况下它可以简化为

  matrix = projectionMatrix *
           translationInPixelSpaceMatrix *
           rotationInPixelSpaceMatrix *
           scaleInPixelSpaceMatrix;

还有this article,它在 WebGL 中从 canvas2D 再现矩阵堆栈

【讨论】:

  • 谢谢。我将再次阅读这些文章以了解矩阵的内容。与此同时,我尝试了你的代码,它有点工作,但梯形又被打破了......
  • 梯形代码仅在梯形在平移或旋转之前以原点为中心水平居中时才有效。
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-14
  • 2018-01-08
  • 2011-09-09
  • 2011-06-04
相关资源
最近更新 更多