openGL Projective texture mapping

原文链接:https://sites.google.com/site/gsucomputergraphics/educational/advanced-texture-mapping/projective-texture-mapping

Example

  此示例演示了投影纹理贴图,这是阴影贴图,光照贴图和纹理贴图的基础。

 

 

 

在常规纹理贴图中,每个顶点的纹理坐标都是静态的,通常是在建模软件(例如Maya,3DS Max或Blender)中计算的。在投影纹理贴图中,每个顶点的纹理坐标不是静态的,而是根据顶点的位置计算得出的。基本思想是将顶点从投影仪的视点投影到2D图片。然后,将投影顶点的2D坐标用作其纹理坐标。

首先,从投影仪的角度构造一个视图-投影-偏置矩阵,然后将该矩阵传递给顶点着色器。在顶点着色器中,将顶点位置与此投影机MVPB矩阵相乘,然后将转换后位置的前两个分量用作该顶点的纹理坐标。

 

关键函数是buildProjectorMatrices(),它为投影仪构建视图-投影-偏置矩阵。然后,在顶点着色器中,以下代码行计算顶点的纹理坐标:

 

 

 

textureCoordProj = textureMatrix * modelMatrix * vPos

在片段着色器中,使用textureProj()查找投影纹理。

代码和图像附在此页面的底部。 您应该修改计算机的纹理图像文件路径。

在以下示例中,突出显示了与投影纹理映射直接相关的代码行。

