CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction)

开始

如图所示,本文围绕GLSL里的samplerCube记录天空盒(Skybox)、反射(reflection)、折射(refraction)的实现。

下载

CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

天空盒(Skybox)

samplerCube

想在三维场景里渲染出天空和大地,可以利用一个巨大的立方体,把6个连接的图片分别贴在立方体的6个面上。

这样的立方体就是所谓的天空盒(Skybox)。

OpenGL提供了一个GL_TEXTURE_CUBE_MAP类型的纹理,其本身就是一个立方体,自带6个纹理面。它对应的GLSL里的类型就是samplerCube。SamplerCube正适合做天空盒。

SkyboxNode

渲染天空盒,实际上就是渲染一个巨大的立方体,并且用samplerCube为其上色。

其vertex shader如下:

  1. #version core
  2.  
  3. layout(location = ) in vec3 inPosition;// 顶点位置
  4.  
  5. uniform mat4 mvpMatrix;
  6.  
  7. out vec3 texCoord;// 立方体纹理在此顶点处的坐标值
  8.  
  9. void main()
  10. {
  11. vec4 position = mvpMatrix * vec4(inPosition, 1.0);
  12. gl_Position = position.xyww;// 保证天空盒的深度始终为最深
  13. texCoord = inPosition;// 立方体纹理的特殊情况
  14. }

注意,这里的gl_Position = position.xyww;,是为了保证天空盒的深度始终为最深。这样就不会遮挡住场景里的其他物体。再注意,texCoord = inPosition;这句,就要求我们的天空盒模型必须是中心在坐标原点的立方体,这样才能保证inPosition在数值上等于此顶点的纹理坐标值。

其fragment shader如下:

  1. #version core
  2.  
  3. uniform samplerCube skybox;
  4.  
  5. in vec3 texCoord;
  6.  
  7. out vec4 color;
  8.  
  9. void main()
  10. {
  11. color = texture(skybox, texCoord);
  12. }

极其简单,就是从skybox纹理中取出对应位置的颜色,写入Framebuffer。

如果把镜头拉远,你会看到所谓的天空盒是这样的:一个剔除了正面的立方体 

反射(Reflection)

利用samplerCube,可以实现一个反射效果——根据反射原理,把天空盒的纹理贴到模型上,看上去的感觉是,模型像镜子一样反射了周围的东西。此即为环境映射的一种。

GLSL自带了反射函数reflect(,);

实现反射的vertex shader如下:

  1. #version core
  2.  
  3. layout (location = ) in vec3 inPosition;
  4. layout (location = ) in vec3 inNormal;
  5.  
  6. uniform mat4 projection;
  7. uniform mat4 view;
  8. uniform mat4 model;
  9.  
  10. out vec3 passNormal;
  11. out vec3 passPosition;
  12.  
  13. void main()
  14. {
  15. gl_Position = projection * view * model * vec4(inPosition, 1.0);
  16.  
  17. passNormal = mat3(transpose(inverse(model))) * inNormal;
  18. passPosition = vec3(model * vec4(inPosition, 1.0));
  19. }

此vertex shader做了3件事:1.给gl_Position赋值。2.传递world space里的法线passNormal。3.传递world space里的位置passPosition。

下面根据反射原理为模型上色(fragment shader):

  1. #version core
  2.  
  3. uniform vec3 cameraPos;
  4. uniform samplerCube skybox;
  5.  
  6. in vec3 passNormal;
  7. in vec3 passPosition;
  8.  
  9. out vec4 FragColor;
  10.  
  11. void main()
  12. {
  13. vec3 I = normalize(passPosition - cameraPos);
  14. vec3 R = reflect(I, normalize(passNormal));
  15. FragColor = vec4(texture(skybox, R).rgb, 1.0);
  16. }

这里利用reflect函数找到反射方向(即纹理坐标),从而找到目标颜色。

折射(Refraction)

折射与反射类似,也是一种环境映射方式。其vertex shader与反射相同,fragment shader也只有一点点不同:利用GLSL内置的refract()函数找到折射方向。

  1. #version core
  2.  
  3. uniform vec3 cameraPos;
  4. uniform samplerCube skybox;
  5.  
  6. in vec3 passNormal;
  7. in vec3 passPosition;
  8.  
  9. out vec4 FragColor;
  10.  
  11. void main()
  12. {
  13. float ratio = 1.00 / 1.52;
  14. vec3 I = normalize(passPosition - cameraPos);
  15. vec3 R = refract(I, normalize(passNormal), ratio);
  16. FragColor = vec4(texture(skybox, R).rgb, );
  17. }

