【发布时间】:2016-06-02 22:59:26
【问题描述】:
我目前正在使用 Three.js 提供的MeshPhongMaterial 用基本的水创建一个简单的场景。我希望水材质具有Hard Light 混合模式,可以在 Photoshop 等应用程序中找到。如何实现右侧下方的Hard Light 混合模式?
上面图片的右半部分在 Photoshop 中设置为Hard Light。我正在尝试在 Three.js 中重新创建 Hard Light 混合模式。
我遇到的一条线索是完全重新实现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();
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"></script>
【问题讨论】:
-
将灯光移近表面。
-
@gaitat,我的问题是如何为 MeshPhongMaterial 重新创建在 Photoshop 等应用程序中看到的强光混合模式。据我所知,这是一个乘法+屏幕操作。灯光的位置无关紧要。
-
你试过什么?如果你提高聚光灯(0.9)和镜面反射分量(60),它似乎更接近我。
-
@holtavolt
MeshPhongMaterial的基本外观是正确的,但我正在寻找的是 Photoshop 中的混合模式Hard Light。Hard Light的效果,如我帖子的右半部分所示,提供了一些透明度(乘法+屏幕操作),但保留了大部分蓝色。公式可以在这里查看en.wikipedia.org/wiki/Blend_modes#Hard_Light我对着色器很陌生,所以如果在 Three.js 中制作自定义着色器是方法,我很想得到一些指点。谢谢! -
好的 - 您是否尝试设置不透明度?当我添加不透明度:0.90(并如前所述调整照明)时,我再次得到更接近硬光混合的东西。
标签: javascript three.js glsl webgl shader