自学内容网 自学内容网

OpenGL笔记二十一之几何类设计

OpenGL笔记二十一之几何类设计

—— 2024-09-16 下午


bilibili赵新政老师的教程看后笔记

code review!

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 face
halfSize, -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 face
4, 5, 6, 6, 7, 4,   // Back face
8, 9, 10, 10, 11, 8,  // Top face
12, 13, 14, 14, 15, 12, // Bottom face
16, 17, 18, 18, 19, 16, // Right face
20, 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到当前的vao
glBindBuffer(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 通过两层循环(纬线在外,经线在内)->位置、uv
for (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与vao
GLuint& 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));

//绑定当前的program
shader->begin();
shader->setInt("sampler", 0);
shader->setMatrix4x4("transform", transform);
shader->setMatrix4x4("viewMatrix", camera->getViewMatrix());
shader->setMatrix4x4("projectionMatrix", camera->getProjectionMatrix());
 
//绑定当前的vao
GL_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;
}

原文地址:https://blog.csdn.net/weixin_43297891/article/details/142304586

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!