使用透明着色器材料重叠边缘 - Three.js

时间:2016-06-02 20:52:45

标签: javascript three.js

我是webgl世界的新手,并试图学习一些东西。在我弄清楚着色器如何工作之后,我想更进一步,制作一个平滑透明的云。实际上我做到了,但正如你在下面的图片中所看到的,有一些重叠的边缘看起来是锯齿状的。

你能解释为什么会这样,以及如何解决它?

谢谢

V77

片段

var camera, controls, scene, renderer;
var sceneCss, rendererCss;
var dirLight, ambientLight, pointLight;
var displacementMaterial;

var wH = window.innerHeight;
var wW = window.innerWidth;
var start = Date.now();
var properties;
var cloudRadius = 150;
var cloudMesh;

var noiseMaterial, noiseMap;
var uniforms, displamentUniforms;


$(document).ready(function() {
  //init Core Engine;
  init();
  //init All Engines; 
  onLoaded();
  animateAll();
});

//Give it life;
function init() {

  properties = {
    smoke: 2.0,
    heat: 0.0007,
    shapeBiasX: 1.5,
    shapeBiasY: 2.5,
    displacementScale: 40,
    displacementBias: -22,
    turbulence: 40,
    twist: 0,
    wireframes: false,
    rotationX: .5,
    rotationY: 0,
    rotationZ: 0,
    opacity: 1.0
  }

  // add camera and controls
  camera = new THREE.PerspectiveCamera(70, wW / wH, 0.1, 20000);
  camera.position.set(0, 0, 400);

  //PostProcess Materials
  sceneRenderTarget = new THREE.Scene();

  cameraOrtho = new THREE.OrthographicCamera(wW / -2, wW / 2, wH / 2, wH / -2, -10000, 10000);
  cameraOrtho.position.z = 100;
  cameraOrtho.updateProjectionMatrix();

  var plane = new THREE.PlaneGeometry(wW, wH);
  quadTarget = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ transparent: true, opacity: .1, color: 0x000000 }));
  quadTarget.position.z = -500;
  sceneRenderTarget.add(quadTarget);

  //
  //scene
  scene = new THREE.Scene();
  sceneCss = new THREE.Scene();
  fog = new THREE.FogExp2(0x212121, 0.002);
  scene.fog = fog;

  //renderer
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(wW, wH);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.sortObjects = false;
  renderer.domElement.style.zIndex = 0;
  renderer.setClearColor(0x222222);
  document.body.appendChild(renderer.domElement);
}

function onLoaded() {
  //Will Check Processes
  createClouds();
}

function createClouds() {

  uniforms = {
    time: {
      type: "f",
      value: 1.0
    },
    uSpeed: {
      type: "f",
      value: 1.0
    },
    scale: {
      type: "v2",
      value: new THREE.Vector2(1, 1)
    },
    opacity: {
      type: "f",
      value: 1.0
    }
  };

  noiseMaterial = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: document.getElementById('noise_vertex').textContent,
    fragmentShader: document.getElementById('noise_fragment').textContent,
    lights: false,
    wireframe: properties.wireframes
  });

  noiseMap = new THREE.WebGLRenderTarget(512, 512, {
    minFilter: THREE.LinearFilter,
    magFilter: THREE.LinearFilter,
    format: THREE.RGBFormat,
    wrapS: THREE.RepeatWrapping
  });

  displacementUniforms = {
    time: {
      type: "f",
      value: 1.0
    },
    tHeightMap: {
      type: "t",
      value: noiseMap.texture
    },
    uDisplacementBias: {
      type: "f",
      value: properties.displacementBias
    },
    uDisplacementScale: {
      type: "f",
      value: properties.displacementScale
    },
    uColor1: {
      type: "c",
      value: new THREE.Color(0xffff00)
    },
    uColor2: {
      type: "c",
      value: new THREE.Color(0x0000ff)
    },
    uSmoke: {
      type: "f",
      value: properties.smoke
    },
    uShapeBias: {
      type: "v2",
      value: new THREE.Vector2(properties.shapeBiasX, properties.shapeBiasY)
    },
    uScreenHeight: {
      type: "f",
      value: wH
    },
    uTurbulence: {
      type: "f",
      value: properties.turbulence
    },
    uTwist: {
      type: "f",
      value: properties.twist
    },
    opacity: {
      type: "f",
      value: 1.0
    }
  };

  displacementMaterial = new THREE.ShaderMaterial({
    wireframe: properties.wireframes,
    transparent: true,
    uniforms: displacementUniforms,
    vertexShader: document.getElementById('displacement_vertex').textContent,
    fragmentShader: document.getElementById('displacement_fragment').textContent,
    premultipliedAlpha: true,
    side: THREE.DoubleSide,
    shading: THREE.SmoothShading,
    depthTest: false
  });

  var geometrySphere = new THREE.SphereGeometry(cloudRadius, 140, 100);
  geometrySphere.computeFaceNormals();
  cloudMesh = new THREE.Mesh(geometrySphere, displacementMaterial);
  cloudMesh.position.y = -40;
  cloudMesh.renderOrder = 5;
  scene.add(cloudMesh);
}

