How do I take a compute shader result and apply it to a material?

I’m trying to see the output of a compute shader on the screen, but I just can’t get it to work:

    if self.texture_out then
        render.set_compute("game_of_life")
        --I believe that the following can use layout too if I don't want to specify stuff in .compute
        render.enable_texture(hash("texture_out"), self.texture_out)
        --texture_out has special flags that make it work
        --render.set_cons
        --local constants = render.constant_buffer()
        --constants["cons.color"] = vmath.vector4(1.0, 1.0, 0.0, 1.0)
        --number of global invocations, needs to match texture:
        render.dispatch_compute(256, 256, 1)--, {constants = constants})
        
        render.set_compute()
        render.disable_texture(hash("texture_out"))

        --Now, we attempt to set the texture to the material. Note that this is 
        --one at a time and therefore suboptimal:

        --In the same way, it should be possible to write the texture to the string:
        render.enable_texture(hash("texture_sampler"), self.texture_out)
        render.draw(predicates.texture_render, draw_options_world)
        render.disable_texture(hash("texture_sampler"))
    end

Compute shader:

#version 430

layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

// We need to give this uniform block a binding point. Let's use 0.
//layout(binding = 0) uniform Constants {
//    vec4 color;
//} cons; // <-- We give the block an "instance name" to use it

// The binding for texture_out must now be different, e.g., 1.
layout(binding = 1, rgba32f) uniform image2D texture_out;

void main()
{
    ivec2 tex_coord = ivec2(gl_GlobalInvocationID.xy);

    // Access 'color' through the block's instance name
    imageStore(texture_out, tex_coord, vec4(1.0, 0.0,0.0,1.0));
}

And the fragment shader:

#version 430 core

// Input texture coordinates from the vertex shader
in vec2 var_texcoord0;

// Output fragment color
layout(location = 0) out vec4 out_fragColor;

// Uniform sampler for the 2D texture
uniform sampler2D texture_sampler;

void main()
{
	// Sample the texture at the given texture coordinates
	vec4 intermediate = texture(texture_sampler, var_texcoord0);

	// Set the output fragment color
	out_fragColor = vec4(intermediate.rgb, 1.0);
}

I’ve confirmed that the fragment shader is rendering to the screen. The texture_out is currently empty, as I just see a black rectangle. What am I doing wrong? If I can figure out how to get this to work, I’d be willing to update the compute shader example.

Thanks for your help!

My (long term) goal is to learn all things about shaders so I am interested in this; currently I don’t know the answer. This question goes with the question you asked a few days ago: Compute shader example does not work (I think it would have been less confusing if you had post this there). You raised a github issue (linked on that ticket) which is good to do ( Compute shader example does not work · Issue #10861 · defold/defold · GitHub) and the devs are responding to that, and not so much in three places at once, maybe this is kind of a different question.

Is there a working example of a compute shader anywhere? It would be good to have one on the examples page (which is fantastically useful, small examples without ott bells and whistles:-) There probably is one, and I have forgotten where.

Try this example: defold-graphics-integration-tests/14-compute-shaders at master · Jhonnyg/defold-graphics-integration-tests · GitHub

3 Likes

I’m posting these in parallel: example compute project