Search code examples
c#opengltexturesfragment-shader

Coloring a heightmap with 1D texture in C# and openGL


I'm been stuck on this for two days. I have a height map which plots fine. The vertices are stored in a Vector3 with x and z regularly spaced and the height is y. I want to color the vertices according to height which varies from 0 to 1; I am using the opengl4CSharp libraries. I am a complete beginner here and every example I see is for c++ and 2D textures. So this is what I have so far. I am sure I am missing some commands or done things wrong. I define a byte array for the texture

        byte[] data = new byte[]
        {
             255, 000, 000,   
             000, 255, 000,   
             000, 000, 255   
        };

I then define the various opengl parameters as follows:

        Gl.Enable(EnableCap.Texture1D);
        Gl.PixelStorei(PixelStoreParameter.UnpackAlignment, 1);

        // Create a texture name
        var textureID = Gl.GenTexture();

        IntPtr myTexturePtr = Marshal.AllocHGlobal(data.Length);
        Marshal.Copy(data, 0, myTexturePtr, data.Length);

     //   Marshal.FreeHGlobal(myTexturePtr);
        Gl.BindTexture(TextureTarget.Texture1D, textureID);

        Gl.TexParameteri(TextureTarget.Texture1D, TextureParameterName.TextureWrapS, TextureParameter.Repeat);
        Gl.TexParameteri(TextureTarget.Texture1D, TextureParameterName.TextureWrapT, TextureParameter.Repeat);

        Gl.TexParameteri(TextureTarget.Texture1D, TextureParameterName.TextureMinFilter, TextureParameter.Linear);
        Gl.TexParameteri(TextureTarget.Texture1D, TextureParameterName.TextureMagFilter, TextureParameter.Linear);
        Gl.TexImage1D(TextureTarget.Texture1D, 0, PixelInternalFormat.Three, 3, 0, PixelFormat.Rgb, PixelType.UnsignedByte, myTexturePtr);

Next I do the following but I am hung up on these steps...I get an error on the samplerLocation in particular the program parameter. What is that supposed to be? The shader programs?

        uint samplerLocation = Gl.GetUniformLocation(plottingProgram, "ColorRamp");
        Gl.Uniform1i(samplerLocation, 0);
        Gl.ActiveTexture(TextureUnit.Texture0);
        Gl.BindTexture(TextureTarget.Texture1D, textureID);

and here are the shaders

   public static string VertexShader = @"
    #version 130
    layout(location = 0) in vec3 vertexPosition;

    out float height;

    uniform mat4 projection_matrix;
    uniform mat4 view_matrix;
    uniform mat4 model_matrix;

    void main(void)
    {
        height = vertexPosition.y;
        gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
    }
    ";

    public static string FragmentShader = @"
    #version 130
    uniform sampler1D colorRamp;
    in float height;

    out vec4 FragColor;
    void main(void)
    {
        FragColor = texture(colorRamp, height).rgba;
    }
    ";

Can somebody please help out? Thanks


Solution

  • You can create a pointer to your byte[] like so:

    IntPtr myTexturePtr = Marshal.AllocHGlobal(myTexture.Length);
    Marshal.Copy(myTexture, 0, myTexturePtr, myTexture.Length);
    

    Then you should be able to pass the myTexturePtr in place of where you are currently trying to pass myTexture.

    Gl.TexImage1D(TextureTarge
        t.Texture1D, 0, 
        PixelInternalFormat.Three, 3, 0, 
        PixelFormat.Rgb, PixelType.UnsignedByte, 
        myTexturePtr);
    

    Afterwards, free the pointer when you are done.

    Marshal.FreeHGlobal(myTexturePtr);