標籤:style blog http io color ar os sp for
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?
- vec3 projPos = vec3(5.0f,5.0f,5.0f);
- vec3 projAt = vec3(-2.0f,-4.0f,0.0f);
- vec3 projUp = vec3(0.0f,1.0f,0.0f);
- mat4 projView = glm::lookAt(projPos, projAt, projUp);print(projView);
- mat4 projProj = glm::perspective(30.0f, 1.0f, 0.2f, 1000.0f);print(projProj);
- mat4 projScaleTrans = glm::translate(vec3(0.5f)) * glm::scale(vec3(0.5f));
- prog.setUniform("ProjectorMatrix", projScaleTrans * projProj * projView);
-
- // Load texture file
- glActiveTexture(GL_TEXTURE0);
- TGAIO::loadTex("../media/texture/flower.tga");
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
頂點shader
[cpp] view plaincopyprint?
- #version 430
-
- layout (location = 0) in vec3 VertexPosition;
- layout (location = 1) in vec3 VertexNormal;
-
- out vec3 EyeNormal; // Normal in eye coordinates
- out vec4 EyePosition; // Position in eye coordinates
- out vec4 ProjTexCoord;
-
- uniform mat4 ProjectorMatrix;
-
- uniform vec3 WorldCameraPosition;
- uniform mat4 ModelViewMatrix;
- uniform mat4 ModelMatrix;
- uniform mat3 NormalMatrix;
- uniform mat4 ProjectionMatrix;
- uniform mat4 MVP;
-
- void main()
- {
- vec4 pos4 = vec4(VertexPosition,1.0);
-
- EyeNormal = normalize(NormalMatrix * VertexNormal);
- EyePosition = ModelViewMatrix * pos4;
- ProjTexCoord = ProjectorMatrix * (ModelMatrix * pos4);
- gl_Position = MVP * pos4;
- }
片元shader
[cpp] view plaincopyprint?
- #version 430
-
- in vec3 EyeNormal; // Normal in eye coordinates
- in vec4 EyePosition; // Position in eye coordinates
- in vec4 ProjTexCoord;
-
- layout(binding=0) uniform sampler2D ProjectorTex;
-
- struct MaterialInfo {
- vec3 Kd;
- vec3 Ks;
- vec3 Ka;
- float Shininess;
- };
- uniform MaterialInfo Material;
-
- struct LightInfo {
- vec3 Intensity;
- vec4 Position;
- };
- uniform LightInfo Light;
-
- layout( location = 0 ) out vec4 FragColor;
-
- vec3 phongModel( vec3 pos, vec3 norm ) {
- vec3 s = normalize(vec3(Light.Position) - pos);
- vec3 v = normalize(-pos.xyz);
- vec3 r = reflect( -s, norm );
- vec3 ambient = Light.Intensity * Material.Ka;
- float sDotN = max( dot(s,norm), 0.0 );
- vec3 diffuse = Light.Intensity * Material.Kd * sDotN;
- vec3 spec = vec3(0.0);
- if( sDotN > 0.0 )
- spec = Light.Intensity * Material.Ks *
- pow( max( dot(r,v), 0.0 ), Material.Shininess );
-
- return ambient + diffuse + spec;
- }
-
- void main() {
- vec3 color = phongModel(vec3(EyePosition), EyeNormal);
-
- vec4 projTexColor = vec4(0.0);
- if( ProjTexCoord.z > 0.0 )
- projTexColor = textureProj( ProjectorTex, ProjTexCoord );
-
- FragColor = vec4(color,1.0) + projTexColor * 0.5;
- }
在片元著色器中,if( ProjTexCoord.z > 0.0 ) 意思是如果ProjTexCoord.z 為負,則說明在投影機的後面,我們不需要尋找對應的紋理了。
textureProj 函數是用來訪問紋理的(傳入的紋理座標是投影座標系下的座標),在前面我們提到,在平移縮放投影矩陣後,我們需要除以其座標中的w項,而textureProj 會為我們做這些。
在本例子中有一個很大的缺點,投影紋理(projected texture) 將會投射到情境中的任何物體上,即便有物體遮擋。例如,我們可以讓的地板向下移動一些。結果
總結:
投影紋理映射真正的流程是 “ 根據投影機(視點相機)的位置、投影角度,物體的座標,求出每個頂點所對應的紋理座標,然後依據紋理座標去查詢紋理值 ” ,也就是說,不是將紋理投影到牆上,而是把牆投影到紋理上。投影紋理座標的求得,也與紋理本身沒有關係,而是由投影機的位置、角度,以及 3D 模型的頂點座標所決定
projtexcoord=位移矩陣 * 光源投影矩陣 * 光源觀察矩陣 * 建模矩陣
OpenGL 4.0 GLSL 實現 投影紋理映射(Projective Texture Mapping) (轉)