/*
   This example demonstrates projective texture mapping, which
   is the basis for shadow mapping, lightmap, and texture decal.
  此示例演示了投影纹理贴图,这是阴影贴图,光照贴图和纹理贴花的基础。  
In regular texture mapping, the texture coordinates from each vertex is static, often calculated in the modeling software such as Maya, 3DS Max, or Blender. In projective texture mapping, the texture coordinates for each vertex are not static, but calculated from the position of the vertice. The basic idea is to project the vertex from the projector's viewpoint to a 2D picture. The 2D coordinates of the projected vertex are then used as its texture coordinates.
  在常规纹理贴图中,每个顶点的纹理坐标都是静态的,通常是在建模软件
 (例如Maya,3DS Max或Blender)中计算的。 在投影纹理贴图中,每个
  顶点的纹理坐标不是静态的,而是根据顶点的位置计算得出的。 基本思想
是将顶点从投影仪的视点投影到2D图片。 然后将投影顶点的2D坐标用作其纹理坐标 First, construct a view-projection-bias matrix from the projector's perspective, and then pass this matrix to the vertex shader. In the vertex shader, multiply the vertex position with this matrix, and then use the first two component's of the transformed position as the texture coordinates for this vertex.
首先,从投影仪的角度构造一个视图-投影-偏置矩阵,然后将该矩阵传递给顶点着色器。 在顶点着色器中,
将顶点位置与此矩阵相乘,然后将转换后位置的前两个分量用作该顶点的纹理坐标。 The key function is buildProjectorMatrices(), which builds the view-projection-bias matrix for the projector. Then in the vertex shader, the following line of code calculates the texture coordinates for the vertex:
关键函数是buildProjectorMatrices(),它为投影仪构建视图-投影-偏置矩阵。
然后,在顶点着色器中,以下代码行计算顶点的纹理坐标: textureCoord = textureMatrix * modelMatrix * vPos; Ying Zhu Georgia State University 佐治亚州立大学 November 2016
*/ // GLEW header #include <GL/glew.h> // This must appear before freeglut.h 必须在freeglut.h之前出现 // Freeglut header #include <GL/freeglut.h> // GLM header files #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtx/transform2.hpp> #include <glm/gtc/matrix_access.hpp> #include <glm/gtx/projection.hpp> #include <glm/gtc/matrix_inverse.hpp> #include <glm/gtc/type_ptr.hpp> // Simple OpenGL Image Library header file 简单的OpenGL图像库头文件 #include <SOIL.h> #include <check_error.hpp> // C++ header files #include <iostream> using namespace std; using namespace glm; #define BUFFER_OFFSET(offset) ((GLvoid *) offset) /* // A square with two triangles. 有两个三角形的正方形。 GLfloat vertices[][4] = { { 1.368670f, 1.321428f, 0.094483f, 1.0f }, { -1.274187f, 1.321429f, 0.094483f, 1.0f }, { -1.274187f, -1.321428f, 0.094483f, 1.0f }, { 1.368670f, 1.321428f, 0.094483f, 1.0f }, { -1.274187f, -1.321428f, 0.094483f, 1.0f }, { 1.368670f, -1.321429f, 0.094483f, 1.0f } }; int numVertices = 6; GLfloat normals[][4] = { { 0.000000f, 0.000000f, 1.000000f, 1.0f }, { 0.000000f, 0.000000f, 1.000000f, 1.0f }, { 0.000000f, 0.000000f, 1.000000f, 1.0f }, { 0.000000f, 0.000000f, 1.000000f, 1.0f }, { 0.000000f, 0.000000f, 1.000000f, 1.0f }, { 0.000000f, 0.000000f, 1.000000f, 1.0f }, }; // Specify texture coordinates. 指定纹理坐标。 GLfloat textureCoords[][2] = { { 0.000000f, 0.000000f }, { 1.000000f, 0.000000f }, { 1.000000f, 1.000000f }, { 0.000000f, 0.000000f }, { 1.000000f, 1.000000f }, { 0.000000f, 1.000000f } }; */ // A pyramid object. 金字塔对象。 GLfloat vertices[][4] = { { 1.0f, -1.0f, 1.0f, 1.0f }, // face 1 { -1.0f, -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, -1.0f, 1.0f }, // face 2 { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f }, // face 3 { 0.0f, 1.0f, 0.0f, 1.0f }, { -1.0f, -1.0f, 1.0f, 1.0f }, { -1.0f, -1.0f, 1.0f, 1.0f }, // face 4 { 0.0f, 1.0f, 0.0f, 1.0f }, { -1.0f, -1.0f, -1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, // face 5 { 1.0f, -1.0f, -1.0f, 1.0f }, { -1.0f, -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f, 1.0f }, // face 6 { -1.0f, -1.0f, 1.0f, 1.0f }, { -1.0f, -1.0f, -1.0f, 1.0f } }; int numVertices = 18; GLfloat normals[][4] = { { 0.0f, -1.0f, 0.0f, 1.0f }, // normal 1 { 0.0f, -1.0f, 0.0f, 1.0f }, { 0.0f, -1.0f, 0.0f, 1.0f }, { 0.8944f, 0.4472f, 0.0f, 1.0f }, // normal 2 { 0.8944f, 0.4472f, 0.0f, 1.0f }, { 0.8944f, 0.4472f, 0.0f, 1.0f }, { -0.0f, 0.4472f, 0.8944f, 1.0f }, // normal 3 { -0.0f, 0.4472f, 0.8944f, 1.0f }, { -0.0f, 0.4472f, 0.8944f, 1.0f }, { -0.8944f, 0.4472f, 0.0f, 1.0f }, // normal 4 { -0.8944f, 0.4472f, 0.0f, 1.0f }, { -0.8944f, 0.4472f, 0.0f, 1.0f }, { 0.0f, 0.4472f, -0.8944f, 1.0f }, // normal 5 { 0.0f, 0.4472f, -0.8944f, 1.0f }, { 0.0f, 0.4472f, -0.8944f, 1.0f }, { 0.0f, -1.0f, 0.0f, 1.0f }, // normal 6 { 0.0f, -1.0f, 0.0f, 1.0f }, { 0.0f, -1.0f, 0.0f, 1.0f } }; GLfloat textureCoords[][2] = { { 0.0319, 0.4192 }, // textureCoord 1 { 0.3546, 0.0966 }, { 0.3546, 0.4192 }, { 0.4223, 0.5177 }, // textureCoord 2 { 0.2541, 0.8753 }, { 0.0996, 0.5116 }, { 0.8047, 0.5250 }, // textureCoord 3 { 0.6434, 0.8857 }, { 0.4820, 0.5250 }, { 0.6637, 0.0981 }, // textureCoord 4 { 0.5130, 0.4184 }, { 0.3748, 0.0926 }, { 0.8416, 0.4227 }, // textureCoord 5 { 0.6922, 0.0988 }, { 0.9834, 0.0954 }, { 0.0319, 0.4192 }, // textureCoord 6 { 0.0319, 0.0966 }, { 0.3546, 0.0966 } }; // Remeber to update the texture image file path for your computer.
// 记住要更新计算机的纹理图像文件路径。
const char *imageFileName = "..\\..\\Images\\marble1.jpg"; const char *projectiveTextureImageName = "..\\..\\Images\\mona_lisa.jpg"; // VBO buffer IDs VBO缓冲区ID GLuint vertexArrayBufferID = 0; GLuint normalArrayBufferID = 0; GLuint texCoordArrayBufferID = 0; GLuint program; // shader program ID 着色器程序ID // Shader variable IDs 着色器变量ID GLint vPos; // vertex attribute: position 顶点属性:位置 GLint normalID; // vertex attribute: normal 顶点属性:正常 GLint textureCoordID; // vertex attribute: texture coordinates 顶点属性:纹理坐标 GLint mvpMatrixID; // uniform variable: model, view, projection matrix 统一变量:模型,视图,投影矩阵 GLint modelMatrixID; // uniform variable: model, view matrix 统一变量:模型,视图矩阵 GLint normalMatrixID; // uniform variable: normal matrix for transforming normals 统一变量:用于转换法线的法线矩阵 GLint textureMatrixID; // uniform variable: texture matrix for calculating texture 统一变量:用于计算纹理的纹理矩阵 // coordinates for projective texture mapping 投影纹理映射的坐标 GLint lightSourcePositionID; // uniform variable: for lighting calculation 统一变量:用于照明计算 GLint diffuseLightProductID; // uniform variable: for lighting calculation GLint ambientID; GLint attenuationAID; GLint attenuationBID; GLint attenuationCID; GLint textureSamplerID; // texture sampler ID 纹理采样器ID GLint projTextureSamplerID; // projective texture sampler ID 投影纹理采样器ID // Texture object ID 纹理对象ID GLuint textureID; GLuint projTextureID; // Texture unit ID 纹理单元ID // These two values must be consistent. 这两个值必须一致。 GLenum textureUnitID = GL_TEXTURE1; // Sometimes, setting this to 0 will connect the sampler to any active texture unit.
// 有时,将此值设置为0会将采样器连接到任何活动纹理单元。
// But it's better to avoid using this "trick".
// 但是最好避免使用此“技巧”。
GLuint textureSamplerValue = 1; // Texture unit ID for the projective texture 投影纹理的纹理单元ID // These two values must be consistent. 这两个值必须一致 GLenum projTextureUnitID = GL_TEXTURE2; // Sometimes, setting this to 0 will connect the sampler to any active texture unit.
// 有时,将此值设置为0会将采样器连接到任何活动纹理单元。
// But it's better to avoid using this "trick". GLuint projTextureSamplerValue = 2; // Transformation matrices mat4 projMatrix; mat4 mvpMatrix; mat4 modelMatrix; mat4 viewMatrix; mat3 normalMatrix; // Normal matrix for transforming normals 用于变换法线的法线矩阵 mat4 textureCoordTransformationMatrix; // Light parameters 灯光参数 vec4 lightSourcePosition = vec4(0.0f, 4.0f, 0.0f, 1.0f); vec4 diffuseMaterial = vec4(0.5f, 0.5f, 0.5f, 1.0f); vec4 diffuseLightIntensity = vec4(1.0f, 1.0f, 1.0f, 1.0f); vec4 ambient = vec4(0.2f, 0.2f, 0.2f, 1.0f); float attenuationA = 1.0f; float attenuationB = 0.2f; float attenuationC = 0.0f; vec4 diffuseLightProduct; // Camera parameters vec3 eyePosition = vec3(0.0f, 0.0f, 4.0f); vec3 lookAtCenter = vec3(0.0f, 0.0f, 0.0f); vec3 upVector = vec3(0.0f, 1.0f, 0.0f); float fieldOfView = 30.0f; float nearPlane = 0.1f; float farPlane = 1000.0f; // Mouse controlled rotation angles 鼠标控制旋转角度 float rotateX = 0; float rotateY = 0; // Projector parameters 投影机参数 // Define the projector's location and orientation.
// 定义投影机的位置和方向。
vec3 projectorPosition = vec3(0.0f, 1.0f, 0.0f); vec3 projectorLookAtPosition = vec3(0.5f, 0.0f, 0.0f); vec3 projectorUpVector = vec3(0.0f, 0.0f, 1.0f); float projectorFOV = 60.0f; //--------------------------------------------------------------- // Initialize vertex arrays and VBOs
// 初始化顶点数组和VBO
void prepareVBOs() { // Define a 3D pyramid. 定义3D金字塔 // Get an unused buffer object name. Required after OpenGL 3.1.
  // 获取未使用的缓冲区对象名称。 在OpenGL 3.1之后需要。
glGenBuffers(1, &vertexArrayBufferID); // If it's the first time the buffer object name is used, create that buffer.
  // 如果是第一次使用缓冲区对象名称,请创建该缓冲区。
glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBufferID); // Allocate memory for the active buffer object. // 1. Allocate memory on the graphics card for the amount specified by the 2nd parameter. // 2. Copy the data referenced by the third parameter (a pointer) from the main memory to the // memory on the graphics card. // 3. If you want to dynamically load the data, then set the third parameter to be NULL.

      //为活动缓冲区对象分配内存。
      // 1.在图形卡上分配第二个参数指定的内存量。
      // 2.将第三个参数(指针)引用的数据从主存储器复制到
      //显卡上的内存。
      // 3.如果要动态加载数据,则将第三个参数设置为NULL。


glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glGenBuffers(1, &normalArrayBufferID); glBindBuffer(GL_ARRAY_BUFFER, normalArrayBufferID); glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW); // Create a buffer object to store the texture coordinates. // Later we will passt his over to the shader.

     //创建一个缓冲区对象以存储纹理坐标。
     //稍后我们将其传递给着色器。


glGenBuffers(1, &texCoordArrayBufferID); glBindBuffer(GL_ARRAY_BUFFER, texCoordArrayBufferID); glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW); } //------------------------------------------------------------------- void prepareShaders() { // Vertex shader source code // The vertex position and normal vector are transformed and then passed on to the fragment shader.
  

    //顶点着色器源代码
    //将顶点位置和法向矢量转换,然后传递到片段着色器。


const char* vSource = { "#version 330\n" "in vec4 vPos;" "in vec4 normal;" "in vec2 vTextureCoord;" "uniform mat4x4 mvpMatrix;" "uniform mat4x4 modelMatrix;" "uniform mat3x3 normalMatrix;" // The model-view-projection matrix for the projector // This matrix is used to calculate the texture coordinates for the vertex.

         //投影机的模型-视图-投影矩阵
         //此矩阵用于计算顶点的纹理坐标。


"uniform mat4x4 textureMatrix;" "out vec4 transformedPosition;" "out vec3 transformedNormal;" "out vec2 textureCoord;" "out vec4 textureCoordProj;" "void main() {" " gl_Position = mvpMatrix * vPos;" // Transform the vertex position to the world space.
// //将顶点位置转换为世界空间。
" transformedPosition = modelMatrix * vPos;" // Transform the normal vector to the world space.
// 将法线向量转换为世界空间。
" transformedNormal = normalize(normalMatrix * normal.xyz);" " textureCoord = vTextureCoord;" // Calculates the texture coordinates for the vertex // Project the vertex to a 2D picture and then take the 2D coordinates as // the texture coordinates.
// 计算顶点的纹理坐标
// 将顶点投影到2D图片,然后将2D坐标作为
// 纹理坐标。
" textureCoordProj = textureMatrix * modelMatrix * vPos;" // If modelMatrix is removed from this calculation, the projected texture will // "stick" to the object, rather than be fixed in space. This is called texture decal. // " textureCoordProj = textureMatrix * vPos;"

          //如果从此计算中删除了modelMatrix,则投影的纹理将
           //“粘贴”到对象,而不是固定在空间中。 这称为纹理贴花。
           //“ textureCoordProj = textureMatrix * vPos;”


"}" }; // Fragment shader source code // A point light source is implemented. // For simplicity, only the ambient and diffuse components are implemented. // The lighting is calculated in world space, not in camera space. // Note that the transformedPosition and transformedNormal in the fragment shader are for each fragment (pixel). // They are interpolated from the vertex positions and vertex normals in the (invisible) rasterization stage.
  

    //片段着色器源代码
    //实现点光源。
    //为简单起见,仅实现了环境和漫反射组件。
    //光照是在世界空间而不是摄影机空间中计算的。


    //请注意,片段着色器中的transformdPosition和transformedNormal是针对每个片段(像素)的。
    //它们是在(不可见的)光栅化阶段从顶点位置和顶点法线插值的。


