首页 > 系统相关 >Linux 下的 OpenGL 之路(九):天空盒、反射和折射

Linux 下的 OpenGL 之路(九):天空盒、反射和折射

时间:2023-07-29 11:13:15浏览次数:35  
标签:__ GL OpenGL textureID jpg 天空 折射 Linux include

前言

搞定了天空盒,才算是真正完成了场景的搭建,以后再要进行什么样的图形学测试,都可以在这个场景下进行。比如后面的反射、折射就是这样的例子。

写完这篇,我决定暂时结束这个系列。主要是因为我太懒了,居然拖拖拉拉拖了两年。其实可以探索的内容还有很多,比如阴影啊、HDR啊、辉光啊、基于物理的渲染啊什么的,内容还挺多,我想的是等以后我把我的代码搞得更完善一点之后,可能重写这一个系列。

也有可能不重写这个系列了,直接进军 Vulkan。

天空盒的技术其实挺简单

在没有做天空盒的时候,觉得天空盒很神秘。做了天空盒之后,发现天空盒的技术其实挺简单,就是利用了立方体贴图而已。

先说模型,就是绘制六个面,组成一个盒子而已,唯一不同的,可能就是这个盒子的面都是向内的。至于盒子的大小,其实不重要,后来我算是想明白了,反正应用纹理之后,我们看到的都是一个封闭的世界背景,那么把这个背景放在坐标为1的位置,还是放在远处,其实没什么区别。唯一需要注意的是,需要在 Shader 里面修改它的深度值,让它绘制在所有物体的后面,这样,其实是给了我们一个天空盒在无穷远处的假象。

再说立方体贴图,其实就是 6 张图片,使用相应的 API 载入而已。

最后说一说在场景中漫游的问题。通过前面的描述,可以看出盒子的位置一定在原点,盒子的大小不重要,所以 Model Matrix 就没有必要要了。但是我们还是需要在场景中转动,所以 View Matrix 还是要考虑,但是又要和前面的 View Matrix 不同,也就是我们只考虑摄像机的转动,而不用考虑摄像机的移动。所以这个要单独处理。

下面直接贴代码:

#ifndef __SKYBOX_H__
#define __SKYBOX_H__

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include <string>
#include <string.h>
#include <GL/glew.h>
#include <iostream>
#include "model.hpp"

class SkyBox
{
protected:
    GLuint VAO, VBO, textureID;

public:
    GLuint getTextureID(){
        return textureID;
    }

    void loadSkyBox(std::string directory)
    {
        std::cout << "Directory name: " << directory << std::endl;
        float vertex_data[] = {
            // positions
            -1.0f, 1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,

            -1.0f, -1.0f, 1.0f,
            -1.0f, -1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, -1.0f,
            -1.0f, 1.0f, 1.0f,
            -1.0f, -1.0f, 1.0f,

            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,

            -1.0f, -1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, -1.0f, 1.0f,
            -1.0f, -1.0f, 1.0f,

            -1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, -1.0f,
            1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f,
            -1.0f, 1.0f, 1.0f,
            -1.0f, 1.0f, -1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f, 1.0f,
            1.0f, -1.0f, 1.0f};

        GLuint vertex_num = 36;

        glCreateVertexArrays(1, &VAO);
        glBindVertexArray(VAO);
        glCreateBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glNamedBufferStorage(VBO, sizeof(vertex_data), vertex_data, 0);
        std::cout << "sizeof vertex_data:" << sizeof(vertex_data) << std::endl;
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);

        std::vector<std::string> faces{
            "right.jpg",
            "left.jpg",
            "top.jpg",
            "bottom.jpg",
            "front.jpg",
            "back.jpg"
        };

    glGenTextures(1, &textureID);
    glActiveTexture(GL_TEXTURE0 + textureID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

    int width, height, nrChannels;
    for (unsigned int i = 0; i < faces.size(); i++)
    {
        unsigned char *data = stbi_load((directory + "/" + faces[i]).c_str(), &width, &height, &nrChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 
                         0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data
            );
            stbi_image_free(data);
        }
        else
        {
            std::cout << "Cubemap texture failed to load at path: " << directory + "/" + faces[i] << std::endl;
            stbi_image_free(data);
        }
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    }