注意,这里有个ratio是指两种透明物体的折射率。1.52是玻璃对空气的折射率。再注意,这里我们只计算了一个面的折射,然而本文的模型有光线的进入和穿出两次折射。不过一般这样也没关系,最终效果还是不错的。

总结

没什么可总结的。

CSharpGL(43)环境映射(Environment Mapping)-天空盒(Skybox)反射(Reflection)和折射(Refraction)的更多相关文章

  1. 3DShader之立方体环境映射(cubic environment mapping)

    前面讲了球形环境映射,然而目前采用更多的是立方体环境映射.国际惯例:上图先: 1.反射: 2.折射 3.fresnel(反射+折射) 4.色散 好了,大概讲下原理, 立方体纹理我就不多讲了,它以一个3 ...

  2. 《The Cg Tutorial》阅读笔记——环境贴图 Environment Mapping

    本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/4969956.html 环境贴图 Environment Mapping 一.简介 环 ...

  3. Environment Perception: 3D Truss Environment Mapping and Parametric Expression Extraction

    Experiments Preparation roscore rosrun pcl_ros pcd_to_pointcloud ~/.ros/wh2_lg707070_1ms0.01_filtere ...

  4. [经验] Unity3D 里怎么制作天空盒(skybox)

    记载一个简单的  天空盒子  的制作方法 第一步: 在 assets 文件夹下新建一个文件夹, 随便取个名字, 不过最好是用来专门管理场景游戏对象的文件夹,    例如放在这个 Skybox 里:  ...

  5. 立方体贴图(Cubemap)

    http://blog.csdn.net/asdjy123/article/details/51190643 点击打开链接 好东西保存方便查看 立方体贴图(Cubemap) 原文 Cubemaps 作 ...

  6. (转)OpenGL学习——立方体贴图

    转自:https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/06%20Cubemaps/ 我们之前一直使用的是2 ...

  7. OpenGL 核心技术之立方体贴图

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  8. Grand Theft Auto V (侠盗列车手5)图形研究

    原文地址:http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/   原文的简介: GTA(侠盗猎车)系列自从1997 ...

  9. DirectX11 With Windows SDK--22 立方体映射:静态天空盒的读取与实现

    前言 这一章我们主要学习由6个纹理所构成的立方体映射,以及用它来实现一个静态天空盒. 但是在此之前先要消除两个误区: 认为这一章的天空盒就是简单的在一个超大立方体的六个面内部贴上天空盒纹理: 认为天空 ...

随机推荐

  1. 通过LOGBACK实现每个类、包或自定义级别

    项实现LOGBACK对每个包或者类或者通过自定义级别的方式实现自定义输出的日志进入制定的文件.查阅了很多资料,都没有找到行之有效的解决方案,直到看到了这篇文章http://www.360doc.com ...

  2. [0] 服务器 TCP 提供程序无法在 [ 'any' <ipv4> *] 上侦听。TCP 端口已在使用中。

    配置工具——配置管理器——SQLEXPRESS协议下的TCP/IP协议 将其已启用改为禁用. 同时停止SQLEXPRESS服务即可

  3. [0] C# 扩展方法(Extension Method)

    有时有这样的情况,有一个类,你不能修改它,但你又想对它扩展(添加一个方法),这个时候就可以用到扩展方法了.请看下面的例子: using System;using System.Collections. ...

  4. 用Nodejs做一个简单的小爬虫

    Nodejs将JavaScript语言带到了服务器端,作为js主力用户的前端们,因此获得了服务器端的开发能力,但除了用express搭建一个博客外,还有什么好玩的项目可以做呢?不如就做一个网络爬虫吧. ...

  5. JavaScript事件与例子

    事件,就是预先设置好的一段代码,等到用户触发的时候执行. 一:常见的事件: 1.关于鼠标的事件 onclick 鼠标单击触发 ondblclick 鼠标双击触发 onmouseover 鼠标移上触发 ...

  6. mysql 左连接 右连接 内链接

    一般所说的左连接,右连接是指左外连接,右外连接.做个简单的测试你看吧.先说左外连接和右外连接:[TEST1@orcl#16-12月-11] SQL>select * from t1;ID NAM ...

  7. Kafka 源代码分析之LogManager

    这里分析kafka 0.8.2的LogManager logmanager是kafka用来管理log文件的子系统.源代码文件在log目录下. 这里会逐步分析logmanager的源代码.首先看clas ...

  8. asp.net core 中灵活的配置方式

    asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统 ...

  9. Vijos 1034 家族 并查集

    描述 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚.如果x,y是亲戚 ...

  10. JavaScript 语言中的 this

    JavaScript 语言中的 this 由于其运行期绑定的特性,JavaScript 中的 this 含义要丰富得多,它可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式.JavaSc ...