zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    冒泡 希尔 快速 插入 堆 基数
    排序总结
    软件工程(齐治昌-谭庆平-宁洪)
    Java简单计算器
    插入排序
    Android中theme.xml与style.xml的区别
    activity theme parent 属性浅析
    xml中不能直接添加ViewGroup
    Java中对象的上转型对象
    Android原理View、ViewGroup
  • 原文地址:https://www.cnblogs.com/chandler00x/p/4630479.html
Copyright © 2011-2022 走看看