GLSL per pixel illumination "turn"

Source: Internet
Author: User

reprint: http://blog.csdn.net/hgl868/article/details/7872414

Per-pixel directional light (directional-Pixel)
This section will change the previous shader code to the directional light for pixel-wise calculations. We need to split the work according to two shader to determine what needs to be done on a per-pixel basis.
First look at the information that each vertex receives:
• Normal
• Semi-vector
• Light source Direction
We need to transform the normals into the viewpoint space and then normalization. We also need to normalized the semi-vector and the light direction, but they are already in the viewpoint space. These normalized vectors are interpolated and then fed into the fragment shader, so it is necessary to declare volatile variables to hold these vectors.
We can also do some calculations related to light and material in vertex shader, which can help balance the load of vertex shader and fragment shader.

The vertex shader code can be written in the following form:

Next, in the fragment shader, first declare the same volatile variable. In addition to normalization of normals again, ray vectors do not need to be normalized, because the directional light is consistent for all vertices, and the results of interpolation are not changed naturally. This is followed by calculating the dot product of the interpolated normal vector and the ray vector.

Varying VEC4 diffuse,ambient;
Varying VEC3 normal,lightdir,halfvector;

void Main ()
{
VEC3N,HALFV;
FLOATNDOTL,NDOTHV;

VEC4 color =ambient;

n =normalize (normal);

Ndotl =max (dot (n,lightdir), 0.0);
...

If the dot product result is ndotl greater than 0, we must calculate the scattered light, that is, the scattering term passed by the vertex shader multiplied by the dot product. We also need to calculate specular light, which is first normalized to the received half-vector, and then computes the dot product between the half-vector and the normals.

...
if (ndotl> 0.0)
{
Color + = diffuse * NDOTL;
HALFV = normalize (halfvector);
NDOTHV = max (dot (N,HALFV), 0.0);
Color + = Gl_frontmaterial.specular *
Gl_lightsource[0].specular *
Pow (NDOTHV, gl_frontmaterial.shininess);
}

Gl_fragcolor= color;
}

Shows the difference between per-pixel illumination and point-by-vertex lighting effects:

The content of this section shader designer works:
Http://www.lighthouse3d.com/wp-content/uploads/2011/03/dirpixsd.zip

Pixel-wise Point-light perpixel
This section is based on the previous content of the directional light, and most of the code is the same. This section mainly deals with the differences between directional light and point light. Directional light generally assumes that the light source is infinitely far away, so it is a parallel light when it reaches the object. Instead, the point light has a position in the space and radiates light in all directions. In addition, the intensity of the point light weakens with the distance to the vertex.
For OpenGL programs, the difference between these two types of light is mainly:
• The W component of the position field of the light source: it is 0 for the directional light, the surface of this position is actually a direction (direction); For the point light, this component is 1.
• The attenuation of a point light source is determined by three coefficients: a constant term, a linear term, and a two-time term.
For directional light, the direction of the light is the same for all vertices, but for the point light, the direction is the vector from the vertex to the position of the light source. So what needs to be changed for us is to add the content that calculates the ray direction in the vertex shader.
The attenuation in OpenGL is calculated by the following formula:

The K0 in the formula is the constant attenuation coefficient, the K1 is the linear attenuation coefficient, the K2 is the two attenuation coefficient, and D is the distance from the source position to the vertex.
Note that attenuation and distance are nonlinear, so we cannot calculate attenuation by vertex and use interpolation results in fragment shader, but we can calculate the distance in the vertex shader and then use the interpolation of the distance in the fragment shader to calculate the attenuation.
The formula for calculating color values using Point light is:

In the above formula, the ambient light portion must be decomposed into two items: the Global ambient light setting using the lighting model and the ambient light setting in the light source. Vertex shader must also calculate the two ambient light components separately. The new vertex shader is as follows:

Varying VEC4 diffuse,ambientglobal,ambient;
Varying VEC3 normal,lightdir,halfvector;
varying float dist;

