It seems that my assumption: "fragment shader only ouput normalized values" turns to be right. But I really hope that somebody could tell me it is not the truth, and give me instructions to show my assumption is wrong.

You'll need to use GL_RGB_INTEGER (not GL_RGB) when moving integer data around, like with glReadPixels.

Hi, arekkusu. Thanks for hitting the point. Using GL_RGB_INTEGER in step3, I got the CORRECT result. Yes, I actually read the latest version of Opengl programming guide. In that book, it says the format could be GL_RGB or GL_RGB_INTEGER. The word 'or' makes me believe that these two formats are equivalent.

Now, the bulb of my assumption goes to be exploded. I am very happy with that.