    void render()
    {
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
};

#endif

主文件的代码我就不贴了。下面来看看顶点着色器的代码和片段着色器的代码。

#version 330 core
layout (location = 0) in vec3 aPos;

out vec3 TexCoords;

uniform mat4 projection_matrix;
uniform mat4 view_matrix;

void main()
{
    TexCoords = aPos;
    vec4 tempPosition = projection_matrix * view_matrix * vec4(aPos, 1.0);
    gl_Position = tempPosition.xyww;
}
#version 330 core
out vec4 FragColor;

in vec3 TexCoords;

uniform samplerCube skybox;

void main()
{    
    FragColor = texture(skybox, TexCoords);
}

关于反射和折射

关于反射和折射的计算,大家都懂,主要是涉及到视线方向和法线方向。当我知道了 GLSL 里面本来就有 reflect 函数和 refract 函数之后,我就觉得,这 TM 也实在是太简单了。

多的话不说,直接上图吧。

嗯,还是有点意思的。

总结

这个系列暂时就到这里结束吧,虽然我还有一点意犹未尽。让图形学的东西通过自己的代码在自己的屏幕上显示出来,还是挺激动人心的。以后我可能会将这个系列重整,也可能会添加一些东西,但是那就不知道是什么时候的事情了,可能要等我把手上的事情忙完,也可能那时候我又换了新电脑,换了新环境。

如果下次再重整这个系列,我可能会先解决在 OpenGL 里面显示文字的功能,然后显示个帧率看看,这样,可以让自己对各种图形学的算法和实现的效率有一个体验,也是不错的。

哦,对了,还有 VS Code 不得不提,真的是挺好用的。

版权申明

该随笔由京山游侠在2023年07月29日发布于博客园,引用请注明出处,转载或出版请联系博主。QQ邮箱:[email protected]

标签:__,GL,OpenGL,textureID,jpg,天空,折射,Linux,include
From: https://www.cnblogs.com/youxia/p/cg009.html

相关文章

  • linux获取子文件和子目录
    linux获取子文件和子目录#include<dirent.h>#include<sys/stat.h>#include<string>#include<vector>#include<stdio.h>//#include<android/log.h>#defineTAG"[demo]"//#defineLOGD(...)__android_log_print(AND......
  • ffmpeg 编译安装android和linux
    ffmpeg编译安装android和linux下载:https://github.com/FFmpeg/FFmpeghttps://www.ffmpeg.org/download.htmlenvirenmentndk:https://github.com/android/ndk/wiki/Unsupported-Downloadssudoapt-getinstallbuild-essentialpkg-configsudoapt-getintalllibx264-dev......
  • linux tar命令之小知识-解压指定层级目录以及指定文件
    我们以解压k8s二进制源码文件为例,只解压出第三层级目录下的kube-apiserver、kube-controller-manager、kubectl、kubelet、kube-proxy、kube-scheduler这几个文件。k8s源码文件目录结构,目录实在太多了,我删除了大部分,不在这里显示[root@k8s-master01tmp]#treekubernetesku......
  • VirtualEnv 20.24.0 发布 | 《Linux就该这么学》
    VirtualEnv20.24.0现已发布,VirtualEnv用于在一台机器上创建多个独立的Python运行环境,可隔离项目之间的第三方包依赖,为部署应用提供方便,把开发环境的虚拟环境打包到生产环境即可,不需要在服务器上再折腾一翻。新版更新内容如下:release20.23.1#2590修复CI#2593......
  • VirtualEnv 20.24.0 发布 | 《Linux就该这么学》
    VirtualEnv20.24.0现已发布,VirtualEnv用于在一台机器上创建多个独立的Python运行环境,可隔离项目之间的第三方包依赖,为部署应用提供方便,把开发环境的虚拟环境打包到生产环境即可,不需要在服务器上再折腾一翻。新版更新内容如下:release20.23.1#2590修复CI#2593......
  • linux console
    内核配置文件(比如arch\arm\configs\imx_v6_v7_defconfig)会配置宏CONFIG_CMDLINE,用于某些情况下配置内核CONFIG_CMDLINE="noinitrdconsole=ttymxc0,115200"由以下代码可知,当设备树没有bootargs,或者设置了CONFIG_CMDLINE_FORCE,则使用内核配置文件提供的CONFIG_CMDLINE......
  • Linux开发
    shell命令概述Shell作用:命令解释器介于操作系统内核与用户之间,负责解释命令行获得命令帮助内部命令help命令的“--help”选项使用man命令阅读手册页命令行编辑的几个辅助操作Tab键:自动补齐反斜杠“\”:强制换行快捷键Ctrl+U:清空至行首快捷键Ctrl+K:清空至行尾快捷键Ctr......
  • 使用scp在Linux服务器之间传输文件
    第一章、scp命令介绍scp就是securecopy,一个在linux下用来进行远程拷贝文件的命令。scp文件名1远程用户名@IP地址:文件名2几个参数:-v用来显示进度.可以用来查看连接-C使能压缩选项-P选择端口-4强行使用IPV4地址.-6强行使用IPV6地址.第二章、实......
  • 第三章 指针才是C语言的精髓(嵌入式Linux与物联网软件开发 C语言内核深度解析)
    这仅仅是读《嵌入式Linux与物联网软件开发:C语言内核深度解析》pdf的知识记录 地址:指的都是某个字节的地址。比如inta的空间大小有4个字节,每个字节都有一个地址(也就是有4个地址),但是只有首字节地址才能作为整个a空间的地址。也就是说,整个内存以1个字节为基本单位划分无数个地址,......
  • /usr/local/arm/5.4.0/usr/bin/../libexec/gcc/arm-none-linux-gnueabi/5.4.0/cc1: er
    arm-linux-gcca.c报错/usr/local/arm/5.4.0/usr/bin/../libexec/gcc/arm-none-linux-gnueabi/5.4.0/cc1:errorwhileloadingsharedlibraries:libmpc.so.3:cannotopensharedobjectfile:Nosuchfileordirectory安装arm-linux-gcca.c没安装g++解决方法:重新安装g++......