从着色器访问纹理贴图是非常简单的。纹理坐标将会作为属性传递到我们的顶点着色器,在片段着色器当中,这些属性通常是在顶点之间进行平滑插值的。片段着色器使用这些差值纹理坐标来对纹理进行采样。
(1)只处理纹理单元
// The TexturedIdentity Shader
// Vertex Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
//最为简单的纹理渲染器
#version 130
//传递到顶点着色器当中一个顶点坐标
in vec4 vVertex;
//传递到顶点着色器当中一个纹理坐标,注意核心部分就是这个s和t纹理坐标的输入
//顶点属性vTexCoords以及输出变量vVaringTexCoords。用纹理坐标在三角形表面进行差值
//所需要的,就是这些
in vec2 vTexCoords;
smooth out vec2 vVaryingTexCoords;
void main(void)
{
vVaryingTexCoords = vTexCoords;
gl_Position = vVertex;
}
以上就是仅仅处理纹理单元的顶点着色器,在顶点着色器当中,仅仅对顶点坐标以及顶点的纹理坐标s、t进行相应的传递以及处理。因为其为2D纹理图像,所以纹理坐标仅仅包含s、t。
// The TexturedIdentity Shader
// Fragment Shader
// Richard S. Wright Jr.
// OpenGL SuperBible
#version 130
//注意这个新的数据变量类型sample2D
//一个采样器(sample)实际上就是一个这么好设计(使用glUniform1i来设置值)它代表我们将要
//采样的纹理所绑定的纹理单元。sample2D中的2D表示这是一个2D纹理,我们也可以使用1D
//2D或者3D等类型的采样器。 这个值总是设置为0,代表指示纹理单元0。
uniform sampler2D colorMap;
out vec4 vFragColor;
smooth in vec2 vVaryingTexCoords;
void main(void)
{
//将当前传递进片段着色器当中的st纹理坐标和colormap采样进行texture函数
//从而得到最终要进行光栅化的片段颜色。
vFragColor = texture(colorMap, vVaryingTexCoords.st);
}
如上就是纹理坐标的片段着色器,其中仅仅使用了一个texture函数作为fragColor的值。
#pragma comment(lib,"GLTools.lib")
#include <GLTools.h> // OpenGL toolkit
#include <GLShaderManager.h> // Shader Manager Class
#include <GL/glut.h> // Windows FreeGlut equivalent
GLBatch triangleBatch;
GLShaderManager shaderManager;
GLint myTexturedIdentityShader;
GLuint textureID;
///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
}
// 加载一个tga图像作为一个2D纹理,并且进行必要的初始化
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;
// 读取对应文件当下的图像
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if (pBits == NULL)
return false;
//设置对应图象的功能以及设置环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits);
//在设置完成参数之后,可以释放对应的字符指针
free(pBits);
if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
//生成对应的2维图像
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
///////////////////////////////////////////////////////////////////////////////
// 设置渲染环境
void SetupRC()
{
// 背景
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//渲染器初始化
shaderManager.InitializeStockShaders();
// Load up a triangle
GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f };
GLfloat vTexCoords[] = { 0.0f, 0.0f,
1.0f, 0.0f,