繁体   English   中英

C#/ OpenTK-将着色器应用于加载的纹理时出现问题。 缩小和翻转纹理

[英]C#/OpenTK - Problems applying shaders to loaded texture. Texture is scaled down and flipped

我一直在尝试找出如何使它工作。 我正在使用OpenTK for C#修改图像。 现在,我能够成功加载图像,但是当我尝试使用着色器修改图像时,我开始遇到问题。 我有3种基本方法:

  • 1)LoadTexture(将纹理设置为GL)
  • 2)DrawImage(实际绘制纹理)
  • 3)AddShaders(此方法在DrawImage内部调用,将应用着色器)

所以这是我遇到的两个问题:

  • 1)我正在尝试创建2个三角形,它们覆盖整个纹理。 这是因为我想让片段着色器在整个纹理上工作。 我实际上得到的是覆盖屏幕左侧的大三角形,以及屏幕右侧的矩形。 编辑:取得了一些进展! 但仍然看起来很奇怪...着色器脚本已更新。.EDIT2:较新的进度图片已上传

  • 2)当我希望它们使用纹理中的颜色但修改了红色通道时,这些形状显示为绿色。 重要的是要知道我需要能够分析每个像素。 更改每个像素的红色通道仅是我要实际完成的概念证明(使用颜色距离公式,色相平移等,但我需要首先更简单地开始)

这是我已成功加载为纹理的图像: Loaded Texture

这是LoadTexture的代码:

      public int LoadTexture(string file)
    {
        Bitmap bitmap = new Bitmap(file);

        int tex;
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

        GL.GenTextures(1, out tex);
        GL.BindTexture(TextureTarget.Texture2D, tex);

        BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
       ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
        bitmap.UnlockBits(data);


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

        return tex;
    }

这是DrawImage的代码:

        public static void DrawImage(int image)
    {


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

        GL.Ortho(0, 1920, 0, 1080, -1, 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.Begin(PrimitiveType.Quads);

        GL.TexCoord2(0,1);
        GL.Vertex3(0, 0, 0);

        GL.TexCoord2(1, 1);
        GL.Vertex3(1920, 0, 0);

        GL.TexCoord2(1, 0);
        GL.Vertex3(1920, 1080, 0);

        GL.TexCoord2(0, 0);
        GL.Vertex3(0, 1080, 0);


        GL.End();

        AddShaders();

        GL.Disable(EnableCap.Texture2D);
        GL.PopMatrix();

        GL.MatrixMode(MatrixMode.Projection);
        GL.PopMatrix();

        GL.MatrixMode(MatrixMode.Modelview);

        ErrorCode ec = GL.GetError();
        if (ec != 0)
            System.Console.WriteLine(ec.ToString());
        Console.Read();

    }

这是AddShaders的代码:

      private static void AddShaders()
    {

        /***********Vert Shader********************/
        var vertShader = GL.CreateShader(ShaderType.VertexShader);
        GL.ShaderSource(vertShader, @"attribute vec3 a_position;
                                        varying vec2 vTexCoord;
                                        void main() {
                                        vTexCoord = a_position.xy;
                                        gl_Position = vec4(a_position, 1);
                                        }");
        GL.CompileShader(vertShader);


        /***********Frag Shader ****************/
        var fragShader = GL.CreateShader(ShaderType.FragmentShader);
        GL.ShaderSource(fragShader, @"uniform sampler2D sTexture;
                                      varying vec2 vTexCoord;
                                void main ()
                                {
                                    vec4    color   = texture2D (sTexture, vTexCoord);
                                    color.r = 0.5;
                                    // Save the result
                                    gl_FragColor    = color;
                                }");
        GL.CompileShader(fragShader);

        var program = GL.CreateProgram();
        GL.AttachShader(program, vertShader);
        GL.AttachShader(program, fragShader);
        GL.LinkProgram(program);
        GL.ClearColor(Color.AliceBlue);

        // OpenGL expects vertices to be defined counter clockwise by default
        float[] vertices = {
                // Left bottom triangle
                -1f, 1f, 0f,
                -1f, -1f, 0f,
                1f, -1, 0f,
                // Right top triangle
                1f, -1f, 0f,
                1f, 1f, 0f,
                -1f, 1f, 0f
        };

        var buffer = GL.GenBuffer();
        var positionLocation = GL.GetAttribLocation(program, "a_position");
        GL.EnableVertexAttribArray(positionLocation);
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
        GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float,false,0,0);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);

        GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length);
        GL.UseProgram(program);

    }  

