绘制广告牌的问题

时间:2014-08-26 19:41:05

标签: opengl shader opentk

我目前正试图用“现代opengl方法”绘制广告牌和几何图形。问题是我不能强迫广告牌保持其在太空中的位置。

我需要将文本位置与其他对象的位置链接。文本位置的坐标为(3,3,3),相同的坐标为黑线的末尾。在某些位置,我完全符合我的要求:文本在行尾绘制,但在某些位置 - 它距离行尾太远。

enter image description here enter image description here

我的渲染代码:

           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);
        }

我的轴着色器是非常简单的路径。

//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;  
}

以下是文字(纹理)着色器:

//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);    
}

1 个答案:

答案 0 :(得分:1)

对我来说,看起来有一些基本的坐标系混淆。我没有在这里查看所有内容,但对我来说,

worldViewProj = modelMatrix * viewMatrix * projectionMatrix;

看起来像是错误的方式,因为顶点应该从右侧乘以

projection*view*model*vertex

同样的问题在您的着色器中。 此外,我不完全确定,但似乎你在着色器中计算gl_Position的像素坐标(因为你在函数ModelToWindowCoordinates中应用了一些viewporttransform)。由于像素坐标可以是范围从0,0到1920,1080它们对于gl_Position不正确,它应该在剪辑坐标中。

我认为你应该阅读一篇关于3D广告牌和数学的好教程 this one看起来非常有趣。然后逐步修改示例代码以满足您的需求。