Computer Graphics Assignment 6

 In this assignment, I am writing some shaders. I do this by applying all of the stuff in shdr.bkcore.com and try to familiarize myself with the GLSL language. The hand-in will be a Canvas Assignment, and the shdr.bkcore.com editor gives me a way to build a "link" that helps to implement shaders. I want to include the link in both the text box of the canvas submission, and the README, as well as uploading the shaders as a .txt file. This is achieved by clicking the "download" button on the top of the interface. 



I need to write a fragment shader and a corresponding vertex shader. These are used to build an application, and attach a shader to said application. 

There are 3 requirements for this assignment, and I'm going to put it into some very simple terms:


1. Some shading needs to happen inside of the fragment shader. You want to assign a lot of variation, and do not simply interpolate the color accross each triangle and assign it to a varying and directly using it in gl_FragColor as one shader does. Need to put stuff inside of the fragment shader. 


2. I need to implement a shader with both diffuse and specular reflection.

3. I need to use a "time" uniform uniform to have some element of my scene that I change dynamically through time, which some example can do at the same time.

There are some other things I can do in order to finish this assignment properly. We can make the color of the object vary accross the spatial extent of the object. We can make the geometry of the model being shown "stretch" or otherwise deformed. Finally, we can use the "discard" functionality to create artistic transparency. 


Here is the actual problem:


and it's time to start the solution. It starts with the following code:


VERTEX SHADER:

precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fColor;

const float ambient_coeff   = 0.25;
const float specular_coeff  = 1.0;
const float specular_exp    = 32.0;
const vec3  light_direction = vec3(-1.0,1.0,1.0); // stationary light
const vec3  light_color     = vec3(1.0,1.0,1.0);
const vec3  object_color    = vec3(1.0,0.6,0.0); // yellow-ish orange

void main()
{
  vec4 pos = modelViewMatrix * vec4(position, 1.0);
  gl_Position = projectionMatrix * pos;

  vec3 l = normalize(light_direction);
  vec3 n = normalize(normalMatrix * normal);
  vec3 e = normalize(-pos.xyz);
  vec3 h = normalize (e+l);

  vec3 ambient_color  = ambient_coeff  * object_color;
  vec3 specular_color = specular_coeff * pow(max(0.0,dot(n,h)),specular_exp) * light_color;

  fColor=ambient_color+specular_color;
}


FRAGMENT SHADER:

precision highp float;
varying vec3 fColor;

void main()
{
  gl_FragColor = vec4(fColor, 1.0);
}

And the following picture:



and the main() code has this for its template:

VERTEX SHADER:

precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;

void main()
{
  fNormal = normalize(normalMatrix * normal);
  vec4 pos = modelViewMatrix * vec4(position, 1.0);
  fPosition = pos.xyz;
  gl_Position = projectionMatrix * pos;
}


FRAGMENT SHADER:

precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;

void main()
{
  gl_FragColor = vec4(fNormal, 1.0);
}


VERTEX SHADER: 

precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;

void main()
{
  fNormal = normalize(normalMatrix * normal);
  vec4 pos = modelViewMatrix * vec4(position, 1.0);
  fPosition = pos.xyz;
  gl_Position = projectionMatrix * pos;
}


and the following picture: 



Ok, so the first thing that I need to do is to put stuff into the fragment shader. I'm going to go to the previous lectures inside of this blog to see what I can find. The thing that I have to insert into the fragment shader is the shading. 

Now, heres my new vertex and fragment code, and picture.

VERTEX:

precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;

void main()
{
  fNormal = normalize(normalMatrix * normal);
  vec4 pos = modelViewMatrix * vec4(position, 1.0);
  fPosition = pos.xyz;
  gl_Position = projectionMatrix * pos;
}

FRAGMENT:

precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;

const float ambient_coeff = 0.25;
const float specular_coeff = 0.88;
const float specular_exp = 10.0;

const vec3 light_direction = vec3(5.0, 0.0, 5.0);

const vec3 lightColor = vec3(1.0, 1.0, 1.0);
const vec3 object_color = vec3(4.0, 0.0, 4.0);
//const vec 
void main()
{
 
  vec3 nld = normalize(light_direction);
  vec3 nfn = normalize(fNormal);
  vec3 fpn = normalize(-fPosition);
  vec3 h = normalize(fpn + nld);
  vec3 ambient_color = ambient_coeff * object_color;
  vec3 specular_color = specular_coeff * pow(max(0.0, dot(nfn,h)), specular_exp) * lightColor;
  
  
  
  gl_FragColor = vec4(ambient_color * specular_color, 1.0);
}


PICTURE:






