Vulkan_模板测试运用1(轮廓绘制)

关于模板测试的概念和原理就不再赘述,具体可参照LearnOpenGL CN 模板测试章节
在这里插入图片描述

一、轮廓绘制原理

为物体创建轮廓的步骤如下:

  1. 在绘制(需要添加轮廓的)物体之前,将模板函数设置为VK_COMPARE_OP_ALWAYS,每当物体的片段被渲染时,将模板缓冲更新为1。
  2. 渲染物体。
  3. 禁用模板写入以及深度测试。
  4. 将每个物体缩放一点点。
  5. 使用一个不同的片段着色器,输出一个单独的(边框)颜色。
  6. 再次绘制物体,但只在它们片段的模板值不等于1时才绘制。
  7. 再次启用模板写入和深度测试。

因为要绘制物体轮廓那么在场景中分别画了两遍模型,第一次是原始的模型,第二遍是带有模板写入并且是带有纯色模型。最后是对原物体关闭深度测试,不写入模板测试,而对第二遍绘制的模型对其位置进行了法线方向的移动。

二、vulkan实现

2.1 管线布局

		// 模型管线及模板填充
		shaderStages[0] = loadShader(getShadersPath() + "model.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
		shaderStages[1] = loadShader(getShadersPath() + "model.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
		rasterizationState.cullMode = VK_CULL_MODE_NONE;
		depthStencilState.stencilTestEnable = VK_TRUE;
		// 在物体片段被渲染时,总是将模板缓冲更新为1
		depthStencilState.back.compareOp = VK_COMPARE_OP_ALWAYS;
		depthStencilState.back.failOp = VK_STENCIL_OP_REPLACE;
		depthStencilState.back.depthFailOp = VK_STENCIL_OP_REPLACE;
		depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE;
		depthStencilState.back.compareMask = 0xff;
		depthStencilState.back.writeMask = 0xff;
		depthStencilState.back.reference = 1;
		depthStencilState.front = depthStencilState.back;
		vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.stencil);
		// 轮廓管线
		// 如果新片段的深度值不等于旧片段的深度值时(针对外扩部分)
		depthStencilState.back.compareOp = VK_COMPARE_OP_NOT_EQUAL;
		depthStencilState.back.failOp = VK_STENCIL_OP_KEEP;
		depthStencilState.back.depthFailOp = VK_STENCIL_OP_KEEP;
		depthStencilState.back.passOp = VK_STENCIL_OP_REPLACE;
		depthStencilState.front = depthStencilState.back;
		depthStencilState.depthTestEnable = VK_FALSE;
		shaderStages[0] = loadShader(getShadersPath() + "outline.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
		shaderStages[1] = loadShader(getShadersPath() + "outline.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
		vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelines.outline);
	

此处使用了两个管线,并具体可以看出其管线深度测试的开启关闭模式,第一个管线为正常渲染模型管线(简单的光照模型管线不再赘述),第二个管线为针对轮廓处理的模型(偏移固定轮廓宽度)。

2.2 轮廓管线

轮廓管线很简单:在顶点着色器中进行偏移,片元着色器中进行纯色输出。
顶点着色器:

#version 450

layout (location = 0) in vec4 inPos;
layout (location = 2) in vec3 inNormal;

layout (binding = 0) uniform UBO 
{
	mat4 projection;
	mat4 model;
	vec4 lightPos;
	float outlineWidth;
} ubo;

out gl_PerVertex
{
	vec4 gl_Position;
};

void main() 
{
	// 轮廓偏移
	vec4 pos = vec4(inPos.xyz + inNormal * ubo.outlineWidth, inPos.w);
	gl_Position = ubo.projection * ubo.model * pos;
}

片元着色器:

#version 450

layout (location = 0) out vec4 outFragColor;

void main() 
{
	// 纯色输出
	outFragColor = vec4(vec3(0.55,1.0,0.0), 1.0); 
}

可分别进行渲染输入对比如下:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值