简体   繁体   中英

OpenGL fragment shader is moving objects

I'm trying to write directional lighting into an OpenGL shader in a similar fashion to the one suggested in this Vuforia post:

https://developer.vuforia.com/resources/dev-guide/enabling-lighting-effects

However, the effect is rather dingy from this shader and is locked to the device, as though the light source is from the screen. Instead, therefore, I've created a uniform vec3f which is manipulated by the model view projection matrix to allow me to lock a constant vector to the model frame (this bit seems to be working, by the way). To counteract the dinginess, I increased the value of the ambient and diffuse light colour vectors, and I also added a slight yellow cast to the directional light and a slight blue one to the ambient light.

This caused some things to disappear; I guessed that possibly the shader was creating invalid colour values. No problem. I added a clamping system to the end that takes values from 0.9 to 1.1 and condenses them to the range 0.9 to 1.0 (a sort of primitive soft clip) and takes any values below 0.0 and clamps them to 0.0.

The upper bound clamping worked for some objects but not others. The lower bound clamping has caused various objects to appear rotated at apparently random angles.

So what I assume is happening is something from my shader is overflowing into an adjacent memory location and screwing up the vertex rendering, but I don't know what. Moreover, since I'm not writing to gl_FragColor till after the intermediate colour vector has been clamped, I can't tell why this would happen. Can anyone make any suggestions?

Full shader code herewith:

static const char* cubeMeshVertexShader = " \
  \
attribute vec4 vertexPosition; \
attribute vec4 vertexNormal; \
attribute vec2 vertexTexCoord; \
 \
varying vec2 texCoord; \
varying vec4 normal; \
 \
uniform mat4 modelViewMatrix; \
uniform mat4 modelViewProjectionMatrix; \
void main() \
{ \
   gl_Position = modelViewProjectionMatrix * vertexPosition; \
   normal = modelViewMatrix * vec4(vertexNormal.xyz, 0.0); \
   normal = normalize(normal); \
   texCoord = vertexTexCoord; \
} \
";


static const char* cubeFragmentShader = " \
 \
precision mediump float; \
 \
varying vec2 texCoord; \
varying vec4 normal; \
 \
uniform sampler2D texSampler2D; \
uniform vec3 lightingVector; \
uniform vec3 diffuseMaterial; \
 \
void main() \
{ \
   vec3 n = normalize(normal.xyz); \
   vec3 lightDir = vec3(0.0, 0.0, -1.0); \
   vec3 ambient = vec3(0.5, 0.57, 0.6); \
   vec3 diffuseLight = vec3(0.9, 0.89, 0.87); \
   float diffuseFactor = max(0.0, dot(n, normalize(lightingVector))); \
   vec3 diffuse = diffuseFactor * diffuseMaterial * diffuseLight; \
   vec3 shadedColor = ambient + diffuse; \
 \
   vec4 intermediate = vec4(shadedColor, 1.0) * texture2D(texSampler2D, texCoord); \
   if(intermediate.x>0.9) { \
      if(intermediate.x<1.1) { \
         intermediate.x = intermediate.x / 2.0 + 0.45; \
      } else { \
         intermediate.x = 1.0; \
      } \
   } else if(intermediate.x<0.0) { \
      intermediate.x = 0.0; \
   } \
   if(intermediate.y>0.9) { \
      if(intermediate.y<1.1) { \
         intermediate.y = intermediate.y / 2.0 + 0.45; \
      } else { \
         intermediate.y = 1.0; \
      } \
   } else if(intermediate.y<0.0) { \
      intermediate.y = 0.0; \
   } \
   if(intermediate.z>0.9) { \
      if(intermediate.z<1.1) { \
         intermediate.z = intermediate.z / 2.0 + 0.45; \
      } else { \
         intermediate.z = 1.0; \
      } \
   } else if(intermediate.y<0.0) { \
      intermediate.y = 0.0; \
   } \
   gl_FragColor = intermediate; \
} \
";

EDIT: the OpenGL standard states that gl_FragColor is automatically clamped to [0,1], so my clamping system is unnecessary (though I will probably keep the soft clip). However, this suggests that it's actually a side-effect of the shader's operation that's causing the problem, not an effect.

Light dir in your shader is constant, but lightdir should be the one from the object pointing to the light source, so it should be computed per vertex in your vertex shader

vec3 LightDir = normalize(gl_LightSource[0].position.xyz - vec3(gl_ModelViewMatrix * gl_Vertex);

Moreover one of your coef in Intermediate computation (clamping have an appropriate function: clamp) coulb be equal to 0.

this could be:

  • your texture is not bound which will multiply by (0,0,0,0) your shadedColor.
  • your diffuse material is not set
  • your light vect is perpendicular to normal ( dot product = 0)

This was actually cause by me stupidly failing to zero initialize some parameters in another edit; it was trying to rotate some objects by NaN . I'm leaving the question here because the comments have some good advice about shader programming.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM