Three.js中的硬光材料混合模式?

Jas*_*son 11 javascript shader glsl webgl three.js

我目前正在使用MeshPhongMaterialThree.js提供的基本水创建一个简单的场景.我希望水材料具有Hard Light可在Photoshop等应用程序中找到的混合模式.如何Hard Light在右侧实现下面的混合模式?

比较我拥有的和期望的最终结果 Photoshop的普通和硬光混合模式的比较

上面图像的右半部分设置为Hard LightPhotoshop.我试图Hard Light在Three.js中重新创建混合模式.

我遇到的一个主要是完全重新实现了MeshPhongMaterial片段和顶点着色器,但这需要一些时间,因为我对此很新.

在Three.js中为材质实现混合模式的方法是什么Hard Light

/* 
 * Scene config
 **/
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 10000);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});

renderer.setClearColor(0xffffff);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.set(0, 500, 1000);
camera.lookAt(scene.position);

/*
 * Scene lights
 **/

var spotlight = new THREE.SpotLight(0x999999, 0.1);
spotlight.castShadow = true;
spotlight.shadowDarkness = 0.75;
spotlight.position.set(0, 500, 0);
scene.add(spotlight);

var pointlight = new THREE.PointLight(0x999999, 0.5);
pointlight.position.set(75, 50, 0);
scene.add(pointlight);

var hemiLight = new THREE.HemisphereLight(0xffce7a, 0x000000, 1.25);
hemiLight.position.y = 75;
hemiLight.position.z = 500;
scene.add(hemiLight);

/* 
 * Scene objects
 */

/* Water */

var waterGeo = new THREE.PlaneGeometry(1000, 1000, 50, 50);
var waterMat = new THREE.MeshPhongMaterial({
  color: 0x00aeff,
  emissive: 0x0023b9,
  shading: THREE.FlatShading,
  shininess: 60,
  specular: 30,
  transparent: true
});

for (var j = 0; j < waterGeo.vertices.length; j++) {
  waterGeo.vertices[j].x = waterGeo.vertices[j].x + ((Math.random() * Math.random()) * 30);
  waterGeo.vertices[j].y = waterGeo.vertices[j].y + ((Math.random() * Math.random()) * 20);
}

var waterObj = new THREE.Mesh(waterGeo, waterMat);
waterObj.rotation.x = -Math.PI / 2;
scene.add(waterObj);

/* Floor */

var floorGeo = new THREE.PlaneGeometry(1000, 1000, 50, 50);
var floorMat = new THREE.MeshPhongMaterial({
  color: 0xe9b379,
  emissive: 0x442c10,
  shading: THREE.FlatShading
});

for (var j = 0; j < floorGeo.vertices.length; j++) {
  floorGeo.vertices[j].x = floorGeo.vertices[j].x + ((Math.random() * Math.random()) * 30);
  floorGeo.vertices[j].y = floorGeo.vertices[j].y + ((Math.random() * Math.random()) * 20);
  floorGeo.vertices[j].z = floorGeo.vertices[j].z + ((Math.random() * Math.random()) * 20);
}

var floorObj = new THREE.Mesh(floorGeo, floorMat);
floorObj.rotation.x = -Math.PI / 2;
floorObj.position.y = -75;
scene.add(floorObj);

/* 
 * Scene render
 **/
var count = 0;

function render() {
  requestAnimationFrame(render);

  var particle, i = 0;
  for (var ix = 0; ix < 50; ix++) {
    for (var iy = 0; iy < 50; iy++) {
      waterObj.geometry.vertices[i++].z = (Math.sin((ix + count) * 2) * 3) +
        (Math.cos((iy + count) * 1.5) * 6);
      waterObj.geometry.verticesNeedUpdate = true;
    }
  }

  count += 0.05;

  renderer.render(scene, camera);
}

render();
Run Code Online (Sandbox Code Playgroud)
html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

gma*_*man 2

我认为你不会得到你想要的效果。

如何生成第一张图像?我想你只是在 Photoshop 中制作了模糊椭圆形并选择了“强光”?

如果您想要在 Three.js 中实现相同的效果,则需要生成一个模糊椭圆并使用 Three.js 中的后处理效果将其应用到 2D 中

您可以通过在 Three.js 中创建第二个场景来生成这样的椭圆形,添加灯光并将它们照射在没有波浪的黑色平面上,该平面与原始场景中的水的位置相同。将其渲染到渲染目标。您可能只需要该场景中的聚光灯和点光源。在当前场景中,请务必移除聚光灯。将其渲染到另一个渲染目标。

完成后,使用实现强光的后处理效果组合场景

// pseudo code
vec3 partA = texture2D(sceneTexture, texcoord);
vec3 partB = texture2D(lightTexture, texcoord);
vec3 line1 = 2.0 * partA * partB;
vec3 line2 = 1.0 - (1.0 - partA) * (1.0 - partB);
gl_FragCoord = vec4(mix(line2, line1, step(0.5, partA)), 1); 
Run Code Online (Sandbox Code Playgroud)