android opengl es 2.0 glm 投影不工作
android opengl es 2.0 glm projection not working
我正在使用 c/c++ (NDK) for android 在 opengl es 2.0 中编程。由于 android 没有官方的 C++ 库,我使用的是 GLM 库 !
到目前为止,我可以在黑色背景上绘制一个白色三角形,而无需应用任何 projection/frustum 或 camera/view 矩阵。当然,这会导致三角形沿屏幕宽度缩放。
然而,一旦我应用相机和投影变换,三角形就会从场景中消失,只出现背景颜色。
这是相关代码:
float triangleCoords[] = { // in counterclockwise order:
0, 1, 0, // top
-1, 0, 0, // bottom left
1, 0, 0 // bottom right
};
std::string vertexShaderCode =
"attribute vec4 vPosition; "
"uniform mat4 uMVPMatrix; "
"void main() {"
" gl_Position = uMVPMatrix*vPosition;"
"}";
std::string fragmentShaderCode =
"precision mediump float;"
"uniform vec4 vColor;"
"void main() {"
" gl_FragColor = vColor;"
"}";
mvpMatrix=glm::translate(mvpMatrix,vec3(0,-0.5,0));
mvpMatrix*=glm::lookAt(vec3(0,0,-3),vec3(0,0,0),vec3(0,1,0));
mvpMatrix*=glm::frustum(-1.0f,1.0f,-ratio,ratio,3.0f,7.0f);
其中 vec3 是 "typedef glm::vec3" 并且 mvpMatrix 是 "glm::mat4x4"
我已经尝试了很多方法,例如在截锥体之前乘以 lookAt 并改变截锥体的近远值等。
我也试过改变三角形坐标看它是否被剪裁但无济于事
但是,如果未应用 lookAt 和 frustum,则 0.5 单位的转换可以正常工作,这意味着从矩阵到着色器的值传递是正确的。
帮我解决这个问题
您对 glm 库的使用不当。
您在着色器中使用的约定(匹配旧的固定功能管道的默认约定以及 glm 的约定)是 matrix * vector
。
当您将多个变换组合到一个矩阵时,您会得到以下结果:M=A*B*C
并将其应用于某个向量 v
作为 v' = M * v
。但是这个和v' = A * ( B * ( C * v))
是一样的,所以C
其实是先应用。在你的情况下,你有 M * V * P
,但正确的 "ModelViewProjection" 转换首先应用模型转换(到达世界 space),然后是视图转换(到达眼睛 space) 最后投影转换到剪辑 space,所以你需要 P * V * M
.
请注意,根据您选择的数字,三角形最终会恰好位于近平面 - 但由于数值不精确,它可能仍会被剔除。
我正在使用 c/c++ (NDK) for android 在 opengl es 2.0 中编程。由于 android 没有官方的 C++ 库,我使用的是 GLM 库 !
到目前为止,我可以在黑色背景上绘制一个白色三角形,而无需应用任何 projection/frustum 或 camera/view 矩阵。当然,这会导致三角形沿屏幕宽度缩放。
然而,一旦我应用相机和投影变换,三角形就会从场景中消失,只出现背景颜色。
这是相关代码:
float triangleCoords[] = { // in counterclockwise order:
0, 1, 0, // top
-1, 0, 0, // bottom left
1, 0, 0 // bottom right
};
std::string vertexShaderCode =
"attribute vec4 vPosition; "
"uniform mat4 uMVPMatrix; "
"void main() {"
" gl_Position = uMVPMatrix*vPosition;"
"}";
std::string fragmentShaderCode =
"precision mediump float;"
"uniform vec4 vColor;"
"void main() {"
" gl_FragColor = vColor;"
"}";
mvpMatrix=glm::translate(mvpMatrix,vec3(0,-0.5,0));
mvpMatrix*=glm::lookAt(vec3(0,0,-3),vec3(0,0,0),vec3(0,1,0));
mvpMatrix*=glm::frustum(-1.0f,1.0f,-ratio,ratio,3.0f,7.0f);
其中 vec3 是 "typedef glm::vec3" 并且 mvpMatrix 是 "glm::mat4x4"
我已经尝试了很多方法,例如在截锥体之前乘以 lookAt 并改变截锥体的近远值等。
我也试过改变三角形坐标看它是否被剪裁但无济于事
但是,如果未应用 lookAt 和 frustum,则 0.5 单位的转换可以正常工作,这意味着从矩阵到着色器的值传递是正确的。
帮我解决这个问题
您对 glm 库的使用不当。
您在着色器中使用的约定(匹配旧的固定功能管道的默认约定以及 glm 的约定)是 matrix * vector
。
当您将多个变换组合到一个矩阵时,您会得到以下结果:M=A*B*C
并将其应用于某个向量 v
作为 v' = M * v
。但是这个和v' = A * ( B * ( C * v))
是一样的,所以C
其实是先应用。在你的情况下,你有 M * V * P
,但正确的 "ModelViewProjection" 转换首先应用模型转换(到达世界 space),然后是视图转换(到达眼睛 space) 最后投影转换到剪辑 space,所以你需要 P * V * M
.
请注意,根据您选择的数字,三角形最终会恰好位于近平面 - 但由于数值不精确,它可能仍会被剔除。