OpenGL GLSL 丢弃片段

在片段着色器中我们可以使用方法discard来丢弃不想绘制出来的片段

比如下面的代码表示当一个片段的alpha值小于0.1时,就不绘制该片段

if(vColorValue.a < 0.1f)
{
     discard;
}

本节我们写一个具有腐蚀效果的例子

如下图:




我们会看到,泳圈模型上有斑点,就像被腐蚀了一样

我们的代码和ADSPhone程序的代码差不多。只是使用了diacard方法而已

下面是具体的代码实现,基本上每一句话都有注释

下面是顶点着色器Dissolve.vp的全部的代码

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

// 需要从外界传入的字段
//顶点
in vec4 vVertex;
//顶点法线
in vec3 vNormal;
//纹理坐标
in vec2 vTexCoords0;


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

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


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

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

		// 得到光源方向
		vVaryingLightDir = normalize(vLightPosition - vPosition3);
		
		// 得到纹理坐标
		vVaryingTexCoord = vTexCoords0.st;

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

下面是片段着色器Dissolve.fp的全部代码

// 要求OpenGL的版本最低是1.3
#version 130
//传出到光栅化阶段的颜色值
out vec4 vFragColor;

//环境光颜色值
uniform vec4      ambientColor;
//漫反射光颜色值
uniform vec4      diffuseColor;   
//镜面光颜色值
uniform vec4      specularColor;
//需要使用的纹理对象
uniform sampler2D  cloudTexture;
//腐蚀值
uniform float      dissolveFactor;

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

void main(void)
    { 
		vec4 vCloudSample = texture(cloudTexture, vVaryingTexCoord);
		//判断是否丢弃片段
		if(vCloudSample.r < dissolveFactor)
			discard;
	   

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

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

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


		// 乘上纹理颜色值
		vFragColor *= vCloudSample;
		
		// 加上镜面光颜色值
		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);
			}
    }


下面是工程中的代码

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

#include <GLTools.h>	
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>

#include <math.h>
#define FREEGLUT_STATIC
#include <GL/glut.h>


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

GLuint	ADSDissloveShader;	
//着色器uniform值
GLint	locAmbient;			
GLint   locDiffuse;			
GLint   locSpecular;		
GLint	locLight;			
GLint	locMVP;				
GLint	locMV;				
GLint	locNM;				
GLint	locTexture;			
GLint   locDissolveFactor;  
//纹理对象
GLuint	cloudTexture;


下面是主函数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)
{
	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);

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

		// 生成小球模型数据
		gltMakeTorus(torusBatch, .80f, 0.25f, 52, 26);
		//加载自己写的着色器程序
		ADSDissloveShader = gltLoadShaderPairWithAttributes("Dissolve.vp", "Dissolve.fp", 3, GLT_ATTRIBUTE_VERTEX, "vVertex",
				GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoords0");

		//得到着色器中的uniform值的位置引用,以便对它赋值
		locAmbient = glGetUniformLocation(ADSDissloveShader, "ambientColor");
		locDiffuse = glGetUniformLocation(ADSDissloveShader, "diffuseColor");
		locSpecular = glGetUniformLocation(ADSDissloveShader, "specularColor");
		locLight = glGetUniformLocation(ADSDissloveShader, "vLightPosition");
		locMVP = glGetUniformLocation(ADSDissloveShader, "mvpMatrix");
		locMV  = glGetUniformLocation(ADSDissloveShader, "mvMatrix");
		locNM  = glGetUniformLocation(ADSDissloveShader, "normalMatrix");
		locTexture = glGetUniformLocation(ADSDissloveShader, "cloudTexture");
		locDissolveFactor = glGetUniformLocation(ADSDissloveShader, "dissolveFactor");
		//创建一个纹理对象
		glGenTextures(1, &cloudTexture);
		//绑定纹理对象
		glBindTexture(GL_TEXTURE_1D, cloudTexture);
		//加载纹理
		LoadTGATexture("Clouds.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.1f, 0.1f, 0.1f, 1.0f };
		GLfloat vDiffuseColor[] = { 0.1f, 1.0f, 0.1f, 1.0f };
		GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		//使用自己写的着色器
		glUseProgram(ADSDissloveShader);
		//设置着色器中的uniform值
		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, 1);
		//在十秒之内 生成0-1的数值,然后赋值给locDissolveFactor
		//GetElapsedSeconds函数表示自程序运行以来一共过去了多长时间
		//fmod是一个求余函数 既x/y的余数
		float fFactor = fmod(rotTimer.GetElapsedSeconds(), 10.0f);
		fFactor /= 10.0f;
		//设置统一值locDissolveFactor
		glUniform1f(locDissolveFactor, fFactor);
		//绘制模型
		torusBatch.Draw();

		modelViewMatrix.PopMatrix();


		glutSwapBuffers();
		glutPostRedisplay();
	}

















  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值