B-4:三维模型的交互与光照效果

B-4. 三维模型的交互与光照效果


作业要求:

  1. 对第 3 题读入的模型使用鼠标进行旋转、缩放操作;
  2. 利用光照模型实现简单光照效果,使用物体材质和环境光、漫反射、镜面反射结合
    产生光照效果;
  3. 光照参考效果见附件“模型光照效果.jpg”。

在这里插入图片描述

鼠标操作

与之前通过捕捉光标而使鼠标移动时自动确定视角方位不同,此题要求鼠标来控制旋转和缩放操作。

因此不能捕捉光标,而是设计为鼠标左键控制平移,右键控制旋转,中键(滚轮)控制缩放。

平移

用一个bool变量MOUSE_LEFT_ON来记录鼠标被按下的事件发生之前,处于被按下还是松开的状态。如果之前是松开的,则记录下当前的光标位置并存储到lastXlastY,以便后续再次松开时能通过光标移动的相对距离xoffsetyoffset来更改摄像机的平移位置。

void processInput(GLFWwindow *window) {
   	... ...
    if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {//正在被按下
        if (MOUSE_LEFT_ON == false) {//之前没被按下
            MOUSE_LEFT_ON = true;
            //保存下来lastX和lastY
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
            lastX = xpos;
            lastY = ypos;
        } else {//之前一直被按着
            //重新获得当前的位置
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos;
            lastX = xpos;
            lastY = ypos;
            camera.ProcessMouseMovement(-xoffset, -yoffset);//更改摄像机位置
        }
    } else {//被松开
        MOUSE_LEFT_ON = false;
    }
    ... ...
}

摄像机的平移操作可以由助教给的Camera类里的ProcessMouseMovement()函数完成。

// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true)
{
    xoffset *= MouseSensitivity;
    yoffset *= MouseSensitivity;
    Yaw   += xoffset;
    Pitch += yoffset;
    // make sure that when pitch is out of bounds, screen doesn't get flipped
    if (constrainPitch)
    {
        if (Pitch > 89.0f)
            Pitch = 89.0f;
        if (Pitch < -89.0f)
            Pitch = -89.0f;
    }
    // update Front, Right and Up Vectors using the updated Euler angles
    updateCameraVectors();
}

旋转

用一个bool变量MOUSE_RIGHT_ON来记录鼠标被按下的事件发生之前,处于被按下还是松开的状态。如果之前是松开的,则记录下当前的光标位置并存储到lastXlastY,以便后续再次松开时能通过光标移动的相对距离xoffsetyoffset来更改摄像机的旋转角度。

void processInput(GLFWwindow *window) {
   	... ...
	if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) {//正在被按下
        if (MOUSE_RIGHT_ON == false) {//之前没被按下
            MOUSE_RIGHT_ON = true;
            //保存下来lastX和lastY
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
            lastX = xpos;
            lastY = ypos;
        } else {//之前一直被按着
            //重新获得当前的位置
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);
            float sensitivity = 3e-3;
            float xoffset = (xpos - lastX)*sensitivity;
            float yoffset = (lastY - ypos)*sensitivity;
            lastX = xpos;
            lastY = ypos;

            camera.ProcessKeyboard(RIGHT, -xoffset);
            camera.ProcessKeyboard(UP   , -yoffset);
        }
    } else {//被松开
        MOUSE_RIGHT_ON = false;
    }
    ... ...
}

注意为了使光标移动一小段距离时不至于产生过大的旋转,需要降低灵敏度,将相对位移乘以一个系数后传入Camera类的ProcessKeyBoard()函数进行处理。

// processes input received from any keyboard-like input system.
// Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
void ProcessKeyboard(Camera_Movement direction, float deltaTime)
{
    float velocity = MovementSpeed * deltaTime;
    if (direction == FORWARD)
        Position += Front * velocity;
    if (direction == BACKWARD)
        Position -= Front * velocity;
    if (direction == LEFT)
        Position -= Right * velocity;
    if (direction == RIGHT)
        Position += Right * velocity;
    if (direction == UP)
        Position += Up * velocity;
    if (direction == DOWN)
        Position -= Up * velocity;
}

缩放

首先通过回调函数scroll_callback()将鼠标事件的变化值传给Camera类。

// glfw: whenever the mouse scroll wheel scrolls, this callback is called
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
    camera.ProcessMouseScroll(yoffset);
}

再通过Camera类中的ProcessMouseScroll()函数完成对相机zoom参数的修改。

// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
void ProcessMouseScroll(float yoffset)
{
    Zoom -= (float)yoffset;
    if (Zoom < 1.0f)
        Zoom = 1.0f;
    if (Zoom > 45.0f)
        Zoom = 45.0f; 
}

通过修改相机的zoom参数,每次在获取投影矩阵projection并设置着色器参数时,就能使渲染的图像得到缩放。

......
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
......
ourShader.setMat4("projection", projection);
......

光照

此题的光照效果与C-4作业的要求完全一样,因此不再赘述。直接使用C-4的实现即可。

效果图

最后的显示效果如下图所示。

第8号材质
第1号材质
第9号材质
第F号材质
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zongy17

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值