2015-12-30 16 views
5

この最小限のテストケースを設定しました。カスタムフラグメントシェーダ(jsfiddle)を使用してオシレーション赤色をアンダーサンプリングして生成されたモアレパターンを簡単に確認できます。GLSLシェーダで生成されたモアレパターンを削除する

GLSLを使用してこのようなパターンを削除する一般的な方法は何ですか?私はデリバリ拡張を含むと仮定しますが、実装方法を決して理解できませんでした。私は基本的にアンチエイリアスをしなければならないと思いますか?

var canvas = document.getElementById('canvas'); 
 
var scene = new THREE.Scene(); 
 
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true}); 
 
var camera = new THREE.PerspectiveCamera(75, canvas.clientWidth/canvas.clientWidth, 1, 1000); 
 

 
var geometry = new THREE.SphereGeometry(50, 50, 50); 
 
var material = new THREE.ShaderMaterial({ 
 
    vertexShader: document.getElementById('vertex-shader').textContent, 
 
    fragmentShader: document.getElementById('fragment-shader').textContent 
 
}); 
 
var sphere = new THREE.Mesh(geometry, material); 
 

 
scene.add(sphere); 
 

 
camera.position.z = 100; 
 

 
var period = 30; 
 
var clock = new THREE.Clock(); 
 
render(); 
 

 
function render() { 
 
    requestAnimationFrame(render); 
 
    
 
    if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) { 
 
    renderer.setSize(canvas.clientWidth, canvas.clientHeight, false); 
 
    camera.aspect = canvas.clientWidth/canvas.clientHeight; 
 
    camera.updateProjectionMatrix(); 
 
    } 
 
    
 
    sphere.rotation.y -= clock.getDelta() * 2 * Math.PI/period; 
 
    renderer.render(scene, camera); 
 
}
html, body, #canvas { 
 
    margin: 0; 
 
    padding: 0; 
 
    width: 100%; 
 
    height: 100%; 
 
    overflow: hidden; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script> 
 
<canvas id="canvas"></canvas> 
 
<script id="vertex-shader" type="x-shader/x-vertex"> 
 
    varying vec2 vUv; 
 

 
    void main() { 
 
    vUv = uv; 
 
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
 
    } 
 
</script> 
 
<script id="fragment-shader" type="x-shader/x-fragment"> 
 
    #define M_TAU 6.2831853071795864769252867665590 
 

 
    varying vec2 vUv; 
 

 
    void main() { 
 
    float w = sin(500.0 * M_TAU * vUv.x)/2.0 + 0.5; 
 
    vec3 color = vec3(w, 0.0, 0.0); 
 
    gl_FragColor = vec4(color, 1.0); 
 
    } 
 
</script>

アップデート:私は、私はそれを正しく実装されているかどうかわからない、super-samplingを実装しようとしたが、あまりにも多くを助けていないようです。

+0

は、この効果を得るためだけの簡単な方法でした。シーム自体は問題を作り出していません。そうでなければ、シーム自体の周りに問題が見えます。 –

答えて

6

残念ながら、ここでのモアレパターンは、コントラストの高い線がNyquist Frequencyに近づいた結果です。言い換えれば、1ピクセルまたは2ピクセル幅の高コントラストラインを、そのようなアーティファクトを導入したり、見分けがつかないようにぼかすことなく、次のピクセルにスムーズにシフトさせることはできません。

派生型拡張子に言及しましたが、実際には拡張子を使用してUVがスクリーンスペース内でどのくらいの速さで変化しているかを把握することができるため、この問題をラグの下で掃引する必要があります。下の独自の例の修正版では、fwidthを使用して、ノイズが悪化する球面を赤にします。ここで定数に定義されている浮動小数点数で試してみてください。紫外線COORDを使用して

Wacł [email protected]

var canvas = document.getElementById('canvas'); 
 
var scene = new THREE.Scene(); 
 
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true}); 
 
var camera = new THREE.PerspectiveCamera(75, canvas.clientWidth/canvas.clientWidth, 1, 1000); 
 

 
var geometry = new THREE.SphereGeometry(50, 50, 50); 
 
var material = new THREE.ShaderMaterial({ 
 
    vertexShader: document.getElementById('vertex-shader').textContent, 
 
    fragmentShader: document.getElementById('fragment-shader').textContent 
 
}); 
 
var sphere = new THREE.Mesh(geometry, material); 
 

 
scene.add(sphere); 
 

 
camera.position.z = 100; 
 

 
var period = 30; 
 
var clock = new THREE.Clock(); 
 
render(); 
 

 
function render() { 
 
    requestAnimationFrame(render); 
 
    
 
    if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) { 
 
    renderer.setSize(canvas.clientWidth, canvas.clientHeight, false); 
 
    camera.aspect = canvas.clientWidth/canvas.clientHeight; 
 
    camera.updateProjectionMatrix(); 
 
    } 
 
    
 
    sphere.rotation.y -= clock.getDelta() * 2 * Math.PI/period; 
 
    renderer.render(scene, camera); 
 
}
html, body, #canvas { 
 
    margin: 0; 
 
    padding: 0; 
 
    width: 100%; 
 
    height: 100%; 
 
    overflow: hidden; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script> 
 
<canvas id="canvas"></canvas> 
 
<script id="vertex-shader" type="x-shader/x-vertex"> 
 
    varying vec2 vUv; 
 

 
    void main() { 
 
    vUv = uv; 
 
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
 
    } 
 
</script> 
 
<script id="fragment-shader" type="x-shader/x-fragment"> 
 
    #extension GL_OES_standard_derivatives : enable 
 

 
    #define M_TAU 6.2831853071795864769252867665590 
 

 
    varying vec2 vUv; 
 

 
    void main() { 
 
    float linecount = 200.0; 
 
    float thickness = 0.0; 
 
    float blendregion = 2.8; 
 
    
 
    // Loosely based on https://github.com/AnalyticalGraphicsInc/cesium/blob/1.16/Source/Shaders/Materials/GridMaterial.glsl#L17-L34 
 
    float scaledWidth = fract(linecount * vUv.s); 
 
    scaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5)); 
 
    vec2 dF = fwidth(vUv) * linecount; 
 
    float value = 1.0 - smoothstep(dF.s * thickness, dF.s * (thickness + blendregion), scaledWidth); 
 
    gl_FragColor = vec4(value, 0.0, 0.0, 1.0); 
 
    } 
 
</script>

+0

答えをありがとう!私が尋ねることができる唯一の事は、多分、このタイプの事件のための様々なテクニックに関するさらなる情報または文書ですか?彼らは基本的に高周波のものをぼかしていますか? –

+1

私が知る限り、これは唯一の解決策です。ピクセルベースのディスプレイは、単にピクセル密度よりも高い周波数を表示することはできません。上記のコードでは、 'thickness'と' blendregion'は 'fwidth'のおかげでscreen-spaceピクセルで指定されています。つまり、ピクセルは〜3ピクセル離れたところで重なるようになります。それ以下では、ラインのピクセルが1ピクセル、ギャップのピクセルが1ピクセルしかないため、ピクセルグリッドに線が張られていないと状況が乱雑になります。 – emackey

+1

ところで、このコードに基づいたロジックについては、Cozzi and Ringの "Virtual Globesのための3Dエンジン設計"のリスト4.13に詳しく書かれています。 – emackey

関連する問題