首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >去除GLSL着色器产生的云纹图案

去除GLSL着色器产生的云纹图案
EN

Stack Overflow用户
提问于 2015-12-30 05:50:42
回答 1查看 1.9K关注 0票数 8

我已经设置了这个最小的测试用例,您可以很容易地看到通过使用自定义片段着色器(小提琴)对振荡红色进行欠采样所产生的云纹图案。

使用GLSL消除这种模式的一般技术是什么?我认为它涉及到衍生工具的扩展,但我从来没有完全理解如何实现它。我想我基本上得做些反混叠?

代码语言:javascript
运行
复制
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);
}
代码语言:javascript
运行
复制
html, body, #canvas {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
代码语言:javascript
运行
复制
<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>

更新:我尝试过实现超采样,不确定我是否正确地实现了它,但它似乎没有太大帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-30 17:06:18

不幸的是,这里的莫尔图案是高对比度线接近奈奎斯特频率的结果.换句话说,没有一个好的方法,让1或2像素宽的高对比度线平稳地转移到下一个像素,而不引入这样的人工制品,或模糊的线条是无法区分的。

你提到了导数扩展,实际上,这个扩展可以用来计算你的超视距在屏幕空间中的变化有多快,因此,找出需要多少模糊才能把这个问题扫到地毯下面。在下面示例的修改版本中,我尝试使用fwidth将噪声变差的球体变成红色。尝试使用一些在这里定义为常量的浮点数,看看你能找到什么。

代码语言:javascript
运行
复制
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);
}
代码语言:javascript
运行
复制
html, body, #canvas {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
代码语言:javascript
运行
复制
<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>

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34523682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档