我已经研究了几天,但我完全被卡住了。 感谢任何能够看到我在做什么的人。 对我而言,这一定是小巧而笨拙的!

编辑:当我在AddShaders中删除所有与顶点相关的代码时,我得到了所需的输出,除了它的1/4大小,并在屏幕的右上角翻转了。 因此,以某种方式,我的着色器甚至不关心顶点。 为什么将其缩小为1/4大小并翻转?

EDIT2:好的,感谢罗伯特·鲁哈尼(Robert Rouhani),我已经完成了这项工作! 进度看来三角形顶点可能被弄乱了??

这是我的新代码。 我将功能重构为方法,停止在每一帧中创建程序/缓冲区等。现在,我具有用于保存GL特定数据的类级变量,用于为应用程序创建GL程序,创建着色器,创建缓冲区等的方法。我知道1920x1080硬编码是硬编码的。 那是我的动力所在。

    string file = "lambo2.png";
    int program;
    int vertShader;
    int fragShader;
    int buffer;
    int positionLocation;
    int texture;
    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 CreateProgram()
    {
        program = GL.CreateProgram();
        GL.AttachShader(program, vertShader);
        GL.AttachShader(program, fragShader);
        GL.LinkProgram(program);
    }
    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);
                                     if(color.r < 0.3){color.r = 1.0;}
                                     // Save the result
                                     gl_FragColor    = color;
                                 }");
        //   GL.ShaderSource(fragShader, System.IO.File.ReadAllText(@"C:\Users\Matt\Desktop\hue-shader-backup.ps"));
        GL.CompileShader(fragShader);
    }
    private void InitBuffers()
    {
        buffer = GL.GenBuffer();
        positionLocation = GL.GetAttribLocation(program, "a_position");
        GL.EnableVertexAttribArray(positionLocation);
        GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);
        GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
    }
    private void Init()
    {
        texture = LoadTexture(file);
        CreateShaders();
        CreateProgram();
        InitBuffers();
    }
    public int LoadTexture(string file)
    {
        Bitmap bitmap = new Bitmap(file);

        int tex;
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

        GL.GenTextures(1, out tex);
        GL.BindTexture(TextureTarget.Texture2D, tex);
        bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
        BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
       ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
        bitmap.UnlockBits(data);


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

        return tex;
    }

    public void DrawImage(int image)
    {

        GL.Viewport(new Rectangle(0, 0, 1920, 1080));
        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.Begin(PrimitiveType.Quads);

        GL.TexCoord2(0, 1);
        GL.Vertex3(0, 0, 0);

        GL.TexCoord2(1, 1);
        GL.Vertex3(1920, 0, 0);

        GL.TexCoord2(1, 0);
        GL.Vertex3(1920, 1080, 0);

        GL.TexCoord2(0, 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);


        ErrorCode ec = GL.GetError();
        if (ec != 0)
            System.Console.WriteLine(ec.ToString());
        Console.Read();
    }
    private void RunShaders()
    {

        GL.ClearColor(Color.AliceBlue);
        GL.UseProgram(program);
        GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);

        ErrorCode ec = GL.GetError();
        if (ec != 0)
            System.Console.WriteLine(ec.ToString());
        Console.Read();

    }

要开始回答而不是继续评论。 您仍然有一些小问题正在加重。 您应该注释掉GL.BeginGL.End之间的所有内容,因为RunShaders函数应该确实在屏幕上绘制了您需要的所有内容。 还要注释掉GL.Ortho线,如果使用[-1,1]范围内的顶点,则不需要它。

其次,问题是您只将一半的顶点缓冲区上传到GPU。 InitBuffers行的GL.BufferData ,将sizeof(ushort)更改为sizeof(float) ,因为您的顶点是浮点数(4个字节长)而不是ushorts(2个字节长)。

GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

一起可以使您的程序正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM