vTextCoord 值不起作用 - c# OPENTK

Posted

技术标签:

【中文标题】vTextCoord 值不起作用 - c# OPENTK【英文标题】:vTextCoord value is not working - c# OPENTK 【发布时间】:2019-01-29 04:59:19 【问题描述】:

我的应用正在使用 OpenGL 着色器代码全屏显示图像,如下所示。我在这里使用的顶点着色器是从某处复制而来的。谁能解释为什么这里使用vTexCoord = (a_position.xy+1)/2;?当我尝试使用vTexCoord = a_position.xy 时,我的 OpenGL 输出被分成四个矩形,只有它的右上角部分显示图像。其他三个方面似乎也很模糊。我应该做些什么改变才能使用 vTexCoord = a_position.xy

项目中用到的一些重要功能如下所示。请检查并帮助更正。

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
    ;
    private void CreateShaders()
    
        /***********Vert Shader********************/
        vertShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(vertShader, @"attribute vec3 a_position;
                                    varying vec2 vTexCoord;
                                    void main() 
                                    vTexCoord = (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 vTexCoord;                      
          void main ()
         
        vec4 color= texture2D (sTexture, vTexCoord);                           
        gl_FragColor =color;
                             ");
        GL.CompileShader(fragShader);
    
    private void InitBuffers()
    
        buffer = GL.GenBuffer();
        positionLocation = GL.GetAttribLocation(program, "a_position");
        positionLocation1 = GL.GetUniformLocation(program, "sTexture");
        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 void DrawImage(int image)
    
        GL.Viewport(new Rectangle(0, 0, ScreenWidth, ScreenHeight));

        GL.MatrixMode(MatrixMode.Projection);
        GL.PushMatrix();
        GL.LoadIdentity();

        //GL.Ortho(0, 1920, 0, 1080, 0, 1);

        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.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);
        glControl1.SwapBuffers();
    
    private void RunShaders()
    
        GL.UseProgram(program);
        GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
    

【问题讨论】:

【参考方案1】:

谁能解释这里为什么使用vTexCoord = (a_position.xy+1)/2;

您示例中的顶点坐标在范围 [-1, 1] 中,用于 x 和组件。这与标准化设备空间相匹配。标准化的设备空间是从左下前(-1、-1、-1)到右上后(1、1、1)的立方体,这是“可见”的区域。此区域已映射到视口。 在您的示例中,这会导致顶点坐标形成一个覆盖整个视口的矩形。

如果纹理坐标应该将整个纹理包裹到四边形,那么纹理坐标 (u, v) 必须在 [0, 1] 范围内。 (0, 0) 是纹理的左下角, (1, 1) 是右上角。 另见How do OpenGL texture coordinates work?

所以a_position 的 x 和 y 分量必须从 [-1, 1] 范围映射到 [0, 1] 范围,用作纹理查找的 uv 坐标:

u = (a_position.x + 1) / 2
v = (a_position.y + 1) / 2

我应该做些什么改变来使用vTexCoord = a_position.xy

这是不可能的,但是可以生成单独的纹理坐标属性,这很常见:

attribute vec3 a_position;
attribute vec2 a_texture;

varying vec2 vTexCoord;

void main() 
    vTexCoord   = a_texture;
    gl_Position = vec4(a_position, 1);

float[] vertices = 
  // x    y   z      u   v
    // Left bottom triangle
    -1f, -1f, 0f,    0f, 0f
     1f, -1f, 0f,    1f, 0f
     1f,  1f, 0f,    1f, 1f
    // Right top triangle
     1f,  1f, 0f,    1f, 1f
    -1f,  1f, 0f,    0f, 1f
    -1f, -1f, 0f     0f, 0f
;
buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

positionLocation = GL.GetAttribLocation(program, "a_position");
tetureLocation   = GL.GetAttribLocation(program, "a_texture");

GL.EnableVertexAttribArray(positionLocation);
GL.EnableVertexAttribArray(tetureLocation);

int stride   = sizeof(float) * 5; // 5 because of (x, y, z, u, v)
int offsetUV = sizeof(float) * 3; // 3 because the u and v coordinates are the 4th and 5th coordinate

GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.VertexAttribPointer(tetureLocation,   2, VertexAttribPointerType.Float, false, stride, (IntPtr)(offsetUV));

【讨论】:

以上是关于vTextCoord 值不起作用 - c# OPENTK的主要内容,如果未能解决你的问题,请参考以下文章

为啥恐慌恢复以局部变量返回值不起作用?

最小值不起作用

当指针指向数组时,为啥 operator(*) 的值不起作用?

为啥链接元素中的媒体属性对打印值不起作用? [复制]

在角度 FormGroup 上设置值不起作用

Vue Array prop 默认值不起作用