Hi all,
I’m trying to use a compute shader to make an adjacency matrix for the boundaries between cells in a voronoi diagram. The voronoi diagram texture and the texture containing the boundary information are created by this method, as btex, and used only in simple render to texture methods with quads, their format is not altered:
# Create a GraphicsBuffer to render to, we'll get the textures out of this
finalBuffer = engine.makeOutput(pipe, "Buffer", 0, fb_prop, win_prop, flags)
ftex = pc.Texture("final texture")
ftex.setup2dTexture(texW, texH, pc.Texture.T_unsigned_byte, pc.Texture.F_rgba8)
ftex.setWrapV(pc.Texture.WM_clamp)
ftex.setWrapU(pc.Texture.WM_repeat)
ftex.setClearColor((0,0,0,0))
finalBuffer.addRenderTexture(ftex, pc.GraphicsOutput.RTM_copy_ram)
def makeBuffer(textureName: str):
buffer = engine.makeOutput(pipe, "Buffer", 0, fb_prop, win_prop, flags, finalBuffer.getGsg(), finalBuffer)
btex = pc.Texture(textureName)
btex.setup2dTexture(texW, texH, pc.Texture.T_unsigned_byte, pc.Texture.F_rgba8)
btex.setWrapV(pc.Texture.WM_clamp)
btex.setWrapU(pc.Texture.WM_repeat)
btex.setClearColor((0,0,0,0))
buffer.addRenderTexture(btex, pc.GraphicsOutput.RTM_copy_ram)
return buffer, btex
The method calling the compute shader is:
def boundaryGraph(seeds: int, voronoi: pc.Texture, boundaries: pc.Texture):
# Create the texture we'll render to
boundaryCounts = pc.Texture()
boundaryCounts.setup2dTexture(seeds, seeds, pc.Texture.T_unsigned_byte, pc.Texture.F_rgba8)
boundaryCounts.setClearColor((0,0,0,0))
# Create the node
node = pc.NodePath("compute")
# Assign the shader and the shader inputs
node.set_shader(boundaryCountShader)
node.set_shader_input("voronoi", voronoi)
node.set_shader_input("boundaries", boundaries)
node.set_shader_input("counts", boundaryCounts)
# Retrieve the underlying ShaderAttrib
sattr = node.get_attrib(pc.ShaderAttrib)
# Dispatch the compute shader
engine.dispatch_compute((int(texW / 32), int(texH / 32), 1), sattr, finalBuffer.getGsg())
return boundaryCounts
The compute shader itself is:
#version 430
// Set the number of invocations in the work group.
layout (local_size_x = 32, local_size_y = 32) in;
// Declare uniforms we will use
layout (rgba8) uniform readonly image2D voronoi;
layout (rgba8) uniform readonly image2D boundaries;
layout (rgba8) uniform image2D counts;
//============================================================
vec4 EncodeData (in ivec2 texcoord) {
vec4 count = imageLoad(counts, texcoord);
if (imageLoad(boundaries, texcoord).r == 1.0) {
// diverging
int count_d = int(count.b*256) + (int(count.r*256) << 8);
count_d += 1;
count.r = count_d >> 8;
count.b = count_d & 0x00FF;
} else {
// converging
int count_c = int(count.g*256) + (int(count.a*256) << 8);
count_c += 1;
count.g = count_c >> 8;
count.a = count_c & 0x00FF;
}
return count;
}
//============================================================
void main (void)
{
ivec2 texcoord = ivec2(gl_GlobalInvocationID.xy);
int ourPlate = int(imageLoad(voronoi, texcoord).b*256);
int theirPlate = 256 - int(imageLoad(boundaries, texcoord).a*256);
ivec2 boundary = ivec2(ourPlate-1, theirPlate-1);
vec4 pixel = EncodeData(texcoord);
imageStore(counts, boundary, pixel);
}
When I run this, the shader compiles and executes, but I get some warnings from the Graphics State Guardian and the texture renders out with its clear colour:
:display:gsg:glgsg(error): Texture boundaries has an unsized format. Textures bound to a shader as an image need a sized format.
:display:gsg:glgsg(error): Texture voronoi has an unsized format. Textures bound to a shader as an image need a sized format.
I’ve read the panda3d documentation for compute shaders that mentions using a sized format for them, but all of the textures I’m using use the sized format Texture.F_rgba8
so I’m not sure what the cause of the error is. I’ve also tried the compute shader with layout (rgba32f)
and the result is identical.
Any help is greatly appreciated!