Hey everyone I'm working with lighting in a 2D Tile Based game and have run into a problem with my lighting calculations, in my game I take greyscale images then color them using shaders whatever color I like whether that be green(rgb=(0,1,0)) or red(rgb=(1,0,0)) or any color. So then I apply my lighting calculations to that textured and colored pixel. The lighting works fine when the light is white(rgb=(1,1,1)) but when it is say red or green it wont show the way I want it to. I know why this is happening of course because realistic a pure red light in a pure green room would reflect no red light so the room would remain dark. What I really want is to see a red light appear over a green surface. So my question is how can I show a red light clearly on a green surface?(or really any other color on any surface)
This is the code for my fragment shader, where attenuation is simply the attenuation for the light, lightColor is obviously the lights rgb value, distance is the distance from the given vector to that light(calculated in the vertex shader) and finally color is the rgb value that is applied to the texture.
Thanks in advance for your help!
vec3 totalDiffuse = vec3(0.0);
for(int i = 0; i < 4; i++)
{
float attFactor = attenuation[i].x + (attenuation[i].y * distance[i]) + (attenuation[i].z * distance[i] * distance[i]);
totalDiffuse = totalDiffuse + (lightColor[i])/attFactor;
}
totalDiffuse = max(totalDiffuse,0.2);
out_Color = texture(textureSampler, pass_textureCoords)*vec4(color,alpha)*vec4(totalDiffuse,1);
And here is an image of what a pure red light looks like on a surface currently, it should be inside the white circle and you may be able to see it is affecting the water a little bit because I give the water a small red component- Light Demo Image
One possibility would be to change the light calculation.
Calculate a gray scales of the light color and the surface color. Multiply the surface color by the gray scale of the light color and the multiply the light color by the gray scale of the surface color, finally sum them up:
vec4 texCol = texture(textureSampler, pass_textureCoords);
float grayTex = dot(texCol.rgb, vec3(0.2126, 0.7152, 0.0722));
float grayCol = dot(colGray.rgb, vec3(0.2126, 0.7152, 0.0722));
vec3 mixCol = texCol.rgb * grayCol + color.rgb * grayTex;
out_Color = vec4(mixCol * totalDiffuse, texCol.a * alpha);
Note, this algorithm emphasizes the color of the light at the expense of the color of the surface. But that was what you wanted by dipping a green area in red light. Of course, that contradicts the desire to illuminate an area in its own color. If the light is white, then the surface will also shine white.
If you want some light sources with the effect described above, other sources but with the original effect of the question, then I recommend to introduce a parameter that mixes the two effects:
uniform float u_lightTint;
void main()
{
.....
vec3 mixCol = texCol.rgb * grayCol + color.rgb * grayTex;
mixCol = mix(texCol.rgb * color.rgb, mixCol.rgb, u_lightTint);
out_Color = vec4(mixCol * totalDiffuse, texCol.a * alpha);
}
If u_lightTint
is set 1.0, then the "new" light calculation is uses, it it is set 0.0, then the original light calculation is use. Both algorithms can be interpolated linearly by u_lightTint
.
Alternatively the u_lightTint
parameter can be encoded in the alpha channel of the light color:
mixCol = mix(texCol.rgb * color.rgb, mixCol.rgb, color.a);