OpenGL4 не может загрузить текстуру в Sampler2D

Я не могу связать свою текстуру с sampler2D во фрагментном шейдере. Теоретически моя программа должна рисовать всю сцену одним цветом (мое изображение - красный, большой квадрат размером 64x64). При использовании textureSize для получения размеров sampler2D возвращается 1x1.

Ни TextureID, ни SamplerLocation не возвращают -1

Что я делаю в данный момент:

  1. Загрузите изображение в память графического процессора и получите Location (int TextureID) с помощью loadImage().
  2. Получить UniformLocation моего sampler2D (int SamplerLocation)
  3. В методе рендеринга: свяжите текстуру и соответственно установите равномерное расположение

Исходный код:

Метод loadImage, скопированный с http://neokabuto.blogspot.de/

    int loadImage(Bitmap image)
    {
        int texID = GL.GenTexture();

        GL.BindTexture(TextureTarget.Texture2D, texID);
        BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

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

        image.UnlockBits(data);

        GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

        return texID;
    }

Метод OnLoad вызывается один раз при запуске

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        int status_code;
        string info;

        Console.Out.WriteLine(GL.GetString(StringName.Version));

        m.loadFromOBJ("C:/Users/Anwender/Downloads/lpm_yard.obj");
        m.init();

        TextureID = loadImage("C:/Users/Anwender/Desktop/test.png");

        // Setup openGL
        GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        GL.Enable(EnableCap.DepthTest);
        GL.DepthFunc(DepthFunction.Lequal);

        // Create MVP-Matrices and Camera Data
        ProjectionMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.5f, 10000.0f);
        WorldMatrix = new Matrix4();
        ModelviewMatrix = new Matrix4();
        CameraPosition = new Vector3(0.5f, 0.5f, 0);

        defaultPickSSB = new PickSSB();
        defaultPickSSB.DepthValue = float.MaxValue;
        defaultPickSSB.PickIndex = -1;

        string VertexSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/vs.glsl");
        string FragmentSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/fr.glsl");

        // Create Shaders
        int VertexID = GL.CreateShader(ShaderType.VertexShader);
        int FragmentID = GL.CreateShader(ShaderType.FragmentShader);

        // Compile vertex shader
        GL.ShaderSource(VertexID, VertexSource);
        GL.CompileShader(VertexID);
        GL.GetShaderInfoLog(VertexID, out info);
        GL.GetShader(VertexID, ShaderParameter.CompileStatus, out status_code);

        if (status_code != 1)
            throw new ApplicationException(info);

        // Compile fragment shader
        GL.ShaderSource(FragmentID, FragmentSource);
        GL.CompileShader(FragmentID);
        GL.GetShaderInfoLog(FragmentID, out info);
        GL.GetShader(FragmentID, ShaderParameter.CompileStatus, out status_code);

        if (status_code != 1)
            throw new ApplicationException(info);

        // Create and Link Program
        Program = GL.CreateProgram();
        GL.AttachShader(Program, FragmentID);
        GL.AttachShader(Program, VertexID);

        GL.BindFragDataLocation(Program, 0, "color");

        GL.LinkProgram(Program);

        GL.UseProgram(Program);

        // Get Buffer Locations
        PickColorLocation = GL.GetAttribLocation(Program, "vertex_pick_index");
        PositionLocation = GL.GetAttribLocation(Program, "vertex_position");
        NormalLocation = GL.GetAttribLocation(Program, "vertex_normal");
        ColorLocation = GL.GetAttribLocation(Program, "vertex_color");
        UniformMVPMatrixLocation = GL.GetUniformLocation(Program, "mvp_matrix");
        UniformMouseXLocation = GL.GetUniformLocation(Program, "mouse_x");
        UniformMouseYLocation = GL.GetUniformLocation(Program, "mouse_y");
        SamplerLocation = GL.GetUniformLocation(Program, "main_texture");


        GL.GenBuffers(1, out SSB);
        GL.BindBuffer(BufferTarget.ShaderStorageBuffer, SSB);
        GL.BufferData(BufferTarget.ShaderStorageBuffer, (IntPtr)(4 * sizeof(float)), ref defaultPickSSB, BufferUsageHint.DynamicCopy);
        GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, SSB);

        GL.UseProgram(0);
    }

Метод OnRenderFrame

    protected override void OnRenderFrame(FrameEventArgs e)
    {
        base.OnRenderFrame(e);

        GL.Viewport(0, 0, Width, Height);
        GL.ClearColor(0.0f, 0.8f, 0.8f, 1.0f);
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

        GL.UseProgram(Program);

        GL.BindTexture(TextureTarget.Texture2D, TextureID);
        GL.Uniform1(SamplerLocation, TextureID);

        m.draw(PositionLocation, NormalLocation, ColorLocation, PickColorLocation);

        GL.UseProgram(0);

        SwapBuffers();
    }

Мой фрагмент шейдера:

#version 430
in vec4 frag_color;
in vec4 gl_FragCoord;
flat in int frag_pick_index;

out vec4 color;

layout (std430, binding = 0) buffer mouse_color { int pick_index; float depth_value; };

uniform int mouse_x;
uniform int mouse_y;
uniform sampler2D main_texture;

void main(void)
{       
    if (int(gl_FragCoord.x) == mouse_x && int(gl_FragCoord.y) == mouse_y) {
        if (gl_FragCoord.z < depth_value) 
        {
            pick_index = frag_pick_index;
            depth_value = gl_FragCoord.z;
        }
    }

    // pick_index = textureSize(main_texture, 0).y;

    if (int(gl_FragCoord.x) == mouse_x || int(gl_FragCoord.y) == mouse_y) {
        color = vec4(0.0f, 1,0,1.0f);
    } else {
        color = frag_color;
    }

    color = texture(main_texture, vec2(0.5f, 0.5f));
}

1 ответ

Решение

Целое число, которое вы передаете в сэмплер, должно быть индексом текстуры, к которой привязана текстура, а не идентификатором текстуры. Если вы не звонили GL.ActiveTexture где-то активная текстурная единица TextureUnit.Texture0Это означает, что вы должны передать 0 GL.Uniform1:

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, 0);
Другие вопросы по тегам