const char* fSource = { "#version 330\n" "in vec4 transformedPosition;" "in vec3 transformedNormal;" "in vec2 textureCoord;" "in vec4 textureCoordProj;" "uniform vec4 lightSourcePosition;" "uniform vec4 diffuseLightProduct;" "uniform vec4 ambient;" "uniform float attenuationA;" "uniform float attenuationB;" "uniform float attenuationC;" // Don't use the reserved word "texture" as variable name.
     //不要使用保留字“ texture”作为变量名。
"uniform sampler2D tex;" // Regular texture image 常规纹理图像 "uniform sampler2D texProj;" // Projected texture image 投影的纹理图像 "out vec4 fragColor;" "void main() {" // Light direction 灯光方向 " vec3 lightVector = normalize(transformedPosition.xyz - lightSourcePosition.xyz);" // Distance between the light source and vertex 光源和顶点之间的距离 " float dist = distance(lightSourcePosition.xyz, transformedPosition.xyz);" // Attenuation factor 衰减系数 " float attenuation = 1.0f / (attenuationA + (attenuationB * dist) + (attenuationC * dist * dist));" // Calculate the diffuse component of the lighting equation. 计算照明方程的漫反射分量。 " vec4 diffuse = attenuation * (max(dot(transformedNormal, lightVector), 0.0) * diffuseLightProduct);" // For regular texture mapping 用于常规纹理映射 " vec4 textureColor = texture(tex, textureCoord);" // For perspective projection effect 透视投影效果 " vec4 textureColorProj = textureProj(texProj, textureCoordProj);" // Combine the ambient component and diffuse component. 合并环境成分和扩散成分。 " vec4 lightTextureMix = mix((ambient + diffuse), textureColor, 0.6f);" " fragColor = mix(lightTextureMix, textureColorProj, 0.4f);" "}" }; // Declare shader IDs 声明着色器ID GLuint vShader, fShader; // Create empty shader objects 创建空的着色器对象 vShader = glCreateShader(GL_VERTEX_SHADER); checkGlCreateXError(vShader, "vShader"); fShader = glCreateShader(GL_FRAGMENT_SHADER); checkGlCreateXError(fShader, "fShader"); // Attach shader source code the shader objects 附加着色器源代码着色器对象 glShaderSource(vShader, 1, &vSource, NULL); glShaderSource(fShader, 1, &fSource, NULL); // Compile shader objects 编译着色器对象 glCompileShader(vShader); printShaderInfoLog(vShader); glCompileShader(fShader); printShaderInfoLog(fShader); // Create an empty shader program object 创建一个空的着色器程序对象 program = glCreateProgram(); checkGlCreateXError(program, "program"); // Attach vertex and fragment shaders to the shader program
// 将顶点和片段着色器附加到着色器程序
glAttachShader(program, vShader); glAttachShader(program, fShader); // Link the shader program
// 链接着色器程序
glLinkProgram(program); printShaderProgramInfoLog(program); } //--------------------------------------------------------------- // Retrieve the IDs of the shader variables. Later we will // use these IDs to pass data to the shaders.
// 检索着色器变量的ID。 稍后,我们将使用这些ID将数据传递到着色器。
void getShaderVariableLocations(GLuint shaderProgram) { // Retrieve the ID of a vertex attribute, i.e. position 检索顶点属性的ID,即位置 vPos = glGetAttribLocation(shaderProgram, "vPos"); checkGlGetXLocationError(vPos, "vPos"); normalID = glGetAttribLocation(shaderProgram, "normal"); checkGlGetXLocationError(normalID, "normal"); // get the ID of the texture coordinate variable in the shader.
// 获取着色器中纹理坐标变量的ID。
textureCoordID = glGetAttribLocation(shaderProgram, "vTextureCoord"); checkGlGetXLocationError(textureCoordID, "vTextureCoord"); mvpMatrixID = glGetUniformLocation(shaderProgram, "mvpMatrix"); checkGlGetXLocationError(mvpMatrixID, "mvpMatrix"); modelMatrixID = glGetUniformLocation(shaderProgram, "modelMatrix"); checkGlGetXLocationError(modelMatrixID, "modelMatrix"); normalMatrixID = glGetUniformLocation(shaderProgram, "normalMatrix"); checkGlGetXLocationError(normalMatrixID, "normalMatrix"); lightSourcePositionID = glGetUniformLocation(shaderProgram, "lightSourcePosition"); checkGlGetXLocationError(lightSourcePositionID, "lightSourcePosition"); diffuseLightProductID = glGetUniformLocation(shaderProgram, "diffuseLightProduct"); checkGlGetXLocationError(diffuseLightProductID, "diffuseLightProduct"); ambientID = glGetUniformLocation(shaderProgram, "ambient"); checkGlGetXLocationError(ambientID, "ambient"); attenuationAID = glGetUniformLocation(shaderProgram, "attenuationA"); checkGlGetXLocationError(attenuationAID, "attenuationA"); attenuationBID = glGetUniformLocation(shaderProgram, "attenuationB"); checkGlGetXLocationError(attenuationBID, "attenuationB"); attenuationCID = glGetUniformLocation(shaderProgram, "attenuationC"); checkGlGetXLocationError(attenuationCID, "attenuationC"); // get the ID of the texture sampler in the shader.
// 获取着色器中纹理采样器的ID。
textureSamplerID = glGetUniformLocation(shaderProgram, "tex"); checkGlGetXLocationError(textureSamplerID, "tex"); textureMatrixID = glGetUniformLocation(shaderProgram, "textureMatrix"); checkGlGetXLocationError(textureMatrixID, "textureMatrix"); projTextureSamplerID = glGetUniformLocation(shaderProgram, "texProj"); checkGlGetXLocationError(projTextureSamplerID, "texProj"); } //--------------------------------------------------------------- void setShaderVariables() { // value_ptr is a glm function
// value_ptr是glm函数
glUniformMatrix4fv(mvpMatrixID, 1, GL_FALSE, value_ptr(mvpMatrix)); glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, value_ptr(modelMatrix)); glUniformMatrix3fv(normalMatrixID, 1, GL_FALSE, value_ptr(normalMatrix)); glUniformMatrix4fv(textureMatrixID, 1, GL_FALSE, value_ptr(textureCoordTransformationMatrix)); glUniform4fv(lightSourcePositionID, 1, value_ptr(lightSourcePosition)); glUniform4fv(diffuseLightProductID, 1, value_ptr(diffuseLightProduct)); glUniform4fv(ambientID, 1, value_ptr(ambient)); glUniform1f(attenuationAID, attenuationA); glUniform1f(attenuationBID, attenuationB); glUniform1f(attenuationCID, attenuationC); // Specify the current active texture unit number. // // There are certain number of texture units on the graphics card (for example 32). // Check OpenGL extension viewer to find out how many texture units are on your card. // // The shader accesses the texture through texture units, not the texture IDs. // In other words, the shader does not know the texture IDs; it only sees // (for example) 32 texture units. // You can have more than 32 texture images stored in the graphics card's memory, but // at any given time, the shader only sees 32 texture units. In the OpenGL program, // you can associate a texture unit with any texture ID, and change it at any time. // This is how you can transfer potentially large numbers of texture images to the // shader through a limited channel.
  

      //指定当前的活动纹理单位编号。


     //图形卡上有一定数量的纹理单位(例如32)。
     //检查OpenGL扩展查看器,找出卡上有多少个纹理单位。
     //
    //着色器通过纹理单位而不是纹理ID访问纹理。
    //换句话说,着色器不知道纹理ID。 例如,它只能看到32个纹理单位。
    //您可以在图形卡的内存中存储32个以上的纹理图像,但是
     //在任何给定时间,着色器只能看到32个纹理单位。 在OpenGL程序中
     //您可以将纹理单元与任何纹理ID关联,并随时更改它。
     //通过这种方式,您可以通过有限的通道将大量的纹理图像传输到着色器。

