投影纹理映射 (projective texture mapping):就是把纹理投射到场景的物体上,就像一个投影机把幻灯片投影到其他物体上一样。
如下图:用左边的纹理图像投影到一个茶壶上
投影纹理的实现方法:
其实最重要的一点就是确定纹理坐标,纹理坐标的确定依赖于物体表面点的相对位置和投影机的位置。在OpenGL中我们可以定义一个camera,我们定义一个中心在投影机位置的坐标空间,viewMatrix(V)把世界坐标系的点转换到投影机的坐标系中,然后定义一个投影矩阵(P)。这样P*V就把点转化到投影空间,但规格化的投影空间是[-1,1],而纹理坐标是[0,1],因此我们需要把 这个视景体转化到[0,1]中,我们可以先把其缩小1/2,然后再平移1/2,这样就转化到了[0,1]上。如图:
注意:由于坐标是齐次坐标系(homogeneous),在我们用其访问纹理坐标前需要除以w。
应用程序设置代码片段
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
#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
#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=偏移矩阵 * 光源投影矩阵 * 光源观察矩阵 * 建模矩阵
http://blog.csdn.net/zhuyingqingfen/article/details/19331721
相关推荐
内容包含了glm glut 等库,用vs2008 基于OpenGL 4.0 ,可以直接运行,包含所有源码,里面含有很多使用性技巧
本文将深入探讨如何使用GLSL来实现投影纹理,这是一种技术,能让我们在3D物体上投射2D图像,产生诸如聚光灯、阴影或者环境映射等效果。 ### GLSL简介 GLSL是OpenGL的着色语言,用于定义顶点、几何和像素着色器,...
总结来说,"glsl shader 多重纹理映射"是一个涉及OpenGL、GLSL、纹理处理和混合技术的复杂概念。通过理解和应用这些技术,我们可以创建出如地球外观这样的逼真3D效果,包括其日夜变化和云层覆盖。在实际项目中,`...
非常不好找的 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 ...
If you are an OpenGL programmer looking to use the modern features of GLSL 4.0 to create real-time, three-dimensional graphics, then this book is for you. Familiarity with OpenGL programming, along ...
纹理过滤决定了当映射的纹理被放大或缩小时,OpenGL如何处理纹理图像。放大时,纹理过滤可以使用GL_NEAREST或GL_LINEAR。GL_NEAREST使用最接近纹理坐标的像素,而GL_LINEAR则使用多个像素进行插值。缩小时,可以使用...
在OpenGL中实现环境纹理映射,首先需要准备一个环境贴图(environment map)。环境贴图是一个立方体贴图,包含六个面,分别对应于正前方、正后方、正上方、正下方、右方和左方。这样,每个方向都能反映出周围环境的...
综上所述,基于OpenGL和GLSL的鱼眼全景图实现涉及到图像处理、3D图形编程和着色器技术等多个方面,通过精心设计的顶点和片段着色器,以及合理的纹理映射,我们可以成功地将二维的全景图转化为具有鱼眼视觉效果的三维...
在OpenGL中,实现纹理映射的步骤如下: 1. 加载纹理图像:可以使用库如SOIL或自由格式读取函数加载PNG、JPEG等格式的图像。 2. 创建纹理对象:使用`glGenTextures`生成纹理ID,然后使用`glBindTexture`绑定到目标...
- **OpenGL 4.0版本更新**:OpenGL 4.0 版本于2010年发布,引入了一系列新特性,包括对多线程的支持、新的纹理格式支持、扩展的几何着色器功能等,为高性能图形渲染提供了更强大的工具集。 - **核心功能增强**:...
本教程将深入探讨如何使用OpenGL ES在Android中实现立方体的多纹理映射以及混色光照效果,这对于游戏开发、虚拟现实应用以及其他需要动态图形的场景至关重要。 首先,我们需要了解纹理映射的概念。纹理映射是将2D...
此外,我们还可以使用GLSL中的`textureProj()`函数来处理投影纹理,或者`textureLod()`来控制纹理的MIP级别,以优化性能或实现特殊效果。 在实际的GLSL代码中,你可能会看到这样的结构:在顶点着色器中设置纹理坐标...
OpenGL 4.0 Shading Language Cookbook 是一本专为学习和深入理解OpenGL 4.0着色语言(GLSL)而编写的书籍,旨在帮助开发者掌握现代图形编程技术。GLSL是OpenGL的重要组成部分,用于在GPU上编写计算和渲染任务的程序...
OpenGL 4.0 Shading Language Cookbook是一本关于OpenGL着色器语言(OpenGL Shading Language,简称GLSL)的书籍。OpenGL是一种广泛使用的跨语言、跨平台的应用程序编程接口(API),用于渲染2D和3D矢量图形。随着...