rabn21's picture

VB.net problem with multiple textures being passed to a shader

Edit: I completely forgot the shader code which might be the most important bit!

Hi folks.

I am having a bit of trouble with using multiple textures in my game and I am hoping someone can help. I have got my code working with a single texture using shaders which is being applied to a cube using uv mapping. I am having trouble however when trying to create a version of this shader to use two textures. One for the diffuse / colour map (this is named colour_texture) and one for the normal map (normal_texture). It always seems to use the first texture loaded no matter which texture I reference within the shader. I can load the normal texture into texture0 and it displays ok so I know there is no issue with loading the texture.

Anyway here is my code. I hope it is easy enough to follow.

I am using Windows 7 (64 bit) and when I load the details using the following lines

        System.Diagnostics.Debug.Print(GL.GetString(StringName.Version))
        System.Diagnostics.Debug.Print(GL.GetString(StringName.Renderer))
        System.Diagnostics.Debug.Print(GL.GetString(StringName.Vendor))

i get these in the debug console

3.3.10750 Compatibility Profile Context
ATI Radeon HD 4800 Series
ATI Technologies Inc.

Here is the shader code.

Vertext Shader:-

void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;

// Set the position of the current vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragment Shader (always seems to show colour_texture):-

uniform sampler2D colour_texture;
uniform sampler2D normal_texture;

void main() {
gl_FragColor = texture2D(normal_texture, gl_TexCoord[0].st);
}

Here is the vb code.

Option Explicit On
 
Imports OpenTK
Imports OpenTK.Graphics
Imports OpenTK.Graphics.OpenGL
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
 
