Соотношение сторон изображения отсутствует при отображении нескольких текстур в элементе управления openGL - OpenTK - PullRequest
1 голос
/ 18 марта 2019

Я могу отображать три текстуры одинаково на элементе управления OpenGL, используя приведенный ниже код.Элемент управления OpenGL находится в нижней части экрана (высота равна половине высоты экрана, а ширина равна ширине экрана).Но, похоже, в OpenGL Control отсутствует соотношение сторон изображений.Большая часть моего кода вставлена ​​здесь.Подскажите, пожалуйста, в чем причина проблемы?

this.glControl1.BackColor = System.Drawing.Color.Blue;
this.glControl1.Location = new System.Drawing.Point(13, 412);
this.glControl1.Margin = new System.Windows.Forms.Padding(0);
this.glControl1.Name = "glControl1";
this.glControl1.Size = new System.Drawing.Size(469, 285);
this.glControl1.TabIndex = 8;
this.glControl1.VSync = false;

 float[] vertices = {
            // Left bottom triangle
            -1f, -1f, 0f,
            1f, -1f, 0f,
            1f, 1f, 0f,
            // Right top triangle
            1f, 1f, 0f,
           -1f, 1f, 0f,
           -1f, -1f, 0f
    };
    int texSizeLoc;
    int texSize1Loc;
    int texSize2Loc;

 public PlaywithTripleCam()
    {
        InitializeComponent();
        this.SizeChanged += new EventHandler(PlaywithTripleCam_SizeChanged);
        //ScreenWidth = Screen.PrimaryScreen.Bounds.Width;
        //ScreenHeight = Screen.PrimaryScreen.Bounds.Height;
          ScreenWidth = this.Width;
          ScreenHeight = this.Height;
          screenaspectratio =(float) ScreenWidth /(float) ScreenHeight;
        //code for showing camera  device list in three combo box
    }

