Удалить область, отличную от текстур, из элемента управления OpenGL - c # opentk - PullRequest
1 голос
/ 21 мая 2019

Используя приведенный ниже код шейдера, я могу отображать кадры с трех камер на один элемент управления openGL.Начальное местоположение этого элемента управления opengl должно быть от центра экрана и должно начинаться с левого края до полной ширины экрана.То есть ширина элемента управления равна ширине экрана, а высота равна половине высоты экрана.Но проблема в том, что есть область, отличная от текстур, и она выглядит как ClearColor (которая установлена ​​как синий цвет).

enter image description here

if (ув. y> 1.0) сбросить;

Можно ли удалить / удалить эту дополнительную область из GLControl?

   int y = Screen.PrimaryScreen.Bounds.Height - this.PreferredSize.Height;
        glControl1.Location = new Point(0, y/2);
    private void OpenGL_SizeChanged(object sender, EventArgs e)
    {
        glControl1.Width = this.Width;
        glControl1.Height = this.Height/2;
    }

 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);

  private void CreateShaders()
    {
        /***********Vert Shader********************/
        vertShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(vertShader, @"attribute vec3 a_position;
                                varying vec2 vTexCoordIn; 
                         //uniform float aspect;   
     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;  
    else
    gl_FragColor = texture2D(sTexture, uv);
}
else if ( vTexCoord.x >= 1.0/3.0 && vTexCoord.x < 2.0/3.0 )
{  
 vec2 uv = vec2(vTexCoord.x * 3.0 - 1.0, vTexCoord.y);
 uv.y *= sTexSize1.x / sTexSize1.y;
 if (uv.y > 1.0)
 discard;  
 else
 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;
  else
  gl_FragColor = texture2D(sTexture2, uv);
 }
   }");
  GL.CompileShader(fragShader);
    }

1 Ответ

1 голос
/ 21 мая 2019

Я думаю, что вы должны сделать изменение размера на стороне процессора вместо шейдеров ...

  1. изменить размер всех кадров до общей высоты
  2. Суммируйте ширину кадров с измененными размерами
  3. измените масштаб всех кадров так, чтобы суммарная ширина была равна ширине вашего окна / рабочего стола
  4. измените высоту окна, чтобы соответствовать новомуобщая высота после # 3

Похоже, вы делаете # 1, # 2, # 3 внутри вашего бутона шейдеров, игнорируя # 4 в результатев этой пустой области.Вы не можете совпасть с размером окна по x и y без нарушения соотношения сторон изображения камеры.Поэтому оставьте размер x и измените размер окна y, чтобы решить вашу проблему.

Здесь небольшой пример VCL / C ++ / legacy GL (извините, я не кодирую в C # и слишком ленив, чтобы кодировать новые вещи для этого):

//---------------------------------------------------------------------------
#include <vcl.h>
#include <gl\gl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1  *Form1;                 // VCL Application window object
int     xs,ys;                  // window resolution
HDC     hdc=NULL;               // device context for GL
HGLRC   hrc=NULL;               // rendering context for GL
//---------------------------------------------------------------------------
const int camera_res[]= // (x,y) resolutions of each camera
    {
    320,200,
    640,480,
    352,288,
    0,0
    };
float frame_pos[128];   // (x0,x1) position of each frame
void frame_resize(int xs,int &ys)   // position/resize frames and change ys to common height so xs fit without breaking aspect ratio
    {
    int i,j;
    float dx,dy,x,y;
    // comon height placemet
    for (x=0.0,i=0,j=0;camera_res[i];)
        {
        dx=camera_res[i]; i++;
        dy=camera_res[i]; i++;
        dx*=1000.0/dy;          // any non zero common height for example 1000
        frame_pos[j]=x; x+=dx; j++;
        frame_pos[j]=x-1.0;    j++;
        }
    frame_pos[j]=-1.0; j++;
    frame_pos[j]=-1.0; j++;
    // rescale summed width x to match xs
    x=float(xs)/x;              // scale
    ys=float(1000.0*x);         // common height
    for (j=0;frame_pos[j]>-0.1;)
        {
        frame_pos[j]*=x; j++;
        frame_pos[j]*=x; j++;
        }
    }
//---------------------------------------------------------------------------
void gl_draw()
    {
    if (hrc==NULL) return;

    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    // view in pixel units
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glTranslatef(-1.0,+1.0,0.0);
    glScalef(2.0/float(xs),-2.0/float(ys),1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // render rectangle
    int i; float x0,y0,x1,y1;
    y0=0.0; y1=ys-1;
    glColor3f(1.0,1.0,1.0);
    for (i=0;frame_pos[i]>-0.1;)
        {
        x0=frame_pos[i]; i++;
        x1=frame_pos[i]; i++;
        // here bind (i/2) camera frame as texture (only one texture at a time)
        glBegin(GL_LINE_LOOP);
        glTexCoord2f(0.0,0.0); glVertex2f(x0,y0);
        glTexCoord2f(0.0,1.0); glVertex2f(x0,y1);
        glTexCoord2f(1.0,1.0); glVertex2f(x1,y1);
        glTexCoord2f(1.0,0.0); glVertex2f(x1,y0);
        glEnd();
        }

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    // desktop      You can hardcode xs,ys instead
    TCanvas *scr=new TCanvas();
    scr->Handle=GetDC(NULL);
    xs=scr->ClipRect.Width();               // desktop width
    ys=scr->ClipRect.Height();              // desktop height
    delete scr;
    // window       This is important
    int ys0=ys;                             // remember original height
    frame_resize(xs,ys);                    // compute sizes and placements
    SetBounds(0,(ys0-ys)>>1,xs,ys);         // resize window and place in the center of screen

    // GL init      most likely you can ignore this you already got GL
    hdc = GetDC(Handle);                    // get device context for this App window
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory( &pfd, sizeof( pfd ) );      // set the pixel format for the DC
    pfd.nSize = sizeof( pfd );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
    hrc = wglCreateContext(hdc);            // create current rendering context
    if(hrc == NULL)
        {
        ShowMessage("Could not initialize OpenGL Rendering context !!!");
        Application->Terminate();
        }
    if(wglMakeCurrent(hdc, hrc) == false)
        {
        ShowMessage("Could not make current OpenGL Rendering context !!!");
        wglDeleteContext(hrc);          // destroy rendering context
        Application->Terminate();
        }
    // resize GL framebufers            this is important
    glViewport(0,0,xs,ys);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    // GL exit          most likely you can ignore this
    wglMakeCurrent(NULL, NULL);     // release current rendering context
    wglDeleteContext(hrc);          // destroy rendering context
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,TShiftState Shift)
    {
    if (Key==27) Close();   // Escape exits app
    }
//---------------------------------------------------------------------------

Игнорировать материал VCL , единственная важная вещь здесь - это функция frame_resize и ее использование.gl_draw просто визуализирует прямоугольники вместо ваших кадров, поэтому для исправления просто свяжите текстуру и используйте GL_QUAD вместо GL_LINE_LOOP.Или перенесите его на новый GL, чтобы VBO / VAO ...

Я кодировал его, чтобы он поддерживал любое количество камер выше 0 ... просто убедитесь, что массив frame_pos достаточно большой (2 записина камеру).

Как видите, шейдеры не нужны.Конечно, в новом стиле GL вам нужны шейдеры, поэтому в них просто копируйте тексель из текстуры в фрагмент ...

...