Public Class ShaderQuads
    Inherits GameWindow
 
    Protected angle As Single
    Protected textures(2) As Integer
 
    Protected vertex_shader_object As Integer
    Protected fragment_shader_object As Integer
    Protected shader_program As Integer
 
    Protected texture0 As Integer
    Protected texture1 As Integer
 
    Protected verticies() As Vector3
    Protected normals() As Vector3
    Protected uvs() As Vector2
    Protected uvquads() As UVQuad
    Dim faceCount As Integer
 
    Public Sub New()
        MyBase.New(468, 360, GraphicsMode.Default, "Shader Test - Normal Mapping")
    End Sub
 
    Public Sub LoadModels()
        Dim filename As String = "dice.js"
 
        Dim mString As String = File.ReadAllText(filename)
 
        'System.Diagnostics.Debug.Print(mString)
 
        Dim vcString As String = mString.Substring(mString.IndexOf("""vertices"" :"))
        vcString = vcString.Substring(vcString.IndexOf("[") + 1)
        vcString = vcString.Substring(0, vcString.IndexOf("]"))
 
        Dim vcList() As String = vcString.Split(",")
 
        Dim vertCount As Integer = vcList.Length / 3
        ReDim verticies(vertCount)
 
        For v As Integer = 0 To vertCount - 1
            verticies(v) = New Vector3(Single.Parse(vcList(v * 3)), Single.Parse(vcList((v * 3) + 1)), Single.Parse(vcList((v * 3) + 2)))
            'System.Diagnostics.Debug.Print(verticies(v).ToString)
        Next v
 
        Dim ncString As String = mString.Substring(mString.IndexOf("""normals"" :"))
        ncString = ncString.Substring(ncString.IndexOf("[") + 1)
        ncString = ncString.Substring(0, ncString.IndexOf("]"))
 
        Dim ncList() As String = ncString.Split(",")
        Dim normCount As Integer = ncList.Length / 3
        ReDim normals(normCount)
 
        For n As Integer = 0 To normCount - 1
            normals(n) = New Vector3(Single.Parse(ncList(n * 3)), Single.Parse(ncList((n * 3) + 1)), Single.Parse(ncList((n * 3) + 2)))
            'System.Diagnostics.Debug.Print(normals(n).ToString)
        Next n
 
        Dim uvcString As String = mString.Substring(mString.IndexOf("""uvs"" :"))
        uvcString = uvcString.Substring(uvcString.IndexOf("[[") + 2)
        uvcString = uvcString.Substring(0, uvcString.IndexOf("]"))
 
        Dim uvcList() As String = uvcString.Split(",")
        Dim uvCount As Integer = uvcList.Length / 2
        ReDim uvs(uvCount)
 
        For u As Integer = 0 To uvCount - 1
            uvs(u) = New Vector2(Single.Parse(uvcList(u * 2)), Single.Parse(uvcList((u * 2) + 1)))
            'System.Diagnostics.Debug.Print(uvs(u).ToString)
        Next u
 
        Dim fcString As String = mString.Substring(mString.IndexOf("""faces"" :"))
        fcString = fcString.Substring(fcString.IndexOf("[") + 2)
        fcString = fcString.Substring(0, fcString.IndexOf("]"))
 
        Dim fcList() As String = fcString.Split(",")
        faceCount = fcList.Length / 14
        ReDim uvquads(faceCount)
 
        For f As Integer = 0 To faceCount - 1
            Dim a As Vector3 = verticies(Integer.Parse(fcList((f * 14) + 1)))
            Dim b As Vector3 = verticies(Integer.Parse(fcList((f * 14) + 2)))
            Dim c As Vector3 = verticies(Integer.Parse(fcList((f * 14) + 3)))
            Dim d As Vector3 = verticies(Integer.Parse(fcList((f * 14) + 4)))
            Dim materialIndex As Integer = Integer.Parse(fcList((f * 14) + 5))
            Dim uva As Vector2 = uvs(Integer.Parse(fcList((f * 14) + 6)))
            Dim uvb As Vector2 = uvs(Integer.Parse(fcList((f * 14) + 7)))
            Dim uvc As Vector2 = uvs(Integer.Parse(fcList((f * 14) + 8)))
            Dim uvd As Vector2 = uvs(Integer.Parse(fcList((f * 14) + 9)))
            Dim na As Vector3 = normals(Integer.Parse(fcList((f * 14) + 10)))
            Dim nb As Vector3 = normals(Integer.Parse(fcList((f * 14) + 11)))
            Dim nc As Vector3 = normals(Integer.Parse(fcList((f * 14) + 12)))
            Dim nd As Vector3 = normals(Integer.Parse(fcList((f * 14) + 13)))
            uvquads(f) = New UVQuad(a, b, c, d, materialIndex, uva, uvb, uvc, uvd, na, nb, nc, nd)
            'System.Diagnostics.Debug.Print(uvquads(f).ToString)
        Next f
 
    End Sub
 
    Private Sub CreateTexture(ByRef texture As Integer, ByVal bitmap As Bitmap)
 
        GL.GenTextures(1, texture)
 
        ' Still required else TexImage2D will be applyed on the last bound texture
        GL.BindTexture(TextureTarget.Texture2D, texture)
 
        Dim data As BitmapData = 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, Integer.Parse(TextureMinFilter.Linear))
 
    End Sub
 
    Private Sub BindTexture(ByRef textureId As Integer, ByVal textureUnit As TextureUnit, ByVal UniformName As String)
 
        GL.ActiveTexture(textureUnit)
        GL.BindTexture(TextureTarget.Texture2D, textureId)
        GL.Uniform1(GL.GetUniformLocation(shader_program, UniformName), textureUnit - textureUnit.Texture0)
 
    End Sub
 
    Protected Sub LoadTextures()
 
        Dim bitmap0 As New Bitmap("diffuse1.jpg")
        Dim bitmap1 As New Bitmap("normal1.jpg")
 
        CreateTexture(texture0, bitmap0)
        CreateTexture(texture1, bitmap1)
 
        BindTexture(texture0, TextureUnit.Texture0, "colour_texture")
        BindTexture(texture1, TextureUnit.Texture1, "normal_texture")
 
    End Sub
 
    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        MyBase.OnLoad(e)
 
        System.Diagnostics.Debug.Print(GL.GetString(StringName.Version))
        System.Diagnostics.Debug.Print(GL.GetString(StringName.Renderer))
        System.Diagnostics.Debug.Print(GL.GetString(StringName.Vendor))
 
        GL.ClearColor(0.1, 0.5, 0.6, 0)
        GL.ClearDepth(1.0)
        GL.ShadeModel(ShadingModel.Smooth)
        GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest)
        GL.Enable(EnableCap.DepthTest)
        GL.Enable(EnableCap.Texture2D)
 
        LoadTextures()
        LoadModels()
 
        Using vs As New StreamReader("Simple_VS.glsl")
            Using fs As New StreamReader("Simple_FS.glsl")
                CreateShaders(vs.ReadToEnd(), fs.ReadToEnd(),
                    vertex_shader_object, fragment_shader_object,
                    shader_program)
            End Using
        End Using
 
    End Sub
 
    Sub CreateShaders(ByVal vs As String, ByVal fs As String,
            ByRef vertexObject As Integer, ByRef fragmentObject As Integer,
            ByRef program As Integer)
 
        Dim status_code As Integer
        Dim info As String = ""
 
        vertexObject = GL.CreateShader(ShaderType.VertexShader)
        fragmentObject = GL.CreateShader(ShaderType.FragmentShader)
 
        ' Compile vertex shader
        GL.ShaderSource(vertexObject, vs)
        GL.CompileShader(vertexObject)
        GL.GetShaderInfoLog(vertexObject, info)
        GL.GetShader(vertexObject, ShaderParameter.CompileStatus, status_code)
 
        If status_code <> 1 Then
            Throw New ApplicationException(info)
        End If
 
        'Compile vertex shader
        GL.ShaderSource(fragmentObject, fs)
        GL.CompileShader(fragmentObject)
        GL.GetShaderInfoLog(fragmentObject, info)
        GL.GetShader(fragmentObject, ShaderParameter.CompileStatus, status_code)
 
        If status_code <> 1 Then
            Throw New ApplicationException(info)
        End If
 
        program = GL.CreateProgram()
        GL.AttachShader(program, fragmentObject)
        GL.AttachShader(program, vertexObject)
 
        GL.LinkProgram(program)
        GL.UseProgram(program)
 
    End Sub
 
    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        MyBase.OnResize(e)
        GL.Viewport(0, 0, Me.Width, Me.Height)
        Dim aspect As Single = CSng(Me.Width) / Me.Height
        Dim projMat As Matrix4 = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect, 0.1, 100.0)
        GL.MatrixMode(MatrixMode.Projection)
        GL.LoadMatrix(projMat)
        GL.MatrixMode(MatrixMode.Modelview)
        GL.LoadIdentity()
    End Sub
 
    Protected Overrides Sub OnRenderFrame(ByVal e As OpenTK.FrameEventArgs)
        MyBase.OnRenderFrame(e)
        GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit)
        GL.LoadIdentity()
        GL.Translate(0, 0, -5)
 
        GL.Rotate(angle, 1, 0, 0)
        GL.Rotate(angle, 0, 1, 0)
        GL.Rotate(angle, 0, 0, 1)
        angle += 0.5
 
        GL.Begin(BeginMode.Quads)
 
        For f As Integer = 0 To (faceCount - 1)
            GL.TexCoord2(uvquads(f).UVA.X, 1.0 - uvquads(f).UVA.Y) : GL.Vertex3(uvquads(f).A.X, uvquads(f).A.Y, uvquads(f).A.Z) : GL.Normal3(uvquads(f).NormalA.X, uvquads(f).NormalA.Y, uvquads(f).NormalA.Z)
            GL.TexCoord2(uvquads(f).UVB.X, 1.0 - uvquads(f).UVB.Y) : GL.Vertex3(uvquads(f).B.X, uvquads(f).B.Y, uvquads(f).B.Z) : GL.Normal3(uvquads(f).NormalB.X, uvquads(f).NormalB.Y, uvquads(f).NormalB.Z)
            GL.TexCoord2(uvquads(f).UVC.X, 1.0 - uvquads(f).UVC.Y) : GL.Vertex3(uvquads(f).C.X, uvquads(f).C.Y, uvquads(f).C.Z) : GL.Normal3(uvquads(f).NormalC.X, uvquads(f).NormalC.Y, uvquads(f).NormalC.Z)
            GL.TexCoord2(uvquads(f).UVD.X, 1.0 - uvquads(f).UVD.Y) : GL.Vertex3(uvquads(f).D.X, uvquads(f).D.Y, uvquads(f).D.Z) : GL.Normal3(uvquads(f).NormalD.X, uvquads(f).NormalD.Y, uvquads(f).NormalD.Z)
        Next f
 
        GL.End()
        SwapBuffers()
 
    End Sub
 
    Public Shared Sub Main()
        Dim app As New ShaderQuads
        app.Run(60, 60)
    End Sub
 
End Class

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rabn21's picture

I think I have managed to fix this one. It seems to work ok when I put both into variables in the shader first and then set gl_FragColor as the second texture like this

uniform sampler2D colour_texture;
uniform sampler2D normal_texture;

vec3 color = texture2D(colour_texture, gl_TexCoord[0].st).rgb;
vec3 normal = texture2D(normal_texture, gl_TexCoord[0].st).rgb;

gl_FragColor = vec4(normal, 1.0);

Edit: I have just realised that in my previous post the code would be returning a vec3 instead of a vec4 so not sure if that was the problem or not.