Shader testgrid-锯齿和断线

问题描述 投票:1回答:1

我需要为testgrid地面编写一个简单的着色器。我想基本上在着色器代码中绘制平行线。

问题:随着线距摄像机的距离越来越远,它们开始断裂,并且它们之间存在间隙。我知道为什么我的代码会发生这种情况-因为OpenGL估计片段的位置距离我的计算点太远,因此将其标记为不属于一行。

我正在将平面向量的实际世界位置传递给我的着色器-这就是我可以计算的方式。

我已经使用了一个小时的算法,但似乎无法获得良好的结果。

我尝试过的最好的主意是包括一个较小的系数,该系数随着线从相机获得的越远而增大-但结果令人震惊。我以线性方式计算系数,但我想我需要一些更聪明的公式来执行此路线,因为屏幕上线条变细的速率不是线性的。我到目前为止还不能弄清楚。当前,它要么使闭合线太粗(这是不希望的),要么对于远距离线仍然存在相同的问题。

为简单起见,我目前仅绘制X轴线

我包括一段着色器代码和问题的屏幕截图。

#version 300 es

precision highp float;
precision highp int;

in highp vec3 vertexPosition;

out mediump vec4 fragColor;

void main()
{
    highp float lineWidth = 0.2;
    highp float squareSize = 5.0f;

    highp int roundX = int(vertexPosition.x / squareSize);
    highp int roundY = int(vertexPosition.z / squareSize);
    highp float remainderX = vertexPosition.x - float(roundX)*squareSize;
    highp float remainderY = vertexPosition.x - float(roundY)*squareSize;

    // this is the small coefficient I was trying to add to linewidth
    highp float test = abs(0.08 * float(roundX));

    if (abs(remainderX) <= (lineWidth))
    {
        fragColor = vec4(1,0,0, 1);
    }
    else
    {
        fragColor = vec4(0.8,0.8,0.8, 1);
    }
}

Lines breaking up

ps.s。不要看代码的优化程度-我目前只是在寻找正确的主意p.p.s.如果有人可以告诉我该示例如何进行简单的抗锯齿-这也将是非常受欢迎的。

java opengl-es glsl fragment-shader
1个回答
0
投票

一种可能的解决方案是通过视口的y轴将vertexPosition的偏导数乘以dFdydFdy的偏导数的长度给出了模型空间中2个片段之间的距离。因此,可以定义一条线的最小厚度:

vertexPosition

请参见Three.js示例,该示例使用着色器:

vec3 dy = dFdy(vertexPosition);
float minWidth = length(dy);

if (abs(remainderX) <= max(lineWidth, minWidth))
{
    fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
else
{
    fragColor = vec4(0.8, 0.8, 0.8, 1.0);
}
(function onLoad() {
  var camera, scene, renderer, orbitControls;
  
  init();
  animate();

  function init() {
    
    renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });

    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    document.body.appendChild(renderer.domElement);

    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 300);
    camera.position.set(10, 15, -60);

    loader = new THREE.TextureLoader();
    loader.setCrossOrigin("");

    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);
    scene.add(camera);
    window.onresize = resize;
    
    orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
    
    var helper = new THREE.GridHelper(400, 10);
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    scene.add(helper);

    var axis = new THREE.AxesHelper(1000);
    scene.add(axis);
    
    var material = new THREE.ShaderMaterial({  
          vertexShader: document.getElementById('vertex-shader').textContent,
          fragmentShader: document.getElementById('fragment-shader').textContent,
    });
    material.extensions = {
      derivatives: true
    }

    var geometry = new THREE.BoxGeometry( 100, 0.1, 100 );
    var mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
  }

  function resize() { 
    var aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = aspect;
    camera.updateProjectionMatrix();
  }

  function animate() {
    requestAnimationFrame(animate);
    orbitControls.update();
    render();
  }

  function render() {
    renderer.render(scene, camera);
  }
})();
© www.soinside.com 2019 - 2024. All rights reserved.