OpenGL太阳系行星系统简单实现

这篇具有很好参考价值的文章主要介绍了OpenGL太阳系行星系统简单实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、项目简介

使用OpenGL(glfw, glad)模拟太阳系(地球、月球、太阳)系统,涉及三维图形变换、坐标系统,光照模型(待添加)、键盘鼠标事件处理等内容,在main函数中封装了绝大部分的OpenGL接口,极大的减少了代码量,操作简便。

二、代码特点

Shader.h Camera.h与Texture.h封装着色器、摄像机与纹理类,其中纹理类实例化即完成生成纹理与绑定、设置纹理环绕方式与过滤等工作,减少大量代码量。

VertexArray,VertexBuffer与IndexBuffer封装VAO, VBO, EBO,类实例化时即自动生成顶点数组对象、顶点缓冲对象、元素缓冲对象,并提供绑定与解绑等接口。VertexBufferLayout类可自由设置顶点属性。

Sphere类获得绘制球体所需的所有顶点坐标以及索引缓冲数组,用于实例化VBO和EBO对象,可手动调节设置球体绘制的精细程度。

通过Renderer类的Draw方法实现球体绘制。

三、源码实现及详细说明

GitHub源码地址:wonderful2643/SolarSystem (github.com)

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

#include "Shader.h"
#include "Sphere.h"
#include "Config.h"
#include "Camera.h"
#include "Renderer.h"
#include "Texture.h"

#include "VertexArray.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "VertexBufferLayout.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);

// camera
Camera camera(glm::vec3(0.0f, 5.0f, 35.0f));
float lastX = WindowWidth / 2.0f;
float lastY = WindowHeight / 2.0f;
bool firstMouse = true;

// timing
float deltaTime = 0.0f;    // time between current frame and last frame
float lastFrame = 0.0f;

