# Blinn Phong rendering

I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane. I know that to do a rendering we have to use 3d programing API such as OpenGL or WebGL and so on.
My purpose is to render the surface plane without those APIs. The steps that I take are, I create 2 spaces:

1. image space: (0,0) is at the top left of the image.
2. camera space: (0,0) is at the middle of the image.

For vector computation, I convert every pixel position of image space to camera space then to world space.

double[] cam=((new double[]{0,0,1}));
double[] lum=((new double[]{0,0,1}));
double[] E=new double[3];
double[] L=new double[3];
double[] H=new double[3];
double D2;
Mat image=new Mat(rows,cols,CvType.CV_8UC3);
System.out.println("Start!!");
System.out.println("ok");
for(int i=0;i<tileHNumber;i++)
{
for(int j=0;j<tileWNumber;j++)
{
for(int s=0;s<192;s++)
{
for(int t=0;t<192;t++)
{
originS=s+192*i;//ligne
originT=t+192*j;//colonne
double[] pos=(Image2Cam(new double[]{originT,originS,0}));
E=normalize(XY(cam,pos));
L=normalize(XY(lum, pos);
H=normalize(le);
D2=dot(E,E);
double blue=color(blueColor,pos,E,L,H,D2);
double green=color(greenColor,pos,E,L,H,D2);
double red=color(redColor,pos,E,L,H,D2);
image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});
}
}
}
}
public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)
{
double value=0;
double[] N=normalize((new double[]{pos[0],pos[1],1}));
double diffuse=Math.max(0, dot(N,L));
double specular=Math.pow(Math.max(0, dot(N,H)),60);
value=d*diffuse*0.5+0.2*d+specular*255*0.3;
return value;
}


The 2 images below show my results: the first one shows diffuse image only. The second one shows specular image only represented by the white color.

My question is why the lobe specular is not surrounding the center of the image.

• To add, this is usually seen when the light direction is near parallel to the surface (like a sunset scene). When the light direction is perpendicular the specular highlight becomes much more circular. I would check your normal calculation in color(..), it looks like it is producing a normal that isn't perpendicular to your plane. Something like {0,0,-1} should be correct and facing towards your {0,0,1} light, not {pos.x,pos.y,1} like it currently is – PaulHK Jul 20 '16 at 7:01
• It appears that the new images that have replaced the old ones show a new and unrelated problem. Would this be better posted as a new question, so that the old problem is still here for future readers? There is some discussion on meta about this general point. – trichoplax Jul 29 '16 at 10:48
• Yeah, my comments make no sense now the question has been updated. – PaulHK Aug 29 '16 at 2:53
• I did not figure out how to resolve it. – Valimo Ral Sep 2 '16 at 19:59

If I'm guessing right, you are drawing a plane which is facing the camera, so your normals need to be 0,0,-1.

change

double[] N=normalize((new double[]{pos[0],pos[1],1}));

to

double[] N=normalize((new double[]{0,0,-1}));

• Thanks for your reply. I try this but I only have the ambiant color – Valimo Ral Jul 20 '16 at 9:52
• Maybe flip the sign. I'm not sure what your intention for the normals is, but for a plane every pixel should have the same normal. – PaulHK Jul 20 '16 at 9:55
• Yes I try -1 and then 1. My purpose is to have a circular specular on the surface plane – Valimo Ral Jul 20 '16 at 9:57
• The half-vector takes care of this normally, this will vary across your image. It looks like you are close to what you are intending, just something is on the wrong axis, at a guess. I encountered this problem and had similar results several times, was almost always down to incorrectly working out the eye-space/half-vector. – PaulHK Jul 20 '16 at 10:06
• Looking a bit more at your code example, the L vector calculation looks wrong. Should that not just be the world-space light vector?(Lum). Your lambert calculation would be something like dot( N={0,0,-1}, L={0,0,1} ) for the whole surface, which should return an intensity of 1 for the diffuse component. – PaulHK Jul 20 '16 at 10:17