OpenGL问题列表
✔️ OpenGL没有做任何MVP变换那默认视觉空间的范围多大?
默认的视觉空间为从
-z
方向看 [ − 1 , 1 ] 3 [-1,1]^3 [−1,1]3标准立方体内没有depth_test
的正交投影。也就是只能看见x,y
这个平面。
✔️view
变换应是先将摄像机平移到原点,之后进行摄像机坐标与世界坐标的对齐,也就是先T
再R
。glm::lookAt
的实现把TR
操作放到一个变换矩阵中,岂不是先R
后T
了?
问题本质源于games101图形学理论与OpenGL中具体实现的区别,即理论支撑和落地实践的区别。
games101:先确定相机位置,将相机移动到原点位置,同时所有物体随之做相对运动,最后对齐相机坐标和世界坐标,所有物体依旧做相对运动。
OpenGL:相机(视点)永远在原点位置,根据定义的摄像机坐标先与世界坐标对齐,最后物体再平移。可以说没有相对运动一说,因为相机永远不动,只有物体去找自己应该站的位置。
template <typename T>
GLM_FUNC_QUALIFIER detail::tmat4x4<T> lookAt
(
detail::tvec3<T> const & eye,
detail::tvec3<T> const & center,
detail::tvec3<T> const & up
)
{
detail::tvec3<T> f = normalize(center - eye);
detail::tvec3<T> u = normalize(up);
detail::tvec3<T> s = normalize(cross(f, u));
u = cross(s, f);
detail::tmat4x4<T> Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] =-f.x;
Result[1][2] =-f.y;
Result[2][2] =-f.z;
Result[3][0] =-dot(s, eye);
Result[3][1] =-dot(u, eye);
Result[3][2] = dot(f, eye);
return Result;
}
✔️glm::lookAt
的上向量参数设置成不同的参数值,呈现效果却一样?
此方法的上向量参数,并不是严格意义上的上向量(up)。具体看源码,他是根据此向量和lookat向量生成right向量,然后由right和lookat重新生成真正意义上的up向量。并且无需传进一个单位向量,方法内部会自动进行标准化。
✔️ 归一化的意义是什么?
为了适配不同大小的视口
✔️ 关于深度测试Z
值越大离视点近,还是越小离视点近的问题。
正常按标准来说视点在原点位置,看向
-z
方向,那应该z
的值越小离视点越远啊!实际上并不是这样,这里的z
说的是世界坐标,而深度测试时所用的z
其实是归一化之后的坐标,区间为[0,1],所以应该是z
越小离视点越近。
✔️ GS的输入类型与DrawArray()
设置的类型有关联吗?
强关联
在使法线可视化实验中,以下两种参数配置所呈现出的效果等价。
versionⅠ:
// main 中 `glDrawArrays(GL_POINTS, 0, 36);` #version 330 core layout (points) in; layout (line_strip, max_vertices = 2) out; in VS_OUT { vec3 normal; } gs_in[]; const float MAGNITUDE = 0.3; uniform mat4 projection; void GenerateLine(int index) { gl_Position = projection * gl_in[index].gl_Position; EmitVertex(); gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE); EmitVertex(); EndPrimitive(); } void main() { GenerateLine(0); }
versionⅡ:
// main 中 `glDrawArrays(GL_TRIANGLES, 0, 36);` #version 330 core layout (triangles) in; layout (line_strip, max_vertices = 6) out; in VS_OUT { vec3 normal; } gs_in[]; const float MAGNITUDE = 0.3; uniform mat4 projection; void GenerateLine(int index) { gl_Position = projection * gl_in[index].gl_Position; EmitVertex(); gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE); EmitVertex(); EndPrimitive(); } void main() { GenerateLine(0); GenerateLine(1); GenerateLine(2); }
✔️ Emitvertex()
会把GS中out
对象当前数据也存储一份吗?
是的,
Emitvertex()
负责产生一个新的顶点作为几何着色器的输出。既然是shader的输出,那必然包括out对象。#version 330 core layout (triangles) in; layout (line_strip, max_vertices = 6) out; in VS_OUT { vec3 normal; } gs_in[]; const float MAGNITUDE = 0.3; uniform mat4 projection; void GenerateLine(int index) { gl_Position = projection * gl_in[index].gl_Position; EmitVertex(); gl_Position = projection * (gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE); EmitVertex(); EndPrimitive(); } void main() { GenerateLine(0); GenerateLine(1); GenerateLine(2); }