Texture Buffers for hardware instanced geometry

Here’s some quick and dirty code showing how to do that in Panda. I may clean up the code a bit when I have time.

from random import random
from panda3d.core import *
loadPrcFileData("init-ms-meter", """
show-frame-rate-meter true
frame-rate-meter-milliseconds true
frame-rate-meter-ms-text-pattern %0.2f ms
""")

from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor

NUM_INSTANCES = 3600

vshad = """#version 330

uniform mat4 p3d_ModelViewProjectionMatrix;

in vec4 vertex;
in vec2 texcoord;

//in mat4 transform;
in vec4 offset;

out vec2 tcset;

void main() {
  gl_Position = p3d_ModelViewProjectionMatrix * (vertex + offset);
  tcset = texcoord;
}"""

fshad = """#version 330

uniform sampler2D p3d_Texture0;

out vec4 p3d_FragColor;

in vec2 tcset;

void main() {
  p3d_FragColor = texture(p3d_Texture0, tcset);
}
"""

base = ShowBase()

node = Actor('panda-model', {'walk' : 'panda-walk4'})
node.loop('walk')
node.setScale(0.01)

shader = Shader.make(Shader.SL_GLSL, vshad, fshad)
node.setShader(shader)
node.reparentTo(render)

gnode = node.find("**/+GeomNode").node()

iformat = GeomVertexArrayFormat()
iformat.setDivisor(1)
iformat.addColumn("offset", 4, Geom.NT_stdfloat, Geom.C_other)

format = GeomVertexFormat(gnode.getGeom(0).getVertexData().getFormat())
format.addArray(iformat)
format = GeomVertexFormat.registerFormat(format)

vdata = gnode.modifyGeom(0).modifyVertexData()
vdata.setFormat(format)

poswriter = GeomVertexWriter(vdata.modifyArray(2), 0)
for i in range(NUM_INSTANCES):
    poswriter.add_data3((i % 60) * 700 + random() * 100, (i // 60) * 1200 + random() * 200, 0)

poswriter = None
vdata = None
geom = None

node.setInstanceCount(NUM_INSTANCES)

node.node().setBounds(OmniBoundingVolume())
node.node().setFinal(True)

base.trackball.node().set_pos(4.7, 172.7, -49.7)
base.trackball.node().set_hpr(61.5281, 12.0915, -18.2124)

base.run()

It’s also possible to pass a matrix using this method, by using C_matrix instead of C_other and add_matrix4 instead of add_data3. However, I can’t get that to work right now. I’ll try to come back to it later.