int main()
{
  glfwInit();
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  GLFWwindow* window = glfwCreateWindow(WindowWidth, WindowHeight, "Solar System", nullptr, nullptr);

  if (!window)
  {
    std::cout << "Failed to create GLFW window" << std::endl;
    glfwTerminate();
    return -1;
  }

  glfwMakeContextCurrent(window);
  glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
  glfwSetCursorPosCallback(window, mouse_callback);
  glfwSetScrollCallback(window, scroll_callback);

  //注释该行,调试出bug键盘鼠标不会卡死
  //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  glfwSwapInterval(1);

  if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  {
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
  }

  std::cout << glGetString(GL_VERSION) << std::endl;
  
  //获得球体所有顶点坐标以及EBO数组
  Sphere mySphere(40);
  std::vector<float> sphereVertices = mySphere.getVertices();
  std::vector<unsigned int> sphereIndices = mySphere.getIndices();

  {
    //VAO
    VertexArray va;
    //VBO
    VertexBuffer vb(&sphereVertices[0], sphereVertices.size() * sizeof(float));

    VertexBufferLayout layout;
    //顶点属性布局:前三位为球体上点的x, y, z坐标,后两位为2D纹理坐标
    layout.Push<float>(3);
    layout.Push<float>(2);
    va.AddBuffer(layout);

    IndexBuffer ib(&sphereIndices[0], sphereIndices.size());//放在最后

    glEnable(GL_DEPTH_TEST);

    Shader shader("res/shader/task3.vs", "res/shader/task3.fs");
    shader.Bind();
    shader.setInt("u_Texture", 0);

    Texture textureSun("res/textures/sun.jpg");
    Texture textureEarth("res/textures/earth.jpg");
    Texture textureMoon("res/textures/moon.jpg");

    vb.Unbind();
    va.Unbind();
    ib.Unbind();
    shader.Unbind();

    Renderer render;

    glm::mat4 view = camera.GetViewMatrix();
    glm::mat4 proj = glm::perspective(glm::radians(camera.Zoom), (float)WindowWidth / (float)WindowHeight, 0.1f, 100.0f);

    // 渲染循环
    while (!glfwWindowShouldClose(window))
    {
      float currentFrame = static_cast<float>(glfwGetTime());
      deltaTime = currentFrame - lastFrame;
      lastFrame = currentFrame;

      processInput(window);

      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      va.Bind();
      {
        // Sun
        glm::mat4 model = glm::mat4(1.0f);
        model = glm::translate(model, glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::rotate(glm::mat4(1.0f), -(float)glfwGetTime() / 5, glm::vec3(0.0f, 1.0f, 0.0f));
        model = scale(model, glm::vec3(sunScale, sunScale, sunScale));
        glm::mat4 mvp = proj * view * model;

        textureSun.Bind();
        shader.Bind();
        shader.setMat4("u_MVP", mvp);

        render.Draw(mySphere.getNumIndices());
      }
      
      {
        // Earth
        glm::mat4 model = glm::mat4(1.0f);
        // 公转
        model = glm::rotate(model, (float)glfwGetTime() / 1.5f, glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::translate(model, glm::vec3(SunEarthDistance, .0f, .0f));
        // 抵消公转对自身倾斜方向的影响,保证公转后 仍然向右倾斜
        model = glm::rotate(model, -(float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::rotate(model, -glm::radians(ErothAxialAngle), glm::vec3(0.0, 0.0, 1.0));
        // 自转
        model = glm::rotate(model, -(float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
        glm::mat4 mvp = proj * view * model;

        textureEarth.Bind();
        shader.Bind();
        shader.setMat4("u_MVP", mvp);

        render.Draw(mySphere.getNumIndices());
      }

      {
        // Moon
        glm::mat4 model = glm::mat4(1.0f);
        // 地日公转
        model = glm::rotate(model, (float)glfwGetTime() / 1.5f, glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::translate(model, glm::vec3(SunEarthDistance, .0f, .0f));
        // 月球公转
        model = glm::rotate(model, (float)glfwGetTime() * 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
        model = glm::translate(model, glm::vec3(MoonEarthDistance, 0.0, 0.0));
        // 月球自转
        model = glm::rotate(model, -(float)glfwGetTime(), glm::vec3(0.0f, 1.0f, 0.0f));
        model = scale(model, glm::vec3(moonScale, moonScale, moonScale));
        glm::mat4 mvp = proj * view * model;

        textureMoon.Bind();
        shader.Bind();
        shader.setMat4("u_MVP", mvp);

        render.Draw(mySphere.getNumIndices());
      }

      glfwSwapBuffers(window);
      glfwPollEvents();
    }
  }

  glfwTerminate();
  return 0;
}

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, deltaTime);
  if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
    camera.ProcessKeyboard(BACKWARD, deltaTime);
  if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
    camera.ProcessKeyboard(LEFT, deltaTime);
  if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
    camera.ProcessKeyboard(RIGHT, deltaTime);
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
  glViewport(0, 0, width, height);
}

void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
  float xpos = static_cast<float>(xposIn);
  float ypos = static_cast<float>(yposIn);

  if (firstMouse)
  {
    lastX = xpos;
    lastY = ypos;
    firstMouse = false;
  }

  float xoffset = xpos - lastX;
  float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

  lastX = xpos;
  lastY = ypos;

  camera.ProcessMouseMovement(xoffset, yoffset);
}

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

四、效果展示及项目框架

glfw绘制地球,c++,opencv,Powered by 金山文档

参考链接

C++ 实现太阳系行星系统(OpenGL)

OpenGL画球面(6) - 邗影 - 博客园 (cnblogs.com)

openGL编程学习(3):太阳、地球、月亮(含自转和公转)和航天飞机_LynnJute的博客-CSDN博客_glfw实现日地月

OpenGL入门三——变换进阶

LearnOpenGL CN

【【译】TheCherno-OpenGL系列教程】文章来源地址https://www.toymoban.com/news/detail-763990.html

到了这里,关于OpenGL太阳系行星系统简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 H5 与 WebGL 的3D太阳系立体展示

    前言 近年来随着引力波的发现、黑洞照片的拍摄、火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如《三体》、《流浪地球》、《星际穿越》等的传播普及,宇宙空间中那些原本遥不可及的事物离我们越来越近,人们对未知文明的关注和对宇宙空间的好奇达

    2024年02月20日
    浏览(44)
  • WxGL应用实例:绘制高精度的3D太阳系模型

    天何所沓?十二焉分?日月安属?列星安陈?—— 屈原 远古时期的人类就对神秘幽邃的星空充满了好奇与敬畏。仰望星空,宇宙浩瀚。比宇宙更壮阔的,是人类对宇宙的不懈追问和沉淀在基因中的探索精神。 本文尝试用WxGL来回答“日月安属、列星安陈”这个古老的问题。太

    2023年04月21日
    浏览(45)
  • 【计算机图形学】【实验报告】太阳系绘制、B样条曲线绘制(附代码)

    实 验 报 告 一、实验目的 掌握三维图形的显示原理和方法,掌握三维观察的原理和方法; 掌握OpenGL中矩阵堆栈函数的使用,会使用堆栈函数进行复杂场景的组装。 掌握OpenGL中三维观察变换常用的函数的使用方法,了解三维模型的贴图方法; 掌握自由曲线的生成方法,熟练

    2024年02月10日
    浏览(41)
  • Visual Studio 2022 搭建GLFW OpenGL开发环境

    最近工作需要 需要写一个全景的视频播放器 网上搜了下大概解决方案是 ffmpeg+opengl b站有很多视频  按照视频 搭建了OpenGL的开发环境 先去GLFW的网站下载 windows平台的库文件 为什么使用GLFW  因为GLFW是跨平台的   我下的是64位版本解压后有目录如下    包含了动态库和静态库

    2024年02月03日
    浏览(52)
  • Ubuntu20.04搭建OpenGL环境(glfw+glad)

    本文在VMware安装Ubuntu20.04桌面版的环境下搭建OpenGL, 按照本文搭建完成后可以执行LearnOpenGL网站上的demo 。 关于VMware可自行到VMware Workstation Pro | CN下载 关于Ubuntu20.04桌面版可自行到官网或Index of /ubuntu-releases/20.04.6/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror下载 这里窗口

    2024年02月12日
    浏览(56)
  • Visual studio2022 利用glfw+glad配置OpenGL环境

    链接:https://visualstudio.microsoft.com/zh-hans/ 搜索时最常见的是glut,但是了解到glut最后更新时间是1998年,比我还小两岁…目前没人维护了,也被弃用了… 目前,最常用的就是freeglut+glew和glfw+glad两种组合。据说前者比较经典,后者比较新潮,所以作为潮人,我选择了后者(具体可

    2024年02月04日
    浏览(66)
  • 【GIS开发】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)

    🍺三维数字地球系列相关文章如下🍺: 1 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第一期 2 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第二期 3 【小沐学GIS】基于OpenSceneGraph(OSG)绘制三维数字地球Earth 4 【小沐学GIS】基于C++绘制太阳系

    2023年04月17日
    浏览(63)
  • OpenGL —— 2.5、绘制第一个三角形(附源码,glfw+glad)(更新:纹理贴图)

    源码效果   C++源码        纹理图片            需下载stb_image.h这个解码图片的库,该库只有一个头文件。         具体代码:            vertexShader.glsl              fragmentShader.glsl              main.c      

    2024年02月11日
    浏览(48)
  • Android OpenGL ES实现简单绿幕抠图

    目录 正文 OES Filter BlendShader Filter 最后的效果 缺陷 实现绿幕抠图,其实想法很简单。 这里简单粗暴的使用着色器替换。 OES Filter 直接实现在相机预览上的Shader ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #extension GL_OES_EGL_image_external : require precision mediump float ;        

    2024年02月13日
    浏览(29)
  • 太阳辐射环境模拟系统系统

    太阳辐射环境模拟系统是一种高度专业化的设备,用于模拟太阳光的全谱段辐射,包括紫外线、可见光和红外线。这种系统的核心功能是在实验室条件下复制太阳的辐射条件,以评估材料、产品或设备在实际太阳辐射影响下的性能和耐久性。   光伏电池测试:评估太阳能电池

    2024年03月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包