private void TripleCam_SizeChanged(object sender, EventArgs e)
{
   glControl1.Width = this.Width;
   glControl1.Height = this.Height / 2;
}
private void PlayButton_Click(object sender, EventArgs e)
    {      
        StartPlaying();  
        GL.ClearColor(Color.MidnightBlue);
        GL.Enable(EnableCap.DepthTest);
        TexUtil.InitTexturing();
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
        GL.DepthFunc(DepthFunction.Lequal);
        GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
        GL.Enable(EnableCap.ColorMaterial);
        GL.Enable(EnableCap.Blend);
        GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
        GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // render per default onto screen, not some FBO

        glControl1.Resize += new EventHandler(glControl1_Resize);
        glControl1.Paint += new PaintEventHandler(glControl1_Paint);
        Application.Idle += Application_Idle;
        // Ensure that the viewport and projection matrix are set correctly.
        glControl1_Resize(glControl1, EventArgs.Empty);

    }
    private void Application_Idle(object sender, EventArgs e)
    {
        while (glControl1.IsIdle)
        {
            Render();

        }
    }
    public void Render()
    {
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); // use the visible framebuffer
        if (videoFrame != null)
            lock (videoFrame)
            {
                if (videoTexture != -1)
                GL.DeleteTextures(1, ref videoTexture);
                videoTexture = LoadTexture(videoFrame);
                videoFrame.Dispose();
                videoFrame = null;
            }
        GC.Collect();
        if (videoFrame2 != null)
            lock (videoFrame2)
            {
                if (videoTexture2 != -1)
                GL.DeleteTextures(1, ref videoTexture2);
                videoTexture2 = LoadTexture(videoFrame2);
                videoFrame2.Dispose();
                videoFrame2 = null;
            }
        GC.Collect();
        if (videoFrame3!= null)
            lock (videoFrame3)
            {
                if (videoTexture3 != -1)
                GL.DeleteTextures(1, ref videoTexture3);
                videoTexture3 = LoadTexture(videoFrame3);
                videoFrame3.Dispose();
                videoFrame3 = null;
            }
        GC.Collect();
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        DrawImage(videoTexture, videoTexture2, videoTexture3);
    }
    private void CreateShaders()
    {
        /***********Vert Shader********************/
        vertShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(vertShader, @"attribute vec3 a_position;
        varying vec2 vTexCoordIn;                
     void main() {
     vTexCoordIn=( a_position.xy+1)/2;
     gl_Position = vec4(a_position,1);
      }");
     GL.CompileShader(vertShader);

        /***********Frag Shader ****************/
        fragShader = GL.CreateShader(ShaderType.FragmentShader);
        GL.ShaderSource(fragShader, @"
        uniform sampler2D sTexture;
        uniform sampler2D sTexture1;
        uniform sampler2D sTexture2;
        uniform vec2 sTexSize;
        uniform vec2 sTexSize1;
        uniform vec2 sTexSize2;

        varying vec2 vTexCoordIn;
        void main ()
        {                                               
  vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);
  if ( vTexCoord.x < 1.0/3.0 )
{
    vec2 uv = vec2(vTexCoord.x * 3.0, vTexCoord.y);
    uv.y *= sTexSize.x / sTexSize.y;
    if (uv.y > 1.0)
        discard;
    gl_FragColor = texture2D(sTexture, uv);
}
else if ( vTexCoord.x >= 1.0/3.0 && vTexCoord.x < 2.0/3.0 )
{
    vec2 uv = vec2(1.0-(vTexCoord.x * 3.0 - 1.0), vTexCoord.y);
    uv.y *= sTexSize1.x / sTexSize1.y;
    if (uv.y > 1.0)
        discard;
    gl_FragColor = texture2D(sTexture1, uv);
}
else if ( vTexCoord.x >= 2.0/3.0 )
{
    vec2 uv = vec2(vTexCoord.x * 3.0 - 2.0, vTexCoord.y);
    uv.y *= sTexSize2.x / sTexSize2.y;
    if (uv.y > 1.0)
        discard;
    gl_FragColor = texture2D(sTexture2, uv);
}}");
       GL.CompileShader(fragShader);
     }
    public void DrawImage(int image, int image1,int image2)
    {
        GL.Viewport(new Rectangle(0, 0, this.Width, this.Height / 2));
        GL.MatrixMode(MatrixMode.Projection);
        GL.PushMatrix();
        GL.LoadIdentity();
        GL.MatrixMode(MatrixMode.Modelview);
        GL.PushMatrix();
        GL.LoadIdentity();
        GL.Disable(EnableCap.Lighting);
        GL.Enable(EnableCap.Texture2D);
        GL.ActiveTexture(TextureUnit.Texture0);
        GL.BindTexture(TextureTarget.Texture2D, image);
        GL.Uniform1(positionLocation1, 0);
        GL.ActiveTexture(TextureUnit.Texture1);
        GL.BindTexture(TextureTarget.Texture2D, image1);
        GL.Uniform1(positionLocation2, 1);
        GL.ActiveTexture(TextureUnit.Texture2);
        GL.BindTexture(TextureTarget.Texture2D, image2);
        GL.Uniform1(positionLocation3, 2);

       if(videoFrame !=null )
        {
            float texW = videoFrame.Width;
            float texH = videoFrame.Height;
            GL.Uniform2(texSizeLoc, texW, texH);

        }

        if (videoFrame2 != null)
        {

            float tex1W = videoFrame2.Width;
            float tex1H = videoFrame2.Height;
            GL.Uniform2(texSize1Loc, tex1W, tex1H);
        }
        if (videoFrame3 != null)
        {
            float tex2W = videoFrame3.Width;
            float tex2H = videoFrame3.Height;
            GL.Uniform2(texSize2Loc, tex2W, tex2H);

        }

        GL.Begin(PrimitiveType.Quads);
        GL.TexCoord2(0, 1);
        GL.Vertex3(0, 0, 0);
        GL.TexCoord2(0, 0);
        GL.Vertex3(1920, 0, 0);
        GL.TexCoord2(1, 1);
        GL.Vertex3(1920, 1080, 0);
        GL.TexCoord2(1, 0);
        GL.Vertex3(0, 1080, 0);
        GL.End();
        RunShaders();
        GL.Disable(EnableCap.Texture2D);
        GL.PopMatrix();
        GL.MatrixMode(MatrixMode.Projection);
        GL.PopMatrix();
        GL.MatrixMode(MatrixMode.Modelview);
        ErrorCode ec = GL.GetError();
        if (ec != 0)
        System.Console.WriteLine(ec.ToString());
        Console.Read();
        glControl1.SwapBuffers();
    }
    private void RunShaders()
    {
        GL.UseProgram(program);
        GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
        ErrorCode ec = GL.GetError();
        if (ec != 0)
        System.Console.WriteLine(ec.ToString());
        Console.Read();
    }
    private void glControl1_Paint(object sender, PaintEventArgs e)
    {
        Render();
    }
    private void glControl1_Resize(object sender, EventArgs e)
    {
        Init();
    }
    private void Init()
    {
        CreateShaders();
        CreateProgram();
        InitBuffers();
    }
    private void CreateProgram()
    {
        program = GL.CreateProgram();
        GL.AttachShader(program, vertShader);
        GL.AttachShader(program, fragShader);
        GL.LinkProgram(program);
    }
    private void InitBuffers()
    {
        buffer = GL.GenBuffer();
        positionLocation = GL.GetAttribLocation(program, "a_position");
        positionLocation1 = GL.GetUniformLocation(program, "sTexture");
        positionLocation2 = GL.GetUniformLocation(program, "sTexture1");
        positionLocation3 = GL.GetUniformLocation(program, "sTexture2");

        texSizeLoc = GL.GetUniformLocation(program, "sTexSize");
        texSize1Loc = GL.GetUniformLocation(program, "sTexSize1");
        texSize2Loc = GL.GetUniformLocation(program, "sTexSize2");

        GL.EnableVertexAttribArray(positionLocation);
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);

    }
    public int LoadTexture(Bitmap bitmap)
    {
        int tex = -1;
        if (bitmap != null)
        {
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            GL.GenTextures(1, out tex);
            GL.BindTexture(TextureTarget.Texture2D, tex);
            bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
            BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
            OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
            bitmap.UnlockBits(data);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
        }
        return tex;
    }