void Main ()
{
Vec4ecpos;
Vec3aux;
Normal =normalize (Gl_normalmatrix * gl_normal);


Ecpos =gl_modelviewmatrix * GL_VERTEX;
Aux =VEC3 (Gl_lightsource[0].position-ecpos);
Lightdir =normalize (aux);
Dist =length (aux);
Halfvector =normalize (GL_LIGHTSOURCE[0].HALFVECTOR.XYZ);


Diffuse =gl_frontmaterial.diffuse * gl_lightsource[0].diffuse;


Ambient =gl_frontmaterial.ambient * gl_lightsource[0].ambient;
Ambientglobal = Gl_frontmaterial.ambient *gl_lightmodel.ambient;
gl_position= Ftransform ();
}

In the fragment shader, it is necessary to calculate the attenuation and also to normalized the light direction vectors that are worthy of being interpolated, because the light direction of each vertex is generally different.

Varying vec4 diffuse,ambientglobal, ambient;
Varying VEC3 normal,lightdir,halfvector;
varying float dist;

void Main ()
{
Vec3n,halfv,viewv,ldir;
FLOATNDOTL,NDOTHV;
VEC4 color =ambientglobal;
Floatatt;

n =normalize (normal);

Ndotl =max (dot (n,normalize (lightdir)), 0.0);
if (ndotl> 0.0)
{
ATT = 1.0/(Gl_lightsource[0].constantattenuation +
Gl_lightsource[0].linearattenuation * Dist +
Gl_lightsource[0].quadraticattenuation * dist * dist);
Color + = ATT * (diffuse * ndotl + ambient);
HALFV = normalize (halfvector);
NDOTHV = max (dot (N,HALFV), 0.0);
Color + att * gl_frontmaterial.specular *gl_lightsource[0].specular *
Pow (ndothv,gl_frontmaterial.shininess);
}
Gl_fragcolor= color;
}

Shows the vertex-to-pixel effect of the fixed function by the vertices and the pixels in this section:

The content of this section shader designer project:
Http://www.lighthouse3d.com/wp-content/uploads/2011/03/pointlightsd.zip

Per-pixel spotlight (spot light perpixel)
This section is basically consistent with the previous section, except that the spotlight is different from the point light, and the light emitted is confined to a cone.
For OpenGL programs, the difference between these two types of light is mainly:
• The spotlight contains a directional vector spotdirection that represents the axis of the cone.
• The cone contains an angle that can be used in GLSL to use the angle value set by the application and the corresponding cosine value spotcoscutoff.
• Finally there is an attenuation rate of spotexponent, which represents the attenuation of time intensity from the central axis of the cone to the outer surface.
The vertex shader of the spotlight is exactly the same as the point light, and we only need to make some modifications to the fragment shader. The scattering, specular, and ambient light components need to be shaded only if the current fragment is within the light cone of the spotlight. So we have to check this condition first.
The cosine of the angle between the light source and a point line vector and the spotlight direction vector (spotdirection) must be greater than spotcoscutoff, otherwise this point is outside the spotlight and can only receive global ambient light.

...

n = normalize (normal);


NDOTL = max (dot (n,normalize (lightdir)), 0.0);

if (Ndotl > 0.0)
{
Spoteffect =dot (Normalize (gl_lightsource[0].spotdirection),
Normalize (-lightdir));
if (Spoteffect > Gl_lightsource[0].spotcoscutoff)
{

}
}

Gl_fragcolor = ...

The light calculation below is very similar to the point light, the only difference being that the attenuation must be multiplied by the spot effect (spotlight effect), which is calculated as the following formula:

Spoteffect = Pow (spoteffect, gl_lightsource[0].spotexponent);
ATT = spoteffect/(gl_lightsource[0].constantattenuation +
Gl_lightsource[0].linearattenuation * Dist +
Gl_lightsource[0].quadraticattenuation * dist * dist);

Color + = ATT * (diffuse * ndotl + ambient);

HALFV = normalize (halfvector);
NDOTHV = max (dot (N,HALFV), 0.0);
Color + = att * gl_frontmaterial.specular *
Gl_lightsource[0].specular *
Pow (ndothv,gl_frontmaterial.shininess);

The per-vertex illumination calculations using fixed-function pipelining are shown separately, as well as the spot effects computed using pixel-per-light illumination in this section shader.

The content of this section shader designer works:
Http://www.lighthouse3d.com/wp-content/uploads/2011/03/spotlightsd.zip

GLSL per pixel illumination "turn"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.