首页 > 其他分享 >GLSL教程 第十三章:综合项目:创建一个完整的渲染场景(一更)

GLSL教程 第十三章:综合项目:创建一个完整的渲染场景(一更)

时间:2024-08-01 11:24:09浏览次数:15  
标签:GLSL 教程 场景 void TEXTURE uniform vec3 第十三章 GL

 

目录

13.1 项目规划和设计

13.1.1 项目目标

13.1.2 设计要求

13.2 实现场景中的光照、材质和纹理

13.2.1 创建基础场景

13.2.2 应用材质和纹理

13.3 集成高级渲染效果和后期处理

13.3.1 阴影映射(Shadow Mapping)

13.3.2 环境光遮蔽(AO)

13.3.3 简单的景深效果(Depth of Field)

13.3.4 阴影技术

13.4 性能优化

13.4.1 批处理渲染

13.4.2 LOD(细节层次)

13.4.3 减少状态切换

13.4.4 延迟渲染


     在本章中,我们将创建一个完整的渲染场景,涵盖从基础的场景设置到高级的渲染效果和后期处理。我们将使用OpenGL和GLSL来实现场景的渲染,并逐步引入光照、材质、纹理、阴影映射、环境光遮蔽(AO)以及景深效果等技术。

13.1 项目规划和设计

13.1.1 项目目标

       本项目的目标是创建一个包含地面、墙壁和一个简单3D模型(如立方体)的基本渲染场景。除此之外,我们还将实现以下高级渲染效果:

  • 阴影映射(Shadow Mapping)
  • 环境光遮蔽(Ambient Occlusion,AO)
  • 简单的景深效果(Depth of Field)
13.1.2 设计要求
  1. 场景内容:
    • 地面
    • 墙壁
    • 3D模型(立方体)
  2. 光照效果:
    • 点光源
    • 环境光
  3. 材质效果:
    • 漫反射和高光
  4. 高级渲染效果:
    • 阴影映射
    • 环境光遮蔽(AO)
    • 简单的景深效果

13.2 实现场景中的光照、材质和纹理

13.2.1 创建基础场景

       首先,我们将设置基础场景,包括地面、墙壁和一个简单的3D模型(立方体)。我们使用OpenGL创建这些基本几何体,并为每个对象定义适当的顶点和片段着色器。

顶点着色器 (shader.vert):

#version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    vec4 worldPosition = model * vec4(aPos, 1.0);
    FragPos = worldPosition.xyz;
    Normal = mat3(transpose(inverse(model))) * aNormal;
    TexCoord = aTexCoord;
    gl_Position = projection * view * worldPosition;
}

片段着色器 (shader.frag):

#version 330 core

in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;

out vec4 FragColor;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

struct Light {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Material material;
uniform Light light;
uniform vec3 viewPos;
uniform sampler2D diffuseTexture;

void main() {
    // Ambient
    vec3 ambient = material.ambient * light.ambient;

    // Diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(light.position - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = material.diffuse * diff * light.diffuse;

    // Specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = material.specular * spec * light.specular;

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0) * texture(diffuseTexture, TexCoord);
}
13.2.2 应用材质和纹理

       接下来,我们为场景中的物体应用基础的材质和纹理。材质的主要属性包括漫反射、镜面反射和环境光成分。纹理则用于为物体添加更多的细节和颜色。

纹理加载和绑定 (texture.cpp):

#include "texture.hpp"
#include <iostream>

Texture::Texture(const char* imagePath) {
    glGenTextures(1, &ID);
    glBindTexture(GL_TEXTURE_2D, ID);

    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 加载并生成纹理
    int width, height, nrChannels;
    unsigned char* data = stbi_load(imagePath, &width, &height, &nrChannels, 0);
    if (data) {
        GLenum format;
        if (nrChannels == 1)
            format = GL_RED;
        else if (nrChannels == 3)
            format = GL_RGB;
        else if (nrChannels == 4)
            format = GL_RGBA;

        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cerr << "Failed to load texture: " << imagePath << std::endl;
    }
    stbi_image_free(data);
}

void Texture::bind() const {
    glBindTexture(GL_TEXTURE_2D, ID);
}

场景对象加载 (scene_object.cpp):

#include "scene_object.hpp"
#include <glm/gtc/matrix_transform.hpp>

SceneObject::SceneObject(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const char* texturePath)
    : vertices(vertices), indices(indices), texture(texturePath) {
    setupMesh();
}

