关于Cursor使用的小白第一视角

最近看破局感觉洋哥总是提到cursor,感觉好火,所以打算学习一下怎么用Cursor,如果可以希望能做一个我自己的网站。

之前从来没用过Cursor。所以,这是一篇小白视角的Cursor使用教程。

如果你也是一个小白,并且对Cursor感兴趣,那么就进来看看吧。

首先找到Cursor的下载入口:https://changelog.cursor.sh/

一、前期准备

这里参考了圈友小潘 老师的教程:https://t.zsxq.com/5GtKY
Cursor是一个软件,安装完成后展示的这个界面

在这里插入图片描述 在这里插入图片描述

进入到登陆界面,因为我有账号,就直接登录啦,至于邮箱/谷歌账号/github账号注册,网上教程很多
需要自行解决。

在这里插入图片描述

我用的谷歌账号(需要魔法),完美登录Cursor。

在这里插入图片描述 在这里插入图片描述

在这里插入图片描述

PS:官方文档界面是全英文的,不懂也没关系,下载个“沉浸式翻译:双语对照网页翻译&pdf文档翻译”的英翻中的插件就好啦

在这里插入图片描述

二、初次探索Cursor基础功能

当然参考的还是小潘老师的帖子:https://t.zsxq.com/5GtKY

(这一章大致预览一下就好,工具只有多使用才能熟悉)

一些信息需要知道:cursor是收费的,但注册后14天可以免费试用
在这里插入图片描述

登陆好之后看到的是这样的

在这里插入图片描述

然后到Cursor里随便逛逛,在getting_started.md里看到了简单的介绍,还看到了cursor的官方网址,复制到浏览器打开,收藏,一气呵成

在这里插入图片描述

注意,官方网站是英文的,不过没关系,我上面提到的那个翻译插件,可以自动翻译出中文

在这里插入图片描述

官方文档:https://docs.cursor.com/get-started/migrate-from-vscode
根据官方文档,熟悉一下基本操作

(一)Cursor Tab

简单来说,这个功能可以自动填充代码,你的光标停留在哪,Cursor会自动建议一些代码,你按下“Tab”键,代表你同意这些代码加入,它就会自动把显示的代码填入。

当然,并不是所有情况Cursor都会给出建议,官网上有个论坛讨论的部分,可以提交自己使用Cursor时,出现的异常情况

1、Tab功能打开和关闭入口:页面右下角的“光标选项卡”
在这里插入图片描述
2、把Tab的功能梳理出来
①生成代码:从光标所在的地方给出建议添加的代码
②多行编辑:一次性可以修改好几行,而不是仅限于光标在的那行
③智能重写:可以根据你最近的更新和报错,提出一些建议
④光标预测:自动预测下一个光标所放的位置,可以引导你写代码

这里,试用版和付费版有一些区别:免费版可以获得2000条建议,付费版(Pro和Business 建议次数不受限制)

3、Tab(Cursor预测功能)的显示主要有两种
①灰色的代码,表示所预测的接下来的代码,按下“Tab”键,这些代码就真正显示到你的这一行了
在这里插入图片描述
②当你写的有问题想要修改更新代码时,Cursor发现了你的问题,并且给出建议的代码,是用一个弹窗表示的
在这里插入图片描述在这里插入图片描述

4、同意和拒绝加入预测的代码
①按下“Tab”键表示同意,按下“Esc”表示拒绝
②只想同意一部分代码,按 “Ctrl” + “→”

那么对于Cursor Tab(我理解成代码预测功能)部分的初步了解和摸索就到这啦,再让我看看下一个

(二)Chat

简单来说,就是用语言模型(ChatGPT 4.0这种)帮你生成代码,还不用自己复制粘贴,你觉得代码生成的还可以,就让Cursor直接帮你放文件里。

1、打开和关闭Chat功能:按下Ctrl + L
在这里插入图片描述

2、把Chat的功能梳理一下

①按下“Ctrl”+“Enter” ,输入关键词,就可以从自己的代码库里查询到相关的代码

②输入“@”就可以引用文件夹中所有文件和代码符号

③可以使用图片,点

