CSh*_*pie 5 opengl vertex-shader
在OpenGL中进行旋转和转换时我有点卡住了.
我有3个矩阵,投影,视图和模型.
我的VertexShader:
gl_Position = projection * model * view * vec4(vertexData, 1);
Run Code Online (Sandbox Code Playgroud)
翻译和旋转对象的最佳方法是什么?
要么将我的模型矩阵与平移和/或旋转矩阵相乘,要么将数据(旋转和平移)传递给着色器和那里的数学?
我还需要知道我的鼠标实现的"最终对象位置".
到目前为止我做的是这样的:
object.Transformation = Matrix.CreateTransLation(x,y,z) * Matrix.CreateRotation(x,y,z);
Run Code Online (Sandbox Code Playgroud)
...
ForEach object to Draw
{
modelMatrix.Push();
modelMatrix.Mult(object.Transformation); // this also updates the matrix for the shader
object.Draw();
modelMatrix.Pop();
}
Run Code Online (Sandbox Code Playgroud)
这有效,但感觉不对.最好的方法是什么?
dat*_*olf 16
这个
Run Code Online (Sandbox Code Playgroud)gl_Position = projection * model * view * vec4(vertexData, 1);
是错的.矩阵乘法不是可交换的,即操作顺序很重要.顶点位置的变换按顺序为:
OpenGL使用的列向量的矩阵乘法是左关联的,即从右到左.因此,声明的R方面的表达应该是
Run Code Online (Sandbox Code Playgroud)gl_Position = projection * view * model * vec4(vertexPosition, 1);
但是,您可以将视图和模型转换为复合模型视图(第一个模型,然后是视图)转换.这样可以节省全矩阵乘法
Run Code Online (Sandbox Code Playgroud)gl_Position = projection * modelview * vec4(vertexPosition, 1);
投影应保持分离,因为其他阴影步骤可能需要顶点的眼睛空间位置,这是modelview * position未施加投影的结果.
顺便说一句:你正在改变顶点位置,而不是数据.顶点包含大量属性(不仅仅是位置),因此称其为"数据"在语义上是错误的.
翻译和旋转对象的最佳方法是什么?
这些是模型视图转换的一部分.您应该创建一个变换矩阵恰好一个在CPU上的时间和它传递给GPU.在着色器中执行此操作将强制GPU重做每个顶点的整个计算.你不想这样做.
假设您正在使用我的→linmath.h.然后在您的绘图功能中,您已经为场景设置了脚手架,即设置视口,构建投影和视图矩阵
#include <linmath.h>
/* ... */
void display(void)
{
mat4x4 projection;
mat4x4 view;
glClear(…),
glViewport(…);
mat4x4_frustum(projection, …);
// linmath.h doesn't have a look_at function... yet
// I'll add it soon
mat4x4_look_at(view, …);
Run Code Online (Sandbox Code Playgroud)
然后,对于每个对象,您有一个位置和方向(平移和旋转).方向最方便地存储在四元数中,但是对于处理向量,矩阵表示更好.所以我们迭代场景中的对象
for(int i_object = 0; i_object < scene->n_objects; i++) {
Object * const obj = scene->objects + i;
mat4x4 translation, orientation, model_view;
mat4x4_translate(translation, obj->pos.x, obj->pos.y, obj->pos.z);
mat4x4_from_quat(orientation, obj->orientation);
mat4x4_mul(model_view, translation, orientation);
Run Code Online (Sandbox Code Playgroud)
model_view现在包含模型矩阵.接下来我们将view矩阵乘以它.请记住,矩阵乘法是从右到左(mat4x4_mul可以输出到其输入操作数之一).
mat4x4_mul(model_view, view, model_view);
Run Code Online (Sandbox Code Playgroud)
现在model_view包含完整的compount模型方向和转换和视图矩阵.我们现在需要做的就是绑定用于该对象的着色器程序
glUseProgram(obj->shader->program);
Run Code Online (Sandbox Code Playgroud)
设置制服
glUniformMatrix4f(obj->shader->location.projection, 1, GL_FALSE, projection);
glUniformMatrix4f(obj->shader->location.modelview, 1, GL_FALSE, model_view);
// and a few others...
Run Code Online (Sandbox Code Playgroud)
并绘制对象
object_draw(obj);
}
/* ... */
}
Run Code Online (Sandbox Code Playgroud)