0

I'm using OpenTK (.NET wrapper around OpenGL), and have a GLControl in a form.

I've used the Loading a texture from disk and Loading multiple textures and passing through to a shader tutorial to get texture mapping working. But when I try to to set GL.ActiveTexture(TextureUnit.Texture1), and do all of my texture binding and loading on that unit, I get a solid colour displaying (seemingly the colour at texel (0,0)).

I'm befuddled as to why simply switching the texture unit to use 1 instead of the default 0 would break the program.

I figured I'd move away from the fixed-function pipeline and instead use shaders to do the texture colouring. No luck there either.

I'm thinking it has to do with the way I feed vertices to the vertex shader using glDrawArrays. I use constant vertex data in the shader, picked using gl_VertexID, for simplicity instead of using attributes.

Vertex Shader:

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

Draw command:

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

Entire source:

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);
        }
    }
}
Protongun
  • 3,230
  • 1
  • 15
  • 13
  • post the sample with texture1, correct statements are there to make it working if texture1 is well referenced in: Active texture, uniform name <-> textureUnit, and in the shader, the uniform name used in the sampling statement... – j-p Jul 04 '14 at 13:44
  • Uncomment this: `// TextureUnit tUnit = TextureUnit.Texture1;`, and comment the line above it: `TextureUnit tUnit = TextureUnit.Texture0;` . I set `GL.ActiveTexture(tUnit)` thereafter and pass `(tUnit - TextureUnit.Texture0)` to the shader uniform, so everything should would, just the way it does for Texture Unit 0 – Protongun Jul 04 '14 at 14:17
  • 1
    what texture are you sampling in the shader itself? 'color = texture2D( MyTexture3, tcoord);' if it's your current statement, you should replace the Uniform name accordingly: 'GL.Uniform1(GL.GetUniformLocation(shaderProgramHandle, "MyTexture3") – j-p Jul 05 '14 at 00:02

0 Answers0