OpenGL 4.0 GLSL 實現 投影紋理映射(Projective Texture Mapping) (轉)


http://blog.csdn.net/zhuyingqingfen/article/details/19331721

 
分類: GLSL 

投影紋理映射 (projective texture mapping):就是把紋理投射到場景的物體上,就像一個投影機把幻燈片投影到其他物體上一樣。

如下圖:用左邊的紋理圖像投影到一個茶壺上

 

投影紋理的實現方法:

其 實最重要的一點就是確定紋理坐標,紋理坐標的確定依賴於物體表面點的相對位置和投影機的位置。在OpenGL中我們可以定義一個camera,我們定義一 個中心在投影機位置的坐標空間,viewMatrix(V)把世界坐標系的點轉換到投影機的坐標系中,然后定義一個投影矩陣(P)。這樣P*V就把點轉化 到投影空間,但規格化的投影空間是[-1,1],而紋理坐標是[0,1],因此我們需要把 這個視景體轉化到[0,1]中,我們可以先把其縮小1/2,然后再平移1/2,這樣就轉化到了[0,1]上。如圖:

 

注意:由於坐標是齊次坐標系(homogeneous),在我們用其訪問紋理坐標前需要除以w。

應用程序設置代碼片段

  1. vec3 projPos = vec3(5.0f,5.0f,5.0f);  
  2.    vec3 projAt = vec3(-2.0f,-4.0f,0.0f);  
  3.    vec3 projUp = vec3(0.0f,1.0f,0.0f);  
  4.    mat4 projView = glm::lookAt(projPos, projAt, projUp);print(projView);  
  5.    mat4 projProj = glm::perspective(30.0f, 1.0f, 0.2f, 1000.0f);print(projProj);  
  6.    mat4 projScaleTrans = glm::translate(vec3(0.5f)) * glm::scale(vec3(0.5f));  
  7.    prog.setUniform("ProjectorMatrix", projScaleTrans * projProj * projView);  
  8.   
  9.    // Load texture file  
  10.    glActiveTexture(GL_TEXTURE0);  
  11.    TGAIO::loadTex("../media/texture/flower.tga");  
  12.    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);  
  13.    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);  


頂點shader

  1. #version 430  
  2.   
  3. layout (location = 0) in vec3 VertexPosition;  
  4. layout (location = 1) in vec3 VertexNormal;  
  5.   
  6. out vec3 EyeNormal;       // Normal in eye coordinates  
  7. out vec4 EyePosition;     // Position in eye coordinates  
  8. out vec4 ProjTexCoord;  
  9.   
  10. uniform mat4 ProjectorMatrix;  
  11.   
  12. uniform vec3 WorldCameraPosition;  
  13. uniform mat4 ModelViewMatrix;  
  14. uniform mat4 ModelMatrix;  
  15. uniform mat3 NormalMatrix;  
  16. uniform mat4 ProjectionMatrix;  
  17. uniform mat4 MVP;  
  18.   
  19. void main()  
  20. {  
  21.     vec4 pos4 = vec4(VertexPosition,1.0);  
  22.   
  23.     EyeNormal = normalize(NormalMatrix * VertexNormal);  
  24.     EyePosition = ModelViewMatrix * pos4;  
  25.     ProjTexCoord = ProjectorMatrix * (ModelMatrix * pos4);  
  26.     gl_Position = MVP * pos4;  
  27. }  


片元shader

  1. #version 430  
  2.   
  3. in vec3 EyeNormal;       // Normal in eye coordinates  
  4. in vec4 EyePosition;     // Position in eye coordinates  
  5. in vec4 ProjTexCoord;  
  6.   
  7. layout(binding=0) uniform sampler2D ProjectorTex;  
  8.   
  9. struct MaterialInfo {  
  10.     vec3 Kd;  
  11.     vec3 Ks;  
  12.     vec3 Ka;  
  13.     float Shininess;  
  14. };  
  15. uniform MaterialInfo Material;  
  16.   
  17. struct LightInfo {  
  18.     vec3 Intensity;  
  19.     vec4 Position;  
  20. };  
  21. uniform LightInfo Light;  
  22.   
  23. layout( location = 0 ) out vec4 FragColor;  
  24.   
  25. vec3 phongModel( vec3 pos, vec3 norm ) {  
  26.     vec3 s = normalize(vec3(Light.Position) - pos);  
  27.     vec3 v = normalize(-pos.xyz);  
  28.     vec3 r = reflect( -s, norm );  
  29.     vec3 ambient = Light.Intensity * Material.Ka;  
  30.     float sDotN = max( dot(s,norm), 0.0 );  
  31.     vec3 diffuse = Light.Intensity * Material.Kd * sDotN;  
  32.     vec3 spec = vec3(0.0);  
  33.     if( sDotN > 0.0 )  
  34.         spec = Light.Intensity * Material.Ks *  
  35.                pow( max( dot(r,v), 0.0 ), Material.Shininess );  
  36.   
  37.     return ambient + diffuse + spec;  
  38. }  
  39.   
  40. void main() {  
  41.     vec3 color = phongModel(vec3(EyePosition), EyeNormal);  
  42.   
  43.     vec4 projTexColor = vec4(0.0);  
  44.     if( ProjTexCoord.z > 0.0 )  
  45.         projTexColor = textureProj( ProjectorTex, ProjTexCoord );  
  46.   
  47.     FragColor = vec4(color,1.0) + projTexColor * 0.5;  
  48. }  



在片元着色器中,if( ProjTexCoord.z > 0.0 )  意思是如果ProjTexCoord.z 為負,則說明在投影機的后面,我們不需要查找對應的紋理了。

 

textureProj 函數是用來訪問紋理的(傳入的紋理坐標是投影坐標系下的坐標),在前面我們提到,在平移縮放投影矩陣后,我們需要除以其坐標中的w項,而textureProj 會為我們做這些。

 

在本例子中有一個很大的缺點,投影紋理(projected texture) 將會投射到場景中的任何物體上,即便有物體遮擋。例如,我們可以讓上圖的地板向下移動一些。結果如圖:

 

總結:

投 影紋理映射真正的流程是 “ 根據投影機(視點相機)的位置、投影角度,物體的坐標,求出每個頂點所對應的紋理坐標,然后依據紋理坐標去查詢紋理值 ” ,也就是說,不是將紋理投影到牆上,而是把牆投影到紋理上。投影紋理坐標的求得,也與紋理本身沒有關系,而是由投影機的位置、角度,以及 3D 模型的頂點坐標所決定
projtexcoord=偏移矩陣 * 光源投影矩陣 * 光源觀察矩陣 * 建模矩陣


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM