游戏中主角被遮挡解决方法

玩家被遮挡怎么办?这篇教程帮助你!

Featured image

在游戏中,经常出现镜头面前被操纵角色被其他物体遮挡而影响操作的问题,一般有以下三种解决方法:

接下来我将使用opengl,来实现第三中解决方法!

以马里欧奥德赛为例,当马里奥被石柱遮挡时,将显示一个主角的裁影

马里奥奥德赛

分析

要想实现这个效果,需要得到以下信息:

知识点

实现原理

实现该效果的原理不复杂,我们只需要 在渲染正常角色时,若没有通过深度测试但通过了模板测试写入一个模板值, 之后再通过之前写入的模板值渲染裁剪效果,具体做法大致如下:

  1. 清除模板缓冲
  2. 设置模板写入参数,当模板和深度都通过时,就写入1
  3. 启用模板函数,设定为ALWAYS, 将模板值写入到片元中
  4. 渲染角色
  5. 设置模板写入参数,当模板和深度都通过时,写入0,
  6. 渲染场景
  7. 禁用深度测试和模板写入,启用模板函数
  8. 在一次渲染角色,这次使用裁剪效果
  9. 重新启用模板写入和深度测试

开始实现吧!

首先搭建一个简单的场景,我们将mur猫作为游戏的主角: 场景样式 再一个制作裁剪效果的shader,这里比较简单,单纯选择一个突出的颜色:

// vertex Shader
#version 330 core

layout(location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection *view *vec4(vec3(model *vec4(aPos,1.0)),1.0);
}
// fragment Shader
#version 330 core
out vec4 FragColor;



void main()
{
    FragColor = vec4(1,0.714,0.7569,1); // 将向量的四个分量全部设置为1.0
}

结果如下: shader效果

接下来编写渲染代码:

//...
	// 材质设置 ......
	shader->use();
	shader->setInt("shadowMap", 10);
	shader->setMat4("lightSpaceMatrix", lightProjection * view);
	glActiveTexture(GL_TEXTURE10);
	glBindTexture(GL_TEXTURE_2D, DepthMap);
	//...... 材质设置
	view = camera.GetViewMatrix();


	// 开启模板测试
	glEnable(GL_STENCIL_TEST);
	glStencilMask(0xff);
	// 开启深度测试
	glEnable(GL_DEPTH_TEST);
	// 清除模板缓冲、颜色缓冲和深度缓冲
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


	// 设置写入规则,当深度和模板都测试成功则写入1
	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
	// 启用渲染测试函数,这里设置为always,表示深度测试永远通过
	glStencilFunc(GL_ALWAYS, 1, 0xFF);
	// 绘制角色
	murCat->Draw(*shader, view, projection);
	
	// 设置写入规则,当深度和模板都测试成功则写入0,其他保持原样,由于上面启用了Always,这里就不再重复
	glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
	// 正常渲染场景
	drawScene(shader, view, projection);

	/*接下来渲染角色的剪影*/
	glStencilFunc(GL_EQUAL, 0, 0xFF);
	glStencilMask(0x00);
	// 关闭深度测试,由于剪影一直渲染在屏幕的顶部
	glDisable(GL_DEPTH_TEST);
	// 使用剪影材质渲染角色
	murCat->Draw(*clipShader, view, projection);
	glStencilMask(0xFF);
	glEnable(GL_DEPTH_TEST);
	glDisable(GL_STENCIL_TEST);
//...

最终结果如下: shader效果

是不是很完美O(∩_∩)O~~当然,您也可以加一些贴图在上面,使得该效果更加炫酷,

加油!