Shader programming , create light interaction to image

97 views Asked by At

I am trying to learn shader programming in RenderMonkey, if I took a picture and want to apply some light interaction to that object.

How should I do this in a good way, I do not want to use the default openGL light, want do define one by myself.

Let say I create a color from the variable lightColor, a float shininess coefficient and a vec3 lightPos with the x, y and z position of the light source. In the default pipeline, light positions are expressed in camera coordinates. How should I do this in the best way?

And if I want a pixel shader in best quality which shader should I to to implement the shading calculation?

1

There are 1 answers

3
jwlaughton On

Let's see if this answers your question. This is old version 1.1 code, but should be easily adapted to newer versions. I've edited this code heavily from it's initial version, so I don't guarantee there are not errors in it, but I did at least compile and link it without errors.

The vertex shader:

#version 120

attribute vec4 Position;
attribute vec2 TexCoord;
attribute vec3 Normal;

uniform vec4 LightPosition;

uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat3 NormalMatrix;

varying vec2 texCoord;
varying float DiffuseIntensity;
varying float SpecularIntensity;

void main()
{
    vec3 lightPosition= vec3(LightPosition);
    float shininess = 30.0;

    vec3 ecPosition = vec3(ViewMatrix * ModelMatrix * Position);
    vec3 tnorm = normalize(NormalMatrix * Normal);
    vec3 lightVec = normalize(lightPosition - ecPosition);
    vec3 reflectVec = reflect(-lightVec, tnorm);
    vec3 viewVec = normalize(-ecPosition);
    float spec = clamp(dot(reflectVec, viewVec), 0.0, 1.0);

    SpecularIntensity = pow(spec, shininess / 5.0);

    DiffuseIntensity = max(dot(lightVec, tnorm), 0.0);

    texCoord = TexCoord;

    gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * Position;
}

The fragment shader:

#version 120

uniform sampler2D Texture;
uniform vec4 Emission;
uniform vec4 Ambient;
uniform vec4 Diffuse;
uniform vec4 Specular;

varying vec2 texCoord;
varying float DiffuseIntensity;
varying float SpecularIntensity;

void main()
{
    vec3 emission = vec3(Emission);
    vec3 ambient = vec3(Ambient);
    vec3 diffuse = vec3(Diffuse);
    vec3 specular = vec3(Specular);

    vec3 lightColor = emission;
    lightColor = lightColor + ambient;
    lightColor = lightColor + (SpecularIntensity * specular);
    lightColor = lightColor + (DiffuseIntensity * diffuse);

    vec3 face = texture2D(Texture, texCoord).rgb * lightColor;
    face = clamp(face, 0.0, 1.0);

    gl_FragColor = vec4(face, 1.0);

}

EDIT:

To illustrate the use of the keyword "discard" (which can only be used in the fragment shader) I modified the last few lines of the fragment shader to be:

vec3 face = texture2D(FaceTexture, texCoord).rgb * lightColor;
face = clamp(face, 0.0, 1.0);

if((texCoord[0] >= 0.45 && texCoord[0] <= 0.55) || (texCoord[1] >= 0.45 && texCoord[1] <= 0.55))
{
    discard;
}

gl_FragColor = vec4(face, 1.0);

This created a cross shaped hole in the texture. You can, of course, use any condition you want in the if statement.