OpenGL纹理映射与纹理单元0一起使用,但不与纹理单元1一起使用

时间:2014-07-02 14:05:26

标签: c# opengl shader opentk

我正在使用OpenTK(围绕OpenGL的.NET包装),并在表单中使用GLControl。

我已经使用Loading a texture from diskLoading multiple textures and passing through to a shader教程来完成纹理映射。但是当我尝试设置GL.ActiveTexture(TextureUnit.Texture1),并在该单元上进行所有纹理绑定和加载时,我得到一个纯色显示(看似是texel(0,0)处的颜色)。 p>

我很困惑为什么简单地将纹理单元切换为使用1而不是默认值为0会破坏程序。

我想我会离开固定功能管道,而是使用着色器来进行纹理着色。也没有运气。

我认为这与使用glDrawArrays将顶点提供给顶点着色器的方式有关。我在着色器中使用常量顶点数据,使用gl_VertexID进行挑选,以简化而不是使用属性。

顶点着色器:

#version 420

const mat4x3 vs = mat4x3(-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0);
const mat4x2 ts = mat4x2(0.0, 1.0,1.0, 1.0, 1.0, 0.0, 0.0, 0.0);

out vec2 tcoord;
void main() {
    gl_Position = vec4(vs[gl_VertexID],1);
    tcoord = ts[gl_VertexID];
}

Fragment Shader:

#version 420
uniform sampler2D MyTexture0;
uniform sampler2D MyTexture1;
uniform sampler2D MyTexture2;
uniform sampler2D MyTexture3;

in vec2 tcoord;
out vec4 color;
void main(void)
{
    color = texture2D( MyTexture3, tcoord);  
}

绘制命令:

GL.DrawArrays(PrimitiveType.Quads, 0, 4);

整个来源:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.Diagnostics;
using System.Drawing.Imaging;

namespace TextureShaderDemoGLControl
{
    public partial class Form1 : Form
    {
        bool immediateMode = true;
        public Form1()
        {
            InitializeComponent();
        }

        Stopwatch sw = Stopwatch.StartNew();

        int fragmentShaderHandle, shaderProgramHandle, texture0, texture1, texture2, texture3;

        Bitmap bitmap0 = new Bitmap(@"img.gif");

        string vertShaderSource = @"
        #version 420

        const mat4x3 vs = mat4x3(-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0);
        const mat4x2 ts = mat4x2(0.0, 1.0,1.0, 1.0, 1.0, 0.0, 0.0, 0.0);

        out vec2 tcoord;
        void main() {
            gl_Position = vec4(vs[gl_VertexID],1);
            tcoord = ts[gl_VertexID];
        }

        ";

        string fragmentShaderSource = @"
                #version 420
                uniform sampler2D MyTexture0;
                uniform sampler2D MyTexture1;
                uniform sampler2D MyTexture2;
                uniform sampler2D MyTexture3;

                in vec2 tcoord;
                out vec4 color;
                void main(void)
                {
                    color = texture2D( MyTexture3, tcoord);  
                }"
            ;

        void CreateShaders()
        {
            int vertShaderHandle = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(vertShaderHandle, vertShaderSource);
            GL.CompileShader(vertShaderHandle);
            Debug.WriteLine(GL.GetShaderInfoLog(vertShaderHandle));

            fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource); 
            GL.CompileShader(fragmentShaderHandle);
            Debug.WriteLine(GL.GetShaderInfoLog(fragmentShaderHandle));

            // Create program
            shaderProgramHandle = GL.CreateProgram();
            GL.AttachShader(shaderProgramHandle, vertShaderHandle);
            GL.AttachShader(shaderProgramHandle, fragmentShaderHandle);

            GL.LinkProgram(shaderProgramHandle);
            Debug.WriteLine(GL.GetProgramInfoLog(shaderProgramHandle));

            GL.UseProgram(shaderProgramHandle);

        }

        private void CreateTexture(out int texture, Bitmap bitmap)
        {
            // load texture 
            GL.GenTextures(1, out texture);

            // Still required else TexImage2D will be applied on the last bound texture
            GL.BindTexture(TextureTarget.Texture2D, texture);

            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);
        }


        private void DrawRect()
        {
            GL.Begin(PrimitiveType.Quads);

            GL.Color3(Color.Silver);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(-1.0f, -1.0f, -1.0f);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(-1.0f, 1.0f, -1.0f);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(1.0f, 1.0f, -1.0f);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(1.0f, -1.0f, -1.0f);

            GL.End();
        }

        private void glControl1_Load(object sender, EventArgs e)
        {

            CreateShaders();

            //GL.Enable(EnableCap.Texture2D);

            // Immediate mode drawing works with Texture Unit 0
            TextureUnit tUnit = TextureUnit.Texture0;

            // Immediate mode drawing fails with Texture Unit 1
            // TextureUnit tUnit = TextureUnit.Texture1;

            GL.ActiveTexture(tUnit);

            CreateTexture(out texture0, bitmap0);

            GL.Uniform1(GL.GetUniformLocation(shaderProgramHandle, "MyTexture0"), tUnit - TextureUnit.Texture0);

            string a = GL.GetString(StringName.ShadingLanguageVersion);
            string b = GL.GetString(StringName.Version);

            int vao = GL.GenVertexArray();
            GL.BindVertexArray(vao);

            glControl1.Invalidate();

        }

        private void glControl1_Paint(object sender, PaintEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            if (immediateMode) {
            // The immediate mode DrawRect which encapsulates GL.Begin(); GL.Vertex2(..) ... ; GL.End() works nicely
                DrawRect();
            } else {
            // Something must be wrong with the way DrawArrays feeds vertices to the vertex shader.
            //GL.DrawArrays(PrimitiveType.Quads, 0, 4);
            }

            sw.Stop();
            label1.Text = (1000.0 / sw.Elapsed.TotalMilliseconds).ToString();
            sw.Restart();

            glControl1.SwapBuffers();

        }

        private void glControl1_Resize(object sender, EventArgs e)
        {
            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
        }
    }
}

0 个答案:

没有答案