0

I am currently trying to draw billboards and some geometry with "modern opengl approach". Problem is that I cannot force billboards to keep their positions in space.

I need to link text positions with positions of another objects. Coordinates of text position are (3,3,3) and same coordinates has end of black line. In some positions I have exactly what I need: text is drawn at the end of line, but in some - it is too far from the end of line.

enter image description here enter image description here

My render code:

           public void Draw() 
           {
           //Set up matrices 
            projectionMatrix = Matrix4.CreateOrthographic(_width, _height, -10000, 10000);
            modelMatrix = Matrix4.Identity;
            viewMatrix = Matrix4.CreateRotationY((float)xrot) *
                        Matrix4.CreateRotationX((float)yrot) *
                        Matrix4.CreateScale((float)scale);

            var viewPort = new Rectangle(-(_width / 2), -(_height / 2), _width, _height);
            var viewportTransformationMatrix = ComputeViewportTransformationMatrix(viewPort, -100, 100);
            var viewportOrthographicMatrix = ComputeViewportOrthographicMatrix(viewPort);

            worldViewProj = modelMatrix * viewMatrix * projectionMatrix;

            //DRAW AXISES 
            GL.UseProgram(axisesProgramID);
            axisesProgram.Uniforms["worldViewProj"].SetValue(worldViewProj);

            axisesVAO.Bind();
            for (int i = 0; i < 4; i++)
            {
                GL.DrawArrays(PrimitiveType.Lines, i * 2, 2);
            }

            //DRAW TEXT WITH PRE-CREATED TEXTURE
            GL.UseProgram(textProgramID);

            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, textureID);

            //set-up uniforms
                  textProgram.Uniforms["og_viewportOrthographicMatrix"].SetValue(viewportOrthographicMatrix);
            textProgram.Uniforms["og_viewportTransformationMatrix"].SetValue(viewportTransformationMatrix);
            textProgram.Uniforms["Position"].SetValue(new float[] { 3.0f, 3.0f, 3.0f });
            textProgram.Uniforms["projectionMatrix"].SetValue(projectionMatrix);
            textProgram.Uniforms["modelViewMatrix"].SetValue(modelViewMatrix);
            textProgram.Uniforms["og_texture0"].SetValue(0);

            GL.DrawArrays(PrimitiveType.Points, 0, 1);
            GL.BindTexture(TextureTarget.Texture2D, 0);
            }

            public Matrix4 ComputeViewportTransformationMatrix(Rectangle viewport, float nearDepthRange, float farDepthRange)
        {
            double halfWidth = viewport.Width * 0.5;
            double halfHeight = viewport.Height * 0.5;
            double halfDepth = (farDepthRange - nearDepthRange) * 0.5;

            //
            // Bottom and top swapped:  MS -> OpenGL
            //
            return new Matrix4(
                (float)halfWidth, 0.0f, 0.0f, (float)viewport.Left + (float)halfWidth,
                0.0f, (float)halfHeight, 0.0f, (float)viewport.Top + (float)halfHeight,
                0.0f, 0.0f, (float)halfDepth, (float)nearDepthRange + (float)halfDepth,
                0.0f, 0.0f, 0.0f, 1.0f);
        }
        public static Matrix4 ComputeViewportOrthographicMatrix(Rectangle viewport)
        {
            //
            // Bottom and top swapped:  MS -> OpenGL
            //
            return Matrix4.CreateOrthographicOffCenter(
                (float)viewport.Left, (float)viewport.Right,
                (float)viewport.Top, (float)viewport.Bottom,
                0.0f, 1.0f);
        }

My axises shaders are really simple path-through.

//VERTEX SHADER
#version 150 core
in vec3 in_Position;
in vec3 in_Color;

out vec4 color;

uniform mat4 worldViewProj;

void main(void) {
    gl_Position = worldViewProj * vec4(in_Position, 1.0);
    color = vec4(in_Color, 1.0f);
}

//FRAGMENT SHADER
#version 150 core

in vec4 color;

out vec4 out_Color;

void main(void) 
{
    out_Color = color;  
}

Here are text (texture) shaders:

//VERTEX SHADER
#version 330
out float gsOrigin;
out vec2 gsPixelOffset;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 og_viewportTransformationMatrix;


uniform float origin = 6;                  // TODO:  Why does this not work when float is int?
uniform vec2 pixelOffset = vec2(0,0);

uniform vec3 Position;

