How to draw point/circle/ellipse using OpenGL ES 2.0 GLSL

I have spend a quite some time experimenting with different solutions. Tried GL_POINT thing – didn’t work as i expected.

First, setup your render process to draw a quad. I do not want to go into details. Maybe I’ll cover 2d OpenGL ES rendering another time.

After setup, call glDrawElements.
As you see, I’m using GL_TRIANGLE_STRIP to draw quad.

glDrawElements(GL_TRIANGLE_STRIP, 4,
GL_UNSIGNED_SHORT, (void *)0);

My vertex shader:

#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

uniform mat4 mvp_matrix;
uniform vec4 u_color;

attribute vec4 a_position;
attribute vec2 a_texcoord;

varying vec4 v_color;
varying vec2 v_texcoord;

void main()
{
gl_Position = mvp_matrix * a_position;
v_color = u_color;
v_texcoord = a_texcoord;
}

u_color – I’m using this uniform to define point color.
v_color – varying shared between vertex and fragment shader. Used to transport color value to fragment shader.
a_texcoord – an attribute. Its value is determined on the basis of VBO contents.
v_textcoord – a variable used to transport texture coordinates to fragment shader.

Texture should be disabled before glDrawElements call;
Use glBindTexture(GL_TEXTURE_2D, 0);

Despite no active texture, shader will receive valid texture coordinates;

Fragment shader:


#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

varying vec4 v_color;
varying vec2 v_texcoord;

void main()
{
float l = length(v_texcoord - vec2(0.5, 0.5));

if (l > 0.5)
discard;

gl_FragColor = v_color;
}

Here is the magic.

v_texcoord isn’t just copied from VBO. Value is interpolated for each fragment shader call.

float l = length(v_texcoord - vec2(0.5, 0.5));

variable l contains distance of current rendered quad pixel from center of quad.
Because texture coordinates are normalized ( values are in the range 0.0 and 1.0) 0.5,0.5 represents center of quad.

The function /length/ is OpenGL ES2 buildin. Calculates distance between two vectors.

If distance between currently rendered pixel and center of quad is more then 0.5 pixel is discarded. When distance is less or equal 0.5, fragment is rendered using color stored in v_Color;

point_rendering

I hope this picture help to understand how it works.

Blue are texture coordinates.
Pink area is rendered using u_color/v_color.
White space where fragment shader was discarded.
Green lines – distance between fragment coordinates and quad center. Calculated by length function.

Pros and cons of this solution:

Pros:

  • Looks same regardless of size.
  • Shader can be easily modified to produce blured „nova” effect.
  • Works both on mobile and desktop

Cons:

  • No antialiasing – sharp edges.
Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: