1

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?

skaffman
  • 398,947
  • 96
  • 818
  • 769
user4390280
  • 33
  • 10

1 Answers1

0

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.

jwlaughton
  • 905
  • 1
  • 6
  • 11
  • I copied old code for this answer, but today I would bring in a ModelView matrix into the vertex shader rather than separate Model and View matrices. This would be more efficient because the GPU would not need to make the ViewMatrix * ModelMatrix calculation two times for every vertex. – jwlaughton Jan 07 '15 at 04:34
  • Thanks, do you also have an idea how to use the discard option of the fragment shader to create a hole on a specific location in the image? And change the background color to check if it works. Cant figure that out – user4390280 Jan 07 '15 at 22:44
  • I'm not sure what you mean by "change the background color to see if it works", but maybe you could change the glClearColor to be the background color you want. – jwlaughton Jan 08 '15 at 05:11