Partial diffuse and full specular

Hi everybody,

I am currently working lighting in OpenGL. In my shader code, I have added the diffuse and specular effect as follows:

vec3 total = ambient + diffuse + specular;
    FragColor =vec4(total,1.0);

i want the diffuse component should have the low alpha value (like 0.2), but my specular component should have the full alpha value(1.0) for rendering transparent object with glossy effect. Any one have idea about this?

If i edit my shader like this, it has full alpha diffuse value

vec3 total = ambient + diffuse + specular;
    FragColor =vec4(diffuse,0.2) + vec4(specular,1.0);

Don’t have the time to think much about your problem, but just think about, what you are doing.

Lets say your diffuse and specular terms at a specific point look like this:

diffuse = vec3(0.0, 0.0, 1.0); // blue
specular = vec3(1.0, 0.0, 0.0) // red

Now what is the result if you apply the vec4 extension and the addition as you posted it?

Here it is:

FragColor = vec4(1.0, 0.0, 1.0, 1.2);

Your alpha channel is now at 1.2 which is clamped to 1.0 and means you see a violet pixel which is not transparent!

If I understood your intention correct then what you need is an alpha value for your specular term that depends on the intensity of the reflected light. For example, you can extract the maximum value of your specular term and use it or a scaled value as alpha value. This way direct reflections should deliver alpha values of 1.0 or higher while it goes to 0 the more you are away from a perfectly reflected ray.

Thanks for your reply ProgrammerX.

I hereby attach the two images with and without fresnel affect. I want to implement this fresnel effect in my shader.

With fresnel effect, the diffuse component of the object looks like transparent but the specular component is not transparent. So i am trying to set alpha value for diffuse to be low and alpha value for specular to be high. But when i calculate a diffuse and specular effect for an object and add it for calculate color the alpha value of the diffuse and specular also added, result in full diffuse and specular.

Do you have any idea?

Thanks.

[QUOTE=unknown123;1291879]Thanks for your reply ProgrammerX.

I hereby attach the two images with and without fresnel affect. I want to implement this fresnel effect in my shader.

With fresnel effect, the diffuse component of the object looks like transparent but the specular component is not transparent. So i am trying to set alpha value for diffuse to be low and alpha value for specular to be high. But when i calculate a diffuse and specular effect for an object and add it for calculate color the alpha value of the diffuse and specular also added, result in full diffuse and specular.

Do you have any idea?

Thanks.[/QUOTE]

It would be helpful to know, what I can see on the pictures. I guess it is a blue, transparent object in front of a red opaque object? The first picture is what you want to have but with a more intense reflection and the second picture is what you get with your current method?

If that is correct I ll try to post in pseudo code what I think you should do:


vec3 diffuseColor = CalcDiffuse();
vec3 specularColor = CalcSpecular();

float specularAlpha = max(specularColor); // optionally devide by a factor to scale the value

FragColor = vec4(diffuseColor,0.2) + vec4(specularColor, specularAlpha)

I can’t promise that it will give the results which you want since I have not tested it and the last time I did some shader/light programming lies a few month in the past. But here is the idea behind it:

The diffuse term does not depend on the angle of the reflected light towards the camera and is therefore constant (As is its alpha value). If you look directly into the ray which is reflected from the surface, then it is so much light that you just see a white spot. If your resulting alpha value in this case is smaller than 1, then you won’t get a white spot, since the color is mixed with whatever color which is currently in the color buffer. So you must make sure, that your alpha value has to be 1 or higher at this point. On the other hand, if you are not looking directly into the reflection, then the arriving amount of light is significantly smaller. Now you can actually see through the transparent surface, since you are not “blinded” by the light. What this basically means is that not only your color value, but also your alpha value depends on the angle of the camera to the reflected ray of light. You can account for that in your specular calculation function which then returns a vec4 or you do it the dirty way I did by just taking the maximum value of your specular color which already depends on the angle and use it (or scaled by factor) as your alpha value.

Translucent, reflective surfaces need to use either two passes or dual-source blending.

With two passes, the first pass deals with the translucency, multiplying the destination colour (i.e. the colour of the occluded surface) by the colour of the occluding surface. The second pass adds the reflected light (both diffuse and specular).

With dual-source blending, the primary source colour is the total reflected light (which has already been multiplied by the diffuse/specular material colours), the secondary source colour is the surface colour, the source factor is GL_ONE and the destination factor is GL_SRC1.

Either way, the surface colour needs the alpha “baked” into it, i.e. mix(vec3(1,1,1),colour,alpha).

Also: this ideally needs to use linear intensity, not gamma-law (sRGB) brightness values.

Thanks for your reply ProgrammerX and GClements. I will try dual-source blending and i will update.

Is there any example code in dual-source blending.

See some of the links in this thread, including ARB_blend_func_extended and Blending#Dual_Source_Blending.

Thanks for your reply programmerX. I have tried your method. It helped me. Now i have another question. How to only apply color to the the edges of object.

It depends upon how you define “edges”. From the context, it probably means surfaces which are tangential to the view direction, i.e. whose normal is perpendicular to the view direction. In that case, you probably want to scale the alpha based upon the dot product of the normal and the view direction, with values closer to zero having higher opacity.

Glad to help. I should mention that this method might work, but it is not physically correct. So you might get some strange artifacts under some circumstances. I am not sure, since I haven’t checked it, but if you want it physically correct you might end up with the method mentioned by GClements.
In reality the light from the object behind the surface will be partially transmitted and add up with the reflected light. So you would do something like taking the color value in the color buffer (which should not be clamped to 1) multiply it by a factor that represents the percentage of transmitted light and add this up with the reflected light from the surface. After you have calculated all the color values in your scene, you need to divide every value in the color buffer by the same value to scale most of the values back into the range of 0-1. This what your eye is usually doing by controlling how much light is let in. Some of the mentioned steps might not be as easy to implement as it sound. :wink:

Well, can’t help you with a specific solution since I have not done it myself and I am currently preparing all the low level stuff to start a new graphics engine. Means I am currently not doing much graphic related stuff. I can only give you a hint here: I know that there is a section about edge detection in the OpenGL Cookbook. Every topic also has minimal code examples. So you could start there. The book is available for free as a pdf. Just google it.