GLSL: Changes in uniforms not rendered
I'm tweaking the shader examples in OpenGL Superbible 2010 to learn about shader usage.
I wanna change the red component of a directional light that's passed as a uniform to a diffuse light shader. The vector
GLfloat vDiffuseColor [] = {redDirectionalLight, greenDirectionalLight, blueDirectionalLight, 1.0f};
is defined globally.
I can tweak the light color if I specify the variables before compiling but not when the code is running. The glut keyboard function that I'm using does increment the color values at runtime, but the modified uniform isn't being reloaded. In the SetupRC
function I locate the position of the diffuseColor
uniform
locColor = glGetUniformLocation(DirectionalLightSimpleDiffuseShader, "diffuseColor");
What I'm missing here?
vertex program:
#version 130
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;
// Set per batch
uniform vec4 diffuseColor;
uniform vec3 vLightPosition;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
// Color to fragment program
smooth out vec4 vVaryingColor;
void main(void)
{
// Get surface normal in eye coordinates
vec3 vEyeNormal = normalMatrix * vNormal;
// Get vertex position in eye coordinates
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
// Get vector to light source
vec3 vLightDir = normalize(vLightPosition - vPosition3);
// Dot product gives us diffuse intensity
float diff = max(0.0, dot(vEy开发者_如何学JAVAeNormal, vLightDir));
// Multiply intensity by diffuse color
vVaryingColor.rgb = diff * diffuseColor.rgb;
vVaryingColor.a = diffuseColor.a;
// Let's not forget to transform the geometry
gl_Position = mvpMatrix * vVertex;
}
fragment program:
#version 130
out vec4 vFragColor;
smooth in vec4 vVaryingColor;
void main(void)
{
vFragColor = vVaryingColor;
}
Here's the RenderScene code, which is called via glutDisplayFunc:
void RenderScene (void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix();
M3DMatrix44f mCamera; // CAMERA MATRIX
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.PushMatrix(mCamera);
M3DMatrix44f vLightPos= {0.0f, 10.0f, 5.0f, 1.0f};
M3DVector4f vLightEyePos;
m3dTransformVector4 (vLightEyePos, vLightPos, mCamera);
shaderManager.UseStockShader (GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
for (int i=0; i<NUM_SPHERES; i++){
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]);
glUseProgram (DirectionalLightSimpleDiffuseShader);
glUniform4fv (locColor, 1, vDiffuseColor);
glUniform3fv (locLight, 1, vEyeLight);
glUniformMatrix4fv (locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
glUniformMatrix4fv (locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
glUniformMatrix3fv (locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());
sphereBatch.Draw();
// glUseProgram(0);
modelViewMatrix.PopMatrix();
}
Please tell me you're changing vDiffuseColor
and not redDirectionalLight
, greenDirectionalLight
, blueDirectionalLight
.
GLfloat vDiffuseColor [] = {redDirectionalLight, greenDirectionalLight, blueDirectionalLight, 1.0f};
makes an array by copying the initializer, there is no connection to the original three variables.
If you want to address the three component by name, instead use (assuming C++):
GLfloat vDiffuseColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
GLfloat& redDirectionalLight = vDiffuseColor[0];
GLfloat& greenDirectionalLight = vDiffuseColor[1];
GLfloat& blueDirectionalLight = vDiffuseColor[2];
精彩评论