OpenGL纹理渲染 - 仅显示左上角的像素

时间:2014-11-20 08:48:37

标签: c# opengl opentk

我使用C#和OpenTK。 目前我只想在三角形上绘制纹理。 它似乎工作但是在最近的纹理滤镜上,整个三角形只用bmp图像的左上角像素颜色着色,如果我将纹理滤镜设置为线性,三角形仍然只显示一种颜色,但看起来它是否是现在与其他像素混合。 有人可以在代码中找到错误吗?

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

            GL.Enable(EnableCap.Texture2D);
            GL.ClearColor(0.5F, 0.5F, 0.5F, 1.0F);

            int vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
            int fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);

            string vertexShaderSource = @"#version 400
                                            layout(location = 0) in vec3 position;
                                            layout(location = 1) in vec2 uv;
                                            out vec2 texture_uv;
                                            void main()
                                            {
                                                gl_Position = vec4(inPosition.xyz, 1);
                                                texture_uv = uv;
                                            }";
            string fragmentShaderSource = @"#version 400
                                            in vec2 texture_uv;
                                            out vec3 outColor;
                                            uniform sampler2D uniSampler;
                                            void main()
                                            {
                                                outColor = texture( uniSampler, texture_uv ).rgb;
                                            }";

            GL.ShaderSource(vertexShaderHandle, vertexShaderSource);
            GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource);

            GL.CompileShader(vertexShaderHandle);
            GL.CompileShader(fragmentShaderHandle);

            prgHandle = GL.CreateProgram();
            GL.AttachShader(prgHandle, vertexShaderHandle);
            GL.AttachShader(prgHandle, fragmentShaderHandle);
            GL.LinkProgram(prgHandle);

            GL.DetachShader(prgHandle, vertexShaderHandle);
            GL.DetachShader(prgHandle, fragmentShaderHandle);
            GL.DeleteShader(vertexShaderHandle);
            GL.DeleteShader(fragmentShaderHandle);

            uniSamplerLoc = GL.GetUniformLocation(prgHandle, "uniSampler");

            texHandle = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, texHandle);
            Bitmap bmp = new Bitmap("C:/Users/Michael/Desktop/Test.bmp");
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

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

            bmp.UnlockBits(bmpData);

            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);

            vaoHandle = GL.GenVertexArray();
            GL.BindVertexArray(vaoHandle);

            vboHandle = GL.GenBuffer();
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
            float[] bufferData = {  0.5F, 1, 0, 1, 1, 
                                    0, 0, 0, 0, 0, 
                                    1, 0, 0, 1, 0 };
            GL.BufferData<float>(BufferTarget.ArrayBuffer, (IntPtr) (15 * sizeof(float)), bufferData, BufferUsageHint.StaticDraw);

            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);
            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
            GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
        }
        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);

            GL.DeleteTexture(texHandle);
            GL.DeleteProgram(prgHandle);
            GL.DeleteBuffer(vboHandle);
            GL.DeleteVertexArray(vaoHandle);
        }
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);

            GL.Clear(ClearBufferMask.ColorBufferBit);
            GL.UseProgram(prgHandle);
            GL.Uniform1(uniSamplerLoc, texHandle);
            GL.BindVertexArray(vaoHandle);
            GL.DrawArrays(PrimitiveType.Triangles, 0, 3);

            SwapBuffers();
        }

编辑:

我试过了:

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

    GL.Clear(ClearBufferMask.ColorBufferBit);
    GL.UseProgram(prgHandle);

    GL.BindVertexArray(vaoHandle);

    GL.ActiveTexture(TextureUnit.Texture3);
    GL.BindTexture(TextureTarget.Texture2D, texHandle);
    GL.Uniform1(uniSamplerLoc, 3);

    GL.DrawArrays(PrimitiveType.Triangles, 0, 3);

    SwapBuffers();
}

但没有改变:(

1 个答案:

答案 0 :(得分:2)

采样器均匀变量的值必须是它应该采样的纹理单元。在你的代码中,它被设置为纹理名称(也就是纹理id,也就是纹理句柄):

GL.Uniform1(uniSamplerLoc, texHandle);

可以使用ActiveTexture()设置纹理单元。调用glBindTexture()时,当前活动纹理单元的值确定纹理绑定到哪个单位。活动纹理单元的默认值为0.因此,如果您从未调用ActiveTexture(),则应将制服设置为:

GL.Uniform1(uniSamplerLoc, 0);

正如单挑,另一个相关的错误来源是均匀的值是纹理单元的基于0的索引,而glActiveTexture()调用采用以{{1}开头的枚举}。例如,使用C绑定(不确定C#和OpenTK的外观如何,但它应该足够相似),这会将纹理绑定到纹理单元3,并设置一个统一的采样器变量来使用它:

GL_TEXTURE0

请注意glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, texId); glUniform1i(texUniformLoc, 3); 的参数中使用的GL_TEXTURE3glActiveTexture()中的3 {。}}。