OpenGL游戏引擎开发[10]-多重纹理

简介

有时候我们在游戏,会看到类似这样裸露的土地、沼泽之类的:

这是游戏《自然之力》的地图,在草地上会有“粘土”、“黑土”这样裸露的区域,玩家能够在这片区域挖土,不同的材料可以制作不同的道具。

那这个是怎么做的呢?

  • 最粗暴的办法,就是画一个这样的纹理,贴到地形上
  • 还有一种就是使用几种不同的纹理对地形进行混合贴图

比如,unity中刷地形的时候,就是使用第二种办法,事先加载好纹理,再使用“刷子”在地形上画对应的纹理贴图。

这节我们使用代码来实现这样的效果。

原理

原理很简单,就是取不同的纹理贴图的颜色,使用一张混合贴图将这些颜色进行混合。后面我们结合代码来讲具体的过程。

实现

实现好的效果是这样的。

首先我们写一个多重纹理类来保存我们需要使用到的纹理:

接着,我们在片段着色器中计算混合的纹理颜色:

我们想要实现的效果是,在一片绿油油的草地上,有裸露的土地和道理,那么地形的整体背景应该是“草”,对应混合贴图 blendMap 中的黑色背景。 为啥是黑色背景,而不是透明背景? 因为黑色背景 r=g=b=0 这样,我们计算的时候就比较方便了,因为任何颜色值乘以0还是0,这样就很容易过滤掉其他的颜色。

接下来我们逐行代码解释:

1// pass_textureCoordinates 为整个地形块的纹理坐标
2// 对混合贴图 blendMap 采样也使用这个纹理坐标,因为 混合贴图代表着最终地形的贴图是啥样的
3vec4 blendMapColor = texture(blendMap, pass_textureCoordinates);
1// 过滤掉混合贴图中的其他颜色,主要是为了贴地形的背景纹理
2float backTextureAmount = 1 - (blendMapColor.r +  blendMapColor.g + blendMapColor.b);

看在ps中使用颜色拾取器,查看混合贴图中每个像素的颜色,可以发现这个像素要么是纯色的,要么是两种颜色的混合。注意,这里的像素值是0-255,在片段着色器中是0-1,就是除以了255归一化了而已。

根据这个,我们可以发现,混合贴图中任意一点的像素r,g,b通道的值加起来不会超过255(在片段着色器中不会超过1)。

那么backTextureAmount计算的就是除去混合贴图中某点像素值的r,g,b通道值,用这个差值作为地形的背景混合因子。

这也是接下来代码做的事情。

1vec2 tileCoords = pass_textureCoordinates * 40.0f;
2vec4 backgroundTextureColor = texture(backgroundTexture, tileCoords) * backTextureAmount;

是不是很奇怪,为啥这里把地形的纹理采样坐标pass_textureCoordinates乘以40。因为我们的地形贴图很小啊,地形很大啊,如果使用地形的采样坐标去采样贴图的画,相当于把一张小贴图拉到地形那么大,那么你会看到什么呢?

对啊,那就糊了啊。

但是你可能会说,那乘以40不就超过1了嘛,纹理采样坐标不是0-1嘛。

对啊,你说滴对。

但是,你忘了之前有个文章说到纹理环绕模式了吗? 超过1的纹理坐标会根据加载纹理时设置的纹理环绕模式进行采样的。

你看,乘以40之后采样的纹理很清晰。

1vec4 rTextureColor = texture(rTexture,tileCoords) * blendMapColor.r;
2vec4 gTextureColor = texture(gTexture,tileCoords) * blendMapColor.g;
3vec4 bTextureColor = texture(bTexture,tileCoords) * blendMapColor.b;
4
5vec4 totalColor = backgroundTextureColor +  rTextureColor + gTextureColor + bTextureColor;

接下来,我们分别使用 混合地图中的 每个通道的颜色值作为混合因子,使用地形贴图 比如 泥土、道路贴图 作为对应的采样贴图,进行颜色计算。

最后将几种颜色加起来作为最终的输出颜色。

由于这里用到了5张纹理,1张混合贴图+4张地形贴图,所以,我们在渲染的时候,需要开启4个纹理单元:

最后,我们在生成地形时指定对应的贴图纹理即可。

最后结果,前面已经看到了。

好了,结束。

其实很简单有没有。

欢迎大家关注我的公众号【OpenGL编程】。

分享3D编程的心得、算法,包括:OpenGL、Shader编程、WebGL(Three.js)等,一起走进3D编程的世界。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值