- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Three.js 作为开发空间模拟器的框架,我正在尝试,但未能让夜灯正常工作。
模拟器可以在这里访问:
orbitingeden.com
可以在此处找到运行以下代码段的页面:
orbitingeden.com/orrery/soloearth.html
示例页面的代码在这里。我什至不知道从哪里开始。我尝试渲染两个相距几个单位的地球仪,一个更靠近太阳(白天版),一个更靠近太阳(白天版),另一个更远(夜间版),但有很多问题,其中最重要的是它们开始以奇怪的十二面体形式相互重叠方法。我从这个 orrery 中采用了 tDiffuse2 的想法,但无法让它工作。
<!doctype html>
<html lang="en">
<head>
<title>three.js webgl - earth</title>
<meta charset="utf-8">
<script src="three.js/Detector.js"></script>
<script src="three.js/Three.js"></script>
</head>
<body>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var radius = 6371;
var tilt = 0.41;
var rotationSpeed = 0.02;
var cloudsScale = 1.005;
var SCREEN_HEIGHT = window.innerHeight;
var SCREEN_WIDTH = window.innerWidth;
var container, camera, scene, renderer;
var meshPlanet, meshClouds, dirLight, ambientLight;
var clock = new THREE.Clock();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0x000000, 0.00000025 );
camera = new THREE.PerspectiveCamera( 25, SCREEN_WIDTH / SCREEN_HEIGHT, 50, 1e7 );
camera.position.z = radius * 5;
scene.add( camera );
dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( -20, 0, 2 ).normalize();
scene.add( dirLight );
ambientLight = new THREE.AmbientLight( 0x000000 );
scene.add( ambientLight );
//initialize the earth
var planetTexture = THREE.ImageUtils.loadTexture( "textures/earth-day.jpg" ),
nightTexture = THREE.ImageUtils.loadTexture( "textures/earthNight.gif" ),
cloudsTexture = THREE.ImageUtils.loadTexture( "textures/clouds.gif" ),
normalTexture = THREE.ImageUtils.loadTexture( "textures/earth-map.jpg" ),
specularTexture = THREE.ImageUtils.loadTexture( "textures/earth-specular.jpg" );
var shader = THREE.ShaderUtils.lib[ "normal" ];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ "tNormal" ].texture = normalTexture;
uniforms[ "uNormalScale" ].value = 0.85;
uniforms[ "tDiffuse" ].texture = planetTexture;
uniforms[ "tDiffuse2" ].texture = nightTexture;
uniforms[ "tSpecular" ].texture = specularTexture;
uniforms[ "enableAO" ].value = false;
uniforms[ "enableDiffuse" ].value = true;
uniforms[ "enableSpecular" ].value = true;
uniforms[ "uDiffuseColor" ].value.setHex( 0xffffff );
uniforms[ "uSpecularColor" ].value.setHex( 0x333333 );
uniforms[ "uAmbientColor" ].value.setHex( 0x000000 );
uniforms[ "uShininess" ].value = 15;
var parameters = {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: uniforms,
lights: true,
fog: true
};
var materialNormalMap = new THREE.ShaderMaterial( parameters );
geometry = new THREE.SphereGeometry( radius, 100, 50 );
geometry.computeTangents();
meshPlanet = new THREE.Mesh( geometry, materialNormalMap );
meshPlanet.rotation.y = 0;
meshPlanet.rotation.z = tilt;
scene.add( meshPlanet );
// clouds
var materialClouds = new THREE.MeshLambertMaterial( { color: 0xffffff, map: cloudsTexture, transparent: true } );
meshClouds = new THREE.Mesh( geometry, materialClouds );
meshClouds.scale.set( cloudsScale, cloudsScale, cloudsScale );
meshClouds.rotation.z = tilt;
scene.add( meshClouds );
renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.sortObjects = false;
renderer.autoClear = false;
container.appendChild( renderer.domElement );
};
function animate() {
requestAnimationFrame( animate );
render();
};
function render() {
// rotate the planet and clouds
var delta = clock.getDelta();
meshPlanet.rotation.y += rotationSpeed * delta;
meshClouds.rotation.y += 1.25 * rotationSpeed * delta;
//render the scene
renderer.clear();
renderer.render( scene, camera );
};
</script>
</body>
</html>
最佳答案
如果我理解你的问题......
我不知道three.js,但总的来说,我会通过让一个着色器通过白天和黑夜时间纹理然后在着色器中选择一个或另一个来做到这一点。例如
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
varying vec3 v_surfaceToLight; // assumes this gets passed in from vertex shader
varying vec4 v_normal; // assumes this gets passed in from vertex shader
varying vec2 v_texCoord; // assumes this gets passed in from vertex shader
void main () {
vec3 normal = normalize(v_normal);
vec3 surfaceToLight = normalize(v_surfaceToLight);
float angle = dot(normal, surfaceToLight);
vec4 dayColor = texture2D(dayTexture, v_texCoords);
vec4 nightColor = texture2D(nightTexture, v_texCoord);
vec4 color = angle < 0.0 ? dayColor : nightColor;
...
gl_FragColor = color * ...;
}
vec4 color = angle < 0.0 ? dayColor : nightColor;
// convert from -1 <-> +1 to 0 <-> +1
float lerp0To1 = angle * 0.5 + 0.5;
// mix between night and day
vec4 color = mix(nightColor, dayColor, lerp0to1);
// sharpen the mix
angle = clamp(angle * 10.0, -1.0, 1.0);
// convert from -1 <-> +1 to 0 <-> +1
float lerp0To1 = angle * 0.5 + 0.5;
// mix between night and day
vec4 color = mix(nightColor, dayColor, lerp0to1);
const vs = `
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
vNormal = normalMatrix * normal;
gl_Position = projectionMatrix * mvPosition;
}
`;
const fs = `
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
uniform vec3 sunDirection;
varying vec2 vUv;
varying vec3 vNormal;
void main( void ) {
vec3 dayColor = texture2D( dayTexture, vUv ).rgb;
vec3 nightColor = texture2D( nightTexture, vUv ).rgb;
// compute cosine sun to normal so -1 is away from sun and +1 is toward sun.
float cosineAngleSunToNormal = dot(normalize(vNormal), sunDirection);
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 10.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
// Select day or night texture based on mix.
vec3 color = mix( nightColor, dayColor, mixAmount );
gl_FragColor = vec4( color, 1.0 );
}
`;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(40, 1, 1, 3000);
camera.position.z = 4;
scene.add( camera );
const directionalLight = new THREE.DirectionalLight( 0xaaff33, 0 );
directionalLight.position.set(-1, 1, 0.5).normalize();
scene.add( directionalLight );
const textureLoader = new THREE.TextureLoader();
const uniforms = {
sunDirection: {value: new THREE.Vector3(0,1,0) },
dayTexture: { value: textureLoader.load( "https://i.imgur.com/dfLCd19.jpg" ) },
nightTexture: { value: textureLoader.load( "https://i.imgur.com/MeKgLts.jpg" ) }
};
const material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vs,
fragmentShader: fs,
});
const mesh = new THREE.Mesh( new THREE.SphereGeometry( 0.75, 32, 16 ), material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
resize(true);
requestAnimationFrame(render);
function resize(force) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (force || canvas.width !== width || canvas.height !== height) {
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
function render(time) {
time *= 0.001; // seconds
resize();
uniforms.sunDirection.value.x = Math.sin(time);
uniforms.sunDirection.value.y = Math.cos(time);
// Note: Since the earth is at 0,0,0 you can set the normal for the sun
// with
//
// uniforms.sunDirection.value.copy(sunPosition);
// uniforms.sunDirection.value.normalize();
mesh.rotation.y = time * .3
mesh.rotation.x = time * .7;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
uniform sampler2D dayTexture;
uniform sampler2D nightTexture;
uniform vec3 sunDirection;
varying vec2 vUv;
varying vec3 vNormal;
void main( void ) {
vec3 dayColor = texture2D( dayTexture, vUv ).rgb;
vec3 nightColor = texture2D( nightTexture, vUv ).rgb;
// compute cosine sun to normal so -1 is away from sun and +1 is toward sun.
float cosineAngleSunToNormal = dot(normalize(vNormal), sunDirection);
// sharpen the edge beween the transition
cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 10.0, -1.0, 1.0);
// convert to 0 to 1 for mixing
float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5;
// Select day or night texture based on mixAmount.
vec3 color = mix( nightColor, dayColor, mixAmount );
gl_FragColor = vec4( color, 1.0 );
// comment in the next line to see the mixAmount
//gl_FragColor = vec4( mixAmount, mixAmount, mixAmount, 1.0 );
}
关于webgl - 将夜灯添加到 WebGL/Three.js 地球,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10644236/
一些网站说你应该通过以下方式初始化 webgl: var gl = c.getContext("webgl") || c.getContext("experimental-webgl"); if (!
我一直在寻找有关 WebGL 的信息以及可以分配用于渲染的最大纹理数/内存量。这显然是特定于硬件/设备的,因此我正在寻找一种智能处理纹理的方法。 我目前有 512x512 RGBA8 格式的纹理。一个
我想知道是否可以利用WebGL进行任何异步调用? 我研究了Spec v1和Spec v2,他们什么都没提及。在V2中,有一种WebGL查询机制,我认为这不是我想要的。 在网络上进行搜索并没有确定的定义
我正在参与一个 webgl 项目。 当我调用 gl.DrawElements 时,会显示错误“范围超出缓冲区范围”。 我肯定确保我传递了正确的缓冲区长度或偏移量。但是,仍然显示错误。 我认为有几个原因
我知道 WebGL 中有 8 个纹理的限制。 我的问题是,8 是全局限制还是每个着色器/程序明智的? 如果它是每个着色器/程序明智的限制,这是否意味着,一旦我将纹理加载到一个着色器的制服上,我就可以开
我一直在使用 Haxe + Away3D 编写一个小型行星生成器,并将其部署到 HTML5/WebGL。但是在渲染云时我遇到了一个奇怪的问题。我有行星网格,然后云网格在相同位置稍大一些。 我正在使用柏
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
在 OpenGL 中,深度缓冲区值是根据场景的近和远裁剪平面计算的。 (引用:Getting the true z value from the depth buffer) 这在 WebGL 中是如何
简单的问题,但我无法在任何地方的规范中找到答案。我可能在某处遗漏了明显的答案。 我可以在 WebGL 片段着色器中同时使用多少个纹理?如果它是可变的,那么假设 PC 使用的合理数字是多少? (对移动不
我有一个渲染场景的帧缓冲区,现在我想将它渲染到“全屏”四边形。如何设置我的相机以及我应该在我的顶点着色器中放置什么以便将帧缓冲区的纹理渲染到整个屏幕。 我试过像这样创建一个全屏四边形 var gl =
我正在阅读 here 的教程。 var gl; function initGL() { // Get A WebGL context var canvas = document.getEle
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在学习 WebGL,我能感觉到我的速度很慢,因为我很难调试我的代码。是否有任何扩展或工具可以帮助我知道缓冲区、属性指针、矩阵等的值。 我在谷歌上搜索并了解了 chrome 扩展程序 spector
我可以在某处找到任何文档来记录 WebGL 调用所需的先决条件吗? 我已经对 WebGL 基础有了相当深入的了解,但现在我正在创建自己的“框架”,并且我正在更深入地了解。 例如, enableVert
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 7年前关闭。 Improve t
我有兴趣在 webgl 中执行一些密集计算,所以它在 GPU 上运行。 大多数文档都讨论了如何渲染图形。 我正在完成非常简单的任务:对于给定的图像,将其转换为灰度,并找到局部最大值的坐标(比其邻居更亮
我目前在 WebGL 中使用这个片段着色器来对照片纹理应用高光/阴影调整。 着色器本身是直接从优秀的 GPUImage 中拉出来的适用于 iOS 的库。 uniform sampler2D input
我是 webgl 的新手。我正在尝试设置时间统一,因此我可以随着时间的推移更改片段着色器的输出。我认为这实现起来相当简单,但我正在努力。我知道这两种方法可能涉及: https://developer.
我正在尝试使用两个 Canvas 并排绘制相同的 WebGL 场景。是否可以?到目前为止,我还没有走运。 思路如下: 我加载几何 我设置了两个gl上下文,每幅 Canvas 一个 我调用 drawEl
我正在学习 WebGL 并尝试显示一个球体。没有纹理,只有每个顶点着色,但我在 Opera 和 Chrome 中收到以下错误消息:“[.WebGLRenderingContext]GL 错误:GL_I
我是一名优秀的程序员,十分优秀!