opengl之几何着色器(爆破物体)

爆破物体

opengl官方文档之几何着色器

  • 尽管绘制房子非常有趣,但我们不会经常这么做。这也是为什么我们接下来要继续深入,来爆破(Explode)物体!虽然这也是一个不怎么常用的东西,但是它能向你展示几何着色器的强大之处。

    当我们说爆破一个物体时,我们并不是指要将宝贵的顶点集给炸掉,我们是要将每个三角形沿着法向量的方向移动一小段时间。效果就是,整个物体看起来像是沿着每个三角形的法线向量爆炸一样。爆炸三角形的效果在纳米装模型上看起来像是这样的:

  • 因为每一个点的法线值和面的法线值是不一样的,所以我们要自己进行计算

过程(教程中的例子)

  • 顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout(location  = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;//纹理坐标

out VS_OUT {
    vec2 texCoords;
	vec3 normal;
} vs_out;
//这里使用了uniform 缓冲对象
layout (std140) uniform Matrices
{
    mat4 projection;
};
uniform mat4 view;
uniform mat4 model;

void main()
{
	vs_out.normal = mat3(transpose(inverse(model)))*aNormal;//因为旋转的时候法向量是要变的,考虑到等比例缩放这里需要给值(光照理论的部分也用到了)
    vs_out.texCoords = aTexCoords;
    gl_Position = projection * view * model * vec4(aPos, 1.0); 
}
  • 片段着色器
#version 330 core

out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture_diffuse1;

void main()
{
    FragColor = texture(texture_diffuse1, TexCoords);	//根据纹理坐标放到像素上
}

  • 几何着色器:获取法向量函数
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

in VS_OUT {
    vec2 texCoords;
		vec3 normal;
} gs_in[];

out vec2 TexCoords; 

uniform float time;

//根据时间来计算新的位置
vec4 explode(vec4 position, vec3 normal)
{
    float magnitude = 2.0;
    vec3 direction = normal * ((sin(time) + 1.0) / 2.0) * magnitude; 
    return position + vec4(direction, 0.0);	//返回新的位置
}

//获取法向量函数
//因为每一个点的法线值和面的法线值是不一样的,所以我们要自己进行计算
vec3 GetNormal()
{	
	//3个点,通过右手法则来进行计算
    vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
    vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
    return normalize(cross(b, a));	
}

void main() {    

	//一个一个点来进行计算位置的值和颜色,然后发布褚图元
    vec3 normal = -GetNormal();
	//normal=-gs_in[0].normal;	//看一下使用点的法向有什么不同
    gl_Position = explode(gl_in[0].gl_Position, normal);
    TexCoords = gs_in[0].texCoords;
    EmitVertex();
	//normal=-gs_in[1].normal;
    gl_Position = explode(gl_in[1].gl_Position, normal);
    TexCoords = gs_in[1].texCoords;
    EmitVertex();
	//normal=-gs_in[2].normal;
    gl_Position = explode(gl_in[2].gl_Position, normal);
    TexCoords = gs_in[2].texCoords;
    EmitVertex();
    EndPrimitive();
}
  • 主函数
int main()
{ 
	GLFWwindow* window=init();

	Shader skyboxShader("skybox.vert","skybox.frag");
	Shader geoShader("geometry_shader.vert", "geometry_shader.frag", "geometry_shader.glsl");//这里不适用cube进行着色
	//glPolygonMode(GL_FRONT_AND_BACK,/*GL_FILL*/GL_LINE);
	glfwSetScrollCallback(window,scroll_callback);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_STENCIL_TEST);
	glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
	//glEnable(GL_PROGRAM_POINT_SIZE);

	Model ourModel("D:/openGLResource/bin/nanosuit/nanosuit.obj");
	
	_models.insert(pair<string,pair<glm::vec3,Model>>("Zhang3",pair<glm::vec3,Model>(cubePositions[0],ourModel)));
	_models["Li4"]=pair<glm::vec3,Model>(cubePositions[2],ourModel);

    unsigned int skyboxVAO, skyboxVBO;
    glGenVertexArrays(1, &skyboxVAO);
    glGenBuffers(1, &skyboxVBO);
    glBindVertexArray(skyboxVAO);
    glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	vector<std::string> faces;
	faces.push_back("skybox/right.jpg");
	faces.push_back("skybox/left.jpg");
	faces.push_back("skybox/top.jpg");
	faces.push_back("skybox/bottom.jpg");
	faces.push_back("skybox/front.jpg");
	faces.push_back("skybox/back.jpg");

	unsigned int cubemapTexture=loadCubemap(faces);
	unsigned int uboExampleBlock;
	glGenBuffers(1, &uboExampleBlock);
	glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
	glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), NULL, GL_STATIC_DRAW); // 分配152字节的内存
	glBindBuffer(GL_UNIFORM_BUFFER, 0);
	glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboExampleBlock, 0, sizeof(glm::mat4));

	while(!glfwWindowShouldClose(window))
	{
		currentFrame=glfwGetTime();
		deltaTime=currentFrame-lastFrame;
		lastFrame=currentFrame;

		processInput(window);
		float radius=10.0f;
		float camX=sin(glfwGetTime())*radius;
		float camZ=cos(glfwGetTime())*radius;

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);


		glm::mat4 trans=glm::mat4(1.0f);
		model=glm::mat4(1.0f);
		view=glm::mat4(1.0f);
		view=camera.GetViewMatrix();
		projection=glm::mat4(1.0f);;
		projection=glm::perspective(glm::radians(camera.fov),800.0f/600.0f,near,far);
		//深度缓冲处理
		glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
		glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), &projection, GL_STATIC_DRAW); 
		glBindBuffer(GL_UNIFORM_BUFFER, 0);
		
		//给几何着色器的shader传值
		geoShader.useShader();
		geoShader.setMat4("view",view);
		geoShader.setFloat("time", glfwGetTime());

		for(_modelsIter=_models.begin();_modelsIter!=_models.end();_modelsIter++)
		{
				model=glm::translate(trans,_modelsIter->second.first);
				model=glm::rotate(model,(float)glfwGetTime(),glm::vec3(0.0f,1.0f,0.0f));
				geoShader.useShader();
				geoShader.setMat4("model",model);
				_modelsIter->second.second.Draw(geoShader);	
		}

		glDepthFunc(GL_LEQUAL);
		skyboxShader.useShader();
		view=glm::mat4(glm::mat3(camera.GetViewMatrix()));
		skyboxShader.setMat4("view",view);
		//skyboxShader.setMat4("projection",projection);
		
		glBindVertexArray(skyboxVAO);
		glBindTexture(GL_TEXTURE_CUBE_MAP,cubemapTexture);
		glDrawArrays(GL_TRIANGLES,0,36);
		glDepthFunc(GL_LESS);
		glBindVertexArray(0);

		glfwPollEvents();
		glfwSwapBuffers(window);

	}
	//退出![请添加图片描述](https://img-blog.csdnimg.cn/322acb8427724a05826a939ade013e2c.gif)

	glfwTerminate();
	return 0;
}
  • 效果
    请添加图片描述
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值