GE Vertex Shader: Cannot construct mat3 from a matrix in GLSL 1.10

Hi

I am a newbee to blender game engine and trying to make an old example patch work for blender 2.67, but I am struggling with a shader error:

Cannot construct mat3 from a matrix in GLSL 1.10

which is caused by the following line:

dir =  mat3(cam2world) * (view, normal);

acrording to the net it is caused by the inability of GLSL 1.10 to cast mat4 to mat3. But I am stunned, because my GFX-card supports GLSL 1.5 and I have done this casting in other apps as well.

Can somebody tell me what is going wrong?

I have not done much with GLSL directly. Have you tried putting:
#150

At the top of your shader source? This tells your video card driver what version of GLSL it is using. If your card suports 1.5 and 1.5 supports casting mat4 to mat3 then this should fix your problem. I’m not sure if Blender has a specific version of GLSL that it has to work with.

Thank you for this hint. but no success. But I am not sure if I put it at the right position. the inherited code is a strange mix of python code and shader code. its begins with some python, than changes to vertex shader and fragment shader definition and then ends with a python method definition.


import bge.logic as g
scene = g.getCurrentScene()
g.setLogicTicRate(60.0)
 
# -------------------------------------
cont = g.getCurrentController()
own = cont.owner
  
lamp = scene.objects['Lamp']

lightpos = lamp.worldPosition

thickness = own.get('thick')

colr = own.get('r')
colg = own.get('g')
colb = own.get('b')

camera = scene.objects['Camera']
cam2world = camera.getCameraToWorld()

MaterialIndexList = [0] # material index
GlobalAmbient = [0.39,0.35,0.32,1]
AmbF = 0.5





# ------------------------------------
VertexShader = """
#150
 
// Set light-position  
uniform vec3 LightPosition;  
   
// Varying variables to be sent to Fragment Shader  
varying vec3 worldNormal, eyeVec, lightVec, vertPos, lightPos, dir, view, normal, lightDir;  

uniform mat4 cam2world;
   
void subScatterVS(in vec4 ecVert)  
{  
    lightVec = LightPosition - ecVert.xyz;  
    eyeVec = -ecVert.xyz;  
    vertPos = ecVert.xyz;  
    lightPos = LightPosition;  
}  
   
 ////////////////  
 //  MAIN LOOP //  
 ////////////////  
   
void main()  
{  
    worldNormal = gl_NormalMatrix * gl_Normal;  
   
    vec4 ecPos = gl_Vertex;  
   
    // Call function to set varyings for subscatter FS  
    subScatterVS(ecPos);  
   
    //Transform vertex by modelview and projection matrices  
    gl_Position = ftransform();  
  
    //Forward current texture coordinates after applying texture matrix  
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;  

    //coords for cubemap
    normal = normalize(gl_NormalMatrix * gl_Normal);  
    view = (gl_ModelViewMatrix * gl_Vertex).xyz;
    view = (view, normal);
    //mat3 tester = mat3(cam2world);
    dir =  mat3(cam2world) * view;
    
    lightDir = vec3(gl_LightSource[0].position.xyz - view);

 }  
 
"""
 
 
FragmentShader = """
 
// Variables for lighting properties  
uniform float MaterialThickness;  
uniform vec3 ExtinctionCoefficient; // Will show as X Y and Z ports in QC, but actually represent RGB values.  
uniform vec4 LightColor;  
//uniform vec4 BaseColor;  
uniform vec4 SpecColor;  
uniform float SpecPower;  
uniform float RimScalar;  
uniform sampler2D Texture;  
uniform samplerCube CubeMap;
   
// Varying variables to be sent to Fragment Shader  
varying vec3 worldNormal, eyeVec, lightVec, vertPos, lightPos, dir, view, normal, lightDir;

   
float halfLambert(in vec3 vect1, in vec3 vect2)  
{  
    float product = dot(vect1,vect2);  
    return product * 0.5 + 0.5;  
}  
   
float blinnPhongSpecular(in vec3 normalVec, in vec3 lightVec, in float specPower)  
{  
    vec3 halfAngle = normalize(normalVec + lightVec);  
    return pow(clamp(0.0,1.0,dot(normalVec,halfAngle)),specPower);  
}  
   
// Main fake sub-surface scatter lighting function  
   
vec4 subScatterFS()  
{  
    float attenuation = 5.0 * (1.0 / distance(lightPos,vertPos));  
    vec3 eVec = normalize(eyeVec);  
    vec3 lVec = normalize(lightVec);  
    vec3 wNorm = normalize(worldNormal);  
 
    vec3 L = normalize(lightDir);     
    vec3 R = reflect(-L, normal);
    vec3 E = normalize(-view);
    float specular = pow( max(dot(R, E), 0.0), gl_FrontMaterial.shininess );
    
    vec4 dotLN = vec4(halfLambert(lVec,wNorm) * attenuation);  
    dotLN *= texture2D(Texture, gl_TexCoord[0].xy);  
    //dotLN *= BaseColor;  
       
    float fresnel = dot(normalize(view),normalize(normal));
    fresnel = abs(fresnel);
    fresnel = 1.0 - fresnel;
    
    vec3 indirectLightComponent = vec3(MaterialThickness * max(0.0,dot(-wNorm,lVec)));  
    indirectLightComponent += MaterialThickness * halfLambert(-eVec,lVec);  
    indirectLightComponent *= attenuation;  
    indirectLightComponent.r *= ExtinctionCoefficient.r;  
    indirectLightComponent.g *= ExtinctionCoefficient.g;  
    indirectLightComponent.b *= ExtinctionCoefficient.b;  
   
    vec3 rim = vec3(1.0 - max(0.0,dot(wNorm,eVec)));  
    rim *= rim;  
    rim *= max(0.0,dot(wNorm,lVec)) * SpecColor.rgb;  
  
    vec4 finalCol = dotLN + vec4(indirectLightComponent,1.0)*texture2D(Texture, gl_TexCoord[0].xy);  
    finalCol.rgb += (rim * RimScalar * attenuation * finalCol.a);  
    finalCol.rgb += vec3(blinnPhongSpecular(wNorm,lVec,SpecPower) * attenuation * SpecColor * finalCol.a * 0.05);  
    finalCol.rgb *= LightColor.rgb;  
       
    finalCol.rgb += gl_LightSource[0].specular * gl_FrontMaterial.specular * specular;

    finalCol.rgb += textureCube(CubeMap, dir)*0.5*fresnel*fresnel;
    return finalCol;  
}  
   
////////////////  
//  MAIN LOOP //  
////////////////  
   
void main()  
{  
    gl_FragColor = subScatterFS();  
}  

"""
 
 
 
def MainLoop ():
  
    for mesh in own.meshes:

        for mat in mesh.materials:
               
            # regular TexFace materials do NOT have this function
            if not hasattr(mat, "getMaterialIndex"):
                return
               
            mat_index = mat.getMaterialIndex()
 
            # find an index   
            found = 0
            for i in range(len(MaterialIndexList)):
                if mat_index == MaterialIndexList[i]:
                    found=1
                    break
            if not found: continue
 
            shader = mat.getShader()
            if shader != None:
                if not shader.isValid():
                    shader.setSource(VertexShader, FragmentShader,1)

                shader.setSampler('Texture',0)
                shader.setUniform1f('RimScalar',0.1)
                shader.setUniform1f('SpecPower',0.1)               
                shader.setUniform1f('MaterialThickness',thickness) 
                shader.setUniform3f('LightPosition',lightpos[0], lightpos[1], lightpos[2])
                shader.setUniform4f('LightColor',0.05, 0.05, 0.05, 0.0)
#                   shader.setUniform4f('BaseColor',1.0, 1.0, 1.0, 0.0)                 
                shader.setUniform4f('SpecColor',0.03, 0.06, 0.04, 0.0)              
                shader.setUniform3f('ExtinctionCoefficient',colr, colg, colb)
                shader.setSampler('CubeMap',1)
                #shader.setUniformMatrix4('cam2world',cam2world)    
                                                      
 
# -------------------------------------
 
MainLoop()
 
#------------------------------------------------------------------------------

add this function:

mat3 m3( mat4 m )
{
mat3 result;

result[0][0] = m[0][0];
result[0][1] = m[0][1];
result[0][2] = m[0][2];

result[1][0] = m[1][0];
result[1][1] = m[1][1];
result[1][2] = m[1][2];

result[2][0] = m[2][0];
result[2][1] = m[2][1];
result[2][2] = m[2][2];

return result;
}

and then try:

dir = m3(cam2world) * (view, normal);

#150 should be

#version 150

http://www.opengl.org/wiki/Core_Language_(GLSL)#Version

Just a little short inline version of mat4 → mat3 code:

mat3 m3 = mat3( m4[0].xyz, m4[1].xyz, m4[2].xyz);

Excellent, thank you for all these hints. I made it work:

Translucenct_suzanne_b26x.blend.zip (516 KB)

#version 120

did the trick (lowercase is important!), and some cast’s from vec4 to vec3, since I cant use ‘#version 150’ even though my gfx card supports glsl 1.5 (at least I think: macbook pro NVIDIA GeForce 9600M GT) , but blender doesnt wannt to swallow it. strange.

Wow this was really useful! Thank you guys very much! Especially maybites from adapting the code!