enter image description here

1 Ответ

1 голос
/ 18 марта 2019

Вы должны учитывать соотношение сторон для каждой текстуры отдельно.Добавьте 3 одинаковые переменные с размерами текстур и умножьте соотношение сторон на v соответственно v компонента текстуры.
Далее вы должны отбросить фрагменты, которые находятся за пределами границ.текстуры, это можно сделать с помощью ключевого слова discard:

uniform sampler2D sTexture;
uniform sampler2D sTexture1;
uniform sampler2D sTexture2;

uniform vec2 sTexSize;
uniform vec2 sTexSize1;
uniform vec2 sTexSize2;

varying vec2 vTexCoordIn;

void main ()
{
    vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);

    if ( vTexCoord.x < 1.0/3.0 )
    {
        vec2 uv = vec2(vTexCoord.x * 3.0, vTexCoord.y);
        uv.y *= sTexSize.x / sTexSize.y;
        if (uv.y > 1.0)
            discard;
        gl_FragColor = texture2D(sTexture, uv);
    }
    else if ( vTexCoord.x >= 1.0/3.0 && vTexCoord.x < 2.0/3.0 )
    {
        vec2 uv = vec2(1.0-(vTexCoord.x * 3.0 - 1.0), vTexCoord.y);
        uv.y *= sTexSize1.x / sTexSize1.y;
        if (uv.y > 1.0)
            discard;
        gl_FragColor = texture2D(sTexture1, uv);
    }
    else if ( vTexCoord.x >= 2.0/3.0 )
    {
        vec2 uv = vec2(vTexCoord.x * 3.0 - 2.0, vTexCoord.y);
        uv.y *= sTexSize2.x / sTexSize2.y;
        if (uv.y > 1.0)
            discard;
        gl_FragColor = texture2D(sTexture2, uv);
    }
}

Sst, значения униформ: GL.Uniform2:

texSizeLoc = GL.GetUniformLocation(program, "sTexSize");
texSize1Loc = GL.GetUniformLocation(program, "sTexSize1");
texSize2Loc = GL.GetUniformLocation(program, "sTexSize2");
float texW = ...;
float texH = ...;
GL.GetUniform2(texSizeLoc, texW, texH);

float tex1W = ...;
float tex1H = ...;
GL.GetUniform2(texSize1Loc, tex1W, tex1H);

float tex2W = ...;
float tex2H = ...;
GL.GetUniform2(texSize2Loc, tex2W, tex2H);
...