OpenGL GLSL访问纹理

这一节我们给上一节的ADSPhone的程序贴上一张纹理贴图

如下图:

OpenGL GLSL访问纹理_第1张图片



GLSL访问纹理很简单,只需要把要使用的纹理坐标和纹理的对象传入着色器即可

对于本程序,我们把纹理坐标和纹理对象传入顶点着色器ADSTexture.vp中,在片段着色器ADSTexture.fp计算颜色值时 乘上 纹理的颜色值,其余的ADSPhone的程序都一样


下面是顶点着色器ADSTexture.vp的所有代码,每一句都有注释

// 要求OpenGL的版本最低是1.3
#version 130

// 需要从外界传入的字段
//顶点
in vec4 vVertex;
//顶点法线
in vec3 vNormal;
//纹理对象
in vec4 vTexture0;

//模型视图变换矩阵
uniform mat4   mvpMatrix;
//视图变换矩阵
uniform mat4   mvMatrix;
//模型视图变换矩阵法线矩阵
uniform mat3   normalMatrix;
//光源的位置
uniform vec3   vLightPosition;

//需要传入片段着色器的字段
//面法线
smooth out vec3 vVaryingNormal;
//光源的方向
smooth out vec3 vVaryingLightDir;
//纹理坐标
smooth out vec2 vTexCoords;

void main(void) 
    { 
		// 得到法线在照相机坐标系下的位置
		vVaryingNormal = normalMatrix * vNormal;

		// 得到顶点在照相机坐标系下的位置
		vec4 vPosition4 = mvMatrix * vVertex;
		vec3 vPosition3 = vPosition4.xyz / vPosition4.w;

		// 得到光源方向
		vVaryingLightDir = normalize(vLightPosition - vPosition3);

		// 得到纹理坐标
		vTexCoords = vTexture0.st;

		// 把顶点变换到照相机坐标系下
		gl_Position = mvpMatrix * vVertex;
    }

下面是片段着色器ADSTexture.fp的所有代码

#version 130
//传出到光栅化阶段的颜色值
out vec4 vFragColor;

//环境光颜色值
uniform vec4      ambientColor;
//漫反射光颜色值
uniform vec4      diffuseColor;   
//镜面光颜色值
uniform vec4      specularColor;
//纹理对象
uniform sampler2D colorMap;

//从顶点着色器传入的值
//面法线
smooth in vec3 vVaryingNormal;
//光源的方向
smooth in vec3 vVaryingLightDir;
//纹理坐标
smooth in vec2 vTexCoords;

void main(void)
    { 
		// 计算漫反射光强度
		float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));

		// 漫反射光强度 乘上 漫反射光颜色值
		vFragColor = diff * diffuseColor;

		// 加上环境光颜色值
		vFragColor += ambientColor;

		// 乘上纹理颜色值
		vFragColor *= texture(colorMap, vTexCoords);

		// 加上镜面光颜色值
		vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
		float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
		if(diff != 0) {
			float fSpec = pow(spec, 128.0);
			vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
			}
    }


下面是OpenGL工程中的代码

首先我们来看一下需要包含的头文件和全局变量

#include 	
#include 
#include 
#include 
#include 
#include 

#include 
#define FREEGLUT_STATIC
#include 


GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     sphereBatch;
GLMatrixStack       modelViewMatrix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;

GLuint	ADSTextureShader;	
//着色器中的统一值(uniform)
GLint	locAmbient;			
GLint   locDiffuse;			
GLint   locSpecular;		 
GLint	locLight;		
GLint	locMVP;				
GLint	locMV;				
GLint	locNM;				
GLint   locTexture;
//纹理对象
GLuint  texture;


下面是主函数main