// camera.cpp #include "camera.h" #include <glm/gtc/quaternion.hpp> #include <cmath> // 用向量值构造函数 Camera::Camera(glm::vec3 position, glm::vec3 up, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)) , MovementSpeed(SPEED) , MouseSensitivity(SENSITIVITY) , Zoom(ZOOM) , Position(position) , WorldUp(up) , Yaw(yaw) , Pitch(pitch) { updateCameraVectors(); // 初始化方向向量 } // 用标量值构造函数 Camera::Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)) , MovementSpeed(SPEED) , MouseSensitivity(SENSITIVITY) , Zoom(ZOOM) , Position(posX, posY, posZ) , WorldUp(upX, upY, upZ) , Yaw(yaw) , Pitch(pitch) { updateCameraVectors(); } // 返回使用欧拉角和观察矩阵计算出的视图矩阵 glm::mat4 Camera::GetViewMatrix() { return glm::lookAt(Position, Position + Front, Up); } //键盘控制摄像机上下左右移动 void Camera::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; } //鼠标控制摄像机移动 void Camera::ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch) { xoffset *= MouseSensitivity; yoffset *= MouseSensitivity; Yaw += xoffset; Pitch += yoffset; if (constrainPitch) { if (Pitch > 89.0f) Pitch = 89.0f; if (Pitch < -89.0f) Pitch = -89.0f; } updateCameraVectors(); } // 鼠标滚轮缩放摄像机 void Camera::ProcessMouseScroll(float yoffset) { Zoom -= static_cast<float>(yoffset) * 2.0f; if (Zoom < 1.0f) Zoom = 1.0f; if (Zoom > 45.0f) Zoom = 45.0f; } //根据相机(更新后的)欧拉角计算前向量 void Camera::updateCameraVectors() { glm::vec3 front; front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch)); front.y = sin(glm::radians(Pitch)); front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch)); Front = glm::normalize(front); Right = glm::normalize(glm::cross(Front, WorldUp)); Up = glm::normalize(glm::cross(Right, Front)); } // camera.h #pragma once #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> // 枚举必须在类外定义 enum Camera_Movement { FORWARD, BACKWARD, LEFT, RIGHT }; // 全局常量(用于默认值) const float YAW = -90.0f; const float PITCH = 0.0f; const float SPEED = 2.5f; const float SENSITIVITY = 0.1f; const float ZOOM = 45.0f; class Camera { public: // 成员变量 glm::vec3 Position; // 摄像机在世界空间中的位置坐标 glm::vec3 Front;//摄像机朝向的前方单位向量 glm::vec3 Up;//当前摄像机自身的“上方”方向 glm::vec3 Right;//由 Front × WorldUp 得到的右方向,用于左右平移 glm::vec3 WorldUp;//通常是 (0,1,0),表示世界的“绝对上方向” float Yaw; // 偏航角,绕 Y 轴旋转,控制左右看 float Pitch;//俯仰角,绕 X 轴旋转,控制上下看 float MovementSpeed;//WASD 移动速度(每秒移动距离) float MouseSensitivity;//鼠标灵敏度(偏移量乘数) float Zoom;//视野角度(FOV),用于透视投影,越小越“放大” //用向量值构造函数 Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH); //用标量值构造函数 Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch); //返回视图矩阵lookAt glm::mat4 GetViewMatrix(); void ProcessKeyboard(Camera_Movement direction, float deltaTime); void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true); void ProcessMouseScroll(float yoffset); private: // 计算摄像机的前向量 void updateCameraVectors(); }; #include "Cone.h" Cone::Cone(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cone::~Cone() { } void Cone::initData(DataParam *param) { dataParam = *param; GLfloat radius = dataParam.radius; GLuint longSegments = dataParam.longSegments; //GLuint latSegments = param->latSegments; GLfloat height = dataParam.height; //float fPhi = glm::pi<float>() / latSegments; //纬度上角度差:Phi float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据 verticesSize = 2 * (longSegments + 2);// *sizeof(TextureColorVertex); vertices = new TextureColorVertex[verticesSize]; verticesSize *= sizeof(TextureColorVertex); int start = 0; //生成侧面数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = height / 2.0f; vertices[start].coordinate.z = 0; vertices[start].texture.s = 0.5; vertices[start].texture.t = 0.5; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i < start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(glm::pi<float>() * 2 - i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(glm::pi<float>() * 2 - i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } start += longSegments + 1; //生成下底顶点数据 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = -height / 2.0f; vertices[start].coordinate.z = 0.0f; vertices[start].texture.s = 0.5f; vertices[start].texture.t = 0.5f; vertices[start].color.r = vertices[start].color.g = vertices[start].color.b = 1.0f; ++start; for (int i = start; i < start + longSegments + 1; i++) { vertices[i].coordinate.x = radius * cos(i * fTheta); vertices[i].coordinate.y = -height / 2.0f; vertices[i].coordinate.z = radius * sin(i * fTheta); vertices[i].texture.s = 0.5f + 0.5f * cos(i * fTheta); vertices[i].texture.t = 0.5f + 0.5f * sin(i * fTheta); vertices[i].color.r = vertices[i].color.g = vertices[i].color.b = 1.0f; } createBuffer(sizeof(TextureColorVertex)); delete[]vertices; revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 0.1f; rotationSpeed = 0.5f; } void Cone::renderObject() { glBindVertexArray(VAO); GLint first = 0; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2); first += dataParam.longSegments + 2; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments + 2); } void Cone::update(float dt) { revolutionAngle += revolutionSpeed; rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 0.0f, 1.0f)); model = glm::translate(model, glm::vec3(0.0f, 4.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); } #pragma once #include "Object.h" class Cone :public Object { public: Cone(std::string vs, std::string fs, std::string texName = ""); ~Cone(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); private: DataParam dataParam; }; #include "Cube18.h" Cube18::Cube18(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cube18::~Cube18() { } void Cube18::initData(DataParam *param) { TextureColorVertex verticesData[] = { // positions // colors // texture coords //top glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 0.0f), //0 glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(1.0f, 1.0f), //1 glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //2 glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), //3 //side glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(4.0f, 0.0f), //7// bottom right glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(4.0f, 1.0f), //6// top right glm::vec3(-0.5f, -0.5f,0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(3.0f, 0.0f), //5// bottom left glm::vec3(-0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(3.0f, 1.0f), //4// top left glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(2.0f, 0.0f), //8 glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(2.0f, 1.0f), //9 glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f,0.0f), //10 glm::vec3(0.5f, 0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(1.0f,1.0f), //11 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f), //12 glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(0.0f, 1.0f), //13 //bottom glm::vec3(0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f), //14 glm::vec3(0.5f, -0.5f, 0.5f), glm::vec3(0.0f, 1.0f, 1.0f), glm::vec2(1.0f, 1.0f), //15 glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 0.0f), //16 glm::vec3(-0.5f, -0.5f, 0.5f), glm::vec3(1.0f, 0.0f, 1.0f), glm::vec2(0.0f, 1.0f) //17 }; vertices = new TextureColorVertex[18]; verticesSize = sizeof(verticesData);//sizeof(TextureColorVertex) * 18; memcpy(vertices, verticesData, verticesSize); createBuffer(sizeof(TextureColorVertex)); revolutionAngle = 0.0f; rotationAngle = 0.0f; revolutionSpeed = 5.0f; rotationSpeed = 0.5f; } void Cube18::renderObject() { glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 4, 10); glDrawArrays(GL_TRIANGLE_STRIP, 14, 4); } void Cube18::update(float dt) { rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(1.0f, 1.0f, 1.0f)); model = glm::scale(model, glm::vec3(3.0f, 3.0f, 3.0f)); }#pragma once #include "Object.h" class Cube18 :public Object { public: Cube18(std::string vs, std::string fs, std::string texName = ""); ~Cube18(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); }; #include "Cylinder.h" Cylinder::Cylinder(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName) { } Cylinder::~Cylinder() { } void Cylinder::initData(DataParam *param) { dataParam = *param; GLfloat radius = dataParam.radius;//圆柱半径(粗细) GLuint longSegments = dataParam.longSegments;//把圆周切成几段(越多样子越圆) GLfloat height = dataParam.height;//高度(多长) float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta int numVertices = 2 * (longSegments + 1) + (longSegments + 2) + (longSegments + 2); // 删除旧数据 if (vertices) { delete[] vertices; } // 分配新内存 vertices = new TextureColorVertex[numVertices]; int index = 0; //生成侧面顶点数据,请补充代码 for (int i = 0; i < (longSegments + 1); i++) { vertices[2 * i].coordinate.x = radius * cosf(i * fTheta); vertices[2 * i].coordinate.y = -(height / 2.0f); vertices[2 * i].coordinate.z = radius * sinf(i * fTheta); vertices[2 * i].texture.s = (longSegments - i) * (1.0f / longSegments);//这里 s 是 (L - i)/L → 随着 i 增大而减小 → 从右往左贴图 vertices[2 * i].texture.t = 0; vertices[2 * i].color.r = vertices[2 * i].color.g = vertices[2 * i].color.b = 1.0f; vertices[2 * i + 1].coordinate.x = radius * cosf(i * fTheta); vertices[2 * i + 1].coordinate.y = (height / 2.0f); vertices[2 * i + 1].coordinate.z = radius * sinf(i * fTheta); vertices[2 * i + 1].texture.s = (longSegments - i) * (1.0f / longSegments); vertices[2 * i + 1].texture.t = 1; vertices[2 * i + 1].color.r = vertices[2 * i + 1].color.g = vertices[2 * i + 1].color.b = 1.0f; } int start = 2 * (longSegments + 1); //生成上底顶点数据,请补充代码 vertices[start].coordinate.x = 0; vertices[start].coordinate.y = height / 2.0f; vertices[start].coordinate.z =0; vertices[start].texture.s =0.5f; vertices[start].texture.t =0.5f; vertices[start].color.r =1.0f; vertices[start].color.g =1.0f; vertices[start].color.b =1.0f; ++start; for (int i = 0; i < longSegments + 1; i++) { vertices[i + start].coordinate.x = radius * cos(glm::pi<float>() * 2 - i * fTheta);//2pi-i*sita是为了让点按逆时针方向排列 vertices[i + start].coordinate.y = height / 2.0f; vertices[i + start].coordinate.z = radius * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i + start].texture.s = 0.5f + 0.5f * cos(glm::pi<float>() * 2 - i * fTheta);// cos(angle) 和 sin(angle) 的值在 [-1, 1] 之间,乘以 0.5 → 变成 [-0.5, 0.5],再加 0.5 → 变成 [0, 1], 所以 (s,t) 落在 [0,1]×[0,1] 内,正好匹配纹理贴图! vertices[i + start].texture.t = 0.5f + 0.5f * sin(glm::pi<float>() * 2 - i * fTheta); vertices[i + start].color.r = 1.0f; vertices[i + start].color.g = 1.0f; vertices[i + start].color.b = 1.0f; } start += longSegments + 1; //生成下底顶点数据,请补充代码 vertices[start].coordinate.x =0; vertices[start].coordinate.y = -height / 2.0f; vertices[start].coordinate.z =0.0f; vertices[start].texture.s = 0.5f; vertices[start].texture.t = 0.5f; vertices[start].color.r = 1.0f; vertices[start].color.g = 1.0f; vertices[start].color.b = 1.0f; ++start; for (int i = 0; i < longSegments + 1; i++) { vertices[i + start].coordinate.x = radius * cosf(i * fTheta); vertices[i + start].coordinate.y = -height / 2.0f; vertices[i + start].coordinate.z = radius * sinf(i * fTheta); vertices[i + start].texture.s = 0.5f + 0.5f * cosf(i * fTheta); vertices[i + start].texture.t = 0.5f + 0.5f * sinf(i * fTheta); vertices[i + start].color.r = 1.0f; vertices[i + start].color.g = 1.0f; vertices[i + start].color.b = 1.0f; } //createBuffer(sizeof(TextureColorVertex), true); verticesSize = numVertices * sizeof(TextureColorVertex); GLsizei stride = sizeof(TextureColorVertex); createBuffer(stride, false); // 不需要 EBO delete[]vertices; revolutionAngle = 0.0f; //公转角度(绕X轴,在YZ平面环绕) rotationAngle = 0.0f; //自转角度 revolutionSpeed = 5.0f; //公转角速度 rotationSpeed = 1.0f; //自转角速度 } void Cylinder::renderObject() { glBindVertexArray(VAO); GLint first = 0; glDrawArrays(GL_TRIANGLE_STRIP, first, (dataParam.longSegments + 1) * 2); first += (dataParam.longSegments + 1) * 2; glDrawArrays(GL_TRIANGLE_FAN, first, dataParam.longSegments +2); first += dataParam.longSegments + 2; glDrawArrays(GL_TRIANGLE_FAN,first, dataParam.longSegments + 2); } void Cylinder::update(float dt) { revolutionAngle += revolutionSpeed * dt; rotationAngle += rotationSpeed * dt * 3; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::translate(model, glm::vec3(0.0f, 0.0f,3.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 0.0f,1.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); }#pragma once #include "Object.h" class Cylinder :public Object { public: Cylinder(std::string vs, std::string fs, std::string texName = ""); ~Cylinder(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); private: DataParam dataParam; }; #include "Demo.h" Demo::Demo() { cullMode = GL_BACK; frontFace = GL_CCW; enableCullFace = false; } Demo::~Demo() { } void Demo::setRenderParameter(bool enableCullFace, GLenum cullMode, GLenum frontFace) { this->enableCullFace = enableCullFace; this->cullMode = cullMode; this->frontFace = frontFace; } void Demo::beginRender() { if (enableCullFace) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } glCullFace(cullMode); glFrontFace(frontFace); }#ifndef DEMO_H_ #define DEMO_H_ #include <glad/glad.h> class Demo { public: Demo(); ~Demo(); private: bool enableCullFace; GLenum cullMode; GLenum frontFace; protected: const char* vertexShaderSource; const char* fragmentShaderSource; public: virtual void setRenderParameter(bool enableCullFace = false, GLenum cullMode = GL_FRONT, GLenum frontFace = GL_CCW); virtual void beginRender(); virtual void render() = 0; virtual void update(float deltaTime) = 0; }; #endif #include "Demo08.h" #include "TexturePool.h" #include "camera.h" extern Camera camera; Demo08::Demo08(int scr_width, int scr_height) { screen_height = scr_height; screen_width = scr_width; } Demo08::~Demo08() { cleanUp(); } void Demo08::init() { TexturePool* textPool = TexturePool::getInstance(); TexturePool::getInstance()->addTexture("sun", "./texture/sun.jpg"); TexturePool::getInstance()->addTexture("earth", "./texture/earth.jpg"); TexturePool::getInstance()->addTexture("cube", "./texture/container.jpg"); TexturePool::getInstance()->addTexture("saturn", "./texture/saturn.jpg"); objects[0] = new Cube18("star.vs", "star.fs", "cube"); //定义立方体对象 objects[1] = new Sphere("star.vs", "star.fs", "earth"); //定义球对象 objects[2] = new Cylinder("star.vs", "star.fs", "sun"); //定义圆柱对象 objects[3] = new Cone("star.vs", "star.fs", "saturn"); //定义圆锥对象 objects[0]->initData(); DataParam earthParam = { 20,20,1.0f }; objects[1]->initData(&earthParam); DataParam cylinderParam = { 20,20,1.0f,4.0f }; objects[2]->initData(&cylinderParam); DataParam coneParam = { 10,10,1.0f,2.0f }; objects[3]->initData(&coneParam); } void Demo08::cleanUp() { if (earth) { delete earth; } if (cube) { delete cube; } if (cylinder) { delete cylinder; } if (cone) { delete cone; } for (int i = 0; i < 4; ++i) { if (objects[i]) { delete objects[i]; } } } void Demo08::update(float dt) //遍历所有场景中的物体,调用它们各自的 update 方法,用于更新物体的旋转角度、公转角度、位置动画等随时间变化的状态,dt: deltaTime,表示上一帧到当前帧的时间间隔(秒),用于实现帧率无关的平滑动画 { for (int i = 0; i < 4; ++i) { objects[i]->update(dt); //调用每个物体的 update 函数,处理自身动画逻辑(如自转、公转) } } void Demo08::render() { glClearColor(0.2f, 0.3f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); beginRender(); glEnable(GL_DEPTH_TEST); if (screen_height <= 0 || screen_width <= 0) return; glm::mat4 view = camera.GetViewMatrix(); float aspect = static_cast<float>(screen_width) / static_cast<float>(screen_height); float fovRad = glm::radians(camera.Zoom); glm::mat4 projection = glm::perspective( fovRad, // 第一个参数:fov in radians aspect, // 第二个:aspect ratio 0.1f, // 第三个:near 100.0f // 第四个:far ); for (int i = 0; i < 4; ++i) { objects[i]->render(view, projection); } } void Demo08::setViewport(int width, int height) { screen_width = width; screen_height = height; } #pragma once #include "Demo.h" #include "Cube18.h" #include "Sphere.h" #include "Cylinder.h" #include "Cone.h" class Demo08 : public Demo { public: Demo08(int scr_width,int scr_height); ~Demo08(); private: Cube18* cube; Sphere* earth; Cylinder* cylinder; Cone* cone; Object* objects[4]; int screen_width; int screen_height; public: void render(); void update(float deltaTime); void init(); void cleanUp(); void setViewport(int width, int height); }; #version 460 core in vec2 TexCoord; in vec3 FragPos; in vec3 Normal; out vec4 FragColor; // 材质 struct Material { sampler2D diffuse; vec3 specular; float shininess; }; // 点光源 struct PointLight { vec3 position; vec3 ambient; vec3 diffuse; vec3 specular; float constant; float linear; float quadratic; }; uniform Material material; uniform PointLight light; uniform vec3 viewPos; void main() { // 环境光 vec3 ambient = light.ambient * texture(material.diffuse, TexCoord).rgb; // 漫反射 vec3 norm = normalize(Normal); vec3 lightDir = normalize(light.position - FragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoord).rgb; // 镜面反射 vec3 viewDir = normalize(viewPos - FragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); vec3 specular = light.specular * spec * material.specular; // 衰减 float distance = length(light.position - FragPos); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * distance * distance); vec3 result = (ambient + diffuse + specular) * attenuation; FragColor = vec4(result, 1.0); } #version 460 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor; layout(location = 2) in vec2 aTexCoord; layout(location = 3) in vec3 aNormal; // 新增法线输入 out vec2 TexCoord; out vec3 FragPos; out vec3 Normal; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { FragPos = vec3(model * vec4(aPos, 1.0)); Normal = mat3(transpose(inverse(model))) * aNormal; TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); gl_Position = projection * view * vec4(FragPos, 1.0); } #include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> #include "Demo08.h" #include "camera.h" unsigned int scr_width = 1200; unsigned int scr_height = 800; GLFWwindow* window; void framebuffer_size_callback(GLFWwindow* window, int width, int height); void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); void processInput(GLFWwindow* window); void update(float dt); void render(); void init(); void cleanup(); bool enableCullFace = true; GLenum cullMode = GL_BACK; GLenum frontFace = GL_CCW; Demo08* demo08 = nullptr; Camera camera(glm::vec3(0.0f, 1.0f, 12.0f)); // 初始位置 (x=0, y=1, z=12) float lastX = 600.0f; float lastY = 400.0f; bool firstMouse = true; void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = static_cast<float>(xpos); lastY = static_cast<float>(ypos); firstMouse = false; } float xoffset = static_cast<float>(xpos - lastX); float yoffset = static_cast<float>(lastY - ypos); // 反转 Y 轴方向更自然 lastX = static_cast<float>(xpos); lastY = static_cast<float>(ypos); camera.ProcessMouseMovement(xoffset, yoffset); } void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { camera.ProcessMouseScroll(static_cast<float>(yoffset)); } int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif window = glfwCreateWindow(scr_width, scr_height, "Lab3-3", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetKeyCallback(window, key_callback); glfwSetCursorPosCallback(window, mouse_callback); // 鼠标移动 glfwSetScrollCallback(window, scroll_callback); // 滚轮 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } int nrAttributes; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes); std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl; init(); double t = 0.5; while (!glfwWindowShouldClose(window)) { processInput(window); double dt = glfwGetTime() - t; t = glfwGetTime(); update(static_cast<float>(dt)); render(); glfwSwapBuffers(window); glfwPollEvents(); } cleanup(); glfwTerminate(); return 0; } void cleanup() { if (demo08) { delete demo08; } } void init() { demo08 = new Demo08(scr_width, scr_height); demo08->setRenderParameter(enableCullFace, cullMode, frontFace); demo08->init(); } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); // 摄像机移动控制 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, 0.016f); // 近似帧时间 if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, 0.016f); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, 0.016f); if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, 0.016f); } void update(float dt) { if (demo08) { demo08->update(dt); } } void render() { if (demo08) { demo08->render(); } } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { scr_width = width; scr_height = height; glViewport(0, 0, width, height); } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (action == GLFW_RELEASE) { // 可用于切换模式等(例如空格键切换剔除) switch (key) { case GLFW_KEY_SPACE: enableCullFace = !enableCullFace; if (demo08) demo08->setRenderParameter(enableCullFace, cullMode, frontFace); break; } } } //#include <glad/glad.h> //#include "TexturePool.h" //#include "Object.h" //Object::Object(std::string vs, std::string fs, std::string texName) //{ // createShader(vs.c_str(), fs.c_str()); // if (texName != "") // { // texture = TexturePool::getInstance()->getTexture(texName); // // activate shader // shader->use(); // // shader->setInt("tex", 0); // shader->setVec4("testColor", glm::vec4(255, 0, 0, 255)); // // } // vertices = nullptr; // indices = nullptr; // stride = 0; // //} // // //Object::~Object() //{ // // glDeleteVertexArrays(1, &VAO); // glDeleteBuffers(1, &VBO); // glDeleteBuffers(1, &EBO); // if (shader) // { // delete shader; // } // /*if (vertices) // { // delete[]vertices; // }*/ //} // //void Object::createShader(const char* vs, const char* fs) //{ // if (shader) // { // delete shader; // } // shader = new Shader(vs, fs); //} //void Object::setTexture(std::string texName) //{ // texture = TexturePool::getInstance()->getTexture(texName); //} // //void Object::createBuffer(GLsizei stride, bool createEBO , GLenum ussage) //{ // glGenVertexArrays(1, &VAO); // glGenBuffers(1, &VBO); // if (createEBO) // { // glGenBuffers(1, &EBO); // } // glBindVertexArray(VAO); // // glBindBuffer(GL_ARRAY_BUFFER, VBO); // glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, ussage); // // if (createEBO) // { // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, ussage); // } // // // this -> stride = stride; // updateDataBuffer(); //} // // //void Object::render(glm::mat4& view, glm::mat4& projection) //{ // // // glActiveTexture(GL_TEXTURE0); // glBindTexture(GL_TEXTURE_2D, texture); // // // glBindVertexArray(VAO); // shader->use(); // shader->setMat4("model", model); // shader->setMat4("view", view); // shader->setMat4("projection", projection); // // renderObject(); // //} // // //void Object::updateDataBuffer() //{ // //position attribute // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); // glEnableVertexAttribArray(0); // // glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(1 * sizeof(glm::vec3))); // glEnableVertexAttribArray(1); // // // texture coord attribute // glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3))); // glEnableVertexAttribArray(2); //} #include <glad/glad.h> #include "TexturePool.h" #include "Object.h" Object::Object(std::string vs, std::string fs, std::string texName) : shader(nullptr), vertices(nullptr), indices(nullptr), texture(0), VAO(0), VBO(0), EBO(0) { createShader(vs.c_str(), fs.c_str()); if (!texName.empty()) { texture = TexturePool::getInstance()->getTexture(texName); shader->use(); shader->setInt("material.diffuse", 0); } } Object::~Object() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); delete shader; delete[] vertices; delete[] indices; } void Object::createShader(const char* vs, const char* fs) { if (shader) delete shader; shader = new Shader(vs, fs); } void Object::setTexture(std::string texName) { texture = TexturePool::getInstance()->getTexture(texName); } void Object::createBuffer(GLsizei s, bool createEBO, GLenum usage) { stride = s; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, usage); if (createEBO && indices) { glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, usage); } updateDataBuffer(); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } void Object::updateDataBuffer() { glBindVertexArray(VAO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(glm::vec3))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3))); glEnableVertexAttribArray(2); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, stride, (void*)(2 * sizeof(glm::vec3) + sizeof(glm::vec2))); glEnableVertexAttribArray(3); glBindVertexArray(0); } void Object::render(glm::mat4& view, glm::mat4& projection) { shader->use(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); shader->setMat4("model", model); shader->setMat4("view", view); shader->setMat4("projection", projection); renderObject(); } #pragma once #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <string> #include "Shader.h" #include <glad/glad.h> // 添加这一行!关键! typedef struct { glm::vec3 coordinate; glm::vec3 color; glm::vec2 texture; } TextureColorVertex; typedef struct { GLuint latSegments; GLuint longSegments; GLfloat radius; GLfloat height; }DataParam; class Object { public: Object(std::string vs, std::string fs, std::string texName = ""); virtual ~Object(); protected: Shader* shader; TextureColorVertex* vertices; GLushort * indices; GLuint indexCount; GLint verticesSize; GLuint indexSize; GLuint texture; GLuint VBO, VAO, EBO; protected: glm::mat4 model; float rotationSpeed; float revolutionSpeed; float rotationAngle; float revolutionAngle; glm::vec3 translation; GLsizei stride; void createBuffer(GLsizei stride,bool createEBO = false, GLenum ussage = GL_STATIC_DRAW); public: void createShader(const char* vs, const char* fs); virtual void initData(DataParam *param = nullptr) = 0; void setTexture(std::string texName); void render(glm::mat4& view, glm::mat4& projection); virtual void update(float dt) {} virtual void renderObject() = 0; virtual void updateDataBuffer(); }; #version 460 core out vec4 FragColor; void main() { FragColor = vec4(1.0, 1.0, 1.0, 1.0); // 白色光源 } #version 460 core layout(location = 0) in vec3 aPos; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); } #include "Sphere.h" Sphere::Sphere(std::string vs, std::string fs, std::string texName) :Object(vs,fs,texName ) { } Sphere::~Sphere() { } void Sphere::initData(DataParam *param) { GLfloat radius = param->radius; GLuint longSegments = param->longSegments; GLuint latSegments = param->latSegments; float fPhi = glm::pi<float>() / latSegments; //纬度上角度差:Phi float fTheta = (glm::pi<float>() * 2.0f) / longSegments; //经度上角度差:Theta //生成顶点数据,请补充代码 verticesSize = ((longSegments + 1) * (latSegments + 1)) * sizeof(TextureColorVertex); vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)]; //创建顶点数组 TextureColorVertex * p = vertices; for (GLuint i = 0; i < latSegments + 1; i++) { float latitude = i * fPhi - glm::pi<float>() / 2.0f;; //fPhi = π / latSegments → 每一“段”的纬度跨度。i * fPhi:当前在总半圆中的位置(从 0 到 π)。减去 π/2 是为了让角度中心对齐赤道!所以最终 latitude ∈ [-π/2, +π/2] for (GLuint j = 0; j < longSegments + 1; j++) { float longitude = j * fTheta; //经度longitude ∈ [0, 2π) p->coordinate.x = radius * cosf(latitude) * cosf(longitude); p->coordinate.y = radius * sinf(latitude); p->coordinate.z = radius * cosf(latitude) * sinf(longitude); p->color.r =1.0f; p->color.g =1.0f; p->color.b =1.0f; p->texture.s = longitude / (glm::pi<float>() * 2.0f); p->texture.t = (latitude + glm::pi<float>() / 2.0f) / glm::pi<float>();//(s,t) ∈ [0,1]×[0,1] p++; } } //生成索引数据 indexCount = (1 + longSegments) * 2 * (1 + latSegments); //计算索引数量 indices = new GLushort[indexCount]; indexSize = indexCount * sizeof(GLushort); GLushort * pIdx = indices; for (GLuint i = 0; i < latSegments + 1; i++) { for (GLuint j = 0; j < longSegments + 1; j++) { *pIdx = i * (longSegments + 1) + j; pIdx++; *pIdx = (i + 1) * (longSegments + 1) + j; pIdx++; } } createBuffer(sizeof(TextureColorVertex),true); delete[]vertices; delete[]indices; revolutionAngle = 0.0f; //公转角度 rotationAngle = 0.0f; //自转角度 revolutionSpeed = 0.01f; //公转速度 rotationSpeed = 0.5f; //自转速度 } void Sphere::renderObject() { glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0); } void Sphere::update(float dt) { revolutionAngle += revolutionSpeed; rotationAngle += rotationSpeed; model = glm::mat4(1.0f); model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::translate(model, glm::vec3(5.0f,0.0f,0.0f)); model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f)); } #pragma once #include "Object.h" class Sphere : public Object { public: Sphere(std::string vs, std::string fs, std::string texName = ""); ~Sphere(); void initData(DataParam *param = nullptr); void renderObject(); void update(float dt); }; #version 460 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D tex; void main() { FragColor = texture(tex, TexCoord); }#version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor; layout(location = 2) in vec2 aTextCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; uniform vec4 testColor; out vec4 color; void main() { gl_Position = projection * view * model * vec4(aPos,1.0f); TexCoord = vec2(aTextCoord.x,1-aTextCoord.y); color = testColor; }#include "TexturePool.h" #include <SOIL2/SOIL2.h> #include <iostream> TexturePool::TexturePool() { } TexturePool::~TexturePool() { for (Textures::iterator ite = textures.begin(); ite != textures.end(); ++ite) { glDeleteTextures(1, &ite->second); } } void TexturePool::addTexture(string name, string path) { GLuint texID; if (name.empty()) { return; } texID = SOIL_load_OGL_texture(path.c_str(), 0, 0, SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y); if (texID != 0) { textures[name] = texID; } else { std::cout << "Failed to load texture" << path <<" " <<std::endl; } glBindTexture(GL_TEXTURE_2D, texID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } TexturePool* TexturePool::getInstance() { static TexturePool instance; return &instance; } GLuint TexturePool::getTexture(string name) { if (textures.find(name) != textures.end()) { return textures[name]; } return 0; }#pragma once #include <glad/glad.h> #include <GLFW/glfw3.h> #include <map> #include <string> using namespace std; typedef map<string, GLuint> Textures; class TexturePool { public: virtual ~TexturePool(); private: TexturePool(); Textures textures; public: void addTexture(string name, string path); static TexturePool *getInstance(); GLuint getTexture(string name); }; 用冯氏光照模型生成光照场景,在框架Demo08的基础上,添加必要的代码(着色器代码、c++代码),实现光照场景,如下(其中白色的小球表示光源位置):不要乱改
最新发布
11-15
评论 17
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值