我在Visual C ++中使用OpenGL,并在VBO和VAO中显示矩形,并且我有一个基本的顶点着色器和片段着色器来为对象应用颜色和位置。
我想产生物体的滚动效果,直到按下 Esc 键。最好的方法是什么?
我知道您可以将模型矩阵,视图矩阵和投影矩阵提供给着色器,以对对象执行更改。尤其是用于执行转换的模型矩阵。我可以更改对象的位置并旋转它,但是我不确定如何产生连续或滚动效果,即移动对象或旋转直到按下某个键。
到目前为止,我的代码:
GLfloat vb_data[] = {
-0.25f, 0.25f, 0.0f, // Top-left
0.25f, 0.25f, 0.0f, // Top-right
0.25f, -0.25f, 0.0f, // Bottom-right
-0.25f, -0.25f, 0.0f // Bottom-left
};
glGenBuffers(1, &vbo_ID);
glBindBuffer(GL_ARRAY_BUFFER, vbo_ID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vb_data), vb_data, GL_DYNAMIC_DRAW);
GLfloat incre = 0.01f;
glClear(GL_COLOR_BUFFER_BIT);
while (1){
glm::mat4 trans = glm::mat4(1.0f);
glm::mat4 transBar = glm::translate(trans, glm::vec3(0.2f, 0.2f, 1.0f));
glm::mat4 MVP = transBar;
glUseProgram(pgID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo_ID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_QUADS,0, 4);
glDisableVertexAttribArray(0);
SwapBuffers(g_pOpenGLWindow->hDC);
}
答案 0 :(得分:0)
但是我不确定如何产生连续或滚动的效果来移动对象或旋转...
要生成平滑运动(平移或旋转),必须在每帧中分别减小模型矩阵的平移或旋转部分和相应的角度。这可以通过控制变量来实现,该控制变量在每帧中以一小步递增。必须在每一帧中使用此控制变量来重新计算模型矩阵。
请参见以下伪代码中的概念:
translate_x = 0;
angle = 0;
while (1)
model_matrix = translate(translate_x, 0, 0) * roatateX(angle)
translate_x = translate_x + step_x
angle = angle + step_angle
尝试以下代码并使用参数,以达到您所需的效果:
float angle = 0.0f;
float step_ang = 1.0f;
float trans_x = -0.5f;
float step_x = 0.01f;
bool move_forward = true;
while (1)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(trans_x, 0.2f, 1.0f));
model = glm::rotate(model, glm::radians(angle), glm::vec3(0.0f, 0.0f, 1.0f));
angle += step_ang;
trans_x += move_forward ? step_x : -step_x;
move_forward = move_forward ? trans_x < 0.5f : trans_x <= -0.5f;
glm::mat4 MVP = model;
.....
...直到按下一个键。
由于问题被标记为 winapi ,因此我假设您已初始化WNDCLASSEX
数据结构,并且已将WindowProc callback function设置为成员lpfnWndProc
您必须在窗口回调函数中实现WM_KEYDOWN消息事件,并检查是否按下了 Esc (VK_ESCAPE
):
全局变量:
bool esc_pressed = false;
回叫功能:
LRESULT CALLBACK WindowProcedure( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam )
{
switch(msg)
{
case WM_KEYDOWN:
if ( wparam == VK_ESCAPE )
esc_pressed = true;
break;
// other messages
// ...
}
return DefWindowProc( hWnd, msg, wparam, lparam );
}
此外,您还必须处理主循环中的窗口消息。请参见GetMessage
函数和DispatchMessage
函数。
代替
while (1)
{
.....
}
您必须
MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) )
{
DispatchMessage( &msg );
.....
}