- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在处理一个渲染点和线段的 three.js 场景。 The scene如果我为线条使用 LineBasicMaterial Material ,渲染效果很好:
/**
* constructor for the gl manager
**/
function World() {
this.renderTarget = document.querySelector('#render-target');
this.scene = this.getScene();
this.camera = this.getCamera();
this.renderer = this.getRenderer();
this.controls = this.getControls();
this.masterCounts = null; // {id: nMasters}
this.edges = null; // 2d array where [[master, app, app]]
this.positions = null; // {id: [x,y]}
this.z = 0; // flat z dim
this.loadData();
this.render();
}
World.prototype.getScene = function() {
return new THREE.Scene();
}
World.prototype.getContainerSize = function() {
var elem = this.renderTarget;
return {
w: elem.clientWidth,
h: elem.clientHeight,
}
}
World.prototype.getCamera = function() {
var size = this.getContainerSize();
var camera = new THREE.PerspectiveCamera(75, size.w/size.h, 0.01, 10);
camera.position.set(0.5, 0.5, -0.67);
return camera;
}
World.prototype.getRenderer = function() {
var renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
var size = this.getContainerSize();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(size.w, size.h);
document.querySelector('#render-target').appendChild(renderer.domElement);
return renderer;
}
World.prototype.getControls = function() {
var controls = new THREE.TrackballControls(this.camera, this.renderer.domElement);
controls.zoomSpeed = 0.4;
controls.panSpeed = 0.4;
controls.target.set(0.5, 0.5, 1);
return controls;
}
World.prototype.render = function() {
requestAnimationFrame(this.render.bind(this));
this.renderer.render(this.scene, this.camera);
this.controls.update();
}
World.prototype.getPointScale = function() {
return window.devicePixelRatio * window.innerHeight * 0.00001;
}
World.prototype.loadData = function() {
get('https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/node-positions-twopi.json', function(data) {
this.positions = center(JSON.parse(data));
get('https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/id-to-aggregate-masters.json', function(data) {
this.masterCounts = JSON.parse(data);
get('https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/edges.json', function(data) {
this.edges = JSON.parse(data);
this.addPoints();
this.addEdges();
}.bind(this));
}.bind(this));
}.bind(this));
}
World.prototype.addPoints = function() {
var geometry = new THREE.InstancedBufferGeometry(),
translations = getPointTranslations(this.positions),
colors = getColors(this.positions, this.masterCounts);
geometry.addAttribute('position',
new THREE.BufferAttribute( new Float32Array([0, 0, 0]), true, 3));
geometry.addAttribute('translation',
new THREE.InstancedBufferAttribute(translations, 3, true, 1) );
geometry.addAttribute('target',
new THREE.InstancedBufferAttribute(translations, 3, true, 1) );
geometry.addAttribute('color',
new THREE.InstancedBufferAttribute(colors, 3, true, 1) );
this.points = new THREE.Points(geometry, this.getShaderMaterial());
this.points.frustumCulled = false; // prevent mesh click on drag
this.scene.add(this.points);
}
World.prototype.addEdges = function() {
var indices = [],
positions = [],
idToIndex = {}, // {node id: index in edgePositions}
ids = Object.keys(this.edges);
// flatten edges into [[s,t],[s,t]]
for (var i=0; i<ids.length; i++) {
var idEdges = this.edges[ids[i]];
for (var j=0; j<idEdges.length; j++) {
// here ids[i] is a master node id, idEdges is list of
// apprentice node ids
var masterId = ids[i];
var apprenticeId = idEdges[j];
if (!(masterId in idToIndex)) {
idToIndex[masterId] = positions.length;
positions.push(this.positions[masterId]);
}
if (!(apprenticeId in idToIndex)) {
idToIndex[apprenticeId] = positions.length;
positions.push(this.positions[apprenticeId]);
}
indices = indices.concat([
idToIndex[masterId],
idToIndex[apprenticeId]
]);
}
}
var geometry = new THREE.BufferGeometry(),
translations = new Float32Array(3*positions.length),
iter = 0,
indices = new Uint16Array(indices);
for (var i=0; i<positions.length; i++) {
var e = positions[i];
translations[iter++] = e[0];
translations[iter++] = e[1];
translations[iter++] = this.z;
}
var material = new THREE.LineBasicMaterial({
color: 0xee6559,
opacity: 0.3,
transparent: true,
})
geometry.addAttribute('position',
new THREE.BufferAttribute(translations, 3, true, 1));
geometry.setIndex(new THREE.BufferAttribute(indices, 1, true, 1));
this.lines = new THREE.LineSegments(geometry, material);
this.lines.frustumCulled = false; // prevent mesh click on drag
this.scene.add(this.lines);
}
World.prototype.getShaderMaterial = function() {
return new THREE.RawShaderMaterial({
vertexShader: find('#vertex-shader').textContent,
fragmentShader: find('#fragment-shader').textContent,
uniforms: {
transitionPercent: { type: 'f', value: 0.0 },
pointScale: { type: 'f', value: this.getPointScale(), },
}
});
}
/**
* Helpers
**/
function get(url, handleSuccess, handleErr, handleProgress) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status === 200) {
if (handleSuccess) handleSuccess(xmlhttp.responseText)
} else {
if (handleErr) handleErr(xmlhttp)
}
};
};
xmlhttp.onprogress = function(e) {
if (handleProgress) handleProgress(e);
};
xmlhttp.open('GET', url, true);
xmlhttp.send();
};
function find(querySelector) {
return document.querySelector(querySelector);
}
window.addEventListener('resize', function() {
var size = world.getContainerSize();
world.camera.aspect = size.w / size.h;
world.camera.updateProjectionMatrix();
world.renderer.setSize(size.w, size.h);
})
function center(data) {
var ids = Object.keys(data);
// find the domains of each axis in the data
var p = Number.POSITIVE_INFINITY,
n = Number.NEGATIVE_INFINITY,
domains = {x: {min: p, max: n}, y: {min: p, max: n}};
for (var i=0; i<ids.length; i++) {
vals = data[ids[i]];
if (vals[0] < domains.x.min) domains.x.min = vals[0];
if (vals[0] > domains.x.max) domains.x.max = vals[0];
if (vals[1] < domains.y.min) domains.y.min = vals[1];
if (vals[1] > domains.y.max) domains.y.max = vals[1];
}
// center each axis 0:1
for (var i=0; i<ids.length; i++) {
var d = data[ids[i]];
d[0] = (d[0]-domains.x.min)/(domains.x.max-domains.x.min);
d[1] = (d[1]-domains.y.min)/(domains.y.max-domains.y.min);
}
return data;
}
function getPointTranslations(data) {
var ids = Object.keys(data);
var arr = new Float32Array(ids.length*3),
iter = 0;
for (var i=0; i<ids.length; i++) {
arr[iter++] = data[ids[i]][0];
arr[iter++] = data[ids[i]][1];
arr[iter++] = world.z;
}
return arr;
}
function getColors(data, masterCounts) {
var ids = Object.keys(data);
var maxMasters = 0;
for (var i=0; i<ids.length; i++) {
if (masterCounts[ids[i]] > maxMasters) maxMasters = masterCounts[ids[i]];
}
var colors = [
'#1f77b4', '#86abd7', '#cbcdd3', '#f8dba8',
'#eec570', '#eba055', '#ee6559',
];
var arr = new Float32Array(ids.length * 3),
iter = 0;
for (var i=0; i<ids.length; i++) {
var nMasters = Math.min(colors.length, masterCounts[ids[i]] || 0);
var hex = colors[ Math.floor(colors.length * (nMasters / maxMasters)) ];
var c = hexToRgb(hex);
arr[iter++] = c.r / 255;
arr[iter++] = c.g / 255;
arr[iter++] = c.b / 255;
}
return arr;
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? '0' + hex : hex;
}
function rgbToHex(r, g, b) {
return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
} : {r: 0, g: 0, b: 0};
}
var world = new World();
html,
body {
width: 100%;
height: 100%;
background: linear-gradient(#efefef, #efefef);
}
body {
margin: 0;
overflow: hidden;
}
div#select-target {
padding: 20px 0;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
font-family: 'Mallory';
text-indent: 0.01px;
text-overflow: '';
border: none;
padding: 7px 40px 7px 10px;
background-image: url(down-caret.png);
background-position: 90% 50%;
background-size: 15px;
background-repeat: no-repeat;
font-size: 1em;
text-transform: uppercase;
border: 1px solid #c7c7c7;
font-family: arial, sans-serif;
}
#render-container {
text-align: center;
max-height: 100%;
max-width: 100%;
padding-bottom: 20px;
}
#render-target {
margin: 0 auto;
width: 700px;
height: 700px;
}
<div id='render-container'>
<div id='select-target'></div>
<div id='render-target'></div>
</div>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/three.min.js'></script>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/trackball-controls.min.js'></script>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/tweenlite.min.js'></script>
<script type='x-shader/x-vertex' id='vertex-shader'>
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float transitionPercent;
uniform vec3 cameraPosition;
uniform float pointScale;
attribute vec3 position;
attribute vec3 translation;
attribute vec3 target;
attribute vec3 color;
varying vec3 vColor;
float scalePointZ(in vec4 pos, in vec3 cameraPosition) {
float zDelta = pow(pos[2] - cameraPosition[2], 2.0);
float delta = pow(zDelta, 0.5);
float scaled = pointScale / delta;
return scaled;
}
void main() {
vec3 t1 = position + translation;
vec3 t2 = position + target;
vec3 pos = mix(t1, t2, clamp(transitionPercent, 0.0, 1.0));
vec4 mvPos = modelViewMatrix * vec4(pos, 1.0);
gl_Position = projectionMatrix * mvPos;
gl_PointSize = 6.0;
vColor = color;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
varying vec3 vColor;
void main() {
// make points circular
vec2 coord = gl_PointCoord - vec2(0.5);
if (length(coord) > 0.5) discard;
// set point color
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
</script>
但是,我一直在努力使用线条的原始着色器 Material 来实现相同的场景。这是我尝试为原始着色器 Material 设置线条的方法之一:
World.prototype.addEdges = function() {
var indices = [],
positions = [],
idToIndex = {}, // {node id: index in edgePositions}
ids = Object.keys(this.edges);
// flatten edges into [[s,t],[s,t]]
for (var i=0; i<ids.length; i++) {
var idEdges = this.edges[ids[i]];
for (var j=0; j<idEdges.length; j++) {
// here ids[i] is a master node id, idEdges is list of
// apprentice node ids
var masterId = ids[i];
var apprenticeId = idEdges[j];
if (!(masterId in idToIndex)) {
idToIndex[masterId] = positions.length;
positions.push(this.positions[masterId]);
}
if (!(apprenticeId in idToIndex)) {
idToIndex[apprenticeId] = positions.length;
positions.push(this.positions[apprenticeId]);
}
indices = indices.concat([
idToIndex[masterId],
idToIndex[apprenticeId]
]);
}
}
var geometry = new THREE.BufferGeometry(),
translations = new Float32Array(3*positions.length),
iter = 0,
indices = new Uint16Array(indices);
for (var i=0; i<positions.length; i++) {
var e = positions[i];
translations[iter++] = e[0];
translations[iter++] = e[1];
translations[iter++] = this.z;
}
var material = this.getShaderMaterial().clone();
geometry.addAttribute('position',
new THREE.BufferAttribute(new Float32Array([0, 0, 0]), 3, true, 1));
geometry.addAttribute('translation',
new THREE.BufferAttribute(translations, 3, true, 1));
geometry.addAttribute('target',
new THREE.BufferAttribute(translations, 3, true, 1));
geometry.setIndex(new THREE.BufferAttribute(indices, 1, true, 1));
this.lines = new THREE.LineSegments(geometry, material);
this.lines.frustumCulled = false; // prevent mesh click on drag
this.scene.add(this.lines);
}
然而,这什么也没有呈现。有谁知道我如何使用上面定义的原始着色器 Material 渲染上面的线条?任何指示或建议都会非常有帮助!
最佳答案
我认为发生这种情况是因为您在片段着色器中使用了 gl_PointCoord
,尽管您渲染的不是点而是线。如果我删除以下两行代码,您的行将被渲染:
vec2 coord = gl_PointCoord - vec2(0.5);
if (length(coord) > 0.5) discard;
演示:https://jsfiddle.net/Ldynhxkq/
也许对两个基元使用不同的着色器程序会更好。
关于javascript - Three.js:将 RawShaderMaterial 与 LineSegments 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55777403/
我有一个由一组点组成的多边形,我想通过组合对应点的列表然后将最后一个点与第一个点组合来找到该多边形的线段列表 例如:点列表 - (p1,p2,p3,p4,p5,p6) 线段列表 - ((p1,p2),
这是 passing a color array for segments to THREE.LineSegments 的后续内容我希望找到并回答避免我完全陌生的低级着色器( potentially
我有一个 THREE.LineSegments 对象,我想动态更改顶点数。但是,当我修改几何顶点数组时,任何带有已删除顶点的线都将保留原样。 有没有办法在创建几何体后删除顶点? 例如,下面我采用了一个
我正在研究 Three.JS 中线条路径的可视化,并已成功将一堆具有正确顶点的线条添加到场景中,以及我想要的 Material ,但线条很难看到。有没有一种方法可以将线段转换为某种管,而不必从头开始并
在 Wpf 中你可以
我使用两个 Point 来定义一个 Line 和一个 LineSegment,例如: class Point { ... }; class Line { Point p1, p2; //...
我试图让 Three.js 仅渲染几何图形的 FrontSide 轮廓。我想要实现的是看起来尽可能接近这个: 使用 BoxGeomtry 我已经接近了我想要的效果,但是在 CylinderGeomet
我已经创建了一个示例来在 three.js 中绘制一个 LineSegment。我已将 vertexColors 应用于其 material 并为顶点推送 color。现在,当我将鼠标悬停在 Line
我在third.js中创建了两个绘制线条的示例,一个使用不同的geometry和material,另一个仅使用一种 >几何体和一种 Material 。 fiddle 的链接是:https://jsf
我正在处理一个渲染点和线段的 three.js 场景。 The scene如果我为线条使用 LineBasicMaterial Material ,渲染效果很好: /** * constructor
我正在研究 scene将一些 THREE.LineSegments 呈现为线框。我现在想慢慢地移动 LineSegments Material 中的顶点(这个对象在上面的场景中被命名为 warehou
我是一名优秀的程序员,十分优秀!