您将如何为对象产生滚动效果?

How would you produce a scrolling effect for an object?

我在 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);
}

but I am not sure how to produce a continuous or a scrolling effect of moving the object or rotating ...

为了生成平滑的运动(平移或旋转),模型矩阵的平移或旋转部分必须在每一帧中分别改变少量角度。这可以通过在每一帧中增加一小步的控制变量来实现。必须通过在每一帧中使用此控制变量来重新计算模型矩阵。
参见以下伪代码中的概念:

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;

    .....

... till a key is pressed.

由于问题被标记为 winapi,我假设您已经为成员 lpfnWndProc.

初始化了一个 WNDCLASSEX data structure and that you have set the WindowProc callback function

你必须执行 WM_KEYDOWN message event in the window callback function and to check if the 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 );
}

此外,您必须在主循环中处理 window 消息。请参见 GetMessage function and DispatchMessage 函数。

而不是

while (1)
{
    .....
}

你必须

MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) )
{
    DispatchMessage( &msg );

    .....
}