function animateAll() {

  uniforms.uSpeed.value += properties.heat;
  uniforms.time.value += properties.heat * .3;

  displacementUniforms.opacity.value = properties.opacity;
  displacementMaterial.uniforms["time"].value += properties.heat * .3;

  //cloudMesh.rotation.x = properties.rotationX;
  cloudMesh.rotation.z = properties.rotationZ;
  //cloudMesh.rotation.y = properties.rotationY;

  cloudMesh.rotation.y += 0.002;



  requestAnimationFrame(animateAll);
  renderAll();
}

//render
function renderAll() {
  renderer.clear();

  quadTarget.material = noiseMaterial;

  renderer.render(sceneRenderTarget, cameraOrtho, noiseMap, true);
  renderer.render(scene, camera);

}
canvas {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: -10
}

body {
  overflow: hidden;
  padding: 0;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.2.js"></script>
<script data-src="shaders/displacement_vertex.js" data-name="Displacement" type="x-shader/x-vertex" id="displacement_vertex">
uniform float time;
uniform vec2 scale;
uniform float uTwist;
varying vec2 vUv;
varying vec3 vNormal;
uniform vec2 uShapeBias;
uniform float uTurbulence;

#ifdef VERTEX_TEXTURES
uniform sampler2D tHeightMap;
uniform float uDisplacementScale;
uniform float uDisplacementBias;
#endif

vec4 DoTwist( vec4 pos, float t )
{
  float st = sin(t);
  float ct = cos(t);
  vec4 new_pos;

  new_pos.x = pos.x*ct - pos.z*st;
  new_pos.z = pos.x*st + pos.z*ct;

  new_pos.y = pos.y;
  new_pos.w = pos.w;

  return( new_pos );
}

void main( void ) {

  vUv = uv;
  vNormal = normalize( normalMatrix * normal );

  //change matrix
  vec4 mPosition = modelMatrix *  vec4( position, 1.0 );

  mPosition.x *= uShapeBias.x +1.0; //      uShapeBias.x*(vUv.x+1.0);
  mPosition.y *=  (1.0 -(vUv.y-0.5)*-uShapeBias.y);
  //mPosition.y -= 40.0;

  float turbFactor = uTurbulence*(vUv.y-0.5);

  //shape turbulance
  mPosition.x += sin(mPosition.y/100.0 + time*20.0 )*turbFactor;
  mPosition.z += cos(mPosition.y/100.0 + time*20.0 )*turbFactor;

  //twist
  float angle_rad = uTwist * 3.14159 / 180.0;
  float height = -300.0;
  float ang = (position.y-height*0.5)/height * angle_rad;

  vec4 twistedPosition = DoTwist(mPosition, ang);
  vec4 twistedNormal = DoTwist(vec4(vNormal,1.0), ang);

  //change matrix
  vec4 mvPosition = viewMatrix * twistedPosition;

  #ifdef VERTEX_TEXTURES
  vec3 dv = texture2D( tHeightMap, vUv ).xyz;
  float df = uDisplacementScale * dv.x + uDisplacementBias;
  vec4 displacedPosition = vec4( twistedNormal.xyz * df, 0.0 ) + mvPosition;
  gl_Position = projectionMatrix * displacedPosition;
  #else
  gl_Position = projectionMatrix * mvPosition;
  #endif

}
    </script>
    <script data-src="shaders/displacement_fragment.js" data-name="Displacement" type="x-shader/x-fragment" id="displacement_fragment">

varying vec2 vUv;

uniform sampler2D tHeightMap;
uniform float uSmoke;
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform float uScreenHeight;
void main( void ) {


  vec4 heightColor = texture2D( tHeightMap, vUv);
  vec3 heightAlpha = texture2D( tHeightMap, vUv).xyz;

  vec3 gradient1 = uColor1/(gl_FragCoord.y/uScreenHeight*4.0);
  vec3 gradient2 = uColor2/(gl_FragCoord.y/uScreenHeight*4.0);
  vec3 fireSumColor = (gradient1+gradient2)*heightColor.b;
  float opacity = heightAlpha.x *.05;

  //smoke
  gl_FragColor = vec4(mix( fireSumColor, vec3(1.0), gl_FragCoord.y/uScreenHeight*uSmoke ), opacity);

  float depth = gl_FragCoord.z / gl_FragCoord.w;
  float fogFactor = smoothstep( 10.0, 400.0, depth* .9 );

  gl_FragColor = mix( gl_FragColor, vec4( vec3(0.0,0.0,0.0), gl_FragColor.w ), fogFactor )*1.0;

  //  gl_FragColor = gl_FragColor*vec4(vec3(1.0), 1.0);

}
    </script>
    <script data-src="shaders/noise_vertex.js" data-name="Noise" type="x-shader/x-vertex" id="noise_vertex">
varying vec2 vUv;
uniform vec2 scale;

void main( void ) {
  vUv = uv * scale;
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}    
    </script>
    <script data-src="shaders/noise_fragment.js" data-name="Noise" type="x-shader/x-fragment" id="noise_fragment">
//
// Description : Array and textureless GLSL 3D simplex noise function.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : ijm
//     Lastmod : 20110409 (stegu)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//

uniform float time;
uniform float uSpeed;

varying vec2 vUv;

vec4 permute( vec4 x ) {

  return mod( ( ( x * 34.0 ) + 1.0 ) * x, 289.0 );
}

vec4 taylorInvSqrt( vec4 r ) {

  return 1.79284291400159 - 0.85373472095314 * r;

}

float PI = 3.14159265;
float TWOPI = 6.28318531;
float BaseRadius = 1.0;

vec3 sphere( float u, float v) {

  u *= PI;
  v *= TWOPI;
  vec3 pSphere;

  pSphere.x = BaseRadius * cos(v) * sin(u);
  pSphere.y = BaseRadius * sin(v) * sin(u);
  pSphere.z = BaseRadius * cos(u);

  return pSphere;
}

float snoise( vec3 v ) {

  const vec2 C = vec2( 1.0 / 6.0, 1.0 / 3.0 );
  const vec4 D = vec4( 0.0, 0.5, 1.0, 2.0 );

  // First corner

  vec3 i  = floor( v + dot( v, C.yyy ) );
  vec3 x0 = v - i + dot( i, C.xxx );

  // Other corners

  vec3 g = step( x0.yzx, x0.xyz );
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  vec3 x1 = x0 - i1 + 1.0 * C.xxx;
  vec3 x2 = x0 - i2 + 2.0 * C.xxx;
  vec3 x3 = x0 - 1. + 3.0 * C.xxx;

  // Permutations

  i = mod( i, 289.0 );
  vec4 p = permute( permute( permute(
    i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) )
                            + i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) )
                   + i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) );

  // Gradients
  // ( N*N points uniformly over a square, mapped onto an octahedron.)

  float n_ = 1.0 / 7.0; // N=7

  vec3 ns = n_ * D.wyz - D.xzx;

  vec4 j = p - 49.0 * floor( p * ns.z *ns.z );  //  mod(p,N*N)

  vec4 x_ = floor( j * ns.z );
  vec4 y_ = floor( j - 7.0 * x_ );    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs( x ) - abs( y );

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );


  vec4 s0 = floor( b0 ) * 2.0 + 1.0;
  vec4 s1 = floor( b1 ) * 2.0 + 1.0;
  vec4 sh = -step( h, vec4( 0.0 ) );

  vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
  vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;

  vec3 p0 = vec3( a0.xy, h.x );
  vec3 p1 = vec3( a0.zw, h.y );
  vec3 p2 = vec3( a1.xy, h.z );
  vec3 p3 = vec3( a1.zw, h.w );

  // Normalise gradients

  vec4 norm = taylorInvSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;

  // Mix final noise value

  vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 );
  m = m * m;
  return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ),  dot( p2, x2 ), dot( p3, x3 ) ) );

}

float surface( vec3 coord ) {

  float n = 0.0;

  n += 0.7    * abs( snoise( coord ) );
  n += 0.25   * abs( snoise( coord * 2.0 ) );
  n += 0.125  * abs( snoise( coord * 4.0 ) );
  n += 0.0625 * abs( snoise( coord * 8.0 ) );

  return n;

}

void main( void ) {

  vec3 coord = sphere(vUv.y,vUv.x);

  coord.x += uSpeed;
  coord.y += -time;
  coord.z += -time;

  float n = surface( coord );

  gl_FragColor = vec4( vec3( n, n, n ), 1.0 );

}
    </script>

1 个答案:

答案 0 :(得分:3)

如果在three.js中有重叠的透明材质,通常可以通过设置

删除不需要的工件
material.depthTest = false;

这取决于您的使用案例。

但是,如果您有遮挡透明对象的不透明对象,它将无法正常工作。但这不是你的用例。

编辑:正如@Bahadir在下面的评论中指出的那样,你也可以试试

material.depthWrite = false;

three.js r.77