int main(int argc, char* argv[])
    {
		//设置工程路径
		gltSetWorkingDirectory(argv[0]);
		//初始化GLUT
		glutInit(&argc, argv);
		//设置需要使用的窗口模式
		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
		//窗口的大小
		glutInitWindowSize(800, 600);
		//窗口的名字
		glutCreateWindow("Lit Texture");
		//窗口大小改变时的回调函数
		glutReshapeFunc(ChangeSize);
		//渲染时的回调函数
		glutDisplayFunc(RenderScene);
		//初始化glew
		GLenum err = glewInit();
		if (GLEW_OK != err) {
			fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
			return 1;
		}
		//初始化函数
		SetupRC();    
		//消息循环
		glutMainLoop();
		//程序退出时的清理工作
		ShutdownRC();
		return 0;
    }

下面是窗口改变时的回调函数ChangeSize

void ChangeSize(int w, int h)
	{
		// Prevent a divide by zero
		if(h == 0)
			h = 1;

		//设置视口大小
		glViewport(0, 0, w, h);
		//设置投影变换矩阵
		viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
		//设置模型变换矩阵
		projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
		transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
	}


下面是初始化函数SetupRC

void SetupRC(void)
	{
		// Background
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_CULL_FACE);

		shaderManager.InitializeStockShaders();
		viewFrame.MoveForward(4.0f);

		//创建小球模型数据
		gltMakeSphere(sphereBatch, 1.0f, 26, 13);
		//加载自己写的着色器
		ADSTextureShader = gltLoadShaderPairWithAttributes("ADSTexture.vp", "ADSTexture.fp", 3, GLT_ATTRIBUTE_VERTEX, "vVertex",
				GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexture0");
		//得到统一值在着色器程序中的位置引用,以便我们给它赋值
		locAmbient = glGetUniformLocation(ADSTextureShader, "ambientColor");
		locDiffuse = glGetUniformLocation(ADSTextureShader, "diffuseColor");
		locSpecular = glGetUniformLocation(ADSTextureShader, "specularColor");
		locLight = glGetUniformLocation(ADSTextureShader, "vLightPosition");
		locMVP = glGetUniformLocation(ADSTextureShader, "mvpMatrix");
		locMV  = glGetUniformLocation(ADSTextureShader, "mvMatrix");
		locNM  = glGetUniformLocation(ADSTextureShader, "normalMatrix");
		locTexture = glGetUniformLocation(ADSTextureShader, "colorMap");
		//创建一个纹理对象
		glGenTextures(1, &texture);
		//绑定一个纹理对象
		glBindTexture(GL_TEXTURE_2D, texture);
		//加载纹理
		LoadTGATexture("CoolTexture.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
	}


下面是纹理加载函数LoadTGATexture

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);
    //设置mip贴图
    if(minFilter == GL_LINEAR_MIPMAP_LINEAR || 
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
        glGenerateMipmap(GL_TEXTURE_2D);
    
	return true;
}


下面是渲染函数RenderScene

void RenderScene(void)
	{
		static CStopWatch rotTimer;

		// Clear the window and the depth buffer
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		
		modelViewMatrix.PushMatrix(viewFrame);
		modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);

		GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };
		GLfloat vAmbientColor[] = { 0.2f, 0.2f, 0.2f, 1.0f };
		GLfloat vDiffuseColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		//绑定纹理对象
		glBindTexture(GL_TEXTURE_2D, texture);
		//使用自己写的着色器
		glUseProgram(ADSTextureShader);
		//设置统一值
		glUniform4fv(locAmbient, 1, vAmbientColor);
		glUniform4fv(locDiffuse, 1, vDiffuseColor);
		glUniform4fv(locSpecular, 1, vSpecularColor);
		glUniform3fv(locLight, 1, vEyeLight);
		glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
		glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
		glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());
			glUniform1i(locTexture, 0);
		//绘制模型
		sphereBatch.Draw();

		modelViewMatrix.PopMatrix();

		glutSwapBuffers();
		glutPostRedisplay();
	}


下面是程序退出时的清理函数ShutdownRC

void ShutdownRC(void)
   {
		//删除纹理对象
		glDeleteTextures(1, &texture);
   }





 






你可能感兴趣的:(OpenGL)