Point sprites distance and size

Hello community,

I use point sprites. They appear correctly except that when the camera is far,
they look bigger and when the camera is near them, they are small…

Shader:

ps = gl::GlslProg::create(gl::GlslProg::Format().vertex(CI_GLSL(150,

uniform mat4 ciModelViewProjection;
in vec4 ciPosition;
in vec4 ciColor;
in float vSize;

out vec4 color;

void main(void)
{
	gl_Position = ciModelViewProjection * ciPosition;
	gl_PointSize = vSize;
	color = ciColor;
}

)).fragment(CI_GLSL(150,

uniform sampler2D uTexture;
in vec4 color;

out vec4 oColor;

void main(void)
{
	oColor = color * texture(uTexture, gl_PointCoord);
}

)));

Any answer welcome,
Azerty

Hi,

there’s probably something wrong with the way you calculate vSize, but you didn’t provide that code so it’s just a guess.

The size of the point sprite should change with its distance to the camera. One way to obtain this distance is as follows:
float cameraDist = length( vec3( ciModelView * ciPosition ) )

There’s a lot of ways to then calculate an appropriate size, e.g. using log or sqrt, but a simple formula can be found here. See also this post.

~Paul

Hello,

I’ve modified the shader as follow and I still have the same problem. The point sprites
are not correctly sized depending of the distance.

	const float maxDistance = 100.0;
	in mat4 ciModelView;
	uniform mat4 ciModelViewProjection;
	in vec4 ciPosition;
	in vec4 ciColor;
	in float vSize;

	out vec4 color;

	void main(void)
	{
		float cameraDist = length(vec3(ciModelView * ciPosition));
		float pointScale = 1.0 - (cameraDist / maxDistance);
		gl_Position = ciModelViewProjection * ciPosition;
		gl_PointSize = vSize * pointScale;
		color = ciColor;
	}

)).fragment(CI_GLSL(150,

	uniform sampler2D uTexture;
	in vec4 color;

	out vec4 oColor;

	void main(void)
	{
		oColor = color * texture(uTexture, gl_PointCoord);
	}
)));

Here is how I initialize the point sprites:

_psTex = Texture2d::create(loadImage("data/ps.png"));

vec4 c[5] =
{
	vec4(.796f, .631f, .537f, .5f),
	vec4(.791f, .759f, .553f, .5f),
	vec4(.522f, .741f, .796f, .5f),
	vec4(.662f, .557f, .744f, .5f),
	vec4(.551f, .752f, .625f, .5f)
};

for (int i = 0; i < _numPoints; ++i)
{
	vec4 pos = vec4(randFloat(-10.f, 10.f), randFloat(-1.5f, 1.5f), randFloat(-10.f, 10.f), 1.f);
	_positions.push_back(pos);
	vec4 mov = vec4(0.f);
	_movement.push_back(mov);
	vec4 fp = vec4(0.f);
	_finalpos.push_back(fp);
	_sizes.push_back(10.f + .1f * (rand() % 300));
	_speed.push_back(.25f + .75f * randFloat(.1f, 1.f));
	_colors.push_back(c[rand() % 5]);
}

auto posLayout = gl::VboMesh::Layout().attrib(geom::POSITION, 4).usage(GL_DYNAMIC_DRAW);
auto colorAndSizeLayout = gl::VboMesh::Layout().attrib(geom::COLOR, 4).attrib(geom::CUSTOM_0, 1).usage(GL_STATIC_DRAW);

auto mesh = gl::VboMesh::create(_numPoints, GL_POINTS, { posLayout, colorAndSizeLayout });
mesh->bufferAttrib(geom::POSITION, _finalpos);
mesh->bufferAttrib(geom::COLOR, _colors);
mesh->bufferAttrib(geom::CUSTOM_0, _sizes);

_geometry1 = gl::Batch::create(mesh, ps, { { geom::Attrib::CUSTOM_0, "vSize" } });
_geometry2 = gl::Batch::create(mesh, ps, { { geom::Attrib::CUSTOM_0, "vSize" } });

ciModelView should be passed as a uniform, not an attribute:

	const float maxDistance = 100.0;
	uniform mat4 ciModelView;
	uniform mat4 ciModelViewProjection;
	in vec4 ciPosition;
    ....