// 
    glActiveTexture(textureUnitID);

    // Bind the texture ID with the active texture unit number. 
    // In this case, texture ID "textureID" is associated with texture unit #2. 
    // When the shader reads texture unit #2, it will read the texture identified by ID textureID. 

    //将纹理ID与活动的纹理单位编号绑定。
    //在这种情况下,纹理ID“ textureID”与纹理单元#2相关联。
    //当着色器读取纹理单元#2时,它将读取ID TextureID标识的纹理。


glBindTexture(GL_TEXTURE_2D, textureID); // Associate texture sampler ID in the shader with the active texture unit number. // glActiveTexture() function and glUniform1i(textUnit, ...) function calls must be consistent. // If you change texture unit number in one function all, you must change the texture unit // in the other function call.

    //将着色器中的纹理采样器ID与活动的纹理单位编号相关联。
    // glActiveTexture()函数和glUniform1i(textUnit,...)函数调用必须保持一致。
    //如果您在一项功能中更改了纹理单位编号,则必须更改纹理单位
    //在另一个函数调用中。


glUniform1i(textureSamplerID, textureSamplerValue); glActiveTexture(projTextureUnitID); glBindTexture(GL_TEXTURE_2D, projTextureID); glUniform1i(projTextureSamplerID, projTextureSamplerValue); } //--------------------------------------------------------------- // Set lighting related parameters
// //设置照明相关参数
void setLightingParam() { diffuseLightProduct = diffuseMaterial * diffuseLightIntensity; } void prepareTextureImage() { // Use SOIL to load a picture. 使用SOIL加载图片 textureID = SOIL_load_OGL_texture(imageFileName, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y); // Adding SOIL_FLAG_MIPMAPS is also fine. 添加SOIL_FLAG_MIPMAPS也可以。 // SOIL will call glGenTexture() and glTexImage2D() to specify textures. SOIL将调用glGenTexture()和glTexImage2D()来指定纹理。 // If textureID is 0, then there is an error. 如果textureID为0,则存在错误。 checkGlCreateXError(textureID, "textureID"); projTextureID = SOIL_load_OGL_texture(projectiveTextureImageName, SOIL_LOAD_RGBA, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); // SOIL will call glGenTexture() and glTexImage2D() to specify textures.
// SOIL将调用glGenTexture()和glTexImage2D()来指定纹理。
// If textureID is 0, then there is an error. 如果textureID为0,则存在错误。 checkGlCreateXError(projTextureID, "projTextureID"); } //--------------------------------------------------------------- // Build the model matrix. This matrix will transform the 3D object to the proper place.
// 建立模型矩阵。 该矩阵会将3D对象转换到正确的位置
mat4 buildModelMatrix() { mat4 rotationXMatrix = rotate(mat4(1.0f), radians(rotateX), vec3(1.0f, 0.0f, 0.0f)); mat4 rotationYMatrix = rotate(mat4(1.0f), radians(rotateY), vec3(0.0f, 1.0f, 0.0f)); mat4 matrix = rotationYMatrix * rotationXMatrix; return matrix; } //--------------------------------------------------------------- // This function build a view-projection matrix from a // projector's viewpoint. mat4 buildProjectorMatrices() { // Construct a view-projection matrix as if the camera is placed at the projector. // If we use this view-projection matrix to transform the object, the object will // be projected from the projector to a 2D space, which is the texture space // for the projector view. The texture coordinates in this 2D space are the // texture coordinates for the projective texture. // The view matrix from the projector's viewpoint. mat4 projectorViewMatrix = lookAt(projectorPosition, projectorLookAtPosition, projectorUpVector); // The projection matrix for the projector. mat4 projectorProjectionMatrix = perspective(projectorFOV, 1.0f, 0.5f, 10.0f); // mat4 projectorProjectionMatrix = ortho(0.3f, 0.3f, 0.3f, 0.0f, 0.5f, 10.0f); // After the initial projection, the origin is at the center of the window. // However, the origin of a texture image is at the lower left corner. // The scale and bias matrix is used to transform the origin from the center // to the corner. mat4 scaleBiasMatrix = scale(translate(mat4(1.0f), vec3(0.5, 0.5, 0.5)), vec3(0.5f)); // Construct the combined matrix to transform the vertex position to its projective // texture coordiantes. mat4 projectorTransformMatrix = scaleBiasMatrix * projectorProjectionMatrix * projectorViewMatrix; return projectorTransformMatrix; } //--------------------------------------------------------------- void buildMatrices() { modelMatrix = buildModelMatrix(); mvpMatrix = projMatrix * viewMatrix * modelMatrix; normalMatrix = column(normalMatrix, 0, vec3(modelMatrix[0][0], modelMatrix[0][1], modelMatrix[0][2])); normalMatrix = column(normalMatrix, 1, vec3(modelMatrix[1][0], modelMatrix[1][1], modelMatrix[1][2])); normalMatrix = column(normalMatrix, 2, vec3(modelMatrix[2][0], modelMatrix[2][1], modelMatrix[2][2])); // Use glm::inverseTranspose() to create a normal matrix, which is used to transform normal vectors. normalMatrix = inverseTranspose(normalMatrix); textureCoordTransformationMatrix = buildProjectorMatrices(); } //--------------------------------------------------------------- // Handles the display event void display() { // Clear the window with the background color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); buildMatrices(); setShaderVariables(); // Activate the shader program glUseProgram(program); // If the buffer object already exists, make that buffer the current active one. // If the buffer object name is 0, disable buffer objects. glBindBuffer(GL_ARRAY_BUFFER, vertexArrayBufferID); // Associate the vertex array in the buffer object with the vertex attribute: "position" glVertexAttribPointer(vPos, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); // Enable the vertex attribute: "position" glEnableVertexAttribArray(vPos); glBindBuffer(GL_ARRAY_BUFFER, normalArrayBufferID); glVertexAttribPointer(normalID, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glEnableVertexAttribArray(normalID); // Associate the texture coordinate array in the buffer object with the vertex attribute "vTextureCoord", // which is identified by texCoordID. glBindBuffer(GL_ARRAY_BUFFER, texCoordArrayBufferID); glVertexAttribPointer(textureCoordID, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glEnableVertexAttribArray(textureCoordID); // Start the shader program. Draw the object. The third parameter is the number of vertices. glDrawArrays(GL_TRIANGLES, 0, numVertices); // Refresh the window glutSwapBuffers(); checkOpenGLError(); } //--------------------------------------------------------------- // Handles the reshape event void reshape(int width, int height) { // Specify the width and height of the picture within the window glViewport(0, 0, width, height); projMatrix = perspective(fieldOfView, (float)width / (float)height, nearPlane, farPlane); viewMatrix = lookAt(eyePosition, lookAtCenter, upVector); } //--------------------------------------------------------------- // Read mouse motion data and convert them to rotation angles. void passiveMotion(int x, int y) { rotateY = (float)x * -0.5f; rotateX = (float)y * 0.5f; // Generate a dislay event to force refreshing the window. glutPostRedisplay(); } //----------------------------------------------------------------- void init() { prepareVBOs(); prepareShaders(); getShaderVariableLocations(program); setLightingParam(); prepareTextureImage(); // Specify the background color glClearColor(1, 1, 1, 1); glEnable(GL_DEPTH_TEST); // Most of the OpenGL API calls are made from this function. // So we need to check error here. checkOpenGLError(); } //--------------------------------------------------------------- void main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Projective texture mapping"); glutReshapeWindow(800, 800); glewInit(); initOpenGLDebugContext(true); init(); // Register the display callback function glutDisplayFunc(display); // Register the reshape callback function glutReshapeFunc(reshape); // Register the passive mouse motion call back function // This function is called when the mouse moves within the window // while no mouse buttons are pressed. glutPassiveMotionFunc(passiveMotion); // Start the event loop glutMainLoop(); }

 

posted @ 2020-10-16 15:53  yiwenzhang  阅读(674)  评论(0编辑  收藏  举报