Код шейдера для отображения выбранной части изображения - OpenTk - PullRequest
1 голос
/ 26 июня 2019

Я хочу показать выбранную область из второй половины изображения (это диапазон от 0,5 до 1,0) в моем glcontrol. Для этого я использовал две переменные RightsliderStartval (любое значение от 0,5 до 1,0) и rightsliderEndval (любое значение от 1,0 до 0,5). Я хочу точно выбранную область между этим rightsliderStartval и rightsliderEndval. При попытке, как показано ниже, выделенная область становится, но растягивается.

  decimal RateOfResolution = (decimal)videoSource.VideoResolution.FrameSize.Width / (decimal)videoSource.VideoResolution.FrameSize.Height;          
  int openGLwidth = (this._Screenwidth / 3) - 40;  
  int openGLheight = Convert.ToInt32(screenWidthbyThree / RateOfResolution); 
  glControl.Width = openGLwidth;
  glControl.Height = openGLheight;
  GL.Viewport(new Rectangle(0, 0, glControl.Width, glControl.Height));


 public 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, @"precision highp float;

    uniform sampler2D sTexture;
    varying vec2 vTexCoordIn;
    void main ()
    {
        vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);
        float rightsliderStartval=0.6;//0.5 to 1.0
        float rightsliderEndval=0.8;//1.0 to 0.5
        float rightsliderDelta=rightsliderEndval-rightsliderStartval;

     if (vTexCoordIn.x < 0.5)
     discard;
    float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);

   vec4 color = texture2D(sTexture, vec2(u, vTexCoordIn.y));
   gl_FragColor = color;


    }");
GL.CompileShader(fragShader);
   }

В скриншоте белая линия представляет центр изображения. Хочу показать область между желтой и оранжевой линией. White line represent center of image. Want to show area between yellow and orange line

Output

1 Ответ

1 голос
/ 28 июня 2019

Если вы хотите пропустить некоторые части текстуры, вы можете использовать ключевое слово discard. Эта команда приводит к тому, что выходные значения фрагмента отбрасываются, а фрагменты не отображаются вообще.

Если у вас прямоугольная область и вы хотите рисовать только во 2-й половине прямоугольной области, то вы должны отбросить фрагменты в 1-й половине:

if (vTexCoordIn.x < 0.5)
    discard;

Если вы хотите нарисовать диапазон от rightsliderStartval до rightsliderEndval во 2-й половине прямоугольной области, то вам необходимо отобразить координату входящей текстуры ранга [0.5, 1.0] vTexCoordIn.x на [rightsliderStartval, rightsliderEndval] ]:

float w = (vTexCoordIn.x-0.5) * 2.0;                      // [0.5, 1.0] -> [0.0, 1.0]
float u = mix(rightsliderStartval, rightsliderEndval, w); // [0.0, 1.0] -> [0.7, 0.9]

Это приводит к фрагменту шейдера:

precision highp float;

uniform sampler2D sTexture;
varying vec2 vTexCoordIn;

void main ()
{
    float rightsliderStartval = 0.7;
    float rightsliderEndval   = 0.9;

    if (vTexCoordIn.x < 0.5)
        discard;

    float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);

    vec4 color = texture2D(sTexture, vec2(u, vTexCoordIn.y));
    gl_FragColor = color;
}

Если вы не хотите, чтобы изображение растягивалось, у вас есть 2 варианта.

Либо откажитесь от региона от 0,0 до 0,7 и от 0,9 до 1,0:

precision highp float;

uniform sampler2D sTexture;
varying vec2 vTexCoordIn;

void main ()
{
    float rightsliderStartval = 0.7;
    float rightsliderEndval   = 0.9;

    if (vTexCoordIn.x < 0.7 || vTexCoordIn.x > 0.9)
        discard;

    vec4 color = texture2D(sTexture, vTexCoordIn.xy));
    gl_FragColor = color;
}

Или масштабируйте изображение в направлении y:

precision highp float;

uniform sampler2D sTexture;
varying vec2 vTexCoordIn;

void main ()
{
    float rightsliderStartval = 0.7;
    float rightsliderEndval   = 0.9;

    if (vTexCoordIn.x < 0.5)
        discard;

    float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);

    float v_scale = (rightsliderEndval - rightsliderStartval) / 0.5;
    float v = vTexCoordIn.y * v_scale + (1.0 - v_scale) / 2.0;;

    vec4 color = texture2D(sTexture, vec2(u, v));
    gl_FragColor = color;
}
...