【问题标题】:Why isn't this orthographic vertex shader producing the correct answer?为什么这个正交顶点着色器不能产生正确的答案?
【发布时间】:2011-10-21 22:49:22
【问题描述】:

我的问题是我有一个(工作的)正交顶点和片段着色器对,允许我通过传入的“translateX”和“translateY”制服指定精灵的中心 X 和 Y。我乘以一个投影矩阵是硬编码的,效果很好。就正交运算而言,一切都有效。我传入此着色器的几何图形以 0、0、0 为中心点。

我现在想弄清楚平移后的中心点(局部坐标空间中的 0、0、0)变成了什么。我需要在片段着色器中知道这些信息。我假设我可以在 0、0、0 处创建一个向量,然后应用相同的平移。但是,我没有得到正确的答案。

我的问题:我做错了什么,我该如何调试正在发生的事情?我知道正在计算的值一定是错误的,但我不知道它是什么。 (我的平台是 Xcode 4.2 on OS X 为 OpenGL ES 2.0 iOS 开发)

这是我的顶点着色器:

// Vertex Shader for pixel-accurate rendering
attribute vec4 a_position;
attribute vec2 a_texCoord;

varying vec2 v_texCoord;

uniform float translateX;
uniform float translateY;

// Set up orthographic projection 
// this is for 640 x 960
mat4 projectionMatrix = mat4( 2.0/960.0, 0.0, 0.0, -1.0,
                             0.0, 2.0/640.0, 0.0, -1.0,
                             0.0, 0.0, -1.0, 0.0,
                             0.0, 0.0, 0.0, 1.0);                        

void main()
{
    // Set position
    gl_Position = a_position;

    // Translate by the uniforms for offsetting
    gl_Position.x += translateX;
    gl_Position.y += translateY;

    // Translate
    gl_Position *= projectionMatrix;


    // Do all the same translations to a vector with origin at 0,0,0
    vec4 toPass = vec4(0, 0, 0, 1); // initialize.  doesn't matter if w is 1 or 0
    toPass.x += translateX;
    toPass.y += translateY;
    toPass *= projectionMatrix;

    // this SHOULD pass the computed value to my fragment shader.
    // unfortunately,  whatever value is sent, isn't right.
    //v_translatedOrigin = toPass;

    // instead, I use this as a workaround, since I do know the correct values for my
    // situation.  of course this is hardcoded and is terrible.
    v_translatedOrigin = vec4(500.0, 200.0, 0.0, 0.0);
}

编辑:作为对我的正交矩阵错误的回应,以下是wikipedia 对正交投影的看法,而我的 -1 看起来是正确的。因为在我的情况下,例如我的垫子的第 4 个元素应该是 -((right+left)/(right-left)),它是 0 左边 960 的右边,所以 -1 * (960/960) 是 -1 .

编辑:我可能在这里发现了根本问题 - what do you think?

【问题讨论】:

  • “但是,我没有得到正确的答案。”那么,你得到了什么答案?
  • @Nicol 我不知道我得到了什么。我怎么知道?这是我的问题的一部分。我知道我正在用它做什么,但它还很遥远。
  • 要知道你得到什么答案,你必须使用着色器调试策略。这包括但不限于:将您提供给片段着色器的值写入屏幕(转换为适合颜色范围)。将您提供给片段着色器的值写入辅助渲染目标(通过 FBO)并使用glReadPixels 读取这些值。您应该能够预测您希望看到的内容,然后注意与此的差异。
  • WRT 到您的投影,最右边一列中的值是否对应于矩阵中的值 12、13、14?
  • 转置我的投影矩阵使我当前在屏幕上显示的精灵不显示。

标签: opengl shader vertex-shader


【解决方案1】:

为什么您的正交矩阵的每列底部都有 -1?那些应该是零。当然,这不会影响任何事情。

我比较关心这个:

gl_Position *= projectionMatrix;

这是什么意思?矩阵乘法不是可交换的M * aa * M 不同。那么您希望gl_Position 乘以哪一边?

奇怪的是,GLSL 规范没有说明(我为此提交了错误报告)。所以你应该选择保证有效的方法:

gl_Position = projectionMatrix * gl_Position;

此外,您应该使用正确的矢量化代码。您应该有一件translate 制服,即vec2。然后你可以做gl_Position.xy = a_position.xy + translate;。您必须用常数 (gl_Position.zw = vec2(0, 1);) 填写 Z 和 W。


GLSL 中的矩阵是列主要的。前四个值是矩阵的第一个 ,而不是第一行。您正在与转置的正交矩阵相乘。

【讨论】:

  • 我尝试将其拆分为 ` .. = projectionMatrix * .. ` 并且它对我的常规正交投影或平移此本地原点没有影响。我不知道为什么我的正交矩阵在每列的底部都有 -1,但是当我煞费苦心地设置所有这些正交绘图时,我似乎需要它,而且我仍然需要它,因为如果我更改为 0,我的精灵会绘制在“错误”的地方。矢量化代码是一种优化,不会影响正在发生的事情,但感谢您的建议。
  • @Nektarios:如果删除那些 -1 会使事情中断,那么它们已经被破坏了。发生了两个错误让事情顺利进行,但这并没有减少他们的错误。
  • 请看我的编辑。你能告诉我为什么这些不应该是-1吗?因为,它以我期望的方式工作,我再次查找了正交矩阵定义,它与我正在做的事情相匹配
  • 无论如何,我不确定您是否可以阅读gl_Position。但我想如果不是这样,那将是一个编译错误。
  • @Christian 你绝对可以 - 我的那部分代码按我的预期工作
【解决方案2】:

我必须附和尼可波拉斯的观点。发生两个错误以使事情正常进行是令人沮丧的,但并没有减少错误。事情出现在您期望的地方很可能是因为矩阵的平移部分是 0、0、0。

您发布的等式是正确的,但符号是行主要的,而 OpenGL 是列主要的:

我开始的每个新项目都会与这些东西发生冲突。 This site 是一个非常好的资源,它帮助我保持这些事情的正确性。他们在projection matrices 上有另一个页面。

如果您不确定您的正交投影是否正确(现在不正确),请尝试将相同的值插入 GL_PROJECTION 的 glOrthoreading the values back out

【讨论】:

  • 不幸的是,glOrtho 在 ES 2.0 上不存在。我试图找出两个错误 - 因为我的正交矩阵是错误的,所以它的错误对应可能是什么?我发送顶点数据,这可能是错误的,但这没有意义。顶点着色器乘以这个正交矩阵(这是“错误的”部分)。片段着色器只是添加颜色,这不会错。然后就是这样。如果我传入不同的几何图形,我会按照预期在屏幕上的不同位置进行渲染。如果我传入我的“translateX”并添加它,那就可以了。这部分内容并不多。
  • 而且由于这部分内容不多,显而易见的答案是我应该编写一个示例并发布。
  • 从硬编码的正交矩阵来看,看起来你的原点是左下角。您是否有可能指定假设左上角的坐标?回复:glOrtho,你可以在常规的 GL 项目中尝试它,或者相信我的话 :)
猜你喜欢
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 2018-04-06
  • 2013-07-22
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
相关资源
最近更新 更多