2
votes

In setting up the fragment shaders for my OpenGL game I've found that when an object darkens from being far from lights, it also loses opacity as the gl_FragColor calculation affects all four members of the color points:

GLES20.glEnable(GL_BLEND);
GLES20.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

final String Light1fragmentShader  = 
...
"varying vec4 v_Color;" +
...
"void main()" +"{"  +
...
"gl_FragColor = v_Color * diffuse * texture2D(u_Texture, v_TexCoordinate);" +
...

Since my game has tranparency enabled through GL_BLEND, my opaque textured objects render as transparent when the light is low or the sightline to normal is high as the alpha is also reduced with the RGB values. Is there an elegant way to set up my fragment shader to only have the first 3 members of each vec4 color point be affected by the diffuse?

1

1 Answers

2
votes

You can use Swizzling to access the color channels. You can use x, y, z, or w, (respectively r, g, b, a or s, t, p, q) referring to the first, second, third, and fourth components, respectively. You can use any combination of the letters to create a vector (e.g.: texColor.rgb):

vec4 texColor = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = v_Color * vec4(diffuse * texColor.rgb, texColor.a);

If the binary operators (like *) are used between vectors of the same type, they work component-wise (e.g. v_Color * vec4(...)).
A binary operator can also be used for an operation of a floating-point value to all components of a vector (e.g. diffuse * texColor.rgb).
(See further GLSL Programming/Vector and Matrix Operations)

Vectors can be constructed from other vectors, or a combination of vectors and scalars (e.g. vec4(vec3(...), texColor.a)). See Vector constructors.


Alternatively you can create a 3 component vector from diffuse and construct a 4 component vector, where the 4th component is 1 (vec4(vec3(diffuse), 1.0)):

gl_FragColor = 
    v_Color * vec4(vec3(diffuse), 1.0) * texture2D(u_Texture, v_TexCoordinate);