繁体   English   中英

GLSL:基于与相机的距离淡入淡出 2D 网格

[英]GLSL: Fade 2D grid based on distance from camera

我目前正在尝试仅使用着色器在单个四边形上绘制 2D 网格。 我使用 SFML 作为图形库和 sf::View 来控制相机。 到目前为止,我已经能够绘制一个抗锯齿的多级网格。 第一级(蓝色)勾勒出一个区块,第二级(灰色)勾勒出一个区块内的图块。

在此处输入图片说明

我现在想根据与相机的距离淡化网格级别。 例如,块网格应该随着相机的放大而淡入。在块网格完全淡入之后,对平铺网格也应该这样做。

我不确定如何实现这一点,因为我还是 OpenGL 和 GLSL 的新手。 如果有人对如何实现此功能有任何指示,请告诉我。

顶点着色器

#version 130
out vec2 texCoords;

void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    texCoords = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
}

片段着色器

#version 130

uniform vec2 chunkSize = vec2(64.0, 64.0);
uniform vec2 tileSize = vec2(16.0, 16.0);

uniform vec3 chunkBorderColor = vec3(0.0, 0.0, 1.0);
uniform vec3 tileBorderColor = vec3(0.5, 0.5, 0.5);

uniform bool drawGrid = true;

in vec2 texCoords;

void main() {
    vec2 uv = texCoords.xy * chunkSize;
    
    vec3 color = vec3(1.0, 1.0, 1.0);

    if(drawGrid) {
        float aa = length(fwidth(uv));

        vec2 halfChunkSize = chunkSize / 2.0;
        vec2 halfTileSize =  tileSize / 2.0;
        vec2 a = abs(mod(uv - halfChunkSize, chunkSize) - halfChunkSize);
        vec2 b = abs(mod(uv - halfTileSize, tileSize) - halfTileSize);

        color = mix(
            color, 
            tileBorderColor, 
            smoothstep(aa, .0, min(b.x, b.y))
        );

        color = mix(
            color, 
            chunkBorderColor, 
            smoothstep(aa, .0, min(a.x, a.y))
        );
    }

    gl_FragColor.rgb = color;
    gl_FragColor.a = 1.0;
}   

您需要将顶点着色器中的乘法拆分为两部分:

// have a variable to be interpolated per fragment
out vec2 vertex_coordinate;
...
{
  // this will store the coordinates of the vertex
  // before its projected (i.e. its "world" coordinates)
  vertex_coordinate = gl_ModelViewMatrix * gl_Vertex;

  // get your projected vertex position as before
  gl_Position = gl_ProjectionMatrix * vertex_coordinate;
  ...
}

然后在片段着色器中根据世界顶点坐标和相机位置更改颜色:

in vec2 vertex_coordinate;
// have to update this value, every time your camera changes its position
uniform vec2 camera_world_position = vec2(64.0, 64.0);
...
{
...
  // calculate the distance from the fragment in world coordinates to the camera
  float fade_factor = length(camera_world_position - vertex_coordinate);

  // make it to be 1 near the camera and 0 if its more then 100 units.
  fade_factor = clamp(1.0 - fade_factor / 100.0, 0.0, 1.0);

  // update your final color with this factor
  gl_FragColor.rgb = color * fade_factor;
...
}

第二种方法是使用投影坐标的w 我个人更喜欢以空间为单位计算距离。 我没有测试这段代码,它可能有一些细微的语法错误,但如果你理解了这个想法,你可以用任何其他方式应用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM