I'm developing an application that uses Qt 4.7 with the goal of creating a simple 3D OpenGL viewer. I want to use GLSL 3.30 shaders. I use Linux Ubutu 11.10, my CG is a NVIDIA with a NVS 3100M GPU, the NVIDIA driver version is 280.13 and OpenGL version is 3.3.0
I have a working basic shader which doesn't compute any lighting. That is wanted to do next but I'm stuck with a problem.
Here is my not-working modified vertex shader.
#version 330
in vec3 inPosition;
in vec4 inColor;
in vec3 inNormal;
uniform mat4 inModelMatrix;
uniform mat4 inViewMatrix;
uniform mat4 inProjectionMatrix;
out vec4 exColor;
uniform Light {
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
} lights[4];
void main(void)
{
gl_Position = inProjectionMatrix * inViewMatrix * inModelMatrix * vec4(inPosition, 1.0);
exColor = lights[0].ambient;
}
The OpenGL Shading Language reference for GLSL 3.30 states that:
uniform Transform { // API uses “Transform[2]” to refer to instance 2
mat4 ModelViewMatrix;
mat4 ModelViewProjectionMatrix;
float Deformation;
} transforms[4];
...
... = transforms[2].ModelViewMatrix; // shader access of instance 2
// API uses “Transform.ModelViewMatrix” to query an offset or other query
So if I'm not mistaken, the code is correct. However, it doesn't even compile. The following error is thrown:
QGLShader::link: "Vertex info
-----------
Internal error: assembly compile error for vertex shader at offset 1805:
-- error message --
line 38, column 15: error: expected '='
line 82, column 36: error: expected ';'
-- internal assembly text --
!!NVvp4.1
OPTION NV_parameter_buffer_object2;
# cgc version 3.1.0001, build date Jul 27 2011
# command line args:
#vendor NVIDIA Corporation
#version 3.1.0.1
#profile gp4_1vp
#program main
#semantic Light.lights
#semantic inModelMatrix
#semantic inViewMatrix
#semantic inProjectionMatrix
#var float4 gl_Position : $vout.POSITION : HPOS : -1 : 1
#var float4 lights[0].position : BUFFER[0] : buffer[0][0] : -1 : 0
#var float4 lights[0].ambient : BUFFER[0] : buffer[0][16] : -1 : 1
#var float4 lights[0].diffuse : BUFFER[0] : buffer[0][32] : -1 : 0
#var float4 lights[0].specular : BUFFER[0] : buffer[0][48] : -1 : 0
#var float4 lights[1].position : BUFFER[1] : buffer[1][0] : -1 : 0
#var float4 lights[1].ambient : BUFFER[1] : buffer[1][16] : -1 : 0
#var float4 lights[1].diffuse : BUFFER[1] : buffer[1][32] : -1 : 0
#var float4 lights[1].specular : BUFFER[1] : buffer[1][48] : -1 : 0
#var float4 lights[2].position : BUFFER[2] : buffer[2][0] : -1 : 0
#var float4 lights[2].ambient : BUFFER[2] : buffer[2][16] : -1 : 0
#var float4 lights[2].diffuse : BUFFER[2] : buffer[2][32] : -1 : 0
#var float4 lights[2].specular : BUFFER[2] : buffer[2][48] : -1 : 0
#var float4 lights[3].position : BUFFER[3] : buffer[3][0] : -1 : 0
#var float4 lights[3].ambient : BUFFER[3] : buffer[3][16] : -1 : 0
#var float4 lights[3].diffuse : BUFFER[3] : buffer[3][32] : -1 : 0
#var float4 lights[3].specular : BUFFER[3] : buffer[3][48] : -1 : 0
#var float3 inPosition : $vin.ATTR0 : ATTR0 : -1 : 1
#var float4 inColor : : : -1 : 0
#var float3 inNormal : : : -1 : 0
#var float4x4 inModelMatrix : : c[0], 4 : -1 : 1
#var float4x4 inViewMatrix : : c[4], 4 : -1 : 1
#var float4x4 inProjectionMatrix : : c[8], 4 : -1 : 1
#var float4 exColor : $vout.ATTR0 : ATTR0 : -1 : 1
PARAM c[12] = { program.local[0..11] };
CBUFFER buf0[][] = { program.buffer[0..3] };
ATTRIB vertex_attrib[] = { vertex.attrib[0..0] };
OUTPUT result_attrib[] = { result.attrib[0..0] };
TEMP R0, R1, R2, R3, R4, R5, R6, R7, R8;
MOV.F R3, c[9];
MOV.F R2, c[8];
MUL.F R0, R3, c[5].y;
MOV.F R1, c[10];
MAD.F R0, R2, c[5].x, R0;
MAD.F R5, R1, c[5].z, R0;
MOV.F R0, c[11];
MAD.F R6, R0, c[5].w, R5;
MUL.F R4, R3, c[4].y;
MAD.F R5, R2, c[4].x, R4;
MAD.F R5, R1, c[4].z, R5;
MAD.F R5, R0, c[4].w, R5;
MUL.F R4, R6, c[1].y;
MAD.F R8, R5, c[1].x, R4;
MUL.F R4, R3, c[6].y;
M UL.F R7, R6, c[0].y;
MAD.F R4, R2, c[6].x, R4;
MUL.F R3, R3, c[7].y;
MAD.F R2, R2, c[7].x, R3;
MAD.F R3, R1, c[6].z, R4;
MAD.F R1, R1, c[7].z, R2;
MAD.F R2, R0, c[6].w, R3;
MUL.F R4, R6, c[2].y;
MAD.F R0, R0, c[7].w, R1;
MAD.F R3, R2, c[1].z, R8;
MAD.F R1, R0, c[1].w, R3;
MAD.F R7, R5, c[0].x, R7;
MAD.F R3, R2, c[0].z, R7;
MAD.F R3, R0, c[0].w, R3;
MUL.F R1, vertex.attrib[0].y, R1;
MAD.F R1, vertex.attrib[0].x, R3, R1;
MUL.F R3, R6, c[3].y;
MAD.F R3, R5, c[3].x, R3;
MAD.F R3, R2, c[3].z, R3;
MAD.F R4, R5, c[2].x, R4;
MAD.F R3, R0, c[3].w, R3;
MAD.F R2, R2, c[2].z, R4;
MAD.F R0, R0, c[2].w, R2;
MAD.F R0, vertex.attrib[0].z, R0, R1;
ADD.F result.position, R0, R3;
LDC.F32X4 result.attrib[0], buf0[0][16];
END
# 41 instructions, 9 R-regs
"
If I remove the call to lights[0].ambient, the shader compiles but when I try to get the uniform location, it doesn't work:
int lightsLocation = shaderProgram.uniformLocation("Light[0]");
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)(context()->getProcAddress("glGetUniformLocation"));
qDebug() << lightsLocation << glGetUniformLocation(shaderProgram.programId(), "Light[0]"); // -1 -1
I've also tried this with "Light", "lights", "lights[0]", "lights[0].ambient" as uniform name with no success.
After some search, I've found this post: Setting the values of a struct array from JS to GLSL and thus tried to use structures as it is shown but this doesn't work either.
Subsequent question
Event if I could bring that to work thanks to some answer, I don't know which method of QGLShaderProgram I should use to upload the data.
tl;dr
1) Why doesn't the following code compile? out vec4 exColor;
uniform Light {
vec4 ambient;
} lights[4];
void main(void) {
exColor = lights[0].ambient;
}
2) What uniform name should one use as parameter of QGLShaderProgam::uniformLocation() to get the location of a uniform Light { ... } lights[4];
or struct Light { ... }; uniform Light lights[4];
?
3) Once the location is retrieved, what function of QGLShaderProgram should one use to upload the data to the GPU?
Thank you very much!