This completes the first 2 requirements, as it also implements a shader that requires specular reflection.
The last requirements is to implement the "timer" requirement. Here is what I plan on doing: 

I'm gonna look at the timer code again, denoted here, and make changes accordingly.
 
Here is the Vertex code: 

precision highp float;
attribute vec3 position;
attribute vec3 normal;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;

uniform float time;

const float pi=3.14159;
varying vec3 modelX;
varying vec3 modelN;
varying vec3 rawX;

vec2 Rotate2D(vec2 vec_in, float angle)
{
  vec2 vec_out;
  vec_out.x=cos(angle)*vec_in.x-sin(angle)*vec_in.y;
  vec_out.y=sin(angle)*vec_in.x+cos(angle)*vec_in.y;
  return vec_out;
}

void main()
{
  modelX=position;
  rawX=position;
  modelN=normal;  
  
  // Comment these lines out to stop twisting
  modelX.xz = Rotate2D(modelX.xz,0.5*pi*modelX.y*sin(10.0*time)); // Try commenting out *just* this line :)
  modelN.xz = Rotate2D(modelN.xz,0.5*pi*modelX.y*sin(10.0*time)); // This is simple as that only since the transform is rotation
  
  fNormal = normalize(normalMatrix * modelN);
  vec4 pos = modelViewMatrix * vec4(modelX, 1.0);
  fPosition = pos.xyz;
  gl_Position = projectionMatrix * pos;
}




and here is the fragment code: 

precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;
varying vec3 rawX;

const vec3  lightV1    = vec3(0.0,1.0,0.0); // stationary light
const float lightI     = 1.0;               // only for diffuse component
const float ambientC   = 0.15;
const float diffuseC   = 0.7;
const float specularC1 = 1.0;               // For stationary light
const float specularE1 = 64.0;
const float specularE2 = 16.0;
const vec3  lightCol   = vec3(1.0,1.0,1.0);
const vec3  objectCol  = vec3(1.0,0.6,0.0); // yellow-ish orange

vec2 blinnPhongDir(vec3 lightDir, float lightInt, float Ka, float Kd, float Ks, float shininess)
{
  vec3 s = normalize(lightDir);
  vec3 v = normalize(-fPosition);
  vec3 n = normalize(fNormal);
  vec3 h = normalize(v+s);
  float diffuse = Ka + Kd * lightInt * max(0.0, dot(n, s));
  float spec =  Ks * pow(max(0.0, dot(n,h)), shininess);
  return vec2(diffuse, spec);
}

void main()
{
  float angle      = 25.0*time;
  vec3 lightV2     = vec3(sin(angle),-0.5,cos(angle));
  float specularC2 = 0.7;  // For moving light -- make this zero to keep only stationary light

  vec3 ColorS1 = blinnPhongDir(lightV1,0.0   ,0.0,     0.0,     specularC1,specularE1).y*lightCol;
  vec3 ColorS2 = blinnPhongDir(lightV2,0.0   ,0.0,     0.0,     specularC2,specularE2).y*lightCol;
  vec3 ColorAD = blinnPhongDir(lightV1,lightI,ambientC,diffuseC,0.0      ,1.0       ).x*objectCol;
  gl_FragColor = vec4(ColorAD+ColorS1+ColorS2,1.0);
  
  // Stripe-discard effect -- comment out to keep solid model
  if(sin(50.0*rawX.x)>0.5) discard;
}


And the time attribute is in the Fragment Shader. From this, I am able to make modifications accordingly. I just make an angle called time, and now I have a changing monkey.

This is my final fragment code, and now it's time to turn this assignment in. 

precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;

const float ambient_coeff = 0.25;
const float specular_coeff = 0.88;
const float specular_exp = 10.0;

const vec3 light_direction = vec3(5.0, 0.0, 5.0);

const vec3 lightColor = vec3(1.0, 1.0, 1.0);
const vec3 object_color = vec3(4.0, 0.0, 4.0);
//const vec 
void main()
{
  
  float angle = 10.0 * time;
  vec3 lightV2     = vec3(sin(angle),-0.01,cos(angle));
 
  vec3 nld = normalize(light_direction);
  vec3 nfn = normalize(fNormal);
  vec3 fpn = normalize(-fPosition);
  vec3 h = normalize(fpn + nld);
  vec3 ambient_color = ambient_coeff * object_color;
  vec3 specular_color = specular_coeff * pow(max(0.0, dot(nfn,h)), specular_exp) * lightColor;
  
  
  
  gl_FragColor = vec4(ambient_color * specular_color * lightV2, 1.0);
}

and the final submission code is here. 


Comments

Popular Posts