Computer Graphics: GL Shading Language

 The hardware accelerated pipeline helps to deliver 3D information to you, and there is a historical trajectory in how we got to this point. (Apple and Nvidia). 



We are trying to render meshes and fit into a stream of polygons for triangles.

Vertices will be put in a pipeline and passed into a vertex processor. We write the same program on all of the vertex shaders, and one of the outputs of the vertex program are the normalized device coordinates of every "triangle" and that Triangle map is being converted into normalized device ourses, and we are doing manipulations in a triangle processing state.


Rasterization figures out what pixels are touched by the particular triangle (this is rasterization in hardware).  Fragments are the pixels that were touched by the triangle. These are the pipeline, and a program will determine the color of a particular pixel.  The information is eventually dispatched to the hardware.


The 2 programmable parts are the vertex shader and the fragment shader. 

The vertex program is a program that is executed on every vertex on every triangle. The fragment program is executed on every triangle that every fragment is rasterized on. Sometimes the fragments are rendered onside of the domain, or far to the left, then they are called away and cannot be processed at all.


If a triangle is completely perpendicular to the view, then it will not be drawn either. This is executed by every pixel that is covered by every triangle in the program, and the fragment will be executed with every instance of every pixel. 


We will discuss GLSL, the OpenGL shading Language.



GLSL is a special language that are designed for shader programs and it has been accustomed in accordance to the C programming language. 

The GPU runs these programs. The compilation is a part of your graphics driver, there is going to be a graphics driver that interfaces your program. 

We will show demonstrations using shdr.bkcore.com, a sandbox website.


The tool has done the hard work of loading the meshes into a JavaScript Programs, and the only exception to specify are the vertex shaders and the fragment shaders. How do we modify the appearance of this? To create a red rendering, perform the following:


gl_FragColor = vec4(1.0, 0.0, 0.0 1.0); 


The main() function is the entry point for both vertex and fragment shaders. You can have other user-defined functions. main() has no arguments and does not take anything, by the way. 


We are going to see more specifics on how we code these shaders. The syntax error will be on the bottom left of the particular page. 

You can write and edit the code of a vertex shader or a fragment shader at the same time. These are windows, and they can be run simultaneously. It graphs a lot of effects and makes a textMode program due to talking to the graphics driver. It uses the shader to create a rendering and visualization.

It also has a stash of meshes. You might be able to see some polygonal edges, and fail to see perfectly smooth curves. The mesh, in result, is simply a collection of triangles.     


The sandbox provides with a cube model (6 faces with 2 triangles). then a sphere. There is a torus and doughnut shape and a model of a dragon and a monkey (a low-resolution pattern). 


A sample vertex shader is as follows:

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_losition = projectionMatrix * pos;


}


And a sample fragment shader is as follows:


uniform float time;

uniform vec2 resolution;

varying vec3 fPosition;

varying vec3 fNormal;

void main()

{

gl_FragColor = vec4(fNormal, 1.0);

}


We can easily access subsets of vectors, or make a vector by concatenating vector componenets.

The vector components are listed as x/y/z/w or r/g/b/a and more complex operations are made through an explicit cast. 

These are concatenating vector components.

vec3 v;
float a = v.x;
vec2 b = v.xy;
vec2 c = v.yz;
vec3 d = v.zyx;
vec3 e = v.xxx;

vec2 a,b;
vec3 c;

You can use rgb for red, green, blue and a for alpha.  

You cannot use different pneumonics such as xgz, etc. You can replace v.xxx with v.rrr and it will be the same.

The main() function is the entry point for both the vertex and the fragment shaders.




The objective of the fragment shader is to write in a variable the color that is to be painted. 

GLSL is strongly typed and very strictly typed and have strong variables and not allow conversion. We have to explicitly cast all of the conversions. void, int, float, bool.

What are the actual data types?

void - doesn't return anything
int - integer
float - floating point
bool - boolean value. 

A 4x4 matrix works in the 3-dimensional world and they multiply 4 dimensional representations of vectors.


mat3 and mat4 represent a 3x3 matrix and a 4x4 matrix. These are all floats. If you want to vector of 2 integers, use ivec2. A matrix of 2x2 integets is ivec2. A boolean vector is represented by bvec3. 


