d3d transform matrix 和 vs 的一点优化

本文详细介绍了3D图形渲染中的顶点坐标变换过程,包括世界变换、视图变换和投影变换,并讨论了不同坐标系下进行光照计算的方法。此外,还探讨了如何通过优化矩阵运算来提高渲染效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.顶点坐标变换按照 v.pos*world*view*proj

2.光照可以在model,world或者view space计算,需把顶点坐标和light pos变换到同一坐标系下,再计算光照

3.env map和光照类似,变换的是摄像机位置。

4.软件计算的话,最好变换到model space,这样每个顶点只需一次矩阵运算。

 

为了减少矩阵计算次数,vs const只需world*view和proj即可,可以减少一次矩阵计算,传递给vs的light pos需转换到view space.

 

d3d建议的另外一个办法是,把view matrix设置为identity,所有变换放在world,以提高效率

 

 

 

 

 

 

好的,让我们来制作一个复杂的D3弦图,其中包括以下交互: 1. 鼠标悬停时显示弦段的详细信息。 2. 点击弦段时,将相关的节点弦段高亮显示。 3. 点击节点时,将与该节点相关的所有弦段高亮显示。 4. 双击节点时,展开一个子弦图以显示该节点的上下文信息。 下面是实现该弦图交互的代码: ```javascript // 设置画布大小边距 var margin = { top: 50, right: 50, bottom: 50, left: 50 }, width = 800 - margin.left - margin.right, height = 800 - margin.top - margin.bottom; // 创建SVG元素 var svg = d3.select("#chart") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // 弦图布局 var chord = d3.chord() .padAngle(0.05) .sortSubgroups(d3.descending); // 弦图颜色比例尺 var color = d3.scaleOrdinal() .domain(d3.range(4)) .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b"]); // 弦图外半径内半径 var outerRadius = Math.min(width, height) * 0.5 - 40, innerRadius = outerRadius - 30; // 根据数据生成弦图的矩阵 var matrix = [ [11975, 5871, 8916, 2868], [1951, 10048, 2060, 6171], [8010, 16145, 8090, 8045], [1013, 990, 940, 6907] ]; // 弦图节点名称 var nodes = ["Group A", "Group B", "Group C", "Group D"]; // 通过矩阵节点名称生成弦图的数据 var chords = chord(matrix); // 定义弦段的路径生成器 var arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); // 定义弦的路径生成器 var ribbon = d3.ribbon() .radius(innerRadius); // 生成弦段 var group = svg.append("g") .selectAll("g") .data(chords.groups) .enter() .append("g"); // 添加弦段路径 group.append("path") .style("fill", function(d) { return color(d.index); }) .style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) .attr("d", arc) .on("mouseover", function(d) { // 鼠标悬停时显示弦段的详细信息 d3.select(this).style("fill", "yellow"); }) .on("mouseout", function(d) { d3.select(this).style("fill", color(d.index)); }) .on("click", function(d) { // 点击弦段时,将相关的节点弦段高亮显示 group.selectAll("path") .filter(function(e) { return e.source.index != d.index && e.target.index != d.index; }) .style("opacity", 0.1); group.selectAll("path") .filter(function(e) { return e.source.index == d.index || e.target.index == d.index; }) .style("stroke", "red") .style("stroke-width", 2); }); // 添加弦路径 svg.append("g") .attr("fill-opacity", 0.67) .selectAll("path") .data(chords) .enter() .append("path") .attr("d", ribbon) .style("fill", function(d) { return color(d.target.index); }) .style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }) .on("mouseover", function(d) { // 鼠标悬停时显示弦段的详细信息 d3.select(this).style("fill", "yellow"); }) .on("mouseout", function(d) { d3.select(this).style("fill", color(d.target.index)); }); // 添加节点标签 group.append("text") .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) .attr("dy", ".35em") .attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + (innerRadius + 26) + ")" + (d.angle > Math.PI ? "rotate(180)" : ""); }) .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .text(function(d, i) { return nodes[i]; }) .on("click", function(d, i) { // 点击节点时,将与该节点相关的所有弦段高亮显示 group.selectAll("path") .filter(function(e) { return e.source.index != i && e.target.index != i; }) .style("opacity", 0.1); group.selectAll("path") .filter(function(e) { return e.source.index == i || e.target.index == i; }) .style("stroke", "red") .style("stroke-width", 2); }) .on("dblclick", function(d, i) { // 双击节点时,展开一个子弦图以显示该节点的上下文信息 var newData = [ [11975, 5871, 8916], [1951, 10048, 2060], [8010, 16145, 8090] ]; var newNodes = ["Subgroup A", "Subgroup B", "Subgroup C"]; var newChords = chord(newData); outerRadius = Math.min(width, height) * 0.5 - 80; innerRadius = outerRadius - 30; arc.innerRadius(innerRadius) .outerRadius(outerRadius); ribbon.radius(innerRadius); group.remove(); svg.selectAll("text").remove(); group = svg.append("g") .selectAll("g") .data(newChords.groups) .enter() .append("g"); group.append("path") .style("fill", function(d) { return color(d.index); }) .style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) .attr("d", arc); svg.append("g") .attr("fill-opacity", 0.67) .selectAll("path") .data(newChords) .enter() .append("path") .attr("d", ribbon) .style("fill", function(d) { return color(d.target.index); }) .style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }); group.append("text") .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) .attr("dy", ".35em") .attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + (innerRadius + 26) + ")" + (d.angle > Math.PI ? "rotate(180)" : ""); }) .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .text(function(d, i) { return newNodes[i]; }); }); ``` 这段代码使用D3库的`chord`函数来生成弦图的数据,然后使用`arc``ribbon`函数分别生成弦段弦的路径。在`mouseover`、`click``dblclick`事件处理函数中,我们可以实现鼠标悬停、点击双击时的交互效果。其中,双击事件处理函数会生成一个子弦图,以展示与双击节点相关的上下文信息。 这个复杂的D3弦图交互可以帮助用户更好地理解探索数据,提高数据可视化的交互性易用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值