簡體   English   中英

去除GLSL着色器產生的波紋圖案

[英]Removing moire patterns produced by GLSL shaders

我已經設置了這個最小的測試用例,您可以使用自定義片段着色器( jsfiddle )輕松查看通過對示波器紅色進行欠采樣而產生的莫爾圖案。

使用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> 

更新:我試圖實現超級采樣 ,不確定我是否正確實現了它,但它似乎沒有太多幫助。

不幸的是,這里的莫爾條紋是高對比度線接近奈奎斯特頻率的結果 換句話說,沒有好的辦法讓1或2像素寬的高對比度線平滑地移動到下一個像素,而不會引入這樣的偽像,或模糊線條難以區分。

你提到了衍生物擴展,實際上這個擴展可以用來計算你的UV在屏幕空間中變化的速度,從而計算出在地毯下掃描這個問題需要多少模糊。 在下面您自己的示例的修改版本中,我嘗試使用fwidth將球體變為紅色,噪聲變壞。 嘗試使用一些定義為常量的浮點數,看看你能找到什么。

 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> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM