Okay, I think I have a solution. I don’t quite know what the issue was, but this seems to work.

```
sa = ShaderAttrib.make().set_shader_auto(True)
#state = RenderState.make(ColorAttrib.make_flat(LColor(0, 1.0, 1.0, 0.2)), sa)
state = RenderState.make(sa)
self.particle_effect.set_state(state)
shader = Shader.load(Shader.SL_GLSL, "../shaders/misc/plain.vert", "../shaders/misc/plain.frag")
self.particle_effect.set_shader( shader )
self.particle_effect.set_shader_input( "alpha", 1 ) # min(scale*0.3, 1)-1.5)
self.particle_effect.set_shader_input( "main_color", (1,1,1) ) # Don't modulate color
self.particle_effect.set_texture(loader.load_texture("../textures/misc/noise.png"))
self.particle_effect.set_depth_test(True)
self.particle_effect.set_depth_write(False)
self.particle_effect.set_light_off(True)
self.particle_effect.hide( 0b0001 ) # Hide from shadow caster
self.particle_effect.set_two_sided(False)
self.particle_effect.set_transparency(True)
self.particle_effect.setAttrib(
ColorBlendAttrib.make(
ColorBlendAttrib.M_add,
ColorBlendAttrib.O_incoming_alpha,
ColorBlendAttrib.O_one_minus_incoming_alpha
)
)
```

```
Particle:
#####################
## Smoke:
p0 = Particles.Particles('particles-1')
# Particles parameters
p0.setFactory("PointParticleFactory")
p0.setRenderer("SpriteParticleRenderer")
p0.setEmitter("DiscEmitter")
p0.setPoolSize(200)
p0.setBirthRate(20000.0000)
p0.setLitterSize(7)
p0.setLitterSpread(3)
p0.setSystemLifespan(10)
p0.setLocalVelocityFlag(1)
p0.setSystemGrowsOlderFlag(0)
# Factory parameters
p0.factory.setLifespanBase(1.0000)
p0.factory.setLifespanSpread(0.0000)
p0.factory.setMassBase(2.0000)
p0.factory.setMassSpread(2.0000)
p0.factory.setTerminalVelocityBase(0.0000)
p0.factory.setTerminalVelocitySpread(0.0000)
# Point factory parameters
# Renderer parameters
p0.renderer.setAlphaMode(BaseParticleRenderer.PR_ALPHA_IN_OUT)
#p0.renderer.setUserAlpha(0.80)
# Sprite parameters
#p0.renderer.setStartColor(LVector4(0.5, 0.90, 1.00, 1.00))
#p0.renderer.setEndColor(LVector4(0.0, 0.9, 1.00, 1.00))
p0.renderer.addTextureFromFile('particles/dust.png')
p0.renderer.setColor(Vec4(0.1, 0.1, 0.1, 0.5))
p0.renderer.setXScaleFlag(1)
p0.renderer.setYScaleFlag(1)
p0.renderer.setAnimAngleFlag(1)
p0.renderer.setInitialXScale(0.2500)
p0.renderer.setFinalXScale(0.5)
p0.renderer.setInitialYScale(0.2500)
p0.renderer.setFinalYScale(0.5)
p0.renderer.setNonanimatedTheta(0.0000)
p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PP_BLEND_LINEAR)
p0.renderer.setAlphaDisable(0)
p0.renderer.setColorBlendMode(ColorBlendAttrib.M_add, ColorBlendAttrib.OIncomingAlpha, ColorBlendAttrib.OOneMinusIncomingAlpha)
# Emitter parameters
p0.emitter.setEmissionType(BaseParticleEmitter.ETCUSTOM)
p0.emitter.setAmplitude(3.0000)
p0.emitter.setAmplitudeSpread(2.0000)
p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 4.0000))
p0.emitter.setExplicitLaunchVector(Vec3(0.0000, 0.0000, 0.0000))
p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000))
# Disc parameters
p0.emitter.setRadius(0.1000)
p0.emitter.setOuterAngle(114.7751)
p0.emitter.setInnerAngle(66.3706)
p0.emitter.setOuterMagnitude(1.0000)
p0.emitter.setInnerMagnitude(0.6000)
p0.emitter.setCubicLerping(0)
self.addParticles(p0)
#f0 = ForceGroup.ForceGroup('vertex')
## Force parameters
#force0 = LinearVectorForce(Vec3(0.0000, 0.0000, -9.8100), 1.0000, 0)
#force0.setVectorMasks(1, 1, 1)
#force0.setActive(1)
#f0.addForce(force0)
#self.addForceGroup(f0)
```

The shader is just a very simple shader that takes the texture color, multiplies it by “main_color” and returns the result.

I assume one of the values I set above was inherited from a parent node and had the wrong value.