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. // Load texture file
  9. glActiveTexture(GL_TEXTURE0);
  10. TGAIO::loadTex("../media/texture/flower.tga");
  11. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  12. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

顶点shader

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

片元shader

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

在片元着色器中,if( ProjTexCoord.z > 0.0 )  意思是如果ProjTexCoord.z 为负,则说明在投影机的后面,我们不需要查找对应的纹理了。

textureProj 函数是用来访问纹理的(传入的纹理坐标是投影坐标系下的坐标),在前面我们提到,在平移缩放投影矩阵后,我们需要除以其坐标中的w项,而textureProj 会为我们做这些。

在本例子中有一个很大的缺点,投影纹理(projected texture) 将会投射到场景中的任何物体上,即便有物体遮挡。例如,我们可以让上图的地板向下移动一些。结果如图:

总结:


影纹理映射真正的流程是 “ 根据投影机(视点相机)的位置、投影角度,物体的坐标,求出每个顶点所对应的纹理坐标,然后依据纹理坐标去查询纹理值 ”
,也就是说,不是将纹理投影到墙上,而是把墙投影到纹理上。投影纹理坐标的求得,也与纹理本身没有关系,而是由投影机的位置、角度,以及 3D
模型的顶点坐标所决定
projtexcoord=偏移矩阵 * 光源投影矩阵 * 光源观察矩阵 * 建模矩阵

最新文章

  1. Proactor VS Reactor
  2. 在iOS中实现类似安卓自动消失提示框
  3. string find
  4. 【转】Linux写时拷贝技术(copy-on-write)
  5. SynchronousQueue
  6. 近期最久未使用页面淘汰算法———LRU算法(java实现)
  7. phpcms常用接口调用方法
  8. JVM内存最大能调多大分析
  9. RPC框架
  10. sqlServer:行列转换之多行转一行
  11. 详解 清除浮动 的多种方式(clearfix)
  12. xcode svn commit is not under version control 和 git常用指令
  13. ajax跨域问题及相关解决方案
  14. 程序-代写(qq:928900200)
  15. 听说,你也一直钟爱着equals。。。
  16. 原生JS取代一些JQuery方法的简单实现
  17. 散列算法-MD5
  18. git中的ssh和https方式的使用(gitee为例)
  19. 2018-02-03-PY3下经典数据集iris的机器学习算法举例-零基础
  20. Java多线程学习笔记之二缓存

热门文章

  1. ASP.NET MVC3细嚼慢咽---(1)网站创建与发布
  2. I-frame、B-frame、P-frame及DTS、PTS的关系(转)
  3. javascript 作用域例子
  4. iOS9对SDK的影响(iOS9适配必看)
  5. 第二百二十六天 how can I 坚持
  6. Spark shell的原理
  7. XSS攻击及防御(转)
  8. HDOJ_1010 Tempter of the Bone
  9. PC端 $_SERVER 说明
  10. POJ3080Blue Jeans(暴力)