void SceneObject::setupMesh() {
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

    // 顶点位置
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);

    // 法线
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));

    // 纹理坐标
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));

    glBindVertexArray(0);
}

void SceneObject::draw(const Shader& shader) {
    shader.use();
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

13.3 集成高级渲染效果和后期处理

13.3.1 阴影映射(Shadow Mapping)

       阴影映射用于在场景中生成逼真的阴影效果。我们将使用深度贴图来计算阴影,并在片段着色器中进行深度比较。

阴影映射Shader (shadow_mapping_shader.vert and shadow_mapping_shader.frag):

顶点着色器 (shadow_mapping_shader.vert):

#version 330 core

layout(location = 0) in vec3 aPos;

uniform mat4 lightSpaceMatrix;
uniform mat4 model;

void main() {
    gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0);
}

片段着色器 (shadow_mapping_shader.frag):

#version 330 core

void main() {
    // 这里不需要输出颜色,深度缓冲会自动存储深度值
}
<

标签:GLSL,教程,场景,void,TEXTURE,uniform,vec3,第十三章,GL
From: https://blog.csdn.net/qq_54098120/article/details/140840047

相关文章

  • MySQL安装教程(保姆级)
    1.首先要了解自己的计算机打开设置——系统——系统信息然后就可以知道自己计算机的类型了。2.下载MySQL2.1.来到MySQL官网点击进入我们下拉页面,可以找到DOWNLOADS页面默认给咱们选择最新的版本,咱们不用,咱们尽量选一个稳定的版本。而且,版本过高后,就没......
  • Midjourney保姆级教程!7大方向教你快速生成你想要的人物形象!
    一、前言由于在工作中,经常会涉及到使用人物素材完成Banner设计的工作,于是最近开始探索关于Midjourney进行AI人物生成的相关测试,同时将这一段时间的经验分享出来。刚开始接触和使用Midjourney的时候,最大的问题在于生成的人物图片无法保证人物位置的大小和视角,想要......
  • DevExpress WPF中文教程:如何将GridControl的更改发布到数据库?
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • Spring框架 配置Gateway网关/spring cloud gateway 基础入门案例教程
    文章目录目录文章目录安装流程小结概要安装流程技术细节小结概要网关作为微服务集群唯一的对外入口,可以实现很多功能.例如:统一的解决跨域(一个ajax请求origin域名和请求目标url中域名不同,ip不同,域名不同,端口不同,都会引发的问题)问题.统一的身份认证.认证解......
  • 全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函
    全网最适合入门的面向对象编程教程:29类和对象的Python实现-断言与防御性编程和help函数的使用摘要:在Python中,断言是一种常用的调试工具,它允许程序员编写一条检查某个条件。本文主要介绍了断言的应用场景和特点以及assert语句的使用,同时介绍了防御性编程和help()函数......
  • 【2024最新版】超详细Python+Pycharm安装保姆级教程,Python+Pycharm环境配置和使用指南
    本文将从Python解释器安装到Pycharm专业版安装和配置汉化等使用都进行了详细介绍,希望能够帮助到大家。Python解释器&Pycharm安装包&Pycharm破姐插件我都打包好了。这份完整版的Python安装包已经上传至CSDN官方,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费获取......
  • CTF入门教程(非常详细)从零基础入门到竞赛,看这一篇就够了!
    一、CTF简介CTF(CaptureTheFlag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。发展至今,已经成为全球范围网络安全圈流行的竞赛形......
  • CTF入门教程(非常详细)从零基础入门到竞赛,看这一篇就够了!
    一、CTF简介CTF(CaptureTheFlag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。发展至今,已经成为全球范围网络安全圈流行的竞赛形......
  • 【Python】从0开始写脚本、Selenium详细教程、附源码案例(保姆篇)
    文章目录准备工作安装selenium配置浏览器驱动脚本测试什么是Selenium?Selenium功能示例(可直接拷贝执行)编写一个简单的Python脚本来使用Selenium打开一个网页,并获取网页的标题下面是一个示例,自动打开csdn并进行搜索Selenium使用Selenium元素定位文本输入、清除与提交......
  • Adobe Acrobat DC 2021版安装教程【超简单、超详细】
    AdobeAcrobatDC是Adobe提供的一款专业PDF解决方案,具有许多强大的功能,可以满足各种文档处理需求。注意事项:①下载与激活过程中一定要关闭杀毒软件         ②提供的所有软件都是永久版的         ③软件仅供学习下载使用,不可用于......