-1

I have working fragment shader for resolution 1920x1080. However, I want to change to a dynamic resolution whatever user select.

I have referred < http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c > this link and modified the line ny=576.0-gl_TexCoord[0].y;\n to ny=1080.0-gl_TexCoord[0].y;\n for 1920 x 1080.

The full source of my program is

#include <cplaywidget.h>
#include <mainwindow.h>


#define ATTRIB_VERTEX 3
#define ATTRIB_TEXTURE 4
#define BHANU
#define WORKING_420P
#define YUY2_test

extern int g_cs_Index;
#ifdef BHANU
QOpenGLTexture* texName;
GLuint texture;
#endif

#ifdef YUY2_test
GLubyte *Ytex,*UVtex;
GLhandleARB FSHandle,PHandle;
QOpenGLExtension_ARB_shader_objects* myShader = new QOpenGLExtension_ARB_shader_objects();

// fy   = /*1080.0-*/gl_TexCoord[0].y;
const char *FProgram=
      "uniform sampler2DRect Ytex;\n"
      "uniform sampler2DRect UVtex;\n"
      "void main(void) {\n"
      "  float fx, fy, y, u, v, r, g, b;\n"

      "  fx   = gl_TexCoord[0].x;\n"
      "  fy   = 1080.0-gl_TexCoord[0].y;\n"

      "  y = texture2DRect(Ytex,vec2(fx,fy)).a;\n"
      "  u = texture2DRect(UVtex,vec2(fx/2.0,fy)).b;\n"
      "  v = texture2DRect(UVtex,vec2(fx/2.0,fy)).r;\n"

      "  y=1.164*(y-0.0627);\n"
      "  u=u-0.5;\n"
      "  v=v-0.5;\n"
      "  r = y+1.5958*v;\n"
      "  g = y-0.39173*u-0.81290*v;\n"
      "  b = y+2.017*u;\n"
      "  gl_FragColor=vec4(r, g, b, 1.0);\n"

      "}\n";
#endif
extern camera_t* camera;


CPlayWidget::CPlayWidget(QWidget *parent):QOpenGLWidget(parent)
{
    textureUniformY = 0;
    textureUniformU = 0;
    textureUniformV = 0;

    id_y = 0;
    id_u = 0;
    id_v = 0;

    m_pBufYuv420p = NULL;
    m_pVSHader = NULL;
    m_pFSHader = NULL;
    m_pShaderProgram = NULL;
    m_pTextureY = NULL;
    m_pTextureU = NULL;
    m_pTextureV = NULL;
    m_pYuvFile = NULL;
    m_nVideoH = 0;
    m_nVideoW = 0;
}

CPlayWidget::~CPlayWidget()
{

}

void CPlayWidget::initializeGL()
{

    initializeOpenGLFunctions();

#ifdef YUY2_test
    int i;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,1920,0,1080,-1,1);
    glViewport(0,0,1920,1080);
    glClearColor(0,0,0,0);
    glColor3f(1.0,0.84,0.0);
    glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);

     myShader->initializeOpenGLFunctions();

    PHandle = myShader->glCreateProgramObjectARB();
    FSHandle= myShader->glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

    myShader->glShaderSourceARB(FSHandle,1,&FProgram,NULL);
    myShader->glCompileShaderARB(FSHandle);

    myShader->glGetObjectParameterivARB(FSHandle,GL_OBJECT_COMPILE_STATUS_ARB,&i);

    myShader->glAttachObjectARB(PHandle,FSHandle);
    myShader->glLinkProgramARB(PHandle);

    myShader->glUseProgramObjectARB(PHandle);

#endif
}

void CPlayWidget::resizeGL(int w, int h)
{
    if(h == 0)
    {
    h = 1;
    }
    glViewport(0,0, w,h);
}

 void CPlayWidget::paintGL()
 {
 #ifdef YUY2_test
     int i;
     glClear(0);

     glActiveTexture(GL_TEXTURE1);
     i=myShader->glGetUniformLocationARB(PHandle,"UVtex");
     myShader->glUniform1iARB(i,1);  /* Bind Utex to texture unit 1 -YUY2 working*/
     glBindTexture(GL_TEXTURE_RECTANGLE_NV, 1);
     glEnable(GL_TEXTURE_RECTANGLE_NV);

     glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
     glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
     glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA8, 1920/2/*(camera->width/2)*/, 1080/*(camera->height)*/,0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, UVtex); //UV

     glActiveTexture(GL_TEXTURE0);
     i=myShader->glGetUniformLocationARB(PHandle,"Ytex");
     myShader->glUniform1iARB(i,0);  /* Bind Ytex to texture unit 0 -YUY2 Working*/
     glBindTexture(GL_TEXTURE_RECTANGLE_NV, 2);//id_y);
     glEnable(GL_TEXTURE_RECTANGLE_NV);

     glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
     glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
     glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_LUMINANCE_ALPHA, 1920, 1080, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,Ytex); //Y


     glBegin(GL_QUADS);
     glTexCoord2i(0,0);
     glVertex2i(0,0);
     glTexCoord2i(1920,0);
     glVertex2i(1920,0);
     glTexCoord2i(1920,1080);
     glVertex2i(1920,1080);
     glTexCoord2i(0,1080);
     glVertex2i(0,1080);
     glEnd();

     glDrawArrays(GL_QUADS, 0, 4);

#endif
    return;
 }

void CPlayWidget::PlayOneFrame(unsigned char *l_ui_arr)

