Three.js:使用实例化几何体处理每个实例的纹理偏移

时间:2019-01-03 20:20:56

标签: three.js

我的问题简短:是否有示例可以使用Three.js中的带索引的实例化四边形以自定义(非网格状)偏移量渲染纹理?

关于上下文的问题:我正在一个Three.js场景中工作,该场景有很多四边形,每个四边形用于显示来自图像图集的图像。地图集中的每个图像的每侧均为32px。使用索引的实例化几何体渲染四边形。因此,有4个顶点为所有四边形实例定义“原型”,并且所有特定于实例的信息都作为属性提供给@page @model Definicje.Pages.Shared._TextBoxInfoPartialModel <button type="button" class="visibility-toggler" visibility-toggler="#hint-math@(Model.ID)">Wstaw wzór</button> <div id="hint-math@(Model.ID)" class="hintbox"> some text </div>

挑战在于,要在给定四边形上表示的图像包含在地图集的32px正方形中,但是这些小图像可能有边距。因此,尽管图像在地图集中形成了各种网格,但每个图像的顶部和侧面(样本地图集区域)都有一个未用像素的已知边距:

enter image description here

处理这些边距的相关属性是:

@await Html.PartialAsync("_TextBoxInfoPartial", new _TextBoxInfoPartialModel { ID = g.ID + "" })

然后在片段着色器中,我可以使用以下方法渲染实例的完整32px单元格:

RawShaderMaterial

我的问题是:假设我可以创建一个vec2 var geometry = new THREE.InstancedBufferGeometry(); // uv identifies the blueprint uv values geometry.addAttribute('uv', new THREE.BufferAttribute(new Float32Array([ 1, 1, 0, 1, 0, 0, 1, 0, ]), 2)); // texOffset = the offset of an instance's 32px cell in the atlas {x,y} geometry.addAttribute('texOffset', new IBA(... 2, true, 1)); // uvOffset = the left/right and top/bottom margins of an instance's image in its 32px cell geometry.addAttribute('uvOffset', new IBA(..., 2, true, 1)); ,在其32px单元格容器中包含图像的左右偏移量,那么如何只渲染包含图像的32px正方形的子集?他人在此问题上提供的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

UV的范围是[0.0,1.0],所以假设您希望左侧/右侧的边距为0.1。这使您的可见范围为[0.1, 0.9]。要使边缘不可见,可以使用step() function来创建这样的不透明度曲线:

enter image description here

低于0.1且高于0.9的不透明度为0。

// You first declare the range of the margin (this has x and y)
vec2 uvMargin = vec2(0.1, 0.2);

// Anything outside the margin will have 0 opacity, 
// anything inside the margin will have 1 opacity

// First, you apply a step() function to the left X value
float opacity = step(uvMargin.x, vUV.x);

// then to the right X value (1.0 - margin)
opacity *= step(vUV.x, 1.0 - uvMargin.x);

// then the top Y value
opacity *= step(uvMargin.y, vUV.y)

// then the bottom Y value
opacity *= step(vUV.y, 1.0 - uvMargin.y);

// Sample the texture
vec2 scaledUv = vUv + vTextureOffset;
gl_FragColor = texture2D(texIdx, scaledUv);

// Apply opacity to alpha
gl_FragColor.a = opacity;

这可以优化,但是为了清楚起见,我逐步进行了操作。将transparent: true设置为材料时,您会看到空白处的任何内容都是不可见的。

  • 如果您发现GPU选择方面存在问题,也许您可​​以为不透明度添加难以区分的数量,例如gl_FragColor.a = opacity + 0.01;
  • 如果发现不喜欢的锯齿或锯齿状边缘,则可以尝试使用smoothstep()
  • 您必须将uvMargin声明为InstancedBufferAttribute,而不是像我一样在着色器中声明。