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。

应用程序设置代码片段

[cpp] view plaincopyprint?

  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

[cpp] view plaincopyprint?

  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

[cpp] view plaincopyprint?

  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=偏移矩阵 * 光源投影矩阵 * 光源观察矩阵 * 建模矩阵

时间: 2024-10-08 07:55:57

OpenGL 4.0 GLSL 实现 投影纹理映射(Projective Texture Mapping) (转)的相关文章

OpenGL 4.0 GLSL 基础教程概览——VAO和VBO常用操作接口

OpenGL  4.3 最新渲染管线图 从OpenGL 2.0 到 OpenGL 3.0变化非常大,但从OpenGL 3.0 到OpenGL 4.0 变化不是太大. 着色器程序直接运行在GPU上,并且是并行的,一个片元着色器可能一次执行所有象素. deprecation model, 在OpenGL3.0 提出,为了保持向后兼容,兼容模式compatibility profile.和核心模式core profile的概念在OpenGL 3.2 中提出. 在Qt 4.7以后版本,可以通过下列方式选

Unity Shader:Projective Texture Mapping

Projective-Texture-Mapping是用于投影一个texture到一个物体上.通过设置一个摄像机在投影点上,获取投影摄像机的 VP 矩阵,来获取相对于纹理的uv坐标.具体描述见:GPU 编程与CG 语言之阳春白雪下里巴人 中的12.3节. Shader "Custom/Projective-Texture-Mapping" { Properties { _Tex ("Proj Tex", 2D) = "white" {} _Col

Projective Texture的原理与实现 【转】

Projective Texture是比较常见的一种技术,实现起来代码也就区区的不过百行,了解其原理及技术细节是我们的重点,知其然,知其所以然. 粗略的说就是想象场景中有台投影仪(Projector),texture就是我们投影的内容,把纹理放在近裁剪面(near clip plane)上,沿着投影仪的方向把纹理投影到场景中.Xheartblue兄翻译了一篇文章,很好的给投影纹理的原理进行的阐述[1],有兴趣阅读原文 的可以访问这里[2],这本书可以是好东东啊!! 在这里有几个概念不能混淆 了:

OpenGL ES2.0 入门经典例子

原文链接地址:http://www.raywenderlich.com/3664/opengl-es-2-0-for-iphone-tutorial 免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作! ps:非常感谢skingTree为我们提供的这篇翻译教程,感谢yy.小狼.北方加入我的教程翻译团队,谢谢你们! 教程截图: OpenGL ES 是

iOS OpenGL ES2.0 开发实例

本教程源码地址下载:https://github.com/wanglixin1999/HelloGL OpenGL ES 是可以在iphone上实现2D和3D图形编程的低级API. 如果你之前接触过 cocos2d,sparrow,corona,unity 这些框架,你会发现其实它们都是基于OpenGL上创建的. 多数程序员选择使用这些框架,而不是直接调用OpenGL,因为OpenGL实在是太难用了. 而这篇教程,就是为了让大家更好地入门而写的. 在这个系列的文章中,你可以通过一些实用又容易上手

第三章:初始化 OpenGL 4.0

原文地址: http://www.rastertek.com/gl40tut03.html Tutorial 3: Initializing OpenGL 4.0 This tutorial will be the first real introduction to working with OpenGL 4.0. We will address three main things which are initializing OpenGL 4.0, shutting it down, and

NeHe OpenGL教程 第六课:纹理映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第六课:纹理映射 纹理映射: 在这一课里,我将教会你如何把纹理映射到立方体的六个面. 学习 texture map 纹理映射(贴图)有很多好处.比方说您想让一颗导弹飞过屏幕.根据前几课的知识,我们最可行的办法可能是很多个多边形来构建

openGL点精灵PointSprite详解: 纹理映射,旋转,缩放,移动

第一,什么是点精灵 openGL的图形由顶点构成,以后利用顶点进行纹理的映射.点精灵就是,一个顶点被当作一个精灵来处理.特别之处就是,一个顶点也可进行纹理贴出.例如,原来是个顶点构成的一个矩形,现在一个顶点就可以完成了.瞬间我们就可以想想,粒子效果,那些云雾水流火花什么的用了点精灵,就可以瞬间减少3个顶点的计算,glDrawArrays使用GL_POINT就可以了,完全也不需要什么顶点索引了.这是非常诱人的效率. 第二,点精灵的局限 一个顶点缩放都必须是矩形.并且大小的最大最小值是有范围的,每个

iOS开发——图形编程OC篇&OpenGL ES2.0编程步骤

OpenGL ES2.0编程步骤 OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机.PDA和游戏主机等嵌入式设备而设计.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. 1. 保存全局变量的数据结构 以下例子程序均基于Linux平台. 1 typedef struct _escontext 2 { 3 void* userData; // P