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

  • 相关阅读:
    C++雾中风景1:友元类与面向对象
    NFS服务器的安装与配置
    未来工作相关
    python 函数
    pycharm、sublime个性化设置
    hadoop中HDFS的NameNode原理
    Cat搭建遇坑记
    美团点评CAT监控平台研究
    阿里sentinel源码研究深入
    阿里熔断限流Sentinel研究
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/4088983.html
Copyright © 2020-2023  润新知