OpenGL笔记二十一之几何类设计
OpenGL笔记二十一之几何类设计
—— 2024-09-16 下午
bilibili赵新政老师的教程看后笔记
code review!
文章目录
- OpenGL笔记二十一之几何类设计
- 1.运行
- 1.1.立方体运行
- 1.2.球体运行
- 2.几何类搭建
- 1.立方体分析
- 2.球体分析
- 3.图片资源文件
- 4.关键实现
- 4.1.geometry.h
- 4.2.geometry.cpp
- 4.3.vertex.glsl
- 4.4.fragment.glsl
- 4.5.main.cpp
1.运行
1.1.立方体运行
1.2.球体运行
2.几何类搭建
1.立方体分析
将0.5替换成halfSize就可以了。
2.球体分析
3.图片资源文件
goku.jpg
earth.png
4.关键实现
4.1.geometry.h
代码
#pragma once#include "core.h"class Geometry {
public:Geometry();~Geometry();static Geometry* createBox(float size);static Geometry* createSphere(float radius);GLuint getVao()const { return mVao; }uint32_t getIndicesCount()const { return mIndicesCount; }private:GLuint mVao{ 0 };GLuint mPosVbo{ 0 };GLuint mUvVbo{ 0 };GLuint mEbo{ 0 };uint32_t mIndicesCount{ 0 };
};
4.2.geometry.cpp
代码
#include "geometry.h"
#include <vector>Geometry::Geometry() {}Geometry::~Geometry() {if (mVao != 0) {glDeleteVertexArrays(1, &mVao);}if (mPosVbo != 0) {glDeleteBuffers(1, &mPosVbo);}if (mUvVbo != 0) {glDeleteBuffers(1, &mUvVbo);}if (mEbo != 0) {glDeleteBuffers(1, &mEbo);}
}Geometry* Geometry::createBox(float size) {Geometry* geometry = new Geometry();geometry->mIndicesCount = 36;float halfSize = size / 2.0f;float positions[] = {// Front face-halfSize, -halfSize, halfSize, halfSize, -halfSize, halfSize, halfSize, halfSize, halfSize, -halfSize, halfSize, halfSize,// Back face-halfSize, -halfSize, -halfSize, -halfSize, halfSize, -halfSize, halfSize, halfSize, -halfSize, halfSize, -halfSize, -halfSize,// Top face-halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, -halfSize, -halfSize, halfSize, -halfSize,// Bottom face-halfSize, -halfSize, -halfSize, halfSize, -halfSize, -halfSize, halfSize, -halfSize, halfSize, -halfSize, -halfSize, halfSize,// Right facehalfSize, -halfSize, halfSize, halfSize, -halfSize, -halfSize, halfSize, halfSize, -halfSize, halfSize, halfSize, halfSize,// Left face-halfSize, -halfSize, -halfSize, -halfSize, -halfSize, halfSize, -halfSize, halfSize, halfSize, -halfSize, halfSize, -halfSize};float uvs[] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,};unsigned int indices[] = {0, 1, 2, 2, 3, 0, // Front face4, 5, 6, 6, 7, 4, // Back face8, 9, 10, 10, 11, 8, // Top face12, 13, 14, 14, 15, 12, // Bottom face16, 17, 18, 18, 19, 16, // Right face20, 21, 22, 22, 23, 20 // Left face};//2 VBO创建GLuint& posVbo = geometry->mPosVbo, uvVbo = geometry->mUvVbo;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO创建glGenBuffers(1, &geometry->mEbo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->mEbo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO创建glGenVertexArrays(1, &geometry->mVao);glBindVertexArray(geometry->mVao);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0);//5.4 加入ebo到当前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->mEbo);glBindVertexArray(0);return geometry;
}Geometry* Geometry::createSphere(float radius) {Geometry* geometry = new Geometry();//目标:1 位置 2 uv 3 索引//1 主要变量声明std::vector<GLfloat> positions{};std::vector<GLfloat> uvs{};std::vector<GLuint> indices{};//声明纬线与经线的数量int numLatLines = 60;//纬线int numLongLines = 60;//经线//2 通过两层循环(纬线在外,经线在内)->位置、uvfor (int i = 0; i <= numLatLines; i++) {for (int j = 0; j <= numLongLines; j++) {float phi = i * glm::pi<float>() / numLatLines;float theta = j * 2 * glm::pi<float>() / numLongLines;float y = radius * cos(phi);float x = radius * sin(phi) * cos(theta);float z = radius * sin(phi) * sin(theta);positions.push_back(x);positions.push_back(y);positions.push_back(z);float u = 1.0 - (float)j / (float)numLongLines;float v = 1.0 - (float)i / (float)numLatLines;uvs.push_back(u);uvs.push_back(v);}}//3 通过两层循环(这里没有=号)->顶点索引for (int i = 0; i < numLatLines; i++) {for (int j = 0; j < numLongLines; j++) {int p1 = i * (numLongLines + 1) + j;int p2 = p1 + numLongLines + 1;int p3 = p1 + 1;int p4 = p2 + 1;indices.push_back(p1);indices.push_back(p2);indices.push_back(p3);indices.push_back(p3);indices.push_back(p2);indices.push_back(p4);}}//4 生成vbo与vaoGLuint& posVbo = geometry->mPosVbo, uvVbo = geometry->mUvVbo;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(float), positions.data(), GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(float), uvs.data(), GL_STATIC_DRAW);glGenBuffers(1, &geometry->mEbo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->mEbo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);glGenVertexArrays(1, &geometry->mVao);glBindVertexArray(geometry->mVao);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->mEbo);glBindVertexArray(0);geometry->mIndicesCount = indices.size();return geometry;
}
4.3.vertex.glsl
代码
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aUV;out vec2 uv;uniform mat4 transform;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;//aPos作为attribute(属性)传入shader
//不允许更改的
void main()
{vec4 position = vec4(aPos, 1.0);position = projectionMatrix * viewMatrix * transform * position;gl_Position = position;uv = aUV;
}
4.4.fragment.glsl
代码
#version 460 core
out vec4 FragColor;in vec2 uv;uniform sampler2D sampler;void main()
{FragColor = texture(sampler, uv);
}
4.5.main.cpp
代码
#include <iostream>#include "glframework/core.h"
#include "glframework/shader.h"
#include <string>
#include <assert.h>//断言
#include "wrapper/checkError.h"
#include "application/Application.h"
#include "glframework/texture.h"//引入相机+控制器
#include "application/camera/perspectiveCamera.h"
#include "application/camera/orthographicCamera.h"
#include "application/camera/trackBallCameraControl.h"
#include "application/camera/gameCameraControl.h"#include "glframework/geometry.h"/*
*┌────────────────────────────────────────────────┐
*│ 目 标: 设计并实现Geometry系统,用于学习方便
*│ 讲 师: 赵新政(Carma Zhao)
*│ 拆分目标:
* 搭建Geometry类框架
*└────────────────────────────────────────────────┘
*/Geometry* geometry = nullptr;
Shader* shader = nullptr;
Texture* texture = nullptr;
glm::mat4 transform(1.0f);PerspectiveCamera* camera = nullptr;
TrackBallCameraControl* cameraControl = nullptr;void OnResize(int width, int height) {GL_CALL(glViewport(0, 0, width, height));std::cout << "OnResize" << std::endl;
}void OnKey(int key, int action, int mods) {cameraControl->onKey(key, action, mods);
}//鼠标按下/抬起
void OnMouse(int button, int action, int mods) {double x, y;app->getCursorPosition(&x, &y);cameraControl->onMouse(button, action, x, y);
}//鼠标移动
void OnCursor(double xpos, double ypos) {cameraControl->onCursor(xpos, ypos);
}//鼠标滚轮
void OnScroll(double offset) {cameraControl->onScroll(offset);
}void prepareVAO() {geometry = Geometry::createBox(3.0f);// geometry = Geometry::createSphere(3.0f);
}void prepareShader() {shader = new Shader("assets/shaders/vertex.glsl","assets/shaders/fragment.glsl");
}void prepareTexture() {texture = new Texture("assets/textures/goku.jpg", 0);// texture = new Texture("assets/textures/earth.png", 0);
}void prepareCamera() {float size = 6.0f;//camera = new OrthographicCamera(-size, size, size, -size, size, -size);camera = new PerspectiveCamera(60.0f, (float)app->getWidth() / (float)app->getHeight(),0.1f,1000.0f);cameraControl = new TrackBallCameraControl();cameraControl->setCamera(camera);cameraControl->setSensitivity(0.4f);
}void prepareState() {glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);
}void render() {//执行opengl画布清理操作GL_CALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));//绑定当前的programshader->begin();shader->setInt("sampler", 0);shader->setMatrix4x4("transform", transform);shader->setMatrix4x4("viewMatrix", camera->getViewMatrix());shader->setMatrix4x4("projectionMatrix", camera->getProjectionMatrix());//绑定当前的vaoGL_CALL(glBindVertexArray(geometry->getVao()));//发出绘制指令GL_CALL(glDrawElements(GL_TRIANGLES, geometry->getIndicesCount(), GL_UNSIGNED_INT, 0));GL_CALL(glBindVertexArray(0));shader->end();
}int main() {if (!app->init(800, 600)) {return -1;}app->setResizeCallback(OnResize);app->setKeyBoardCallback(OnKey);app->setMouseCallback(OnMouse);app->setCursorCallback(OnCursor);app->setScrollCallback(OnScroll);//设置opengl视口以及清理颜色GL_CALL(glViewport(0, 0, 800, 600));GL_CALL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));prepareShader();prepareVAO();prepareTexture();prepareCamera();prepareState();while (app->update()) {cameraControl->update();render();}app->destroy();return 0;
}