GLSL混合基础纹理与贴花纹理在需要的地方

时间:2012-04-02 08:57:06

标签: opengl glsl

让我们说我们纹理四(两个三角形)。我认为这个问题类似于下一个例子中的纹理喷溅

precision lowp float;

uniform sampler2D Terrain;
uniform sampler2D Grass;
uniform sampler2D Stone;
uniform sampler2D Rock;

varying vec2 tex_coord;

void main(void)
{
vec4 terrain = texture2D(Terrain, tex_coord);
vec4 tex0    = texture2D(Grass, tex_coord * 4.0); // Tile
vec4 tex1    = texture2D(Rock,  tex_coord * 4.0); // Tile
vec4 tex2    = texture2D(Stone, tex_coord * 4.0); // Tile

tex0 *= terrain.r; // Red channel - puts grass
tex1 = mix( tex0, tex1, terrain.g ); // Green channel - puts rock and mix with grass 
vec4 outColor = mix( tex1, tex2, terrain.b ); // Blue channel - puts stone and mix with others

gl_FragColor = outColor; //final color
}

但我想在所需位置放置一个基底四边形纹理的贴花 算法是一样的,但我认为我们不需要额外的纹理和1个填充层来保持贴花的位置(例如红色层!= 0),一些我们必须如何生成我们自己的"地形。 r"(这是浮动吗?)变量并将基础纹理和贴花纹理与它混合。

precision lowp float;

uniform sampler2D base;
uniform sampler2D decal;
uniform vec2 decal_location; //where we want place decal (e.g. 0.5, 0.5 is center of quad)

varying vec2 base_tex_coord;
varying vec2 decal_tex_coord;

void main(void)
{
vec4 v_base = texture2D(base, base_tex_coord);
vec4 v_decal = texture2D(Grass, decal_tex_coord);
float decal_layer = /*somehow get our decal_layer based on decal_position*/

gl_FragColor = mix(v_base, v_decal, decal_layer);
}

如何实现这样的目标?
或者我可能只是在opengl侧生成splat纹理并将其传递给第一个着色器?这将给我最多四个四元组的贴花,但频繁更新会很慢(例如机枪撞墙)

2 个答案:

答案 0 :(得分:2)

float decal_layer = /*somehow get our decal_layer based on decal_position*/

嗯,这取决于你,你如何解释decal_position。我认为一个简单的距离指标就足够了。但这也需要四边形的尺寸。假设您通过额外的统一decal_radius提供此功能。然后我们可以使用

decal_layer = clamp(length(decal_position - vec2(0.5, 0.5)) / decal_radius, 0., 1.);

答案 1 :(得分:1)

是的,如你所述,decal_layer是一个浮点数。它的范围是0到1.但是你没有足够的信息,这里你已经指定了decal_location但是没有贴花的大小。您还不知道此片段在四边形中的位置,如果您想知道此片段相对于正在渲染的四边形的位置,您需要来自顶点着色器的varying vec2 quad_coord;或类似输入。

但是,让我们尝试一种不同的方法。编辑第二个示例的顶部以包含这些制服:

uniform vec2 decal_location; // Location of decal relative to base_tex_coord uniform float decal_size; // Size of decal relative to base_tex_coord

现在,在main()中,您应该可以使用以下内容计算decal_layer:

float decal_layer = 1.0 - smoothstep(decal_size - 0.01, decal_size, max(abs(decal_location.x - base_tex_coord.x), abs(decal_location.y - base_tex_coord.y)));

基本上你试图让decal_layer在贴花内为1.0,在贴花之外为0.0。我在你可以玩的边界添加了0.01模糊边缘。祝你好运!