{

    m_nVideoW = camera->width;
    m_nVideoH = camera->height;
    int nLen;

    switch (g_cs_Index)
    {
    case I420:
    case I422:
    case YV12:
     nLen = m_nVideoW*m_nVideoH*3/2;
    break;
    case RGB24:
     nLen = m_nVideoW*m_nVideoH*3;
    break;
    case YUY2:
    case UYVY:
    nLen = m_nVideoW*m_nVideoH*2;
       break;
    case RGB32:
     nLen = m_nVideoW*m_nVideoH*4;
    break;
    default:
     qDebug() << "Unsupported format\n";
    }

    if(NULL == m_pBufYuv420p)
    {
    m_pBufYuv420p = new unsigned char[nLen];
    Ytex=(GLubyte *)malloc(nLen);
    UVtex = (GLubyte *)malloc(nLen);
    qDebug("CPlayWidget::PlayOneFrame new data memory. Len=%d width=%d height=%d\n",
           nLen, m_nVideoW, m_nVideoH);
    }
    m_pBufYuv420p = l_ui_arr;

    Ytex =UVtex = (GLubyte *)m_pBufYuv420p;
    update();
    return;
}

How to change the resolution from static to dynamic in the fragment shader (dynamic means the user will select the resolution it can be 640x480, 800x600, 1920x1200 and so on)?

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Update: If I change from " ny=1080.0-gl_TexCoord[0].y;\n" to " ny=Image_Width-gl_TexCoord[0].y;\n", then I'm getting black screen. Where Image_Width is parameter which contains dynamic resolution. – Chakravarthi Pradeep Dec 22 '18 at 09:39

1 Answers1

2

Don't hardcode your constants. Instead calculate them at runtime in the hostcode and pass them to the shader via uniforms.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • If I change from " ny=1080.0-gl_TexCoord[0].y;\n" to " ny=Image_Width-gl_TexCoord[0].y;\n", then I'm getting black screen. Where Image_Width is parameter which contains dynamic resolution. – Chakravarthi Pradeep Dec 22 '18 at 09:40
  • 3
    @ChakravarthiPradeep: Where in your code is `Image_Width` defined? There's no uniform with that name there. Also why are you using pixel based texture coordinates in the first place? Just use normalized texture coordinates (i.e. numbers in the range 0 to 1) and fetch the texture with the `texture` function instead of `texture2DRect`. – datenwolf Dec 22 '18 at 09:53
  • Image_Width is a parameter which will contains value from application. For instance, If user select 1920x1080 then Image_Width will have 1920 and Image_Height will have 1080. Sorry, In my previous comment instead of Image_Width it should be Image_Height. Also why are you using pixel based texture coordinates in the first place? I will try, but I'm not sure about this. – Chakravarthi Pradeep Dec 22 '18 at 13:08
  • 2
    @ChakravarthiPradeep: You still didn't answer my question: Where and how are you passing the `Image_Width` and `Image_Height` parameters to the shader? You didn't show us the code which does that so far. You do realize, that you must use a uniform for that, do you? – datenwolf Dec 22 '18 at 14:12
  • Where and how are you passing the Image_Width and Image_Height parameters to the shader ? I had modified the shader from " ny=1080.0-gl_TexCoord[0].y;\n" to " ny=Image_Height-gl_TexCoord[0].y;\n". If I do, then I will be black screen. – Chakravarthi Pradeep Dec 23 '18 at 17:42
  • @ChakravarthiPradeep: Still not answering my question: *Where and how do you pass `Image_Height` to the shader?* You still didn't show us the full source code. I have this suspicion, that you have a symbol `Image_Height` somewhere in your main program and are somehow expecting that this symbol "magically" were accessible to the shader shomehow. That's not how it works. The shader source code you posted in your original question does not define `Image_Height` (nor `Ìmage_Width`) and I'm pretty sure that when you get just "black" it's simply due to compiling the shader failing. – datenwolf Dec 23 '18 at 19:29
  • @datewolf, You can get the source code from https://github.com/chakripradeep/uyvy-opengl/tree/master this link. This is just a experimental code which is only working for 1920x1080. This is static resolution, I want to change this to dynamic resolution. – Chakravarthi Pradeep Dec 26 '18 at 02:47
  • @ChakravarthiPradeep: Okay, now where's the source code for the variant in which you tried dynamic resolution. StackOverflow is not a code writing service, but a question&answer site, where people go, to learn. So I'm not trying to be a dick here, but make this an actual learning experience… not just for you, but also for people to come seeking for knowledge in the future. – datenwolf Dec 26 '18 at 10:20
  • I modified the code using uniform, only few lines are added "uniform float Res;\n" "Res = camera->height;\n" inside main " fy = Res -gl_TexCoord[0].y;\n". with aforesaid change it shows yellow screen – Chakravarthi Pradeep Dec 26 '18 at 18:26
  • @ChakravarthiPradeep: `Res = camera->height` is not going to work. For the same reason, as with `Image_Height` previously: *OpenGL shaders do now see or have access to symbols or variables in your main program!* You can't write `uniform float foo = ;` You have to pass the value by calling `glUniform(location_of_uniform, value_to_set_uniform_to )` in the OpenGL host programs. – datenwolf Dec 26 '18 at 23:09
  • @ChakravarthiPradeep: You really have to understand that, as far as your host program compiler is concerned, the shader code is just some string. And as far as the shader is concerned, it has zero knowledge about anything outside the shader. – datenwolf Dec 26 '18 at 23:10
  • I understand that shader code is just a string. Could you please tell me how to make above code works for dynamic resolution? – Chakravarthi Pradeep Dec 27 '18 at 02:02
  • @ChakravarthiPradeep: I already did tell you what to change. SO is not a code writing service. And even if it were, the little bit of code you pushed on GitHub is not the complete program. So even if I would add some changes, without the complete program I could not test them. – datenwolf Dec 27 '18 at 09:45