GLSL projective texture

Projective Texture(投影贴图)是一项重要的基础技术;尽管在固定管线时代就可以很容易的实现;然而在可编程管线时代,在shader中灵活的运用Projective Texture,是实现各种高级效果的一项基础操作;当然,它本身的效果也很“cool”;另外,对于已经算不上新鲜技术的“shadow mapping”,Projective Texture是必须的一项操作,就是把光源观察方向所得到的Depth Texture(深度贴图)投射到光源的观察的空间;

在固定管线中实现Projective Texture非常简单:

首先要打开纹理自动生成,并设置相关参数:

static GLfloat sPlane[4] = { 1, 0, 0, 0 };
static GLfloat tPlane[4] = { 0, 1, 0, 0 };
static GLfloat rPlane[4] = { 0, 0, 1, 0 };
static GLfloat qPlane[4] = { 0, 0, 0, 1 };

glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);

这样就可以把纹理从眼睛的观察方向投射到场景中去,如果要从光源方向投射纹理,就要使用glActiveTextureARB首先把那一层的纹理单元激活,然后载入光源方向的透视观察矩阵,最后别忘了glEnable(GL_TEXTUREn_ARB);

然而,现在的各种特效,不用shader实现,太费劲了;当进入可编程管线时,上面的设置的自动纹理生成将不起作用;需要自己在shader中实现投影的采样;然而,这一切在GLSL中实现非常容易:

 

以下代码实现了把一个纹理投向一个指定的观察方向,需要预先把要使用的投影观察矩阵载入GL_TEXTURE0_ARB

//Vertex Shader

uniform mat4 camMatInv;
uniform mat4 camMat;
varying vec4 ProjTextureCoord;
void main(void)
{

     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

     vec4 pos = gl_ModelViewMatrix*gl_Vertex;//观察坐标

     pos = camMatInv*pos;//世界坐标
     ProjTextureCoord= gl_TextureMatrix[0]*pos;//纹理坐标;

     ProjTextureCoord.z += 0.99;

}

//Fragment Shader

varying vec4 ProjTextureCoord;
uniform sampler2D ProjectiveTexture;

void main(void)
{

     vec4 test = ProjTextureCoord;
     test.x = test.x/test.w;
     test.y = test.y/test.w;

     vec4 tex_color= texture2DProj( ProjTextureCoord,ProjectiveTexture);
 

     //防止纹理扩出边界和映射到后方表面上
     if(test.x<0.0) tex_color.rgb = 1.0;
     if(test.x>1.0) tex_color.rgb = 1.0;
     if(test.y<0.0) tex_color.rgb = 1.0;
     if(test.y>1.0) tex_color.rgb = 1.0;
     if(test.z<0.0) tex_color.rgb = 1.0;

     gl_FragColor = gl_Color*tex_color;

}


 

你可能感兴趣的:(project)