v.xy will create a 2 dimensional vector that has the x value and y value inside of it, and gives as a value how big the subset selected is. You can have this in any order. You can use v.zyx and v.bgr, and the mean exactly the same. You cannot mix pneumonics though.


vec2 a, b;

vec3 f = vec3(1.0, 2.0, 3.0);

vec3 g = vec3(1,2,3); //rare times an integer works

vec3 h = vec3(a,1);

vec3 h = vec3(1,a);

vec4 k = vec4(a,b);

vec4 l = vec4(a, c.xy);

Whatever it is, you CANNOT convert from float to int. You can also perform concatentations with vectors. 


To make a 3d vector into a 4d vector, just invoke vec4(position, 1.0). 

dot(), normalize(), min(), max(), length();


vec4 x;

vec3 p;

mat4 m;

vec4 y = M * x;

vec4 z = M * vec4(p,1);


float a = dot(x, vec4(p,0));

The GLSL reference card is here.


If you know the direction of the camera and what is pointing forwards towards the camera, if I were to ask the vector what the dot product, that product represents whether the vector is pointing away and pointing forwards a position. 


Type qualifiers:

uniform, varying, const, attribute 


Constant can be integers, ex. ambient color, specular color, diffuse color, etc. 


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);

const float lightI = 1.0;

const float ambientC = 0.15;

const float diffuseC = 0.7;

const float specularC1 = 1.0;

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);


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));

vec3 ColorS1 = blinnPhongDir(lightV1, 0.0, 0.0, 0.0, specularC1, specularE1).y * lightCol;

vec3 ColorS1 = blinnPhongDir(lightV2, 0.0, 0.0, 0.0, specularC2, specularE1).y * lightCol;

vec3 ColorAD = blinnPhongDir(lightV1, lightI, ambientC, diffuseC, 0.0, 1.0).x * objectCol;

gl_FragColor = vec4(ColorAD + ColorS1 + COlorS2, 1.0);

if(sin(50.0 + RawX.x) > 0.5) discard;


}

This is a vertex shader. An attribute is a vertex property. A very common vertex property is its position. You would at least want to inform the GPU what the position of every one of its vertices is. 


These are supplied by a host program made available to the vertex shader, viscosity, temperature, etc. It's important to compute the position, color, and normal vector of each vertex. 


This is the link for shader.bkcore.com.



GLSL are completely what the host program wants to define. Attributes are in the VERTEX shader and vertex shader only.


Positive dot product - facing towards camera



Negative dot product - facing away from camera. 


Uniforms have exactly the same value, before and after execution. An attribute is the property that the host program decides to associate with every vertex.


A uniform can be a property (color, intensity, etc.) This is when the property does not chnage from point to point, from pixel to pixel. A constant has 2 types:


-compile-time constants. There is no way for the outside programs to set the value of a constant to have some particular number. The only thing that can put the right value is determining what to turn in the code.


Uniforms CAN be changed from the host programs. Constants can't.


Modelling transform goes from model coordinates to world coordinates. World goes to camera coordinates. GLSL does not need viewport transforms, they mostly can take of providing its own viewport transform. 


Uniforms are constant across the scene, but the JavaScript programs have the potential to model the values. 


We can multiply the model transform with the camera transform to take the joint matrix. shdr.bkcore does the operation for us. You can go directly from the projection to the camera. 




pos = modelViewMatrix * vec4(position, 1,0) represents the rotation of every device to camera coordinates.

pos.xyz is the location in certain coordinates. 


void main()

{

fNormal = normalize(normalMatrix * normal);


}


The attributes provided are the position and the normal. The position is a 3D space in object space and the normal is a perpendicular vector in object space. 

A rotational transformation can help a model spin in world coordinates. 

Dragging around changes the camera position relative to the world location, the lookout transform is being manipulated. 


The builtin variables called position and normal, are the position and normal of each vertex inside of the object space. 

The fragment shader cannot have any attributes in its declaration. Why? It's not a vertex, it's just a pixel. 


Varying is a variable that can help pass from the from the vertex shader to the camera shader. Pass in vertex locations, pass in on fragment locations.


Comments

Popular Posts