Я думаю, что вы должны сделать изменение размера на стороне процессора вместо шейдеров ...
- изменить размер всех кадров до общей высоты
- Суммируйте ширину кадров с измененными размерами
- измените масштаб всех кадров так, чтобы суммарная ширина была равна ширине вашего окна / рабочего стола
- измените высоту окна, чтобы соответствовать новомуобщая высота после # 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 вам нужны шейдеры, поэтому в них просто копируйте тексель из текстуры в фрагмент ...