WebGL2用drawElements索引绘制在GPU着色器实现顶点插值的方案
适配WebGL2 POINTS模式的顶点插值实现方案
优先用下面两种更简单的方案,完全不需要做索引缓冲区复用:
- 方案1:实例化绘制(性能最优,适配动态插值倍率场景)
原始顶点缓冲仅存储原生流式顶点数据,不需要额外预处理:- 绘制时调用
gl.drawArraysInstanced(gl.POINTS, 0, 原始顶点总数, 插值倍率),最后一个参数直接传2或3即可 - 顶点着色器内用
gl_VertexID取对应原始顶点的属性,用gl_InstanceID区分当前是原始点还是第几个插值点,直接做插值计算输出位置即可
- 绘制时调用
- 方案2:多倍顶点绘制(兼容性最好,无需依赖实例化接口)
直接绘制原始顶点总数 * 插值倍率个点,顶点着色器内做序号拆分即可:
该方案不需要索引缓冲区,也不需要修改原始顶点数据结构,逻辑更直观。#define INTERP_RATE 2 // 或3,也可以作为uniform变量动态传入 in vec3 aPosition; // 原始顶点属性 void main() { int originIdx = gl_VertexID / INTERP_RATE; // 对应原始顶点的索引 int interpIdx = gl_VertexID % INTERP_RATE; // 当前插值点的序号,0为原始点 // 此处按interpIdx做插值计算,输出最终位置 }
gl_VertexID、gl_InstanceID的递增规则
gl_VertexID是当前顶点在本次绘制调用的顶点序列中的顺序号,每处理一个顶点就加1,和索引缓冲区存储的索引值没有直接关系。比如你用索引缓冲[0,0,1,1,2,2]调用gl.drawElements,gl_VertexID的取值是0到5连续递增,不是重复的0/1/2。gl_InstanceID是当前实例的序号,同一个实例内所有顶点的gl_InstanceID相同,每切换一个实例就加1,完全匹配你区分原始点/插值点的需求。
当前问题根因
确实和索引复用逻辑有关:你误以为gl_VertexID会返回索引缓冲区的取值,实际取到的是连续递增的顶点序列序号,取模判断的逻辑完全错位,只有少数顶点的位置计算符合预期,最终只会显示3个点。
内容的提问来源于stack exchange,提问作者Evil
相关产品推荐
相关产品推荐

