渲染透明外壳 [英] Rendering a transparent shell

查看:13
本文介绍了渲染透明外壳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我正在渲染神奇女侠驾驶她的隐形喷气机.射流由多个网格组成,并且大部分是透明的.在透明网格重叠的地方,它变得更加不透明.我不想有那种重叠,这样透明部分仍然是阴影,但材料丢弃了其他片段后面的透明片段,就好像神奇女侠坐在一个透明的壳里一样.

也许一个很好的表达方式是我想渲染像不透明网格一样的透明网格,但仍然允许它们是透明的.

举个例子,这是一个普通女人驾驶她的大部分可见汽车:http://jsfiddle.net/TheJim01/e6ccfo24/

我对深度测试和写作做了不同的排列,并尝试了所有不同的深度测试功能.我还尝试了不同的混合设置(我看到了一些关于 THREE.NoBlending 的建议,但这不是我想要的,因为我失去了透明度).如果我必须为此编写自定义着色器,我会走那条路,但我不确定从哪里开始.

HTML:

CSS:

html *{填充:0;边距:0;宽度:100%;溢出:隐藏;}#主持人 {宽度:100%;高度:100%;}

JavaScript:

//注意:要运行此演示,您必须使用 HTTP 协议,而不是 HTTPS!var msh = new THREE.Mesh(new THREE.SphereGeometry(10, 20, 20), new THREE.MeshLambertMaterial({color: "red"}));msh.position.set(0, 10, 0);场景添加(msh);var mat = new THREE.MeshLambertMaterial({颜色:银色",透明:真实,不透明度:0.5});msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 75, 20), mat);msh.rotation.set(0, 0, Math.PI/2);msh.position.set(0,10,0);场景添加(msh);msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 50, 20), mat);msh.rotation.set(Math.PI/2, 0, 0);msh.position.set(-20,-10,0);场景添加(msh);msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 50, 20), mat);msh.rotation.set(Math.PI/2, 0, 0);msh.position.set(20,-10,0);场景添加(msh);画();

解决方案

如果你想渲染重叠的透明面,但又不想重叠区域变暗,你可以实现一个技巧:先用

渲染面>

material.colorWrite = false;

然后用

再次渲染它们

material.colorWrite = true;

小提琴:http://jsfiddle.net/yrfuy4j8/

你的小提琴:http://jsfiddle.net/5eku8k37/

three.js r.76

Let's say I'm rendering Wonder Woman piloting her Invisible Jet. The jet is made up of multiple meshes, and is mostly transparent. Where the transparent meshes overlap, it becomes more opaque. I'd like to not have that overlap, such that the transparent parts are still shaded, but the material discards transparent fragments that are behind other fragments, as if Wonder Woman is sitting inside a transparent shell.

Perhaps a good way to putting it is that I want to render transparent meshes like opaque meshes, but still allow them to be transparent.

As an example, here is Average Woman driving her Mostly-Visible Car: http://jsfiddle.net/TheJim01/e6ccfo24/

I've done different permutations of depth testing and writing, and tried all the various depth test functions. I've also tried different blending settings (I saw several suggestions for THREE.NoBlending, but that's not what I want because I lose transparency). If I have to write a custom shader for this, I'll go that route, but I'm not sure where to start.

HTML:

<script>
// INITIALIZE
var WIDTH = window.innerWidth,
    HEIGHT = window.innerHeight,
    FOV = 35,
    NEAR = 1,
    FAR = 1000;

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
document.getElementById('host').appendChild(renderer.domElement);

var stats= new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);


var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 250;

var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 5.0; // need to speed it up a little

var scene = new THREE.Scene();

var light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);

scene.add(light);

function draw(){
    light.position.copy(camera.position);
    renderer.render(scene, camera);
  stats.update();
}
trackballControl.addEventListener('change', draw);

function navStartHandler(e) {
  renderer.domElement.addEventListener('mousemove', navMoveHandler);
  renderer.domElement.addEventListener('mouseup', navEndHandler);
}
function navMoveHandler(e) {
  trackballControl.update();
}
function navEndHandler(e) {
  renderer.domElement.removeEventListener('mousemove', navMoveHandler);
  renderer.domElement.removeEventListener('mouseup', navEndHandler);
}

renderer.domElement.addEventListener('mousedown', navStartHandler);
renderer.domElement.addEventListener('mousewheel', navMoveHandler);
</script>

CSS:

html *{
    padding: 0;
    margin: 0;
    width: 100%;
    overflow: hidden;
}

#host {
    width: 100%;
    height: 100%;
}

JavaScript:

// NOTE: To run this demo, you MUST use the HTTP protocol, not HTTPS!

var msh = new THREE.Mesh(new THREE.SphereGeometry(10, 20, 20), new THREE.MeshLambertMaterial({color: "red"}));
msh.position.set(0, 10, 0);
scene.add(msh);

var mat = new THREE.MeshLambertMaterial({
    color: "silver",
  transparent: true,
  opacity: 0.5
});

msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 75, 20), mat);
msh.rotation.set(0, 0, Math.PI / 2);
msh.position.set(0,10,0);
scene.add(msh);

msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 50, 20), mat);
msh.rotation.set(Math.PI / 2, 0, 0);
msh.position.set(-20,-10,0);
scene.add(msh);

msh = new THREE.Mesh(new THREE.CylinderGeometry(15, 15, 50, 20), mat);
msh.rotation.set(Math.PI / 2, 0, 0);
msh.position.set(20,-10,0);
scene.add(msh);

draw();

解决方案

If you want to render overlapping transparent faces, but do not want the overlapping regions to be darker, you can implement a trick: render the faces first with

material.colorWrite = false;

and then render them a second time with

material.colorWrite = true;

fiddle: http://jsfiddle.net/yrfuy4j8/

your fiddle: http://jsfiddle.net/5eku8k37/

three.js r.76

这篇关于渲染透明外壳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