vec4 ModelToWindowCoordinates(
    vec4 v, 
    mat4 modelViewPerspectiveMatrix, 
    mat4 viewportTransformationMatrix)
{
    v = modelViewPerspectiveMatrix * v;                  // clip coordinates
    v.xyz /= v.w;                                                  // normalized device coordinates
    v.xyz = (viewportTransformationMatrix * vec4(v.xyz, 1.0)).xyz; // window coordinates
    return v;
}

void main()                     
{
    gl_Position =  ModelToWindowCoordinates ( vec4(Position, 1.0f) , modelViewMatrix * projectionMatrix , og_viewportTransformationMatrix ) ;

    gsOrigin = origin;
    gsPixelOffset = pixelOffset;
}

//GEOMETRY SHADER
#version 330 
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;

in float gsOrigin[];
in vec2 gsPixelOffset[];

out vec2 fsTextureCoordinates;

uniform sampler2D og_texture0;
uniform float og_highResolutionSnapScale;

uniform mat4 og_viewportOrthographicMatrix;

void main()
{
    float originScales[3] = float[](0.0, 1.0, -1.0);

    vec2 halfSize = vec2(textureSize(og_texture0, 0)) * 0.5 * og_highResolutionSnapScale;

    vec4 center = gl_in[0].gl_Position;
    int horizontalOrigin = int(gsOrigin[0]) & 3;         // bits 0-1
    int verticalOrigin = (int(gsOrigin[0]) & 12) >> 2;   // bits 2-3
    center.xy += (vec2(originScales[horizontalOrigin], originScales[verticalOrigin]) * halfSize);
    center.xy += (gsPixelOffset[0] * og_highResolutionSnapScale);


    vec4 v0 = vec4(center.xy - halfSize, 0, 1.0);
    vec4 v1 = vec4(center.xy + vec2(halfSize.x, -halfSize.y), 0, 1.0);
    vec4 v2 = vec4(center.xy + vec2(-halfSize.x, halfSize.y), 0, 1.0);
    vec4 v3 = vec4(center.xy + halfSize, 0, 1.0);


    gl_Position =  og_viewportOrthographicMatrix * v0;
    fsTextureCoordinates = vec2(0.0, 0.0);
    EmitVertex();

    gl_Position = og_viewportOrthographicMatrix * v1;
    fsTextureCoordinates = vec2(1.0, 0.0);
    EmitVertex();

    gl_Position = og_viewportOrthographicMatrix * v2;
    fsTextureCoordinates = vec2(0.0, 1.0);
    EmitVertex();

    gl_Position = og_viewportOrthographicMatrix * v3;
    fsTextureCoordinates = vec2(1.0, 1.0);
    EmitVertex();
}

//FRAGMENT SHADER 
#version 330   
in vec2 fsTextureCoordinates;

out vec4 fragmentColor;

uniform sampler2D og_texture0;
uniform vec3 u_color;

void main()
{
    vec4 color = texture(og_texture0, fsTextureCoordinates);

    if (color.a == 0.0)
    {
        discard;
    }
    fragmentColor = vec4(color.rgb * u_color.rgb, color.a);    
}
frankie
  • 728
  • 1
  • 10
  • 28
  • Well, judging by your screenshot what you are ultimately trying to do is find the window-space coordinate of the end-point of your black line segment. That will be the general origin of your text (you probably want to move it a few pixels up and over). I don't see anywhere in your code where you do this to compute your `position` uniform. – Andon M. Coleman Aug 28 '14 at 00:23
  • @Andon M. Coleman: But I thought that ModelToWindowCoordinates function performs this. Isn't it? – frankie Aug 28 '14 at 06:44
  • Possibly depending on how the model matrix is setup, but hard coding model-space 3,3,3 coordinates and then transforming those probably is not the same thing. – Andon M. Coleman Aug 28 '14 at 12:46

1 Answers1

1

To me it looks like there is some basic coordinate system confusion. I have not checked everything here, but to me,

worldViewProj = modelMatrix * viewMatrix * projectionMatrix;

looks like the wrong way round, as vertices should be multiplied from the right like

projection*view*model*vertex

The same issue is within your shaders. Also, i am not entirely sure, but it seems you are computing pixel coordinates for gl_Position in the shader (as you are applying some viewporttransform in the function ModelToWindowCoordinates). Since pixel coordinates may e.g. range from 0,0 to 1920,1080 they are not correct for gl_Position, which should be in clip coordinates.

I think you should read up a good tutorial about 3d billboarding and the math, for example this one looks quite interesting. Then modify the sample code to fit your needs step by step.

Thomas
  • 725
  • 4
  • 14