OpenGL Normal Mapping瞎折腾有感

最近在使用OpenGL折腾Normal Mapping。说白了就是有一个纹理,里面存储的是法向量。在计算光照时,用该纹理中采样得到的法向量来替代几何体原法向量进行光照计算。这个存储法向量的纹理叫做Normal Map。有时候场景资源不会直接给你Normal Map,而是给你一个Height Map,该纹理中只存储了一个通道,是[0,1]的灰度值,可以理解成几何体表面凹凸不平的高度,可以根据这个Height Map生成Normal Map。生成过程如下:

uniform sampler2D HeightMapTex;

float h21 = textureOffset(HeightMapTex,Coord,ivec2(1,0)).r;
float h01 = textureOffset(HeightMapTex,Coord,ivec2(-1,0)).r;
float h10 = textureOffset(HeightMapTex,Coord,ivec2(0,-1)).r;
float h12 = textureOffset(HeightMapTex,Coord,ivec2(0,1)).r;
vec3 vr = normalize(vec3(2.0f,0.0f,h21 - h01));
vec3 vt = normalize(vec3(0.0f,2.0f,h12 - h10));

// normal in tangent space
vec3 normal = normalize(cross(vr,vt));

直接从Normal Map中采样得到的和从Height Map中计算得到的normal向量是在tangent space之中。值得注意的是,直接从Normal Map中获取的法向量的每个轴的值是缩放到[0,1]之后的法向量,要先还原才能使用,而从HeightMap计算得到的法相可以直接使用。缩放和还原过程如下:

// 缩放
normal = normal * 0.5f + vec3(0.5f);

//还原
normal = normal * 2.0f - vec3(1.0f);

在进行光照计算时,我们需要光的方向LightDir,视角的方向ViewDir,和法向量n,这些向量必须在转换到同一个坐标系中进行计算。为了提高计算效率,通常我们在VertexShader中把LightDir和ViewDir变换到tangent space中,经过插值后传递到Fragment Shader中,然后对Normal Map进行采样,得到tangent space的法向量之后,进行光照计算。

关于Tangent Space到Object Space的变换矩阵构建,可参考以下链接:http://www.terathon.com/code/tangent.html

时间: 2024-10-29 18:27:59

OpenGL Normal Mapping瞎折腾有感的相关文章

《Normal Mapping》

原文地址:https://learnopengl-cn.github.io/05%20Advanced%20Lighting/04%20Normal%20Mapping/ 原文 Normal Mapping 作者 JoeyDeVries 翻译 Django 校对 KenLee 我们的场景中已经充满了多边形物体,其中每个都可能由成百上千平坦的三角形组成.我们以向三角形上附加纹理的方式来增加额外细节,提升真实感,隐藏多边形几何体是由无数三角形组成的事实.纹理确有助益,然而当你近看它们时,这个事实便隐

【Unity Shaders】法线纹理(Normal Mapping)的实现细节

写在前面 写这篇的目的是为了总结我长期以来的混乱.虽然题目是"法线纹理的实现细节",但其实我想讲的是如何在shader中编程正确使用法线进行光照计算.这里面最让人头大的就是各种矩阵运算和坐标系之间的转换,很容易因为坐标系错误而造成光照结果的错误. 我们将要讨论以下几个问题: 为什么法线纹理通常都是偏蓝色的? 在Unity里,法线纹理是需要把"Texture Type"设置成"Normal Map"才能正确显示,为什么? 把"Textur

瞎折腾--#include到底是什么意思

很多人上了这么多年学,学了这么多年课,考了这么多年试,写了这么多年程序,到头来,问问你#include是什么意思,却只能简单的说说那是一个预处理命令.然后在深问一下,什么是预处理命令,然后就卡壳了.下面我们就来一起瞎折腾一下,看看#include背后的故事. 一般来说,我们都是#include <stdio.h>的,但是今天我不这样写. 先看看我的工程,我的Project中有三个文件,main.cpp ,Foo.txt, Foo.c.这里要看清楚了,我没有使用Foo.h,而是使用了Foo.tx

【瞎折腾系列】mysql存储过程初接触

开始[瞎折腾系列],这个系列纯属瞎折腾,可能没有什么实际意义. mysql存储过程生成表: 新建一张user表,包含id, username , password , usertable字段. 然后创建存储过程: create PROCEDURE create_table() BEGIN DECLARE n int DEFAULT 0; DECLARE t_error INTEGER DEFAULT 0; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET

【瞎折腾系列】Spring DataSource 【结论:没弄好】

本来想弄个多数据源,但是技术不高,嗯,宣布失败... 嗯,结论是失败了... 求高手给我讲讲这些东西啊,感激不尽啊~~~ 以下的折腾也是基于之前配置的Spring Mybatis框架. 想弄多数据源,首先想到的就是从datasource入手. spring-database.xml改成了两个datasource: <bean id="dataSourceA" class="com.alibaba.druid.pool.DruidDataSource">

刚接触Joomla,写一下瞎折腾的初感受~

我这几天一直在苦苦寻找一款可以长期投靠的CMS产品,要求的是 1)必须支持命名空间 2)必须OOP + MVC分层 3)丰富分文档和使用群体,至少是出名的,免得哪一天他们解散了 4)-- 一开始我把目光投向了drupal,看了一下中文网络对他的介绍,什么节点存储思路,创造了什么先河.看了之后都睡不着觉了,恨不得开灯起来下载测试下. 不过第二天下载来安装发现,很让自己失望(自己对Drupal的感受的文章 http://blog.csdn.net/default7/article/details/3

第九章 Normal Mapping and Displacement Mapping

第九章 Normal Mapping and Displacement Mapping 本章主要讲述两种图形学技术,支持在不增加objects的poly primitive的情况下,在场景中增加更多的细节.第一种是normal mapping,通过创建一些"fake" geometry(虚设的多边形图元)模拟光照作用.第二种是displacement mapping,根据纹理数据moving vertices actually(与"fake"相对应,这里指真实的移动

&lt;OpenGL&gt; Texture Mapping

I. Steps in Texture Mapping To use texture mapping, you perform these steps. 1. Create a texture object and specify a texture for that object. 2. Indicate how the texture is to be applied to each pixel. 3. Enable texture mapping. 4. Draw the scene, s

[OpenGL] shadow mapping(实时阴影映射)

source:原文地址 code:点击可以直接下载源代码 1978年,Lance Williams在其发表的论文<Casting curved shadows on curved surfaces>中提出了Shadow mapping算法,从那以后,该算法在离线渲染和实时渲染两个领域都得到了广泛的应用.皮尔斯动画工作室的Renderman渲染器.以及一些知名电影如<玩具总动员>都使用了shadow mapping技术. 在众多图形应用的阴影技术中,shadow mapping只是产